diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 05:54:39 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 05:54:39 +0000 |
commit | 267c6f2ac71f92999e969232431ba04678e7437e (patch) | |
tree | 358c9467650e1d0a1d7227a21dac2e3d08b622b2 /xmlsecurity | |
parent | Initial commit. (diff) | |
download | libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.tar.xz libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.zip |
Adding upstream version 4:24.2.0.upstream/4%24.2.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'xmlsecurity')
701 files changed, 58117 insertions, 0 deletions
diff --git a/xmlsecurity/AllLangMoTarget_xsc.mk b/xmlsecurity/AllLangMoTarget_xsc.mk new file mode 100644 index 0000000000..90b80207ce --- /dev/null +++ b/xmlsecurity/AllLangMoTarget_xsc.mk @@ -0,0 +1,13 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +$(eval $(call gb_AllLangMoTarget_AllLangMoTarget,xsc)) + +$(eval $(call gb_AllLangMoTarget_set_polocation,xsc,xmlsecurity)) + +# vim: set noet sw=4 ts=4: diff --git a/xmlsecurity/CppunitTest_qa_certext.mk b/xmlsecurity/CppunitTest_qa_certext.mk new file mode 100644 index 0000000000..faa5459d3e --- /dev/null +++ b/xmlsecurity/CppunitTest_qa_certext.mk @@ -0,0 +1,27 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +$(eval $(call gb_CppunitTest_CppunitTest,xmlsecurity_qa_certext)) + +$(eval $(call gb_CppunitTest_use_sdk_api,xmlsecurity_qa_certext)) + +$(eval $(call gb_CppunitTest_use_libraries,xmlsecurity_qa_certext,\ + cppu \ + neon \ + sal \ + svl \ + test \ + tl \ +)) + +$(eval $(call gb_CppunitTest_add_exception_objects,xmlsecurity_qa_certext,\ + xmlsecurity/qa/certext/SanCertExt \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/xmlsecurity/CppunitTest_xmlsecurity_dialogs_test.mk b/xmlsecurity/CppunitTest_xmlsecurity_dialogs_test.mk new file mode 100644 index 0000000000..945c33af7b --- /dev/null +++ b/xmlsecurity/CppunitTest_xmlsecurity_dialogs_test.mk @@ -0,0 +1,68 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +#************************************************************************* +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +#************************************************************************* + +$(eval $(call gb_CppunitTest_CppunitScreenShot,xmlsecurity_dialogs_test)) + +$(eval $(call gb_CppunitTest_add_exception_objects,xmlsecurity_dialogs_test, \ + xmlsecurity/qa/unit/xmlsecurity-dialogs-test \ +)) + +$(eval $(call gb_CppunitTest_use_sdk_api,xmlsecurity_dialogs_test)) + +$(eval $(call gb_CppunitTest_set_include,desktop_dialogs_test,\ + -I$(SRCDIR)/xmlsecurity/inc \ + $$(INCLUDE) \ +)) + +$(eval $(call gb_CppunitTest_use_libraries,xmlsecurity_dialogs_test, \ + basegfx \ + comphelper \ + cppu \ + cppuhelper \ + drawinglayer \ + editeng \ + i18nlangtag \ + i18nutil \ + msfilter \ + oox \ + sal \ + salhelper \ + sax \ + sfx \ + sot \ + svl \ + svt \ + test \ + tl \ + tk \ + ucbhelper \ + unotest \ + utl \ + vcl \ + xo \ +)) + +$(eval $(call gb_CppunitTest_use_external,xmlsecurity_dialogs_test,boost_headers)) + +$(eval $(call gb_CppunitTest_use_sdk_api,xmlsecurity_dialogs_test)) + +$(eval $(call gb_CppunitTest_use_ure,xmlsecurity_dialogs_test)) +$(eval $(call gb_CppunitTest_use_vcl_non_headless_with_windows,xmlsecurity_dialogs_test)) + +$(eval $(call gb_CppunitTest_use_rdb,xmlsecurity_dialogs_test,services)) + +$(eval $(call gb_CppunitTest_use_configuration,xmlsecurity_dialogs_test)) + +$(eval $(call gb_CppunitTest_use_uiconfigs,xmlsecurity_dialogs_test,\ + xmlsec \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/xmlsecurity/CppunitTest_xmlsecurity_pdfsigning.mk b/xmlsecurity/CppunitTest_xmlsecurity_pdfsigning.mk new file mode 100644 index 0000000000..667acc97e3 --- /dev/null +++ b/xmlsecurity/CppunitTest_xmlsecurity_pdfsigning.mk @@ -0,0 +1,70 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +#************************************************************************* +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +#************************************************************************* + +$(eval $(call gb_CppunitTest_CppunitTest,xmlsecurity_pdfsigning)) + +$(eval $(call gb_CppunitTest_add_exception_objects,xmlsecurity_pdfsigning, \ + xmlsecurity/qa/unit/pdfsigning/pdfsigning \ +)) + +$(eval $(call gb_CppunitTest_use_libraries,xmlsecurity_pdfsigning, \ + comphelper \ + cppuhelper \ + cppu \ + sal \ + sax \ + sfx \ + test \ + tl \ + unotest \ + utl \ + xmlsecurity \ + vcl \ +)) + +$(eval $(call gb_CppunitTest_use_externals,xmlsecurity_pdfsigning,\ + boost_headers \ +)) + +ifneq ($(OS),WNT) +ifneq (,$(ENABLE_NSS)) +$(eval $(call gb_CppunitTest_use_externals,xmlsecurity_pdfsigning,\ + nssutil3 \ +)) +endif +endif + +$(eval $(call gb_CppunitTest_set_include,xmlsecurity_pdfsigning,\ + -I$(SRCDIR)/xmlsecurity/inc \ + $$(INCLUDE) \ +)) + +$(eval $(call gb_CppunitTest_use_sdk_api,xmlsecurity_pdfsigning)) + +$(eval $(call gb_CppunitTest_use_ure,xmlsecurity_pdfsigning)) +$(eval $(call gb_CppunitTest_use_vcl,xmlsecurity_pdfsigning)) + +$(eval $(call gb_CppunitTest_use_rdb,xmlsecurity_pdfsigning,services)) + +$(eval $(call gb_CppunitTest_use_configuration,xmlsecurity_pdfsigning)) + +ifeq ($(ENABLE_POPPLER),TRUE) +$(eval $(call gb_CppunitTest_use_executable,xmlsecurity_pdfsigning,xpdfimport)) +endif + +ifeq ($(OS),WNT) +# Initializing DocumentSignatureManager will require gpgme-w32spawn.exe in workdir/LinkTarget/Executable +$(eval $(call gb_CppunitTest_use_packages,xmlsecurity_pdfsigning,\ + $(call gb_Helper_optional,GPGMEPP,gpgmepp)\ +)) +endif + +# vim: set noet sw=4 ts=4: diff --git a/xmlsecurity/CppunitTest_xmlsecurity_signing.mk b/xmlsecurity/CppunitTest_xmlsecurity_signing.mk new file mode 100644 index 0000000000..7339800107 --- /dev/null +++ b/xmlsecurity/CppunitTest_xmlsecurity_signing.mk @@ -0,0 +1,94 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +#************************************************************************* +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +#************************************************************************* + +$(eval $(call gb_CppunitTest_CppunitTest,xmlsecurity_signing)) + +$(eval $(call gb_CppunitTest_add_exception_objects,xmlsecurity_signing, \ + xmlsecurity/qa/unit/signing/signing \ +)) + +$(eval $(call gb_CppunitTest_use_libraries,xmlsecurity_signing, \ + comphelper \ + cppuhelper \ + cppu \ + sal \ + sax \ + sfx \ + svx \ + subsequenttest \ + test \ + tl \ + unotest \ + utl \ + vcl \ + xmlsecurity \ + xsec_xmlsec \ +)) + +$(eval $(call gb_CppunitTest_use_externals,xmlsecurity_signing,\ + boost_headers \ + libxml2 \ +)) + +ifneq ($(OS),WNT) +ifneq (,$(ENABLE_NSS)) +$(eval $(call gb_CppunitTest_use_externals,xmlsecurity_signing,\ + nssutil3 \ +)) +endif +endif + +$(eval $(call gb_CppunitTest_set_include,xmlsecurity_signing,\ + -I$(SRCDIR)/xmlsecurity/inc \ + $$(INCLUDE) \ +)) + +$(eval $(call gb_CppunitTest_use_sdk_api,xmlsecurity_signing)) + +$(eval $(call gb_CppunitTest_use_ure,xmlsecurity_signing)) +$(eval $(call gb_CppunitTest_use_vcl,xmlsecurity_signing)) + +$(eval $(call gb_CppunitTest_use_uiconfigs,xmlsecurity_signing, \ + svt \ +)) + +$(eval $(call gb_CppunitTest_use_rdb,xmlsecurity_signing,services)) + +$(eval $(call gb_CppunitTest_use_configuration,xmlsecurity_signing)) + +ifeq ($(ENABLE_POPPLER),TRUE) +$(eval $(call gb_CppunitTest_use_executable,xmlsecurity_signing,xpdfimport)) +endif + +# various hacks to make unit test work on Linux more often +ifeq ($(OS),LINUX) +# reset the LD_LIBRARY_PATH for spawned GPG processes +$(call gb_CppunitTest_get_target,xmlsecurity_signing): \ + EXTRA_ENV_VARS += \ + LIBO_LD_PATH=$$LD_LIBRARY_PATH +endif + +$(eval $(call gb_CppunitTest_use_custom_headers,xmlsecurity_signing,\ + officecfg/registry \ +)) + +ifeq ($(OS),WNT) +# Initializing DocumentSignatureManager will require gpgme-w32spawn.exe in workdir/LinkTarget/Executable +$(eval $(call gb_CppunitTest_use_packages,xmlsecurity_signing,\ + $(call gb_Helper_optional,GPGMEPP,gpgmepp)\ +)) +endif + +$(eval $(call gb_CppunitTest_add_arguments,xmlsecurity_signing, \ + -env:arg-env=$(gb_Helper_LIBRARY_PATH_VAR)"$$$${$(gb_Helper_LIBRARY_PATH_VAR)+=$$$$$(gb_Helper_LIBRARY_PATH_VAR)}" \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/xmlsecurity/CppunitTest_xmlsecurity_signing2.mk b/xmlsecurity/CppunitTest_xmlsecurity_signing2.mk new file mode 100644 index 0000000000..0cd4501219 --- /dev/null +++ b/xmlsecurity/CppunitTest_xmlsecurity_signing2.mk @@ -0,0 +1,94 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +#************************************************************************* +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +#************************************************************************* + +$(eval $(call gb_CppunitTest_CppunitTest,xmlsecurity_signing2)) + +$(eval $(call gb_CppunitTest_add_exception_objects,xmlsecurity_signing2, \ + xmlsecurity/qa/unit/signing/signing2 \ +)) + +$(eval $(call gb_CppunitTest_use_libraries,xmlsecurity_signing2, \ + comphelper \ + cppuhelper \ + cppu \ + sal \ + sax \ + sfx \ + svx \ + subsequenttest \ + test \ + tl \ + unotest \ + utl \ + vcl \ + xmlsecurity \ + xsec_xmlsec \ +)) + +$(eval $(call gb_CppunitTest_use_externals,xmlsecurity_signing2,\ + boost_headers \ + libxml2 \ +)) + +ifneq ($(OS),WNT) +ifneq (,$(ENABLE_NSS)) +$(eval $(call gb_CppunitTest_use_externals,xmlsecurity_signing2,\ + nssutil3 \ +)) +endif +endif + +$(eval $(call gb_CppunitTest_set_include,xmlsecurity_signing2,\ + -I$(SRCDIR)/xmlsecurity/inc \ + $$(INCLUDE) \ +)) + +$(eval $(call gb_CppunitTest_use_sdk_api,xmlsecurity_signing2)) + +$(eval $(call gb_CppunitTest_use_ure,xmlsecurity_signing2)) +$(eval $(call gb_CppunitTest_use_vcl,xmlsecurity_signing2)) + +$(eval $(call gb_CppunitTest_use_uiconfigs,xmlsecurity_signing2, \ + svt \ +)) + +$(eval $(call gb_CppunitTest_use_rdb,xmlsecurity_signing2,services)) + +$(eval $(call gb_CppunitTest_use_configuration,xmlsecurity_signing2)) + +ifeq ($(ENABLE_POPPLER),TRUE) +$(eval $(call gb_CppunitTest_use_executable,xmlsecurity_signing2,xpdfimport)) +endif + +# various hacks to make unit test work on Linux more often +ifeq ($(OS),LINUX) +# reset the LD_LIBRARY_PATH for spawned GPG processes +$(call gb_CppunitTest_get_target,xmlsecurity_signing2): \ + EXTRA_ENV_VARS += \ + LIBO_LD_PATH=$$LD_LIBRARY_PATH +endif + +$(eval $(call gb_CppunitTest_use_custom_headers,xmlsecurity_signing2,\ + officecfg/registry \ +)) + +ifeq ($(OS),WNT) +# Initializing DocumentSignatureManager will require gpgme-w32spawn.exe in workdir/LinkTarget/Executable +$(eval $(call gb_CppunitTest_use_packages,xmlsecurity_signing2,\ + $(call gb_Helper_optional,GPGMEPP,gpgmepp)\ +)) +endif + +$(eval $(call gb_CppunitTest_add_arguments,xmlsecurity_signing2, \ + -env:arg-env=$(gb_Helper_LIBRARY_PATH_VAR)"$$$${$(gb_Helper_LIBRARY_PATH_VAR)+=$$$$$(gb_Helper_LIBRARY_PATH_VAR)}" \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/xmlsecurity/Executable_pdfverify.mk b/xmlsecurity/Executable_pdfverify.mk new file mode 100644 index 0000000000..ed8e9559fc --- /dev/null +++ b/xmlsecurity/Executable_pdfverify.mk @@ -0,0 +1,35 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +$(eval $(call gb_Executable_Executable,pdfverify)) + +$(eval $(call gb_Executable_use_sdk_api,pdfverify)) + +$(eval $(call gb_Executable_use_external,pdfverify,boost_headers)) + +$(eval $(call gb_Executable_set_include,pdfverify,\ + $$(INCLUDE) \ + -I$(SRCDIR)/xmlsecurity/inc \ +)) + +$(eval $(call gb_Executable_use_libraries,pdfverify,\ + comphelper \ + cppu \ + cppuhelper \ + sal \ + tl \ + vcl \ + xmlsecurity \ +)) + +$(eval $(call gb_Executable_add_exception_objects,pdfverify,\ + xmlsecurity/workben/pdfverify \ +)) + +# vim:set noet sw=4 ts=4: diff --git a/xmlsecurity/IwyuFilter_xmlsecurity.yaml b/xmlsecurity/IwyuFilter_xmlsecurity.yaml new file mode 100644 index 0000000000..b27a552751 --- /dev/null +++ b/xmlsecurity/IwyuFilter_xmlsecurity.yaml @@ -0,0 +1,131 @@ +--- +assumeFilename: xmlsecurity/source/xmlsec/xmlsec_init.cxx +excludelist: + xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx: + # complete type is needed + - com/sun/star/security/DocumentSignatureInformation.hpp + xmlsecurity/inc/UriBindingHelper.hxx: + # Base class needs complete type + - com/sun/star/xml/crypto/XUriBinding.hpp + xmlsecurity/inc/xsecctl.hxx: + # Base class needs complete type + - com/sun/star/xml/crypto/sax/XSAXEventKeeperStatusChangeListener.hpp + - com/sun/star/xml/crypto/sax/XSignatureCreationResultListener.hpp + - com/sun/star/xml/crypto/sax/XSignatureVerifyResultListener.hpp + # Needed on WIN32 for rtl::Reference<UriBindingHelper> to compile + - UriBindingHelper.hxx + xmlsecurity/inc/framework/securityengine.hxx: + # Base class needs complete type + - com/sun/star/xml/crypto/XXMLSignature.hpp + - com/sun/star/xml/crypto/sax/XReferenceResolvedBroadcaster.hpp + - com/sun/star/xml/crypto/sax/XSAXEventKeeper.hpp + xmlsecurity/inc/framework/signaturecreatorimpl.hxx: + # Base class needs complete type + - framework/signatureengine.hxx + - com/sun/star/xml/crypto/sax/XBlockerMonitor.hpp + - com/sun/star/xml/crypto/sax/XSignatureCreationResultBroadcaster.hpp + - com/sun/star/lang/XInitialization.hpp + - com/sun/star/lang/XServiceInfo.hpp + xmlsecurity/inc/framework/saxeventkeeperimpl.hxx: + # Base class needs complete type + - com/sun/star/xml/crypto/sax/XSecuritySAXEventKeeper.hpp + - com/sun/star/xml/crypto/sax/XReferenceResolvedBroadcaster.hpp + - com/sun/star/xml/crypto/sax/XSAXEventKeeperStatusChangeBroadcaster.hpp + - com/sun/star/xml/sax/XDocumentHandler.hpp + - com/sun/star/lang/XInitialization.hpp + - com/sun/star/lang/XServiceInfo.hpp + xmlsecurity/inc/framework/signatureverifierimpl.hxx: + # Base class needs complete type + - framework/signatureengine.hxx + - com/sun/star/xml/crypto/sax/XSignatureVerifyResultBroadcaster.hpp + - com/sun/star/lang/XServiceInfo.hpp + - com/sun/star/lang/XInitialization.hpp + xmlsecurity/inc/framework/xmlsignaturetemplateimpl.hxx: + # Base class needs complete type + - com/sun/star/xml/crypto/XXMLSignatureTemplate.hpp + - com/sun/star/lang/XServiceInfo.hpp + xmlsecurity/inc/gpg/SEInitializer.hxx: + # Base class needs complete type + - com/sun/star/xml/crypto/XSEInitializer.hpp + - com/sun/star/lang/XServiceInfo.hpp + xmlsecurity/inc/gpg/xmlsignature_gpgimpl.hxx: + # Base class needs complete type + - com/sun/star/xml/crypto/XXMLSignature.hpp + - com/sun/star/lang/XServiceInfo.hpp + xmlsecurity/inc/xmlsec/xmldocumentwrapper_xmlsecimpl.hxx: + # Base class needs complete type + - com/sun/star/xml/wrapper/XXMLDocumentWrapper.hpp + - com/sun/star/xml/csax/XCompressedDocumentHandler.hpp + - com/sun/star/lang/XServiceInfo.hpp + xmlsecurity/source/gpg/CipherContext.hxx: + # Base class needs complete type + - com/sun/star/xml/crypto/XCipherContext.hpp + xmlsecurity/source/gpg/DigestContext.hxx: + # Base class needs complete type + - com/sun/star/xml/crypto/XDigestContext.hpp + xmlsecurity/source/gpg/CertificateImpl.hxx: + # Base class needs complete type + - com/sun/star/security/XCertificate.hpp + - com/sun/star/lang/XUnoTunnel.hpp + - com/sun/star/lang/XServiceInfo.hpp + xmlsecurity/source/gpg/SecurityEnvironment.hxx: + # Base class needs complete type + - com/sun/star/xml/crypto/XSecurityEnvironment.hpp + - com/sun/star/lang/XUnoTunnel.hpp + xmlsecurity/source/gpg/XMLSecurityContext.hxx: + # Base class needs complete type + - com/sun/star/xml/crypto/XXMLSecurityContext.hpp + - com/sun/star/lang/XServiceInfo.hpp + xmlsecurity/source/gpg/XMLEncryption.hxx: + # Base class needs complete type + - com/sun/star/xml/crypto/XXMLEncryption.hpp + xmlsecurity/source/helper/ooxmlsecparser.hxx: + # Base class needs complete type + - com/sun/star/xml/sax/XDocumentHandler.hpp + - com/sun/star/lang/XInitialization.hpp + xmlsecurity/source/helper/xsecparser.hxx: + # Base class needs complete type + - com/sun/star/xml/sax/XDocumentHandler.hpp + - com/sun/star/lang/XInitialization.hpp + xmlsecurity/source/xmlsec/certificateextension_xmlsecimpl.hxx: + # Base class needs complete type + - com/sun/star/security/XCertificateExtension.hpp + xmlsecurity/source/xmlsec/xmlelementwrapper_xmlsecimpl.hxx: + # Base class needs complete type + - com/sun/star/lang/XServiceInfo.hpp + - com/sun/star/lang/XUnoTunnel.hpp + - com/sun/star/xml/wrapper/XXMLElementWrapper.hpp + xmlsecurity/source/xmlsec/errorcallback.cxx: + # Needed for xmlsec/errors.h + - xmlsec-wrapper.h + xmlsecurity/source/xmlsec/xmlstreamio.cxx: + # comphelper::ScopeGuard is in use but not noticed by IWYU + - comphelper/scopeguard.hxx + xmlsecurity/source/xmlsec/nss/sanextension_nssimpl.hxx: + # Base class needs complete type + - com/sun/star/security/XSanExtension.hpp + xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.hxx: + # Base class needs complete type + - com/sun/star/security/XCertificate.hpp + - com/sun/star/lang/XUnoTunnel.hpp + - com/sun/star/lang/XServiceInfo.hpp + xmlsecurity/source/xmlsec/nss/seinitializer_nssimpl.hxx: + # Base class needs complete type + - nssinitializer.hxx + - com/sun/star/xml/crypto/XSEInitializer.hpp + xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.hxx: + # Base class needs complete type + - com/sun/star/xml/crypto/XSecurityEnvironment.hpp + - com/sun/star/xml/crypto/XCertificateCreator.hpp + - com/sun/star/lang/XServiceInfo.hpp + - com/sun/star/lang/XUnoTunnel.hpp + xmlsecurity/source/xmlsec/nss/secerror.cxx: + # Used as array initializer + - certerrors.h + # Needed for macros used by certerrors.h + - nss.h + xmlsecurity/qa/unit/signing/signing.cxx: + # Don't replace URE header with impl. detail + - osl/thread.hxx + xmlsecurity/workben/pdfverify.cxx: + - comphelper/scopeguard.hxx diff --git a/xmlsecurity/Library_xmlsecurity.mk b/xmlsecurity/Library_xmlsecurity.mk new file mode 100644 index 0000000000..8507b4bab2 --- /dev/null +++ b/xmlsecurity/Library_xmlsecurity.mk @@ -0,0 +1,112 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +$(eval $(call gb_Library_Library,xmlsecurity)) + +$(eval $(call gb_Library_set_componentfile,xmlsecurity,xmlsecurity/util/xmlsecurity,services)) + +$(eval $(call gb_Library_set_include,xmlsecurity,\ + $$(INCLUDE) \ + -I$(SRCDIR)/xmlsecurity/inc \ +)) + +$(eval $(call gb_Library_add_defs,xmlsecurity,\ + -DXMLSECURITY_DLLIMPLEMENTATION \ +)) + +$(eval $(call gb_Library_use_externals,xmlsecurity,\ + boost_headers \ +)) + +$(eval $(call gb_Library_set_precompiled_header,xmlsecurity,xmlsecurity/inc/pch/precompiled_xmlsecurity)) + +$(eval $(call gb_Library_use_sdk_api,xmlsecurity)) + +$(eval $(call gb_Library_use_libraries,xmlsecurity,\ + comphelper \ + cppu \ + cppuhelper \ + sal \ + sax \ + svl \ + sfx \ + svt \ + svxcore \ + tl \ + ucbhelper \ + utl \ + vcl \ + xo \ + i18nlangtag \ + xsec_xmlsec \ +)) + +$(eval $(call gb_Library_add_exception_objects,xmlsecurity,\ + xmlsecurity/source/component/certificatecontainer \ + xmlsecurity/source/dialogs/certificatechooser \ + xmlsecurity/source/dialogs/certificateviewer \ + xmlsecurity/source/dialogs/digitalsignaturesdialog \ + xmlsecurity/source/dialogs/macrosecurity \ + xmlsecurity/source/framework/buffernode \ + xmlsecurity/source/framework/elementcollector \ + xmlsecurity/source/framework/elementmark \ + xmlsecurity/source/framework/saxeventkeeperimpl \ + xmlsecurity/source/framework/securityengine \ + xmlsecurity/source/framework/signaturecreatorimpl \ + xmlsecurity/source/framework/signatureengine \ + xmlsecurity/source/framework/signatureverifierimpl \ + xmlsecurity/source/framework/xmlsignaturetemplateimpl \ + xmlsecurity/source/helper/documentsignaturehelper \ + xmlsecurity/source/helper/documentsignaturemanager \ + xmlsecurity/source/helper/ooxmlsecparser \ + xmlsecurity/source/helper/ooxmlsecexporter \ + xmlsecurity/source/helper/pdfsignaturehelper \ + xmlsecurity/source/helper/UriBindingHelper \ + xmlsecurity/source/helper/xsecctl \ + xmlsecurity/source/helper/xsecparser \ + xmlsecurity/source/helper/xsecsign \ +)) + +ifneq (,$(or $(ENABLE_NSS),$(filter WNT,$(OS)))) +$(eval $(call gb_Library_add_exception_objects,xmlsecurity,\ + xmlsecurity/source/component/documentdigitalsignatures \ + xmlsecurity/source/helper/xmlsignaturehelper \ + xmlsecurity/source/helper/xsecverify \ +)) + +$(eval $(call gb_Library_add_componentimpl,xmlsecurity,dds)) +endif + +$(eval $(call gb_Library_use_externals,xmlsecurity,\ + libxml2 \ +)) +ifeq ($(OS),WNT) +$(eval $(call gb_Library_add_defs,xmlsecurity,\ + -DXMLSEC_CRYPTO_MSCRYPTO \ +)) +$(eval $(call gb_Library_use_system_win32_libs,xmlsecurity,\ + crypt32 \ + Ole32 \ + Shell32 \ +)) +else +ifneq (,$(filter DESKTOP,$(BUILD_TYPE))$(filter ANDROID,$(OS))) +ifeq (TRUE,$(ENABLE_NSS)) +$(eval $(call gb_Library_add_defs,xmlsecurity,\ + -DXMLSEC_CRYPTO_NSS \ +)) +$(eval $(call gb_Library_use_externals,xmlsecurity,\ + nss3 \ + plc4 \ +)) +endif +endif # BUILD_TYPE=DESKTOP +endif + +# vim: set noet sw=4 ts=4: diff --git a/xmlsecurity/Library_xsec_xmlsec.mk b/xmlsecurity/Library_xsec_xmlsec.mk new file mode 100644 index 0000000000..615c3eba00 --- /dev/null +++ b/xmlsecurity/Library_xsec_xmlsec.mk @@ -0,0 +1,188 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +$(eval $(call gb_Library_Library,xsec_xmlsec)) + +$(eval $(call gb_Library_set_componentfile,xsec_xmlsec,xmlsecurity/util/xsec_xmlsec,services)) + +$(eval $(call gb_Library_add_componentimpls,xsec_xmlsec, \ + $(if $(ENABLE_GPGMEPP),gpg) \ + $(if $(or $(ENABLE_NSS),$(filter WNT,$(OS))),nss_mscrypt) \ + $(if $(ENABLE_NSS),nss) \ +)) + +$(eval $(call gb_Library_set_include,xsec_xmlsec,\ + $$(INCLUDE) \ + -I$(SRCDIR)/xmlsecurity/inc \ + -I$(SRCDIR)/xmlsecurity/source/gpg \ + -I$(SRCDIR)/xmlsecurity/source/xmlsec \ + -I$(call gb_UnpackedTarball_get_dir,xmlsec/include) \ +)) + +$(eval $(call gb_Library_use_custom_headers,xsec_xmlsec,\ + officecfg/registry \ +)) + +$(eval $(call gb_Library_use_sdk_api,xsec_xmlsec)) + +$(eval $(call gb_Library_add_defs,xsec_xmlsec,\ + -DXMLSEC_NO_XSLT \ + -DXSECXMLSEC_DLLIMPLEMENTATION \ +)) + +$(eval $(call gb_Library_set_precompiled_header,xsec_xmlsec,xmlsecurity/inc/pch/precompiled_xsec_xmlsec)) + +$(eval $(call gb_Library_use_libraries,xsec_xmlsec,\ + comphelper \ + cppu \ + cppuhelper \ + sal \ + svl \ + tl \ + xo \ + utl \ +)) + +ifeq ($(SYSTEM_XMLSEC),) +$(eval $(call gb_Library_use_packages,xsec_xmlsec,\ + xmlsec \ +)) +endif + +$(eval $(call gb_Library_use_externals,xsec_xmlsec,\ + boost_headers \ + $(if $(ENABLE_GPGMEPP),gpgmepp) \ + libxml2 \ + xmlsec \ +)) + +$(eval $(call gb_Library_add_exception_objects,xsec_xmlsec,\ + xmlsecurity/source/xmlsec/biginteger \ + xmlsecurity/source/xmlsec/certificateextension_certextn \ + xmlsecurity/source/xmlsec/errorcallback \ + xmlsecurity/source/xmlsec/saxhelper \ + xmlsecurity/source/xmlsec/xmldocumentwrapper_xmlsecimpl \ + xmlsecurity/source/xmlsec/xmlelementwrapper_xmlsecimpl \ + xmlsecurity/source/xmlsec/xmlsec_init \ + xmlsecurity/source/xmlsec/xmlstreamio \ +)) + +ifeq ($(ENABLE_GPGMEPP),TRUE) +$(eval $(call gb_Library_add_exception_objects,xsec_xmlsec,\ + xmlsecurity/source/gpg/CertificateImpl \ + xmlsecurity/source/gpg/CipherContext \ + xmlsecurity/source/gpg/DigestContext \ + xmlsecurity/source/gpg/SecurityEnvironment \ + xmlsecurity/source/gpg/SEInitializer \ + xmlsecurity/source/gpg/XMLEncryption \ + xmlsecurity/source/gpg/XMLSecurityContext \ + xmlsecurity/source/gpg/xmlsignature_gpgimpl \ +)) +endif + +ifeq ($(OS),WNT) + +$(eval $(call gb_Library_add_defs,xsec_xmlsec,\ + -DXMLSEC_CRYPTO_MSCRYPTO \ +)) + +$(eval $(call gb_Library_add_libs,xsec_xmlsec,\ + $(call gb_UnpackedTarball_get_dir,xmlsec)/win32/binaries/libxmlsec-mscng.lib \ + $(call gb_UnpackedTarball_get_dir,xmlsec)/win32/binaries/libxmlsec.lib \ +)) + +$(eval $(call gb_Library_use_system_win32_libs,xsec_xmlsec,\ + crypt32 \ + advapi32 \ + ncrypt \ +)) + +$(eval $(call gb_Library_add_exception_objects,xsec_xmlsec,\ + xmlsecurity/source/xmlsec/mscrypt/akmngr \ + xmlsecurity/source/xmlsec/mscrypt/sanextension_mscryptimpl \ + xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl \ + xmlsecurity/source/xmlsec/mscrypt/seinitializer_mscryptimpl \ + xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl \ + xmlsecurity/source/xmlsec/mscrypt/xmlsecuritycontext_mscryptimpl \ + xmlsecurity/source/xmlsec/mscrypt/xmlsignature_mscryptimpl \ +)) + +ifeq ($(ENABLE_NSS),TRUE) + +$(eval $(call gb_Library_add_exception_objects,xsec_xmlsec,\ + xmlsecurity/source/xmlsec/nss/ciphercontext \ + xmlsecurity/source/xmlsec/nss/digestcontext \ + xmlsecurity/source/xmlsec/nss/nssinitializer \ +)) + +# nss3 after static libs to appease --as-needed linkers +$(eval $(call gb_Library_use_externals,xsec_xmlsec,\ + nss3 \ +)) + +endif + +else # !$(OS),WNT + +ifeq ($(SYSTEM_XMLSEC),) +$(eval $(call gb_Library_add_libs,xsec_xmlsec,\ + $(call gb_UnpackedTarball_get_dir,xmlsec)/src/.libs/libxmlsec1.a \ +)) +endif + +ifeq ($(ENABLE_NSS),TRUE) + +ifeq ($(SYSTEM_XMLSEC),) +$(eval $(call gb_Library_add_libs,xsec_xmlsec,\ + $(call gb_UnpackedTarball_get_dir,xmlsec)/src/nss/.libs/libxmlsec1-nss.a \ +)) +endif + +$(eval $(call gb_Library_add_exception_objects,xsec_xmlsec,\ + xmlsecurity/source/xmlsec/nss/ciphercontext \ + xmlsecurity/source/xmlsec/nss/digestcontext \ + xmlsecurity/source/xmlsec/nss/nssinitializer \ + xmlsecurity/source/xmlsec/nss/sanextension_nssimpl \ + xmlsecurity/source/xmlsec/nss/secerror \ + xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl \ + xmlsecurity/source/xmlsec/nss/seinitializer_nssimpl \ + xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl \ + xmlsecurity/source/xmlsec/nss/xmlsecuritycontext_nssimpl \ + xmlsecurity/source/xmlsec/nss/xmlsignature_nssimpl \ +)) + +$(eval $(call gb_Library_add_defs,xsec_xmlsec,\ + -DXMLSEC_CRYPTO_NSS \ +)) + +$(eval $(call gb_Library_use_externals,xsec_xmlsec,\ + plc4 \ +)) +# nss3 after static libs to appease --as-needed linkers +$(eval $(call gb_Library_use_externals,xsec_xmlsec,\ + nss3 \ +)) + +else # ! $(ENABLE_NSS) + +ifeq ($(ENABLE_OPENSSL),TRUE) +$(eval $(call gb_Library_use_external,xsec_xmlsec,openssl)) +endif + +endif # !$(ENABLE_NSS) + +ifeq ($(OS),SOLARIS) +$(eval $(call gb_Library_add_libs,xsec_xmlsec,\ + -ldl \ +)) +endif + +endif # !$(OS),WNT + +# vim: set noet sw=4 ts=4: diff --git a/xmlsecurity/Makefile b/xmlsecurity/Makefile new file mode 100644 index 0000000000..0997e62848 --- /dev/null +++ b/xmlsecurity/Makefile @@ -0,0 +1,14 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +module_directory:=$(dir $(realpath $(firstword $(MAKEFILE_LIST)))) + +include $(module_directory)/../solenv/gbuild/partial_build.mk + +# vim: set noet sw=4 ts=4: diff --git a/xmlsecurity/Module_xmlsecurity.mk b/xmlsecurity/Module_xmlsecurity.mk new file mode 100644 index 0000000000..f5b442683a --- /dev/null +++ b/xmlsecurity/Module_xmlsecurity.mk @@ -0,0 +1,53 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +$(eval $(call gb_Module_Module,xmlsecurity)) + +$(eval $(call gb_Module_add_targets,xmlsecurity,\ + Library_xmlsecurity \ + $(if $(ENABLE_NSS)$(ENABLE_OPENSSL),Library_xsec_xmlsec) \ + UIConfig_xmlsec \ +)) + +$(eval $(call gb_Library_use_custom_headers,xmlsecurity,\ + officecfg/registry \ +)) + +$(eval $(call gb_Module_add_slowcheck_targets,xmlsecurity,\ + CppunitTest_xmlsecurity_pdfsigning \ +)) + +$(eval $(call gb_Module_add_subsequentcheck_targets,xmlsecurity,\ + CppunitTest_xmlsecurity_signing \ + CppunitTest_xmlsecurity_signing2 \ +)) + +$(eval $(call gb_Module_add_l10n_targets,xmlsecurity,\ + AllLangMoTarget_xsc \ +)) + +# failing +#$(eval $(call gb_Module_add_check_targets,xmlsecurity,\ + CppunitTest_qa_certext \ +)) + +# screenshots +$(eval $(call gb_Module_add_screenshot_targets,xmlsecurity,\ + CppunitTest_xmlsecurity_dialogs_test \ +)) + +ifneq (,$(filter DESKTOP,$(BUILD_TYPE))) +ifneq (,$(or $(ENABLE_NSS),$(filter WNT,$(OS)))) +$(eval $(call gb_Module_add_targets,xmlsecurity,\ + $(if $(DISABLE_DYNLOADING),,Executable_pdfverify) \ +)) +endif +endif + +# vim: set noet sw=4 ts=4: diff --git a/xmlsecurity/README.md b/xmlsecurity/README.md new file mode 100644 index 0000000000..5d45e36119 --- /dev/null +++ b/xmlsecurity/README.md @@ -0,0 +1,59 @@ +# Document Signing + +## Introduction + +This code provides dialogs, and infrastructure wrapping `libxmlsec` and +`gpgme` that implements document signing. + +For signing a document, a personal key pair is used, which consists of a +private key and a public key, which is added to the document in addition +to the digital signature of the document, when signing it. + +The document signing can be done both for the source ODF/OOXML files and +the exported PDF files. It is also possible to sign existing PDF files. + +## Module Contents + + * `doc`: OpenDocument workflow legacy information with some illustrations to have an idea of the workflow, for starters check `doc/OpenDocumentSignatures-Workflow.odt`. + * `inc`: Headers to a subset of source files inside the module, parts like `source/framework` have headers inside the folder. + * `qa`: Unit tests for signing and shell scripts for certificates creation for testing. + * `test_docs`: Documents & certificates used for testing. + * `source`: More on that below. + * `uiconfig`: User interface configuration for different dialogs, it is recommended to navigate from relevant source file to the .ui file linked in the class which will be under `uiconfig/ui`. + * `util`: UNO passive registration config for GPG/ NSS. + +## Source Primary Contents + + * `component`: Main implementation of `DocumentDigitalSignatures` where the interaction with security environment and certificates occur. + * `dialogs`: Certificate & Signatures management dialogs. + * `certificatechooser`: Dialog that allows you to find and choose certificates or signatures for encryption. + * `certificateviewer`: More detailed information about each certificate. + * `digitalsignaturesdialog`: Main window for signatures of the documents and the start point of signing document. + * `framework`: Various elements for verifying signatures and running security engine. + * `gpg`: The implementation of encrypting with GPG and security environment initialization. + * `helper`: Some helper classes that include signatures manager and the helpers for PDF signing, UriBinding, and XML signatures. It also include helper tools for XSecurityEnvironment. + * `xmlsec`: XML, NSS, MSCrypt encryption/ signing tools, more on the low-level side of actual implementation of algorithms. + + +## PDF Testing + +To test the signed PDFs, one can use the `pdfverify` in this way: + + ./bin/run pdfverify $PWD/xmlsecurity/qa/unit/pdfsigning/data/2good.pdf + +The file parameter should be an absolute path. + +This is the output of `pdfverify` for `2good.pdf`: + +``` +verifying signatures +found 2 signatures +signature #0: digest match? 1 +signature #0: partial? 0 +signature #1: digest match? 1 +signature #1: partial? 0 +``` + +## References +* [Adobe: Digital Signatures in a PDF](https://www.adobe.com/devnet-docs/etk_deprecated/tools/DigSig/Acrobat\_DigitalSignatures_in_PDF.pdf) +* [Adobe: Acrobat DC Digital Signatures - Supported Standards](https://www.adobe.com/devnet-docs/acrobatetk/tools/DigSigDC/standards.html) diff --git a/xmlsecurity/UIConfig_xmlsec.mk b/xmlsecurity/UIConfig_xmlsec.mk new file mode 100644 index 0000000000..06482e2a29 --- /dev/null +++ b/xmlsecurity/UIConfig_xmlsec.mk @@ -0,0 +1,24 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +$(eval $(call gb_UIConfig_UIConfig,xmlsec)) + +$(eval $(call gb_UIConfig_add_uifiles,xmlsec,\ + xmlsecurity/uiconfig/ui/certpage \ + xmlsecurity/uiconfig/ui/certdetails \ + xmlsecurity/uiconfig/ui/certgeneral \ + xmlsecurity/uiconfig/ui/digitalsignaturesdialog \ + xmlsecurity/uiconfig/ui/securitylevelpage \ + xmlsecurity/uiconfig/ui/securitytrustpage \ + xmlsecurity/uiconfig/ui/selectcertificatedialog \ + xmlsecurity/uiconfig/ui/macrosecuritydialog \ + xmlsecurity/uiconfig/ui/viewcertdialog \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/xmlsecurity/doc/OpenDocumentSignatures-TestIntegration.odt b/xmlsecurity/doc/OpenDocumentSignatures-TestIntegration.odt Binary files differnew file mode 100644 index 0000000000..e90e4eaade --- /dev/null +++ b/xmlsecurity/doc/OpenDocumentSignatures-TestIntegration.odt diff --git a/xmlsecurity/doc/OpenDocumentSignatures-Workflow.odg b/xmlsecurity/doc/OpenDocumentSignatures-Workflow.odg Binary files differnew file mode 100644 index 0000000000..f7331f024a --- /dev/null +++ b/xmlsecurity/doc/OpenDocumentSignatures-Workflow.odg diff --git a/xmlsecurity/doc/OpenDocumentSignatures.odt b/xmlsecurity/doc/OpenDocumentSignatures.odt Binary files differnew file mode 100644 index 0000000000..78ac14fc0b --- /dev/null +++ b/xmlsecurity/doc/OpenDocumentSignatures.odt diff --git a/xmlsecurity/doc/XMLSecurityFramework.odt b/xmlsecurity/doc/XMLSecurityFramework.odt Binary files differnew file mode 100644 index 0000000000..b3f3a3549c --- /dev/null +++ b/xmlsecurity/doc/XMLSecurityFramework.odt diff --git a/xmlsecurity/inc/UriBindingHelper.hxx b/xmlsecurity/inc/UriBindingHelper.hxx new file mode 100644 index 0000000000..67c9ae69f8 --- /dev/null +++ b/xmlsecurity/inc/UriBindingHelper.hxx @@ -0,0 +1,51 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <rtl/ustring.hxx> + +#include <cppuhelper/implbase.hxx> + +#include <com/sun/star/xml/crypto/XUriBinding.hpp> + +namespace com::sun::star { + namespace io { class XInputStream; } + namespace embed { class XStorage; } +} + +// XUriBinding + +class UriBindingHelper final : public cppu::WeakImplHelper< css::xml::crypto::XUriBinding > +{ +private: + css::uno::Reference < css::embed::XStorage > mxStorage; + +public: + UriBindingHelper(); + explicit UriBindingHelper( const css::uno::Reference < css::embed::XStorage >& rxStorage ); + + void SAL_CALL setUriBinding( const OUString& uri, const css::uno::Reference< css::io::XInputStream >& aInputStream ) override; + + css::uno::Reference< css::io::XInputStream > SAL_CALL getUriBinding( const OUString& uri ) override; + + static css::uno::Reference < css::io::XInputStream > OpenInputStream( const css::uno::Reference < css::embed::XStorage >& rxStore, const OUString& rURI ); +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/biginteger.hxx b/xmlsecurity/inc/biginteger.hxx new file mode 100644 index 0000000000..fc99320c7e --- /dev/null +++ b/xmlsecurity/inc/biginteger.hxx @@ -0,0 +1,51 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <sal/config.h> + +#include <string_view> + +#include <rtl/ustring.hxx> + +#include <com/sun/star/uno/Sequence.h> + +#include "xsecxmlsecdllapi.h" + +namespace xmlsecurity +{ +XSECXMLSEC_DLLPUBLIC OUString bigIntegerToNumericString(const css::uno::Sequence<sal_Int8>& serial); +XSECXMLSEC_DLLPUBLIC css::uno::Sequence<sal_Int8> +numericStringToBigInteger(std::u16string_view serialNumber); + +// DNs read as strings from XML files may need to be mangled for compatibility +// as NSS and MS CryptoAPI have different string serialisations; if the DN is +// from an XCertificate it's "native" already and doesn't need to be mangled. +enum EqualMode +{ + NOCOMPAT, + COMPAT_2ND, + COMPAT_BOTH +}; +XSECXMLSEC_DLLPUBLIC bool EqualDistinguishedNames(std::u16string_view rName1, + std::u16string_view rName2, EqualMode eMode); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/bitmaps.hlst b/xmlsecurity/inc/bitmaps.hlst new file mode 100644 index 0000000000..4224881839 --- /dev/null +++ b/xmlsecurity/inc/bitmaps.hlst @@ -0,0 +1,21 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +inline constexpr OUString BMP_STATE_NOT_VALIDATED = u"xmlecurity/res/notcertificate_40x56.png"_ustr; + +#define BMP_CERT_OK "xmlsecurity/res/certificate_16.png" +#define BMP_CERT_NOT_OK "xmlsecurity/res/notcertificate_16.png" + +inline constexpr OUString BMP_SIG_VALID = u"xmlsecurity/res/signet_11x16.png"_ustr; +inline constexpr OUString BMP_SIG_INVALID = u"svx/res/caution_11x16.png"_ustr; +inline constexpr OUString BMP_SIG_NOT_VALIDATED = u"xmlsecurity/res/notcertificate_16.png"_ustr; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/xmlsecurity/inc/certificate.hxx b/xmlsecurity/inc/certificate.hxx new file mode 100644 index 0000000000..8357f50651 --- /dev/null +++ b/xmlsecurity/inc/certificate.hxx @@ -0,0 +1,43 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include <sal/types.h> + +#include <com/sun/star/uno/Sequence.hxx> + +namespace svl +{ +namespace crypto +{ +enum class SignatureMethodAlgorithm; +} +} + +namespace xmlsecurity +{ +/// Extension of css::security::XCertificate for module-internal purposes. +class SAL_NO_VTABLE SAL_DLLPUBLIC_RTTI SAL_LOPLUGIN_ANNOTATE("crosscast") Certificate +{ +public: + /// Returns the SHA-256 thumbprint. + /// + /// @throws css::uno::RuntimeException + virtual css::uno::Sequence<sal_Int8> getSHA256Thumbprint() = 0; + + /// Same as getSubjectPublicKeyAlgorithm(), but returns an ID, not a string. + virtual svl::crypto::SignatureMethodAlgorithm getSignatureMethodAlgorithm() = 0; + +protected: + ~Certificate() noexcept = default; +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/certificatechooser.hxx b/xmlsecurity/inc/certificatechooser.hxx new file mode 100644 index 0000000000..12303fbf1c --- /dev/null +++ b/xmlsecurity/inc/certificatechooser.hxx @@ -0,0 +1,117 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <com/sun/star/uno/Sequence.hxx> +#include <vcl/weld.hxx> +#include <unotools/resmgr.hxx> +#include <unotools/useroptions.hxx> +#include <unordered_map> + +namespace com::sun::star { + namespace security { class XCertificate; } + namespace xml::crypto { + class XSecurityEnvironment; + } +} + +namespace com::sun::star::xml::crypto { class XXMLSecurityContext; } + +struct UserData +{ + css::uno::Reference<css::security::XCertificate> xCertificate; + css::uno::Reference<css::xml::crypto::XXMLSecurityContext> xSecurityContext; + css::uno::Reference<css::xml::crypto::XSecurityEnvironment> xSecurityEnvironment; +}; + +enum class UserAction +{ + Sign, + SelectSign, // Select signing certificate + Encrypt +}; + +class CertificateChooser final : public weld::GenericDialogController +{ +private: + static inline CertificateChooser* mxInstance = nullptr; + + std::vector< css::uno::Reference< css::xml::crypto::XXMLSecurityContext > > mxSecurityContexts; + std::vector<std::shared_ptr<UserData>> mvUserData; + + bool mbInitialized; + UserAction const meAction; + OUString msPreferredKey; + css::uno::Reference<css::security::XCertificate> mxEncryptToSelf; + + std::unique_ptr<weld::Label> m_xFTSign; + std::unique_ptr<weld::Label> m_xFTEncrypt; + std::unique_ptr<weld::TreeView> m_xCertLB; + std::unique_ptr<weld::Button> m_xViewBtn; + std::unique_ptr<weld::Button> m_xOKBtn; + std::unique_ptr<weld::Label> m_xFTDescription; + std::unique_ptr<weld::Entry> m_xDescriptionED; + std::unique_ptr<weld::Entry> m_xSearchBox; + std::unique_ptr<weld::Button> m_xReloadBtn; + + std::unordered_map<css::uno::Reference< css::xml::crypto::XXMLSecurityContext>, + css::uno::Sequence< css::uno::Reference< css::security::XCertificate > > > xMemCerts; + + DECL_LINK(ReloadButtonHdl, weld::Button&, void); + DECL_LINK(ViewButtonHdl, weld::Button&, void); + DECL_LINK(CertificateHighlightHdl, weld::TreeView&, void); + DECL_LINK(CertificateSelectHdl, weld::TreeView&, bool); + DECL_LINK(SearchModifyHdl, weld::Entry&, void); + + void ImplShowCertificateDetails(); + void ImplInitialize(bool mbSearch = false); + void ImplReloadCertificates(); + static void HandleOneUsageBit(OUString& string, int& bits, int bit, TranslateId name); + +public: + CertificateChooser(weld::Window* pParent, + std::vector< css::uno::Reference< css::xml::crypto::XXMLSecurityContext > > && rxSecurityContexts, + UserAction eAction); + virtual ~CertificateChooser() override; + + static CertificateChooser* getInstance(weld::Window* _pParent, + std::vector< css::uno::Reference< css::xml::crypto::XXMLSecurityContext > > && rxSecurityContexts, + UserAction eAction) { + if (!mxInstance) + { + mxInstance = new CertificateChooser(_pParent, std::move(rxSecurityContexts), eAction); + } + return mxInstance; + } + + short run() override; + + css::uno::Sequence<css::uno::Reference< css::security::XCertificate > > GetSelectedCertificates(); + css::uno::Reference< css::xml::crypto::XXMLSecurityContext > GetSelectedSecurityContext() const; + /// Gets the description string provided when selecting the certificate. + OUString GetDescription() const; + + /// Returns the usage string of the selected certificate, if any. + OUString GetUsageText(); + + static OUString UsageInClearText(int bits); +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/certificateviewer.hxx b/xmlsecurity/inc/certificateviewer.hxx new file mode 100644 index 0000000000..2db66ddba2 --- /dev/null +++ b/xmlsecurity/inc/certificateviewer.hxx @@ -0,0 +1,159 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <utility> +#include <vcl/weld.hxx> + +namespace com::sun::star { + namespace security { class XCertificate; } + namespace xml::crypto { class XSecurityEnvironment; } +} + +class CertificateViewerGeneralTP; +class CertificateViewerDetailsTP; +class CertificateViewerCertPathTP; +class CertificateChooser; + +class CertificateViewer final : public weld::GenericDialogController +{ +private: + friend class CertificateViewerGeneralTP; + friend class CertificateViewerDetailsTP; + friend class CertificateViewerCertPathTP; + + bool const mbCheckForPrivateKey; + + css::uno::Reference< css::xml::crypto::XSecurityEnvironment > mxSecurityEnvironment; + css::uno::Reference< css::security::XCertificate > mxCert; + + CertificateChooser* mpParentChooser; + + std::unique_ptr<weld::Notebook> mxTabCtrl; + + std::unique_ptr<CertificateViewerGeneralTP> mxGeneralPage; + std::unique_ptr<CertificateViewerDetailsTP> mxDetailsPage; + std::unique_ptr<CertificateViewerCertPathTP> mxPathId; + + DECL_LINK(ActivatePageHdl, const OUString&, void); + +public: + CertificateViewer(weld::Window* pParent, const css::uno::Reference< css::xml::crypto::XSecurityEnvironment >& rxSecurityEnvironment, const css::uno::Reference< css::security::XCertificate >& rXCert, bool bCheckForPrivateKey, CertificateChooser* pParentChooser); + CertificateChooser* GetParentChooser() { return mpParentChooser; } +}; + +class CertificateViewerTP +{ +protected: + std::unique_ptr<weld::Builder> mxBuilder; + std::unique_ptr<weld::Container> mxContainer; + CertificateViewer* mpDlg; + +public: + CertificateViewerTP(weld::Container* pParent, const OUString& rUIXMLDescription, + const OUString& rID, CertificateViewer* pDlg); +}; + +class CertificateViewerGeneralTP : public CertificateViewerTP +{ +private: + std::unique_ptr<weld::Image> m_xCertImg; + std::unique_ptr<weld::Label> m_xHintNotTrustedFT; + std::unique_ptr<weld::Label> m_xIssuedToLabelFT; + std::unique_ptr<weld::Label> m_xIssuedToFT; + std::unique_ptr<weld::Label> m_xIssuedByLabelFT; + std::unique_ptr<weld::Label> m_xIssuedByFT; + std::unique_ptr<weld::Label> m_xValidFromDateFT; + std::unique_ptr<weld::Label> m_xValidToDateFT; + std::unique_ptr<weld::Image> m_xKeyImg; + std::unique_ptr<weld::Label> m_xHintCorrespPrivKeyFT; + +public: + CertificateViewerGeneralTP(weld::Container* pParent, CertificateViewer* pDlg); +}; + +struct Details_UserDatat +{ + OUString const maTxt; + bool const mbFixedWidthFont; + + Details_UserDatat(OUString aTxt, bool bFixedWidthFont) + : maTxt(std::move(aTxt)) + , mbFixedWidthFont(bFixedWidthFont) + { + } +}; + +class CertificateViewerDetailsTP : public CertificateViewerTP +{ +private: + std::vector<std::unique_ptr<Details_UserDatat>> m_aUserData; + + std::unique_ptr<weld::TreeView> m_xElementsLB; + std::unique_ptr<weld::TextView> m_xValueDetails; + + DECL_LINK(ElementSelectHdl, weld::TreeView&, void); + void InsertElement(const OUString& rField, const OUString& rValue, + const OUString& rDetails, bool bFixedWidthFont = false); +public: + CertificateViewerDetailsTP(weld::Container* pParent, CertificateViewer* pDlg); +}; + +struct CertPath_UserData +{ + css::uno::Reference< css::security::XCertificate > mxCert; + bool const mbValid; + + CertPath_UserData(css::uno::Reference<css::security::XCertificate> xCert, bool bValid) + : mxCert(std::move(xCert)) + , mbValid(bValid) + { + } +}; + +class CertificateViewerCertPathTP : public CertificateViewerTP +{ +private: + CertificateViewer* mpParent; + bool mbFirstActivateDone; + + std::vector<std::unique_ptr<CertPath_UserData>> maUserData; + std::shared_ptr<CertificateViewer> mxCertificateViewer; + + std::unique_ptr<weld::TreeView> mxCertPathLB; + std::unique_ptr<weld::TreeIter> mxScratchIter; + std::unique_ptr<weld::Button> mxViewCertPB; + std::unique_ptr<weld::TextView> mxCertStatusML; + std::unique_ptr<weld::Label> mxCertOK; + std::unique_ptr<weld::Label> mxCertNotValidated; + + DECL_LINK(ViewCertHdl, weld::Button&, void); + DECL_LINK(CertSelectHdl, weld::TreeView&, void); + void InsertCert(const weld::TreeIter* pParent, const OUString& _rName, + const css::uno::Reference< css::security::XCertificate >& rxCert, + bool bValid); + +public: + CertificateViewerCertPathTP(weld::Container* pParent, CertificateViewer* pDlg); + ~CertificateViewerCertPathTP(); + void ActivatePage(); +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/digitalsignaturesdialog.hxx b/xmlsecurity/inc/digitalsignaturesdialog.hxx new file mode 100644 index 0000000000..08db226fb8 --- /dev/null +++ b/xmlsecurity/inc/digitalsignaturesdialog.hxx @@ -0,0 +1,124 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <vcl/weld.hxx> +#include <com/sun/star/beans/PropertyValue.hpp> + +#include "documentsignaturehelper.hxx" +#include "xmlsignaturehelper.hxx" +#include "documentsignaturemanager.hxx" + +#include <vector> + +namespace com::sun::star { + namespace lang { class XMultiServiceFactory; } + namespace io { class XStream; } + namespace embed { class XStorage; } + namespace xml::dom { class XDocumentBuilder; } +} + + +class HeaderBar; +class CertificateViewer; + +class DigitalSignaturesDialog final : public weld::GenericDialogController +{ +private: + DocumentSignatureManager maSignatureManager; + bool mbVerifySignatures; + bool mbSignaturesChanged; + + OUString const m_sODFVersion; + //Signals if the document contains already a document signature. This is only + //important when we are signing macros and if the value is true. + bool const m_bHasDocumentSignature; + bool m_bWarningShowSignMacro; + + bool m_bAdESCompliant = true; + + std::unique_ptr<weld::Label> m_xHintDocFT; + std::unique_ptr<weld::Label> m_xHintBasicFT; + std::unique_ptr<weld::Label> m_xHintPackageFT; + std::unique_ptr<weld::TreeView> m_xSignaturesLB; + std::unique_ptr<weld::Image> m_xSigsValidImg; + std::unique_ptr<weld::Label> m_xSigsValidFI; + std::unique_ptr<weld::Image> m_xSigsInvalidImg; + std::unique_ptr<weld::Label> m_xSigsInvalidFI; + std::unique_ptr<weld::Image> m_xSigsNotvalidatedImg; + std::unique_ptr<weld::Label> m_xSigsNotvalidatedFI; + std::unique_ptr<weld::Image> m_xSigsOldSignatureImg; + std::unique_ptr<weld::Label> m_xSigsOldSignatureFI; + std::unique_ptr<weld::Button> m_xViewBtn; + std::unique_ptr<weld::Button> m_xAddBtn; + std::unique_ptr<weld::Button> m_xRemoveBtn; + std::unique_ptr<weld::Button> m_xStartCertMgrBtn; + std::unique_ptr<weld::Button> m_xCloseBtn; + + std::shared_ptr<CertificateViewer> m_xViewer; + std::shared_ptr<weld::MessageDialog> m_xInfoBox; + + DECL_LINK(ViewButtonHdl, weld::Button&, void); + DECL_LINK(AddButtonHdl, weld::Button&, void); + DECL_LINK(RemoveButtonHdl, weld::Button&, void); + DECL_LINK(SignatureHighlightHdl, weld::TreeView&, void); + DECL_LINK(SignatureSelectHdl, weld::TreeView&, bool); + DECL_LINK(StartVerifySignatureHdl, LinkParamNone*, bool); + DECL_LINK(OKButtonHdl, weld::Button&, void); + DECL_LINK(CertMgrButtonHdl, weld::Button&, void); + + void ImplGetSignatureInformations(bool bUseTempStream, bool bCacheLastSignature); + void ImplFillSignaturesBox(); + void ImplShowSignaturesDetails(); + + css::uno::Reference<css::security::XCertificate> getCertificate(const SignatureInformation& rInfo); + css::uno::Reference<css::xml::crypto::XSecurityEnvironment> getSecurityEnvironmentForCertificate( + const css::uno::Reference<css::security::XCertificate>& xCert); + + //Checks if adding is allowed. + //See the spec at specs/www/appwide/security/Electronic_Signatures_and_Security.sxw + //(6.6.2)Behaviour with regard to ODF 1.2 + bool canAdd(); + bool canRemove(); + + bool canAddRemove(); + +public: + DigitalSignaturesDialog(weld::Window* pParent, const css::uno::Reference< + css::uno::XComponentContext >& rxCtx, DocumentSignatureMode eMode, + bool bReadOnly, OUString sODFVersion, bool bHasDocumentSignature); + virtual ~DigitalSignaturesDialog() override; + + // Initialize the dialog and the security environment, returns TRUE on success + bool Init(); + + // Set the storage which should be signed or verified + void SetStorage( const css::uno::Reference < css::embed::XStorage >& rxStore ); + void SetSignatureStream( const css::uno::Reference < css::io::XStream >& rxStream ); + + // Execute the dialog... + void beforeRun(); + short run() override; + + // Did signatures change? + bool SignaturesChanged() const { return mbSignaturesChanged; } +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/documentsignaturehelper.hxx b/xmlsecurity/inc/documentsignaturehelper.hxx new file mode 100644 index 0000000000..eb50b37614 --- /dev/null +++ b/xmlsecurity/inc/documentsignaturehelper.hxx @@ -0,0 +1,104 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <com/sun/star/uno/Reference.h> +#include <rtl/ustring.hxx> +#include <svl/sigstruct.hxx> + +#include <vector> + +namespace com::sun::star { + namespace io { class XStream; } + namespace embed { class XStorage; } +} + +namespace com::sun::star::xml::sax { class XDocumentHandler; } + +enum class DocumentSignatureMode +{ + Content, + Macros, + Package +}; + +enum class DocumentSignatureAlgorithm +{ + OOo2, + OOo3_0, + OOo3_2 +}; + +struct SignatureStreamHelper +{ + css::uno::Reference < css::embed::XStorage > xSignatureStorage; + css::uno::Reference < css::io::XStream > xSignatureStream; + /// If this is embed::StorageFormats::OFOPXML, then it's expected that xSignatureStream is an empty reference. + sal_Int32 nStorageFormat; + + SignatureStreamHelper() + : nStorageFormat(0) + { + } +}; + +namespace DocumentSignatureHelper +{ + SignatureStreamHelper OpenSignatureStream( + const css::uno::Reference < css::embed::XStorage >& rxStore, sal_Int32 nOpenMode, + DocumentSignatureMode eDocSigMode ); + + std::vector< OUString > CreateElementList( + const css::uno::Reference < css::embed::XStorage >& rxStore, + DocumentSignatureMode eMode, + const DocumentSignatureAlgorithm mode); + + bool isODFPre_1_2(std::u16string_view sODFVersion); + bool isOOo3_2_Signature(const SignatureInformation & sigInfo); + + DocumentSignatureAlgorithm getDocumentAlgorithm( + std::u16string_view sODFVersion, const SignatureInformation & sigInfo); + + bool CanSignWithGPG(const css::uno::Reference < css::embed::XStorage >& rxStore, + std::u16string_view sOdfVersion); + + bool checkIfAllFilesAreSigned( const ::std::vector< OUString > & sElementList, + const SignatureInformation & sigInfo, const DocumentSignatureAlgorithm alg); + + bool equalsReferenceUriManifestPath( + std::u16string_view rUri, std::u16string_view rPath); + + OUString GetDocumentContentSignatureDefaultStreamName(); + OUString GetScriptingContentSignatureDefaultStreamName(); + OUString GetPackageSignatureDefaultStreamName(); + + /// In case the storage is OOXML, prepend a leading '/' and append content type to the element URIs. + void AppendContentTypes(const css::uno::Reference<css::embed::XStorage>& xStorage, std::vector<OUString>& rElements); + + void writeDigestMethod( + const css::uno::Reference<css::xml::sax::XDocumentHandler>& xDocumentHandler); + void writeSignedProperties( + const css::uno::Reference<css::xml::sax::XDocumentHandler>& xDocumentHandler, + const SignatureInformation& signatureInfo, + const OUString& sDate, + const bool bWriteSignatureLineData); +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/documentsignaturemanager.hxx b/xmlsecurity/inc/documentsignaturemanager.hxx new file mode 100644 index 0000000000..ab89e5b966 --- /dev/null +++ b/xmlsecurity/inc/documentsignaturemanager.hxx @@ -0,0 +1,136 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include "xmlsecuritydllapi.h" + +#include <memory> + +#include <svl/sigstruct.hxx> +#include "xmlsignaturehelper.hxx" +#include "documentsignaturehelper.hxx" + +#include <com/sun/star/xml/crypto/XSEInitializer.hpp> +#include <unotools/tempfile.hxx> + +namespace com::sun::star +{ +namespace beans +{ +struct PropertyValue; +} +namespace embed +{ +class XStorage; +} +namespace frame +{ +class XModel; +} +namespace graphic +{ +class XGraphic; +} +namespace uno +{ +class XComponentContext; +} +} +class PDFSignatureHelper; + +/// Manages signatures (addition, removal), used by DigitalSignaturesDialog. +class XMLSECURITY_DLLPUBLIC DocumentSignatureManager +{ +private: + css::uno::Reference<css::uno::XComponentContext> mxContext; + css::uno::Reference<css::embed::XStorage> mxStore; + XMLSignatureHelper maSignatureHelper; + std::unique_ptr<PDFSignatureHelper> mpPDFSignatureHelper; + SignatureInformations maCurrentSignatureInformations; + DocumentSignatureMode const meSignatureMode; + css::uno::Sequence<css::uno::Sequence<css::beans::PropertyValue>> m_manifest; + css::uno::Reference<css::io::XStream> mxSignatureStream; + css::uno::Reference<css::frame::XModel> mxModel; + rtl::Reference<utl::TempFileFastService> mxTempSignatureStream; + /// Storage containing all OOXML signatures, unused for ODF. + css::uno::Reference<css::embed::XStorage> mxTempSignatureStorage; + css::uno::Reference<css::xml::crypto::XSEInitializer> mxSEInitializer; + css::uno::Reference<css::xml::crypto::XXMLSecurityContext> mxSecurityContext; + css::uno::Reference<css::xml::crypto::XSEInitializer> mxGpgSEInitializer; + css::uno::Reference<css::xml::crypto::XXMLSecurityContext> mxGpgSecurityContext; + +public: + DocumentSignatureManager(const css::uno::Reference<css::uno::XComponentContext>& xContext, + DocumentSignatureMode eMode); + ~DocumentSignatureManager(); + + /** + * Checks if a particular stream is a valid xml stream. Those are treated + * differently when they are signed (c14n transformation) + */ + bool isXML(std::u16string_view rURI); + bool readManifest(); + + SignatureStreamHelper ImplOpenSignatureStream(sal_Int32 nStreamOpenMode, bool bTempStream); + /// Add a new signature, using xCert as a signing certificate, and rDescription as description. + bool add(const css::uno::Reference<css::security::XCertificate>& xCert, + const css::uno::Reference<css::xml::crypto::XXMLSecurityContext>& xSecurityContext, + const OUString& rDescription, sal_Int32& nSecurityId, bool bAdESCompliant, + const OUString& rSignatureLineId = OUString(), + const css::uno::Reference<css::graphic::XGraphic>& xValidGraphic + = css::uno::Reference<css::graphic::XGraphic>(), + const css::uno::Reference<css::graphic::XGraphic>& xInvalidGraphic + = css::uno::Reference<css::graphic::XGraphic>()); + /// Remove signature at nPosition. + void remove(sal_uInt16 nPosition); + /// Read signatures from either a temp stream or the real storage. + void read(bool bUseTempStream, bool bCacheLastSignature = true); + /// Write signatures back to the persistent storage. + void write(bool bXAdESCompliantIfODF); + /// Lazy creation of PDF helper. + PDFSignatureHelper& getPDFSignatureHelper(); +#if 0 + // Checks if the document is a kind where it is relevant to distinguish between using XAdES or not + bool IsXAdESRelevant(); +#endif + /// Attempts to initialize the platform-specific crypto. + bool init(); + /// Get the security environment. + css::uno::Reference<css::xml::crypto::XSecurityEnvironment> getSecurityEnvironment(); + css::uno::Reference<css::xml::crypto::XSecurityEnvironment> getGpgSecurityEnvironment(); + css::uno::Reference<css::xml::crypto::XXMLSecurityContext> const& getSecurityContext() const; + css::uno::Reference<css::xml::crypto::XXMLSecurityContext> const& getGpgSecurityContext() const; + void setStore(const css::uno::Reference<css::embed::XStorage>& xStore) { mxStore = xStore; } + XMLSignatureHelper& getSignatureHelper() { return maSignatureHelper; } + bool hasPDFSignatureHelper() const { return bool(mpPDFSignatureHelper); } + void setSignatureStream(const css::uno::Reference<css::io::XStream>& xSignatureStream) + { + mxSignatureStream = xSignatureStream; + } + void setModel(const css::uno::Reference<css::frame::XModel>& xModel); + const css::uno::Reference<css::embed::XStorage>& getStore() const { return mxStore; } + DocumentSignatureMode getSignatureMode() const { return meSignatureMode; } + SignatureInformations& getCurrentSignatureInformations() + { + return maCurrentSignatureInformations; + } +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/framework/saxeventkeeperimpl.hxx b/xmlsecurity/inc/framework/saxeventkeeperimpl.hxx new file mode 100644 index 0000000000..161b9a9361 --- /dev/null +++ b/xmlsecurity/inc/framework/saxeventkeeperimpl.hxx @@ -0,0 +1,290 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <com/sun/star/xml/crypto/sax/XSecuritySAXEventKeeper.hpp> +#include <com/sun/star/xml/crypto/sax/XReferenceResolvedBroadcaster.hpp> +#include <com/sun/star/xml/crypto/sax/XSAXEventKeeperStatusChangeBroadcaster.hpp> +#include <com/sun/star/xml/sax/XDocumentHandler.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <xmlsecuritydllapi.h> +#include <cppuhelper/implbase.hxx> +#include <vector> +#include <memory> + +class BufferNode; +class ElementMark; +class ElementCollector; +namespace com::sun::star::xml::crypto::sax { class XSAXEventKeeperStatusChangeListener; } +namespace com::sun::star::xml::csax { class XCompressedDocumentHandler; } +namespace com::sun::star::xml::wrapper { class XXMLDocumentWrapper; } + + +class SAXEventKeeperImpl final : public cppu::WeakImplHelper +< + css::xml::crypto::sax::XSecuritySAXEventKeeper, + css::xml::crypto::sax::XReferenceResolvedBroadcaster, + css::xml::crypto::sax::XSAXEventKeeperStatusChangeBroadcaster, + css::xml::sax::XDocumentHandler, + css::lang::XInitialization, + css::lang::XServiceInfo +> +/****** SAXEventKeeperImpl.hxx/CLASS SAXEventKeeperImpl *********************** + * + * NAME + * SAXEventKeeperImpl -- SAX events buffer controller + * + * FUNCTION + * Controls SAX events to be buffered, and controls buffered SAX events + * to be released. + ******************************************************************************/ +{ +private: + /* + * the XMLDocumentWrapper component which maintains all buffered SAX + * in DOM format. + */ + css::uno::Reference< css::xml::wrapper::XXMLDocumentWrapper > + m_xXMLDocument; + + /* + * the document handler provided by the XMLDocumentWrapper component. + */ + css::uno::Reference< css::xml::sax::XDocumentHandler > m_xDocumentHandler; + + /* + * the compressed document handler provided by the XMLDocumentWrapper + * component, the handler has more efficient method definition that the + * normal document handler. + */ + css::uno::Reference< css::xml::csax::XCompressedDocumentHandler > + m_xCompressedDocumentHandler; + + /* + * a listener which receives this SAXEventKeeper's status change + * notification. + * Based on the status changes, the listener can decide whether the + * SAXEventKeeper should chain on/chain off the SAX chain, or whether + * the SAXEventKeeper is useless any long. + */ + css::uno::Reference< css::xml::crypto::sax::XSAXEventKeeperStatusChangeListener > + m_xSAXEventKeeperStatusChangeListener; + + /* + * the root node of the BufferNode tree. + * the BufferNode tree is used to keep track of all buffered elements, + * it has the same structure with the document which maintains those + * elements physically. + */ + std::unique_ptr<BufferNode> m_pRootBufferNode; + + /* + * the current active BufferNode. + * this is used to keep track the current location in the BufferNode tree, + * the next generated BufferNode will become a child BufferNode of it. + */ + BufferNode* m_pCurrentBufferNode; + + /* + * the next Id for a coming ElementMark. + * the variable is increased by 1 when a new ElementMark is generated, + * in this way, we can promise the Id of any ElementMark is unique. + */ + sal_Int32 m_nNextElementMarkId; + + /* + * maintains a collection of all ElementMarks. + */ + std::vector<std::unique_ptr<const ElementMark>> m_vElementMarkBuffers; + + /* + * maintains a list of new ElementCollectors that will be created + * on the element represented by the next incoming startElement SAX + * event. + * The reason that such the m_vNewElementCollectors is necessary + * is: when an ElementCollector is asked to create, it can't be + * created completely at once, because the BufferNode it will be + * working on has not been created until the next startElement + * SAX event comes. + */ + std::vector< const ElementCollector* > m_vNewElementCollectors; + + /* + * maintains the new Blocker that will be created + * on the element represented by the next incoming startElement SAX + * event. + */ + ElementMark* m_pNewBlocker; + + /* + * the document handler to which all received SAX events will be + * forwarded. + */ + css::uno::Reference< css::xml::sax::XDocumentHandler > m_xNextHandler; + + /* + * the current BufferNode which prevents the SAX events to be + * forwarded to the m_xNextHandler. + */ + BufferNode* m_pCurrentBlockingBufferNode; + + /* + * maintains a list of ElementMark that has been asked to release. + * Because during processing a request of releasing an ElementMark, + * another releasing ElementMark request can be invoked. To avoid + * reentering the same method, a such request only add that ElementMark + * into this ElementMark list, then all ElementMarks will be processed in + * order. + */ + std::vector< sal_Int32 > m_vReleasedElementMarkBuffers; + + /* + * a flag to indicate whether the ElementMark releasing process is running. + * When a releasing request comes, the assigned ElementMark is added to + * the m_vReleasedElementMarkBuffers first, then this flag is checked. + * If the ElementMark releasing process is not running, then call that + * method. + */ + bool m_bIsReleasing; + + /* + * a flag to indicate whether it is the "Forwarding" mode now. + * A "Forwarding" mode means that all received SAX events are from the + * XMLDocumentWrapper component, instead of up-stream component in the + * SAX chain. + * The difference between "Forwarding" mode and normal mode is that: + * no SAX events need to be transferred to the XMLDocumentWrapper component + * again even if a buffer request happens. + */ + bool m_bIsForwarding; + + void setCurrentBufferNode(BufferNode* pBufferNode); + + BufferNode* addNewElementMarkBuffers(); + + ElementMark* findElementMarkBuffer(sal_Int32 nId) const; + + void removeElementMarkBuffer(sal_Int32 nId); + + OUString printBufferNode( + BufferNode const * pBufferNode, sal_Int32 nIndent) const; + + static css::uno::Sequence< css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > > + collectChildWorkingElement(BufferNode const * pBufferNode); + + void smashBufferNode( + BufferNode* pBufferNode, bool bClearRoot) const; + + static BufferNode* findNextBlockingBufferNode( + BufferNode* pStartBufferNode); + + static void diffuse(BufferNode* pBufferNode); + + void releaseElementMarkBuffer(); + + void markElementMarkBuffer(sal_Int32 nId); + + sal_Int32 createElementCollector( + css::xml::crypto::sax::ElementMarkPriority nPriority, + bool bModifyElement, + const css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener>& xReferenceResolvedListener); + + sal_Int32 createBlocker(); + +public: + SAXEventKeeperImpl(); + virtual ~SAXEventKeeperImpl() override; + + SAXEventKeeperImpl(const SAXEventKeeperImpl&) = delete; + SAXEventKeeperImpl& operator=(const SAXEventKeeperImpl&) = delete; + + /* XSAXEventKeeper */ + virtual sal_Int32 SAL_CALL addElementCollector( ) override; + virtual void SAL_CALL removeElementCollector( sal_Int32 id ) override; + virtual sal_Int32 SAL_CALL addBlocker( ) override; + virtual void SAL_CALL removeBlocker( sal_Int32 id ) override; + virtual sal_Bool SAL_CALL isBlocking( ) override; + virtual css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > SAL_CALL + getElement( sal_Int32 id ) override; + virtual void SAL_CALL setElement( + sal_Int32 id, + const css::uno::Reference< css::xml::wrapper::XXMLElementWrapper >& aElement ) override; + virtual css::uno::Reference< + css::xml::sax::XDocumentHandler > SAL_CALL + setNextHandler( const css::uno::Reference< + css::xml::sax::XDocumentHandler >& xNewHandler ) override; + virtual OUString SAL_CALL printBufferNodeTree() override; + virtual css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > SAL_CALL + getCurrentBlockingNode() override; + + /* XSecuritySAXEventKeeper */ + virtual sal_Int32 SAL_CALL addSecurityElementCollector( + css::xml::crypto::sax::ElementMarkPriority priority, + sal_Bool modifyElement ) override; + virtual void SAL_CALL setSecurityId( sal_Int32 id, sal_Int32 securityId ) override; + + /* XReferenceResolvedBroadcaster */ + virtual void SAL_CALL addReferenceResolvedListener( + sal_Int32 referenceId, + const css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener >& listener ) override; + virtual void SAL_CALL removeReferenceResolvedListener( + sal_Int32 referenceId, + const css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener >& listener ) override; + + /* XSAXEventKeeperStatusChangeBroadcaster */ + virtual void SAL_CALL addSAXEventKeeperStatusChangeListener( + const css::uno::Reference< css::xml::crypto::sax::XSAXEventKeeperStatusChangeListener >& listener ) override; + virtual void SAL_CALL removeSAXEventKeeperStatusChangeListener( + const css::uno::Reference< css::xml::crypto::sax::XSAXEventKeeperStatusChangeListener >& listener ) override; + + /* XDocumentHandler */ + virtual void SAL_CALL startDocument( ) override; + virtual void SAL_CALL endDocument( ) override; + virtual void SAL_CALL startElement( + const OUString& aName, + const css::uno::Reference< css::xml::sax::XAttributeList >& + xAttribs ) override; + virtual void SAL_CALL endElement( const OUString& aName ) override; + virtual void SAL_CALL characters( const OUString& aChars ) override; + virtual void SAL_CALL ignorableWhitespace( const OUString& aWhitespaces ) override; + virtual void SAL_CALL processingInstruction( + const OUString& aTarget, const OUString& aData ) override; + virtual void SAL_CALL setDocumentLocator( + const css::uno::Reference< css::xml::sax::XLocator >& xLocator ) override; + + /* XInitialization */ + virtual void SAL_CALL initialize( + const css::uno::Sequence< css::uno::Any >& aArguments ) override; + + /* XServiceInfo */ + virtual OUString SAL_CALL getImplementationName( ) override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; +}; + +/// @throws css::uno::RuntimeException +OUString SAXEventKeeperImpl_getImplementationName(); + +/// @throws css::uno::RuntimeException +css::uno::Sequence< OUString > SAXEventKeeperImpl_getSupportedServiceNames( ); + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/framework/securityengine.hxx b/xmlsecurity/inc/framework/securityengine.hxx new file mode 100644 index 0000000000..bebf07306b --- /dev/null +++ b/xmlsecurity/inc/framework/securityengine.hxx @@ -0,0 +1,142 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <com/sun/star/xml/crypto/sax/XReferenceResolvedListener.hpp> +#include <com/sun/star/xml/crypto/sax/XReferenceResolvedBroadcaster.hpp> +#include <com/sun/star/xml/crypto/sax/XKeyCollector.hpp> +#include <com/sun/star/xml/crypto/sax/XMissionTaker.hpp> +#include <com/sun/star/xml/crypto/sax/XSAXEventKeeper.hpp> +#include <com/sun/star/xml/crypto/XXMLSignature.hpp> + +#include <cppuhelper/implbase.hxx> + +#include <xmlsecuritydllapi.h> + +class SAL_DLLPUBLIC_RTTI SecurityEngine : public cppu::WeakImplHelper +< + css::xml::crypto::sax::XReferenceResolvedListener, + css::xml::crypto::sax::XKeyCollector, + css::xml::crypto::sax::XMissionTaker +> +/****** securityengine.hxx/CLASS SecurityEngine ******************************* + * + * NAME + * SecurityEngine -- Base class of SignatureEngine and EncryptionEngine + * + * FUNCTION + * Maintains common members and methods related with security engine + * operation. + ******************************************************************************/ +{ +protected: + + /* + * A SAXEventKeeper internally maintains all resources that a security + * operation needs. The m_xSAXEventKeeper member is used to release + * those resources when the security operation finishes. + */ + css::uno::Reference< css::xml::crypto::sax::XSAXEventKeeper > m_xSAXEventKeeper; + + /* + * the id of ElementCollector of the template element. + * For a signature, the template element is the Signature element, + * for an encryption, the EncryptedData/EncryptedKey element is. + */ + sal_Int32 m_nIdOfTemplateEC; + + /* + * remembers how many referenced elements have been buffered completely, + * including the key element, template element, and referenced element of + * signature. + */ + sal_Int32 m_nNumOfResolvedReferences; + + /* + * the id of ElementCollector of the key element. + * If a Signature element or EncryptedData/EncryptedKey element has + * an internal key sub-element, then this member should be -1 + */ + sal_Int32 m_nIdOfKeyEC; + + /* + * remembers whether the current operation has finished. + */ + bool m_bMissionDone; + + /* + * the Id of the security entity, a signature or encryption, which is used for + * the result listener to identify the entity. + */ + sal_Int32 m_nSecurityId; + + /* + * the status of the operation + */ + css::xml::crypto::SecurityOperationStatus m_nStatus; + + /* + * the result listener, which will receives the security operation result. + */ + css::uno::Reference< css::uno::XInterface > m_xResultListener; + +protected: + explicit SecurityEngine(); + virtual ~SecurityEngine() override {}; + + /* + * perform the security operation. + * Any derived class will implement this method respectively. + */ + /// @throws css::uno::Exception + /// @throws css::uno::RuntimeException + virtual void tryToPerform( ){}; + + /* + * clear up all resources used by this operation. + * This method is called after the operation finishes, or a End-Your-Mission + * message is received. + * Any derived class will implement this method respectively. + */ + virtual void clearUp( ) const {}; + + /* + * notifies any possible result listener. + * When verify a signature or conduct a decryption, the operation result will + * be transferred to a listener by this method. + * Any derived class will implement this method respectively. + */ + /// @throws css::uno::Exception + /// @throws css::uno::RuntimeException + virtual void notifyResultListener() const + {}; + +public: + /* XReferenceResolvedListener */ + virtual void SAL_CALL referenceResolved( sal_Int32 referenceId ) override; + + /* XKeyCollector */ + virtual void SAL_CALL setKeyId( sal_Int32 id ) override; + + /* XMissionTaker */ + virtual sal_Bool SAL_CALL endMission( ) override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/framework/signaturecreatorimpl.hxx b/xmlsecurity/inc/framework/signaturecreatorimpl.hxx new file mode 100644 index 0000000000..d0fc1dc333 --- /dev/null +++ b/xmlsecurity/inc/framework/signaturecreatorimpl.hxx @@ -0,0 +1,96 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <com/sun/star/xml/crypto/sax/XBlockerMonitor.hpp> +#include <com/sun/star/xml/crypto/sax/XSignatureCreationResultBroadcaster.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <cppuhelper/implbase.hxx> + +#include <framework/signatureengine.hxx> + +namespace com::sun::star::xml::crypto { class XSecurityEnvironment; } +namespace com::sun::star::xml::crypto::sax { class XSignatureCreationResultListener;} + +typedef cppu::ImplInheritanceHelper +< + SignatureEngine, + css::xml::crypto::sax::XBlockerMonitor, + css::xml::crypto::sax::XSignatureCreationResultBroadcaster, + css::lang::XInitialization, + css::lang::XServiceInfo +> SignatureCreatorImpl_Base; + +class SignatureCreatorImpl final : public SignatureCreatorImpl_Base +/****** SignatureCreatorImpl.hxx/CLASS SignatureCreatorImpl ******************* + * + * NAME + * SignatureCreatorImpl -- generates a signature + * + * FUNCTION + * Collects all resources for a signature generation, then generates the + * signature by invoking a xmlsec-based signature bridge component. + ******************************************************************************/ +{ +private: + /* + * the Id of template blocker. + */ + sal_Int32 m_nIdOfBlocker; + + css::uno::Reference< css::xml::crypto::XSecurityEnvironment > m_xSecurityEnvironment; + + virtual void notifyResultListener() const override; + virtual void clearUp( ) const override; + virtual void startEngine( const rtl::Reference<XMLSignatureTemplateImpl>& xSignatureTemplate) override; + +public: + explicit SignatureCreatorImpl(); + virtual ~SignatureCreatorImpl() override; + + /* XBlockerMonitor */ + virtual void SAL_CALL setBlockerId( sal_Int32 id ) override; + + /* XSignatureCreationResultBroadcaster */ + void SAL_CALL addSignatureCreationResultListener( + const css::uno::Reference< css::xml::crypto::sax::XSignatureCreationResultListener >& listener ) override; + + void SAL_CALL removeSignatureCreationResultListener( + const css::uno::Reference< css::xml::crypto::sax::XSignatureCreationResultListener >& listener ) override; + + /* XInitialization */ + virtual void SAL_CALL initialize( + const css::uno::Sequence< css::uno::Any >& aArguments ) override; + + /* XServiceInfo */ + virtual OUString SAL_CALL getImplementationName( ) override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; +}; + +/// @throws css::uno::RuntimeException +OUString SignatureCreatorImpl_getImplementationName(); + +/// @throws css::uno::RuntimeException +css::uno::Sequence< OUString > SignatureCreatorImpl_getSupportedServiceNames( ); + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/framework/signatureengine.hxx b/xmlsecurity/inc/framework/signatureengine.hxx new file mode 100644 index 0000000000..6446c2f367 --- /dev/null +++ b/xmlsecurity/inc/framework/signatureengine.hxx @@ -0,0 +1,116 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <com/sun/star/xml/crypto/sax/XReferenceResolvedListener.hpp> +#include <com/sun/star/xml/crypto/sax/XReferenceCollector.hpp> +#include <com/sun/star/xml/crypto/sax/XKeyCollector.hpp> +#include <com/sun/star/xml/crypto/sax/XMissionTaker.hpp> +#include <com/sun/star/xml/crypto/XUriBinding.hpp> + +#include <cppuhelper/implbase.hxx> + +#include <xmlsecuritydllapi.h> +#include <framework/securityengine.hxx> + +#include <vector> + +namespace com::sun::star::io { class XInputStream; } +namespace com::sun::star::xml::crypto { class XXMLSignature; } +namespace rtl { template <class reference_type> class Reference; } + +class XMLSignatureTemplateImpl; + +class SignatureEngine : public cppu::ImplInheritanceHelper +< + SecurityEngine, + css::xml::crypto::sax::XReferenceCollector, + css::xml::crypto::XUriBinding +> +/****** signatureengine.hxx/CLASS SignatureEngine ***************************** + * + * NAME + * SignatureEngine -- Base class of SignatureCreator and SignatureVerifier + * + * FUNCTION + * Maintains common members and methods related with signature operation. + ******************************************************************************/ +{ +protected: + + /* + * the Signature bridge component, which performs signature generation + * and verification based on xmlsec library. + */ + css::uno::Reference< css::xml::crypto::XXMLSignature > m_xXMLSignature; + + /* + * a collection of ElementCollector's ids. Each ElementCollector + * represents one element signed by this signature. + */ + std::vector< sal_Int32 > m_vReferenceIds; + + /* + * remembers how many references this signature has. + */ + sal_Int32 m_nTotalReferenceNumber; + + /* + * a collection of Uri binding. + * + * the m_vUris is used to hold the Uri strings, and the m_vXInputStreams is used + * to hold corresponding bound XInputStream interface. + */ + std::vector< OUString > m_vUris; + std::vector< css::uno::Reference< css::io::XInputStream > > m_vXInputStreams; + +protected: + explicit SignatureEngine(); + virtual ~SignatureEngine() override {}; + + virtual void tryToPerform( ) override; + virtual void clearUp( ) const override; + bool checkReady() const; + + /* + * starts the main function. This method will be implemented by any sub-class. + * For a SignatureCreator, it performs signing operation; + * for a SignatureVerifier, verification operation is performed. + */ + /// @throws css::uno::Exception + /// @throws css::uno::RuntimeException + virtual void startEngine( const rtl::Reference<XMLSignatureTemplateImpl>&) + {}; + +public: + /* XReferenceCollector */ + virtual void SAL_CALL setReferenceCount( sal_Int32 count ) override; + + virtual void SAL_CALL setReferenceId( sal_Int32 id ) override; + + /* XUriBinding */ + virtual void SAL_CALL setUriBinding( + const OUString& uri, + const css::uno::Reference< css::io::XInputStream >& aInputStream ) override; + virtual css::uno::Reference< css::io::XInputStream > + SAL_CALL getUriBinding( const OUString& uri ) override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/framework/signatureverifierimpl.hxx b/xmlsecurity/inc/framework/signatureverifierimpl.hxx new file mode 100644 index 0000000000..15c79643e0 --- /dev/null +++ b/xmlsecurity/inc/framework/signatureverifierimpl.hxx @@ -0,0 +1,88 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <com/sun/star/xml/crypto/sax/XSignatureVerifyResultBroadcaster.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <cppuhelper/implbase.hxx> + +#include <xmlsecuritydllapi.h> +#include <framework/signatureengine.hxx> + +namespace com::sun::star::xml::crypto::sax { class XSignatureVerifyResultListener; } +namespace com::sun::star::xml::crypto { class XXMLSecurityContext; } + +typedef cppu::ImplInheritanceHelper +< + SignatureEngine, + css::xml::crypto::sax::XSignatureVerifyResultBroadcaster, + css::lang::XInitialization, + css::lang::XServiceInfo +> SignatureVerifierImpl_Base; + +class SignatureVerifierImpl final : public SignatureVerifierImpl_Base +/****** SignatureVerifier.hxx/CLASS SignatureVerifierImpl ********************* + * + * NAME + * SignatureVerifierImpl -- verifies a signature + * + * FUNCTION + * Collects all resources for a signature verification, then verifies the + * signature by invoking a xmlsec-based signature bridge component. + ******************************************************************************/ +{ +private: + css::uno::Reference< css::xml::crypto::XXMLSecurityContext > m_xXMLSecurityContext; + + virtual void notifyResultListener() const override; + virtual void startEngine( const rtl::Reference<XMLSignatureTemplateImpl>& xSignatureTemplate) override; + +public: + explicit SignatureVerifierImpl(); + virtual ~SignatureVerifierImpl() override; + + /* XSignatureVerifyResultBroadcaster */ + virtual void SAL_CALL addSignatureVerifyResultListener( + const css::uno::Reference< css::xml::crypto::sax::XSignatureVerifyResultListener >& listener ) override; + virtual void SAL_CALL removeSignatureVerifyResultListener( + const css::uno::Reference< css::xml::crypto::sax::XSignatureVerifyResultListener >& listener ) override; + + /* XInitialization */ + virtual void SAL_CALL initialize( + const css::uno::Sequence< css::uno::Any >& aArguments ) override; + + /* XServiceInfo */ + virtual OUString SAL_CALL getImplementationName( ) override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; + + void updateSignature( const css::uno::Reference< css::xml::crypto::XXMLSignature >& xSignature, + const css::uno::Reference< css::xml::crypto::XXMLSecurityContext >& xContext ) { m_xXMLSignature = xSignature; m_xXMLSecurityContext = xContext; } +}; + +/// @throws css::uno::RuntimeException +OUString SignatureVerifierImpl_getImplementationName(); + +/// @throws css::uno::RuntimeException +css::uno::Sequence< OUString > SignatureVerifierImpl_getSupportedServiceNames( ); + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/framework/xmlsignaturetemplateimpl.hxx b/xmlsecurity/inc/framework/xmlsignaturetemplateimpl.hxx new file mode 100644 index 0000000000..c0dee1173b --- /dev/null +++ b/xmlsecurity/inc/framework/xmlsignaturetemplateimpl.hxx @@ -0,0 +1,95 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <sal/config.h> +#include <rtl/ustring.hxx> +#include <cppuhelper/implbase.hxx> + +#include <com/sun/star/uno/Reference.hxx> + +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/xml/crypto/XXMLSignatureTemplate.hpp> + +#include <vector> + +namespace com::sun::star::lang { class XMultiServiceFactory; } +namespace com::sun::star::xml::wrapper { class XXMLElementWrapper; } + +class XMLSignatureTemplateImpl final : public ::cppu::WeakImplHelper< + css::xml::crypto::XXMLSignatureTemplate , + css::lang::XServiceInfo > +{ + private: + css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > m_xTemplate ; + std::vector< css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > > targets; + css::uno::Reference< css::xml::crypto::XUriBinding > m_xUriBinding; + css::xml::crypto::SecurityOperationStatus m_nStatus; + + public: + explicit XMLSignatureTemplateImpl(); + virtual ~XMLSignatureTemplateImpl() override; + + //Methods from XXMLSignatureTemplate + virtual void SAL_CALL setTemplate( + const css::uno::Reference< css::xml::wrapper::XXMLElementWrapper >& aXmlElement + ) override; + + virtual css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > SAL_CALL getTemplate( + ) override; + + virtual void SAL_CALL setTarget( + const css::uno::Reference< css::xml::wrapper::XXMLElementWrapper >& aXmlElement + ) override; + + virtual css::uno::Sequence< css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > > SAL_CALL getTargets( + ) override; + + virtual void SAL_CALL setBinding( + const css::uno::Reference< css::xml::crypto::XUriBinding >& aUriBinding ) override; + virtual css::uno::Reference< css::xml::crypto::XUriBinding > + SAL_CALL getBinding( ) override; + + virtual void SAL_CALL setStatus( + css::xml::crypto::SecurityOperationStatus status ) override; + virtual css::xml::crypto::SecurityOperationStatus + SAL_CALL getStatus( ) override; + + //Methods from XServiceInfo + virtual OUString SAL_CALL getImplementationName() override ; + + virtual sal_Bool SAL_CALL supportsService( + const OUString& ServiceName + ) override ; + + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override ; + + //Helper for XServiceInfo + static css::uno::Sequence< OUString > impl_getSupportedServiceNames() ; + + /// @throws css::uno::RuntimeException + static OUString impl_getImplementationName() ; + + //Helper for registry + /// @throws css::uno::RuntimeException + static css::uno::Reference< css::uno::XInterface > impl_createInstance( const css::uno::Reference< css::lang::XMultiServiceFactory >& aServiceManager ) ; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/gpg/SEInitializer.hxx b/xmlsecurity/inc/gpg/SEInitializer.hxx new file mode 100644 index 0000000000..e4da22029c --- /dev/null +++ b/xmlsecurity/inc/gpg/SEInitializer.hxx @@ -0,0 +1,47 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/xml/crypto/XSEInitializer.hpp> + +#include <xsecxmlsecdllapi.h> +#include <cppuhelper/implbase.hxx> + +namespace com::sun::star::xml::crypto { class XXMLSecurityContext; } + +class XSECXMLSEC_DLLPUBLIC SEInitializerGpg final : public cppu::WeakImplHelper +< + css::xml::crypto::XSEInitializer, + css::lang::XServiceInfo +> +{ +public: + SEInitializerGpg(); + virtual ~SEInitializerGpg() override; + + /* XSEInitializer */ + virtual css::uno::Reference< css::xml::crypto::XXMLSecurityContext > + SAL_CALL createSecurityContext( const OUString& ) override; + + virtual void SAL_CALL freeSecurityContext( const css::uno::Reference< + css::xml::crypto::XXMLSecurityContext >& securityContext ) override; + + /* XServiceInfo */ + virtual OUString SAL_CALL getImplementationName( ) override; + + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/gpg/xmlsignature_gpgimpl.hxx b/xmlsecurity/inc/gpg/xmlsignature_gpgimpl.hxx new file mode 100644 index 0000000000..906a51d19c --- /dev/null +++ b/xmlsecurity/inc/gpg/xmlsignature_gpgimpl.hxx @@ -0,0 +1,77 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <sal/config.h> +#include <rtl/ustring.hxx> +#include <xsecxmlsecdllapi.h> + +#include <cppuhelper/implbase.hxx> + +#include <com/sun/star/uno/Reference.hxx> + +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/xml/crypto/XXMLSignature.hpp> + +namespace com::sun::star::xml::crypto { class XXMLSignatureTemplate; } +namespace com::sun::star::xml::crypto { class XXMLSecurityContext; } +namespace com::sun::star::lang { class XMultiServiceFactory; } + + +class XSECXMLSEC_DLLPUBLIC XMLSignature_GpgImpl final : public ::cppu::WeakImplHelper< + css::xml::crypto::XXMLSignature , + css::lang::XServiceInfo > +{ + public: + explicit XMLSignature_GpgImpl(); + virtual ~XMLSignature_GpgImpl() override ; + + //Methods from XXMLSignature + virtual css::uno::Reference< css::xml::crypto::XXMLSignatureTemplate > SAL_CALL generate( + const css::uno::Reference< css::xml::crypto::XXMLSignatureTemplate >& aTemplate , + const css::uno::Reference< css::xml::crypto::XSecurityEnvironment >& aEnvironment + ) override ; + + virtual css::uno::Reference< css::xml::crypto::XXMLSignatureTemplate > SAL_CALL validate( + const css::uno::Reference< css::xml::crypto::XXMLSignatureTemplate >& aTemplate , + const css::uno::Reference< css::xml::crypto::XXMLSecurityContext >& aContext + ) override; + + //Methods from XServiceInfo + virtual OUString SAL_CALL getImplementationName() override ; + + virtual sal_Bool SAL_CALL supportsService( + const OUString& ServiceName + ) override ; + + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override ; + + //Helper for XServiceInfo + static css::uno::Sequence< OUString > impl_getSupportedServiceNames() ; + + /// @throws css::uno::RuntimeException + static OUString impl_getImplementationName() ; + + //Helper for registry + /// @throws css::uno::RuntimeException + static css::uno::Reference< css::uno::XInterface > impl_createInstance( const css::uno::Reference< css::lang::XMultiServiceFactory >& aServiceManager ) ; +} ; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/macrosecurity.hxx b/xmlsecurity/inc/macrosecurity.hxx new file mode 100644 index 0000000000..5d9feb94c8 --- /dev/null +++ b/xmlsecurity/inc/macrosecurity.hxx @@ -0,0 +1,126 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <vcl/weld.hxx> +#include <unotools/securityoptions.hxx> + +namespace com::sun::star::xml::crypto { class XSecurityEnvironment; } +class MacroSecurityTP; + +class MacroSecurity final : public weld::GenericDialogController +{ +private: + friend class MacroSecurityLevelTP; + friend class MacroSecurityTrustedSourcesTP; + + css::uno::Reference<css::xml::crypto::XSecurityEnvironment> m_xSecurityEnvironment; + + std::unique_ptr<weld::Notebook> m_xTabCtrl; + std::unique_ptr<weld::Button> m_xOkBtn; + std::unique_ptr<weld::Button> m_xResetBtn; + + std::unique_ptr<MacroSecurityTP> m_xLevelTP; + std::unique_ptr<MacroSecurityTP> m_xTrustSrcTP; + + DECL_LINK(ActivatePageHdl, const OUString&, void); + DECL_LINK(OkBtnHdl, weld::Button&, void); +public: + MacroSecurity(weld::Window* pParent, + css::uno::Reference<css::xml::crypto::XSecurityEnvironment> xSecurityEnvironment); + + void EnableReset(bool bEnable = true) + { + m_xResetBtn->set_sensitive(bEnable); + } +}; + +class MacroSecurityTP +{ +protected: + std::unique_ptr<weld::Builder> m_xBuilder; + std::unique_ptr<weld::Container> m_xContainer; + + MacroSecurity* m_pDlg; +public: + MacroSecurityTP(weld::Container* pParent, const OUString& rUIXMLDescription, + const OUString& rID, MacroSecurity* pDlg); + virtual ~MacroSecurityTP(); + + virtual void ActivatePage(); + virtual void ClosePage() = 0; +}; + +class MacroSecurityLevelTP : public MacroSecurityTP +{ +private: + sal_uInt16 mnCurLevel; + + std::unique_ptr<weld::RadioButton> m_xVeryHighRB; + std::unique_ptr<weld::RadioButton> m_xHighRB; + std::unique_ptr<weld::RadioButton> m_xMediumRB; + std::unique_ptr<weld::RadioButton> m_xLowRB; + std::unique_ptr<weld::Widget> m_xVHighImg; + std::unique_ptr<weld::Widget> m_xHighImg; + std::unique_ptr<weld::Widget> m_xMedImg; + std::unique_ptr<weld::Widget> m_xLowImg; + + DECL_LINK(RadioButtonHdl, weld::Toggleable&, void); +public: + MacroSecurityLevelTP(weld::Container* pParent, MacroSecurity* pDlg); + virtual void ClosePage() override; +}; + +class MacroSecurityTrustedSourcesTP : public MacroSecurityTP +{ +private: + std::vector< SvtSecurityOptions::Certificate > m_aTrustedAuthors; + + bool mbAuthorsReadonly; + bool mbURLsReadonly; + + std::unique_ptr<weld::Image> m_xTrustCertROFI; + std::unique_ptr<weld::TreeView> m_xTrustCertLB; + std::unique_ptr<weld::Button> m_xViewCertPB; + std::unique_ptr<weld::Button> m_xRemoveCertPB; + std::unique_ptr<weld::Image> m_xTrustFileROFI; + std::unique_ptr<weld::TreeView> m_xTrustFileLocLB; + std::unique_ptr<weld::Button> m_xAddLocPB; + std::unique_ptr<weld::Button> m_xRemoveLocPB; + + DECL_LINK(ViewCertPBHdl, weld::Button&, void); + DECL_LINK(RemoveCertPBHdl, weld::Button&, void); + DECL_LINK(AddLocPBHdl, weld::Button&, void); + DECL_LINK(RemoveLocPBHdl, weld::Button&, void); + DECL_LINK(TrustCertLBSelectHdl, weld::TreeView&, void); + DECL_LINK(TrustFileLocLBSelectHdl, weld::TreeView&, void); + + void FillCertLB(const bool bShowWarnings = false); + void ImplCheckButtons(); + void ShowBrokenCertificateError(std::u16string_view rData); + +public: + MacroSecurityTrustedSourcesTP(weld::Container* pParent, MacroSecurity* pDlg); + + virtual void ActivatePage() override; + virtual void ClosePage() override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/pch/precompiled_xmlsecurity.cxx b/xmlsecurity/inc/pch/precompiled_xmlsecurity.cxx new file mode 100644 index 0000000000..16ace305fc --- /dev/null +++ b/xmlsecurity/inc/pch/precompiled_xmlsecurity.cxx @@ -0,0 +1,12 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "precompiled_xmlsecurity.hxx" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/pch/precompiled_xmlsecurity.hxx b/xmlsecurity/inc/pch/precompiled_xmlsecurity.hxx new file mode 100644 index 0000000000..bf9c9025a7 --- /dev/null +++ b/xmlsecurity/inc/pch/precompiled_xmlsecurity.hxx @@ -0,0 +1,200 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +/* + This file has been autogenerated by update_pch.sh. It is possible to edit it + manually (such as when an include file has been moved/renamed/removed). All such + manual changes will be rewritten by the next run of update_pch.sh (which presumably + also fixes all possible problems, so it's usually better to use it). + + Generated on 2021-04-11 19:48:55 using: + ./bin/update_pch xmlsecurity xmlsecurity --cutoff=6 --exclude:system --include:module --include:local + + If after updating build fails, use the following command to locate conflicting headers: + ./bin/update_pch_bisect ./xmlsecurity/inc/pch/precompiled_xmlsecurity.hxx "make xmlsecurity.build" --find-conflicts +*/ + +#include <sal/config.h> +#if PCH_LEVEL >= 1 +#include <algorithm> +#include <assert.h> +#include <cassert> +#include <chrono> +#include <cmath> +#include <cstddef> +#include <cstdlib> +#include <cstring> +#include <float.h> +#include <functional> +#include <initializer_list> +#include <iomanip> +#include <limits.h> +#include <limits> +#include <math.h> +#include <memory> +#include <new> +#include <ostream> +#include <set> +#include <stddef.h> +#include <string.h> +#include <string> +#include <string_view> +#include <type_traits> +#include <unordered_map> +#include <utility> +#include <vector> +#endif // PCH_LEVEL >= 1 +#if PCH_LEVEL >= 2 +#include <osl/diagnose.h> +#include <osl/doublecheckedlocking.h> +#include <osl/endian.h> +#include <osl/file.hxx> +#include <osl/getglobalmutex.hxx> +#include <osl/interlck.h> +#include <osl/mutex.h> +#include <osl/mutex.hxx> +#include <osl/thread.h> +#include <osl/time.h> +#include <rtl/alloc.h> +#include <rtl/instance.hxx> +#include <rtl/locale.h> +#include <rtl/math.h> +#include <rtl/ref.hxx> +#include <rtl/strbuf.hxx> +#include <rtl/string.h> +#include <rtl/string.hxx> +#include <rtl/stringconcat.hxx> +#include <rtl/stringutils.hxx> +#include <rtl/textcvt.h> +#include <rtl/textenc.h> +#include <rtl/uri.hxx> +#include <rtl/ustrbuf.hxx> +#include <rtl/ustring.h> +#include <rtl/ustring.hxx> +#include <rtl/uuid.h> +#include <sal/log.hxx> +#include <sal/macros.h> +#include <sal/saldllapi.h> +#include <sal/types.h> +#include <sal/typesizes.h> +#include <vcl/BinaryDataContainer.hxx> +#include <vcl/Scanline.hxx> +#include <vcl/alpha.hxx> +#include <vcl/bitmap.hxx> +#include <vcl/bitmap/BitmapTypes.hxx> +#include <vcl/bitmapex.hxx> +#include <vcl/checksum.hxx> +#include <vcl/dllapi.h> +#include <comphelper/errcode.hxx> +#include <vcl/fntstyle.hxx> +#include <vcl/font.hxx> +#include <vcl/mapmod.hxx> +#include <vcl/region.hxx> +#include <vcl/task.hxx> +#include <vcl/uitest/factory.hxx> +#include <vcl/vclenum.hxx> +#include <vcl/vclptr.hxx> +#endif // PCH_LEVEL >= 2 +#if PCH_LEVEL >= 3 +#include <basegfx/basegfxdllapi.h> +#include <basegfx/color/bcolor.hxx> +#include <basegfx/numeric/ftools.hxx> +#include <basegfx/point/b2dpoint.hxx> +#include <basegfx/point/b2ipoint.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/polygon/b2dpolypolygon.hxx> +#include <basegfx/range/b2drange.hxx> +#include <basegfx/range/b2irange.hxx> +#include <basegfx/range/basicrange.hxx> +#include <basegfx/tuple/b2dtuple.hxx> +#include <basegfx/tuple/b2i64tuple.hxx> +#include <basegfx/tuple/b2ituple.hxx> +#include <basegfx/tuple/b3dtuple.hxx> +#include <basegfx/utils/common.hxx> +#include <basegfx/vector/b2dvector.hxx> +#include <basegfx/vector/b2enums.hxx> +#include <basegfx/vector/b2ivector.hxx> +#include <com/sun/star/accessibility/XAccessible.hpp> +#include <com/sun/star/accessibility/XAccessibleRelationSet.hpp> +#include <com/sun/star/embed/ElementModes.hpp> +#include <com/sun/star/embed/StorageFormats.hpp> +#include <com/sun/star/embed/XStorage.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XTypeProvider.hpp> +#include <com/sun/star/uno/Any.h> +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/uno/RuntimeException.hpp> +#include <com/sun/star/uno/Sequence.h> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/uno/Type.h> +#include <com/sun/star/uno/Type.hxx> +#include <com/sun/star/uno/TypeClass.hdl> +#include <com/sun/star/uno/XInterface.hpp> +#include <com/sun/star/uno/XWeak.hpp> +#include <com/sun/star/uno/genfunc.h> +#include <com/sun/star/uno/genfunc.hxx> +#include <com/sun/star/util/Date.hpp> +#include <com/sun/star/util/DateTime.hpp> +#include <com/sun/star/util/XCloneable.hpp> +#include <com/sun/star/xml/crypto/DigestID.hpp> +#include <com/sun/star/xml/crypto/SecurityOperationStatus.hpp> +#include <com/sun/star/xml/crypto/XXMLSignature.hpp> +#include <com/sun/star/xml/crypto/sax/XReferenceResolvedBroadcaster.hpp> +#include <com/sun/star/xml/sax/XFastAttributeList.hpp> +#include <com/sun/star/xml/sax/XFastTokenHandler.hpp> +#include <comphelper/comphelperdllapi.h> +#include <cppu/cppudllapi.h> +#include <cppu/unotype.hxx> +#include <cppuhelper/cppuhelperdllapi.h> +#include <cppuhelper/implbase.hxx> +#include <cppuhelper/implbase_ex.hxx> +#include <cppuhelper/implbase_ex_post.hxx> +#include <cppuhelper/implbase_ex_pre.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <cppuhelper/weak.hxx> +#include <i18nlangtag/lang.h> +#include <o3tl/cow_wrapper.hxx> +#include <o3tl/strong_int.hxx> +#include <o3tl/typed_flags_set.hxx> +#include <o3tl/underlyingenumvalue.hxx> +#include <salhelper/salhelperdllapi.h> +#include <salhelper/simplereferenceobject.hxx> +#include <sax/saxdllapi.h> +#include <svl/sigstruct.hxx> +#include <tools/color.hxx> +#include <tools/date.hxx> +#include <tools/degree.hxx> +#include <tools/fldunit.hxx> +#include <tools/fontenum.hxx> +#include <tools/gen.hxx> +#include <tools/link.hxx> +#include <tools/long.hxx> +#include <tools/mapunit.hxx> +#include <tools/solar.h> +#include <tools/toolsdllapi.h> +#include <typelib/typeclass.h> +#include <typelib/typedescription.h> +#include <typelib/uik.h> +#include <uno/any2.h> +#include <uno/data.h> +#include <uno/sequence2.h> +#include <unotools/datetime.hxx> +#include <unotools/options.hxx> +#include <unotools/unotoolsdllapi.h> +#include <xmloff/dllapi.h> +#endif // PCH_LEVEL >= 3 +#if PCH_LEVEL >= 4 +#include <biginteger.hxx> +#include <xmlsecuritydllapi.h> +#include <xsecctl.hxx> +#endif // PCH_LEVEL >= 4 + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/pch/precompiled_xsec_xmlsec.cxx b/xmlsecurity/inc/pch/precompiled_xsec_xmlsec.cxx new file mode 100644 index 0000000000..74123c2f14 --- /dev/null +++ b/xmlsecurity/inc/pch/precompiled_xsec_xmlsec.cxx @@ -0,0 +1,12 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "precompiled_xsec_xmlsec.hxx" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/pch/precompiled_xsec_xmlsec.hxx b/xmlsecurity/inc/pch/precompiled_xsec_xmlsec.hxx new file mode 100644 index 0000000000..d69f3120e0 --- /dev/null +++ b/xmlsecurity/inc/pch/precompiled_xsec_xmlsec.hxx @@ -0,0 +1,149 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +/* + This file has been autogenerated by update_pch.sh. It is possible to edit it + manually (such as when an include file has been moved/renamed/removed). All such + manual changes will be rewritten by the next run of update_pch.sh (which presumably + also fixes all possible problems, so it's usually better to use it). + + Generated on 2021-04-08 13:57:49 using: + ./bin/update_pch xmlsecurity xsec_xmlsec --cutoff=2 --exclude:system --include:module --include:local + + If after updating build fails, use the following command to locate conflicting headers: + ./bin/update_pch_bisect ./xmlsecurity/inc/pch/precompiled_xsec_xmlsec.hxx "make xmlsecurity.build" --find-conflicts +*/ + +#include <sal/config.h> +#if PCH_LEVEL >= 1 +#include <algorithm> +#include <cassert> +#include <chrono> +#include <cstddef> +#include <cstdlib> +#include <initializer_list> +#include <iomanip> +#include <limits> +#include <memory> +#include <new> +#include <ostream> +#ifdef XMLSEC_CRYPTO_NSS +#include <pk11pub.h> +#endif +#include <stddef.h> +#include <string.h> +#include <string> +#include <string_view> +#include <type_traits> +#include <utility> +#include <vector> +#endif // PCH_LEVEL >= 1 +#if PCH_LEVEL >= 2 +#include <osl/diagnose.h> +#include <osl/doublecheckedlocking.h> +#include <osl/file.h> +#include <osl/file.hxx> +#include <osl/getglobalmutex.hxx> +#include <osl/interlck.h> +#include <osl/mutex.h> +#include <osl/mutex.hxx> +#include <osl/thread.h> +#include <osl/time.h> +#include <rtl/alloc.h> +#include <rtl/bootstrap.h> +#include <rtl/bootstrap.hxx> +#include <rtl/instance.hxx> +#include <rtl/malformeduriexception.hxx> +#include <rtl/random.h> +#include <rtl/ref.hxx> +#include <rtl/string.h> +#include <rtl/string.hxx> +#include <rtl/stringconcat.hxx> +#include <rtl/stringutils.hxx> +#include <rtl/textcvt.h> +#include <rtl/textenc.h> +#include <rtl/uri.h> +#include <rtl/uri.hxx> +#include <rtl/ustring.h> +#include <rtl/ustring.hxx> +#include <rtl/uuid.h> +#include <sal/log.hxx> +#include <sal/macros.h> +#include <sal/saldllapi.h> +#include <sal/types.h> +#include <sal/typesizes.h> +#include <vcl/dllapi.h> +#include <comphelper/errcode.hxx> +#endif // PCH_LEVEL >= 2 +#if PCH_LEVEL >= 3 +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XTypeProvider.hpp> +#include <com/sun/star/lang/XUnoTunnel.hpp> +#include <com/sun/star/uno/Any.h> +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/uno/Exception.hpp> +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/uno/RuntimeException.hpp> +#include <com/sun/star/uno/Sequence.h> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/uno/Type.h> +#include <com/sun/star/uno/Type.hxx> +#include <com/sun/star/uno/TypeClass.hdl> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/uno/XInterface.hpp> +#include <com/sun/star/uno/XWeak.hpp> +#include <com/sun/star/uno/genfunc.h> +#include <com/sun/star/uno/genfunc.hxx> +#include <com/sun/star/util/XCloneable.hpp> +#include <com/sun/star/xml/csax/XCompressedDocumentHandler.hpp> +#include <com/sun/star/xml/sax/XAttributeList.hpp> +#include <com/sun/star/xml/wrapper/XXMLDocumentWrapper.hpp> +#include <comphelper/servicehelper.hxx> +#include <cppu/cppudllapi.h> +#include <cppu/unotype.hxx> +#include <cppuhelper/cppuhelperdllapi.h> +#include <cppuhelper/exc_hlp.hxx> +#include <cppuhelper/implbase.hxx> +#include <cppuhelper/implbase_ex.hxx> +#include <cppuhelper/implbase_ex_post.hxx> +#include <cppuhelper/implbase_ex_pre.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <cppuhelper/weak.hxx> +#include <libxml/tree.h> +#include <o3tl/typed_flags_set.hxx> +#include <o3tl/underlyingenumvalue.hxx> +#include <salhelper/singletonref.hxx> +#include <tools/lineend.hxx> +#include <tools/long.hxx> +#include <tools/ref.hxx> +#include <tools/stream.hxx> +#include <tools/toolsdllapi.h> +#include <typelib/typeclass.h> +#include <typelib/typedescription.h> +#include <typelib/uik.h> +#include <uno/any2.h> +#include <uno/data.h> +#include <uno/sequence2.h> +#include <unotools/unotoolsdllapi.h> +#include <xmloff/dllapi.h> +#endif // PCH_LEVEL >= 3 +#if PCH_LEVEL >= 4 +#include <xmlsec-wrapper.h> +#include <xsecxmlsecdllapi.h> +#endif // PCH_LEVEL >= 4 + +// Cleanup windows header macro pollution. +#if defined(_WIN32) && defined(WINAPI) +#include <postwin.h> +#undef RGB +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/pdfsignaturehelper.hxx b/xmlsecurity/inc/pdfsignaturehelper.hxx new file mode 100644 index 0000000000..ea24685d2a --- /dev/null +++ b/xmlsecurity/inc/pdfsignaturehelper.hxx @@ -0,0 +1,73 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#pragma once + +#include "xmlsecuritydllapi.h" + +#include <svl/sigstruct.hxx> + +namespace com::sun::star +{ +namespace frame +{ +class XModel; +} +namespace io +{ +class XInputStream; +} +namespace security +{ +class XCertificate; +} +namespace security +{ +struct DocumentSignatureInformation; +} +namespace xml::crypto +{ +class XSecurityEnvironment; +} +} +class SvStream; + +/// Handles signatures of a PDF file. +class XMLSECURITY_DLLPUBLIC PDFSignatureHelper +{ + SignatureInformations m_aSignatureInfos; + + css::uno::Reference<css::security::XCertificate> m_xCertificate; + OUString m_aDescription; + +public: + PDFSignatureHelper(); + bool ReadAndVerifySignature(const css::uno::Reference<css::io::XInputStream>& xInputStream); + bool ReadAndVerifySignatureSvStream(SvStream& rStream); + css::uno::Sequence<css::security::DocumentSignatureInformation> + GetDocumentSignatureInformations( + const css::uno::Reference<css::xml::crypto::XSecurityEnvironment>& xSecEnv) const; + SignatureInformations const& GetSignatureInformations() const; + + /// Return the ID of the next created signature. + sal_Int32 GetNewSecurityId() const; + /// Certificate to be used next time signing is performed. + void SetX509Certificate(const css::uno::Reference<css::security::XCertificate>& xCertificate); + /// Comment / reason to be used next time signing is performed. + void SetDescription(const OUString& rDescription); + /// Append a new signature at the end of xInputStream. + bool Sign(const css::uno::Reference<css::frame::XModel>& xModel, + const css::uno::Reference<css::io::XInputStream>& xInputStream, bool bAdES); + /// Remove the signature at nPosition (and all dependent signatures) from xInputStream. + static bool RemoveSignature(const css::uno::Reference<css::io::XInputStream>& xInputStream, + sal_uInt16 nPosition); +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/resourcemanager.hxx b/xmlsecurity/inc/resourcemanager.hxx new file mode 100644 index 0000000000..1dc5b29874 --- /dev/null +++ b/xmlsecurity/inc/resourcemanager.hxx @@ -0,0 +1,26 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <unotools/resmgr.hxx> + +inline OUString XsResId(TranslateId aId) { return Translate::get(aId, Translate::Create("xsc")); } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/strings.hrc b/xmlsecurity/inc/strings.hrc new file mode 100644 index 0000000000..7e99a58d52 --- /dev/null +++ b/xmlsecurity/inc/strings.hrc @@ -0,0 +1,68 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#define NC_(Context, String) TranslateId(Context, u8##String) + +#define STR_CERTIFICATE_NOT_VALIDATED NC_("STR_CERTIFICATE_NOT_VALIDATED", "The certificate could not be validated.") +#define STR_VERSION NC_("STR_VERSION", "Version") +#define STR_SERIALNUM NC_("STR_SERIALNUM", "Serial Number") +#define STR_ISSUER NC_("STR_ISSUER", "Issuer") +#define STR_VALIDFROM NC_("STR_VALIDFROM", "Valid From") +#define STR_VALIDTO NC_("STR_VALIDTO", "Valid to") +#define STR_SUBJECT NC_("STR_SUBJECT", "Subject") +#define STR_SUBJECT_PUBKEY_ALGO NC_("STR_SUBJECT_PUBKEY_ALGO", "Subject Algorithm") +#define STR_SUBJECT_PUBKEY_VAL NC_("STR_SUBJECT_PUBKEY_VAL", "Public Key") +#define STR_SIGNATURE_ALGO NC_("STR_SIGNATURE_ALGO", "Signature Algorithm") +#define STR_USE NC_("STR_USE", "Certificate Use") +#define STR_THUMBPRINT_SHA1 NC_("STR_THUMBPRINT_SHA1", "Thumbprint SHA1") +#define STR_THUMBPRINT_MD5 NC_("STR_THUMBPRINT_MD5", "Thumbprint MD5") + +#define STR_XMLSECDLG_OPENED_CRTMGR NC_("STR_XMLSECDLG_OPENED_CRTMGR", "You have opened the certificate manager at\n") +#define STR_XMLSECDLG_OLD_ODF_FORMAT NC_("STR_XMLSECDLG_OLD_ODF_FORMAT", "This document contains signatures in ODF 1.1 (OpenOffice.org 2.x) format. " \ + "Signing documents in %PRODUCTNAME %PRODUCTVERSION requires ODF 1.2 format version. " \ + "Thus no signatures can be added or removed to this document.\n\n" \ + "Save document in ODF 1.2 format and add all desired signatures again.") +#define STR_XMLSECDLG_QUERY_REMOVEDOCSIGNBEFORESIGN NC_("STR_XMLSECDLG_QUERY_REMOVEDOCSIGNBEFORESIGN", "Adding or removing a macro signature will remove all document signatures.\n" \ + "Do you really want to continue?") +#define STR_XMLSECDLG_QUERY_REALLYREMOVE NC_("STR_XMLSECDLG_QUERY_REALLYREMOVE", "Document signature cannot be restored, once removed.\n" \ + "Do you really want to remove selected signature?") + +#define STR_XMLSECDLG_SIGNING_FAILED NC_("STR_XMLSECDLG_SIGNING_FAILED", "An error occurred while adding the signature.") +#define STR_XMLSECDLG_NO_CERT_MANAGER NC_("STR_XMLSECDLG_NO_CERT_MANAGER", "Could not find any certificate manager.") +#define STR_XMLSECDLG_NO_CERT_FOUND NC_("STR_XMLSECDLG_NO_CERT_FOUND", "Could not find the certificate.") + +#define RID_XMLSECWB_NO_MOZILLA_PROFILE NC_("RID_XMLSECWB_NO_MOZILLA_PROFILE", "Digital signatures functionality could not be used, because no Mozilla user profile was found. Please check the Mozilla installation.") + +#define STR_DIGITAL_SIGNATURE NC_("selectcertificatedialog|STR_DIGITAL_SIGNATURE", "Digital signature") +#define STR_NON_REPUDIATION NC_("selectcertificatedialog|STR_NON_REPUDIATION", "Non-repudiation") +#define STR_KEY_ENCIPHERMENT NC_("selectcertificatedialog|STR_KEY_ENCIPHERMENT", "Key encipherment") +#define STR_DATA_ENCIPHERMENT NC_("selectcertificatedialog|STR_DATA_ENCIPHERMENT", "Data encipherment") +#define STR_KEY_AGREEMENT NC_("selectcertificatedialog|STR_KEY_AGREEMENT", "Key Agreement") +#define STR_KEY_CERT_SIGN NC_("selectcertificatedialog|STR_KEY_CERT_SIGN", "Certificate signature verification") +#define STR_CRL_SIGN NC_("selectcertificatedialog|STR_CRL_SIGN", "CRL signature verification") +#define STR_ENCIPHER_ONLY NC_("selectcertificatedialog|STR_ENCIPHER_ONLY", "Only for encipherment") +#define STR_SIGN NC_("selectcertificatedialog|str_sign", "Sign") +#define STR_SELECTSIGN NC_("selectcertificatedialog|str_selectsign", "Select") +#define STR_ENCRYPT NC_("selectcertificatedialog|str_encrypt", "Encrypt") + +#define STR_BROKEN_MACRO_CERTIFICATE_DATA NC_("STR_BROKEN_MACRO_CERTIFICATE_DATA", "Macro security problem!\n\nBroken certificate data: %{data}") + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/xmlsec-wrapper.h b/xmlsecurity/inc/xmlsec-wrapper.h new file mode 100644 index 0000000000..3ad705400c --- /dev/null +++ b/xmlsecurity/inc/xmlsec-wrapper.h @@ -0,0 +1,43 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <sal/config.h> + +#include <sal/types.h> + +#include <libxml/parser.h> +#include <xmlsec/base64.h> +#include <xmlsec/bn.h> +#include <xmlsec/errors.h> +#include <xmlsec/io.h> +#include <xmlsec/keysmngr.h> +#include <xmlsec/strings.h> +#include <xmlsec/xmldsig.h> +#include <xmlsec/xmlenc.h> +#include <xmlsec/xmlsec.h> +#include <xmlsec/xmltree.h> +#ifdef XMLSEC_CRYPTO_NSS +#include <xmlsec/nss/app.h> +#include <xmlsec/nss/crypto.h> +#include <xmlsec/nss/pkikeys.h> +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/xmlsec/errorcallback.hxx b/xmlsecurity/inc/xmlsec/errorcallback.hxx new file mode 100644 index 0000000000..80ba564e9b --- /dev/null +++ b/xmlsecurity/inc/xmlsec/errorcallback.hxx @@ -0,0 +1,30 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <xsecxmlsecdllapi.h> + +// Only used for logging +void setErrorRecorder(); +//ToDo +//void setErrorRecorder(const css::uno::Reference< css::xml::crypto::XXMLEncryptionTemplate >& xTemplate); +void clearErrorRecorder(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/xmlsec/saxhelper.hxx b/xmlsecurity/inc/xmlsec/saxhelper.hxx new file mode 100644 index 0000000000..a5863ffd0e --- /dev/null +++ b/xmlsecurity/inc/xmlsec/saxhelper.hxx @@ -0,0 +1,86 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <sal/config.h> + +#include <string_view> + +#include <libxml/parser.h> +#include <libxml/tree.h> + +#include <rtl/ustring.hxx> + +namespace com::sun::star::xml::csax { struct XMLAttribute; } +namespace com::sun::star::uno { template <typename > class Sequence; } + +/** This class represents a SAX handler which simply forwards to + the corresponding libxml API and translates parameter if necessary. +*/ +class SAXHelper final +{ + private: + xmlParserCtxtPtr m_pParserCtxt ; + xmlSAXHandlerPtr m_pSaxHandler ; + + public: + SAXHelper( ) ; + ~SAXHelper() ; + + xmlNodePtr getCurrentNode() { return m_pParserCtxt->node;} + void setCurrentNode(const xmlNodePtr pNode); + xmlDocPtr getDocument() { return m_pParserCtxt->myDoc;} + + /// @throws css::xml::sax::SAXException + /// @throws css::uno::RuntimeException + void startDocument() ; + + /// @throws css::xml::sax::SAXException + /// @throws css::uno::RuntimeException + void endDocument() ; + + /// @throws css::xml::sax::SAXException + /// @throws css::uno::RuntimeException + void startElement( + std::u16string_view aName , + const css::uno::Sequence< + css::xml::csax::XMLAttribute >& aAttributes ) ; + + /// @throws css::xml::sax::SAXException + /// @throws css::uno::RuntimeException + void endElement( std::u16string_view aName ) ; + + /// @throws css::xml::sax::SAXException + /// @throws css::uno::RuntimeException + void characters( std::u16string_view aChars ) ; + + /// @throws css::xml::sax::SAXException + /// @throws css::uno::RuntimeException + void ignorableWhitespace( std::u16string_view aWhitespaces ) ; + + /// @throws css::xml::sax::SAXException + /// @throws css::uno::RuntimeException + void processingInstruction( + std::u16string_view aTarget , + std::u16string_view aData ) ; + +} ; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/xmlsec/xmldocumentwrapper_xmlsecimpl.hxx b/xmlsecurity/inc/xmlsec/xmldocumentwrapper_xmlsecimpl.hxx new file mode 100644 index 0000000000..8f5695d10d --- /dev/null +++ b/xmlsecurity/inc/xmlsec/xmldocumentwrapper_xmlsecimpl.hxx @@ -0,0 +1,208 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <com/sun/star/xml/wrapper/XXMLDocumentWrapper.hpp> +#include <com/sun/star/xml/csax/XCompressedDocumentHandler.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <cppuhelper/implbase.hxx> + +#include <xmlsec/saxhelper.hxx> +#include <xsecxmlsecdllapi.h> + +#define NODEPOSITION_NORMAL 1 +#define NODEPOSITION_STARTELEMENT 2 +#define NODEPOSITION_ENDELEMENT 3 + +#include <libxml/tree.h> + +class XSECXMLSEC_DLLPUBLIC XMLDocumentWrapper_XmlSecImpl final : public cppu::WeakImplHelper +< + css::xml::wrapper::XXMLDocumentWrapper, + css::xml::sax::XDocumentHandler, + css::xml::csax::XCompressedDocumentHandler, + css::lang::XServiceInfo +> +/** + * NAME + * XMLDocumentWrapper_XmlSecImpl -- Class to manipulate a libxml2 + * document + * + * FUNCTION + * Converts SAX events into a libxml2 document, converts the document back + * into SAX event stream, and manipulate nodes in the document. + ******************************************************************************/ +{ +private: + /* the sax helper */ + SAXHelper saxHelper; + + /* the document used to convert SAX events to */ + xmlDocPtr m_pDocument; + + /* the root element */ + xmlNodePtr m_pRootElement; + + /* + * the current active element. The next incoming SAX event will be + * appended to this element + */ + xmlNodePtr m_pCurrentElement; + + /* + * This variable is used when converting the document or part of it into + * SAX events. See getNextSAXEvent method. + */ + sal_Int32 m_nCurrentPosition; + + /* + * used for recursive deletion. See recursiveDelete method + */ + xmlNodePtr m_pStopAtNode; + xmlNodePtr m_pCurrentReservedNode; + css::uno::Sequence< css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > > m_aReservedNodes; + sal_Int32 m_nReservedNodeIndex; + +private: + void getNextSAXEvent(); + + /// @throws css::xml::sax::SAXException + static void sendStartElement( + const css::uno::Reference< css::xml::sax::XDocumentHandler >& xHandler, + const css::uno::Reference< css::xml::sax::XDocumentHandler >& xHandler2, + const xmlNodePtr pNode); + + /// @throws css::xml::sax::SAXException + static void sendEndElement( + const css::uno::Reference< css::xml::sax::XDocumentHandler >& xHandler, + const css::uno::Reference< css::xml::sax::XDocumentHandler >& xHandler2, + const xmlNodePtr pNode); + + /// @throws css::xml::sax::SAXException + static void sendNode( + const css::uno::Reference< css::xml::sax::XDocumentHandler >& xHandler, + const css::uno::Reference< css::xml::sax::XDocumentHandler >& xHandler2, + const xmlNodePtr pNode); + + static OString getNodeQName(const xmlNodePtr pNode); + + sal_Int32 recursiveDelete( const xmlNodePtr pNode); + + void getNextReservedNode(); + + void removeNode( const xmlNodePtr pNode) const; + + static xmlNodePtr checkElement( + const css::uno::Reference< css::xml::wrapper::XXMLElementWrapper >& xXMLElement); + + void buildIDAttr( xmlNodePtr pNode ) const; + void rebuildIDLink( xmlNodePtr pNode ) const; + +public: + XMLDocumentWrapper_XmlSecImpl(); + virtual ~XMLDocumentWrapper_XmlSecImpl() override; + + /* css::xml::wrapper::XXMLDocumentWrapper */ + virtual css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > SAL_CALL getCurrentElement( ) override; + + virtual void SAL_CALL setCurrentElement( const css::uno::Reference< + css::xml::wrapper::XXMLElementWrapper >& element ) override; + + virtual void SAL_CALL removeCurrentElement( ) override; + + virtual sal_Bool SAL_CALL isCurrent( const css::uno::Reference< + css::xml::wrapper::XXMLElementWrapper >& node ) override; + + virtual sal_Bool SAL_CALL isCurrentElementEmpty( ) override; + + virtual OUString SAL_CALL getNodeName( const css::uno::Reference< + css::xml::wrapper::XXMLElementWrapper >& node ) override; + + virtual void SAL_CALL clearUselessData( + const css::uno::Reference< css::xml::wrapper::XXMLElementWrapper >& node, + const css::uno::Sequence< css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > >& reservedDescendants, + const css::uno::Reference< css::xml::wrapper::XXMLElementWrapper >& stopAtNode ) override; + + virtual void SAL_CALL collapse( const css::uno::Reference< + css::xml::wrapper::XXMLElementWrapper >& node ) override; + + virtual void SAL_CALL generateSAXEvents( + const css::uno::Reference< css::xml::sax::XDocumentHandler >& handler, + const css::uno::Reference< css::xml::sax::XDocumentHandler >& xEventKeeperHandler, + const css::uno::Reference< css::xml::wrapper::XXMLElementWrapper >& startNode, + const css::uno::Reference< css::xml::wrapper::XXMLElementWrapper >& endNode ) override; + + virtual void SAL_CALL getTree( + const css::uno::Reference< css::xml::sax::XDocumentHandler >& handler ) override; + + virtual void SAL_CALL rebuildIDLink( + const css::uno::Reference< css::xml::wrapper::XXMLElementWrapper >& node ) override; + + /* css::xml::sax::XDocumentHandler */ + virtual void SAL_CALL startDocument( ) override; + + virtual void SAL_CALL endDocument( ) override; + + virtual void SAL_CALL startElement( + const OUString& aName, + const css::uno::Reference< css::xml::sax::XAttributeList >& xAttribs ) override; + + virtual void SAL_CALL endElement( const OUString& aName ) override; + + virtual void SAL_CALL characters( const OUString& aChars ) override; + + virtual void SAL_CALL ignorableWhitespace( const OUString& aWhitespaces ) override; + + virtual void SAL_CALL processingInstruction( const OUString& aTarget, const OUString& aData ) override; + + virtual void SAL_CALL setDocumentLocator( const css::uno::Reference< css::xml::sax::XLocator >& xLocator ) override; + + /* css::xml::csax::XCompressedDocumentHandler */ + virtual void SAL_CALL compressedStartDocument( ) override; + + virtual void SAL_CALL compressedEndDocument( ) override; + + virtual void SAL_CALL compressedStartElement( + const OUString& aName, + const css::uno::Sequence< css::xml::csax::XMLAttribute >& aAttributes ) override; + + virtual void SAL_CALL compressedEndElement( const OUString& aName ) override; + + virtual void SAL_CALL compressedCharacters( const OUString& aChars ) override; + + virtual void SAL_CALL compressedIgnorableWhitespace( const OUString& aWhitespaces ) override; + + virtual void SAL_CALL compressedProcessingInstruction( const OUString& aTarget, const OUString& aData ) override; + + virtual void SAL_CALL compressedSetDocumentLocator( + sal_Int32 columnNumber, + sal_Int32 lineNumber, + const OUString& publicId, + const OUString& systemId ) override; + + /* css::lang::XServiceInfo */ + virtual OUString SAL_CALL getImplementationName( ) override; + + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/xmlsec/xmlsec_init.hxx b/xmlsecurity/inc/xmlsec/xmlsec_init.hxx new file mode 100644 index 0000000000..417acd288b --- /dev/null +++ b/xmlsecurity/inc/xmlsec/xmlsec_init.hxx @@ -0,0 +1,17 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include <xsecxmlsecdllapi.h> + +XSECXMLSEC_DLLPUBLIC void initXmlSec(); +XSECXMLSEC_DLLPUBLIC void deInitXmlSec(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/xmlsec/xmlstreamio.hxx b/xmlsecurity/inc/xmlsec/xmlstreamio.hxx new file mode 100644 index 0000000000..6e3d506a4d --- /dev/null +++ b/xmlsecurity/inc/xmlsec/xmlstreamio.hxx @@ -0,0 +1,39 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <xsecxmlsecdllapi.h> + +namespace com::sun::star::xml::crypto +{ +class XUriBinding; +} +namespace com::sun::star::uno +{ +template <typename> class Reference; +} + +int xmlEnableStreamInputCallbacks(); +void xmlDisableStreamInputCallbacks(); +int xmlRegisterStreamInputCallbacks( + css::uno::Reference<css::xml::crypto::XUriBinding> const& aUriBinding); +int xmlUnregisterStreamInputCallbacks(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/xmlsecuritydllapi.h b/xmlsecurity/inc/xmlsecuritydllapi.h new file mode 100644 index 0000000000..7f31e6f8f4 --- /dev/null +++ b/xmlsecurity/inc/xmlsecuritydllapi.h @@ -0,0 +1,20 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include <sal/types.h> + +#if defined(XMLSECURITY_DLLIMPLEMENTATION) +#define XMLSECURITY_DLLPUBLIC SAL_DLLPUBLIC_EXPORT +#else +#define XMLSECURITY_DLLPUBLIC SAL_DLLPUBLIC_IMPORT +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/xmlsignaturehelper.hxx b/xmlsecurity/inc/xmlsignaturehelper.hxx new file mode 100644 index 0000000000..d6e2b90eeb --- /dev/null +++ b/xmlsecurity/inc/xmlsignaturehelper.hxx @@ -0,0 +1,176 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <tools/link.hxx> +#include <rtl/ustring.hxx> +#include <rtl/ref.hxx> +#include <svl/sigstruct.hxx> +#include "xmlsecuritydllapi.h" +#include "xmlsignaturehelper.hxx" +#include "xsecctl.hxx" + +#include <com/sun/star/security/XCertificate.hpp> +#include <com/sun/star/xml/crypto/XSecurityEnvironment.hpp> + +class DateTime; +class UriBindingHelper; + +namespace com::sun::star { + namespace io { + class XOutputStream; + class XInputStream; + } + namespace embed { class XStorage; } +} + +namespace com::sun::star::graphic { class XGraphic; } +namespace com::sun::star::uno { class XComponentContext; } +namespace com::sun::star::xml::crypto { class XXMLSecurityContext; } +namespace com::sun::star::xml::sax { class XDocumentHandler; } +namespace com::sun::star::xml::sax { class XWriter; } + +/********************************************************** + XMLSignatureHelper + + Helper class for the XML Security framework + + Functions: + 1. help to create a security context; + 2. help to listen signature creation result; + 3. help to listen signature verify result; + 4. help to indicate which signature to verify. + + **********************************************************/ + +class XMLSECURITY_DLLPUBLIC XMLSignatureHelper +{ +private: + css::uno::Reference< css::uno::XComponentContext > mxCtx; + rtl::Reference<UriBindingHelper> mxUriBinding; + + rtl::Reference<XSecController> mpXSecController; + bool mbError; + bool mbODFPre1_2; + Link<LinkParamNone*,bool> maStartVerifySignatureHdl; + +private: + XMLSignatureHelper(const XMLSignatureHelper&) = delete; + +public: + XMLSignatureHelper(const css::uno::Reference< css::uno::XComponentContext >& mrCtx ); + ~XMLSignatureHelper(); + + void StartVerifySignatureElement(); + + // Set the storage which should be used by the default UriBinding + // Must be set before StartMission(). + //sODFVersion indicates the ODF version + void SetStorage( const css::uno::Reference < css::embed::XStorage >& rxStorage, std::u16string_view sODFVersion ); + + // Argument for the Link is a uno::Reference< xml::sax::XAttributeList >* + // Return 1 to verify, 0 to skip. + // Default handler will verify all. + void SetStartVerifySignatureHdl( const Link<LinkParamNone*,bool>& rLink ); + + // After signing/verifying, get information about signatures + SignatureInformation GetSignatureInformation( sal_Int32 nSecurityId ) const; + SignatureInformations GetSignatureInformations() const; + /// ImplVerifySignature calls this to figure out which X509Data is the + /// signing certificate and update the internal state with the result. + /// @return + /// A sequence with the signing certificate at the back on success. + /// An empty sequence on failure. + std::vector<css::uno::Reference<css::security::XCertificate>> + CheckAndUpdateSignatureInformation( + css::uno::Reference<css::xml::crypto::XSecurityEnvironment> const& xSecEnv, + SignatureInformation const& rInfo); + + // See XSecController for documentation + void StartMission(const css::uno::Reference<css::xml::crypto::XXMLSecurityContext>& xSecurityContext); + void EndMission(); + sal_Int32 GetNewSecurityId(); + /** 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 OUString& ouX509IssuerName, + const OUString& ouX509SerialNumber, const OUString& ouX509Cert, const OUString& ouX509CertDigest, + svl::crypto::SignatureMethodAlgorithm eAlgorithmID); + + void AddEncapsulatedX509Certificate(const OUString& ouEncapsulatedX509Certificate); + + void SetGpgCertificate(sal_Int32 nSecurityId, const OUString& ouGpgCertDigest, + const OUString& ouGpgCert, const OUString& ouGpgOwner); + + void SetDateTime( sal_Int32 nSecurityId, const DateTime& rDateTime ); + void SetDescription(sal_Int32 nSecurityId, const OUString& rDescription); + void SetSignatureLineId(sal_Int32 nSecurityId, const OUString& rSignatureLineId); + void + SetSignatureLineValidGraphic(sal_Int32 nSecurityId, + const css::uno::Reference<css::graphic::XGraphic>& xValidGraphic); + void SetSignatureLineInvalidGraphic( + sal_Int32 nSecurityId, const css::uno::Reference<css::graphic::XGraphic>& xInvalidGraphic); + + void AddForSigning( sal_Int32 securityId, const OUString& uri, bool bBinary, bool bXAdESCompliantIfODF ); + void CreateAndWriteSignature( const css::uno::Reference< css::xml::sax::XDocumentHandler >& xDocumentHandler, bool bXAdESCompliantIfODF ); + bool ReadAndVerifySignature( const css::uno::Reference< css::io::XInputStream >& xInputStream ); + + // MT: ??? I think only for adding/removing, not for new signatures... + // MM: Yes, but if you want to insert a new signature into an existing signature file, those function + // will be very useful, see Mission 3 in the new "multisigdemo" program :-) + css::uno::Reference< css::xml::sax::XWriter> CreateDocumentHandlerWithHeader( const css::uno::Reference< css::io::XOutputStream >& xOutputStream ); + static void CloseDocumentHandler( const css::uno::Reference< css::xml::sax::XDocumentHandler>& xDocumentHandler ); + static void ExportSignature( + const css::uno::Reference< css::xml::sax::XDocumentHandler >& xDocumentHandler, + const SignatureInformation& signatureInfo, + bool bXAdESCompliantIfODF ); + + /// Read and verify OOXML signatures. + bool ReadAndVerifySignatureStorage(const css::uno::Reference<css::embed::XStorage>& xStorage, bool bCacheLastSignature = true); + /// Read and verify a single OOXML signature. + bool ReadAndVerifySignatureStorageStream(const css::uno::Reference<css::io::XInputStream>& xInputStream); + /// Adds or removes an OOXML digital signature relation to _rels/.rels if there wasn't any before. + void EnsureSignaturesRelation(const css::uno::Reference<css::embed::XStorage>& xStorage, bool bAdd); + /// Given that xStorage is an OOXML _xmlsignatures storage, create origin.sigs and its relations. + void ExportSignatureRelations(const css::uno::Reference<css::embed::XStorage>& xStorage, int nSignatureCount); + /// Given that xSignatureStorage is an OOXML _xmlsignatures storage, create and write a new signature. + void CreateAndWriteOOXMLSignature(const css::uno::Reference<css::embed::XStorage>& xRootStorage, const css::uno::Reference<css::embed::XStorage>& xSignatureStorage, int nSignatureIndex); + /// Similar to CreateAndWriteOOXMLSignature(), but used to write the signature to the persistent storage, not the temporary one. + void ExportOOXMLSignature(const css::uno::Reference<css::embed::XStorage>& xRootStorage, const css::uno::Reference<css::embed::XStorage>& xSignatureStorage, const SignatureInformation& rInformation, int nSignatureIndex); + /// Given that xStorage is an OOXML root storage, advertise signatures in its [Content_Types].xml stream. + void ExportSignatureContentTypes(const css::uno::Reference<css::embed::XStorage>& xStorage, int nSignatureCount); +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/xsecctl.hxx b/xmlsecurity/inc/xsecctl.hxx new file mode 100644 index 0000000000..558301a796 --- /dev/null +++ b/xmlsecurity/inc/xsecctl.hxx @@ -0,0 +1,408 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <svl/sigstruct.hxx> + +#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 <rtl/ref.hxx> +#include <cppuhelper/implbase.hxx> + +#include <vector> + +#include "UriBindingHelper.hxx" + +namespace com::sun::star::embed { class XStorage; } +namespace com::sun::star::graphic { class XGraphic; } +namespace com::sun::star::io { class XInputStream; } +namespace com::sun::star::lang { class XInitialization; } +namespace com::sun::star::uno { class XComponentContext; } +namespace com::sun::star::xml::crypto { class XXMLSecurityContext; } +namespace com::sun::star::xml::crypto { class XXMLSignature; } +namespace com::sun::star::xml::crypto:: sax { class XReferenceResolvedListener; } +namespace com::sun::star::xml::sax { class XDocumentHandler; } + +inline constexpr OUString NS_XMLDSIG = u"http://www.w3.org/2000/09/xmldsig#"_ustr; +inline constexpr OUString NS_DC = u"http://purl.org/dc/elements/1.1/"_ustr; +inline constexpr OUString NS_XD = u"http://uri.etsi.org/01903/v1.3.2#"_ustr; +inline constexpr OUString NS_MDSSI = u"http://schemas.openxmlformats.org/package/2006/digital-signature"_ustr; +inline constexpr OUString NS_LOEXT = u"urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0"_ustr; + +inline constexpr OUString ALGO_C14N = u"http://www.w3.org/TR/2001/REC-xml-c14n-20010315"_ustr; +inline constexpr OUString ALGO_RSASHA1 = u"http://www.w3.org/2000/09/xmldsig#rsa-sha1"_ustr; +inline constexpr OUString ALGO_RSASHA256 = u"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"_ustr; +inline constexpr OUString ALGO_RSASHA512 = u"http://www.w3.org/2001/04/xmldsig-more#rsa-sha512"_ustr; +inline constexpr OUString ALGO_ECDSASHA1 = u"http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1"_ustr; +inline constexpr OUString ALGO_ECDSASHA256 = u"http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256"_ustr; +inline constexpr OUString ALGO_ECDSASHA512 = u"http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512"_ustr; +inline constexpr OUString ALGO_XMLDSIGSHA1 = u"http://www.w3.org/2000/09/xmldsig#sha1"_ustr; +inline constexpr OUString ALGO_XMLDSIGSHA256 = u"http://www.w3.org/2001/04/xmlenc#sha256"_ustr; +inline constexpr OUString ALGO_XMLDSIGSHA512 = u"http://www.w3.org/2001/04/xmlenc#sha512"_ustr; +inline constexpr OUString ALGO_RELATIONSHIP = u"http://schemas.openxmlformats.org/package/2006/RelationshipTransform"_ustr; + +class XMLDocumentWrapper_XmlSecImpl; +class SAXEventKeeperImpl; +class XMLSignatureHelper; +namespace svl::crypto { enum class SignatureMethodAlgorithm; } + +class InternalSignatureInformation +{ +public: + SignatureInformation signatureInfor; + + css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > xReferenceResolvedListener; + + ::std::vector< sal_Int32 > vKeeperIds; + + InternalSignatureInformation( + sal_Int32 nId, + css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > const & xListener) + :signatureInfor(nId) + { + xReferenceResolvedListener = xListener; + } + + void addReference( SignatureReferenceType type, sal_Int32 digestID, const OUString& uri, sal_Int32 keeperId, const OUString& rType ) + { + signatureInfor.vSignatureReferenceInfors.push_back( + SignatureReferenceInformation(type, digestID, uri, rType)); + vKeeperIds.push_back( keeperId ); + } +}; + +class XSecController final : public cppu::WeakImplHelper +< + css::xml::crypto::sax::XSAXEventKeeperStatusChangeListener, + css::xml::crypto::sax::XSignatureCreationResultListener, + css::xml::crypto::sax::XSignatureVerifyResultListener +> +/****** XSecController.hxx/CLASS XSecController ******************************* + * + * NAME + * XSecController -- the xml security framework controller + * + * FUNCTION + * Controls the whole xml security framework to create signatures or to + * verify signatures. + * + ******************************************************************************/ +{ + friend class XSecParser; + friend class OOXMLSecParser; + +private: + css::uno::Reference< css::uno::XComponentContext> mxCtx; + + /* + * used to buffer SAX events + */ + rtl::Reference<XMLDocumentWrapper_XmlSecImpl> m_xXMLDocumentWrapper; + + /* + * the SAX events keeper + */ + rtl::Reference<SAXEventKeeperImpl> m_xSAXEventKeeper; + + /* + * the bridge component which creates/verifies signature + */ + css::uno::Reference< css::xml::crypto::XXMLSignature > m_xXMLSignature; + + /* + * the Security Context + */ + css::uno::Reference< css::xml::crypto::XXMLSecurityContext > m_xSecurityContext; + + /* + * 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 + */ + std::vector< InternalSignatureInformation > 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. + */ + css::uno::Reference< css::uno::XInterface > m_xPreviousNodeOnSAXChain; + /* + * whether the previous node can provide an XInitialize interface, + * use this variable in order to typecast the XInterface to the + * correct interface type. + */ + bool m_bIsPreviousNodeInitializable; + + /* + * 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. + */ + + /* + * status of security related components + */ + enum class InitializationState { UNINITIALIZED, INITIALIZED, FAILTOINITIALIZED } m_eStatusOfSecurityComponents; + + /* + * 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; + + /* + * the XSecParser which is used to parse the signature stream + */ + css::uno::Reference<css::xml::sax::XDocumentHandler> m_xSecParser; + + /* + * 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; + + /* + * An xUriBinding is provided to map Uris to XInputStream interfaces. + */ + rtl::Reference<UriBindingHelper> m_xUriBinding; + +private: + + /* + * Common methods + */ + void createXSecComponent( ); + int findSignatureInfor( sal_Int32 nSecurityId ) const; + bool chainOn(); + void chainOff(); + void checkChainingStatus(); + void initializeSAXChain(); + + css::uno::Reference< css::io::XInputStream > getObjectInputStream( const OUString& objectURL ); + + //sal_Int32 getFastPropertyIndex(sal_Int32 nHandle) const; + + /* + * For signature generation + */ + static OUString createId(); + css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > prepareSignatureToWrite( + InternalSignatureInformation& signatureInfo, + sal_Int32 nStorageFormat, + bool bXAdESCompliantIfODF ); + + /* + * For signature verification + */ + void addSignature(); + /// Sets algorithm from <SignatureMethod Algorithm="...">. + void setSignatureMethod(svl::crypto::SignatureMethodAlgorithm eAlgorithmID); + void switchGpgSignature(); + bool haveReferenceForId(std::u16string_view rId) const; + void addReference( + const OUString& ouUri, + sal_Int32 nDigestID, + const OUString& ouType ); + void addStreamReference( + const OUString& ouUri, + bool isBinary, + sal_Int32 nDigestID ); + void setReferenceCount() const; + + void setX509Data( + std::vector<std::pair<OUString, OUString>> & rX509IssuerSerials, + std::vector<OUString> const& rX509Certificates); + void setX509CertDigest( + OUString const& rCertDigest, sal_Int32 const nReferenceDigestID, + std::u16string_view const& rX509IssuerName, std::u16string_view const& rX509SerialNumber); + + void setSignatureValue( OUString const & ouSignatureValue ); + void setDigestValue( sal_Int32 nDigestID, OUString const & ouDigestValue ); + void setGpgKeyID( OUString const & ouKeyID ); + void setGpgCertificate( OUString const & ouGpgCert ); + void setGpgOwner( OUString const & ouGpgOwner ); + + void setDate(OUString const& rId, OUString const& ouDate); + void setDescription(OUString const& rId, OUString const& rDescription); + void setValidSignatureImage(std::u16string_view rValidSigImg); + void setInvalidSignatureImage(std::u16string_view rInvalidSigImg); + void setSignatureLineId(const OUString& rSignatureLineId); + +public: + void setSignatureBytes(const css::uno::Sequence<sal_Int8>& rBytes); + +private: + void setId( OUString const & ouId ); + + css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > prepareSignatureToRead( + sal_Int32 nSecurityId ); + +public: + explicit XSecController(css::uno::Reference<css::uno::XComponentContext> xCtx); + virtual ~XSecController() override; + + sal_Int32 getNewSecurityId( ); + + void startMission(const rtl::Reference<UriBindingHelper>& xUriBinding, const css::uno::Reference<css::xml::crypto::XXMLSecurityContext>& xSecurityContext); + + void setSAXChainConnector(const css::uno::Reference< css::lang::XInitialization >& xInitialization); + + void clearSAXChainConnector(); + void endMission(); + + SignatureInformation getSignatureInformation( sal_Int32 nSecurityId ) const; + SignatureInformations getSignatureInformations() const; + /// only verify can figure out which X509Data is the signing certificate + void UpdateSignatureInformation(sal_Int32 nSecurityId, + std::vector<SignatureInformation::X509Data> && rDatas); + + static void exportSignature( + const css::uno::Reference< css::xml::sax::XDocumentHandler >& xDocumentHandler, + const SignatureInformation& signatureInfo, + bool bXAdESCompliantIfODF ); + + + /* + * For signature generation + */ + void signAStream( sal_Int32 securityId, const OUString& uri, bool isBinary, bool bXAdESCompliantIfODF); + + + /** 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 OUString& ouX509IssuerName, + const OUString& ouX509SerialNumber, + const OUString& ouX509Cert, + const OUString& ouX509CertDigest, + svl::crypto::SignatureMethodAlgorithm eAlgorithmID); + + void addEncapsulatedX509Certificate(const OUString& rEncapsulatedX509Certificate); + + void setGpgCertificate( + sal_Int32 nSecurityId, + const OUString& ouCertDigest, + const OUString& ouCert, + const OUString& ouOwner); + + void setDate( + sal_Int32 nSecurityId, + const css::util::DateTime& rDateTime ); + void setDescription(sal_Int32 nSecurityId, const OUString& rDescription); + void setSignatureLineId(sal_Int32 nSecurityId, const OUString& rSignatureLineId); + void + setSignatureLineValidGraphic(sal_Int32 nSecurityId, + const css::uno::Reference<css::graphic::XGraphic>& xValidGraphic); + void setSignatureLineInvalidGraphic( + sal_Int32 nSecurityId, const css::uno::Reference<css::graphic::XGraphic>& xInvalidGraphic); + + bool WriteSignature( + const css::uno::Reference< css::xml::sax::XDocumentHandler >& xDocumentHandler, + bool bXAdESCompliantIfODF); + + /* + * For signature verification + */ + void collectToVerify( std::u16string_view referenceId ); + void addSignature( sal_Int32 nSignatureId ); + css::uno::Reference< css::xml::sax::XDocumentHandler > const & createSignatureReader(XMLSignatureHelper& rXMLSignatureHelper, sal_Int32 nType = 0); + void releaseSignatureReader(); + +public: + /* Interface methods */ + + /* + * XSAXEventKeeperStatusChangeListener + */ + virtual void SAL_CALL blockingStatusChanged( sal_Bool isBlocking ) override; + virtual void SAL_CALL collectionStatusChanged( + sal_Bool isInsideCollectedElement ) override; + virtual void SAL_CALL bufferStatusChanged( sal_Bool isBufferEmpty ) override; + + /* + * XSignatureCreationResultListener + */ + virtual void SAL_CALL signatureCreated( sal_Int32 securityId, css::xml::crypto::SecurityOperationStatus nResult ) override; + + /* + * XSignatureVerifyResultListener + */ + virtual void SAL_CALL signatureVerified( sal_Int32 securityId, css::xml::crypto::SecurityOperationStatus nResult ) override; + + /// Writes XML elements inside a single OOXML signature's <Signature> element. + bool WriteOOXMLSignature(const css::uno::Reference<css::embed::XStorage>& xRootStorage, const css::uno::Reference<css::xml::sax::XDocumentHandler>& xDocumentHandler); + /// Exports an OOXML signature, called by WriteOOXMLSignature(). + void exportOOXMLSignature(const css::uno::Reference<css::embed::XStorage>& xRootStorage, const css::uno::Reference<css::xml::sax::XDocumentHandler>& xDocumentHandler, const SignatureInformation& rInformation); +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/xsecxmlsecdllapi.h b/xmlsecurity/inc/xsecxmlsecdllapi.h new file mode 100644 index 0000000000..36f8ad52ac --- /dev/null +++ b/xmlsecurity/inc/xsecxmlsecdllapi.h @@ -0,0 +1,20 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include <sal/types.h> + +#if defined(XSECXMLSEC_DLLIMPLEMENTATION) +#define XSECXMLSEC_DLLPUBLIC SAL_DLLPUBLIC_EXPORT +#else +#define XSECXMLSEC_DLLPUBLIC SAL_DLLPUBLIC_IMPORT +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/qa/certext/SanCertExt.cxx b/xmlsecurity/qa/certext/SanCertExt.cxx new file mode 100644 index 0000000000..c117f4c001 --- /dev/null +++ b/xmlsecurity/qa/certext/SanCertExt.cxx @@ -0,0 +1,260 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <test/officeconnection.hxx> + +#include <com/sun/star/security/XSanExtension.hpp> +#include <com/sun/star/security/ExtAltNameType.hpp> +#include <com/sun/star/xml/crypto/XSecurityEnvironment.hpp> +#include <com/sun/star/xml/crypto/SEInitializer.hpp> +#include <com/sun/star/xml/crypto/XXMLSecurityContext.hpp> +#include <com/sun/star/security/XCertificate.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/beans/NamedValue.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/uno/Reference.hxx> + +#include <cppuhelper/bootstrap.hxx> +#include "cppunit/TestAssert.h" +#include "cppunit/TestFixture.h" +#include "cppunit/extensions/HelperMacros.h" +#include "cppunit/plugin/TestPlugIn.h" +#include <sal/types.h> +#include <rtl/ustring.hxx> + +#include <neon/ne_ssl.h> + +using namespace com::sun::star; + +#define OID_SUBJECT_ALTERNATIVE_NAME "2.5.29.17" + + +namespace { + + class Test: public CppUnit::TestFixture { + + private: + static uno::Sequence< security::CertAltNameEntry > altNames; + static bool runOnce; + + uno::Reference< xml::crypto::XSecurityEnvironment > initUno(); + void init(); + OString getB64CertFromFile(const char filename[]); + test::OfficeConnection connection_; + + public: + + Test(); + + ~Test(); + + void test_Others(); + + void test_RFC822(); + + void test_DNS(); + + void test_Directory(); + + void test_URI(); + + void test_IP(); + + void test_RID(); + + void test_EDI(); + + void test_X400(); + + CPPUNIT_TEST_SUITE(Test); + CPPUNIT_TEST(test_Others); + CPPUNIT_TEST(test_RFC822); + CPPUNIT_TEST(test_DNS); + CPPUNIT_TEST(test_Directory); + CPPUNIT_TEST(test_URI); + CPPUNIT_TEST(test_IP); + CPPUNIT_TEST(test_RID); + CPPUNIT_TEST(test_EDI); + CPPUNIT_TEST(test_X400); + CPPUNIT_TEST_SUITE_END(); + }; + + uno::Sequence< security::CertAltNameEntry > Test::altNames; + bool Test::runOnce = false; + + CPPUNIT_TEST_SUITE_REGISTRATION(Test); + + Test::Test() + { + if (runOnce) + return; + runOnce = true; + connection_.setUp(); + init(); + } + + Test::~Test() + { + if (runOnce) + { + connection_.tearDown(); + runOnce = false; + } + } + + + uno::Reference< xml::crypto::XSecurityEnvironment > Test::initUno() + { + uno::Reference< uno::XComponentContext > context(connection_.getComponentContext(), uno::UNO_QUERY_THROW); + uno::Reference< lang::XMultiServiceFactory > factory(context->getServiceManager(), uno::UNO_QUERY_THROW); + uno::Reference< xml::crypto::XSEInitializer > xSEInitializer = xml::crypto::SEInitializer::create(context); + uno::Reference< xml::crypto::XXMLSecurityContext > xSecurityContext( + xSEInitializer->createSecurityContext(OUString())); + return xSecurityContext->getSecurityEnvironment(); + } + + + void Test::init() + { + uno::Reference< xml::crypto::XSecurityEnvironment > xSecurityEnv = initUno(); + OString b64Cert(getB64CertFromFile("User_35_Root_11.crt")); + uno::Reference< security::XCertificate > xCert = xSecurityEnv->createCertificateFromAscii( + OStringToOUString( b64Cert, RTL_TEXTENCODING_ASCII_US ) ); + uno::Sequence< uno::Reference< security::XCertificateExtension > > extensions = xCert->getExtensions(); + for (sal_Int32 i = 0 ; i < extensions.getLength(); i++) + { + uno::Reference< security::XCertificateExtension >element = extensions[i]; + OString aId ( (const char *)element->getExtensionId().getArray(), element->getExtensionId().getLength()); + if (aId.equals(OID_SUBJECT_ALTERNATIVE_NAME)) + { + uno::Reference< security::XSanExtension > sanExtension ( element, uno::UNO_QUERY ); + altNames = sanExtension->getAlternativeNames(); + break; + } + } + } + + OString Test::getB64CertFromFile(const char filename[]) + { + ne_ssl_certificate* cert = ne_ssl_cert_read(filename); + char* certExportB64 = ne_ssl_cert_export(cert); + OString certB64( certExportB64 ); + return certB64; + } + + + void Test::test_Others() { + CPPUNIT_ASSERT_ASSERTION_PASS( CPPUNIT_ASSERT( altNames.getLength() > 0 ) ); + for(int n = 1; n < altNames.getLength(); n++) + { + if (altNames[n].Type == security::ExtAltNameType_OTHER_NAME) + { + css::beans::NamedValue otherNameProp; + if (altNames[n].Value >>= otherNameProp) + { + CPPUNIT_ASSERT_EQUAL( OUString("1.2.3.4"), otherNameProp.Name); + uno::Sequence< sal_Int8 > ipAddress; + otherNameProp.Value >>= ipAddress; + CPPUNIT_ASSERT_ASSERTION_PASS( CPPUNIT_ASSERT( ipAddress.getLength() > 0 ) ); + } + } + } + } + + void Test::test_RFC822() { + CPPUNIT_ASSERT_ASSERTION_PASS( CPPUNIT_ASSERT( altNames.getLength() > 0 ) ); + for(int n = 1; n < altNames.getLength(); n++) + { + if (altNames[n].Type == security::ExtAltNameType_RFC822_NAME) + { + OUString value; + altNames[n].Value >>= value; + CPPUNIT_ASSERT_EQUAL( OUString("my@other.address"), value); + } + } + } + + void Test::test_DNS() { + CPPUNIT_ASSERT_ASSERTION_PASS( CPPUNIT_ASSERT( altNames.getLength() > 0 ) ); + for(int n = 1; n < altNames.getLength(); n++) + { + if (altNames[n].Type == security::ExtAltNameType_DNS_NAME) + { + OUString value; + altNames[n].Value >>= value; + CPPUNIT_ASSERT_EQUAL( OUString("alt.openoffice.org"), value); + } + } + } + + void Test::test_Directory() { + // Not implemented + } + + void Test::test_URI() { + CPPUNIT_ASSERT_ASSERTION_PASS( CPPUNIT_ASSERT( altNames.getLength() > 0 ) ); + for(int n = 1; n < altNames.getLength(); n++) + { + if (altNames[n].Type == security::ExtAltNameType_URL) + { + OUString value; + altNames[n].Value >>= value; + CPPUNIT_ASSERT_EQUAL( OUString("http://my.url.here/"), value); + } + } + } + + void Test::test_IP() { + CPPUNIT_ASSERT_ASSERTION_PASS( CPPUNIT_ASSERT( altNames.getLength() > 0 ) ); + for(int n = 1; n < altNames.getLength(); n++) + { + if (altNames[n].Type == security::ExtAltNameType_IP_ADDRESS) + { + uno::Sequence< sal_Int8 > ipAddress; + altNames[n].Value >>= ipAddress; + CPPUNIT_ASSERT_ASSERTION_PASS( CPPUNIT_ASSERT( ipAddress.getLength() > 0 ) ); + } + } + + } + + void Test::test_RID() { + CPPUNIT_ASSERT_ASSERTION_PASS( CPPUNIT_ASSERT( altNames.getLength() > 0 ) ); + for(int n = 1; n < altNames.getLength(); n++) + { + if (altNames[n].Type == security::ExtAltNameType_REGISTERED_ID) + { + OUString value; + altNames[n].Value >>= value; + CPPUNIT_ASSERT( OUString("1.2.3.4").equals(value)); + } + } + } + + void Test::test_EDI() { + // Not implemented + } + + void Test::test_X400() { + // Not implemented + } +} +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/qa/certext/User_35_Root_11.crt b/xmlsecurity/qa/certext/User_35_Root_11.crt new file mode 100644 index 0000000000..0092d16c7a --- /dev/null +++ b/xmlsecurity/qa/certext/User_35_Root_11.crt @@ -0,0 +1,64 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4130 (0x1022) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Nov 8 10:51:39 2010 GMT + Not After : Nov 8 10:51:39 2011 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 35 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:9b:36:00:64:f3:ce:93:97:62:19:fa:78:d9:6f: + 92:6a:b9:d2:9a:4e:06:2c:02:52:cd:93:50:84:28: + 19:42:a2:4a:34:e2:cd:e6:b0:39:7a:c8:4d:84:bc: + 71:51:ed:5d:6c:7e:f9:cc:01:5a:4b:73:50:a9:3b: + 5d:ad:cc:89:f7:dc:e0:dd:0a:ff:48:01:a9:34:19: + c0:6a:ee:4b:20:f4:cf:3c:94:c1:ae:88:0f:c9:42: + 1a:a6:47:31:fe:37:04:00:bb:ec:07:5f:cb:ee:70: + c4:c7:7c:6f:ee:03:19:76:de:0b:df:d0:48:91:67: + 55:9b:90:91:f4:ce:56:04:d5 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 91:47:AC:29:95:5D:EF:72:14:8F:82:45:07:E2:94:49:75:C6:7D:73 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DNS:alt.openoffice.org, IP Address:192.168.7.1, IP Address:13:0:0:0:0:0:0:17, email:my@other.address, Registered ID:1.2.3.4, othername:<unsupported>, DirName:/C=DE/O=OpenOffice.org/OU=Development/CN=User 32 Root 11, URI:http://my.url.here/ + Signature Algorithm: sha1WithRSAEncryption + 6e:80:e6:1e:86:3d:d2:65:a6:17:fa:80:2d:2e:dc:85:32:05: + a1:69:82:e1:79:d1:dc:de:69:cd:9e:f0:cc:90:75:a9:45:ee: + 73:46:fe:29:69:c0:99:bb:fc:3a:db:c0:5f:69:c6:b7:ea:9a: + 63:b2:8e:29:2c:a5:5a:88:88:94:75:4b:ab:0a:72:f6:3a:aa: + 5d:6b:3a:5c:b6:9b:57:f5:c1:51:af:df:3c:a6:8a:a3:da:70: + 66:61:49:12:06:78:98:9f:bc:78:3c:43:6d:08:94:aa:32:b6: + f3:cc:af:0d:29:fe:96:47:7d:fe:4a:61:48:90:11:0b:bd:0f: + a0:fd +-----BEGIN CERTIFICATE----- +MIIDajCCAtOgAwIBAgICECIwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDExMDgxMDUx +MzlaFw0xMTExMDgxMDUxMzlaMGAxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxEDAOBgNVBAMTB1VzZXIgMzUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB +AJs2AGTzzpOXYhn6eNlvkmq50ppOBiwCUs2TUIQoGUKiSjTizeawOXrITYS8cVHt +XWx++cwBWktzUKk7Xa3Miffc4N0K/0gBqTQZwGruSyD0zzyUwa6ID8lCGqZHMf43 +BAC77Adfy+5wxMd8b+4DGXbeC9/QSJFnVZuQkfTOVgTVAgMBAAGjggExMIIBLTAL +BgNVHQ8EBAMCBeAwHQYDVR0OBBYEFJFHrCmVXe9yFI+CRQfilEl1xn1zMB8GA1Ud +IwQYMBaAFOhqu8KQ6mxwIj729kgbA+a+t6ZVMIHdBgNVHREEgdUwgdKCEmFsdC5v +cGVub2ZmaWNlLm9yZ4cEwKgHAYcQABMAAAAAAAAAAAAAAAAAF4EQbXlAb3RoZXIu +YWRkcmVzc4gDKgMEoB4GAyoDBKAXDBVzb21lIG90aGVyIGlkZW50aWZpZXKkWDBW +MQswCQYDVQQGEwJERTEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsT +C0RldmVsb3BtZW50MRgwFgYDVQQDEw9Vc2VyIDMyIFJvb3QgMTGGE2h0dHA6Ly9t +eS51cmwuaGVyZS8wDQYJKoZIhvcNAQEFBQADgYEAboDmHoY90mWmF/qALS7chTIF +oWmC4XnR3N5pzZ7wzJB1qUXuc0b+KWnAmbv8OtvAX2nGt+qaY7KOKSylWoiIlHVL +qwpy9jqqXWs6XLabV/XBUa/fPKaKo9pwZmFJEgZ4mJ+8eDxDbQiUqjK288yvDSn+ +lkd9/kphSJARC70PoP0= +-----END CERTIFICATE----- diff --git a/xmlsecurity/qa/create-certs/create-certs.sh b/xmlsecurity/qa/create-certs/create-certs.sh new file mode 100755 index 0000000000..5a4c244c6b --- /dev/null +++ b/xmlsecurity/qa/create-certs/create-certs.sh @@ -0,0 +1,187 @@ +#!/usr/bin/env bash +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# The purpose of this script is to create certificates to be able to test ODF signing code. +# +# What it does: +# +# 1) Create a test root CA. +# +# 2) Create an intermediate CA, as signing certificates with a root CA is +# considered unsafe. +# +# 3) Create two client certificates that can be used to sign ODF documents in +# LibreOffice. +# +# References: +# +# <https://jamielinux.com/docs/openssl-certificate-authority/> for most of the +# commands. +# +# <https://www.sslshopper.com/article-most-common-openssl-commands.html> for +# the PKCS#12 export of self-signed certificates +# + +set -e + +root="$PWD" +algo="RSA" + +if [ -n "$1" ]; then + algo="$1" +fi + +if [ -d "$root/ca" ]; then + echo "'ca' directory already exists in $root, please remove it before running this script." + exit 1 +fi + +if [ -z "$SSLPASS" ]; then + # Unless specified otherwise, we'll use this as a password everywhere. + export SSLPASS="xmlsecurity" +fi + +# 1) Create the root pair. + +mkdir "$root/ca" + +cd "$root/ca" +mkdir certs crl newcerts private +chmod 700 private +touch index.txt +echo 1000 > serial + +sed "s|@ROOT@|$root|g" "$root/templates/root.cnf" > "$root/ca/openssl.cnf" + +# Create the root key. +cd "$root/ca" +openssl genrsa -aes256 -out private/ca.key.pem -passout env:SSLPASS 4096 +chmod 400 private/ca.key.pem + +# Create the root certificate. +cd "$root/ca" +openssl req -config openssl.cnf \ + -key private/ca.key.pem \ + -new -x509 -days 36500 -sha256 -extensions v3_ca \ + -out certs/ca.cert.pem \ + -passin env:SSLPASS \ + -subj "/C=UK/ST=England/O=Xmlsecurity ${algo} Test/CN=Xmlsecurity ${algo} Test Root CA" +chmod 444 certs/ca.cert.pem + +# 2) Create the intermediate pair. + +# Prepare the directory. +mkdir "$root/ca/intermediate" +cd "$root/ca/intermediate" +mkdir certs crl csr newcerts private +chmod 700 private +touch index.txt +echo 1000 > serial + +# crlnumber is used to keep track of certificate revocation lists. +echo 1000 > "$root/ca/intermediate/crlnumber" + +# Copy the intermediate CA configuration file. +sed "s|@ROOT@|$root|g" "$root/templates/intermediate.cnf" > "$root/ca/intermediate/openssl.cnf" + +# Create the intermediate key. + +cd "$root/ca" +openssl genrsa -aes256 \ + -out intermediate/private/intermediate.key.pem \ + -passout env:SSLPASS 4096 +chmod 400 intermediate/private/intermediate.key.pem + +# Create the intermediate certificate. + +# Intermediate key. +cd "$root/ca" +openssl req -config intermediate/openssl.cnf -new -sha256 \ + -key intermediate/private/intermediate.key.pem \ + -out intermediate/csr/intermediate.csr.pem \ + -passin env:SSLPASS \ + -subj "/C=UK/ST=England/O=Xmlsecurity ${algo} Test/CN=Xmlsecurity Intermediate Root CA" + +# The certificate itself. +openssl ca -batch -config openssl.cnf -extensions v3_intermediate_ca \ + -days 36500 -notext -md sha256 \ + -in intermediate/csr/intermediate.csr.pem \ + -passin env:SSLPASS \ + -out intermediate/certs/intermediate.cert.pem +chmod 444 intermediate/certs/intermediate.cert.pem + +# Create the certificate chain file. +cat intermediate/certs/intermediate.cert.pem \ + certs/ca.cert.pem > intermediate/certs/ca-chain.cert.pem +chmod 444 intermediate/certs/ca-chain.cert.pem + +# 3) Create the real certificate. + +for i in Alice Bob +do + # Create a key. + cd "$root/ca" + if [ "$algo" == "ECDSA" ]; then + openssl ecparam -name secp256r1 -genkey \ + -out intermediate/private/example-xmlsecurity-${i}.key.pem + else + openssl genrsa -aes256 \ + -out intermediate/private/example-xmlsecurity-${i}.key.pem \ + -passout env:SSLPASS 2048 + fi + chmod 400 intermediate/private/example-xmlsecurity-${i}.key.pem + + # Create a certificate signing request (CSR). + + cd "$root/ca" + openssl req -config intermediate/openssl.cnf \ + -key intermediate/private/example-xmlsecurity-${i}.key.pem \ + -new -sha256 -out intermediate/csr/example-xmlsecurity-${i}.csr.pem \ + -passin env:SSLPASS \ + -subj "/C=UK/ST=England/O=Xmlsecurity ${algo} Test/CN=Xmlsecurity ${algo} Test example ${i}" + + # To create a certificate, use the intermediate CA to sign the CSR. + cd "$root/ca" + # usr_cert: the cert will be used for signing. + openssl ca -batch -config intermediate/openssl.cnf \ + -extensions usr_cert -days 36500 -notext -md sha256 \ + -in intermediate/csr/example-xmlsecurity-${i}.csr.pem \ + -passin env:SSLPASS \ + -out intermediate/certs/example-xmlsecurity-${i}.cert.pem + chmod 444 intermediate/certs/example-xmlsecurity-${i}.cert.pem + + # Export it in PKCS#12 format. + if [ "$algo" == "ECDSA" ]; then + openssl pkcs12 -export \ + -out ./intermediate/private/example-xmlsecurity-${i}.cert.p12 \ + -passout env:SSLPASS \ + -inkey intermediate/private/example-xmlsecurity-${i}.key.pem \ + -passin env:SSLPASS \ + -in intermediate/certs/example-xmlsecurity-${i}.cert.pem \ + -certfile intermediate/certs/ca-chain.cert.pem + else + openssl pkcs12 -export \ + -out ./intermediate/private/example-xmlsecurity-${i}.cert.p12 \ + -passout env:SSLPASS \ + -inkey intermediate/private/example-xmlsecurity-${i}.key.pem \ + -passin env:SSLPASS \ + -in intermediate/certs/example-xmlsecurity-${i}.cert.pem \ + -certfile intermediate/certs/ca-chain.cert.pem \ + -CSP "Microsoft Enhanced RSA and AES Cryptographic Provider" + fi +done + +echo +echo "Authority certificate is at: <$root/ca/intermediate/certs/ca-chain.cert.pem>." +echo "To be able to import it in Windows, rename the '.pem' extension to '.cer'." +for i in Alice Bob +do + echo "Signing certificate is at <$root/ca/intermediate/private/example-xmlsecurity-${i}.cert.p12>." +done + +# vim:set shiftwidth=4 expandtab: diff --git a/xmlsecurity/qa/create-certs/create-dump-certs.sh b/xmlsecurity/qa/create-certs/create-dump-certs.sh new file mode 100644 index 0000000000..95e8de9c6f --- /dev/null +++ b/xmlsecurity/qa/create-certs/create-dump-certs.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# This script generates 100 certificates (modifiable) for cases of testing UI latency for instance. +# +# Basically, it creates certificates with sender same as receiver following User [number] pattern. +# + +for ((i=1; i<=100; i++)) +do + gpg --batch --gen-key <<EOF + %no-protection + Key-Type: RSA + Key-Length: 2048 + Subkey-Type: RSA + Subkey-Length: 2048 + Name-Real: User $i + Name-Email: user$i@example.com + Expire-Date: 1y + %commit +EOF + + gpg --armor --export user$i@example.com > user$i.asc + + echo "Generated certificate for User $i" +done diff --git a/xmlsecurity/qa/create-certs/templates/intermediate.cnf b/xmlsecurity/qa/create-certs/templates/intermediate.cnf new file mode 100644 index 0000000000..c6fd12d0a6 --- /dev/null +++ b/xmlsecurity/qa/create-certs/templates/intermediate.cnf @@ -0,0 +1,132 @@ +# OpenSSL intermediate CA configuration file. +# Copy to `$root/ca/intermediate/openssl.cnf`. + +[ ca ] +# `man ca` +default_ca = CA_default + +[ CA_default ] +# Directory and file locations. +dir = @ROOT@/ca/intermediate +certs = $dir/certs +crl_dir = $dir/crl +new_certs_dir = $dir/newcerts +database = $dir/index.txt +serial = $dir/serial +RANDFILE = $dir/private/.rand + +# The root key and root certificate. +private_key = $dir/private/intermediate.key.pem +certificate = $dir/certs/intermediate.cert.pem + +# For certificate revocation lists. +crlnumber = $dir/crlnumber +crl = $dir/crl/intermediate.crl.pem +crl_extensions = crl_ext +default_crl_days = 30 + +# SHA-1 is deprecated, so use SHA-2 instead. +default_md = sha256 + +name_opt = ca_default +cert_opt = ca_default +default_days = 375 +preserve = no +policy = policy_loose + +[ policy_strict ] +# The root CA should only sign intermediate certificates that match. +# See the POLICY FORMAT section of `man ca`. +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +[ policy_loose ] +# Allow the intermediate CA to sign a more diverse range of certificates. +# See the POLICY FORMAT section of the `ca` man page. +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +[ req ] +# Options for the `req` tool (`man req`). +default_bits = 2048 +distinguished_name = req_distinguished_name +string_mask = utf8only + +# SHA-1 is deprecated, so use SHA-2 instead. +default_md = sha256 + +# Extension to add when the -x509 option is used. +x509_extensions = v3_ca + +[ req_distinguished_name ] +# See <https://en.wikipedia.org/wiki/Certificate_signing_request>. +countryName = Country Name (2 letter code) +stateOrProvinceName = State or Province Name +localityName = Locality Name +0.organizationName = Organization Name +organizationalUnitName = Organizational Unit Name +commonName = Common Name +emailAddress = Email Address + +# Optionally, specify some defaults. +countryName_default = GB +stateOrProvinceName_default = England +localityName_default = +0.organizationName_default = Xmlsecurity Test +organizationalUnitName_default = +emailAddress_default = + +[ v3_ca ] +# Extensions for a typical CA (`man x509v3_config`). +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer +basicConstraints = critical, CA:true +keyUsage = critical, digitalSignature, cRLSign, keyCertSign + +[ v3_intermediate_ca ] +# Extensions for a typical intermediate CA (`man x509v3_config`). +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer +basicConstraints = critical, CA:true, pathlen:0 +keyUsage = critical, digitalSignature, cRLSign, keyCertSign + +[ usr_cert ] +# Extensions for client certificates (`man x509v3_config`). +basicConstraints = CA:FALSE +nsCertType = client, email +nsComment = "OpenSSL Generated Client Certificate" +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer +keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment +extendedKeyUsage = clientAuth, emailProtection + +[ server_cert ] +# Extensions for server certificates (`man x509v3_config`). +basicConstraints = CA:FALSE +nsCertType = server +nsComment = "OpenSSL Generated Server Certificate" +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer:always +keyUsage = critical, digitalSignature, keyEncipherment +extendedKeyUsage = serverAuth + +[ crl_ext ] +# Extension for CRLs (`man x509v3_config`). +authorityKeyIdentifier=keyid:always + +[ ocsp ] +# Extension for OCSP signing certificates (`man ocsp`). +basicConstraints = CA:FALSE +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer +keyUsage = critical, digitalSignature +extendedKeyUsage = critical, OCSPSigning diff --git a/xmlsecurity/qa/create-certs/templates/root.cnf b/xmlsecurity/qa/create-certs/templates/root.cnf new file mode 100644 index 0000000000..1298d74d3a --- /dev/null +++ b/xmlsecurity/qa/create-certs/templates/root.cnf @@ -0,0 +1,132 @@ +# OpenSSL root CA configuration file. +# Copy to `$root/ca/openssl.cnf`. + +[ ca ] +# `man ca` +default_ca = CA_default + +[ CA_default ] +# Directory and file locations. +dir = @ROOT@/ca +certs = $dir/certs +crl_dir = $dir/crl +new_certs_dir = $dir/newcerts +database = $dir/index.txt +serial = $dir/serial +RANDFILE = $dir/private/.rand + +# The root key and root certificate. +private_key = $dir/private/ca.key.pem +certificate = $dir/certs/ca.cert.pem + +# For certificate revocation lists. +crlnumber = $dir/crlnumber +crl = $dir/crl/ca.crl.pem +crl_extensions = crl_ext +default_crl_days = 30 + +# SHA-1 is deprecated, so use SHA-2 instead. +default_md = sha256 + +name_opt = ca_default +cert_opt = ca_default +default_days = 375 +preserve = no +policy = policy_strict + +[ policy_strict ] +# The root CA should only sign intermediate certificates that match. +# See the POLICY FORMAT section of `man ca`. +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +[ policy_loose ] +# Allow the intermediate CA to sign a more diverse range of certificates. +# See the POLICY FORMAT section of the `ca` man page. +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +[ req ] +# Options for the `req` tool (`man req`). +default_bits = 2048 +distinguished_name = req_distinguished_name +string_mask = utf8only + +# SHA-1 is deprecated, so use SHA-2 instead. +default_md = sha256 + +# Extension to add when the -x509 option is used. +x509_extensions = v3_ca + +[ req_distinguished_name ] +# See <https://en.wikipedia.org/wiki/Certificate_signing_request>. +countryName = Country Name (2 letter code) +stateOrProvinceName = State or Province Name +localityName = Locality Name +0.organizationName = Organization Name +organizationalUnitName = Organizational Unit Name +commonName = Common Name +emailAddress = Email Address + +# Optionally, specify some defaults. +countryName_default = GB +stateOrProvinceName_default = England +localityName_default = +0.organizationName_default = Xmlsecurity Test +organizationalUnitName_default = +emailAddress_default = + +[ v3_ca ] +# Extensions for a typical CA (`man x509v3_config`). +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer +basicConstraints = critical, CA:true +keyUsage = critical, digitalSignature, cRLSign, keyCertSign + +[ v3_intermediate_ca ] +# Extensions for a typical intermediate CA (`man x509v3_config`). +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer +basicConstraints = critical, CA:true, pathlen:0 +keyUsage = critical, digitalSignature, cRLSign, keyCertSign + +[ usr_cert ] +# Extensions for client certificates (`man x509v3_config`). +basicConstraints = CA:FALSE +nsCertType = client, email +nsComment = "OpenSSL Generated Client Certificate" +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer +keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment +extendedKeyUsage = clientAuth, emailProtection + +[ server_cert ] +# Extensions for server certificates (`man x509v3_config`). +basicConstraints = CA:FALSE +nsCertType = server +nsComment = "OpenSSL Generated Server Certificate" +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer:always +keyUsage = critical, digitalSignature, keyEncipherment +extendedKeyUsage = serverAuth + +[ crl_ext ] +# Extension for CRLs (`man x509v3_config`). +authorityKeyIdentifier=keyid:always + +[ ocsp ] +# Extension for OCSP signing certificates (`man ocsp`). +basicConstraints = CA:FALSE +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer +keyUsage = critical, digitalSignature +extendedKeyUsage = critical, OCSPSigning diff --git a/xmlsecurity/qa/unit/data/xmlsecurity-dialogs-test.txt b/xmlsecurity/qa/unit/data/xmlsecurity-dialogs-test.txt new file mode 100644 index 0000000000..1f8ee2b621 --- /dev/null +++ b/xmlsecurity/qa/unit/data/xmlsecurity-dialogs-test.txt @@ -0,0 +1,45 @@ +# -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +# This file contains all dialogs that the unit tests in the module +# will work on if it is in script mode. It will read one-by-one, +# try to open it and create a screenshot that will be saved in +# workdir/screenshots using the pattern of the ui-file name. +# +# Syntax: +# - empty lines are allowed +# - lines starting with '#' are treated as comment +# - all other lines should contain a *.ui filename in the same +# notation as in the dialog constructors (see code) + +# +# The 'known' dialogs which have a hard-coded representation +# in registerKnownDialogsByID/createDialogByID +# + +# No known dialogs in xmlsecurity for now + +# +# Dialogs without a hard-coded representation. These will +# be visualized using a fallback based on weld::Builder +# + +# currently deactivated, leads to problems and the test to not work +# This is typically a hint that these should be hard-coded in the +# test case since they need some document and model data to work + +xmlsec/ui/viewcertdialog.ui +xmlsec/ui/macrosecuritydialog.ui +xmlsec/ui/certgeneral.ui +xmlsec/ui/certdetails.ui +xmlsec/ui/certpage.ui +xmlsec/ui/securitylevelpage.ui +xmlsec/ui/securitytrustpage.ui +xmlsec/ui/selectcertificatedialog.ui +xmlsec/ui/digitalsignaturesdialog.ui diff --git a/xmlsecurity/qa/unit/pdfsigning/data/2good.pdf b/xmlsecurity/qa/unit/pdfsigning/data/2good.pdf Binary files differnew file mode 100644 index 0000000000..10528c57f7 --- /dev/null +++ b/xmlsecurity/qa/unit/pdfsigning/data/2good.pdf diff --git a/xmlsecurity/qa/unit/pdfsigning/data/bad-cert-p1.pdf b/xmlsecurity/qa/unit/pdfsigning/data/bad-cert-p1.pdf Binary files differnew file mode 100644 index 0000000000..04d9950582 --- /dev/null +++ b/xmlsecurity/qa/unit/pdfsigning/data/bad-cert-p1.pdf diff --git a/xmlsecurity/qa/unit/pdfsigning/data/bad-cert-p3-stamp.pdf b/xmlsecurity/qa/unit/pdfsigning/data/bad-cert-p3-stamp.pdf Binary files differnew file mode 100644 index 0000000000..b30f5b0386 --- /dev/null +++ b/xmlsecurity/qa/unit/pdfsigning/data/bad-cert-p3-stamp.pdf diff --git a/xmlsecurity/qa/unit/pdfsigning/data/cr-comment.pdf b/xmlsecurity/qa/unit/pdfsigning/data/cr-comment.pdf new file mode 100644 index 0000000000..b1aae07a21 --- /dev/null +++ b/xmlsecurity/qa/unit/pdfsigning/data/cr-comment.pdf @@ -0,0 +1,4480 @@ +%PDF-1.4
%âãÏÓ
+1 0 obj
<</Metadata 2 0 R/Pages 3 0 R/Type/Catalog/ViewerPreferences<</Direction/L2R>>>>
endobj
2 0 obj
<</Length 45779/Subtype/XML/Type/Metadata>>stream
+<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?> +<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 4.2.2-c063 53.352624, 2008/07/30-18:05:41 "> + <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> + <rdf:Description rdf:about="" + xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" + xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" + xmlns:stEvt="http://ns.adobe.com/xap/1.0/sType/ResourceEvent#" + xmlns:stMfs="http://ns.adobe.com/xap/1.0/sType/ManifestItem#"> + <xmpMM:InstanceID>uuid:e7f483a2-dbf7-4046-8848-508b776dd738</xmpMM:InstanceID> + <xmpMM:DocumentID>xmp.did:89321C534E266811A613EDAC20FB34D2</xmpMM:DocumentID> + <xmpMM:OriginalDocumentID>adobe:docid:indd:924fbc79-cadb-11de-af61-e97e2740acd1</xmpMM:OriginalDocumentID> + <xmpMM:RenditionClass>proof:pdf</xmpMM:RenditionClass> + <xmpMM:DerivedFrom rdf:parseType="Resource"> + <stRef:instanceID>xmp.iid:88321C534E266811A613EDAC20FB34D2</stRef:instanceID> + <stRef:documentID>adobe:docid:indd:924fbc79-cadb-11de-af61-e97e2740acd1</stRef:documentID> + <stRef:originalDocumentID>adobe:docid:indd:924fbc79-cadb-11de-af61-e97e2740acd1</stRef:originalDocumentID> + <stRef:renditionClass>default</stRef:renditionClass> + </xmpMM:DerivedFrom> + <xmpMM:History> + <rdf:Seq> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E4B6ED806F256811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T11:39:47-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E5B6ED806F256811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T11:39:47-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/metadata</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E6B6ED806F256811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T11:44:22-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:80321C534E266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T11:46:03-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:81321C534E266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T11:48-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:82321C534E266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T11:49:01-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:83321C534E266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T11:52:39-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:84321C534E266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T11:58:06-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:85321C534E266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T11:59:50-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:88321C534E266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T12:03:27-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/metadata</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:89321C534E266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T12:03:27-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:4A27385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T13:48:01-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:4B27385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T13:50:54-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:4C27385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T13:54-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:4D27385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T13:55:16-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:4E27385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T13:56:27-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:4F27385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T13:58:44-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:5027385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:05:30-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:5127385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:07:25-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:5227385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:12:43-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:5327385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:13:56-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:5427385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:16:22-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:DE855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:19:25-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:DF855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:27:07-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E0855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:29:58-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E1855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:32:34-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E2855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:33:46-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E3855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:40:42-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E4855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:41:28-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E5855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:42:42-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E6855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:44:36-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E7855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:47:08-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E8855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:51:29-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:80C8B5F5A22068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T10:49:23-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:81C8B5F5A22068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T10:50:43-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:82C8B5F5A22068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T10:52:12-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:00CECC59A92068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T10:53:23-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:01CECC59A92068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T10:53:56-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:02CECC59A92068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T10:56:41-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:03CECC59A92068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T11:03:21-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:04CECC59A92068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T11:06:47-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:05CECC59A92068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T11:09:26-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:06CECC59A92068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T11:11:53-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:07CECC59A92068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T11:13:29-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:999093B2AD2068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T14:21:34-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:9A9093B2AD2068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T14:27:38-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:9B9093B2AD2068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T14:30:31-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:371C0BE61C2368119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-07-02T14:20:55-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:381C0BE61C2368119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-07-02T14:26:33-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:391C0BE61C2368119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-07-02T14:29:07-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:3A1C0BE61C2368119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-07-02T14:31:19-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:7A0142B9242368119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-07-02T14:41:33-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:7B0142B9242368119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-07-02T14:44:10-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + </rdf:Seq> + </xmpMM:History> + <xmpMM:Manifest> + <rdf:Bag> + <rdf:li rdf:parseType="Resource"> + <stMfs:linkForm>ReferenceStream</stMfs:linkForm> + <xmpMM:placedXResolution>72.00</xmpMM:placedXResolution> + <xmpMM:placedYResolution>72.00</xmpMM:placedYResolution> + <xmpMM:placedResolutionUnit>Inches</xmpMM:placedResolutionUnit> + <stMfs:reference rdf:parseType="Resource"> + <stRef:instanceID>uuid:288c3c69-7dd6-7c4f-984d-b085b3307748</stRef:instanceID> + <stRef:documentID>uuid:93F9F49755C5DE1185BCB9A8461E73D9</stRef:documentID> + </stMfs:reference> + </rdf:li> + </rdf:Bag> + </xmpMM:Manifest> + </rdf:Description> + <rdf:Description rdf:about="" + xmlns:xmp="http://ns.adobe.com/xap/1.0/" + xmlns:xmpGImg="http://ns.adobe.com/xap/1.0/g/img/"> + <xmp:CreateDate>2010-07-02T15:32:26-07:00</xmp:CreateDate> + <xmp:ModifyDate>2010-07-02T15:32:26-07:00</xmp:ModifyDate> + <xmp:MetadataDate>2010-07-02T15:32:26-07:00</xmp:MetadataDate> + <xmp:CreatorTool>Adobe InDesign CS4 (6.0.5)</xmp:CreatorTool> + <xmp:Thumbnails> + <rdf:Alt> + <rdf:li rdf:parseType="Resource"> + <xmpGImg:format>JPEG</xmpGImg:format> + <xmpGImg:width>256</xmpGImg:width> + <xmpGImg:height>256</xmpGImg:height> + <xmpGImg:image>/9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA
AQBIAAAAAQAB/+4AE0Fkb2JlAGQAAAAAAQUAAjSA/9sAhAAKBwcHBwcKBwcKDgkJCQ4RDAsLDBEU
EBAQEBAUEQ8RERERDxERFxoaGhcRHyEhISEfKy0tLSsyMjIyMjIyMjIyAQsJCQ4MDh8XFx8rIx0j
KzIrKysrMjIyMjIyMjIyMjIyMjIyMjI+Pj4+PjJAQEBAQEBAQEBAQEBAQEBAQEBAQED/wAARCAC1
AQADAREAAhEBAxEB/8QBogAAAAcBAQEBAQAAAAAAAAAABAUDAgYBAAcICQoLAQACAgMBAQEBAQAA
AAAAAAABAAIDBAUGBwgJCgsQAAIBAwMCBAIGBwMEAgYCcwECAxEEAAUhEjFBUQYTYSJxgRQykaEH
FbFCI8FS0eEzFmLwJHKC8SVDNFOSorJjc8I1RCeTo7M2F1RkdMPS4ggmgwkKGBmElEVGpLRW01Uo
GvLj88TU5PRldYWVpbXF1eX1ZnaGlqa2xtbm9jdHV2d3h5ent8fX5/c4SFhoeIiYqLjI2Oj4KTlJ
WWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+hEAAgIBAgMFBQQFBgQIAwNtAQACEQMEIRIxQQVRE2Ei
BnGBkTKhsfAUwdHhI0IVUmJy8TMkNEOCFpJTJaJjssIHc9I14kSDF1STCAkKGBkmNkUaJ2R0VTfy
o7PDKCnT4/OElKS0xNTk9GV1hZWltcXV5fVGVmZ2hpamtsbW5vZHV2d3h5ent8fX5/c4SFhoeIiY
qLjI2Oj4OUlZaXmJmam5ydnp+So6SlpqeoqaqrrK2ur6/9oADAMBAAIRAxEAPwCReWvLfleTyzo9
zd6VYPJNY2zySy28JZ3aJGZmZkqSTlgApgSbTL/Dfk3/AKtOmf8ASNB/zRhoIsrk8reUZKlNH01q
deNrAf1JjQWymEXlLyYIk9TRdLDU35WsFfxjys82Y5L18peSmPFdE0tiewtLcn/k3gSubyd5OUcm
0LTFA7m0gA/5N4qt/wAKeSf+rLpX/SLb/wDVPFXf4U8k/wDVl0r/AKRbf/qnirX+FPJP/Vl0r/pF
t/8Aqnirf+E/JPT9C6V/0i2//VPFVK+8o+T4oeX6D01fiAqLOH+EeSgLLGRoJY3l7yWp4tpOmgjs
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
xV2KuxV2KpL5z/5Q/Xv+2bef8mJMVf/Z</xmpGImg:image> + </rdf:li> + </rdf:Alt> + </xmp:Thumbnails> + </rdf:Description> + <rdf:Description rdf:about="" + xmlns:idPriv="http://ns.adobe.com/xmp/InDesign/private"> + <idPriv:DocChangeCount>244</idPriv:DocChangeCount> + </rdf:Description> + <rdf:Description rdf:about="" + xmlns:dc="http://purl.org/dc/elements/1.1/"> + <dc:format>application/pdf</dc:format> + </rdf:Description> + <rdf:Description rdf:about="" + xmlns:pdf="http://ns.adobe.com/pdf/1.3/"> + <pdf:Producer>Adobe PDF Library 9.0</pdf:Producer> + <pdf:Trapped>False</pdf:Trapped> + </rdf:Description> + </rdf:RDF> +</x:xmpmeta> +<?xpacket end="r"?>
endstream
endobj
3 0 obj
<</Count 1/Kids[5 0 R]/Type/Pages>>
endobj
5 0 obj
<</ArtBox[0.0 0.0 841.89 595.276]/BleedBox[0.0 0.0 841.89 595.276]/Contents 6 0 R/CropBox[0.0 0.0 841.89 595.276]/Group 7 0 R/MediaBox[0.0 0.0 841.89 595.276]/Parent 3 0 R/Resources<</ColorSpace<</CS0 8 0 R>>/ExtGState<</GS0 9 0 R/GS1 10 0 R/GS2 11 0 R>>/Font<</C2_0 12 0 R/C2_1 13 0 R/C2_2 14 0 R>>/ProcSet[/PDF/Text]/Properties<</MC0<</Metadata 15 0 R>>>>/Shading<</Sh0 16 0 R>>/XObject<</Fm0 17 0 R/Fm1 18 0 R/Fm2 19 0 R/Fm3 20 0 R>>>>/TrimBox[0.0 0.0 841.89 595.276]/Type/Page>>
endobj
6 0 obj
<</Filter/FlateDecode/Length 7843>>stream
+H‰ÌWm‹¹þ>¿¢?¶W*½ƒYðŽ½†ÀÁ/ÜA!¬Ï6‰7áb8È¿ÏSU’Z™ñÝÚ¾#,lOI¥z}ªJ2«]Ìj<ÿï埇ëWoÌòþÓ²Y£ÃR¶k*n %¬”ÂòŸŸï×ßüûÃOo¿q·\w4Ëí‹ãrøùR]9„%Ù•lX¬]‹I|ð‡å_³Èß ëçÅ +e—èÓ•%âLŽ~yxÎÇÕY §ÍòQ~Ƹð§D¥ÍmÚO¬§4…˜°Î-‡NhSjoÇ;;P/zAfïX8¢ä7rÓÍÜj[‰;Ú•²ã>íhG±ðQU«‰LP°•ªlõËZ}S=qÐ[Éc÷áA¬”äº4–Ae‚dSrZ6¿²˜ÇVËÁJg/ùÜ•]mé,´Rb›¦$@“Û±ö[E +¥ÚšïÕŒÍÄn1¤9ÕäH¶ÑøÇ‹¡ªF+Ý3…J¨&ÄâR*Sk@߃ŕde5ŸÕŽ•¢¹1ÈÏV»Õ¥N#Û~µÇÒ—”&Ôh) d/8bÂf¡Ràà‚6‰ˆ«IPÂÊžw‹ËEàt•Po¢G]e`'ð¡‰wCrË/ÐÀíH?.2Sæ¥Õp6 ÀH,ãj9{ݨ ?Ðe%@Œ—øÊŠ=¾1à`£6A“yïëOiG[x‰öá*ÈBY $e&Ñš¢D?# +´¸Õ'‰òäP%CXHêEbÒS +Sö^ö¥é#ãT¤é÷Þ +½¡*Šƒ +ïW†õÉv»½œ¶ÞÊbFá‰SYÌþÍåÜíh03§ò„~y¡·*xZ<¿m7ëá™7·Ü%³;ʼ@0î_RýÜ MåÏ"ê8E2žï3¿Úéólù½3û[u)Ã}Ì)q³?ƒÇ“X< ]½šæ]³-=çsuN3ä$W
~vöí†Üµ¡~î¢Á{ïׯÞØåý§ÃõÝ£Y^ü-˜¯'!òw±Oà—Œ«n¼ÞÞ*v/€¯È>e~Òî{—ÊŒÛæø{ãˆ-ݹlqq¶¸••èrÆ=ýáñpûãrýæƒY>}X^þ¸¼þ•[Ò‰ñ¶Û!&†áÇ +p½uèm†Á }I{‹ü9¨ ¦™`ëÔäWžNþñZˆ/ŽÀ?¢éÃ3š*쨖8U¸É—
¬]*Ì©– UØ*_¥C¥¹<Ü §kßvåp~ÝOt9/·}_Ó¸³Q“¯5“^ûy=-.ÁìùhŠÊ™âhWÓO“]?LS"Ú6%¨±|aHirÍ×}Û\½»‚)ÜÉÜ +bÑN¶—ß]º±îDº|7É>í§ý¹)eÍŸ“mPÖÎŒ”bíäÞ—#¿gîþOZÄ_˜¨¾ž§ónoÙIàg9愧¿óMî‰"cë9;'l®½²—Ó=yoÏY µšœk¯Ë÷{»C>oG˜Þ€'y¹gŽ%i£œË¯ÁrøÆQúŒ“Pú€¾T¶ä?ƒ;•éÜql¥Ý$oÆmïtqŠZœä´(O7LQoÌ·sQ/Ns6z<Ž{ûÛ9ò_«Gs¶ûÍ ifí jE +y
+”'6¿ïÄ’Ä.˜—õ[iÞ7²/stÊtÁc,h¦Yfª—ª¨6w[ëËI~mð~°ó ÎûÞ~>€jgu0¾Z*‰ºÓùç*͆ÝnÞ‡çÕòc5î¶òWMó5ouŠ‹u¾FàXyíÅK› CwS#f¸áb@5ÐYgéPӈˡ21›M˜ê®‡o‡Ì5ûì·E÷¢ÍM¬²hÎľtÚ¡!zÆMÑ*ݵ¾Ö¡1Èʬk»éTÓ¾_–5eOˆíM¤]ìšCÁ;É~]s šQvì2-ææQ]£š±1Älµ}¶×êóïÕŽTs8œfD‚£.GaîW¨ßþ¿öŠçK-b‚µ?
[N¢2XÜÒ!kµÈ7lBÒ³æÁùŽkYnbó/}Û%4PÅjÕÝåþ7Éli0j)$Sß”OàßX]\KH½ÖÐ#ɺ¸¡ùÔWK®ë¸÷*¼;üK¶ßu̲€‚Œ² YU,II¾×~ q[Ïúë{Ωk&¹¥Í<ˆI{"Xµÿ8 ±Y*øò7q››íur |å6 ~tN.ÔøíÈp +i¦b{.+…ÆÞÓ Ñ ¹ÍpNøë«Çñù4k\W>!þuô(\ [rNŠaO@÷!ò\VÈÏ“ç^j¢#Û á¤Ê„üÉJ»Ðˆ,¸ñš¿«g¤˜ŽöÂΘtF+Ó£0dÉ{û˜gå+'§AÌß
¢Û^åÕ +k!ìq&Cú(x(ŽÖ:VALär¼ Yâ?28x}ñÃhWpˆ9ÖÐOYÞè_ä%Ël|ù1šc¹Ú@†LÖñ/°ñ1ÊÇoÙý‚opå˜=¨&~GeÁJµrJ«òvÊX»Å)¾4¨ÓY_Œ^²ð‹PG…CTF +Fçæ°¸Xl¢™çH\v˜µ²,]=‘·•:¿sé¢+¯’ÑØÃ<)Ì)âSèæËÑ$&þ9j•ÞØäßúàH*Ó_ow'¶1àÈRÁ<‰®žè{*%AÚ+à´ìmê +à>€A©M^ó¾ÛôÝ×ê--ÞBjúÂàoqÎÅH“ös{m‡tm=ÚñmòÌf§<ü»öÀíNŽmš&DOkƒ–ÛÁǯ0'ï©n-3:6}Å‚ÙDž·ŒÜn–ÈÛî*RL<èëÙ#ê(FÄä}«ÏÞ‹á°-Ž¸Ðå{ïj+¢‰¯4k +â¸çÈÔ¢BkL}ÔÜ!:+—™ÂÅ©N>,ªÙZ¹ +Ƶ„ñÀŒÀ‹&×åÔtµpÿ W÷Å{ +Þóhçבž‹(Üeô9€†Çl(u$"07±47‰†ßà¼Í“‹)ÜD`ǼOÑœ‡‹õk£³eѽ+‘‹€ù{^¸÷vÇŽ=qßCñ=™¶…-ÒCçxºËýÒ¥=%ó"Ë6–˜S
:Ò@Š¦Ž+¦±rÙ‰£†×BÆ’Ê]'ÅUh·£)ç~3n¦zûÎzZ OŸÎÒi—± N!sÓúgC"ßH.QàÂWo@«jÖZ¡ƒ(U-8ä;‚¡we4I"lF$Œçè? +Ÿá»MµT‡{çµáé•‘2¤2Ê‚¥8*ϬeˬÁ¡Sz'‚ö{ÆmT%[V›B[ù8lÚ^jdÏûZ¾¿gÙ‰GikÖÏæÕ:Ä…Ž9AåûŽ±yüŽ±ÙÆ•Á|ob ì4(cYÖ\¾GÑ!ýµä©ƒ‰÷šéhno‚Á=r5JNÑnxÂ$1üYH¹Ìôwªÿüpõ¯{¾¿\ì6aó<–þƒÂßø«´÷¹cG<J¹‚<#m2}¤o5Ô +”7ÊÕmoõBûb/‘ûç„ÝG¹7T«Ÿô[ì¸êõýÝ +†¡íl¹ÝP÷V>a߯R)V<YR\Ýpu$T%‚zDï9²l4÷=¶ÛK,-¿DÅ9ZdÎÞÚ~ÊËá}ãK?è\ˆ'1R‘µ½îªçöɺùÀ¿ÿÚ®a·Gð}YãPúGþ*Q)1VtδOã,âòbf¼~¥‡4÷ä +Ðnàˆ8碩ÎÂÅÀïÎ@òž¿ñV1/ìegDM"HÖPOø‚qÓ±{C}Z,¨5:³# ?YMN-ŠžC^cêUÁzdü&çP.>Ñrr–äYqKÜq6Ó5ŸÍI1&I§ñXÒ‡H†9ôÅÖ +k˜´aöiK¾.¶ûS‡>“Qﻄ_m”P+{›Ê¸: +€u¥,¼ãXÄÖ×̸BñxDX”ì_Ðj,2’'3K~“,€ª.)¢ˆðÙÓ4c 5]Qõ£¶_u•Ú‘¢HÁcEI~b ” $ +îf@q½Ákš\ÍüØœŸŠ;Žòò9ø +džªpK*þ{£»þ›8hØa®ìz¸òÈS)Ö"µ±È6»¿¥ªŠ¾¹š†m½ÊæŠ^s™-.N@e¥TÝVí*gÜë•ãM“Q¿WY2ÿ(0—W¯Q<¿™Ÿ¸úñb¦Óà.“÷„B#ƒu¶ø#£.ÆÒ[‰>Ïéæ¹€GÜu†»ÈÆ°u²Ð\å’SMi¥®Ðv€–ñ¨[FØT²…áξEðóL°.?
¼Ðþd/nt]ájá¨/¸Âoó5Ÿm¡f‡Zͪ‘ó…W¤ºpΩs&HdÈ nà¿P»"NJ¼Ë;©qíÔ€ó"ÆVhËc6.A $kt>¶“bòÅËU¨ +·Qõ +u¢³v’ˆ:xgÛSÓ¤E|ë&âûïmy¾O€í&m«á
-nÍÄÖÅÅ€5ý³*€‘vÏ|‹gçŒÐymÔ65Âû¥•Ýµ‡ô’cšl/é’ãŠÑ{®jB¨•.wx}_Ì\uVÙ®´ +edñ`
¹ú +ÂâE¥÷J(IÅš1¬ÐÃxk3²’a2Vˆb…#¿ç–îrƒ6#Hì†E£â#¶<ìXxÙIÉ#ñ?÷º$¡¬™ø^ÿ¥WOÜé—Ÿïõú}íî;é–”ÒAyʵù~Á fx'oÇä®12wium +ܤó + ÃÁõ C=hŠ¢[Eû˜Á#ݨ¼ìLÏÔ$ÜÒ$ê¸%ã[n#6ÜyKxå´ÔVrÚ˜äs#Nüúh+,f“þ–¥QÜßQV1‹¬1ùe¨[÷ô<Ë»ïd½Ç²G*ûø%¹@ØyÄk9bsÅ«½`°§Ösjúø§é¦¿Þw‡¿o?~þ2‡?ÿ +xfd`¦âŧ?íê`Þ)bÜú‚O9Œ2þºC†*Ϻ
™ÀŸBŸàð +H‰LŒ1 +Ã@{½b?`ùN:ét!¤6.â>„¸‰Áöÿ!&nÂÃÀ°™g‡ÕÂ!DbWt¹²jÁþ¢VÚ(áMý}:qÐIkYéÜ¿ÿ…x…Yå-<Ï
3úiI8ÜfŒ4ÒW€ +H‰LŒ± +ƒ@DûùŠù×½½œ·Û +’Z,bBl"¨ÿ‘Ø„)³Á‹ŠÍ:IflÌCºÌ&UÉêÜ_xpÅåí}:qàŠ,"åL=÷ï¿CZµÐÔÅÓMŸô3ÛiQ‡™#F| +H‰LŒ± +Ã0Cw}…~ ÎùìØwk¡tš½„fi ÉÿCÝv)žíP“P³Õ VÙ©ùÇ»XC®‰Ç‚;7ì>Ñߦ†¿‘ºÇ”(-ÿþ=l]0³èà|¼p™ÙO«ð\y9bÄ[€ +H‰LŒ± +ƒPE÷|Åýc|y1É*”ÎâP÷RêRAý¨Ô¥Üápàp7 +Ž„yå(M‰ä^ÑtΪû‹Xi#Á›Úûtâ +*™*äÜ¿ÿ#ÝÅ`æ\#£‚ç‡†í´Ž·#ô` +H‰ª6RÈÌKIP0Ô3 +¹PTšÁTš0Òn¹ •p‡äÀq-@€ +<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?> +<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 4.2.2-c063 53.352624, 2008/07/30-18:05:41 "> + <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> + <rdf:Description rdf:about="" + xmlns:dc="http://purl.org/dc/elements/1.1/"> + <dc:format>application/pdf</dc:format> + <dc:title> + <rdf:Alt> + <rdf:li xml:lang="x-default">MS_Logo_70%</rdf:li> + </rdf:Alt> + </dc:title> + </rdf:Description> + <rdf:Description rdf:about="" + xmlns:xmp="http://ns.adobe.com/xap/1.0/" + xmlns:xmpGImg="http://ns.adobe.com/xap/1.0/g/img/"> + <xmp:CreatorTool>Adobe Illustrator CS3</xmp:CreatorTool> + <xmp:CreateDate>2009-10-28T13:10:30-07:00</xmp:CreateDate> + <xmp:ModifyDate>2009-10-28T14:10:20-07:00</xmp:ModifyDate> + <xmp:MetadataDate>2009-10-28T14:10:20-07:00</xmp:MetadataDate> + <xmp:Thumbnails> + <rdf:Alt> + <rdf:li rdf:parseType="Resource"> + <xmpGImg:width>256</xmpGImg:width> + <xmpGImg:height>44</xmpGImg:height> + <xmpGImg:format>JPEG</xmpGImg:format> + <xmpGImg:image>/9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA
AQBIAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK
DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f
Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgALAEAAwER
AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA
AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB
UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE
1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ
qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy
obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp
0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo
+DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8A9SXlzHa2k9zJ/dwRtK/y
QFj+rFXzFcTyTzyTyGskrM7nxZjU5JCzFX0V5IYN5R0kg1H1aMfSBQ5EpeT/AJpeYhqvmJraFuVp
pwMKUOxkr+9b7xx+jJBDDcVZz5H0+9PlPzJe2cDz3U8aWNvHEpZiJD+9oB/kuDgVj/8AgzzZ/wBW
i7/5FP8A0wq9u8i6VLpflTT7SaMxz8DJMjCjBpGLkMPEcqZEpT7FXYq7FXYq7FXYq7FXYq7FXYq7
FXYq7FXYq7FXYq7FXYq8L87+f9W1TVLiCyupLfS4WaOKOJinqBTQu5FCeVKgHpkqQhPJuh67rGrW
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</xmpGImg:image> + </rdf:li> + </rdf:Alt> + </xmp:Thumbnails> + </rdf:Description> + <rdf:Description rdf:about="" + xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/"> + <xmpMM:DocumentID>uuid:93F9F49755C5DE1185BCB9A8461E73D9</xmpMM:DocumentID> + <xmpMM:InstanceID>uuid:288c3c69-7dd6-7c4f-984d-b085b3307748</xmpMM:InstanceID> + <xmpMM:DerivedFrom rdf:parseType="Resource"/> + </rdf:Description> + <rdf:Description rdf:about="" + xmlns:xmpTPg="http://ns.adobe.com/xap/1.0/t/pg/" + xmlns:stDim="http://ns.adobe.com/xap/1.0/sType/Dimensions#" + xmlns:xmpG="http://ns.adobe.com/xap/1.0/g/"> + <xmpTPg:NPages>1</xmpTPg:NPages> + <xmpTPg:HasVisibleTransparency>False</xmpTPg:HasVisibleTransparency> + <xmpTPg:HasVisibleOverprint>False</xmpTPg:HasVisibleOverprint> + <xmpTPg:MaxPageSize rdf:parseType="Resource"> + <stDim:w>6.000000</stDim:w> + <stDim:h>2.000000</stDim:h> + <stDim:unit>Inches</stDim:unit> + </xmpTPg:MaxPageSize> + <xmpTPg:PlateNames> + <rdf:Seq> + <rdf:li>Black</rdf:li> + </rdf:Seq> + </xmpTPg:PlateNames> + <xmpTPg:SwatchGroups> + <rdf:Seq> + <rdf:li rdf:parseType="Resource"> + <xmpG:groupName>Default Swatch Group</xmpG:groupName> + <xmpG:groupType>0</xmpG:groupType> + <xmpG:Colorants> + <rdf:Seq> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>K=100</xmpG:swatchName> + <xmpG:mode>GRAY</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:gray>255</xmpG:gray> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>C=0 M=0 Y=0 K=0</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>0.000000</xmpG:cyan> + <xmpG:magenta>0.000000</xmpG:magenta> + <xmpG:yellow>0.000000</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>K=100</xmpG:swatchName> + <xmpG:mode>GRAY</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:gray>255</xmpG:gray> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>C=0 M=0 Y=0 K=0</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>0.000000</xmpG:cyan> + <xmpG:magenta>0.000000</xmpG:magenta> + <xmpG:yellow>0.000000</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + </rdf:Seq> + </xmpG:Colorants> + </rdf:li> + </rdf:Seq> + </xmpTPg:SwatchGroups> + </rdf:Description> + <rdf:Description rdf:about="" + xmlns:illustrator="http://ns.adobe.com/illustrator/1.0/"> + <illustrator:Type>Document</illustrator:Type> + </rdf:Description> + <rdf:Description rdf:about="" + xmlns:pdf="http://ns.adobe.com/pdf/1.3/"> + <pdf:Producer>Adobe PDF library 8.00</pdf:Producer> + </rdf:Description> + </rdf:RDF> +</x:xmpmeta> +<?xpacket end="r"?>
endstream
endobj
12 0 obj
<</BaseFont/UZUFLT+Segoe-Semibold/DescendantFonts 34 0 R/Encoding/Identity-H/Subtype/Type0/ToUnicode 35 0 R/Type/Font>>
endobj
13 0 obj
<</BaseFont/SJATJX+Segoe/DescendantFonts 36 0 R/Encoding/Identity-H/Subtype/Type0/ToUnicode 37 0 R/Type/Font>>
endobj
14 0 obj
<</BaseFont/QTGHHB+Segoe-Bold/DescendantFonts 38 0 R/Encoding/Identity-H/Subtype/Type0/ToUnicode 39 0 R/Type/Font>>
endobj
38 0 obj
[40 0 R]
endobj
39 0 obj
<</Filter/FlateDecode/Length 531>>stream
+H‰\”Íjã0F÷~ +-ÛE±-Ý+µmÒ@óÃdæ[I
mg‘·Å't`-låûιùj»ÞvídòŸc_ïâdm׌ñÜ_Æ:š}<¶]VZÓ´õt§ù}ª†,O‡w×óOÛîÐg‹…É¥‡çi¼š‡×¦ßÇÇ,ÿ16ql»£yø³Ú=š|w†ÏxŠÝd +³\š&Ò}«†ïÕ)š|>ö´mÒóvº>¥3ÿÞø}¢±3—”©û&ž‡ªŽcÕc¶(Ògi›ôYf±kþ{ +ŽíõG5ί»ôzQØb9“‡ô=C+èz‡Þ
´š©, 5TBï…6éŽôR RÈBèRèò==Ë5ô:“%AH°$ wÁÝ’'äYò„<Kžg™’0%KºnI—{:3ff™™03ÇÌ„™9f&ÌÌ13afŽ™)3s)F#ÅÈa¤9Œ#‡‘bä0RŒÒ°f +~ŠŸÃAqZ+…žJO¡§§§ÐÓÓSèéé)ôôôzzz +===…žžžBOOO¡§§§pž{îÁs‚ƒ¿;pž{PŒ<FÊ=xîAñóø)~?Å(`¤Œ£€‘b0RŒFŠQÀH1 +)F#¥u õêÞÚcœ~ø÷_øm¤Me¾öK}Ç´Zæu6ï”Û6i»øµñ†~0éÔí/û+À +H‰j +H‰dVTT×½ç¾÷f +Ú,UÚàâ/ýãџУºŒ!O"1oÆàgÒù˜CFa$¿Nœò˜á‹¶û~_üN4ÞZ¼G¦vG…?Þü.ÜjÛ¾L‰œv[/ˆu5›Ö”鮚xÁ›‰.:Š:XhôÓhÍߊ(‡f÷`G`9Ÿ¶?{OõI<5ûוdMÆÕÓ+3ñFã|Ëø`Kê\stÜÁ‡U_»Wßb—“þóåÍ…w;£&¦¦ÅÎŽ‰Ñ(z¤#z è8s¥n5¹èduEt†sr$žÆ»§6çV=šÅjÖìÛuïVÉï°iåÜ$‹uÕ¼Ù™’‹qÎ/@Ž»ÿW¾ûÝ÷®=ݹmßÉÓ¹Ož²jͦŠìà®ÜŸ¸6DäMá\äÕ½ÁäLAä-eÅ.\BŒNµwüÈmN]fJ)õHË~&8$ÑI +4Q«%¥+3/ÇO¹éËõ7WƒHlRÊí‡áQDlôFÂÅŽkÚÉž
cþ™l¤;X¨Õhùö0£QGu𢢈jG;vþWmç/Š7¦Ä¯=”:×?+Ü“–±yÍ©/r£&AÍ¥ï”ò…óÙÌ%{-]G°f™ú<yn³XÄ~‰£NT¹v +9O.{#—–ìʈ'–¾}GI“¡óG±¨ÇÕ3ÔsOèG{!GÝÈ7Híçñ$Iñ´Rèw‚SÄ·Iß&PPûp¤BÐPY£t÷d;‡Íœ“ =èHß´/]ç3‰¾Sóɇ—k#9½´/±Ë»ôŠì®ëƸ–^ ùÛÕÕu†ÿsï¹wq‹ºPЬë–P»1Æè²"áQå±ìE¤D”‘¢âsàÂ`5¨PÂXÃJ†ZL5Ç*t¨EkÔµˆË0Žµ‰cvÏö?wwR™ù<ë½çœÿõý+Ó@BIê¿'ª)õ¹Ê/k—¦eÄØ7¢¥ïç&®ÿh4椬ÿŒ²p´BQ–¿+ºnQ£2°P„²’ï'j¨WàdJK'ݾÔ[ÿld ·âô‹Ù<¡[èf–¥o§G·¢§Í¶W>öGšml6¹Óƒ³©üÏ®—í|W,îÒzv™Œ>A8j™áömÒËÎwI ]¸X¯hq&xfFÑbo-¬·ˆŸ¥
‚UTÞ½``WI mÀÒ‰ì
s~+öÑ@ìBzerõbMp0Ÿ?L8—gúHžIÀ$ö±;4çzí*YO¦œ=ו·3‹œe½çëÌ‹Öl…êÖÕÖƒÄ07¸9odf –Åø™b÷¤sY6är›4ŒYΧ€’‚ü]×5sÌRˆì:Ú^ötdRv…Dл=›3ØãÂœŒ}©y;Øõ#EÒ°c÷™š²ÝËVVýrÓúÍÜÞ8´¨- +PúªbÌèpåi¬beî‘êÃ
õ„œMúÅî²D˯ì(Žª®ê'ꚣï±ç愤Êòz3j÷Ñ|ÔÚwœ‡xUA¥qÌ'¦Oþ)YžÏ®ÐÍ=_–––ܼš@I»¾m]îöè…™é‘QPÙ´³‚u'ª„õvyåG¥Í•UËcÌ nIZÔÜOáµ~Š~~¨ÿ¨Ê\¬EVQ#[C&4—T
üPQÖtøÆÐÞì^{bXÈOHSÒÇ*ž“Iµ¥GKïFÞ_•Š^™ƒ=J/SÎb‚êúûýy™ +2Ý#Ÿ¨^Pûä ëlmÝ\Ø•C_|‘7d§·äøqý˜Ž ~Zx=¡[¯n=&î”Y¯¼²€T7±³7wüü7«“éæÛW(þë…4Má›v.Ûµk;ûÏgmáD¶6åPr+ñ{L¼êŽ)r'§/^Þx|Ÿ9¡-±aeJSâ¡ôR%¨î¶T¥i¬³ñÃy.Þ|MÒ@ˆ}°8*çˆaÇÞß3ü?ä£îIßbå™<~y·¼—mIþ('1iÃ4~‡»l]ÆÒ¸5k_n£Èaç¦sŸ
üÑY?eê0¡¹¦q·|˜?´$eQÈñ±w•]+ýíŒÁO¨n‹ÊÑ"o¥o»g,ˆ´Ëן\)€mµˆbgT¶‡“>¦s$—ð¤g"ºÄ÷>p½“û1Z:Ÿ7yV½¿q,î4¹–Å®|ž¼^‘öNbFÁÝÄíi×_–í¸,$ôíßâ¸FáTüüˆ‹Y¶[ï,”à3N¿™"‹u¶¤lR®ÛÚG¬ „ìÏpœ£ÐðKu³½OOr} ›f‚B ìÕ’F +ÿ +ãh—zëÎÔ”ÿ‹Lút·%·¬Ùeµ¨§¾ +w~6ÖfžCa+6*×Å_ž§t5³©:þæÍ#’Ž•)5rÙëžQ±|`+w±hª?ÏMw'ãòvÞo(¯ûäDÜ®}aK_-..*ݤK?øA< ;–šB`Ý:CÈ»s#—ï¬>cx»êÝ7~:/ÚŒ²8?•B•Y¿.|”LöáYï‡+<]vˆµ75‘ðGŠç›¼ƒÉZrgè›TÖ5IJNqÇÁvŒ9ïã©zJs÷ã] +LãxJü~nš=—
&ìAج¹FÂýç´cµäðãvzWi
ëŠÌìÖ–Ähóî÷°L’~ñ T=õ…ÚXÁ4{pa±ÈG£ÍñB׶kO·¬sur¬Ýv”áÅ¿a
hÇ0Vw^Ñ‚ÿ¿¦¿¶âÓá씤
9‰É¦³Nν¿°êñcv¹µ5·àÚÚÆU¾o~‘?h§ºšŸ98tëÚžeLŽø/LG=ðïüߧQeý¦(Àirt¨5^6Ü7óÒ}ÂËæè +Ô’Ï00ãÕHch”NƒYÆçB4Š‡A/ÍÃçS¡QÕ²¡3r>§f”ytRTK«@í¥_)dzcwhGŸˆ €+·å†hÁߥ8½%@ýlb/ÄÑç+ĉ˜£üî›ùB¬sÝ¥ü¶©¬`£½ˆ|çø>q.ž·Aº¨¾ÛNW•3ACsÁ‹&8íâD¹¹˜=¸ZQþeÅn·›Û챉ë¯èô(:ZÇuZ†ú
"þ‚hÕíÇàz
‘¢ +1>-ˆÃâ(3áVÞ4I›Ì TÁlX!äA¨Ø«¤Qíq2®§\ìâÆwè Êþ5Ì‘‚À$[1†h_=4‰qè£&ˆ•g‚E>…¶ J@ǹ§Üa„Tμ‡ûå-Ú&Õ +(áõøŠËUÙÙhr˜çr7Q X QÀï£gð=úÇ^¸é4q~ +—ÀÄÜ0ppû^Z ϧª½‘÷<ÏÊüÛ"T8"n ¾WlwCášœÈ"Hh£Ð ¾‚Œ1GÞ“s`DyzAYø^<{ZÎYäMç§Âäæ +H‰\”ÝŠÛ0FïýºÜ½Xü#´Áu6‹þдàØJjhl£8yû*:a5$p°Gg¾q&y³ÛìÆaQù÷0u{¿¨ã0öÁ_¦kè¼:øÓ0fe¥ú¡[”¾»s;gy,Þß.‹?ïÆã”V*ÿo^–pSOë~:øç,ÿz†ñ¤ž~5ûg•ï¯óüÇŸý¸¨BÕµêý1ô¥¿¶g¯òTö²ëãýa¹½ÄšOü¼Í^U‰Kšé¦Þ_æ¶ó¡O>[ñªÕj¯:ócÿß}Ñ”ŽÝï6¤Çu|¼(ª¢Nd!
½C¯P½A[¨ITÐ*¡ƒÆP¾BqŠæ”Š:M]%‰LÑ™¡³ÊAâLÙ}ú¬0š>
}j::ÓøŸÆ'ø4>Á§ß !13afš^„^b»w²%„Ïâ3ø,>ƒÏâ3ä³ä3Ø-vƒÝb7Ø-vƒÝ>ìh
}@ïS²LI˜’eJÂ[±¼•8žD[ˆ :&(äsäò9ò ùù„|Ž|B>G>!Ÿ#ŸÏ‘OÈçÈ'äsäò9ò5–üq¿ùûRÄÝUŸ×]CˆË–<mÙ}¿†ÑþÌÓ¬bÕý“ý` +H‰j +H‰\V T”×~÷ýo–ÄmF˜AÔÃ8Vq”a(j5Š8"¨ "à‚ˆâ†TÃ*ˆ„¨5#x)µV\ÚºÅå ±ÖX·$.1GKmVþgï›AbÊœÇ?oûîò}÷þC€¢&9D"dÖSàÆØcp¥GÜÒ•›’^V</ÇïO éçX–¸8áŽê¶!š +\^†š#êE8ÿ +ç.KY—þùû“8o'ä=õÊÔ%‹‰Wb<!žÿÅyï”Åé«¥4rŒ#ÅóÞ«§$ö‰¹òç>„H"±E°“(SÔ(ÌxÂázÒ$‰&©)í¥ ŒJÑW’OÞùûhÖÌY$”ôé¤JƽÈ!õv:É›OÄ#Šja
Å8‰”CÛ1Z!VAëkÐr$"çPÂñ@»Ü?ÚÅIÉ`ÅŠ2ˆx*ƒdÀat3â0X
Îa–Ì8TFÉÌŠõ¼+<ñö¨ìÈÛfïpõþDî¶l[Wd†¬kgêüz2_Åb$ðPÎW‰ëh†ò4¾‡#ÑjÀŒÿ¨Œ £wñ‹üÄSUC*Ïå*ÞoxàÚwÝ74oïÀw¼¥¬üâ.°R£üšï…
ð^C&/Ã;þüŒ%÷羌ݷ~ý}®ƒ'¸W +´‰fˆ=0X´I¾CбEx·æÍN.‘^xÏ]iôñ³›õ>É4"4t„iÒüaaøÃüE¾ùAêR4‘>D'<Sáq?Ælö–4o-©«(ëÆ¥õÛ2ïÀ9¿Ã[! +ógÍíMÛ*øB–½– +õgBŸû“ÄØí7*½Ô¹+U:=zd0j17×ÓÌLo»Àc¡êlJ¶uås£^ñö3õŸNãugTGÌ€ÚSi«5ñÑÅ›Žú3íüXJ®òQÛåG\îúÍÌSì›X!fÞ£Q½]YG“:?£J©Õx`Ö¬¬pï?ùåæ?~Ó +ÁÛ«Oþ§j_eÉÃojÇÚ¾<!°èï—Æ6Eî«ãøóÚÝqÈ'F¢‘¨‰ÆŧãT¢×Þ¸ué¯âÛ¡ˆ¾h”ÿôíu£é=ÞÜÒ¦¨‘'RÿÎJ¾!ŠtQ„‚NÊœC:*«é
ù*UÊ4œ(jª¸± +åíº xChMA‚ÃûÝ;’¿*œXfD±Ë4·;¸k_¹ÖYÁâfÕ¨TüüzV é=ÌÁV0+×:ú²nÜ#‚ëuz¦>pŽöS
g®é\š=nXg›:"1òlWˆ¢¦kÀš±~)= ®œ°¡h¡·Sã‚[#"vUš·lÝRòú´ +gg6òÆ
HíçrŠd,Ú´Õ×àùèì™ÝX¢òÝ„¾}’_V·R¤ ±„Ja‘-§f—; þoëRŽ”…Of•Åîn¯#ÐØ$ïUÔ¤$úäª\BҶʯªE®6aíT¡&†¾?,‚·¨?,d«¨—Dtîzñ‘ªR³þ~Þ–k÷©>ÿ}ɦì¶3Ñkš²¦O
þmãÌ(Xñ»¥ë½/ŽûÐp#fZH\ÂñÍ“Sͧ¢BÇÅ$„Ž^<?£UÖc5cQY¬7_âàñÒ}íà +Z…§ú㩇.m +GÈ¿²ÇAÙšù?©zo]±Ü¶'=2:yÕ¥C—Ï ÿë°ƒ¿rêGth]Û-oôÊÞ¾q¶
Ųñ&Ì't&„DÇì’O¡DVœã±è{)‚$)nbÇè'ô÷Ó/Iô÷¤€á!!ÃBÛíŠÔ€ ãLãÇw$0ŒúÍîÕ}Óóÿnjz~Yh†±<±ùìW}PUÇ?wwï{€ˆ€F4ƼAƒJ©eT‹–*ZúüBÊ ?FÑØ–P
!V,c‰˜c¨UòBˆAƒŒI‹d:ÖIˆ5‘Xjk¬–Á:F[c©Â}ý}}MÚÿ:SßÌoξý8»çì7eêÌïœõSUnyKKÞ1ÚX.¯øY¬óÂpŸ!aÙùWksÞØwÒŠ"ã’5À¼Ô•d´Yá¾UƬê©o3<Â_߈c.nf˜¯~ùHæï§|aÁÞrÌõLŒÏÏðt¬œ–‚ÍVÏMKúô_7‰Ôý3§½ÿ³îF‘mŒNÿaEw£¢ê_OJ\Ô/ÚçÆ>·nÁOùÀø +wCáº3oî'‘bLkÜ +öþÓGdGS +V÷õ½Ëè6kÈéÏRŠuébû¦ç+Ë:.FíÂù¯¾’¹ø`Uõ¼9B}iýñÅò‹FŸŠRë¼÷ÈŠ'–®ümã'O.çcE«¹út~9ÆÏøÿ.ÇÜÜñZ]w¥yòÀWrGB´Ž„0½öðÏwÀíÄ°ò‡~T`ˆ¶OaClò¼Œì´‚Ó¿oE‹M-Ïÿüï†0ñ½T8?#gõÑ÷—Í{r±Ïç¢I…³Ïþ÷éÛ¦÷ÒäY0á‘™Ó<)3"3–5t_WtbÍä !XŸímœ[¹ã-?ngÍdo•rÑ–µ¢¡â©g*Ï/*ÿøG¿úéâe%î%ÑQ?.Iœi„¯Ÿ“1¥~Iù¤Ù &}÷égß|ôõï¥%%ãY8»Åx;D±«+^”a:ÃŒOÐo7}·¢81ÛºV_?{¾!,kº{òè HcŒÈ*»1ø!«µ¬»yÅ‚Hþ¶@F<‡øëÉ»PÊ•y÷œG-o³¶z:ó_õ€ŸÆ;xù¿kÚ[!fcmXzk{½äQ+§Ú*zÇPCœf`„¦¨Ÿ|݃ÓKM:Žáf=Vú^Rl
ýµ†þ=Ò¬·Ží9ÑÇT2ü‚Ç:Zw¯
ú·Ê6HÒÊzÅ™Qã‡OìŽDÛ5.&NRWWTÂÈx©ìwÜŠ¼(nïsk#¹Õª5ÜÍ-¡C•Š9ÖddZ
Í„VòÛPÞ}Ãr©Žœf0®‹ «Ú5Öœip|†X.Ô¢|~a_uÂígl³¢×Ÿ,&>¦hŠÛZóž1 ¯ÃìgWt3Ó:¼-|Ûaiu]8aPœŒà“¢îɵÐÈߌ.1ž¿ôäÚîÝ"½ë=‘Õ}ZFÈÖ®ƒeqrjÅ ÎÈÔγQwÉ´w=²Ã/ÿZ'î,DþéØøJU2HãêôÃ[õ›ô%
þüýƒJË3ùdµt7f¸‰=+6v7£cŸÕbÕfé^¿Ÿ˜ŠåÏêWαÀt:€ËkP)»jG¥™5”o´QÈ¥2 BΧT³€Ú&)ã¨rty?Ç|~ÖÙ@ x€<{l)ÅóyY`„²–²’Jœª3£)BUR“ºFYfd05Évj2‹ð5‰Hà4
Pô¡&g,ƺ¨É@YªÐ–;0vƒ +ÔXŠ67ÐÕIá΢U®Ê)v´È +÷Óäò}È$ò`¹*ƒjœ.ªf8b)UL¥M2ŠÌBjwœ£ >§c3¹õ]ú +{§ÐlõÅaN“©(Tý€šåpœ}ÍvÑÇvز‹¢±_sO눣Bæ ô´š£(þÈ2Ì3à8Úã+Þ׹Ȅ=à0ÇlÈòÀ×\ õ©·hûïÞXbµ@÷r±‰2j-î`û5/Û(ëÓ÷÷||¶d€ÏˆHopí!Úv|W=`nˆNìÑ@ÃE!MyeTÑ*1™Ü†‡âð}—dp'-#aWs–yÃüdŽ0?CUìÃÙµ
à8óÌŽ›`ñ m—á»ËT_lp&;©˜ã’9mb›×ÑRÌÕ¶€;½%óNóé’cÑLÖr¨Žö‡ë›%Ç-Ï¿§DL3G!‡Bºà×ãàm#|Û’ýlA¶ãÿø4r¯BlÀåœ8u.@<j '`Þ6[nf)2}ýb#öé²÷ë%Õ)ïÉž¶Î!ˆ‘Þ’ó +Çv/ùrϽõ–œt€”3|’ÿë˜FÌý§’sç[°ùq‹'—a‡}:Sö™£{ÎÂùVÄÒÇ"Ö{ +s2/ÔÞ#Ž±Þ#â5Èo«9ßÛà¨ò¶ŠaÞý<yøü€!Ç©:Äû™oÓ!Ö-†á¿c4È9ò&þ DÐ."iŒŠ£Q*ÂÑŸš2ÈO¥ˆû¥?:_¤LYþí ç ó
õKªä>µí‘d‚ëy\n¦Tž£vÓB=o,½!»¼–Ú‰v<õ‘å4‹ÇcÂT-í–oÓUŠµhë4Kq³)ØA´Ý‘Où°ñ’Þ‹ï’ût¬¿Ÿ5‚WÁ{øŽÏé<E¡Î³û¢™kê9Š3ß²óÂ6üG½â5f%î:_x;ÔÊ6-ô¼Æ\\«öÙyëu,s¾/T1tG5ʼ‚y3s_F};‰öëíHÆ\®‡ˆõ€ºíÒq»µ5ü³áOŽ¹NRr+¥©ôò:d…š;!wÚõ€¥]çd +¹˜Wæ*´Q£Ô1Œm„Ÿ–#¶£½Ÿ\æ^HÒóÝŽHy“ãü%¼Âl=Ì3Ô‡›B+1¿cØ[þœÅ~ò7ð“vÙ|î-{øó8ç®6ÇK·È“x— µc5ÞC¹Fœƒ/WS¥¨ÄšÁ'Çhž3ù/¹0q3œªUmÐÁ@»rœaÀ9N#g®f)öƒè[÷À®»àSœÐáþFšäÚhú*ÄÀ¯ÁTkzá<¬NðN“
½ð;?ài†ßƨ˜?ªlül"ÇN೯‡zœ¨¬¸ú€§€ñ–Äs4ð +y€<@ ¥y—Ty†<AºTùß²&a˜ßÌÎ×]·UÄŸ×ÀÏëà—ÀÔ£WdFµKxßô8¢Fô¸B×Ñgà*â_kÔ¨\®ƒï_à=q?Ö¹vú gÊ)>rw8´zNŸã|®xj6Æí·Â#c·Æ*§Í¦ÍñjÅVçW°•BìN²6'’yc]°bgU&ke—læœ.äï>É$N'³¦/<Égw¥1iÊ¡z ¡Œªà+ÐÚ¥!d@-üÖ¤XŒš¹Ï˜’¡
ÔÑž¶¨gÁ³àòT¾o™ÑöU+#^Î\à®ðžÀ +ìÎÏ/3PŽ:¹¹…§}^9Íùžn×°––ˆl”¢ŸœµOBl”âœQów"=xzĦå„SYçÇÿý‹~ +H‰\”ÙŠÛ0†ïýºœ¹¼HGÊ@0d™@.ºÐ´àØJjhl£8yû*úÂj°áCË¿Àq¾Ùo÷C?«ü{ÛƒŸÕ©ºà¯ã-´^ý¹²²R]ßÎOJßöÒLYî×Ù_öÃiÌ–K•ÿˆ‹×9ÜÕ˪þ5Ë¿…·~8«—_›Ã«Ê·iúã/~˜U¡êZuþ/úÒL_›‹Wy:ö¶ïâz?ßßâ™;~Þ'¯ªÄ%fÚ±óשi}h†³Ï–E|jµÜŧÎüÐý·.±ã©ýÝ„´]ÇíEQu"•…4´ƒ6‰ÊÚB%ôq§æÎR +Ú@ï‰*ôz;
;+Ô
ꕃ´€z‡,´†zæ©GCMCMC†h7Ñ"‘HãZpq-¸Ö¸\k\®5>Ÿz9h, +‹‚AÁ¢`P°(z±ôbгèô,z†–,-Z²´dðbŸ^> 5Dƒ–…-
+
Z´4(4èhPHäH$$r$9 ‰‰„DŽDB"G"!‘#‘È‘hÁÚ +Z?YÇ1yÎÃc`â\«Ïilo!ÄALß&ð1{ýà?ÿÓ8©xêñf +H‰j +H‰dVXTÇž3wî.‚ +»°¬HX®@MU–e°Uëã«FD@>šP?EEŸŒ/4¾¨5 +–‹FIâƒúˆøâ3ZãcµECˆZe•š¨A²ì=sªùºûÍ;3çüçœÿœ³!^d%‘ŸÜ?jñk¥ðMŽŒé³ó³^y?&Ä/jÆ´ÉSo}s÷ !º7ð]Ì|¡“´óq‚ë>3ræõoyç>®ó‘îÎÎÍœÜ$ß‹'ÄF<Í™œ7—Þ!Ç1ŽÁó¡s&çLË<0×Ùx~;‘X*M#2ar™lÆ{=3
&Y4Ë‹R-e”PŠXÞ—ŸqãÆ“¡$´j!Õ^kèðPT)ö‘wm¤sÝõðÿkJvu<†ÓrJ÷ÅmE2Ka–èsT !@Å'ƒŸ.’”?$1vImΤ$kìø$ë ân0ÉgÛäí8‡xîjIñW‡Õ¬³¤'–ßlå&gÊŸ“I»õ~lmr&î÷CJeb³;kpK¬TÈŸoà«a™ {ðbñçб‡óV˜Š‘AOø+þfÛÞ¬|ÓŠ;ÅPOÒêŽÅd(¦ +ÔWW{'uØaqôù+–9âSRãã“'%[ã'ÄVíIè°³¾r
ñ&„ÈaTçGÌ¡øð÷£ +Φ(íowB·ÐÈÉ+à?‚ƹKá}·Â·òeô6„€Þ}Öý˜š„þ8Ž2„˜-c‰ŽP´ªƒÉ0ö®]¾|ñéC5¯<¬ÜÃÏÓ§¡bõñ…3—íúgÁcÅü§rÞÀ.11Q^/NˆÕhŽÒ[”0‹FÆsA¼¦0Z4† +úh'úÈ@H¸F U]e4 Kˆ! +#n¬+?q›7üíµÊ!©°†ÃDø"îéÛü»vož¦zqËóTûýTÔ‚&’ Óå ‰ð‰¼òlŒÜÑ.—¹GòžËl.½Z[ +>¡ +žòžÉ‹ÙxšÍÕÂF<gåÉ(O¢|l¸{ŠÃA+þCsÜ"¤ÝôgVçy¨Rs‘˜uG"J¤sGªÇÙ³ƒè%·›»ôh.àîkBO´ÕŠÑE° Ð àA Ñc“Nnì&1C +‹a”T²}ö€9Qí,¸Wé’o]År™ëÝ‚‘y‰ÒzDá±Fpĵü\x„EX5ÉÛ×[Û£Þ¤ùýţ™…ýÍnW:â|6:dÌŸ¤"Õ*x Føˆì“=<PŸF
z‘:~”ºø5¾–Áï ,â¼þbKË™KŽ¦ (A.¤A%ÏåµüS>µñ†?á·@ÿPèÕÉ&xá-ЂÀ…†“—†*œh/þÕ;¶ìÙù!en—\ö°þ*Amn×ÚUù«R^¡"íIz#g1·úü,} 6šJËOó&„¼Þƒ1‹Zù[[žž¾ä¸ïÍ·ÀïµP +±èð*žÃOòfþÛŒ°Ÿñ»»‚»PW"j=Vn¤q„¢¨È;3Ñè]è¥5ûG/Ÿã€oî½Øµ#}T£›Õ.,]»*öºk岿)½þZÊû±¿ó¸õÙ™s1zÙvé<Z†ÕIˆõåDF`mêcö¤ ¨JFOº‡E佚Ñ4ß'ƒïÍc+W™µ"eÏ©=¼µ5íJ°!‰5c—¼=±nCÍ«3kj⸙i™-8ÞhF=ØqØ(5#=~ǪO«Ÿ`"™ÝÌl6•±¢n;3C”,CÍRÿSÐÀtƒVî泜ȺaC¬,^ÍÌríA¼¬ÞSë¼r¿kÖDr;ê§eÝ|ùsþ/>øôÔh˜Lô¸Áü€:%{Ü'ź‚PI‹%+6“õh·Ç'N`‚4B[ãÉôpLt[ Wòj¯’Ý‘ìM›m +›eK‘ÞdAXÙ°zš,ŠZöýÂã՞ƒÝJš®ºo¡'Ù¬sí‡ñÐïìñò؆?@6=yÒ[Ó×ïÙ]¿ìÛ÷Úü+Ê >×½ê{ŒM:acvºÐS´@~Œ~xQ)QRÌسôس”0©SÚd`³ÛY~ã×ß»NælÌ~¿t}^Þ¶¼íž{Š?²wðËtÔºœçŽmÙ§vä$´ažjƒ¨ÎaÄ‚]ö%5°:Kó¸ÏBçæ¬Üe›¶åÝ%ýF€éH00º1©n×ÇÇRJ”Ä,](=Þ j4Šâ%½Ú¥6çÞ™G@êÏObö%³VmÞ˜—»£ò8è`ÞNg9hêì²3vî?´Ñ#[jC”:Q;@oŠ²T°B¼Þ`ˆD#'~«eoá¦ïuxãb}sSCz¡?œä÷¦|• +Æ6Drçýûëç˺QÃÄ¿@lƒÙ 2O±˜Õÿ%FÚ8(¦òÁƒæÏ?¿úIr´Ü?è̆ZW4ªv[Õ%½ÀÄC˜1õ&‘è;Ñç#-žH{L÷ÓÓ-æŸYÎ,üTWZ]U}˜-¸U÷ßü*]°9{uIñ¢Ee`¨Öqü‹Ìp¼ zû +ž’S~æh顃Åw2´/úYÿ_Þ«>(ªëŠŸ{ß}o¤¸ Htx€:ˆfY?bÀ-Ä©Q]»¬kaýÀªã0Äâ˜:¶A³ÍPG u0µtM6Ö–qŒu¬“8elµN§P©c‰%Ôt/=÷í[‚ÔÎ$DÎü¸çí»çÜsî9÷žóĽoª£B —³´ä››0ê{ÚÏR+ù®×ðað=ö]4k÷p*i“‡ðŠs\†×d‰Yh³-\d³ígw²®´d|™À°gCÙÑrž¨ËÆ?-;Ed¢îT昖ù7..]‘g^ë¯-g˜?œvå…cG¤á?ùèO„¨0)A_D?#%ðZ‘ÌXfò<ÒGyŒ<øŸlÒÃã÷tIÒ(†*§·_|úå(Æ&Q«³ôMÛ¬Xm³â´*w¾Z·nwÿ•ò\ËÝ[ñŽºõï¤æj>µ-ÐMK‰âÝèfà=·¹ü +ßh +Ùœªåãøµ¨Q²^«lFe[n’Rº„L§!àgpâ·¼L€8)n”žSEg<s¢’‚y¢¢ÉtÍ?x?I<"‘üöý¦cÇ_#ñ?'Óþ‰ÍËL~÷ñ¿ùŸ¤´Ÿè"åï‹;‚¿Àö£NýŽó2:Öôì;bÇÍÿÊoø¿º#°éC#ïŒÿ#µØrD\¿zKY´–/³žÚÃ8:h)pìAuyç«RbÊé×\¾)v©O- MªÞ‡ŠÏK‹ž—²×ZN®Ø{dÃεµû–ÍÛ÷“ú?_x3ñÖ†ÚÌìy¯4;žI½¾üåô¹‹æ-|³¢åWBÆh?õãZL°³ŒÒή9Jœcíê¢þÜjÞÓÑ1ðŹß)=<…Xi‚p9¿æç&û*ñ™01´HŠƒ‹Z2£LÁ4Ž’RÙ¦«üðýÞªý÷ZMNcëö>|d-Ç!Xј¥EEK!™S´J4%“îáüÖ4›<õ.îGÀVZT–KÏj2xnŠ2¢š¥HÁ®}œlhd½ÃçÃŒ,lÒ•!ÞóȦ(JDÏnŨÂ;oÓv5/gV u§ÍxååÙô“@jÜJk2í+Œré!® îJ"—Ÿ„$Yø3RÂ??k˜ÁÂ"¾æÃo§õÜG";ã#YxÒ9Ni +Œ±Gê„Ü“6\£µ¡Ÿ Ð* ¤A!u@Ô +;1‡µü»"OE®Ú¡ÞÐ +ò§tÞ +À
µ4À”Wa)>Õ!/þÛ5½bÆMªIÅßÅšUø®^{râèÄq›¶¾˜YŒ\%Ê9“’ñɥͫy4|[ƒclÆßÜh‰ +%¨ÏùìY
k¹˜Ÿ%úÕŠèg±¦ßñ¹W³iï¶"/ÖüúrßÆÌç°3ÿ` +0000000016 00000 n
+0000000112 00000 n
+0000045968 00000 n
+0000000000 00000 f
+0000046019 00000 n
+0000046517 00000 n
+0000054429 00000 n
+0000056144 00000 n
+0000056814 00000 n
+0000089522 00000 n
+0000089637 00000 n
+0000069062 00000 n
+0000069198 00000 n
+0000069325 00000 n
+0000057522 00000 n
+0000057173 00000 n
+0000054485 00000 n
+0000054847 00000 n
+0000055208 00000 n
+0000055569 00000 n
+0000056926 00000 n
+0000057100 00000 n
+0000056002 00000 n
+0000057027 00000 n
+0000056954 00000 n
+0000055929 00000 n
+0000056217 00000 n
+0000056424 00000 n
+0000056679 00000 n
+0000056312 00000 n
+0000056732 00000 n
+0000057315 00000 n
+0000057410 00000 n
+0000083527 00000 n
+0000083552 00000 n
+0000077005 00000 n
+0000077030 00000 n
+0000069457 00000 n
+0000069482 00000 n
+0000070082 00000 n
+0000070556 00000 n
+0000070625 00000 n
+0000070888 00000 n
+0000070967 00000 n
+0000077563 00000 n
+0000077976 00000 n
+0000078045 00000 n
+0000078303 00000 n
+0000078382 00000 n
+0000084090 00000 n
+0000084519 00000 n
+0000084588 00000 n
+0000084863 00000 n
+0000084942 00000 n
+0000089748 00000 n
+trailer
<</Size 56/Root 1 0 R/Info 55 0 R/ID[<9ACF01BAB32244F184A6B6A3D6DB10C2><BD2963D24D474598BA7FB4CC0AD67B3F>]>>
startxref
89924
%%EOF
2 0 obj
<</Length 47827/Subtype/XML/Type/Metadata>>stream
+<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?> +<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 4.2.1-c043 52.372728, 2009/01/18-15:56:37 "> + <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> + <rdf:Description rdf:about="" + xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" + xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" + xmlns:stEvt="http://ns.adobe.com/xap/1.0/sType/ResourceEvent#" + xmlns:stMfs="http://ns.adobe.com/xap/1.0/sType/ManifestItem#"> + <xmpMM:InstanceID>uuid:7e7b597d-426f-3642-8dca-bcbf37236e1d</xmpMM:InstanceID> + <xmpMM:DocumentID>xmp.did:89321C534E266811A613EDAC20FB34D2</xmpMM:DocumentID> + <xmpMM:OriginalDocumentID>adobe:docid:indd:924fbc79-cadb-11de-af61-e97e2740acd1</xmpMM:OriginalDocumentID> + <xmpMM:RenditionClass>proof:pdf</xmpMM:RenditionClass> + <xmpMM:DerivedFrom rdf:parseType="Resource"> + <stRef:instanceID>xmp.iid:88321C534E266811A613EDAC20FB34D2</stRef:instanceID> + <stRef:documentID>adobe:docid:indd:924fbc79-cadb-11de-af61-e97e2740acd1</stRef:documentID> + <stRef:originalDocumentID>adobe:docid:indd:924fbc79-cadb-11de-af61-e97e2740acd1</stRef:originalDocumentID> + <stRef:renditionClass>default</stRef:renditionClass> + </xmpMM:DerivedFrom> + <xmpMM:History> + <rdf:Seq> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E4B6ED806F256811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T11:39:47-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E5B6ED806F256811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T11:39:47-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/metadata</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E6B6ED806F256811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T11:44:22-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:80321C534E266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T11:46:03-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:81321C534E266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T11:48-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:82321C534E266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T11:49:01-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:83321C534E266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T11:52:39-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:84321C534E266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T11:58:06-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:85321C534E266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T11:59:50-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:88321C534E266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T12:03:27-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/metadata</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:89321C534E266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T12:03:27-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:4A27385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T13:48:01-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:4B27385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T13:50:54-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:4C27385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T13:54-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:4D27385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T13:55:16-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:4E27385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T13:56:27-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:4F27385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T13:58:44-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:5027385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:05:30-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:5127385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:07:25-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:5227385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:12:43-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:5327385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:13:56-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:5427385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:16:22-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:DE855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:19:25-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:DF855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:27:07-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E0855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:29:58-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E1855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:32:34-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E2855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:33:46-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E3855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:40:42-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E4855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:41:28-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E5855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:42:42-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E6855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:44:36-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E7855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:47:08-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E8855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:51:29-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:80C8B5F5A22068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T10:49:23-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:81C8B5F5A22068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T10:50:43-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:82C8B5F5A22068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T10:52:12-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:00CECC59A92068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T10:53:23-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:01CECC59A92068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T10:53:56-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:02CECC59A92068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T10:56:41-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:03CECC59A92068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T11:03:21-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:04CECC59A92068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T11:06:47-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:05CECC59A92068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T11:09:26-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:06CECC59A92068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T11:11:53-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:07CECC59A92068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T11:13:29-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:999093B2AD2068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T14:21:34-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:9A9093B2AD2068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T14:27:38-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:9B9093B2AD2068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T14:30:31-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:371C0BE61C2368119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-07-02T14:20:55-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:381C0BE61C2368119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-07-02T14:26:33-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:391C0BE61C2368119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-07-02T14:29:07-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:3A1C0BE61C2368119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-07-02T14:31:19-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:7A0142B9242368119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-07-02T14:41:33-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:7B0142B9242368119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-07-02T14:44:10-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + </rdf:Seq> + </xmpMM:History> + <xmpMM:Manifest> + <rdf:Bag> + <rdf:li rdf:parseType="Resource"> + <stMfs:linkForm>ReferenceStream</stMfs:linkForm> + <xmpMM:placedXResolution>72.00</xmpMM:placedXResolution> + <xmpMM:placedYResolution>72.00</xmpMM:placedYResolution> + <xmpMM:placedResolutionUnit>Inches</xmpMM:placedResolutionUnit> + <stMfs:reference rdf:parseType="Resource"> + <stRef:instanceID>uuid:288c3c69-7dd6-7c4f-984d-b085b3307748</stRef:instanceID> + <stRef:documentID>uuid:93F9F49755C5DE1185BCB9A8461E73D9</stRef:documentID> + </stMfs:reference> + </rdf:li> + </rdf:Bag> + </xmpMM:Manifest> + </rdf:Description> + <rdf:Description rdf:about="" + xmlns:xmp="http://ns.adobe.com/xap/1.0/" + xmlns:xmpGImg="http://ns.adobe.com/xap/1.0/g/img/"> + <xmp:CreateDate>2010-07-02T15:32:26-07:00</xmp:CreateDate> + <xmp:ModifyDate>2010-07-02T15:32:59-07:00</xmp:ModifyDate> + <xmp:MetadataDate>2010-07-02T15:32:59-07:00</xmp:MetadataDate> + <xmp:CreatorTool>Adobe InDesign CS4 (6.0.5)</xmp:CreatorTool> + <xmp:Thumbnails> + <rdf:Alt> + <rdf:li rdf:parseType="Resource"> + <xmpGImg:format>JPEG</xmpGImg:format> + <xmpGImg:width>256</xmpGImg:width> + <xmpGImg:height>256</xmpGImg:height> + <xmpGImg:image>/9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA
AQBIAAAAAQAB/+4AE0Fkb2JlAGQAAAAAAQUAAjSA/9sAhAAKBwcHBwcKBwcKDgkJCQ4RDAsLDBEU
EBAQEBAUEQ8RERERDxERFxoaGhcRHyEhISEfKy0tLSsyMjIyMjIyMjIyAQsJCQ4MDh8XFx8rIx0j
KzIrKysrMjIyMjIyMjIyMjIyMjIyMjI+Pj4+PjJAQEBAQEBAQEBAQEBAQEBAQEBAQED/wAARCAC1
AQADAREAAhEBAxEB/8QBogAAAAcBAQEBAQAAAAAAAAAABAUDAgYBAAcICQoLAQACAgMBAQEBAQAA
AAAAAAABAAIDBAUGBwgJCgsQAAIBAwMCBAIGBwMEAgYCcwECAxEEAAUhEjFBUQYTYSJxgRQykaEH
FbFCI8FS0eEzFmLwJHKC8SVDNFOSorJjc8I1RCeTo7M2F1RkdMPS4ggmgwkKGBmElEVGpLRW01Uo
GvLj88TU5PRldYWVpbXF1eX1ZnaGlqa2xtbm9jdHV2d3h5ent8fX5/c4SFhoeIiYqLjI2Oj4KTlJ
WWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+hEAAgIBAgMFBQQFBgQIAwNtAQACEQMEIRIxQQVRE2Ei
BnGBkTKhsfAUwdHhI0IVUmJy8TMkNEOCFpJTJaJjssIHc9I14kSDF1STCAkKGBkmNkUaJ2R0VTfy
o7PDKCnT4/OElKS0xNTk9GV1hZWltcXV5fVGVmZ2hpamtsbW5vZHV2d3h5ent8fX5/c4SFhoeIiY
qLjI2Oj4OUlZaXmJmam5ydnp+So6SlpqeoqaqrrK2ur6/9oADAMBAAIRAxEAPwCReWvLfleTyzo9
zd6VYPJNY2zySy28JZ3aJGZmZkqSTlgApgSbTL/Dfk3/AKtOmf8ASNB/zRhoIsrk8reUZKlNH01q
deNrAf1JjQWymEXlLyYIk9TRdLDU35WsFfxjys82Y5L18peSmPFdE0tiewtLcn/k3gSubyd5OUcm
0LTFA7m0gA/5N4qt/wAKeSf+rLpX/SLb/wDVPFXf4U8k/wDVl0r/AKRbf/qnirX+FPJP/Vl0r/pF
t/8Aqnirf+E/JPT9C6V/0i2//VPFVK+8o+T4oeX6D01fiAqLOH+EeSgLLGRoJY3l7yWp4tpOmgjs
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
xV2KuxV2KpL5z/5Q/Xv+2bef8mJMVf/Z</xmpGImg:image> + </rdf:li> + </rdf:Alt> + </xmp:Thumbnails> + </rdf:Description> + <rdf:Description rdf:about="" + xmlns:idPriv="http://ns.adobe.com/xmp/InDesign/private"> + <idPriv:DocChangeCount>244</idPriv:DocChangeCount> + </rdf:Description> + <rdf:Description rdf:about="" + xmlns:dc="http://purl.org/dc/elements/1.1/"> + <dc:format>application/pdf</dc:format> + </rdf:Description> + <rdf:Description rdf:about="" + xmlns:pdf="http://ns.adobe.com/pdf/1.3/"> + <pdf:Producer>Adobe PDF Library 9.0</pdf:Producer> + <pdf:Trapped>False</pdf:Trapped> + </rdf:Description> + </rdf:RDF> +</x:xmpmeta> + + + + + + + + + + + + + + + + + + + + + +<?xpacket end="w"?>
endstream
endobj
3 0 obj
<</Count 2/Kids[59 0 R 5 0 R]/Type/Pages>>
endobj
40 0 obj
<</BaseFont/QTGHHB+Segoe-Bold/CIDSystemInfo 41 0 R/CIDToGIDMap/Identity/DW 1000/FontDescriptor 42 0 R/Subtype/CIDFontType2/Type/Font/W[3[276]6[592]11[369 369]14[707 271 404 271 443 575 575 575 575 575 575 575 575 575 575 271]31[707]33[707]36[703 641 624 737 532 520 711 766 317 445 649 511 957 790 758 614 758 636 536 586 723 667 1005 655 607]62[369]64[369]66[415 314 538 620 480 619 541 383 619 602 284 284 559 284 916 605 611 620]85[398 440 389 605 542 797 552 538]95[326]138[874]192[667]]>>
endobj
42 0 obj
<</Ascent 1065/CIDSet 43 0 R/CapHeight 700/Descent -282/Flags 4/FontBBox[-99 -282 1258 1065]/FontFamily(Segoe)/FontFile2 60 0 R/FontName/QTGHHB+Segoe-Bold/FontStretch/Normal/FontWeight 700/ItalicAngle 0/StemV 156/Type/FontDescriptor/XHeight 500>>
endobj
45 0 obj
<</BaseFont/SJATJX+Segoe/CIDSystemInfo 46 0 R/CIDToGIDMap/Identity/DW 1000/FontDescriptor 47 0 R/Subtype/CIDFontType2/Type/Font/W[3[274]6[591]11[302 302]15[217 400 217 390 539]24[539]31[684]33[684]36[645 573 619 701 506 488 686]44[266]47[471 898 748]51[560 754 575 497 524 687 621 934 590 553]68[505 584 458 585 515 313 585 566 242 242 497 242 861 566 578 584 585 348 390 339 566 479 723 459 484 452]138[890]192[555]]>>
endobj
47 0 obj
<</Ascent 1040/CIDSet 48 0 R/CapHeight 700/Descent -282/Flags 4/FontBBox[-152 -282 1171 1040]/FontFamily(Segoe)/FontFile2 61 0 R/FontName/SJATJX+Segoe/FontStretch/Normal/FontWeight 400/ItalicAngle 0/StemV 80/Type/FontDescriptor/XHeight 500>>
endobj
50 0 obj
<</BaseFont/UZUFLT+Segoe-Semibold/CIDSystemInfo 51 0 R/CIDToGIDMap/Identity/DW 1000/FontDescriptor 52 0 R/Subtype/CIDFontType2/Type/Font/W[3[275 298]6[588]15[234 402 234]19[558]21[558]28[558]31[702]33[702]36[668 604 621 721 517 505 700 738 294]47[489 935 774 753 583 753 601 510 549 710 641 969]61[582]68[505 603 470 603 527 347 603 584 266 266 533 266 889 585 594 603]85[370 407 368 585 507 760 500 511 458]139[888]190[613]]>>
endobj
52 0 obj
<</Ascent 924/CIDSet 53 0 R/CapHeight 700/Descent -236/Flags 4/FontBBox[-130 -236 1190 924]/FontFamily(Segoe Semibold)/FontFile2 62 0 R/FontName/UZUFLT+Segoe-Semibold/FontStretch/Normal/FontWeight 600/ItalicAngle 0/StemV 112/Type/FontDescriptor/XHeight 500>>
endobj
55 0 obj
<</CreationDate(D:20100702153226-07'00')/Creator(Adobe InDesign CS4 \(6.0.5\))/ModDate(D:20100702153259-07'00')/Producer(Adobe PDF Library 9.0)/Trapped/False>>
endobj
56 0 obj
<</BaseFont/LZSDPL+Segoe-Bold/DescendantFonts 197 0 R/Encoding/Identity-H/Subtype/Type0/ToUnicode 198 0 R/Type/Font>>
endobj
57 0 obj
<</BaseFont/JJYRNP+Segoe-Semibold/DescendantFonts 195 0 R/Encoding/Identity-H/Subtype/Type0/ToUnicode 196 0 R/Type/Font>>
endobj
58 0 obj
<</BaseFont/HTEFLT+Segoe/DescendantFonts 193 0 R/Encoding/Identity-H/Subtype/Type0/ToUnicode 194 0 R/Type/Font>>
endobj
59 0 obj
<</ArtBox[0.0 0.0 841.89 595.276]/BleedBox[0.0 0.0 841.89 595.276]/Contents 63 0 R/CropBox[0.0 0.0 841.89 595.276]/Group 64 0 R/MediaBox[0.0 0.0 841.89 595.276]/Parent 3 0 R/Resources<</ColorSpace<</CS0 85 0 R/CS1 100 0 R>>/ExtGState<</GS0 91 0 R/GS1 199 0 R/GS10 200 0 R/GS11 201 0 R/GS12 202 0 R/GS13 203 0 R/GS14 204 0 R/GS15 205 0 R/GS16 206 0 R/GS2 207 0 R/GS3 208 0 R/GS4 209 0 R/GS5 210 0 R/GS6 211 0 R/GS7 212 0 R/GS8 213 0 R/GS9 214 0 R>>/Font<</C2_0 56 0 R/C2_1 57 0 R/C2_2 58 0 R>>/ProcSet[/PDF/Text]/Properties<</MC0<</Metadata 192 0 R>>>>/Shading<</Sh0 139 0 R/Sh1 140 0 R/Sh10 141 0 R/Sh11 142 0 R/Sh12 143 0 R/Sh13 144 0 R/Sh14 145 0 R/Sh2 146 0 R/Sh3 147 0 R/Sh4 148 0 R/Sh5 149 0 R/Sh6 150 0 R/Sh7 151 0 R/Sh8 152 0 R/Sh9 153 0 R>>/XObject<</Fm0 65 0 R/Fm1 66 0 R/Fm10 67 0 R/Fm11 68 0 R/Fm12 69 0 R/Fm13 70 0 R/Fm14 71 0 R/Fm15 72 0 R/Fm16 73 0 R/Fm17 74 0 R/Fm2 75 0 R/Fm3 76 0 R/Fm4 77 0 R/Fm5 78 0 R/Fm6 79 0 R/Fm7 80 0 R/Fm8 81 0 R/Fm9 82 0 R>>>>/TrimBox[0.0 0.0 841.89 595.276]/Type/Page>>
endobj
60 0 obj
<</Filter/FlateDecode/Length 6532/Length1 11712>>stream
+H‰dVPTçþÏ}ìâ³ì‚à#*˲lª–ek}‰ ¥ê " +Ê +øFÅê +T!_AÒ¨ˆ–¨1Ô2¨”±JЊo4„cðE•Ä±ôEQqï¡ç¿»;™;wç¿{Ïã;ç|çœË€1æÅò˜ÈØô™¡áÙÛŠ³3¶Ð¿)éËsÒ|zV}IçíŒù}—±x¡ãnpËÆ‚ÆÓ‘ô‡®¡ÏçôL:,(cEVvyi]÷2ÖÇkùªÔ…lÌ’ÓŒù;è¹ÿŠ…Ù™âVÎØè2’X¹pÅâ=•÷Úè˜É˜¸œ „ƒ‰yB¡Ñ2fÓt&ƒÎ'2%O`ȘСèó ƒÌÄÖJ{å"6Œd´FEk>êm³Øèö±ˆü毤½æ3¶ÆÑW§]‹}wíSõz`C\CÜ#û¸}ok—FW?¯Æ£Èo:‚Kù]ýœŒ³ƒX#´É%¬=˜Î[ýÚñ,¼
›°è„|\#péèIgŽGÇ»WK˜ƒ5=Âñk`²`R\¸ +à1<€O0—´:˜Cª•,¬÷¤3êVƒÎ¢3Hµ˜{°å:äÃ#Ì…ü°›¹G€ÌÅëg¢ØáDqWš5ÐMïvAµP%ñw@–„*¥U0Bu+×Kêi‡FcýIÏWc4[#"-á~иdÖô˲øøŒ±óÃC§ÄΛOò==zñÅÃmÄ#Ê|,œ–K^dk> zLíi—ä*BîÃ#ÖjŒ:o[¤! +Vœ«‚c0£©¨èÏ7n}råì‹ýëó0á˜ëÖçÝÿë³$žŠD.U3¢w³†â +ÑÂXlÛWj†Ð(ˆgyPØIË›["§ŠÂi£±$Û1"s/rÿ7`;}ôgÂ*ßqJ4Jf‘û–{c»]Ç(Âör¹¹Vãžå¦ÞM úóÄåÁÏ_õ©Õ`]¯!¾xŸã±#ûÀVh“Ñ[3t$˜ ‰‰ïWŒu…‰—ÍŸÕÿÑEÙpU¦§eÍã=ÑT’ŸÞh~´l¥ÜVbr2ÜOò¢u“$Œ"yÑ·ƒX`™¾Ïõ”Lí ‰‹(‡p¶r\%`ÃÝl
ðlˆ +"›(KEœ(‚$„XêQA „Ã1ÔPk9Øq_jÝ©‰h
—CqÁPŽÇzRÎüô¿ïÍ $ÎÇ;̼{ÿåþÿ÷—‘蛺k]ð û÷ŠóÑ}Éû"C‰§+°~fÞ«Œ%x›héTÛ +çyŽ·HøuÍGÑÜ÷›ÅÑvîa,EuÙëܨû|ð9Ðáç⤶À¨\¡Üf¸½£‡ 8²Y\ì—Zäï‡õVÿùæFß¹Á>ûáqìÞ{àtRîü9;.jÖ‘ª¶Í{bÈâƒóÜýCüf/û”˜_ê÷…;1KBæÎZ”´*‡U,êqZ%²Õ(_ CdÂ9Ȧ[iÕ«\ZE’Æ’©M}‡Aã‹ÒC¦64Ná™+É8ì…\C_ èÿGHŒ‰+Ù„ˆ’@TÆ&E
{’Df9P¹Âž Þ€Õ9960$Jøžy‡ª2j#+ÒTÁ=&IzNPÁ.¨´‘QsÕKØå$ËJ.§„’Ä,(U]c›u!I)KõYh$äÝœèá¤~‘WfÜJá<ÚB•"óE[vÒéMÚ@¢ð…ÿµRR3‡!¬”NH&»o8ØPKçHh8rÛ>Ìy,àoð7@ã23Ž3ø±(ð‡>0æŽ`âF÷¤`œ?¢}"ŸBl~DÇ2€'CB“¡ß*k…;/*lÞNZ_Ÿ‘–ß +³Èn¼ËÈ¿ënco…â[Ž¦·Ô^*¼C8‚ÇíÛ¤ÎtÊ¢:™'Ð#hF¢LwA£o4ÐSÀÖûÒ&>^öHüÎ…8óñ}p8Ð&¤^¬~¿‘'‚Ž:àœt•»‹¤C”®®L;ªQÇ{MWÉL*H-èàÍìª{OCÒÈħŽæ¦“Ðs¦>|IÂf®ªeuüâ1ÏõhîàtGˆ(±·-P‡~ÌlíÂ^h•
K°Û¢’GK.vaKzËMl£àjî¾Já + [îvoLs^3SŠµ‰¹ÛxǺöÈEíµe}EËWV¾Ÿ¶ó(‹7#ªÀˆìÅÉ/3fø±ö*r¾¬ú¤©1ëŠÊ¢5¿ß¹MëXUÙK,j̇—áQ1å
áè5îGóÐk›1b¬„N㵨½Mý+²D\¡»;¶”–îøæZ%еumN~ÐÂÔäE\EsánBW_Sɧéå+×—¨\±4<ÊhÉ=·ûÂy¢³§¯Ýh¢XE® Ž†%1?º£²ïÕî²æO¾êÿp3Ük‹öóGš{c~ˆÜ·û%±®+=PzwÑýàÀDÌÊœqÎrʺ€ »vv^vŒæðe”»‚sOݳgpµ¥eã–Îä¥tØþóÜ~}¿0©¿äXŽÖ–ùNT‹þ9r³1Ê7ÙLÌ +oôÓKÍ’âö:+>T[Õ'¾ÙÞøÙWÇÒ·¯<ÞYòõ¹$–œ/Õþ)Ù…>~Ò·çÃ>mõ'IkâöŶۧĬ¾za 6yÙŠ#‡ŠÃ£j1’]ØuIâyˆ³X<TãØÇR¥IpõÈ*ïRÝ|I’8>ôá²ÀdÔ!†ÿ +ø?—‡9¸'{‚Ì5~¬ +Ø´½—¡‰]Ÿ³a2ÛCº|mJHXšákxäp2®uøÙZ[Qµ¨1\õ˜]VåõÇ-ñ>ôæ^e×Kÿ4mÈõï¹,¢rŒÈRœûF
ƒ„JË‘þNK-€c¹ +¦SÅÂY/SŠÇªôò¤
U5¨Gà~cÍ1«*ƒr—öñÖúêZâôö﩯ì'Ná+÷ƒŽ±xÐVÑ+ÇQ–1¹å)mýšc·Î˜8æÛ[¹ipîVꇛ׌2Œ¡MÖSß^[þ=±>X¤É);*E-8S±vf¼3ë!¿È¬-âv—8ò}Nµ¿…I”»pÓ’H22Szæ"ÅkÔ¸H(¤*šdÇzÓ¨„°ÜÂûMåõ{k¶û?½VRRPZì┼gqñ«NÌð&ÜÚµÞsç-ZQXÕîñ2ô½¹Síµ (my ž~.óµ$ÞTb§»ªX×ÛbÇòϗæfâÿøq‰§ÚÒ•¬!wú$Bg?¤f‰ãòñ|4Xó*ë‰âÀ–MÔ¸*ÛzˆK\ñç¾ ÇùC›n[&ÏìãBLêÀ4ã¡êàÑ´M“QÅ´xéÁw
»³W.Ïæ‹™]Ôòò\ùvm0Áô”Ç€:j¹Âª NA/YZa.—ˬþBæ4* +j¹‹íͯ^ée8‚62f†{òu†Œ) øfËL¬`Ž±¢9ÿq€EÜJb ºÚn"?ùúgɦƒŽ–T9åå@ixNlÝÕ³æA?ž‡‡~nó¼Ë߈ْeÀ–ÅÁ;KÔàëûf*RkàÖ¦è ð¢ù>J’/N0§“.QîU+h'ë]·”`8Ák™·ÝÈ=7äNÒ$G†¸¡G,®t䉼U¦%7™›Åy?Çî¼ØM{(ä*変ø¡ÂE¼²ºH×(pí¼<åÅg¡âÈIA‚{ì‚ZxÏ:ŽŸî –DN´Ï!Ò=4ü6YLÞ×%¨ë'æíEMtV‘FŠþ¤õÝÐATdýÉvø þÝ~œ¬oZB=Ÿ÷¥¶mÞclÎÀiÄØõ—ìúÖ E2âb6dFÇn˜W‰?,ywaåÓ§p¹¥%G{}Íâ1L=4õó¼GúG”GÒðý™ùPótI"OËi‚‰kva=ƒÃ +›Þ'þQmäõÍOùNG +Â9ÚIlæã˜ÿù|ÇGÚü +r¤`0*ƾj´Š +×û°ÕùVÚ?C\-GºƒD¡Õ*û(n«É˜dÍB'å*«Ã¿@û*âÑLì!&ÝD’¨#j‰±—¾öÑ’qDZ;wa—}»˜}ú±À¥è¶aÃzµÝV'Ší鬇n÷(ºZ¢ +Pfô‹È©*¤U•¿U·=çÆ‘ÓWˆwØÎ~bgMeÿÖXãQʶz´S‡ýºƿo]ÆÓœ÷µ)ãœÿŒÙ7!û–=ìIÖoÖô˜5Æÿ\Ó|®¯—ø!Ñ3¸¶¡u=볘cEÐÊóé!:h·êpPb•í çô£Ý`2ªfÌ°Žc¿xo»[ý~Y§³=Ï ©pŒRÝ˹»PfOD…çîæþöãˆÅxµŽ ÊñPëä^Þ!v *Ü3c”c¥ð„ãˆ_žÑGP!pb‡ptÀW2¯›#’Ü9,QAîÖT-êˆ
2ž~ƒíô»œ½ºàW?ÕP! 7J²ÃËZ¬dÿ•‘‘作Ïb@ +È¿µÛ—8GüÕì=€áZ +ïŸÞGJ,Ú{„=Šõâøã¥ÄÄÄûI‰i‰+JèÛ(¢O¯“·ß£Ÿ£”ý,ß¡¼Äò!{Œçiöé@Zò€Ä¢ÉŒGƾØr»‘·òõÖfÎø’˜*íþ™Á:É%Œ‘¡RòŠÄöYœÛš’Ì?&ˆ<H–ML3æþU)¹ËäüäI’k ÎÑÄ#c*Xó¤µïè»ï[•þ
û—ˆ°¼ÚžãŸw?柷vùœùW9þ ç–^uѧ‡c%ùkÿ”üó¼†R9/g¨ÖÓïvžp{X·”í͘-mN”úˆ—ð ý:¢ú:Ÿ—;ñœýæÁWè_ƽÄìÇ~ +ÏZobž~—<íÂ>ýGl“:ýÏŒqÆúji·¾‹˜ØHÙØu²= [ߤlñg]Âç¤Íä˜>ì°nb>ÛªiS"c:Šz‹ßË<Ôæ¼*sùoK½É…ÒÎ:“wGp½r< ÿè;Ygøó^öï“éfo㜠ù¼ >2÷û8åô7ÇpÿìßÓ_&o–æýbütãÌ]ååóº3ž}nåï9á…ó-æPÞQηhaŽþ:íG#êN£í}³®åáv¶G1ÒÄí¯Q£3×TÓwQ(1ç¼0cv±m“v—Pà|Š²7¸D÷œu˜ó“WN¹ü%¾bÄî<ýD—º=EÎ×òãoÝ1Ô_ÂDçA‘ÌmÆžñÎqÎõ[Ú0žÍÜÂY™~²¶ 7Àç¡r€ß&Kîbþæ»CÞ#t7%ëóÍ|@î¨H}Ó‡Võ2Fè¢oøN19ð„É…;Ýz¬Ð—ñMÅ|( ~œrƒFˆo„ÐMæÈÌŸ+(×ÈËHÅøæsñi>½1_àBÎÊã¡¿0 +H‰tV{XTÇŸ3wöá{ØE#Ëò¨µBda×(h‰µºÁ
‚D|" +> ‚Zå!"ˆ+¢U¢[>‚” +¨_+>ªUC‰6ñm4úÅ›SîØswÁ˜?úí7{ïÌœ9çwÎù3— + áwÖãЙtöa8zÁÀòµ¼'܆󎨬È.ËFïråDþ\,Y–žÈKQÏΔËyû +ž +ùÒX£—þJ¸ŽfÈ.ÞD#Ñj?œè‰Zü£–"~ ÆóÞñTA•Ìs¸‚À®¸ö ÷„ªï<àE`â-Å`¢zñ5¯€õð^C&/Â3¾ü“GRN¼Ñ>´nÝ#®oq¯ºhÍö@¤£u⪇®Íº5ož™\&ðœ‹\ïéh4hÁ<Åß/$ÄÏÊ\¿ÐP|„xóè“0qIz@ÂÑl¥52ëë4ù)¾‘o¾zdudÑHȨÎ×G2
‚Jç¡Æ!ôämºyy]îÎÌ;pÎÆïð«0FÑ6žÓ\SÙ+¡ðü QMÄ"ñ¢«DhÑõ¹Øõi
Æ @_}€BÓèÔˆÖU+´nÜù²%¾¸¬¼>jaƒì ŸL6ý';ê/nÚ5¾&¦f×öY¤×öòù,+á«HKb3$ÎxChðÇ’zŽ +ÄLš“µÁð°”—3~ñç²€²ÒO’¥[ÅÂêÏÍ%0N ¥ü=) +®„Èœ³‚AÝz)gÁÇW/W2§¦}â¡Â&êUsøA¿Á¬ß {Šx²ÌÚSHãÝÂ'x‰_¬
æ:œÈ0¢ïõYžj\ä +=ÔéÕ +gÇÓddþØzÇ@YsRÂÖµ{>ŽzÅ;ÎVï<ÎýzÄ(?²JfÎO?éËÔsc(¹ÁÇæŠO¸ØóÛ©ë˜7ß°]˜=7D-×{82‡&5>zO…\rÅțخŠïø•ÆÏn]ãÕÜý§~(;TZðøVy°åÒy˜¿¸\yèÂ;ËKb1è‰lz¢$*'tè‡DDí[—ÛxÏ…<ú²Vüëývp‡qôol½&³Š“©ow)ø!6Ô"œD-Kuö´Û‡pRTÒ›â
*»¨™È¬e\_†%Ô{¢¸·†Òz”/vÈÚèMåª}b.J8<Žž<×ýÏÕX9ìù-þŠ_?s¶ýLyv¸¦ãÅþòÒ‚ïmü"<ŒÏ8׬/Úf4%rŸ–ï
ƒ¢2HpTŽ7: 6¢íÃY‰¯2»gÄX)µÑÜîâŽ}yª½gI'MH",=$“V£–4i]
F䩶Ál¨3wàZ–)Ü…†€!ŠÑÃàlÎ¥TÆŽî®cÓüG6÷LB²
]¼þ×Â×½d¸Dœ%?×ì¤6È&]݇9Ë•¶/é?Gaý¶aÔX¿}Ý2k÷ÐK„ˆ#Ólêh¯~‰±z)æÈY…ª££6¼>cƒO³2kyí…Úšùó„ŽsÙy"¶»”Õm0B<ùÑLÔÃ˪0#*{§VÉg¯Þ¼xA…åïIzc”UñÎaæS$]{ýg5§a6J¯¬Ý±õñþ8oÇí§Ûó‘R·x¦‰WÂoèåK3¯Üæ«ùqy°”7`ª:T”èó"Ò
w{õú¼õ¢·ò„@i +E¶žž™¿ÇÕÿZ›t¢ÈÆJóŸÜÍ=F ¶N¬Y“«ÜðdîtLÊñÕ~)ÖéØÏÊЯQ}ýÌzá!u4_l¾&©Ÿ9ˆ§qqÕJ?¡,yÓ÷æóþ¡‹c,à2mâŸþ\žuílôšºMÓ§…ÿX;3 +–_².À£e¼—îæ‚ðI±
?Y‘l82~ABè¸è¸¹‹Ñ:ZeíIª ½Ñù"Éh—Q‰«UX
í(5HŠ<vm$¥ãÁÚÅ{â6X‰6&¥Ó„¤žƒ<ª„5xÎ µ?vÔ¨t;ôQ“=;Äÿž‚|çþLé%HìDdN¡ñà a,YŠ +r[ëà88Èm'ù[r÷>±|Åþog)\øÍs|AŒu–36&•’1Wð–´3·°ßMŸÚ`ºO†ÍšÇftWO7D2s¯5fEkš>¾Û½cY¯òú!N¬¿¯¾÷øÔkàýž†y…±ç õvóú¾ø½A[¹2pì_è? ½ˆí`|ŠA,÷µqÃß`ò`
àf¬À4±ƒòÄ4ÉÓHí÷g²#ƒ¹á
¢—°éíhÊÛ[…|2J©Z¡KÔ°_ƒBF%[q½|Îlˆ +·5__µ{xèÿدö ¨®3þsï]ä¹QIÊ"!† Š""EðŠˆ‘Pdu—§º« >‚#1(&$>Æ*]dÇ$”¬8-u:h5„ZÇc”§C“8Êú»X_™ñüÑÖÝùÝóÝ{Î÷8ïqÊLuO‘‹M…{Wn}‹H?¾ÿvÕëWCßJxùÈ6¾*¡¸é‡TTŽ—(ÇÓ3Ä“¿Ð%ÐCÁ³šúûÍÍÍyéñR†÷¥ƒUUºªú£YÉ~fÒ˜¨F+Çsïöw÷•+$ÇðªÈrBB‡–eèèˆjëö· eâºoOšJ^Ûxù¼^^œò÷–¤Ù¾ãX’õÜKæ,²{íéÊ7¿&ÂÞƒõ;çß{5uYÁš³îàö×cîº-Ÿž›ÜeéÊñÑz·Íÿ,y9KÉ%’4D-ûÕ«H~ËDÛ«QH¶t #†?#Õ§ÀóOvTФ¨¨IAQO›Í’1hvä” Y³îèEœõ`8óQ8ÇÝÇé>\%zÜ##Ïð»Ø˜…s¯Ú‰ªfƒÛ+~±/ˆdýv³q–ã‚Ÿm"èÂÂí°H~æIóEæä&-݈"ÝLcã"qÈ5”ÙãÌfÀW[*wf‚-sÛ¥‡ý:yÚÜÌ‹¯–*ÅZ’_cî+˜‹ÊVÿ5?1þ™¢¯HÐøÎ?µÍÚJ³HPÚ+5ÖVê>‰ŒXÞ«¨Øz†wÁNøO¾e‡Q`ñ•£ +ÚíðúÌÄvÈ«J@4a¥spÀBØ¿;ü@Œ@Õg~ŽÔãØà”†hC0tè
¤GÝpFûœ7"Þ^ƒ®ÚëªF˜' +í +-ÂX:J¡UHû)´èé‹óòròLyz^gÒij§†‡‡MÑFçdë´‹ŒkŒ¦ÒBƒv®±¨ÐX¤3å×LÖF¯Z¥-ÊËÉ5k‹Å†¢õýdm²!ÇhhÔækuZS‘NoX+*гµ)¹†‡ËIŽ‹N‰K”I?¶T˜yƒ0!6€ô Eèð]‡ÔQÄTÇ–ðÓ ÿ!ø-y²å‹Àk&(…Bä×Â\|+Bš?u²\>b²Ìµ +ÿZüÎuæb_±üfÀÖ€ízY?™ŒTò|'à[ž<Žk3É2õØ»Û"(ÀoF´D)(ÏðXö$CZ”‚Ï4ÑI2µ-å5êñ¿ÿü3âþ!.'»@QÚ'…à{ƒ¥ã!›f«)%Q‘¥öU‚ÝoÑâ„Å0\îR•È| QýÑì·9š´â…ˆ-èعÜ-ò{ðVËÜmŸåöJ °Nk»c¦šû0÷3›OâSý†ïŽÍ¬“µ8fû¶ò£1(`³LáÍ‹NE,€‚ÇÅ6ð¡NU‰R=”nh ùP…ðR!^*…^b‰BTc»Vð¼ŽãS
ˆ,DÂaF•>="“ç¼R)qçrx+ÔB…ƒš¤ +Ò&hoƒÆ¡¼ÅVÄjЈÕà‹óèÔƒ=؆¢
=®õ‡$Ñ ÑõB#¤‰ÍH£[ T¦+¡žôã|ûÃQ>§ëUסža?òñq´ù} ‹~ØW-tƒ«Ô ã„&ð®‚+Þê¸þÒMØÆ þ|ÞòÜqÞ|ÎCs’íwR캲>÷mZ‰öýˆøÑ5lÛý@»ìGsîûjÜŸVD>ß! +̨#EL‡z¨ãPMx•B"”KeЫºNÜNÕ/ƒÐ¸ª(ÿsß}o¢IjÑ‚Ä! ÚfÓP¦Aj7Y„`ƒFj[™Å$„J:JUBR)&ˆÔPL£Ä`µZ¡´¥ÁEFpQlµÍ"„ b»(¥"©ÝHÄ0¯ß¹yÓÅ@ÑÅá¿sß}çÞsîÿŸófB}á.GÖ
]~†½»Õëï©Èšb¯Fÿš~ŒÚ8û°z“ÇÕŸLË—jg¿Aã^ðQÔˆñ?ñVÉG {3þ
þÁÑZ®lßü0V"8ܤÈÙ½*ðõ +Ø´`ù(ü7šnmý#MGÁf°@^oÀÛKäö)Ðò\ïð{”œ‚ç<Ú Ç˜C-@Á¨ ¬;‘á„¡+Ï»cì³–íW‡~9]ªC
A#õhuÅ´]‡'k÷VVB
+:øžña¬EÛ|Q[}E™/ÓS6'G÷o™~B-þC¥hþ}®£ø<ã¿Ð”Íù~Æ[Ãõýö<šÐ+¶ÆŸÒþ°n»ÎDkiÕÏ2îÔÑqí¶gÔ˜&ÿNE´×óîmµšÏxœûëÕ†DšNé1þö²{m.hý3rv ܇÷äÎΙ_Vcþwž]Q»qÍU1>›Õ…ü¦_Ù;ñw„ä^z׿®r\e³wâ~|X¯:ŸÕuÞZ¶z/ü>o0¦Gű®‡š{’þ¶Äøµ']¬µ~ˆÖ^ãBÐí$½µ~7ÁÇ2ù4ÍÊG“zÕËý
¾¨ÆxœÍúaÖç¢nŒWñcz”¿Æ³cäi +H‰lVXTÇž3wvñ»°,DSX®@MMX–UÀÔX£©FD@>‰Ÿ""> +¾>{~NêH§ôþ/&D;>mÖŒ”«ßÝxˆã§ð]x¾Ð +šEøìÄçÁiéYÙÃÚ¦Þ"Ä7€áÆüÌ™3½ã‹k¯íé3²Ðëd?!ƒp: Ș‘>‹íŠÆ¿^çpþv"cùå‡0þ÷™’êîûpTUŽh=pXLB`°9,Üê£÷VCÉáíËFÆÆEŒ‰†j¡Ók‰˜k>Y^;ä°mªíØû»ÖjDAôRšÅ¤4“ 4v,§ÕÂŽø¿ÄÚc«cî½pßÒé爩øS|UL«”:¢-B(â7ð5'·
Я +x¾ÜŠùcè‡Øƒx¤û²g½D/“µ>µßtàH 4Ñ=4_1õ%T„¦†™ï´nä'é‹>}Ž™=*>!**n²_œ%2frÄ…Ot·
Q5wâMˆ*j=‰) +ÖÙ«·CáèH2+añDƒfÐ+—NÈ•òiÕÍæ¯ø!Æ›¿"®¹)87Qžd³2_G¤|!7å$ˆÞ<ÁCÒd.nèåÔžFÖžQÀŒ +¿ŠYŸÃD{mÃÓfþ#×6Ìá—©or.ˆ…ú7ŸdðKí~/⬲Jp#^Äè±±ÑR²ÝN+Ðté}$\K§:R{æC’§§I»Ï.k גЄ#*×r·S´Üe²öŒªÏàè yŸ0‹µ¢¬1½L|¦pµª–>Ó{óè +>ÁÝ_í~â!=¬¿ú7°Æ +[¶Ï%#´«…
ô-]~ÅY¢*w.-x#;FX(\ldzá.ÿm<Ø,³š&eq×ôo…—iÎP-ëÛÊ‚F¼VëLBœÆùÿ³P¬°¡Š×¿@¯÷•3†ÊåuåTï“»'¥N~¯ƒ<ø=…%¼€7mk;öýŽlA¥%BÏäùG|ëäÍÿ~ȯ‚îg àÛ£:&«Î]F2ÎP$Nž¨±Ã¡Npãÿ|Ú°ckÝÎ÷)“œªò»MçùSj•œ…«sÖÈHy¥‚t +¼Ö{¼úƒý 2J´Ä̽(]Þ JÁ7ÈIOx¾ÞÑ,ãæ±{@šNOc¶Û[æÞ¼1;sGÕÐÙ»Á´ÎsxÓ„ùåÇ>ݹû³.ÛB'¢ÔÊ9tÆP‹^+›×éõ!èqÔÄï´ Ömúá^7_mj½ÓœTä‡ùÍä“ `ètBwÜZ¼Û±~‘ÌÜ‚ [ÔLþ’Ħכôò‰Í&åÌ@[†‡WݾÝúÉ'ç?ŒS
óûïUÕuÅϽᄋ‹XD)E†‡ˆe0 ’uýˆ¢ˆÄ-¥Áîò¡ÀX?ðc4Ã0Äb±ŽQ4Û%F©%ÆPÔÕªŒc¬µ6q¤tbiµ ‡C¬º—žûö-kg’?âžùí=ï½{Î=çÜ{î¹÷ÜN×S—”ìÚÛô§@ag hÓà%Œ8Ó¼”à™iëþÂõ„øž³~ß9¿»¹©¹•UÜ8ßË».äa~¹¦ª¾nýúwòpoéLìÎ;õ»_œ&Aÿ F2cßvžYzà\ÛîŽÕ »¸B§`œE½ðª¼7uiÞ×Öà¨è8|œ&‘:î6œ|Ç©®«îZmÿ®A%òÌBqžvâÄí5€Í¶XfϱXŽ÷°Ûi3g¥/5ÏL{Ê@œöé`.×eCFÊŽ+Q÷? ~HKB÷……KRLÙ¶áÚðû.O9°Gðú“ŠþŒ•)Òã‹8eI¡¼L,f,"Q<…t‘>$÷=M$<Ø}G—$ÕrŸ·â:{ä¾ÇA QöâÜ„k5u²¤¡`Ó‚¬e¨ÜòÓòŸmí¹œ[‰cÙ;ÞU×ÿ“¤Ó»j?Øàn§+‰âÜîngà<±6÷2Ïs×xmŽÖÖãð9jQ£”tµ°•ûœ¬¤óHØ»•nƒ¦?ð}D¦ØQÚÆ‹S¼'çÄ‘Eò¬M¦Y_ð2ÑÝOüøÍ»5¾ABÞ !þGª(~ûáøuiýÉÃM$·ù˜Ø#øö:êÔ÷ˆ!/Çù?Øôù'çÝ®oö<Vu¡‘w{ÿ™&UÛ#6‰ßz¼¥},P[/“GÄ0˜ö™Ó¬ÛP]Ê™¹ªyôM÷C—ºýD”r0kmRõ{€·h½òlÑÂ|Éy£îÐ’í{òº[6••íX”1cǯ*þvöíðyeñ‰3æ×Zw~}mñ«±Óç̘ývAÝGBÜ`uÉñ"ƒÅy7@Ë]S€Ècm뢮äÞÑÜÜûõ×É?~%vT$I¢¡®¾Åüª‹ûç/WB¨Â¹b ͤH\O5ó,ã +´i`‡2„*aÊ«°ŸÊ‘ÿùš^Ñcš&U‚¤â{1f~«ÐžlØÚ°Ý /z.G®ålñ©Xë'Fsh:øµÛrX‹ïìh‰ +™¨ÏöìYÙˆdHEÙèoFD?—kú‹a5>—àhíÛzäŘß^îûèù""#±•4d`ržP +´ÀH©¯2 +”JZ®û¥-M_ +óA}BÆáÙXM¨zV3÷c£êYŽH›\ß»jÌœ¯ÀרI»:~2S´§WÏ3óæSm°‚¨ªTW2Æj÷Y|Õ…ßoùTíÞß#£ÎÐx«¡QZÇY+„²°Wi‹ìB?Œpˆ6A"HÚ©²úÉMˆ’LP‡m®d¼ýÓGEˆ:D ⢠+Úä|î6š
mR4Úö +ç{§Œ +H‰ìWIŽ$Ǽ÷+òS«GÄU$¨“ +M³õ¹j^’MyuMLÍÞ·?S±›—P¶§jî;tã;½ûúÚ7%–eò°Oõ3Ž §BU1ØÇa–BM¿c/ÿÑKLÝKIÔ§w©yGaÌçXÌ¢%t{“«¬ÏØbèä'ÀÔUR½#Zç©Æù©…ʈQôoV]mÎ1Š&éHfX£æÓÌäiN1äÍB«ÚÒ¥‹·tHº³hNÜžêy/^äÄáÄ.1åÔ
íÎh6:¸®ueñêÅneK”iU—,;òuœH·ëà°çèhÍ…VÙ».{ùËIC»—dÃ{¾¡2v06>}’Tì¥z[IKÛ‚!+»3²«,b‡KÙ +¹nÄc” kéî\Òv]Ð-¬êÃî2ùßù¾þáÆvà’8úˆÇʼéIv´†õëRàg…÷âÛ²äú˜®;æTSÚ¿ÈC¯›\·\ŒQ+×éõT#)?*rùà"Çè³áV“bŒ
á +¬Áú¦Å¾ÀŒ§ €pÓeG¹ËÚë™Ø2Ú”º—r¼˜œÏÏö˜°O»^°<ɈȆ %f.‹oT'ê„YPF+¨hMEAÂ4-be¿-™Ûµ±Ya¤u®¯ŸÞØoì Æ™¦<ˆÎ‡á5Ùà2Ü›ëÛˆ%S‚Æs3¤5¡¹†?€2øC‰àøÀÙ‚ˆ6`ÀÒjzoµïÕÚ½FÛ»O/kÿ°dLéÞ®Í~‡4ÝÓ÷ôþmõqß}¶æéç鱸ٶÀm7Û 5}¼ŽŸ7ß«OÏ\»ŸžÛ§ŸnݶÝÝÎJ|ÖáÈì;Ø{t—úZˆ%Dv9D@}˜Êšªo™‰Ä<ŽkvU÷=¦{ÙŒXÚÚ‰WI)ªd%S¬qæÚžHXÄ@\‡à/bV +€%0
3uœÑª1ÄÄÁ
»òh%Þ«È7)³Ö¾ô²ïo(yÀȳ\³h?DÁÈö½4õ±Z@é[µ±iñ‚;ºT$Þ«IS¼Òô » +{¸þ½§ƒÀ;¬‚Ü«ZÙßnåj{hÖâöÀ²šÊkçPv?mÖ¥‰ÙÑ”O@_ì¦Xœî“2`õ/0égu±øÁšÏøfÉK˜Â}XÛ´]²ÕÍ„ÚÑ4§ÎÇ–Ž[XÝÍÛXC¤ +ÕÔ)žÕ|£EDžO5`à¤é·±Q˜i’#È´Z´awfz`„;CŸêúqÞ)7OÜxòe"mãìmáˆï‚Ýz(‹-عX¸NtÚ¹‘ýÜâÅîYÅRД´ÆVÒiùÚ-ü\¡<9Ÿ+R|@ý²â&)ãd=É5íÜÕ+ +çgK•ØX6´éRãEñŽqDµzÛû‚\Fßþ`Ö:ZLÏ'Ju»uÓ¥Ð0ÌJÑ%õJVë6]¨×‡IªÏ'_¤X˜zœcÌú®U*Y03 ´Écô^ Þë~œžü\ÔM>j¦zÉç>—®ôK"[Òw„ê#•'CÑ/~Ì°ù–³%N w÷9oƒÓbU'_vò™™/LQ¤ +çFù¡µûÐ^·(?ÓoÖkðJœ:î(õ=w{fʱ~•f‹Õa)>¶úž~‡†‹bI™ûÁSÄ}—Žyh½?}ÝÉýÖÜ5ÊdaB6]^yPùB8Aà]dGÎ%6%¡?«¼{Ñ#Ô7ö¨ýÊèl‡ŽÛÔšH»â¢<‡êà<½L˜VÜ®d™%JiµZjÜ%uWU³Íœ¸%”|Že=$°jº”‹§ö˜Ü|eÇ’)¬vp‚èõ¼aw‰·%/M3Pb”³‘×"Íë,s⌜ÖÓg%-+jÿ,‡9—©¦‚Šºó:©´áãI¼ôYáQ0{ûƒúÿ þÿ7êÜkíëô.I:Xåg„®”–¾I€·,Ùcû‘ûý¹ug†0â0Ì'¹Î¯À¨ïÙ¯¸¡·à£Äý_óI9_>ìšüÉþå—ZOÖ¢+l½TéÕVË⯳ô]WûÓyYŸ–à×Aˆ¿>דs¢g4êÉ°˜ M=e)ѬƒÝ’uËxXûļVžzJŒ'`Ó6¿dòôjÛ[ùT°íÖáœølç7•Þ`Tsó;ªeÁ +áÆ̳é´Ü’!£€°Q™" +*®5°˜‰n]MV©q¡¤®~SÝ¥hN°xáÑÞŠ&ùU¶î©î“²qXVÁRÞ‹:²*ž7,’¨î3sQ(×®ÊÁ!XZ†¯hÀp}¸F$PË'hŠ£ý +¢¯t,Ìï{ŒŽ!PŸm¡ñ˜`ó ¡ìKs3IËJJœñþÆ¢ªgŸGà›Ls™£B‹ ƒáÞí(
²L‡›‘œãùÝÝ+O˜»Ær£ŸHÝÜoữâc#Øpø2¡
0³dYëì 3íîæGˆõfÒÛÅ]0þÇ~µcIrANÑØ%øû|Òx„1HcöÉ¡§Û+>@u×ÌÒ¥#:Ý…O!™‘‘‹wTfH%ÅRš€ÇOeübÔC/ŠîækòlæKv]“ôn§ü1ê.Jm”ÇråRõUS¼“ìgtÀÉY
Ëà+JCñ®ŠÛ°;Žþ„Ô²ÁëYâSîæ=ËÃ¥Ì=Â0ž‘Êî¨j5Ǧƒ¡\-ûiy‘æÜ *âÞß^Kkø~ø\3s‚µ5³¢tDÏr¹™å]B–ÉÔ¨F!Ÿ¬ç™üªÕå+) ·ðrµôÜ/dÑÔ;£Žñ¨¬ONþmÅ‚¨¸yÀ”a¨c4e »‘¬Ÿµ_£<ˆæÖ醪hÉ:ÁXE;53 +¿)HÓÓš?ÞìJ2ìqû‘~ÕÅ…PbGö‚G²ù½$ц”зØ)m$ÃV×(ŠÕÒÂ1Ç&6:¦•-(êe(åIR ~=(”öŠçäkiI4°¤µšŸÙÈÆSµ91ñd±7w£ÖHÝwGº60 !úöYƒâ3šØ•anFÔa“è…!ùñ&‹2…©È»”¼yX±D‰ÚU>iNe$OG +øYÊj¯¤f‰N*Øx¡Œ§Lm‚Ìæ'唫ê´ÓkÍÎy Ý@xèÒP]æ¼í]ìÈ(ª‘sXW¹¾*0aVWàVÕyeÀŠ~
BaŒéºWu£Sc¥ïíËÛ²RJÝ>£g`[Uÿé[Ú˜ÊRÕø.áiAºf/ôæ +9”¯súÚT7ØŸé¦FQÄäé’ûA*Ý[—hÔ…Zν +’Òâ +öHªè³¸r¥a]]2½¬~‚{ƒQÙËyvH›–ƒÏµX#ƒ>Ã%÷q&‚ϾŠeÀ‹•(Ô)dZa™hˆqçñÙ*½<]÷”O0ÎÇÌdÚPwÁ¤¢—H=rm6*lQN9„”\mèŠ:´À5ƒéšÀ§éá‹}ÿ*-J!E®ÿGõ¶þ"õVC-Å[¬{â·]ÑÕ±QçPŽOëñ!Oò¾I‡i+©Bï°'°®Zk+°r†PÁ;U€ös·D[ÂTRƒ ^M3}é†s>àÊEC&¬›3yé3lÙåÎÒë•íVK×kÖa÷áÂœÛaùR\eV(@FUIð ³îËsóÏ¥ü +TÂV~|”ò—=…ßn…¶Âú (\ZU‰(¹dõ;û5j¯©w“šË^«:¾çÔg*¹
f“iÑûA°$Šœ$¸ÏÔ=¥iÁˆX\w¡Uá:•g°B«nàp\ùŒ% ?¬*¢rc“…¤Ÿ³ÌàÈó +ß\‘¸Ù»S„C‡AL +ŒŽ*Žüq{Ó5h~"¦ðãvÈkÂê¾Å(Õˆø®¢3"á`®èûÏ ¤ºw(Â-{ÇÈgE •yF0C‡„({ÅKãù^Ï^áš„Íó,ºs¯ð)šŠ÷ó”M‘ü´ÃØ–ÛÒç{âìp|õüÆqæ9Åqö9åý:ÞïB¹á{Ê8*éàF@átcKj¢îä ±6í˜B(ãIõäè‘ÝÐŒ¬uâsÁE…)Sš +ßܽEFÎÒ¸¡f ìpU6 ïQ¬ëÍÕQ4T¦Šôõy%’·5÷ºêYúnUG>ÈÌÓû5 +½N´3âê¦}„óÕVd=lÚEá¬÷±<w™StRjdâg+)9L6¯4º<‡Êl#ÙD}|F!ýZœ…ˆÃùº+”qÚîPÓ1³%>Yn#umæ!Þ'¶Ì•X–׈‡ûV«ÒFiËÒ9„nÑ+šžÍ<`%vN•!Ç +ÒÙvv©a:¯©¶ÕÇQšêÅ‘_ÔdW
GŸÔ×àMê>Þàç˜ê2XK‹$_
RŠ²Xêb¡KR_©ªñdoŽ,„zŒ±ÉÌ¡IF“d< +åzѤ2©ãéiNJ&©3Üéî…zF3—Þ‡ò„r¨–ÃU‹Ú5$yZ]”…+t7ÜœìŒM¥‚H +¨éàp>³ç’6|ž|™µ!R¤°Mé*¼Ê‰û™_4‹ˆM+ÊâcÒeN¯Ší®¢–ì’øÊKK +…=(
è“—Î2ôñD·ÒÜ8ÜÑÏÔ’Ø\dGnÂî¯íyRiX²²µÕ¦áÞ%—ÝÙ5}IA”jˆu!–òê©ÂÍ2€'“€M!·mJ¥ýðàãÛD‚K§M>Ï]]ÙcÉ|kˆCñ\¥@WÛ:RW:¬)±DŽlÞp6e0b;BþÔ‹Íü“L%j—hVŠ]½«±¸eðÛk¹Ã(:sž¶|È8ê6fó’îÏnò‰í$aF´&$@{ÖÊH[©;©^3ËEZ”}çLﺟe{ZŠXÍâH11õ†]Ì‚–ÏgŽÎòÁrªˆ\¦êëƒçÝ^¸ùè½fDÉB/ÖP¿zGKrýã\ˆ!npÕ®¹XØ9_èìrYõ3úYBL’rë'Äß ñ$DÇ0m ?÷„ŒÂ_È" ÇDŽÏî@ð Lɲ5OV¸HnkÑh^-kÃ9 +îãjö^0ëËÆjþX¶}åÉ·ˆðƒ¨Â!q¶:“4I;é9ª%ŠUoÕäÒüý ÷—S•v?åµuÏåæô
C·|ÁÌÃârS ¾a5¥ÅEÖä–å@¾ËSÎÌýz¦ÂÖ,û#uMkwLvšë+^.ÈÉn&a,¡lO‘9|wGÞNo6_û¦$PeDöi¥£þ`‚Ÿ&¢è6äç’¤¡ýNz’‡¤î}ý×îR +Ó»”ØÀ·0æs¬OÉíU>”¾b²¤¡ÏdgÎtñŠx:O5nYiË»`¾†c9sÎ}H¥{NݬšÏ17’§S;–9ë’Ñá-}%Íñ:‚·§Z›9qxb€^<¡ÝÉö•›t®«€%©ÆË'Q¤ûæË8ȈÃu›°©jz×e¯ål^s…‰äƒ·ü‚bìËØøøDÔQžXÓ>ÁÐ)›#²)ú¾.EO×E$ñ¸?£%K¦3êNz…Iý°·°*?n~Üt.ûýÍ úŸÇÛ/ÿü-¿ÿûí—ü¨_ÿ… œY¢A¯5‹æ
‰N¦ü¾ØôŒö½T>‡rô{ÃÂ]8--Å +wå
…†èñŽ½-_ÐhAW\ÿ,ºªO/¼ý@ŒÎŸðDë0’ÑÇL¶W0cÄ?½ø ÝçA'Öqž Ïá4]">7Mz0'UçûÈž‚«äh‹ñìÖ"bh”ÏFù%üôËéÊýß
ThúÎzíhžzÖvL}¬¿¿ÀúbÛ/°ÿ”y¡ÖEÇY‚µjýýÖãe>Ì@nÃüUîaƒ”—ŽAoJFܱœG°±F»TÐß>½ÐüQèÝ)éAXù5´Ž ˆ åÝdüýjÙ‘ä6‚÷þŠù“L>¯ü>X÷†\#@6 ïWD$«›ÅÝÁÚÐÂ'aÛ™C²È|DFès›ã ƒD‚•F¢ÀØ7¦¢ŠÁÃãœFõÖ=Ú«û‘lV¤ÂÅä…k(A+½Í¯#*´9:`ˆ2¤×L ÂãEa„îÒê,ô‹©o·¢þJ51³¤Í4I™WS7’ùxž_¶Ê¤.‡8Ty¯2Ê‚H7Í“¼:T£¹¦§9/½È$©Û àqûûÛ/D’€¨²"Ù{fþ.¿—5h®˜Z#9pTë)JtüôóÛ_þö%¼ýçËÛ_~sB«“ NÖ È{×Ixê¿ÿ±Üc3›`V^`f½›½)ÇI&'ð6h¨˜#{×€6ƒµbºy“òÁ›zÅwvUFä,È‚ÅrɨŠà=„ó›ÛžÃž/ˈsñeœ«u¶ÿæ8nHØš“¦ س?Æ@¦Š!]ŽPQ¶9°Uª®Ì˜T¼×»„«Bô²TÔeÔö«ã £é{ø³º Y<èÙNhóʬlmÛÕöݳŻJX<Š‡%F´ +Róé>Pi0³ +fš-Ü…ƒ›ã`ÉF½›8ÐXÒ¥wáhcôN3Š¨ÂWÇñt Hâ‹óUÙˆ:§_FÌ0uõ×ÅF’º€‚v%sÀÈöÕ¾[!{Im÷ý +EI›yI³=YðÞm4õGÞ¥ÎY‡i8aÁTSM“9™}æ‘©úþÅ¡ýF8a´+Aê½—ê€;øš¬Ì"Õ~ý«CÏoæÅ +Ò°ü|ý)Jà-;̳È6Îþ·ëx#Õd,¨?5Þ)¦“±âŠ(Ý&ÀD@ªÚ*TATUÆ6j
G™ÓÈ!¤ÂúðÄ,hMê]f¬ñíHh„ƒ ¢˜¢IàÆHïæ! URU«2‰Ìk²ˆ.MëøÆ4%Q[Ò`yÜ6Ç!Gs™Ôš64e +HŠ†©a¼&¼ÚÚݤ°¼d.çW]sušÙ4Šï^líÎ.©8êii¸QÞNS–K¤«ÍF¼Ä¬Ë~ñÚ‰vt äE“‰x+q›Cú²¨f +Ç¢çäg7}ŸY ø|2‘.&$‚À*4'F“+‡qBÍâÔäì41)¢ïçywb€º4M¤\Zþ`ŸÇ®am Ý¥t€ž€*P(“•®I‡&sàë„ ]"é0Î2ÍÇmshÊHœXÅÍ"sŨQ´qXl(•$b`øúy_W°9A‡È49 +RˆÎó`Fe2£æÌèëu.èŸ-hsÁølAŸbx±/"Ídº±úÕ9jPI€Å¤Ù‰(³sV¢„pðê˜Ú• +€OÑq4p“~ÐŒ)ÙÇM +}Uï'‡™~\®â Ú¿:´?dß?pRŽÄ!Ê,Ý9O”lŽƒ“©ß€–g©¶äÑL•£™Á‹íc؃F(ÝGnð™ +¦ôßÌï,E–¤2xXôlY#xm²ÇÀâv'£@¡jן¯)QšÄÂù‚Géb •ÿ†P"H¤:.àß¿n¿¾EýeODÏâŽ8Šñ/7Ü B?Á.3š&‚AR‰HÝYé5wUwTd¥— +ïGe`?ÑžÐÄB¸PÐÅx6æ+¿yý±‹±Õd!'Ï5Ì{Ô +Šäq—ÙÜ Õƒ†.Ö¸²º0Y‘!œO@áC·NÄŠ”½¢œÚtŒQ5ªÂÿ˜]NåàŠÙ%ßÒT[ÇíÜ€4EÔŽKyt¬ƒæŒÒ™ªPt±iR‰P(
ùL]´_ÓiS£P–Œ§¹^gu/@8ë9i¾.£:q:Kœ¯a’”Õqܾ¬‹x’XZBÛ,?§7f°`ÉSdzžõY/õI©;†Ï 0†2«œœ™E\–‚uiÅ#)GKyšÛæpÁÚâÕaÖÖjœGavf~àê8(qD‰8ºÒ 1›÷Ü’ôøF֪ʜr›Ê踅®ýí¶9´>TwÃáó!»Ìïë“`´2¯û²õZ¿<ûAO÷·²é—Ð8‹ÞÕ[6…´·•VSán¹z\ +b ÈR½«©î/S»0»'µ¤a‰Có¬‡và®x%éÂiy•DOPNrÀ9Mm +. {i¢\uRBôV™|²¥I¹‡ö×ä +rt‰ +ÔçIO”ïE³·‰Â™ë&+lÝÍWž¢·ˆx¼nÂaÔÔ´L»9°=‰˜Ó)q"fdWúðNs\êl%ɺÃ`Ãæ߇R.™§LÛ¢Uµ¹#áÿœ§êã„OT'ˆjÂÝ6ö»\¡£ƒZƒèªQ¼%ô© ùö«}t¶0gO¯É¿³_-»m,GtϯÐ: +^oœà}Bü|V†à±TAðl™•ŒŠ3+¬XO
bVHÄH«¢‹²¾WÈz'ÓíþÈ<x˱ˆ„Ë<ÿyÉ›êŠD¢W,”éGôÙ§]Üâ4"³Ñ+»%Š6)¸ø#»»ŸFg±Â–Š@ŒEy#Ó¤IÁ¥îƒ(aÆA¯Ë9§kÖ½+>)ÎTTÄ}8íÐþP’®j,*‹Þ8n µrMŠóª +þNüÉRé9-)‹‰öôˆšŠ—A²ãî†GN˜C(B H@pŒ´Ò3ëÃ+Obæ3kâ]1²Eðü!±7o“;ˆ"%:?ʖ쟗ÝÇFe +kåQýªðù49 cê̘hn ƒ¡½çJ"‘¹…[Ì%ñe7)¸ÙTŠ†*È!–%‹ sÌÄ~Ø°¸¸EjS{C^€½Qf.¿öÝ{O<²I¢J N\È@Ä©ìrDª0Ö"òE9Ê„F•³à"Ž’û;PMÀXaÿxFâ—ݤ8“"rðhHÔ©i*@:ä¥×•eu¯àվʘ@/½çÒDóÊlŠ52KÖDîžgR/ÉO
ÄB„¦Xàn–«Ð”¬³i'ód›™Ÿ&Nkx&3žR´"
yÆ ›vœ}“‚gË…Q:Ôf[¼|‚Q4ÙXϦ½âL}P¦zjSÄ»)ªp‚·<(‘/0hŒ +îz¥Xõ6A3’ª˜Fïþ»›2óD Y ¶Zª6ÙJ=·r`1!y&…£âLMÚ$i7VÚ¨©|<—£É‰t®rÛ^õÈç"Š…£QN¼#‹&(.ºªÞîgJÜĽ5‰àE³“B›«FÞj¬;R¥HÞ“½”› èD9xb”j¾HEAIªõ +NÕê%:€Oy/4/Îû6_&F&…ÔI’6‚IŽ6KRF¶H¢—È"á¦$z§àD”º + š>BìAؼï wèPÙ(ƒëÙO,<4²Òî›3Ä™¬§8b’AæÏ"qÊÌbtù•¸~\GÁðpññ3èêj,ŠF€˜ø$r¨§ž›ön?±Ê
ÑPãô:ð r“ÂÇ*ºŒ?MÌ$mæežÞ¯fY–°™œªÜoO}E>R P…õÈ¿½Ð8ÚرPìj‰aµDú23ƒ&šˆK^…’uI²Â7käg‹Ê^6]Dà‡#†ï«o¦³èø¶‰Ù?• œ}ηë6I–y"ü=™ +ÊS0æcʽ,7ž¿óDܸ—N¶ÕѶņ¢ú ϧes~:ýΤÁ8Œ5 +¦DˆÁÛüC¬KtþÐÜ»:S2›G}ªãŒá÷øçwº¶±ÍXݦ׮GOÚ(è%B꾋úœ.ÃßGÝWßõ{!—ŠzL“öùlÖë[´;Y¬‡óÆAŸúî^~Ó¹lTé öª#–èõ½êÜÑÎýf—n[ÃúP²…™R],Ü4¶Y·2úÞˆ+øw<îó¡[sZÝ5-ß°Êê‘.š†·§îþÖ¶lÒÚƒ•™B4ý(Pì/eûÃèqŸV7¶ðáÞÌÛ.½Ž‘ªU"Ï(O÷$OÜEž£`yúîK÷sïU©¥LÑ"Îkð®;m£Öšj¢eAÖ
®-ø¦›uÆpMt‡!&P}—ð¯Ç7Þ÷~½˜«ÃûÄçÈ ˜OñyÓúoƒ{ȇëñƵ¬ñîÕWu»ûxòs•%F +Ž„K²\I*A‹÷Žöb}ìûclŸ—4»ÍÔ×@Ç»=зjP÷¾_[
„%oÏN„L(„U +a•šðûXÓB«lÏ*·ŸOúÔ
çÔAßë>±Œ.û4CìYÏmˆúôç¾÷qËûæ¨wf æ=ªeîaoAe_)Û¹¤ÉëB¹5_¯ÊMEr-øNÕóU¸Ž1#†&ýM€½™ƒæ«òÏ¿•˜&È0jíJò.âõhºÈU×ฃœ´Ío‡L¬f$æ¥S¢ºäI+“¬ºV.:Ú¬/rc5ì³aßcˆÈ§MûËHßÁæȽ¦§;Uö!y$Á‡X迈$ûà}¾ûm÷Ç?ÿÍÜýó?}–È1€ó¸(_ÚÔ>5˧Ëm?ËÔÒ[¹±£NkCn€«mŠÐœµNþxÈÛéÓ€j1{¼=Ôôú•ª¦%²“5€u…ˆnU§këßÓÂ[ÈöWᤞ~¥ä»†õã–’/7”Ò
`.šo[\qÿLò󳸸?
wo‡Ž{¨ÜÕŽù-{ÓJCà‚rù–Þt™ê|)Ÿ¿…ÌL)äË[Û®Ù¼.½•§n×>ÏãÛüÍLL|s²ÈÝîW¼µekkøïïÒ1~-+úæ¤ÞêŒê'Ãx…©´Ç´Ÿb¼÷WÍžæ—ƒ1Ï%
eŠ½ƒ;æ)‰§Èa Õgx_l%òÓ(û¶®½Ïºþ4zÛ~Í Pôƒ‡qãö¡Ó÷a>rèŽ×tÍ Wôц98™xªÏ†©Þ(®|3Lý¾œm§?2®Ö·4âŸØú™Ø*™ÿ»‚TõãO$ý¿ i›ZÊEÅ-ú€ +þÏ„y‰©²‘\ΊâÔdîR:2ª´,è8mÒŒƒž5œ¼ÓvyËÖÛ¤È[ð›¿Zx3€;½—p5³MúÞ +÷î§l«¿šDùû(ÏÓ 9÷ýè0JÓCƒžíÚ4ò åtøýåë÷ìðë×Ñ/pLΧ!aÞ±ÿ¸_€¸6À0™J…Ž
g…‰kzFÃz&¹kåJ¨S.ÇžH¼ÈeŽÍy‹Ì*ù +^UfÊçB.qGCÞ¡Ñ÷{ÑnÖpVž‡;p/ÝæÈW¼ù#É5œx›=Ü!)ªUš‹w™Bâp¯ÞÚÙ§€Óik»FÀ^Ê|¥ß6é_X¼ˆ™õS*çSÞj¸ObQÃ(ÔrPz4PÔòðÏ¿ÔÆúÕ-Œ¦K÷¢ûßS|˜„±B潟ŋ nr|±J +Ÿ å½
±‘†‹mÓOš½Óý+SOz`¯1>gÅGT0ËÄGW1¨ê%Jé!ú…TËÂ<ŠÆUÆ÷Ê.£þQo•)9Ъ\fì5‡¯sÑÙå®:d7áè,H„¡øö™q²OÔ¸ì¹ñ Kîàš‘ð–IËôT¼VüSK¶ðDe}Jóɲ„ÄŸ¨Mí‚s ‘š-{/Ð*cµaþ¹‡ÃóU6,î/@t/Cý°¥Ðlâ÷u4k'ˆb<M(ÕEÍG¨æ·ÐEËp«‚ ×N…4r?äõ‰À‹ø7o‹üô” é…—9Œ¿ÒK×=¸‡ñHgQ¬o[‡¨“ÙçÁûB{{r9+;:w<úØü÷À^ߪôr9 xÔ±Äk[´F:ÉÀñ¤·É>O»Ìz\{f …³oÛ¤É%;áïõVHÃë臀& ”6qP\ Ï$i)YÖ"Ø1ÄBÐuóŒ¬M{f:Q,E’Ý´°œœ˜¾7¥qŸÄ¢†Q¨å`*25‰Ã?ÿú¬¸Rà0ŒÌžBŽd3÷ÙE6™\ºÕ݇¸¸ÒÃ<ë9,>û‚¨ ®«¿j¸7a»«±™þ{WW ïÝà:Ç÷groŠ-%}_ÃïµYOMÍzRžõâI–kx×v’Ð(—Ã(—L&ÌÚl8H9~ùúý;üúCaé‹ì ½Ø¸ªù‡ùˆOFÚÕXo磴)Aâ¬õ[æ²m]DÔÅΩÐU墓÷L¹â™ý#ðvNE‰HG4ÃcÉxVkÍN#-æ(PÁ"dKIlDµÃœç8Ù³ÕF¶G'¾=„ª; U¸ÿG¡e¼ZÈ7ËyDÙ{;¶«ÇhÊÐ’;º½j&LæL…†•²$e–š/öì)¡i6ã4ù³>OGn*±ŒÁþç0Ù€¤Ä1q;óSeÅÆb¡Ñ¡°¨õZ¯5»GZ«Ü±M;Á8‚M +Ëj¸é¦æÁ§Ä?] ‹«¯àÉXãR=¥¤FŸÃµ&[Ï;2<’'Ç…óЄÔêMÛ˜Í_néÉŽì7—UØɳ°J2ç'¡4>OŽw£<Ã/Tð§rmM²e½×Ä …|O¿¹ºÒ…ኧ…mšHP88Õ#ØU’2lìª)¼F
iú}èÓÍ^'n¢§écl,LRªßM8§ œÒqÊdmŸµÅb¹q™<ðC29œ³KtL¬—Òj7RUKñ‰gm0þŲ̂Á¬¢–ºã0½ +?7÷0€Y`ä*QÀ5-«wgæÕþjàà®&ÏBxŽNîÍ{ÒѲ€÷Xz5$œ¾…{\·æ0f‹‡/³B?7‹qVíD‰C2‹éKk[ WÁËY©@— =^ &”ðkl´´~rŽ†ìë.,í´†ã:쳑¨@Æãô·”ý ?¦ŠÈ›s¤©LZ“`Ò»Š68+,cÑ£ø,ySñ9ºT¦á’˜Ø÷æ¹ò$H9³`ÌÝ€m-2¶„,RÒVXëm›ÌZ6)³ùfSnÂäŸÀu"&gUšH‡Î®@‰ªÊJf_h¯æ¾„.QX¹š?É
T1•¬±¹ÐÍ'ؽ}‹,¯ªRUB¸%$ââ·‹$èÝ2Ê¥?Ô®‚ôÕV±
ÆGåR¶œÇSšÍ{x6<³Ç–…Ðb± q„οÀ¦EÖX9&Ö +fF²>üN™»¬²`ƒšÅaÃ<‘"ƒœàºú«†{³Œ»Š|/üUÚß逯oð¯/îEx®š„ŠJ×™`bßêDŒlÔ°3 +îœ3£4™ƒ½)$ýæ$¦¨Ï¢kOy°2®¦ã1ƒñ&£_fNaU€å–®¸B0‰ƒ(ÑýZ‹Ð2Üî(Nn~ÞÅ(˜ï‘%.–¥éô^ +IÅcôÃ)Ø性ïÛm(·ÆL·Bž†ã-àë"£ÒSGþ©»g +ÈQK8à‘šH8õ
i>ã÷HzÄ’Ò²—ëŸy¨ÝÖ' è•Es}L®-îÏr*“ëR;ÒÏÙHù‚×Ú¸2GHH›Ñ¨ôÞ¬ÐLrjGäsž1‹ªí t!5ẠíÚ¯E= ’£ÖÕ„á^6†:aDT)§!㸳±y–냥UŸŽæP‘ 'XÙ½žÿ/ûU’1ïyE>àð",9“Ìòÿ·÷4¶Ç±’rBÞÚ½VUòëïöM••Äý(ÌêVú…Û`.¢{l©§[ ÁjV¹`I,µp=2<éú•+MÈà²ÜlCLt0qŽ8|0gHμ\}dKý?AÝC2ÔkC¼ûþÔo~Få¡¢p…žÞ!ApôÕ†¼ìˆàçlð.$lTŽ®{“'’w›r§3[ê˜|ì3¬àU‡7^¬ŒeW«(w_&ÈÂJnnqpE×a0øk•~µ)w B®„ŽæDSE‘§9å7˜QÁŒ€S¸cà^×$³[ïU>Ü’j:$ˆ¡ ×ømC·r™BB÷éYH\ª]
*é˜Ð¨“¬K8Í•öv Û3]õNÀË|ûr×`fyFõc‘SN@üÐÏ«óL(Û@‹§mÍ^VØtuÒ'§vÅ.9xÎñ[k±8=žÈçX[f´áê
°ÆǧIý9FàH¾\|¥ùá4O-ÌuOç
OG×Þœ>C-¥N_Ó~†¤-
{æ#*´í¤]§è3îok°½eÖí&ãM”fÔCê£ëOoÑp”ï[zî*ï/2nHÞOïÃ÷oŒ²áyýp1£MœaùF†4]“AM?j»,0%Ok¾Ï2 +× ¨ÀBÖ\FlÁ,ÀVÚ>p{'²q©Ç +H‰LŒ± +ƒ@DûùŠùÏÛ]ïÜmÁZ,bBl0þ?h’F^1<Þ +õœª±tžJïlÔãëôIkåçßX‘ùD;LÇløŸ4B̘Îþjx¸°˜$ÑÎ÷.3ÛiÉÜ^gŽ±0 +H‰LL; +Ã0Ûu +] Γc;öZ(™C†f/¥YZHsÈ£]Š}´#…X˜J
eØÅj.Øi&ñóÀoì0>ÑO‹Ó_)¶&_˜ãßs«I)Ës–Äû—•ý²×•3fœ +H‰\’=n1„{B-Rü‘Ú +H‰\O»Ž1ìýþL?·H'jDýG'!þ_ÂɧÝÊ™‰=7ˆ“zEs'/_ d`#)ŒÒI,‘Ré%rI +qt\`G<A±÷$*µLØÌ&TcT^Õj.µ<ßâ¼Nñi×-ÁT}M£½
žaU3jëã·‘ëÐÛÏYfúçÌœY6Xæ}˜à®û7üƒ7ü…ãùšãJ&¢…
BZ•Ceóü_H/–®MV¿Z™ƒ—œîx¼> +~øsÇ\à+À +H‰,RKN1Û÷¹@CóiÒœ€5bÁž€zHÀý%’ÌÓH±ë8©;?C÷ØvP4€ IHðHÀïûxƒï±`á†\ák<=¿.øü?@ÍèF5؇q…¸Ý«îc +& s¡‡iè´afC3˜œkÖRÀmLZÈqJ´Á$ÂÍóà¢t ÆÃZEšU%O¢ä&×~0<Û.¸ÊeåDúЫŸf”½ßaÝƼë<u¥2*yà*WA!´»Pæ”ÒÄ›Dôv½ +f
éÛÙr2éNâÒa¨•¬ÙÎÒËq¯’Ê(´&›Š'³3¤ +R1¤ÂðŒÂK¶2Ê@r+_KαƧ\KgyV&‘·Q¦ÝÑ°z·ï3ÕåsÞùJûhK~3_Àm|Œ—|þ +H‰,RKn1ÛûºÀ(–lýNÐuÑEðÐf¼ +H‰4‘KN1D÷9…/ÐÆŸØINÀ±à +ÞPY‘ÐÀsÓ´ŠåEëEæy”îˆ*†¶*:W}½ç? M¡<8³£ŠT[®,l>:ÈXs•48jD<ô*ŽL[áÌelG¾zÉË*ÌËÖ({Ì6˜)UÈw£šÖáMžXÅÙ +Ð<0ºÒ•¬b[8¢Húí½1w]×¾ëÚªy–6dìcy~Î}´œ? +H‰4In1E÷>(ÂŒ}‚¬£,r€V)éHÜ_jp©U’Í+¾áÃmhbx‚‡á”º‘”Ap.†¿÷ñ¿ƒpÚBª“,á{<=¿|þpÿÓc¦W!G5¸\Gg®ãèGÞOyAÃêX³c.a;\ÆÁ˜Ü¹8ÊA0ªŠAYÓZ§¸fY$špŠ[A—64ÕŠ•³e†.sç|µÎDB»‚¹Âo,ûY-ý¬˜s5<„3[·3Ëy×+¥iY>eѽÄ~6n‹RæÊ{7edÚó‹Ç¾t/ öѳï$MïKIkhÏõ5>ÆK}w +H‰\;n1D{ž‚M‘¢(µ‚Ô†‹¸ß"[¬¾?R[ÄëJz#ñ3ó +6&7n¨J¬eVóHªm'ó,>ð–l1$¹ÅN³Ù0Ÿ»Ô:rº”h±s4/$=˱—ìw¶Xu +24½¸ïhì‰6ÁyZyÅ
d'{ÌŒTF—‰¾%uâXh#Gq|sŸ‚°b F:‰>"óÞ÷×ô¿À›°Á +ßø`üÓ×5Ž'|™yñH(|Fååöÿš1ê(VËLNÇhU.w8ßðt]Ÿ+~Þðø` +H‰\“=n\1„{BˆLRâÚ +G5¶|s÷7AÕ.!¤ýH5“Ï~ÃË +H‰LŒ± +ƒPE÷|Åýc^Ò“UÎâP÷RêRAý¨Ô¥Üápàp7ª^XÚ‹8
a74¥c“Àþ¢VÚHð¦ö>8èŠ4³˜AÎýûï°fÜJBkeÏp‹ÄóCýŒvZÇ‚aÆH#} +H‰LŒ1 +ÂPDû9Å\ÀÍß¿Éf·
ˆuHazÓ(ÄÜüh#S<ÞÌŽÁUªSÕÅÌxªQÄuëï;®|aGáÝei8ð“j¦¶EiùïßÃ!£×d†ddØè¼=1ì–ðØx^9cÆG€ +H‰<RAn]1Üû\àƒ
Æ'È:Ê¢øj»H¥´«Ü>þ‰¬'?`<0c¿7qžƒÌ…7vž$u-ú÷³ý ¿ÓYoíéùµÓïÿí¤2BC'[ø‘ít»þÞ.e£Ü†ÓŸvMîcÓ58iã“Ü‘óŠJŽØtk×fÍ´v¡K0ÕªòŠPy©f(Zh¼Õ“Ì›€ÔWv²p°fƒè,¸±g7°šUÝ÷¬°šÇDºsìý€<A]mW}EÁC× µdÊòoöÈÄ?ì6¿lø¨úH1ã!fò²#RÈÜ¥{ÍC©8v-öôF¸€%w‡/9ÝǶn¦º<b…‘¤ó„ +o€5ÜWÅcjŽ·¥Žî#UÜ‹×Øλ{vLj©Ë!hÓ´}Îl%z.x`:J¶¾ÌÃ!€„WºVå£ýj/XŸ +H‰4RKr\1Ü¿Sèƒ 'ð:•E0•xᲫœ¬rû4è¥Þb¦ù´è†¯KœbaÄ"Ðs + ß?¯ãóbÒŒÁý½_/¯ßy¼ý¹¾†tDÆdZ‰.ñ^ãùqUæãz0Øs0™ñ2Ù +kN@«ÜÚ»4ð¢HmF'•J2ñZЊÎM0î›ÑYª0i¯"‘
F(ÅŒKñ_‰uˆðY…ÀÎ^:&ƒS03[)áІS¦Z—O¼£¥ÆT:3Θ§;Ê#λ:vpFg͵àŽÙP¤e˜Ë=ÊÌ,)gjÄ¡Dª¦k#ƒ9U«®Öy3kXM€å[ÁŒ»|íS¾î|ú¡»»å°ëvƒ„äŸ
áÆß·ÛqýWc!©‡|ÎÒ¹òìÂRú +H‰\’½NC1…÷<E^ +u0eÓ‰}†RÔ÷Ê…‘»TZŸÀdÿVàÂ3|ø´ýµvŠVVÁí„Q +î`ôÕôè2FìyÛ˜ûÕÓE8ãþU؆Ðb¶Ñ—îv$XÑvÿƒ0üÈu®®ûF;(ÏK «Ñ;ñÙõ¯Âè_†Ð°ÇÀ´ÏKÃ>ÆifG÷¯ÂBët7øiü…ÎO‡{J_ù']SÉßéðþéŸ[*~<^®P~¿ŸÒº_àãïýA,Ug•Ñ°xU—ôżÏsÉ·s~;æô‘~ +H‰,SAŽ1¼ûþ@Ìöå°mrˆ6Ò&ÿ—RØVKmUS†¢ ¿;M‘nΔSûÄ¡ÒeLë?Ú{ÿÓEFç>ðünßÞ~Œþë_ûº_¸[ÐX8\Ôúë³Uä³=LÓV2ŸýQ +—>‰çê“zv£!«¿ÚË +éкà²Ók¢Ý 'ÒOÜ;%z*8½NšÐz}¨€Òš²ã¾ÅÁÝ‚RÙFè¥ë’‡Q‰0jCÈFv•¼t—JK¦rÅìxð…¶aµxèÁ[,_íš^l~tA”oïùX‰æ
<|¼™C›Úqˆãz¹6’Ô©B³¼¶uÌçy°Ç)€©ñ¹¥qoh 1*›ª„Ù.—1 e;'Šs‡Ë +H‰\Ž;ƒ@D{ŸÂˆYö×FŠR#ŠÐS„"!î/ÅED*{žÆ3Þ@…Øcö)WP%IÅ“JE52I.©ºŒ”9cL•D'øK&'¨Òγò‘–=ÆÃ-5©ä†v~KAO¼N(Öã¹þý:Á?°AÀ7tÏÁÇn´TK®xóf¶ªQ/ëÏвE3‹mÆ¥h‰8p±æ€ûŒ{èá+À +H‰\Ž»ƒ0Ew… &Ä$k¥ª3b(;C âÿ¥Æ0´0Å÷(Ǿ+°ˆ¡¦@Ü2.JAµB²’‰ÇD™²‘X¬ÑÈBÄ.`vPêE9«î>ñ˜rÜ£Irÿvßµ\{±ßW>êpÕÏeÇkû&xáVø†æÙ×g¥6– 9ãM(çSUþÇßf25 ñØ)1j«Çî6ýp›ð1`| +H‰ª6TÈÌKIP0Ô3 +H‰ª6RÈÌKIP0Ô3 +H‰ª6RÈÌKIP0Ô3 +¹PTšÁTš0Òn¹ •p‡äÀq-@€ +<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?> +<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 4.2.2-c063 53.352624, 2008/07/30-18:05:41 "> + <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> + <rdf:Description rdf:about="" + xmlns:dc="http://purl.org/dc/elements/1.1/"> + <dc:format>application/pdf</dc:format> + <dc:title> + <rdf:Alt> + <rdf:li xml:lang="x-default">VS2010_h_c</rdf:li> + </rdf:Alt> + </dc:title> + </rdf:Description> + <rdf:Description rdf:about="" + xmlns:xmp="http://ns.adobe.com/xap/1.0/" + xmlns:xmpGImg="http://ns.adobe.com/xap/1.0/g/img/"> + <xmp:CreatorTool>Adobe Illustrator CS3</xmp:CreatorTool> + <xmp:CreateDate>2009-03-04T14:21:57-08:00</xmp:CreateDate> + <xmp:ModifyDate>2009-03-04T14:21:57-08:00</xmp:ModifyDate> + <xmp:MetadataDate>2009-03-04T14:21:57-08:00</xmp:MetadataDate> + <xmp:Thumbnails> + <rdf:Alt> + <rdf:li rdf:parseType="Resource"> + <xmpGImg:width>256</xmpGImg:width> + <xmpGImg:height>32</xmpGImg:height> + <xmpGImg:format>JPEG</xmpGImg:format> + <xmpGImg:image>/9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA
AQBIAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK
DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f
Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgAIAEAAwER
AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA
AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB
UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE
1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ
qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy
obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp
0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo
+DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8A9N6trem6VB617MIwfsr1
ZvkBlmPFKZoNOfUQxC5GmOv+aPl5T/cXZX+cRpT/AInXMn8jPvDiR7TxnpL8fFPdE8y6LrcbPp10
szJ/exbrIlf5kajD59Mx8mGUPqDm48sZiwXeZfMmkeW9GuNY1ab0LK2FWNKszHZURf2mY7AfwwYs
Upy4Y826MSTQfK35i/8AOQvm/wAw3Etto8r6Lo9aRxQNxuJF6VlmWjb/AMqkL2NeudDpuzYQFy9U
nPxY4Q8y8kubq9kYySOWJNWJJJPzrmyEA5PjSZB5N/NTzl5Tuo5NJ1KWKBW5PZSMZLZ+lQ0THjuB
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</xmpGImg:image> + </rdf:li> + </rdf:Alt> + </xmp:Thumbnails> + </rdf:Description> + <rdf:Description rdf:about="" + xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" + xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#"> + <xmpMM:DocumentID>uuid:8CA472115A0ADE118D6EE84B58BD5EB4</xmpMM:DocumentID> + <xmpMM:InstanceID>uuid:1c2d0ce0-ed76-de45-80b0-35352d7d0ef0</xmpMM:InstanceID> + <xmpMM:DerivedFrom rdf:parseType="Resource"> + <stRef:instanceID>uuid:472287ec-7810-4a41-84bf-8a4190c7dbcd</stRef:instanceID> + <stRef:documentID>uuid:5B20892493BFDB11914A8590D31508C8</stRef:documentID> + </xmpMM:DerivedFrom> + </rdf:Description> + <rdf:Description rdf:about="" + xmlns:illustrator="http://ns.adobe.com/illustrator/1.0/"> + <illustrator:StartupProfile>Basic CMYK</illustrator:StartupProfile> + <illustrator:Type>Document</illustrator:Type> + </rdf:Description> + <rdf:Description rdf:about="" + xmlns:xmpTPg="http://ns.adobe.com/xap/1.0/t/pg/" + xmlns:stDim="http://ns.adobe.com/xap/1.0/sType/Dimensions#" + xmlns:xmpG="http://ns.adobe.com/xap/1.0/g/"> + <xmpTPg:NPages>1</xmpTPg:NPages> + <xmpTPg:HasVisibleTransparency>True</xmpTPg:HasVisibleTransparency> + <xmpTPg:HasVisibleOverprint>False</xmpTPg:HasVisibleOverprint> + <xmpTPg:MaxPageSize rdf:parseType="Resource"> + <stDim:w>753.222900</stDim:w> + <stDim:h>198.807617</stDim:h> + <stDim:unit>Points</stDim:unit> + </xmpTPg:MaxPageSize> + <xmpTPg:PlateNames> + <rdf:Seq> + <rdf:li>Cyan</rdf:li> + <rdf:li>Magenta</rdf:li> + <rdf:li>Black</rdf:li> + </rdf:Seq> + </xmpTPg:PlateNames> + <xmpTPg:SwatchGroups> + <rdf:Seq> + <rdf:li rdf:parseType="Resource"> + <xmpG:groupName>Default Swatch Group</xmpG:groupName> + <xmpG:groupType>0</xmpG:groupType> + <xmpG:Colorants> + <rdf:Seq> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>White</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>0.000000</xmpG:cyan> + <xmpG:magenta>0.000000</xmpG:magenta> + <xmpG:yellow>0.000000</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>Black</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>0.000000</xmpG:cyan> + <xmpG:magenta>0.000000</xmpG:magenta> + <xmpG:yellow>0.000000</xmpG:yellow> + <xmpG:black>100.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>CMYK Red</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>0.000000</xmpG:cyan> + <xmpG:magenta>100.000000</xmpG:magenta> + <xmpG:yellow>100.000000</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>CMYK Yellow</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>0.000000</xmpG:cyan> + <xmpG:magenta>0.000000</xmpG:magenta> + <xmpG:yellow>100.000000</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>CMYK Green</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>100.000000</xmpG:cyan> + <xmpG:magenta>0.000000</xmpG:magenta> + <xmpG:yellow>100.000000</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>CMYK Cyan</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>100.000000</xmpG:cyan> + <xmpG:magenta>0.000000</xmpG:magenta> + <xmpG:yellow>0.000000</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>CMYK Blue</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>100.000000</xmpG:cyan> + <xmpG:magenta>100.000000</xmpG:magenta> + <xmpG:yellow>0.000000</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>CMYK Magenta</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>0.000000</xmpG:cyan> + <xmpG:magenta>100.000000</xmpG:magenta> + <xmpG:yellow>0.000000</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>C=15 M=100 Y=90 K=10</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>14.999998</xmpG:cyan> + <xmpG:magenta>100.000000</xmpG:magenta> + <xmpG:yellow>90.000000</xmpG:yellow> + <xmpG:black>10.000002</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>C=0 M=90 Y=85 K=0</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>0.000000</xmpG:cyan> + <xmpG:magenta>90.000000</xmpG:magenta> + <xmpG:yellow>85.000000</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>C=0 M=80 Y=95 K=0</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>0.000000</xmpG:cyan> + <xmpG:magenta>80.000000</xmpG:magenta> + <xmpG:yellow>95.000000</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>C=0 M=50 Y=100 K=0</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>0.000000</xmpG:cyan> + <xmpG:magenta>50.000000</xmpG:magenta> + <xmpG:yellow>100.000000</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>C=0 M=35 Y=85 K=0</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>0.000000</xmpG:cyan> + <xmpG:magenta>35.000004</xmpG:magenta> + <xmpG:yellow>85.000000</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>C=5 M=0 Y=90 K=0</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>5.000001</xmpG:cyan> + <xmpG:magenta>0.000000</xmpG:magenta> + <xmpG:yellow>90.000000</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>C=20 M=0 Y=100 K=0</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>19.999998</xmpG:cyan> + <xmpG:magenta>0.000000</xmpG:magenta> + <xmpG:yellow>100.000000</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>C=50 M=0 Y=100 K=0</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>50.000000</xmpG:cyan> + <xmpG:magenta>0.000000</xmpG:magenta> + <xmpG:yellow>100.000000</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>C=75 M=0 Y=100 K=0</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>75.000000</xmpG:cyan> + <xmpG:magenta>0.000000</xmpG:magenta> + <xmpG:yellow>100.000000</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>C=85 M=10 Y=100 K=10</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>85.000000</xmpG:cyan> + <xmpG:magenta>10.000002</xmpG:magenta> + <xmpG:yellow>100.000000</xmpG:yellow> + <xmpG:black>10.000002</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>C=90 M=30 Y=95 K=30</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>90.000000</xmpG:cyan> + <xmpG:magenta>30.000002</xmpG:magenta> + <xmpG:yellow>95.000000</xmpG:yellow> + <xmpG:black>30.000002</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>C=75 M=0 Y=75 K=0</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>75.000000</xmpG:cyan> + <xmpG:magenta>0.000000</xmpG:magenta> + <xmpG:yellow>75.000000</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>C=80 M=10 Y=45 K=0</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>80.000000</xmpG:cyan> + <xmpG:magenta>10.000002</xmpG:magenta> + <xmpG:yellow>45.000000</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>C=70 M=15 Y=0 K=0</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>70.000000</xmpG:cyan> + <xmpG:magenta>14.999998</xmpG:magenta> + <xmpG:yellow>0.000000</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>C=85 M=50 Y=0 K=0</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>85.000000</xmpG:cyan> + <xmpG:magenta>50.000000</xmpG:magenta> + <xmpG:yellow>0.000000</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>C=100 M=95 Y=5 K=0</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>100.000000</xmpG:cyan> + <xmpG:magenta>95.000000</xmpG:magenta> + <xmpG:yellow>5.000001</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>C=100 M=100 Y=25 K=25</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>100.000000</xmpG:cyan> + <xmpG:magenta>100.000000</xmpG:magenta> + <xmpG:yellow>25.000000</xmpG:yellow> + <xmpG:black>25.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>C=75 M=100 Y=0 K=0</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>75.000000</xmpG:cyan> + <xmpG:magenta>100.000000</xmpG:magenta> + <xmpG:yellow>0.000000</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>C=50 M=100 Y=0 K=0</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>50.000000</xmpG:cyan> + <xmpG:magenta>100.000000</xmpG:magenta> + <xmpG:yellow>0.000000</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>C=35 M=100 Y=35 K=10</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>35.000004</xmpG:cyan> + <xmpG:magenta>100.000000</xmpG:magenta> + <xmpG:yellow>35.000004</xmpG:yellow> + <xmpG:black>10.000002</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>C=10 M=100 Y=50 K=0</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>10.000002</xmpG:cyan> + <xmpG:magenta>100.000000</xmpG:magenta> + <xmpG:yellow>50.000000</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>C=0 M=95 Y=20 K=0</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>0.000000</xmpG:cyan> + <xmpG:magenta>95.000000</xmpG:magenta> + <xmpG:yellow>19.999998</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>C=25 M=25 Y=40 K=0</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>25.000000</xmpG:cyan> + <xmpG:magenta>25.000000</xmpG:magenta> + <xmpG:yellow>39.999996</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>C=40 M=45 Y=50 K=5</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>39.999996</xmpG:cyan> + <xmpG:magenta>45.000000</xmpG:magenta> + <xmpG:yellow>50.000000</xmpG:yellow> + <xmpG:black>5.000001</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>C=50 M=50 Y=60 K=25</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>50.000000</xmpG:cyan> + <xmpG:magenta>50.000000</xmpG:magenta> + <xmpG:yellow>60.000004</xmpG:yellow> + <xmpG:black>25.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>C=55 M=60 Y=65 K=40</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>55.000000</xmpG:cyan> + <xmpG:magenta>60.000004</xmpG:magenta> + <xmpG:yellow>65.000000</xmpG:yellow> + <xmpG:black>39.999996</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>C=25 M=40 Y=65 K=0</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>25.000000</xmpG:cyan> + <xmpG:magenta>39.999996</xmpG:magenta> + <xmpG:yellow>65.000000</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>C=30 M=50 Y=75 K=10</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>30.000002</xmpG:cyan> + <xmpG:magenta>50.000000</xmpG:magenta> + <xmpG:yellow>75.000000</xmpG:yellow> + <xmpG:black>10.000002</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>C=35 M=60 Y=80 K=25</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>35.000004</xmpG:cyan> + <xmpG:magenta>60.000004</xmpG:magenta> + <xmpG:yellow>80.000000</xmpG:yellow> + <xmpG:black>25.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>C=40 M=65 Y=90 K=35</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>39.999996</xmpG:cyan> + <xmpG:magenta>65.000000</xmpG:magenta> + <xmpG:yellow>90.000000</xmpG:yellow> + <xmpG:black>35.000004</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>C=40 M=70 Y=100 K=50</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>39.999996</xmpG:cyan> + <xmpG:magenta>70.000000</xmpG:magenta> + <xmpG:yellow>100.000000</xmpG:yellow> + <xmpG:black>50.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>C=50 M=70 Y=80 K=70</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>50.000000</xmpG:cyan> + <xmpG:magenta>70.000000</xmpG:magenta> + <xmpG:yellow>80.000000</xmpG:yellow> + <xmpG:black>70.000000</xmpG:black> + </rdf:li> + </rdf:Seq> + </xmpG:Colorants> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:groupName>Grayscale</xmpG:groupName> + <xmpG:groupType>1</xmpG:groupType> + <xmpG:Colorants> + <rdf:Seq> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>K=100</xmpG:swatchName> + <xmpG:mode>GRAY</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:gray>255</xmpG:gray> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>K=90</xmpG:swatchName> + <xmpG:mode>GRAY</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:gray>229</xmpG:gray> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>K=80</xmpG:swatchName> + <xmpG:mode>GRAY</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:gray>203</xmpG:gray> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>K=70</xmpG:swatchName> + <xmpG:mode>GRAY</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:gray>178</xmpG:gray> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>K=60</xmpG:swatchName> + <xmpG:mode>GRAY</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:gray>152</xmpG:gray> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>K=50</xmpG:swatchName> + <xmpG:mode>GRAY</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:gray>127</xmpG:gray> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>K=40</xmpG:swatchName> + <xmpG:mode>GRAY</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:gray>101</xmpG:gray> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>K=30</xmpG:swatchName> + <xmpG:mode>GRAY</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:gray>76</xmpG:gray> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>K=20</xmpG:swatchName> + <xmpG:mode>GRAY</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:gray>50</xmpG:gray> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>K=10</xmpG:swatchName> + <xmpG:mode>GRAY</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:gray>25</xmpG:gray> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>K=5</xmpG:swatchName> + <xmpG:mode>GRAY</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:gray>12</xmpG:gray> + </rdf:li> + </rdf:Seq> + </xmpG:Colorants> + </rdf:li> + </rdf:Seq> + </xmpTPg:SwatchGroups> + </rdf:Description> + <rdf:Description rdf:about="" + xmlns:pdf="http://ns.adobe.com/pdf/1.3/"> + <pdf:Producer>Adobe PDF library 8.00</pdf:Producer> + </rdf:Description> + </rdf:RDF> +</x:xmpmeta> +<?xpacket end="r"?>
endstream
endobj
193 0 obj
[45 0 R]
endobj
194 0 obj
<</Filter/FlateDecode/Length 445>>stream
+H‰\“ÛŠÛ0@ßýzÜ}X|‘FÊB0d½ÈC/4í8¶’Û(ÎCþ¾ŠNØB
$ÍÌiòf÷¾‡EåßÃÔíý¢ŽÃØ™®¡óêàOØ••ê‡nyPúïÎíœåñðþvYüy7§l½Vù¸xYÂM=múéàŸ³ü[è}Æ“zúÕìŸU¾¿Îóö㢠+Uת÷ÇèK;mÏ^åéØË®ëÃr{‰gþíøy›½ª—ÓM½¿ÌmçC;ž|¶.âW«õ6~uæÇþ¿u³âØáØýnCÚ®ãö¢¨Š:Ñ´‚èÚBM¢²€Þ¡ú€*h›¨2‰L YHC2Ð+d¡
ä j1Ô¢ÉnÈ®ÉnÈ®1Œ4Ù…ìZ +¢¡M-B-zI"CKCKCKCKCûˆ‚ŸÅÏàgñ3tÞÒyƒÅ6j&Ú@ÐÄXnEè‹¥/B_,}nÅr+B—]ü~‚ŸÃOðsø ~?ÁÏá'ø9ü?‡Ÿàçðü~+vn¨³y8Xüã#~¼ÖûsŽS§>g¥»†Ç$fšûd£ÿœÞyšU<uÿe +H‰\”Íjã0F÷~ +-ÛEñt¥‚!IÈbÚ2™y +¢AKƒBƒ–…-
+
Zt4(9Œ#‡‘`ä0ŒF‚‘ÃH0r F#ÁÈa$9ŒVw#‹q…ûoþ6qvÕ×ĵ—â°¥OSv›¯~ð_ÿÓ8©xêöÉþ 0 +H‰\”ÍŠ£@F÷>E-»ZuoUB N ‹ùa2ó +™i
Ñ Ð %µÚÑ Ð ÃApp4(4èhPiÐá§ø9ü?‡ŸâçðSü~ŠŸÃOñsø)~?ÅÏá§ø ©•ÔBO!‹'‹Å“EÈâÉ"dñd²x²Y<Y„éþc:ízÚÚõ´+´ëiWÉéÉ©´ëiWi×Ó®Òn ]Å!à 8‡€ƒâpPŠCÀAé3Чb0RRR/8·ÞÎöÇüøÄÓ&2Ÿû£¾cZóºšwÆc[´]üÜhC?˜têñËþ +0 +H‰‹A +€0ïyÅ~À˜Ö6õ¢gшzÑ +¾Þæ2#8©Á™©Sê5±†eMMäÐãÝé ‡„½FØâl¬*JÖ'æÏÒ‹v¼ÃM3ý +H‰\PÑjC1}÷+üÚÑ×ÁØséÃú~ÙVX;hûÿ0“;Øv DñxŽ¹©Ulfd¥â¤“ÜH +£8IK¤T¼¢D6iB!Ç6…h!6ÏB¥ {kjcT^§ÕlêIÿ“cĦœ·¦j«õ>ô5xšU
L«ÝÇk'Ó1oS¸Ìe¦~Æô™ËËäGÜì¾À+~A!QǼÙpÍ?aÿr,øñ€›¸à•"w–ÚÓÝßÌðþïpƒd"b#w))…%ÏîNÏlšð㻎\®ðtÂýñ\ðqÆçà +H‰<ÌA +ÂPÐý?Å\Àt’ß6þ½èZ,x +H‰\R»n1ìõúÐ"Å—ZkÃEÜ»ˆ‹u +A9cw“஋dÕ4£”¿%Ž"´ô Öx¬F̘€NCõÔ_G3¦)¾ ƒ!›ÄÌÎD¨JºÛáwKèïèÒsÔ„ñ¤éå_(憢շ[Qú[â(BµôL¼êñz5_/>häi×¥üßÐÛ>T \ÁN\ç|þ@~†Ïs7°Ðß;¿ØpaºÂݲ½[ÕL!ò7Dz·ÄQ„Ö6ý õyî&ۆ׫úÖ~õ?í³þ»=<½àóÕ~ð %C˜³£—I¶öÿéªlB+hßñhÎÁˆô£=¾ö‡—÷Ñ¿ÞûÏ×þÜžÛ_ +H‰ª6Ô3 +©É +Å¥Iu¦ +ºèf (4*äË›Pi3ÒS!ªåÆ0•FŒ4‚[^_ P` +H‰ŒA +ƒPD÷9Å\ 1ÉÏÿè¾Øu©ÐuUKu!ôôMÌ0áñ+u·‡`=H—VQ{ã¢ÜX½ábÂî†}¦…¾ ¹jS¼À£Š!óšÌ[P1Ãt"ÝšnÁôBÄé€Jö/_;ºñ-¸~è÷` +H‰\T;n1ìu +] ´ø‘Hµ‚Ô†‹¸wë +ˆt…2ôâh¢ÄË‹]˜T +e˜È2—[¤ü‘8g«|,³3Êâ‰j'û + ªykâ¸'<$²••0¢PŸò;\j|†OËð¹v íD²ç©¾Ã¥¶Uxl®h4âL›O¤…|ÄMû…K«ëlÔül4¼| ÷W¼ Ü®±]è1ß<pÆitÙ°”\4§`2ì€ïDM$ !õ.8eY¡Æ1ä ÑËÔsê÷äNcEY¯lt£¥—)]™˜µ²•c»µu›ÏòÕWW'XSíÛ†~Ó–üŠc½ôÄÑLÈøôõÚ"ž9W#‡)¶Q”ÖŽK÷.ÄÑ&×z$1ÑÏ„+Ì5ÿ%«™TøÌá]è±GÙ¾c9–@û~.¡”Z,ñN÷/Ä‘„YTù¼óç¥YùíV8Ë]’õ_èg½ä_ιйíÐÅ OñHsòJ˜¹öâHC¼àFv‹Úç¼Rò0˜¹ó„{Ä‘„™ r9Î+)§p¹¡ÞÚ¯þ§}¶Ñ·§Ÿ/xümÈ;$öcÿų\Þÿ‡(ÎÃ] ·“k€¥øhß_ûÓËûèßû×þÜžÛ? +H‰<ÌA +ÂPÐý?Å\À4ùMòÛ}ѵXð +žÞd# a,¥;]ËV´Qe…5'3…‰:Riôë½<Êç¼'o}"Öa|´4W¼B1U7ìÈmÉmÆ|CÄyƒpþoV+ºã“1½Ë9î'À +H‰\’KN1D÷9…/€Iü‰-bXÀÁŒDƒ4Ìý%ìdӨݯÔ*§"ÝÔ:VøL¡ÛAq˜A x_X)‘Mtbx-ÿ„hÅ&id7TÏãÑ6¬#ì{Þ~¹;Vó,Ç.ŠÌÄj"£§{Ï[Ç¡<¹“f±®“ÔãMHíòs—¬½¢8£pA°zô*Øǘè“(*µÙ‹¨§/„ßP9Ëg[¹4¦9‹ð{”ËãF4ÙÓ¿¶)P.£bm>
|ÁL$Plbãqñ_ ÓÏÚÖ®{DÐÑuE'£å82ƒ¤Wÿ{aÎo¼îqÏ…å^¹G†c&½0ü{aK®
‘%/$ëð尿–gø*ÖóQnž*Îå¦uv†ù¢(àÀáÖÝW‡ï·ò^Na?¤±¥±Ææ͆Îo®8s•–×1ÃŽ{i™Àg¹{Û§c…óî_à±<– +H‰ŒÁ +Â@DïùŠùÓdÝݬwѳ´Ð¶'ÛCÁ¯7)3ÌðÁBݽ,ieK(Ö¸eÃÑNªÜÎëD3}&g”j,ªÕKƒ3æÍ™o§„S-Ø××‚á ·Ý
ÕÈ_L+ºÛKpýÐÃõ` +H‰d”MnÜ0…÷:….E$%RÚ(º²höAÛ +QþÕpwß×ü+Õ"X¸ã_Ê?Óý—Çš¼¥;ÂöHŽ/Æ
Â&±i?ý§ù÷·ô=½&8ÜHnÄyÚdÅûâs÷Ù°^)–Ó·QgqKŸžòýãKÍo/ùóS~Hé¯ +H‰ŒM +ƒ`D÷9Å\ ñKüþº]K…@Ú®Ú¢.Oo"ÞËB’9¶HYønÂ1WH`-ë‹žøQÀ‡šáaµ]¸ eÕ‹®7ÃÛ¨Ž¿i!ssÂwÄ€i†Åni³ïÞ‡O+šþÐýi´; +H‰\ÍjBAF÷yŠ¼€qò3If[(]‹‹º—Ö½¬ï÷Š´2‹Ì9ä!`'cÆBÂÏáB‘†3pR°/B…I¬/Ô\Q”†Y!SFàžÄêä¦ETríÍ°ÐRVÔsäŠî5ðIÌqßx† Þñ®ï¶oû†§+lØ5—"4*£Þÿý>à.?Ý‚|J’›¨"“õ–#ue³:Ɇ©{z0j
1–4¹/”½×±Žgx9àv?5¼NøzÀìàW€ +H‰ŒA +Ã@ï~…>PÇ»‰½ë{IÎ¥> ¤9µ¥É!×w@i`¥nºÖ’q_¡E¹*gÇÅ9km¡ýb×!C͸؀ÂngqâOc„³)ÄiŠSÁüD³£æI"Ϩ6tã[pýÒé/À +H‰ˆÁ +€ ïûï¶UqÓ{Ô9ú€ˆNæAèë3f`2eàUY¥G`Ùz‡g§e¶êQAÝ´ŽB‚´¡©6!ùûþëA7ž‚ᦹñ 0 +H‰\“ËN$1E÷ùŠü +:ÆØJࢊù9ù˜n\áâ´¬à0cµyZû{¦]¦]Çn×Ñ'®d ˾ aáPÃЪ#•*ÈËʴo|ì,ƒ—P« `½G9J¹É(cXoZj C„;‡2Ä„^د®[qÖ›˜lÿã(Þ›Øý›ýÄGð:Ö$A!öìR†]åwºŽpLÁº6Dîá'^¨=ß•~ ™õiÔ7D£z$ÝÑ&ån|\xDôtP{ T‰êQã&QqfßËŽì’|VŠ5—F¾µ€5EÍ&M8|ôWÂáy~lôT-oŸþá1H.ƒ¢ù³`åwËã«âqçì·`²)øl[Dk}½—w&6I£x.i¾Dº6³Y7n€¹Öbqyí5.ÿ.Ì÷`?®¢+ç«dÏéw~OPØÚµo³Ïg̯éöþò¿¯tƒÂsümoÏL*íô$ùóOú›>’9܈nTËŠ6)°ÏÍÑ,
Z›§•¡Z1oéî)ß>¾@þzÉ¿žòCzHÿ +H‰‹Ë
€ ﯊m@xü)ÀèÙHF9#H¬^¸Ì&›F&¹îŒ\I{¡½…QX t4˜¼0F£œtÑK܇†‘¨‘0ÒŽÖT¡xì7®¹ÜŒù¡~ +H‰\‘=nÃ0…wž‚(C‘¢(ŠÎA†f÷PN ÷JÊCêLÒ÷dþ¼çH#iÍ+IéxéTMwÁ•IL•ª£ +•š§t\àMØR°1¹qCUb-³šGRm;™gñ·d‹!É-všÍ†ùÜ¥Ö‘Ó¥´@‹£y!éYÞˆ½d¿£°¥ÀªS¡éÅ}GcO´ ÎÓÊÜ@y²Ç,ÁHet™èá+P²Q'Ž…8rÇgîSVÔH'QÃGdÞûþšþx6XááŒ?púºÆñ„J^:oÈTUGÿº½^3Æ^›YŸÉ2Z?¹Üá|ÃÓue|®øyÃ\àO€ +H‰‹1 +€0û{Å~ÀË]BíEk1?µQÁ×›kf``;¹qì…Ì)fÄ”9k5KP4žÛNq¯´ÑEÂ>E¼°Gí”oÊógé†AÒD¿ +H‰\’1nÃ0Ew‚¨"‘¢D®ŠÎA†f÷ÐN ÷J‘.jg²Þ“Iˆ_z$¹ó +,éE¬Spí.Diô‚½:Ê´v^¿kÙ„ìçÚiBΖ¬±À±‡U£ÿ^XuÉÚÕ…ÍñÄr˜ãñ„"¾Ö6‡;²E#y”¯Ãö—·‰ÈIzõ½ºö`¶óàYر©c¯#Ê÷Âëb°{RÞPêDñFQq±5Nß-ÃAÛK…—‡±¤/øITà;>/öy&Ì•íȪðV3!unxXþÿ0›.¼
0¤j±ë_îéý +§ËÀóW8§sú` +H‰<ÌA +ÂPÐý?Å\À4ùMòÛ}ѵXð +žÞd# a,¥;]ËV´Qe…5'3…‰:Riôë½<Êç¼'o}"Öa|´4W¼B1U7ìÈmÉmÆ|CÄyƒpþoV+ºã“1½Ë9î'À +H‰\’ËjAE÷ýõ.u=»zY-⽈mÈ8 ûÿ!U=ÂÖÁÌœ‹nßzôµéÄ6»*¼•àc¦`8Ç€D
ß±s!O^,piß„YGÒ2(JH´¨ãñö™ö#oŸì}DÅIh¢¡ÈȽP0Ê}äià4Yìlæ¶È"ߌL·?»VöQÈpAJA±GÖªès.ÉNiÕ¢å? +éhRñUV͇ðêeÌôGÆÕq3‹ôò…m \ÃèØ)–AnXIÔ±dÞüwÂò‹Ñ>kÏ8†í«ÓIÕŽ®Åæ¦÷úÂêÈ~X¼Vs)Ϲ6½cúÂVßr—²#‡o7íÒ~ÿÖQ4 Ÿä°üm§_ç/í\B`½8Ã$O²Ã—ÃûŸöÜ®-e¤2¡u¥é=w¬Ù• SÝ›œœ™§|yk?žàt~íðñ +?Ÿà±=¶ÿ +H‰<ŒÁ +Â@Dïûó¦I6ÙÝÞEÏbÁíIÅöPðëÍz70<†1§áxfÌkÊ™¬Œð¦”e„:±)vbäV±ÜÒ=½ÿR©T«@Zs„còs.x†Å¤Å±¡KÿfLW¶ +H‰lAj1E÷:….Å’,ÙÚJ×!‹f?´è¤äþPyZŠöX__ºB52«h]H9ð¤Â ˜º;jMÞÐZ§R+ªRõH©Äq‚'°üB¢²Ogó4n6zxÊžyøK²QÛÁ–™ÿÍ)lt0'
I¬hB¦m ב\~'œà ,0Ã;~CÁí|ÁþíXð|‡»vÅõ’ôê¨ÒÜ^Ž·ø„k–ŸG!B®™°ZŽ¼:îX¨kO]sŸ™ÎÒbl$$wÁé/'Üç‚÷_Ox€ü0 +H‰TŒÁ +ƒ0Dïûóën6‘ä^Ús1àˆõTKõ øõ&xQÞÀðÁDÍ«L+™ã"BÙ|‚SVï¡ÆÑ–‘>ô?twìâô˜‹%ìÚ€
õZëµ (Ø +W¨ÔÞë´ y~½K +H‰lT»n1ìõúÓâC”ØR.âþØ@Öÿ?¡ÎÙó.‚+Vi$r†¼·bF<¹ö)¤õµ˜ÐÄLsTcRé+’æUà@ØHU륜€¨
ú$C«æ-¸}MžUÇ&BŸ‹6<èƒÂ¢Z#fð}’u¤Ó‰ór¦ŽÛ.åo¥7OÀ¨gŠmGÔ]g2W1æô°%ÐE¯Å·H‚˜,mZàÛhÆØ¥º”°•—ò½þ.^¿Êý·ÇVŸßË{–·>BPB†÷ÃÊëŸågyý9‰œDžHhD™™Ø£ {ƒ#K»c<íÈÙ¬š“Iz•o¨MO“^Ë—§zÿøÒêûKýúTÊ^I›{?ùÞl¬ZÈý*EtY¡ò +‡§s'`K`‰<&Z…Óª6—ì Ó4B)æ2î,å•ç}“ÎýÛ‡ðFnzµ58…?ÛœœØÅ”åBGI>Qãèâhm¬&RÈÊIkIßµ›àÈêlf÷@»’|PR…ºùjù s^w +2 2
0000091193 00000 n
+0000139097 00000 n
+40 1
0000139155 00000 n
+42 1
0000139665 00000 n
+45 1
0000139928 00000 n
+47 1
0000140364 00000 n
+50 1
0000140622 00000 n
+52 1
0000141066 00000 n
+55 285
0000141341 00000 n
+0000141517 00000 n
+0000141651 00000 n
+0000141789 00000 n
+0000141918 00000 n
+0000142947 00000 n
+0000149563 00000 n
+0000155304 00000 n
+0000160105 00000 n
+0000175707 00000 n
+0000175764 00000 n
+0000176129 00000 n
+0000176494 00000 n
+0000177113 00000 n
+0000177577 00000 n
+0000178093 00000 n
+0000178637 00000 n
+0000179111 00000 n
+0000179568 00000 n
+0000180082 00000 n
+0000180787 00000 n
+0000181153 00000 n
+0000181519 00000 n
+0000182065 00000 n
+0000182681 00000 n
+0000183291 00000 n
+0000183959 00000 n
+0000184386 00000 n
+0000184818 00000 n
+0000184891 00000 n
+0000185078 00000 n
+0000185145 00000 n
+0000185240 00000 n
+0000185333 00000 n
+0000185576 00000 n
+0000185629 00000 n
+0000185711 00000 n
+0000185824 00000 n
+0000185852 00000 n
+0000185925 00000 n
+0000186113 00000 n
+0000186208 00000 n
+0000186310 00000 n
+0000186383 00000 n
+0000186456 00000 n
+0000186645 00000 n
+0000186721 00000 n
+0000186818 00000 n
+0000186914 00000 n
+0000187170 00000 n
+0000187225 00000 n
+0000187308 00000 n
+0000187382 00000 n
+0000187456 00000 n
+0000187530 00000 n
+0000187676 00000 n
+0000187753 00000 n
+0000187850 00000 n
+0000187963 00000 n
+0000188219 00000 n
+0000188274 00000 n
+0000188357 00000 n
+0000188431 00000 n
+0000188505 00000 n
+0000188694 00000 n
+0000188791 00000 n
+0000188902 00000 n
+0000188976 00000 n
+0000189166 00000 n
+0000189263 00000 n
+0000189364 00000 n
+0000189438 00000 n
+0000189512 00000 n
+0000189586 00000 n
+0000189660 00000 n
+0000189734 00000 n
+0000189923 00000 n
+0000190020 00000 n
+0000190126 00000 n
+0000190200 00000 n
+0000190381 00000 n
+0000190478 00000 n
+0000190570 00000 n
+0000190644 00000 n
+0000190718 00000 n
+0000190907 00000 n
+0000191093 00000 n
+0000191283 00000 n
+0000191471 00000 n
+0000191663 00000 n
+0000191851 00000 n
+0000192040 00000 n
+0000192229 00000 n
+0000192411 00000 n
+0000192599 00000 n
+0000192787 00000 n
+0000192976 00000 n
+0000193160 00000 n
+0000193343 00000 n
+0000193533 00000 n
+0000193679 00000 n
+0000193783 00000 n
+0000193886 00000 n
+0000193989 00000 n
+0000194086 00000 n
+0000194183 00000 n
+0000194280 00000 n
+0000194382 00000 n
+0000194503 00000 n
+0000194610 00000 n
+0000194707 00000 n
+0000194804 00000 n
+0000194907 00000 n
+0000195053 00000 n
+0000195151 00000 n
+0000195258 00000 n
+0000195360 00000 n
+0000195457 00000 n
+0000195564 00000 n
+0000195661 00000 n
+0000195764 00000 n
+0000195861 00000 n
+0000195958 00000 n
+0000196104 00000 n
+0000196202 00000 n
+0000196300 00000 n
+0000196398 00000 n
+0000196495 00000 n
+0000196613 00000 n
+0000196734 00000 n
+0000196850 00000 n
+0000196956 00000 n
+0000197077 00000 n
+0000197175 00000 n
+0000197278 00000 n
+0000197424 00000 n
+0000197522 00000 n
+0000197620 00000 n
+0000233866 00000 n
+0000233892 00000 n
+0000234407 00000 n
+0000234433 00000 n
+0000234962 00000 n
+0000234988 00000 n
+0000235579 00000 n
+0000235695 00000 n
+0000235822 00000 n
+0000235949 00000 n
+0000236066 00000 n
+0000236183 00000 n
+0000236300 00000 n
+0000236419 00000 n
+0000236531 00000 n
+0000236648 00000 n
+0000236765 00000 n
+0000236892 00000 n
+0000237009 00000 n
+0000237133 00000 n
+0000237257 00000 n
+0000237374 00000 n
+0000237491 00000 n
+0000237557 00000 n
+0000237580 00000 n
+0000237918 00000 n
+0000237993 00000 n
+0000238474 00000 n
+0000238547 00000 n
+0000238750 00000 n
+0000238779 00000 n
+0000238876 00000 n
+0000238994 00000 n
+0000239108 00000 n
+0000239137 00000 n
+0000239203 00000 n
+0000239226 00000 n
+0000239589 00000 n
+0000239664 00000 n
+0000240290 00000 n
+0000240363 00000 n
+0000240552 00000 n
+0000240615 00000 n
+0000240712 00000 n
+0000240787 00000 n
+0000241017 00000 n
+0000241072 00000 n
+0000241155 00000 n
+0000241221 00000 n
+0000241244 00000 n
+0000241607 00000 n
+0000241682 00000 n
+0000242470 00000 n
+0000242543 00000 n
+0000242730 00000 n
+0000242827 00000 n
+0000242941 00000 n
+0000243007 00000 n
+0000243030 00000 n
+0000243393 00000 n
+0000243468 00000 n
+0000244067 00000 n
+0000244140 00000 n
+0000244340 00000 n
+0000244461 00000 n
+0000244590 00000 n
+0000244707 00000 n
+0000244773 00000 n
+0000244796 00000 n
+0000245159 00000 n
+0000245234 00000 n
+0000246048 00000 n
+0000246121 00000 n
+0000246318 00000 n
+0000246415 00000 n
+0000246533 00000 n
+0000246599 00000 n
+0000246622 00000 n
+0000246980 00000 n
+0000247055 00000 n
+0000247507 00000 n
+0000247580 00000 n
+0000247776 00000 n
+0000247873 00000 n
+0000247991 00000 n
+0000248057 00000 n
+0000248080 00000 n
+0000248441 00000 n
+0000248516 00000 n
+0000248838 00000 n
+0000248911 00000 n
+0000249611 00000 n
+0000249685 00000 n
+0000249885 00000 n
+0000249982 00000 n
+0000250100 00000 n
+0000250216 00000 n
+0000250282 00000 n
+0000250305 00000 n
+0000250641 00000 n
+0000250716 00000 n
+0000251206 00000 n
+0000251279 00000 n
+0000251467 00000 n
+0000251564 00000 n
+0000251682 00000 n
+0000251748 00000 n
+0000251771 00000 n
+0000252109 00000 n
+0000252184 00000 n
+0000252705 00000 n
+0000252778 00000 n
+0000252967 00000 n
+0000253064 00000 n
+0000253182 00000 n
+0000253248 00000 n
+0000253271 00000 n
+0000253634 00000 n
+0000253709 00000 n
+0000254317 00000 n
+0000254390 00000 n
+0000254587 00000 n
+0000254684 00000 n
+0000254802 00000 n
+0000254868 00000 n
+0000254891 00000 n
+0000255256 00000 n
+0000255331 00000 n
+0000255806 00000 n
+0000255879 00000 n
+0000256078 00000 n
+0000256199 00000 n
+0000256317 00000 n
+0000256383 00000 n
+0000256406 00000 n
+0000256763 00000 n
+0000256838 00000 n
+0000257630 00000 n
+0000257703 00000 n
+0000257902 00000 n
+0000258088 00000 n
+0000258275 00000 n
+0000258372 00000 n
+0000258490 00000 n
+0000258587 00000 n
+0000258705 00000 n
+0000258826 00000 n
+trailer
<</Size 340/Root 1 0 R/Info 55 0 R/ID[<9ACF01BAB32244F184A6B6A3D6DB10C2><8710EA5F576C4886B943D8D96EC67FE1>]/Prev 89924>>
startxref
258944
%%EOF
+342 0 obj +<</Type/Annot/F 132/V 340 0 R/DR<<>>/T(Signature1)/Subtype/Widget/Rect[0 0 0 0]/FT/Sig/P 59 0 R/AP<</N 341 0 R>>>> +endobj +340 0 obj +<</Type/Sig/Contents <308226FB06092A864886F70D010702A08226EC308226E8020101310D300B0609608648016503040201300B06092A864886F70D010701A08219EA308208553082063DA00302010202040100390A300D06092A864886F70D01010B05003063310B300906035504061302534B3113301106035504070C0A4272617469736C61766131133011060355040A0C0A446973696720612E732E31173015060355040B0C0E4143412D3330372D323030372D323111300F06035504030C084341204469736967301E170D3132303930333133323230325A170D3133303930333133323230365A304D3125302306035504030C1C44697369672044455620746573742034202D2050534555444F4E594D310B300906035504061302534B311730150603550405130E494443534B20535039383532373430820122300D06092A864886F70D01010105000382010F003082010A0282010100851B8BB0B1402455ADFAC35792DF63E2EA18CBDEAAF9C20DA4CE5F9F21CA9CAC1B7652D30E6B14295CF13C4D7E1AADDD7A6A09220A5CD38B192EDB2061BDF2AFA1632DDC6C1E42E4387A9691AC05DADF4DC7C3D61033A25FA2B6C3B7B21BCEDC91D1EBD14B9AB926193958D209BA9F406E22722BE0A3EF391A9141BD640DDA621B5FE1D680B5C2FD533E71AD1B9CCDA8206B6C43497412688D31D25B8E0D9C4591A830244A1C2EA055BA475D133DF18AC30B0A3955F3CBFB8C3B226A6C849882FC5CC8415BC7EA070F9D4291280C954EE9996A8D305ACB4A14650E7C69A32719E46B96103E3A19DD1954E25DC71F314F0CAAC00E40544357956E936FDDE049DF0203010001A3820425308204213081A906082B0601050507010104819C308199302406082B060105050730018618687474703A2F2F6163612D6F6373702E64697369672E736B303806082B06010505073002862C687474703A2F2F7777772E64697369672E736B2F616361322F636572742F616361325F64697369672E703763303706082B06010505073002862B687474703A2F2F63612E64697369672E736B2F616361322F636572742F616361325F64697369672E703763301D0603551D0E04160414EB00C2F5304C9E038D89D21C5626BE7AC97E8A393081980603551D2304819030818D8014157F5F5F08692AC67003A1FA516A4DAC8D5F9853A171A46F306D310B300906035504061302534B3113301106035504070C0A4272617469736C61766131223020060355040A0C194E61726F646E792062657A7065636E6F73746E792075726164310E300C060355040B0C0553494245503115301306035504030C0C4B4341204E42552053522033820200F4300C0603551D130101FF04023000308201380603551D200482012F3082012B300F060D2B811E9199840500000001020230820116060E2B811E9193E60A0000010001030230820102303006082B060105050702011624687474703A2F2F7777772E64697369672E736B2F5F7064662F63705F616361322E7064663081CD06082B060105050702023081C00C81BD54656E746F206B76616C6966696B6F76616EC3BD20636572746966696BC3A174206A6520767964616EC3BD2076C3BD6C75C48D6E65206E6120746573746F766163696520C3BAC48D656C792061206BC4BEC3BAC48D6F76C3BD2070C3A1722C206E61206B746F72C3BD20626F6C20767964616EC3BD2C206E656DC3B4C5BE65206279C5A520706F75C5BE6974C3BD206E6120706F6470C3AD73616E6965207072C3A1766E65207AC3A176C3A47A6EC3BD636820646F6B756D656E746F76306E0603551D1F046730653031A02FA02D862B687474703A2F2F7777772E64697369672E736B2F616361322F63726C2F616361325F64697369672E63726C3030A02EA02C862A687474703A2F2F63612E64697369672E736B2F616361322F63726C2F616361325F64697369672E63726C300E0603551D0F0101FF0404030206C0302206082B06010505070103041630143008060604008E4601013008060604008E4601043081CA06052B240803080481C00C81BD54656E746F206B76616C6966696B6F76616EC3BD20636572746966696BC3A174206A6520767964616EC3BD2076C3BD6C75C48D6E65206E6120746573746F766163696520C3BAC48D656C792061206BC4BEC3BAC48D6F76C3BD2070C3A1722C206E61206B746F72C3BD20626F6C20767964616EC3BD2C206E656DC3B4C5BE65206279C5A520706F75C5BE6974C3BD206E6120706F6470C3AD73616E6965207072C3A1766E65207AC3A176C3A47A6EC3BD636820646F6B756D656E746F76300D06092A864886F70D01010B0500038202010099DA573FFB82BAE560A23F10BAA0E2F35369EC43749D403E4DDF2AE70F73FAAB9D38511F71921E2830CBFD694FCA2BA1466E91D7911890AC0A3CF13704286BC243DB80D6B0D89EB28F44B82A75C9B805865312AB40CFD8E4B4903F547B024DA0527EC852E7B7584ABB0538A984DBE958F98D3302AE08B59DBB2E138451A649990D5384D76CDC7CEF4CCD40C13C655E15D48CC80A8D34E86BA6C82E431D991B344A515FD9E9EC684BCA53A87E750E6143B4A0870489D24B9CFF18355F386CF532C621800BC06872ABC5F4A034F596FBD5A245C5E00BAEC88509CEB4224FD12D6EB6A18CDE7036D4018B0399689DE88E2E7D731989F08D3F24F7A49C1623D6B433D23E6275B880A50516CEE0991939ECE72C3BA5774D0BF625CF884EE8DB35E049A5070D91070DA4516EA0EC0D520726E3756E82817173CBDE72D9CB8C8DA49D6FFFACDF975EB83E14B0206DABE96855E0ACE87E273D702ABCA6B010416882159817ABA835E0E8BB9557D9E7B5793BB9AD91D8E8C0C7015785A10948C1A02C0EA9B25C45B368B7DCABD46ABF825C5B56C90B07BE36119166552DD6DE51E46C9685C1B802C3CBE9637C59B1B48E14163ADD4D7055CDEBA74C135E1773B61C275D2ACE153AC444D6A496E9642D89B9996A7F61479ED32FBF03FD61A90D2B0947AD549F266499DC9EF8EAA4D749BCFCC2F1AB02E9435E15FF5FB82ADCB6DBCE5159CF3082088930820671A003020102020101300D06092A864886F70D01010B0500306D310B300906035504061302534B3113301106035504070C0A4272617469736C61766131223020060355040A0C194E61726F646E792062657A7065636E6F73746E792075726164310E300C060355040B0C0553494245503115301306035504030C0C4B4341204E42552053522033301E170D3039313130363039353933395A170D3235313130363037323930395A306D310B300906035504061302534B3113301106035504070C0A4272617469736C61766131223020060355040A0C194E61726F646E792062657A7065636E6F73746E792075726164310E300C060355040B0C0553494245503115301306035504030C0C4B4341204E4255205352203330820222300D06092A864886F70D01010105000382020F003082020A0282020100DBAAD08F2F4A9712D5B9EB7D59DC835C8B3117F2E56E5ECE2CD2C527DC67EAB38EF0D7052197D2940D5449B11F2BEDE4309C8D609372162F0E190AB7BEFF7FC918C9E44011CD5967B3844E848FE7C446A1BB8113E15C55BB23B98747E6C89886745C0920FCC55315D877667EBB63A92DB34BCA78F81C6F64D822BAA794C1D025F38F8314AFBADB5C5D2C57E277890C1C15226897C0B8806967F700B87330B8E231D67D9512BD0DEF2BD86B4816C92776D82D957F45AC0ABD1E129160F19C588EB62EEE8D42EB5A97E48220A8D930D5E0D486B1A19E5C4233A014A1611B69A626C78E6B8BC85C199AF820636FEEC7E115C2DE9B82B95FB502E9391176AD340076DD743B264DB8C4698642AE0F081DD4484AE2F5BD5EE6CB35B0420C14611C6F1DA7B563FD63885493EE40A477D4EDA782736257822D14B7D54D4EA1E78FC880DE160C833BD8093BE725489E4A946EAD6E61E1C8DFBE70215511D5E2E45B516EB13FB0318BD502964A83FD065FA94D2D19A940E385BFB88F5DAA0EE1848DEFAD4F90725FE6A255C984BC74233F79CA404D1291FD17DD2523661DC3C779AF14F99AF9BFED1FF4391627FCF0CCB01635D537E02E2CD4B0662C0EAE18019F8FCB9EB10FB91912820DC670500D7DE572CDDA8D096277ABF596392FE0C14E08DBC687317B2E79AAFB04A9686224ED0AC2483033FFED1E23B95B14BF456EA4D6DB35E8E30203010001A38203323082032E30500603551D20044930473045060D2B811E919984050000000102023034303206082B060105050702011626687474703A2F2F65702E6E627573722E736B2F6B63612F646F632F6B63615F6370732E706466300F0603551D130101FF040530030101FF308201580603551D1F0482014F3082014B3030A02EA02C862A687474703A2F2F65702E6E627573722E736B2F6B63612F63726C73332F6B63616E62757372332E63726C308190A0818DA0818A8681876C6461703A2F2F65702E6E627573722E736B2F636E2533644B43412532304E42552532305352253230332C6F7525336453494245502C6F2533644E61726F646E7925323062657A7065636E6F73746E79253230757261642C6C2533644272617469736C6176612C63253364534B3F63657274696669636174655265766F636174696F6E4C697374308183A08180A07E867C6C6461703A2F2F2F636E2533644B43412532304E42552532305352253230332C6F7525336453494245502C6F2533644E61726F646E7925323062657A7065636E6F73746E79253230757261642C6C2533644272617469736C6176612C63253364534B3F63657274696669636174655265766F636174696F6E4C6973743082013C06082B0601050507010B0482012E3082012A303B06082B06010505073005862F687474703A2F2F65702E6E627573722E736B2F6B63612F63657274732F6B6361332F6B63616E62757372332E703763307A06082B06010505073005866E6C6461703A2F2F65702E6E627573722E736B2F636E3D4B4341204E425520535220332C6F753D53494245502C6F3D4E61726F646E792062657A7065636E6F73746E7920757261642C6C3D4272617469736C6176612C633D534B3F636143657274696669636174653B62696E617279306F06082B0601050507300586636C6461703A2F2F2F636E3D4B4341204E425520535220332C6F753D53494245502C6F3D4E61726F646E792062657A7065636E6F73746E7920757261642C6C3D4272617469736C6176612C633D534B3F636143657274696669636174653B62696E617279300E0603551D0F0101FF040403020106301D0603551D0E041604147FF13D21C2975A2E97070EB1698325FD21863E07300D06092A864886F70D01010B0500038202010036DBF912E96542B2A3B989EE7BD91E726F6FA0B027C2A2EA8A9E17101DB69AC800B88ACB904B5E32DEB593F04582D8576AEF5F0700FD097BB7AB04E3B5FF9FC9381B5356954746FF072CD36E6929D7BF654394BC5CE9DAC12F79EBB25634768D8915B85CD37759B412B087F1068E55B357B4B96D0669D4C85DA460331C22588A686DDDE7BB53DB5A560F822D79770458E2E49F8CD4351C56D556079F8BA6783B7D982B3C55DFC37E3ACEEE56C55C9E2CAF2365E8F8C6D457399D17613136FBA0B9FD3A8DE91CFD57C7485639CECD6C309C992356989A46ED850207210579B0ADFF06ABFCF48F19C76081C154CCFDD833CDC76C36F87445691BDEA2BDB55AA12726B6906085083FA1E82C9AD5DE931386960EE6F57405F82F5C3596A75AC06E2B9F3F878681B9662A1417335D14911824274245C6EB1B40EC3B6E489F519955B3BA9A159CA1FEAFC0A5B87139272A2D3D3147B9975AB9A0ABB556C2330E29B29947B4076B06E725A7902633F7505A61075A6EBD75165C222AB88C37395771DE050BFA3A32F3CD3EF516CE488457DC20F36BB3B6228036A45A15870EF2C1D86A3C78218D6410B8BD4D479CB6E58BD848DA369F4E2676CBD985C255E9AD6FD3D461D646FA05A91F90E5100C61B0CA58FAA1FBC75B2E9EEE0DB7021999D04A646EFA303C33D2608F826612A2EB3DD50401A9E4E19778469E589493C7C5D9A3497AC030820900308206E8A003020102020200F4300D06092A864886F70D01010B0500306D310B300906035504061302534B3113301106035504070C0A4272617469736C61766131223020060355040A0C194E61726F646E792062657A7065636E6F73746E792075726164310E300C060355040B0C0553494245503115301306035504030C0C4B4341204E42552053522033301E170D3039313230383132343733305A170D3139313230383132343632355A3063310B300906035504061302534B3113301106035504070C0A4272617469736C61766131133011060355040A0C0A446973696720612E732E31173015060355040B0C0E4143412D3330372D323030372D323111300F06035504030C08434120446973696730820222300D06092A864886F70D01010105000382020F003082020A0282020100BE0502722CB7A5C658D646006F68A1E9234DB62EF65413927048A2A0282DE67A00E594F98669C5C5D48A9CF848677631AE0A3EB0271777FF57399051B80A3BDD27348A9B29FB32BC674FC7D104EE109A3FB3F3BADB12BBB92F45BCE558E2A9D1E4D913242F1A13F56539A2078161FD6E787969E81F88A3284FD04FB3FA44F95D4A85E4E8288EC32BD92A5AEFFF9226D23993E20F9948C24455449A38D809ECC185CAE672D8D76BEB658A31901AA474506A2AD3BF84D482A0474D345419E737CA50CDDEB9A21E67ECAC257D91AC05645D04F2A32A54180D2991D2EFDDBC04E27CB713E8F9167D1F3AF9F9ABE261E7BA211F0438ADA3B555973C5B1FC3C191F513AE1610C4FACCF7FC6F65BBC19AD870B005E227DA3B12CA375C9E3908CB2F4368FB5B0B8DCEF9E3473145647B3B9B9A9AB7C646FA892D893170E058458AB446D4CA7765DDE1AC44E483FD0D35C34E56E9FA740C98930A4C68FEFCDA5690B50657903B57C4C4999D3C48A4B7D4F97119F8033C9FB4ECDF367866391690410F300783F70F6D416BD1A87DF3DD9A37767872799AAF74A5C759EB7DF268BB01868F1D1B61A2B12429B08EB5181EBF3842B7ECD002DC2500DCCEB426B2ECDB6BE784394CF65807D29938EE7711EF1666B0847F519D9141C15D89E276CAD3AAAF3C1E1668DE5ED4FAC1B980336F055E887FBE9DF33257C0FBA2EF04B0070BAADD4AA39B0203010001A38203B2308203AE30120603551D130101FF040830060101FF02010130530603551D200101FF044930473045060D2B811E919984050000000102023034303206082B060105050702011626687474703A2F2F65702E6E627573722E736B2F6B63612F646F632F6B63615F6370732E70646630420603551D21043B30393017060D2B811E91998405000000010202060604008B300101301E060D2B811E91998405000000010202060D2B811E91998405000000010202300F0603551D240101FF040530038001003082014006082B06010505070101048201323082012E303F06082B060105050730028633687474703A2F2F65702E6E627573722E736B2F6B63612F63657274732F6B6361332F6B63616E62757372335F7037632E703763307A06082B06010505073002866E6C6461703A2F2F65702E6E627573722E736B2F636E3D4B4341204E425520535220332C6F753D53494245502C6F3D4E61726F646E792062657A7065636E6F73746E7920757261642C6C3D4272617469736C6176612C633D534B3F636143657274696669636174653B62696E617279306F06082B0601050507300286636C6461703A2F2F2F636E3D4B4341204E425520535220332C6F753D53494245502C6F3D4E61726F646E792062657A7065636E6F73746E7920757261642C6C3D4272617469736C6176612C633D534B3F636143657274696669636174653B62696E617279300E0603551D0F0101FF040403020106301F0603551D230418301680147FF13D21C2975A2E97070EB1698325FD21863E07308201580603551D1F0482014F3082014B3030A02EA02C862A687474703A2F2F65702E6E627573722E736B2F6B63612F63726C73332F6B63616E62757372332E63726C308190A0818DA0818A8681876C6461703A2F2F65702E6E627573722E736B2F636E2533644B43412532304E42552532305352253230332C6F7525336453494245502C6F2533644E61726F646E7925323062657A7065636E6F73746E79253230757261642C6C2533644272617469736C6176612C63253364534B3F63657274696669636174655265766F636174696F6E4C697374308183A08180A07E867C6C6461703A2F2F2F636E2533644B43412532304E42552532305352253230332C6F7525336453494245502C6F2533644E61726F646E7925323062657A7065636E6F73746E79253230757261642C6C2533644272617469736C6176612C63253364534B3F63657274696669636174655265766F636174696F6E4C697374301D0603551D0E04160414157F5F5F08692AC67003A1FA516A4DAC8D5F9853300D06092A864886F70D01010B05000382020100D96925EA8ED9E68FF70B544536BE5CBC6C5723924715241DDEF671BA9C14B2370A52FC8320D99E5831C712462CA75E33C248D3FEE20E273305B764C5C927E4C18D70E5522C14A1C79D68EDE3C45306F01144008DEA89111E72639CA7767077CD992E95287FCA9F5ED856B6A95700113DEDD0385C8C9F6EDD0388DBCFD379A844B6BC82DC1048DED0C8B154342AE544DA07E43B240E74691C9CC227884DA5C6A084D2E99359841F38DBF0C3EBB8ECE152D1226FF582D2D8EB82A6CCCFD737393D11D629224B42E853E22C35A420A5756DFD44E44ED61E5FEB318F576CB6542E5795B59F3035129DD4EFAD31AAE6BBDE982F6FEA312ED9BED107D9908221A423F174845045F6C6FE78A08EA9AEC1D17B20E8694E6D02CCD1F1B6F23B5D90D4AB7AF26E44EACD9E2B167373AAC24D50D65D90112EDD3BFF7ED8C7C853752C4B8B9FA3D21C777E6CC23C51906FEDD2146280622F543D00B021FE5DF4C1C8A753F6481B6986C3052CF0A5FB7F0AE0F8D48BD0F70A6AD41F958CFDE9B27B21C295481FE27D25CE540C0B3AAF5EFDE57F7D77FF163A17B4A630DC5701C7A5C0E4D25FBFF36CE488B4012CF43B14AC0B79F4D48C7EB67519DF59AFD995D817617498408DC4F6140857E2185C88830EE9B8928E56427DDAC94393E1CE446C742C6CC2287DA835ED1A17CD5F5A48CC894E6E44708414D56C90D7DC120A5A32AF3686B1304D31820CD730820CD3020101306B3063310B300906035504061302534B3113301106035504070C0A4272617469736C61766131133011060355040A0C0A446973696720612E732E31173015060355040B0C0E4143412D3330372D323030372D323111300F06035504030C08434120446973696702040100390A300B0609608648016503040201A081D8301806092A864886F70D010903310B06092A864886F70D010701302F06092A864886F70D010904312204207F16625DD84186495A4CEDFF59B05A1A008D27DD56874F16B48D9F3FE44B205D3037060B2A864886F70D010910022F3128302630243022042015C36FE3F117921FADCF4EDCBE9EECCA20D81C74ED08C3D2DBAD43087FB1EEF43052060B2A864886F70D010910020F31433041060E2B811E919984050000010A04000C302F300B060960864801650304020104207A4C03779BD2C51BCCBD73668A3C30110D7451D9222B4732681866EAEF961E65300B06092A864886F70D0101010482010008916912CE6ADBDB79AC15589EEC96CEDCF2ADCF0370329BE10FDAEB7D2B7F03F6025CF89FD1E406AF4365C368DF9D411C89B0D6EDB435159FB77D9CC2C3C11A15BFC5EE6A022723F89980C615DD5DF3FDD70A158224AD8A9AB7E82A7979585796127E7AB64ACE2BA94391FDAC151071A16A8306B47E48849750908EA396A531178D998A0723E8850ED101EDCC5D2F6CB1929DE5AE563E2DC87920D22FABB3E5F9EF03451F8D6EFA70A23E2D777607EB6FDD113DF4D902E5DDA8404E6D3D364B5DCF4D58F7B84CCFE0745CAD6463D595E6034C6CF10A7C9334702838EBD2728C22E4ACF9F24B1F153ED3C67B898BED04D6A9FB215F61A5160162CAAE38F68B3DA1820A6630820A62060B2A864886F70D010910020E31820A5130820A4D06092A864886F70D010702A0820A3E30820A3A020103310F300D06096086480165030402010500307F060B2A864886F70D0109100104A070046E306C020101060E2B811E9193E60A000001000402003031300D060960864801650304020105000420FCCE78095CE7663D47825CB034C507B1BBD33B8A36632801EF4AF94665288F4902031DA26E181332303133303430393132333433302E3838385A3004800201F402046174B99EA082076C3082076830820550A0030201020204010036E5300D06092A864886F70D01010B05003063310B300906035504061302534B3113301106035504070C0A4272617469736C61766131133011060355040A0C0A446973696720612E732E31173015060355040B0C0E4143412D3330372D323030372D323111300F06035504030C084341204469736967301E170D3132303631343132343833335A170D3134303631343132343833335A3081A0310B300906035504061302534B3113301106035504070C0A4272617469736C61766131133011060355040A0C0A446973696720612E732E31173015060355040B0C0E4143412D3330372D323030372D3231373035060355040B0C2E416B72656469746F76616E6120736C757A6261207679646176616E6961206361736F76656A207065636961746B793115301306035504030C0C54534120434120446973696730820122300D06092A864886F70D01010105000382010F003082010A0282010100B26E4793158A1DF2C8334676EBA81CC02B5D0E2EAF7E432F42646C3AAC8285E1DABA6C47AEA70592F1067A259B5B8481AFE6C840A8B5EE37F74CAC633623830624B5A52011E1297E4FFB7B6EDBA26549E3A4752A76A251F11BA54F65B08B78D0CCD2E7DCA808F2551E3A04286F39E6CFA430221CA188F7609B85B10BDE958E3629A9BFA5E8754E7D908D4A5842A2EF543C17589B496727475FB9C29E451661A3466120D8075C30D47FF903A528BF157905100030DF3BAF81E30E99817D1BC5BB073AE4539D0148F8504DCC6DE2A7CFD7A076C37AC21C112182800EBB806B1EA8FFE14E5A6B8EBCB69EA72E5BD5129F55FC9AE19A10EE78C1E92F4765980A87A30203010001A38202E4308202E03081A906082B0601050507010104819C308199302406082B060105050730018618687474703A2F2F6163612D6F6373702E64697369672E736B303806082B06010505073002862C687474703A2F2F7777772E64697369672E736B2F616361322F636572742F616361325F64697369672E703763303706082B06010505073002862B687474703A2F2F63612E64697369672E736B2F616361322F636572742F616361325F64697369672E703763301D0603551D0E04160414DF279B25630002C0474CD2DF945BAA6B004A2B623081980603551D2304819030818D8014157F5F5F08692AC67003A1FA516A4DAC8D5F9853A171A46F306D310B300906035504061302534B3113301106035504070C0A4272617469736C61766131223020060355040A0C194E61726F646E792062657A7065636E6F73746E792075726164310E300C060355040B0C0553494245503115301306035504030C0C4B4341204E42552053522033820200F4300C0603551D130101FF040230003081B60603551D200481AE3081AB300F060D2B811E919984050000000102023008060604008F7A01023044060E2B811E9193E60A000001000103023032303006082B060105050702011624687474703A2F2F7777772E64697369672E736B2F5F7064662F63705F616361322E7064663048060E2B811E9193E60A000001000402003036303406082B060105050702011628687474703A2F2F7777772E64697369672E736B2F5F7064662F63705F7473615F616361322E706466301C0603551D1104153013811173707261766163614064697369672E736B306E0603551D1F046730653031A02FA02D862B687474703A2F2F7777772E64697369672E736B2F616361322F63726C2F616361325F64697369672E63726C3030A02EA02C862A687474703A2F2F63612E64697369672E736B2F616361322F63726C2F616361325F64697369672E63726C300B0603551D0F04040302064030160603551D250101FF040C300A06082B06010505070308300D06092A864886F70D01010B050003820201003E7D012645CBCC25D661B3F6188D2AD8E89AE369CF5323159A4824956B4C49FC7BC76688FD193A794340F2C62406504C781815BA3D3E14F2C024807EB1653006FC3B2D35CF8AFBE61B0DD10C6599DB7AD16BF0F9D229163A00700534A9F8487356982741B8B79B2A8138ECBC781DF38EA3BFEDC1BE939467E8C059645745F4B6F05BDCBFF0DEBA077D276C217A76DF5E180E86DE7030D6E75DC7352ED04E27FB1E6B81DF448DE9639DFE07A3FF9E7270B1476CA72E4DBEA7E9F0C88B8D0AA6DE260372A2014E229FEB5BEC743FD038B705AC84B4C0733D1A1654FFC22C6ACDB7878CD034759E01720C9C8A1A88105CCBACFD885391DC533450DB119483F276F16CDAC0EAAFBD388C9D790A68FAA50C95AA089ACF99A58C2CA5E09424401529D124E08124833E01F38B04F18192F1BEA62F363135C4BD361218EDCA808AFD0FBFA7B38B70B4E417AE8F2B618320840DA2F80BE9F9B8BCE5B479D1B8662EC219C8E47BE97804D449BD611006BCC4E064F4B7E36B0F54DA3529F2FCC7FF5D16D0999EF4AEF1D272608CEFC3C2ED42DAFBF586BE4E8625A61EBC78576ADD5AA0D54E141FFBD6DBF81DEBE25ED723A0813EF9EEDCBAE1EB22E883FAD681773AF364840EBEB0F86F83104696BD4D5248E5505102098298478434A4A9E134E6230FC16C271B8C19EB483ED744EA1D72705BB6B42C75EBD1B9923FB9DCFE263EB86B25AD318202313082022D020101306B3063310B300906035504061302534B3113301106035504070C0A4272617469736C61766131133011060355040A0C0A446973696720612E732E31173015060355040B0C0E4143412D3330372D323030372D323111300F06035504030C0843412044697369670204010036E5300D06096086480165030402010500A08198301A06092A864886F70D010903310D060B2A864886F70D0109100104301C06092A864886F70D010905310F170D3133303430393132333433305A302B060B2A864886F70D010910020C311C301A301830160414E64E7382EF25C14F926EE7EFDD869676C685EBFF302F06092A864886F70D010904312204204E2B7B76031C4653476A4A93F1763B491335EC0EA5307E7DF5A4783B5FA8E688300D06092A864886F70D0101010500048201003C36E6ED3FC118CEA31050F913221DAC506A96CBE40C78327927A133137C2A44EE7A9DF95211CA9ADE1C0E566A8E6EE1765004B8A089F22DCAD2AFA677EF4B1FD01274854642C9C6B95071586F771BD6907D53579C5CD5ABEED46D757460D18B3D0D450F46CBC0FCED9023EB7D7A157687296A6A8C5844AEDE22625DE10CEB6AD635AB3BC78600989BCE6E9A0236062194F7DA3DB91B3463034301F9217E6B5D0FDEBBD2B953DF9EF4B848442737E3FE098FC2ED5779F1C691F400FAE2734849CF74DF7B02899B49BE2A3E46D624F272201CF2D34DDDDF38DC882771AAB41F792B691C307406DF02433577B104A92ECB0F7D5D97F4FE1C20EA42FC61C284888B0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000>/ByteRange [0 265190 285672 47313 ] /SubFilter/ETSI.CAdES.detached/Filter/Adobe.PPKLite/M(D:20130409143422+02'00')>> +endobj +343 0 obj +<</Type/Font/Subtype/Type1/Name/Helv/Encoding/WinAnsiEncoding/BaseFont/Helvetica>> +endobj +344 0 obj +<</Type/Font/Subtype/Type1/Name/ZaDb/BaseFont/ZapfDingbats>> +endobj +341 0 obj +<</Type/XObject/FormType 1/Subtype/Form/BBox[0 0 0 0]/Resources<</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]>>/Filter/FlateDecode/Length 8/Matrix [1 0 0 1 0 0]>>stream +xœ +endstream +endobj +2 0 obj +<</Type/Metadata/Subtype/XML/Length 44744>>stream +<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?> +<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 4.2.1-c043 52.372728, 2009/01/18-15:56:37 "> + <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> + <rdf:Description rdf:about="" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" xmlns:stEvt="http://ns.adobe.com/xap/1.0/sType/ResourceEvent#" xmlns:stMfs="http://ns.adobe.com/xap/1.0/sType/ManifestItem#"> + <xmpMM:InstanceID>uuid:7e7b597d-426f-3642-8dca-bcbf37236e1d</xmpMM:InstanceID> + <xmpMM:DocumentID>xmp.did:89321C534E266811A613EDAC20FB34D2</xmpMM:DocumentID> + <xmpMM:OriginalDocumentID>adobe:docid:indd:924fbc79-cadb-11de-af61-e97e2740acd1</xmpMM:OriginalDocumentID> + <xmpMM:RenditionClass>proof:pdf</xmpMM:RenditionClass> + <xmpMM:DerivedFrom rdf:parseType="Resource"> + <stRef:instanceID>xmp.iid:88321C534E266811A613EDAC20FB34D2</stRef:instanceID> + <stRef:documentID>adobe:docid:indd:924fbc79-cadb-11de-af61-e97e2740acd1</stRef:documentID> + <stRef:originalDocumentID>adobe:docid:indd:924fbc79-cadb-11de-af61-e97e2740acd1</stRef:originalDocumentID> + <stRef:renditionClass>default</stRef:renditionClass> + </xmpMM:DerivedFrom> + <xmpMM:History> + <rdf:Seq> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E4B6ED806F256811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T11:39:47-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E5B6ED806F256811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T11:39:47-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/metadata</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E6B6ED806F256811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T11:44:22-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:80321C534E266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T11:46:03-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:81321C534E266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T11:48-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:82321C534E266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T11:49:01-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:83321C534E266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T11:52:39-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:84321C534E266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T11:58:06-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:85321C534E266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T11:59:50-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:88321C534E266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T12:03:27-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/metadata</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:89321C534E266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T12:03:27-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:4A27385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T13:48:01-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:4B27385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T13:50:54-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:4C27385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T13:54-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:4D27385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T13:55:16-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:4E27385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T13:56:27-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:4F27385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T13:58:44-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:5027385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:05:30-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:5127385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:07:25-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:5227385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:12:43-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:5327385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:13:56-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:5427385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:16:22-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:DE855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:19:25-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:DF855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:27:07-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E0855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:29:58-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E1855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:32:34-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E2855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:33:46-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E3855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:40:42-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E4855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:41:28-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E5855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:42:42-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E6855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:44:36-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E7855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:47:08-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E8855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:51:29-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:80C8B5F5A22068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T10:49:23-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:81C8B5F5A22068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T10:50:43-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:82C8B5F5A22068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T10:52:12-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:00CECC59A92068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T10:53:23-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:01CECC59A92068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T10:53:56-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:02CECC59A92068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T10:56:41-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:03CECC59A92068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T11:03:21-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:04CECC59A92068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T11:06:47-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:05CECC59A92068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T11:09:26-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:06CECC59A92068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T11:11:53-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:07CECC59A92068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T11:13:29-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:999093B2AD2068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T14:21:34-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:9A9093B2AD2068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T14:27:38-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:9B9093B2AD2068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T14:30:31-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:371C0BE61C2368119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-07-02T14:20:55-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:381C0BE61C2368119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-07-02T14:26:33-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:391C0BE61C2368119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-07-02T14:29:07-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:3A1C0BE61C2368119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-07-02T14:31:19-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:7A0142B9242368119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-07-02T14:41:33-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:7B0142B9242368119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-07-02T14:44:10-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + </rdf:Seq> + </xmpMM:History> + <xmpMM:Manifest> + <rdf:Bag> + <rdf:li rdf:parseType="Resource"> + <stMfs:linkForm>ReferenceStream</stMfs:linkForm> + <xmpMM:placedXResolution>72.00</xmpMM:placedXResolution> + <xmpMM:placedYResolution>72.00</xmpMM:placedYResolution> + <xmpMM:placedResolutionUnit>Inches</xmpMM:placedResolutionUnit> + <stMfs:reference rdf:parseType="Resource"> + <stRef:instanceID>uuid:288c3c69-7dd6-7c4f-984d-b085b3307748</stRef:instanceID> + <stRef:documentID>uuid:93F9F49755C5DE1185BCB9A8461E73D9</stRef:documentID> + </stMfs:reference> + </rdf:li> + </rdf:Bag> + </xmpMM:Manifest> + </rdf:Description> + <rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpGImg="http://ns.adobe.com/xap/1.0/g/img/"> + <xmp:CreateDate>2010-07-02T15:32:26-07:00</xmp:CreateDate> + <xmp:ModifyDate>2013-04-09T14:34:22+02:00</xmp:ModifyDate> + <xmp:MetadataDate>2013-04-09T14:34:22+02:00</xmp:MetadataDate> + <xmp:CreatorTool>Adobe InDesign CS4 (6.0.5)</xmp:CreatorTool> + <xmp:Thumbnails> + <rdf:Alt> + <rdf:li rdf:parseType="Resource"> + <xmpGImg:format>JPEG</xmpGImg:format> + <xmpGImg:width>256</xmpGImg:width> + <xmpGImg:height>256</xmpGImg:height> + <xmpGImg:image>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 +xV2KuxV2KpL5z/5Q/Xv+2bef8mJMVf/Z</xmpGImg:image> + </rdf:li> + </rdf:Alt> + </xmp:Thumbnails> + </rdf:Description> + <rdf:Description rdf:about="" xmlns:idPriv="http://ns.adobe.com/xmp/InDesign/private"> + <idPriv:DocChangeCount>244</idPriv:DocChangeCount> + </rdf:Description> + <rdf:Description rdf:about="" xmlns:dc="http://purl.org/dc/elements/1.1/"> + <dc:format>application/pdf</dc:format> + </rdf:Description> + <rdf:Description rdf:about="" xmlns:pdf="http://ns.adobe.com/pdf/1.3/"> + <pdf:Producer>Adobe PDF Library 9.0; modified using iTextSharp 4.1.6 by 1T3XT</pdf:Producer> + <pdf:Trapped>False</pdf:Trapped> + </rdf:Description> + </rdf:RDF> +</x:xmpmeta><?xpacket end="w"?> +endstream +endobj +59 0 obj +<</Group 64 0 R/Resources<</Font<</C2_2 58 0 R/C2_1 57 0 R/C2_0 56 0 R>>/Shading<</Sh6 150 0 R/Sh5 149 0 R/Sh4 148 0 R/Sh3 147 0 R/Sh2 146 0 R/Sh1 140 0 R/Sh0 139 0 R/Sh14 145 0 R/Sh13 144 0 R/Sh12 143 0 R/Sh11 142 0 R/Sh10 141 0 R/Sh9 153 0 R/Sh8 152 0 R/Sh7 151 0 R>>/ExtGState<</GS13 203 0 R/GS12 202 0 R/GS11 201 0 R/GS10 200 0 R/GS9 214 0 R/GS8 213 0 R/GS7 212 0 R/GS6 211 0 R/GS5 210 0 R/GS4 209 0 R/GS3 208 0 R/GS2 207 0 R/GS1 199 0 R/GS0 91 0 R/GS16 206 0 R/GS15 205 0 R/GS14 204 0 R>>/ProcSet[/PDF/Text]/ColorSpace<</CS0 85 0 R/CS1 100 0 R>>/Properties<</MC0<</Metadata 192 0 R>>>>/XObject<</Fm9 82 0 R/Fm8 81 0 R/Fm7 80 0 R/Fm6 79 0 R/Fm5 78 0 R/Fm4 77 0 R/Fm3 76 0 R/Fm2 75 0 R/Fm1 66 0 R/Fm0 65 0 R/Fm17 74 0 R/Fm16 73 0 R/Fm15 72 0 R/Fm14 71 0 R/Fm13 70 0 R/Fm12 69 0 R/Fm11 68 0 R/Fm10 67 0 R>>>>/Type/Page/BleedBox[0.0 0.0 841.89 595.276]/Contents 63 0 R/CropBox[0.0 0.0 841.89 595.276]/MediaBox[0.0 0.0 841.89 595.276]/Parent 3 0 R/Annots[342 0 R]/ArtBox[0.0 0.0 841.89 595.276]/TrimBox[0.0 0.0 841.89 595.276]>> +endobj +3 0 obj +<</Type/Pages/ITXT(4.1.6)/Kids[59 0 R 5 0 R]/Count 2>> +endobj +1 0 obj +<</Type/Catalog/Metadata 2 0 R/Pages 3 0 R/AcroForm<</DA(/Helv 0 Tf 0 g )/Fields[342 0 R]/SigFlags 3/DR<</Font<</Helv 343 0 R/ZaDb 344 0 R>>>>>>/ViewerPreferences<</Direction/L2R>>>> +endobj +55 0 obj +<</Creator(Adobe InDesign CS4 \(6.0.5\))/Producer(Adobe PDF Library 9.0; modified using iTextSharp 4.1.6 by 1T3XT)/CreationDate(D:20100702153226-07'00')/Trapped/False/ModDate(D:20130409143422+02'00')>> +endobj +xref +0 4 +0000000000 65535 f +0000332170 00000 n +0000286235 00000 n +0000332100 00000 n +55 1 +0000332368 00000 n +59 1 +0000331055 00000 n +340 5 +0000265159 00000 n +0000286029 00000 n +0000265027 00000 n +0000285851 00000 n +0000285951 00000 n +trailer +<</Size 345/ID [<72e46b7e882d7f42edc548905fcedd4f><e8a97564aad74aa17002cb23c576d1e3>]/Info 55 0 R/Prev 258944/Root 1 0 R>> +startxref +332586 +%%EOF + +345 0 obj +<</Length 1617/Filter/FlateDecode>>stream +xœÝUkPWÍn6BTŠøXn +¨ˆA!D| é’D’¨¥$ƒ´>bŽÔt@E«V-"¢ Q”G´ø +Ž+pI1=Ï~\¤ +{e¨ùíóýacj,žðe\]Ix(¯Ë»×Iû²¬$8~jÆÎ)³AóÙò«>ÖEJÓmÓ„å´ƒAÈly·=¿íø½'¿ªöμRM)ä+¿~§§rGXâ0Ï’×”Ð{zÕÒ³”à#íý«^àcö§JβâŘü‚ÛŠŽ—]¿°@’âzk[ÍØ'?ÔÄæN6{.ÞíÆ^åÎËdbÜJË×ÈæÖØâ¡ s„ÁŠgþ—¦å;ÖK5eO-ÏŠ^ý¼?º±ÛñXÓ&‡–JÏå7XÊ*ë¶ûê¹· d³´¤o;ûKûæ?Œa^ÏK‹Ý¦·U´†¦fV礸µt›ÝCz}çÌæ9þ5ãú7q}ísºcÚ1LvŒÒx¥e€‘`7ó×L¥AŸ¡m¾¯¹Û¼ÍXZ¢*ïú.¥:Ôå8š^Ö/t—÷åÍZ¨ö>wèø˜©ÁuÏø²ÃsºûÎîNºÛ{*gþ™ +Ó¾úËPÒ&«Ã’_æ‘“ÉÑ?IOw”ÝJ;oH^»òŠ£]Ýܱ¦õVÛýøEѦհ¹_´qõ‰Êí.nó:yjÁµG?,sN¯š4kw‹ë¼‹Qm¥EýbÖæ3æ´¯°Å{oú'¿ÁŽ0|W$î›)6wìýûaéí˜s¯Ëà~nŠë°Ú»£ª½%~õõ +endstream +endobj +346 0 obj +<</Length 1783/Filter/FlateDecode>>stream +xœ3hâd0hb{±€™‰‘‰‰‰á‹/§V›GÛw^FFnVƒ\CnN6æP6a¦`oCaA‡‡Ë©(±$³8'±,ÑPÉ@$ÈÅ#é—X”Ÿ’W©”ZUšœ—_\ä”%¦òð€Ôpó°{:¹ŠƒøÌ<<ÞÎŽ +~N¡ +ÁA +Ærâ¼–†F†F&æÆQ⼆0®™‘i”A2Î +rñp¹dg¦+$ê늈BìçstvÔ560×52 +«èK Mµ\ÄÞ˜ø7¯¢2ó…|Çb
ÿþ›¹üŒõj}òB£ï°öM¨÷ÿ'©]²œüˆ¦Ç!—P—Y78ßl=õ¬èÆõìש]†¤–”di]Þßr¥i»¯IˆäsóSgïí\$—þfjíÄ5¬)±,Ÿk…HðjN¼ôþî–G5Û…_ü«•·úùsõ£Äç»åY,Ö.Þ:Ý&ZþðÁ‰_…׉ ùuæûŸüÔÝgÝ(ØÀúHý–µÐ)ó˜y–§õ3~Gs÷žûùØÝÐ5¥Úzö¬YÛ¹ýêÔí4,xáÚµÅíÊ©òԻ׸<iþËkzØ/ì寞“¹|2þý¹6a+[øëð#GfεñX²ýÊÏBÉÌ6ó·¼¹oV‘f)6Á‘߀½ù;®cöŵŸïÎ2/«(ªœµ¾déñÈ×µŸ2v3¶õËJ'.Ú¨¢¹¡o«„Ü~§ío.0ÝQe¸sn‹Ú¦7·³Ÿ·Xú|‹`¿4Óâ]¹à{±´
-õs':Œí|Tvêòªõ6rb÷â®ü:¸³Á8Ÿ5®£~ßÜÏFá~/zϲ{Õ]¯Å³™˜71o2hb^g L>²ÂŒŒÿY8Ø€#£A0HL$æiànàÊÆ«Ý(7qf+0›˜±qh³1²²²31Š©e””Xéë§èå%•égëg''ê§ä'ƒèøä‚b½‚”4'¡Š,Ö–âh&²±±0t +T~P ² +Y>1ÑúøxŽLcÌfù®éŸŒV½1ƒŠó›™ª¯ún>ëÿÎâj¶/fON¸ò$wQÙ{ß +wÍÙdÎô§Yáæ¼ÃãBn:ËãŒy\þ÷ˆOݘu{ÊÑ“êOö<
ÒYx|nÆÛÇG‚Ù>º0ô¾ê”+Jž³¼¬ üìL½©õ§æÇÝÛ¶2œAÐö틘žùyw™;nŸ¿\¹ÂeÛž¦;÷.œØb¢õÔåûk¾’L™9‡Ô;|—[ÐréåäÈy‹Û¿ÞñæaÐE¥ü¯M—n¼nZvæüusK[ÁkšJÞN/‚é˜.QXZšû×å‰ß5¹ø׆ýá9ÛBô§no`*4÷Êûµ†«ží¾7C?ÿ•¡ÞÍ}ÙoNhR\¢ü±¤%ÀõÛ±úV®;x±ZáE¦_.Ó™‹·}²ŽpeuÕ§<—Wgçi‹¯:äp-v‚ Þ]ëÿu7ŽŸ.Õñîž¿ø’Ly]Î!›À ùo/‰$5$é‡Ø2lPüûåà‰åÁß<¤3Û³ê|Xú»žëÁ+ݾse]‘ŸÚó÷å¦jÅCS=äÕªžáá¶Z÷÷i}mù1+ñ-Ëî„3_zàÉ¥øýŸsžtlaÔùb-²†»òË•žºm¥’÷#×ßœzC<±d†Cï‘o"á$b:šù^î˜ÔæT{ë¤óä‡ç\rJtriÔ®0}+%~6>ÊãL§_žKA‹ÈÕœ ×ïqE7kÛhà +endstream +endobj +347 0 obj +<</Length 1659/Filter/FlateDecode>>stream +xœ3hâè4hb+\ÀÌÄÈÄÄÈhÀËÆ©ÕæÑö—‘‘›•Á ×Û€“9”…M˜)ØÛPØ@Äaçár*J,É,ÎI,K4T2P +C¯>z˜·Ñ~ƒa÷U¦i^ÍÙâWúêJ®txܺGì*¾‡-½ï×úO(Š¶(ôdËžeûÊS¾BÿŠßUUN“=|¼r½ÈÏY?÷¿•ÿb)¦þçÙ
b¦WÍèé\٦÷N‚q~ÿéyùwJ +5ñ+à}ZtöV/gRùê¯Ó,õôã¸}¬Ý°Z¯rÕo–•I*o¹yÿ+§¼3Zd¿kÞ’k·M_<fbfd`\ÜÄldÐĬg +,žî®l¼Úrg¶°200 +endstream +endobj +348 0 obj +<</Length 4927/Filter/FlateDecode>>stream +xœZytVU’'!„ì!!_"ä#$Iî[¿÷Â’¢jkp +†5>²¿ÿ9Û‚ùXv[Ã/D`ÏbǾFv[–o{ƱG%ì£cmÛÀ§ˆ!° +œ¥á/4ܵï}& +ÛÚß½ÇjB + +@Ðo2¼š²X* +‡!ÿ~e72è¦Ãÿsâ Š©Ë<É__ÄM<´>Úßù [4OòÉM 0 >àq
¿§öF…pägafÀ¾ÕDÈ4°F[Ò÷ߌº‹ˆ†R£mãa¸^¨ñ-ÄØC¾j»JÆaÏ´Òð +$8klÁÕÒnÐøÁbZð¡:%*„ãrM‹%«X‚G°fêXÆz*â +ËŽ%Ú1B¬X=µ>Ò>‰
”°/óر«(¹ìOÌ&?%Kp°ñYðbÓ‰l3 +©=pÊ9±7TtŒ¾ËüŽýE®0ò²ª0à˜Ú&Ó +3–=«Oaf¶˜U…q†íÈœVèìC“2íGkØ™W72ìÛ¦Ã+|PÙµ+„†¡ÈC7èÜîS‡W½½Ç«Œ¬ò¹D~cVã4ÙŠ&P½´ Wx‚)zŠ„¦:
§"Œš‰Ý:7¬Å™ÜÍ€>p,‹+hüaªkq¥†ƒ¶Á0_Bêð#ï¢2ŠÓãé¨ø)rd‚cæù’¸ÊÔ4Ë›õÛuÌÕG f1t2 êXxue1ÐÇ6—G%w“˜ÊÜdž”ì>x 5÷þ„WÛ¨Vþœa¬^úð%#yFáxCp¿\çQ$õáû0p„>ý¶³Úc—¨C\Z!Oiã=DäF¤4(Òƒ$t¼"v¥ ¨ÚÀÒ_ +Ö“ø«äX˜/-ÓøÅ_§räcSÎI?+O)¥Ú5-hü¼>òŠp`œà;VˆõšX‘Ø’Ô&‚Àˆ¥=8ð%%à«aÖðál*àÀ÷"Õuà'’Èx+…·o.ÿ‰^Õ•ÃP>QÁ6æ‚éÖ˧¨M°£ŽÜ:—wêÞ„Ã6å÷“¿¼ége+ßÅa3Õ•ï6pdú/‹`9¼ñ)Ëß6pä&gP‚¡ÇƒYH¯déãÈ¡DÓgP+„ã™îqÐ?,¯;9:ƒÊÃÃAp|ã¢[‘GuG`-áL«¨’¹ú +·N©Š™*IÈ(¼ºKî
¾³ðìúðë¨×ôe½äMWµ¹-LøH1V^Ö%xú¯ø‚d=Äk2ÎËŠ‹JðpªÃp\Y£åž•²…køƯrª>ÞR3Ù*ŸÐZ…)Èþ®ìŽÀ>÷•»é‘!:‹ÃPù)þçò)¤¢c›«ÁjžðZÅõ¹ñ<‰V{Ør±˜žLv;x±Ç<ü0ˆ}•9åàã½àSL)…/D|æà«(ÒvN©!ضØrÈB§h»‡¼¤X…b +mçÉ@´¸¦U¤Ž_+xÜ&V=KÒc'¬×›T}G0ˆ#(ÃÐ$#Ô0fèÕC“#°Ç>š®a4‡Y5´Yé È3öÐG©MqbdÚ}R¯†^Ó\þW§ÊÃûHdÇã9ZUÉK×¼Ù«ÞÅ°åš)ºú7{@íªê P!|Aæ%*ÈÏ$Ãrh5Óvù‘öSÐð¢Ö¼$vˆN Uæy½zø0uÝá)]±3uY‡OÑ0Xâ±à
¿™4Ö“<ÔѾŠº°fmøC´‰Í÷öÃ×3,"´¾aìZyµâ`ƒf›¬5É´ü
4ÑÑ©ù¥‚ñ&Z<ËšÝc%6sÍ4ŒWd¼Im/uJ•ÉœRµ±œàêZ;|JŽk»k7H8Pïx8µ/ª^S¾F¶¹M¬=fl]š~$Í\ðÔëäÆL曜º¼;%Þ¤Š`<e‚‘º‚mYyï#Š’VÃj:ÓÇÖ``^}J†ñÑþýiµ/g;½‰Ø¬¨iË’Á!o±„59]űˆ²™÷Üâò ƒÄ«J%aVB&‰¶Ä”Ñ43‰õ‚²×!v”c̘Ó4OœU¥°{ô|ö·Óhª+Nvþ m‚×âFzŠ'¶¼œâlpv«M¾jq¸Ô9çI!,5ªì–J)€ +RŠôädæLRå&rÂÄì®QŠŒ‚àM„²[9p€¶$ðF›V.˜LvãÕ‚aU0…Z"|aZ‹`ËLàš{ˆ`"„tç“cAí]Ÿ‡¦ðNÚ{d‡E©¾Š6Á›xs)Pß@‡OÈ–KX¿T÷lj
w2œpLr×ßÆp™/ë©ãËרfýY »²å²Y}ê¿VþÆÙÕI0ë¿Õ0ÖL.G#(:êõ#ÃSPô#GÌR„— nAGœW°¼LðqF¦(….{p¤\¥î +xvy„%œÜ|†³Ê9+ÛȃEú:(&Wá…1†HÃ')h¾œutF•Rа3MðÍÙ¨…j5V˼ouÆ›óå›Q§ŒU>rý6º`yÿÍvC0t^Àdýb··ÜW~PyP&©Å£ÑáñrÙ\55¤IXž2òm¬†-Et§„—ËÌ؆Wlc‘öXÙP#SNî†ßÒ#Q|6
_Ò&¾ì“5³Æ¯˜rÔ8šöV݈¶¤±…‚æËoé 5ÎW02¿ù áÛXí¡Ö±ô6ÕkWa7ÃòØ4ÒÀž9eÓ¦&~-@{°¹‡2ÓÕ6/[šéGâGÜ@5«G&ð~8¡3F¯õðš•áûˆßxü§ë˜´7NúÆ'c>R{ã«8¦öÉØÕäAœ>̈Õ2¢ƒ¯ÇßžhiS”8\F[fÓj|Õk’¤ånC£ð÷ƒ-kȬ0 ®R-Çi5Þ¶„ÌØ–Oõjl´¹÷¹òZe zÛ˜ƒW®âœwä¿m]IE¢+©¯ÈLí9©AJJrrÖNqïFümPʽ‰{×*ˆÝÓÖ–6·úw‹{vÿõ†Žk_X׶±µ{ÉÓ‹Ä‚ÿÇW#ËE\}5²äºö¥‹f.¼#~ˬŸ-ž5cá¢ÎeðËò¥í3‘¥¾)Ù«u\sËõVLôU_Ìš0¦)~]ó¤xëOãNWr¿ˆ¹hÙII—SÚÄômÓ¶MY3lβe‹ëëêV¬XQ;¿LYÛ9¯®}F»]7cé|ù6ïkªiñŒöÿsíÿúhÏ®ä¤,nûòém½sW'_x⵩ƒ›vnùùÃïn˜Ñï÷oîºæôÚ~çǹy³~ôàÆ g®í8yûÖ¹ÇV†ïïîOÿŸý¬é“¡³Oý|oQ[ÍÅ!Ý?>=}Ú–Æ/ëgíZ7û‰gß>=äÕÇ_¾ï¯“ß}éšÍ?¶ô\z}ií½ß×þ0·èª›ZþkßÇî/¯\ý}¯®‚oqõ‚…[ß:½å÷mi³{¼ÿÌâOç,¸äL98ÍéóBwðmë[*¾ªš7çüˆ½C¿9SÒ¼hJWë¹Å;~{þÊ%Ö¯JŸð•½?ûÏÅ/¯wd÷»¸'©ãøÖ£ç&6tŸ¾éw7Û±ª×…'¶Ì\Ñuèܽ·>ÖqiË›ßÕ¿zdãÖg몗M6þŠÔÞºñׯç×íùaéÀÙÓ^k{`mÒ]=·µŸÌÛóEç×ãV6oXxxƥ韘²csÝö×z}óâ¤vÿþòâ´ sËÔ?¬î¸p¿3éåN]½ÿª}eOßz2õ蔿ΰ.Žÿìì«ÏÜUüÉéQ¿ÙðÅöÇË—mØ–<gØû#çíÛ±êëù·/ßù\wúçïœïßóܦ3"7^º±õ½ËO®+yÿÝË-G&®|êþ''g-þtì¦
§.<ðMi“=öX¯›ç7ÞräÛ!%“?¨¾ýÈñ‹Ï5t<¿üŽ‡š.»oó¾G<ûHéøXc}á¸ÔÆÓožþã¸m±Ëß]Z¿yå¥ígW¿Ûo×æÍ«|¶wêôé)oøüÍû'ü÷ÿ +endstream +endobj +349 0 obj +<</Length 782/Filter/FlateDecode>>stream +xœ3hbæ5hüÆÄÈhÀËÆ©ÕæÑö—‘‘›•Á ×Û€“9”…M˜)ØÛPØ@Äaçár*J,É,ÎI,K4T2P +…
Œ
,
LL¢x¸€fÉŠ²0s1².00Ð3àñEXX˜˜®Èƒ8Ê,b
"õmMÒ›Îη1³Yõ¯b›;š—™›˜6žü‰'ðÍJû3¬5SwMIò$ê{l¶þAi[·_ÇwÞçJI0ÙátP2Zãvÿœ·ì§¢ê½Ïå¨[¤lº7{2ã¥ÖÏÿÕÝáoìåÛµêNƒJ¨Û±×'ª£lŽ^e½ÿè{¾œñ»o§.ÆõH®õì“{÷„óAç©UlÎ%*Ìž2ÇJîf~¹s7—Áæü“Bƒ3m2[Y_òúrgL8í2׬_w;ûÍsg2^6ü˱¸´qžkKLèÔ—›˜Så¶fÌ©î;\°ißµõg~ö´°xïül¾03OÞgåL%å\…ÜéµÞû‚W>¨rWšYŸ·´\ðò‡ûk¢ïªããìh•ÿ˜™íÑý¶5Lî0º.çÃÊâܤ,ºþ«BŠžÅ¦MéOò¾cú²Ê¡ÐwþݵÓάÎÎþºŸ#4®,ôËòM~…]۾ؕîx1³Õ›÷ÆLëÇwwZñ½MM<p7+Ð.X½=ãÇ<ŽÈ|³ïÕgWœ²ï·ÒÔ°<gÇ`>¡ëuGö[åO?¯ë=å¼ÐÞó<óÞ˃å'Ž¼xÕ=I€aým‘K§‚ÛgEM\¸ò»o’仧‚Ô¿®ûÏ5_ªåcI)_tõܹû·Z‡‰={.³«?°ôR÷ë.¦Ç̶o}Êu’c‰NŠ¼Êqá×|z#·k-åžq~£íƒý“ƒÎ_Nvúcòãßy=¹5 +endstream +endobj +350 0 obj +[345 0 R 346 0 R 347 0 R] +endobj +351 0 obj +[348 0 R 349 0 R] +endobj +352 0 obj +<</CRL 351 0 R/Cert 350 0 R>> +endobj +353 0 obj +<</707ABDC9A8950BA2E2C0B80B412C492C614107A551ACC878038D57E5C79D5C82 352 0 R>> +endobj +354 0 obj +[345 0 R 346 0 R 347 0 R] +endobj +355 0 obj +[348 0 R 349 0 R] +endobj +356 0 obj +<</CRLs 355 0 R/VRI 353 0 R/Certs 354 0 R>> +endobj +2 0 obj +<</Type/Metadata/Subtype/XML/Length 44744>>stream +<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?> +<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 4.2.1-c043 52.372728, 2009/01/18-15:56:37 "> + <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> + <rdf:Description rdf:about="" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" xmlns:stEvt="http://ns.adobe.com/xap/1.0/sType/ResourceEvent#" xmlns:stMfs="http://ns.adobe.com/xap/1.0/sType/ManifestItem#"> + <xmpMM:InstanceID>uuid:7e7b597d-426f-3642-8dca-bcbf37236e1d</xmpMM:InstanceID> + <xmpMM:DocumentID>xmp.did:89321C534E266811A613EDAC20FB34D2</xmpMM:DocumentID> + <xmpMM:OriginalDocumentID>adobe:docid:indd:924fbc79-cadb-11de-af61-e97e2740acd1</xmpMM:OriginalDocumentID> + <xmpMM:RenditionClass>proof:pdf</xmpMM:RenditionClass> + <xmpMM:DerivedFrom rdf:parseType="Resource"> + <stRef:instanceID>xmp.iid:88321C534E266811A613EDAC20FB34D2</stRef:instanceID> + <stRef:documentID>adobe:docid:indd:924fbc79-cadb-11de-af61-e97e2740acd1</stRef:documentID> + <stRef:originalDocumentID>adobe:docid:indd:924fbc79-cadb-11de-af61-e97e2740acd1</stRef:originalDocumentID> + <stRef:renditionClass>default</stRef:renditionClass> + </xmpMM:DerivedFrom> + <xmpMM:History> + <rdf:Seq> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E4B6ED806F256811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T11:39:47-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E5B6ED806F256811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T11:39:47-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/metadata</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E6B6ED806F256811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T11:44:22-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:80321C534E266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T11:46:03-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:81321C534E266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T11:48-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:82321C534E266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T11:49:01-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:83321C534E266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T11:52:39-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:84321C534E266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T11:58:06-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:85321C534E266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T11:59:50-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:88321C534E266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T12:03:27-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/metadata</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:89321C534E266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T12:03:27-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:4A27385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T13:48:01-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:4B27385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T13:50:54-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:4C27385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T13:54-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:4D27385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T13:55:16-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:4E27385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T13:56:27-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:4F27385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T13:58:44-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:5027385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:05:30-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:5127385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:07:25-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:5227385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:12:43-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:5327385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:13:56-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:5427385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:16:22-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:DE855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:19:25-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:DF855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:27:07-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E0855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:29:58-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E1855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:32:34-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E2855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:33:46-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E3855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:40:42-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E4855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:41:28-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E5855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:42:42-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E6855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:44:36-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E7855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:47:08-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E8855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:51:29-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:80C8B5F5A22068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T10:49:23-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:81C8B5F5A22068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T10:50:43-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:82C8B5F5A22068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T10:52:12-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:00CECC59A92068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T10:53:23-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:01CECC59A92068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T10:53:56-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:02CECC59A92068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T10:56:41-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:03CECC59A92068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T11:03:21-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:04CECC59A92068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T11:06:47-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:05CECC59A92068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T11:09:26-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:06CECC59A92068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T11:11:53-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:07CECC59A92068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T11:13:29-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:999093B2AD2068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T14:21:34-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:9A9093B2AD2068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T14:27:38-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:9B9093B2AD2068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T14:30:31-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:371C0BE61C2368119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-07-02T14:20:55-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:381C0BE61C2368119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-07-02T14:26:33-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:391C0BE61C2368119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-07-02T14:29:07-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:3A1C0BE61C2368119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-07-02T14:31:19-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:7A0142B9242368119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-07-02T14:41:33-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:7B0142B9242368119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-07-02T14:44:10-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + </rdf:Seq> + </xmpMM:History> + <xmpMM:Manifest> + <rdf:Bag> + <rdf:li rdf:parseType="Resource"> + <stMfs:linkForm>ReferenceStream</stMfs:linkForm> + <xmpMM:placedXResolution>72.00</xmpMM:placedXResolution> + <xmpMM:placedYResolution>72.00</xmpMM:placedYResolution> + <xmpMM:placedResolutionUnit>Inches</xmpMM:placedResolutionUnit> + <stMfs:reference rdf:parseType="Resource"> + <stRef:instanceID>uuid:288c3c69-7dd6-7c4f-984d-b085b3307748</stRef:instanceID> + <stRef:documentID>uuid:93F9F49755C5DE1185BCB9A8461E73D9</stRef:documentID> + </stMfs:reference> + </rdf:li> + </rdf:Bag> + </xmpMM:Manifest> + </rdf:Description> + <rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpGImg="http://ns.adobe.com/xap/1.0/g/img/"> + <xmp:CreateDate>2010-07-02T15:32:26-07:00</xmp:CreateDate> + <xmp:ModifyDate>2013-09-06T16:23:05+02:00</xmp:ModifyDate> + <xmp:MetadataDate>2013-09-06T16:23:05+02:00</xmp:MetadataDate> + <xmp:CreatorTool>Adobe InDesign CS4 (6.0.5)</xmp:CreatorTool> + <xmp:Thumbnails> + <rdf:Alt> + <rdf:li rdf:parseType="Resource"> + <xmpGImg:format>JPEG</xmpGImg:format> + <xmpGImg:width>256</xmpGImg:width> + <xmpGImg:height>256</xmpGImg:height> + <xmpGImg:image>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 +xV2KuxV2KpL5z/5Q/Xv+2bef8mJMVf/Z</xmpGImg:image> + </rdf:li> + </rdf:Alt> + </xmp:Thumbnails> + </rdf:Description> + <rdf:Description rdf:about="" xmlns:idPriv="http://ns.adobe.com/xmp/InDesign/private"> + <idPriv:DocChangeCount>244</idPriv:DocChangeCount> + </rdf:Description> + <rdf:Description rdf:about="" xmlns:dc="http://purl.org/dc/elements/1.1/"> + <dc:format>application/pdf</dc:format> + </rdf:Description> + <rdf:Description rdf:about="" xmlns:pdf="http://ns.adobe.com/pdf/1.3/"> + <pdf:Producer>Adobe PDF Library 9.0; modified using iTextSharp 4.1.6 by 1T3XT</pdf:Producer> + <pdf:Trapped>False</pdf:Trapped> + </rdf:Description> + </rdf:RDF> +</x:xmpmeta><?xpacket end="w"?> +endstream +endobj +3 0 obj +<</Type/Pages/Kids[59 0 R 5 0 R]/Count 2/ITXT(4.1.6)>> +endobj +1 0 obj +<</Type/Catalog/Pages 3 0 R/DSS 356 0 R/AcroForm<</DA(/Helv 0 Tf 0 g )/Fields[342 0 R]/SigFlags 3/DR<</Font<</Helv 343 0 R/ZaDb 344 0 R>>>>>>/ViewerPreferences<</Direction/L2R>>/Metadata 2 0 R>> +endobj +55 0 obj +<</Creator(Adobe InDesign CS4 \(6.0.5\))/Producer(Adobe PDF Library 9.0; modified using iTextSharp 4.1.6 by 1T3XT)/CreationDate(D:20100702153226-07'00')/Trapped/False/ModDate(D:20130906162305+02'00')>> +endobj +xref +0 4 +0000000000 65535 f +0000389352 00000 n +0000344462 00000 n +0000389282 00000 n +55 1 +0000389562 00000 n +345 12 +0000332986 00000 n +0000334673 00000 n +0000336526 00000 n +0000338255 00000 n +0000343252 00000 n +0000344103 00000 n +0000344146 00000 n +0000344181 00000 n +0000344228 00000 n +0000344323 00000 n +0000344366 00000 n +0000344401 00000 n +trailer +<</Size 357/ID [<b8d12dc8f9ff8ef9b45b85e6c6d797f9><c053b9a644fd8392f5ead8daf0359013>]/Info 55 0 R/Prev 332586/Root 1 0 R>> +startxref +389780 +%%EOF + +359 0 obj +<</Type/Annot/F 132/V 357 0 R/DR<<>>/T(Signature2)/Subtype/Widget/Rect[0 0 0 0]/FT/Sig/P 59 0 R/AP<</N 358 0 R>>>> +endobj +357 0 obj +<</Type/Sig/SubFilter/ETSI.RFC3161/Filter/Adobe.PPKLite/ByteRange [0 390594 411076 46954 ] /Contents <30820a4d06092a864886f70d010702a0820a3e30820a3a020103310f300d06096086480165030402010500307f060b2a864886f70d0109100104a070046e306c020101060e2b811e9193e60a000001000402003031300d0609608648016503040201050004204605d90937c53ba1e4e4320cc80aff57cd0a41fec494cf1d10b315196a67cb970203212dc5181332303133303930363134323332332e3235315a3004800201f402043a5bc766a082076c3082076830820550a003020102020401004485300d06092a864886f70d01010b05003063310b300906035504061302534b3113301106035504070c0a4272617469736c61766131133011060355040a0c0a446973696720612e732e31173015060355040b0c0e4143412d3330372d323030372d323111300f06035504030c084341204469736967301e170d3133303631333132313534365a170d3135303631333132313534365a3081a0310b300906035504061302534b3113301106035504070c0a4272617469736c61766131133011060355040a0c0a446973696720612e732e31173015060355040b0c0e4143412d3330372d323030372d3231373035060355040b0c2e416b72656469746f76616e6120736c757a6261207679646176616e6961206361736f76656a207065636961746b793115301306035504030c0c54534120434120446973696730820122300d06092a864886f70d01010105000382010f003082010a02820101009edca2d345f2dc25e9a996aa9938b87a8d7415e5442a62bfa431bfa67518d32df5577f156bde1cca6179d301aae8657745c5342a794a31a89c5de6074c423e28243a9bd3fc71a9605ce45766aabc009ea49ee2e0330db8bfb4794f4313fc297f1314a7b7122819067992f4584ef508341010a9b8fd15e3eb7ae6c4aafaa76bce61ba174346007ce0753b54b07a3d28ba98be2e9fdf98788586336985dcf1d6d80b44c098fb2ff8808660a8ec8d0177f1cc52e25a717d61451c68aed82e03eff1cfb333e104ace4044e1d10be022f03467a44ecc13bd48a44594cad5d94b78a547893d426769db7af8da2fe7e332a1afd192ab723e9d48a414ca2a7ef54d2c2030203010001a38202e4308202e03081a906082b0601050507010104819c308199302406082b060105050730018618687474703a2f2f6163612d6f6373702e64697369672e736b303806082b06010505073002862c687474703a2f2f7777772e64697369672e736b2f616361322f636572742f616361325f64697369672e703763303706082b06010505073002862b687474703a2f2f63612e64697369672e736b2f616361322f636572742f616361325f64697369672e703763301d0603551d0e041604140b476313fc4a78df06c7e48caf5ee56c950e9f613081980603551d2304819030818d8014157f5f5f08692ac67003a1fa516a4dac8d5f9853a171a46f306d310b300906035504061302534b3113301106035504070c0a4272617469736c61766131223020060355040a0c194e61726f646e792062657a7065636e6f73746e792075726164310e300c060355040b0c0553494245503115301306035504030c0c4b4341204e42552053522033820200f4300c0603551d130101ff040230003081b60603551d200481ae3081ab300f060d2b811e919984050000000102023008060604008f7a01023044060e2b811e9193e60a000001000103023032303006082b060105050702011624687474703a2f2f7777772e64697369672e736b2f5f7064662f63705f616361322e7064663048060e2b811e9193e60a000001000402003036303406082b060105050702011628687474703a2f2f7777772e64697369672e736b2f5f7064662f63705f7473615f616361322e706466301c0603551d1104153013811173707261766163614064697369672e736b306e0603551d1f046730653031a02fa02d862b687474703a2f2f7777772e64697369672e736b2f616361322f63726c2f616361325f64697369672e63726c3030a02ea02c862a687474703a2f2f63612e64697369672e736b2f616361322f63726c2f616361325f64697369672e63726c300b0603551d0f04040302064030160603551d250101ff040c300a06082b06010505070308300d06092a864886f70d01010b05000382020100a4f0cac694feb6638048b5287cc12b503db5b44c300478894ea9401427e53a31e3478c93eab06dfedffd94c0a3b41dc4258d7041ffee19f2bc1e2aef54498bf89ba7364ae05a6757c22d6bb09e153bfaf7d805c9d6f850326dd1dff6af180b31b576d4bba1ab2367ca55bbdea9925f1dd662b4cf1efb40acfa11586d4df11d96731bcdd9b32bbdd94fd99dad55532a9889729116c0c8d7431c90c7d74e2d79ad8b645da70676602d528ad4b5b3daa75fa4d8833b9dd223aaa4bf7e558ffaa48bf640cdd52b5c3b87318e5fb68487fc67859bb6530614dfba0bb4cc7f9291518abf85d7583924adf7ab10484cf40532637a4e819ba1a2c11a048b937602d318de09d56cae1f5ae8304c0a137dd346cb78b8400e93034b7533773ac81d3f8a3739ebaa1981f281726ebfea765f6f82ca1967b67623ce7ded552d16233f9b8ba350e31fd208b54db0e4f549ceb61d59e57a04162c59d7668410082d6f26b41f37d5d2777edd7aba9a4b713654c2e399572baa5585446a55e187251f08f8f882fbbf868cd4e59b5eaefe38d587eff7393193e0abdd7c86bf2055a0e539bd3cdf2d22b48e985aba5e883b3e31945d8f83eff5d6a1c892f30ac5d85bf6b533d0f92e0c440e11b85fff43e4d4070b6f1f2669a22a2e376ce60fd2f758292f522cc3edb8a71f05deeea5320439047a508777faafbafd25d532e7b70d89f9ff4527c4b959318202313082022d020101306b3063310b300906035504061302534b3113301106035504070c0a4272617469736c61766131133011060355040a0c0a446973696720612e732e31173015060355040b0c0e4143412d3330372d323030372d323111300f06035504030c084341204469736967020401004485300d06096086480165030402010500a08198301a06092a864886f70d010903310d060b2a864886f70d0109100104301c06092a864886f70d010905310f170d3133303930363134323332335a302b060b2a864886f70d010910020c311c301a301830160414b50c062e6a34decdbceaef637460b71c33211c55302f06092a864886f70d01090431220420cd56988f2590b0a1f061364a9ac66a336e04a9580213764adfbc95e095bdd7b1300d06092a864886f70d01010105000482010093b0e60c3488c6f9be1a5e3d96e352491635608e118cd6dffb0b4922ff5d338134c069f18548d4571837f72bbd0fbe2d15f5f6d32589b1d345df3081e06f039cfbe38b0b3d1cf1f34078462d6ca8361820c15b88cf61e460caded8946b78bf418eca58c2984e137c9e7d75973eb9d778d12a5621aa27090a81783959f2c8fd824423aaf136e23e1ee4b52ad532dd6cac912e3f373aa4baf5e78c7db13758a0a471cf7fd2b1ce0ff0c27e7250686dfb5ce6d34929e40e40dc6876216ba4ea30d3ed3c265b3ac0f8b7760be7bcdf902da3cb8f9b5e6e541359de83a80212bf9b70d7bb3633ee64d74f57fecad46497ae0a5f40fc5e80c31741ad7b595b24ee78f6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000>>> +endobj +358 0 obj +<</Type/XObject/FormType 1/Subtype/Form/BBox[0 0 0 0]/Resources<</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]>>/Filter/FlateDecode/Length 8/Matrix [1 0 0 1 0 0]>>stream +xœ +endstream +endobj +2 0 obj +<</Type/Metadata/Subtype/XML/Length 44744>>stream +<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?> +<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 4.2.1-c043 52.372728, 2009/01/18-15:56:37 "> + <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> + <rdf:Description rdf:about="" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" xmlns:stEvt="http://ns.adobe.com/xap/1.0/sType/ResourceEvent#" xmlns:stMfs="http://ns.adobe.com/xap/1.0/sType/ManifestItem#"> + <xmpMM:InstanceID>uuid:7e7b597d-426f-3642-8dca-bcbf37236e1d</xmpMM:InstanceID> + <xmpMM:DocumentID>xmp.did:89321C534E266811A613EDAC20FB34D2</xmpMM:DocumentID> + <xmpMM:OriginalDocumentID>adobe:docid:indd:924fbc79-cadb-11de-af61-e97e2740acd1</xmpMM:OriginalDocumentID> + <xmpMM:RenditionClass>proof:pdf</xmpMM:RenditionClass> + <xmpMM:DerivedFrom rdf:parseType="Resource"> + <stRef:instanceID>xmp.iid:88321C534E266811A613EDAC20FB34D2</stRef:instanceID> + <stRef:documentID>adobe:docid:indd:924fbc79-cadb-11de-af61-e97e2740acd1</stRef:documentID> + <stRef:originalDocumentID>adobe:docid:indd:924fbc79-cadb-11de-af61-e97e2740acd1</stRef:originalDocumentID> + <stRef:renditionClass>default</stRef:renditionClass> + </xmpMM:DerivedFrom> + <xmpMM:History> + <rdf:Seq> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E4B6ED806F256811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T11:39:47-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E5B6ED806F256811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T11:39:47-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/metadata</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E6B6ED806F256811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T11:44:22-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:80321C534E266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T11:46:03-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:81321C534E266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T11:48-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:82321C534E266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T11:49:01-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:83321C534E266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T11:52:39-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:84321C534E266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T11:58:06-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:85321C534E266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T11:59:50-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:88321C534E266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T12:03:27-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/metadata</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:89321C534E266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T12:03:27-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:4A27385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T13:48:01-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:4B27385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T13:50:54-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:4C27385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T13:54-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:4D27385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T13:55:16-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:4E27385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T13:56:27-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:4F27385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T13:58:44-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:5027385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:05:30-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:5127385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:07:25-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:5227385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:12:43-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:5327385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:13:56-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:5427385D5F266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:16:22-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:DE855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:19:25-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:DF855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:27:07-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E0855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:29:58-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E1855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:32:34-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E2855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:33:46-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E3855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:40:42-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E4855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:41:28-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E5855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:42:42-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E6855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:44:36-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E7855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:47:08-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:E8855BC063266811A613EDAC20FB34D2</stEvt:instanceID> + <stEvt:when>2010-06-27T14:51:29-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:80C8B5F5A22068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T10:49:23-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:81C8B5F5A22068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T10:50:43-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:82C8B5F5A22068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T10:52:12-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:00CECC59A92068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T10:53:23-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:01CECC59A92068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T10:53:56-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:02CECC59A92068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T10:56:41-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:03CECC59A92068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T11:03:21-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:04CECC59A92068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T11:06:47-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:05CECC59A92068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T11:09:26-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:06CECC59A92068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T11:11:53-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:07CECC59A92068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T11:13:29-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:999093B2AD2068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T14:21:34-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:9A9093B2AD2068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T14:27:38-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:9B9093B2AD2068119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-06-29T14:30:31-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:371C0BE61C2368119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-07-02T14:20:55-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:381C0BE61C2368119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-07-02T14:26:33-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:391C0BE61C2368119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-07-02T14:29:07-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:3A1C0BE61C2368119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-07-02T14:31:19-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:7A0142B9242368119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-07-02T14:41:33-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:7B0142B9242368119109D8C24D4F5870</stEvt:instanceID> + <stEvt:when>2010-07-02T14:44:10-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe InDesign 6.0</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + </rdf:Seq> + </xmpMM:History> + <xmpMM:Manifest> + <rdf:Bag> + <rdf:li rdf:parseType="Resource"> + <stMfs:linkForm>ReferenceStream</stMfs:linkForm> + <xmpMM:placedXResolution>72.00</xmpMM:placedXResolution> + <xmpMM:placedYResolution>72.00</xmpMM:placedYResolution> + <xmpMM:placedResolutionUnit>Inches</xmpMM:placedResolutionUnit> + <stMfs:reference rdf:parseType="Resource"> + <stRef:instanceID>uuid:288c3c69-7dd6-7c4f-984d-b085b3307748</stRef:instanceID> + <stRef:documentID>uuid:93F9F49755C5DE1185BCB9A8461E73D9</stRef:documentID> + </stMfs:reference> + </rdf:li> + </rdf:Bag> + </xmpMM:Manifest> + </rdf:Description> + <rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpGImg="http://ns.adobe.com/xap/1.0/g/img/"> + <xmp:CreateDate>2010-07-02T15:32:26-07:00</xmp:CreateDate> + <xmp:ModifyDate>2013-09-06T16:23:05+02:00</xmp:ModifyDate> + <xmp:MetadataDate>2013-09-06T16:23:05+02:00</xmp:MetadataDate> + <xmp:CreatorTool>Adobe InDesign CS4 (6.0.5)</xmp:CreatorTool> + <xmp:Thumbnails> + <rdf:Alt> + <rdf:li rdf:parseType="Resource"> + <xmpGImg:format>JPEG</xmpGImg:format> + <xmpGImg:width>256</xmpGImg:width> + <xmpGImg:height>256</xmpGImg:height> + <xmpGImg:image>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 +xV2KuxV2KpL5z/5Q/Xv+2bef8mJMVf/Z</xmpGImg:image> + </rdf:li> + </rdf:Alt> + </xmp:Thumbnails> + </rdf:Description> + <rdf:Description rdf:about="" xmlns:idPriv="http://ns.adobe.com/xmp/InDesign/private"> + <idPriv:DocChangeCount>244</idPriv:DocChangeCount> + </rdf:Description> + <rdf:Description rdf:about="" xmlns:dc="http://purl.org/dc/elements/1.1/"> + <dc:format>application/pdf</dc:format> + </rdf:Description> + <rdf:Description rdf:about="" xmlns:pdf="http://ns.adobe.com/pdf/1.3/"> + <pdf:Producer>Adobe PDF Library 9.0; modified using iTextSharp 4.1.6 by 1T3XT</pdf:Producer> + <pdf:Trapped>False</pdf:Trapped> + </rdf:Description> + </rdf:RDF> +</x:xmpmeta><?xpacket end="w"?> +endstream +endobj +59 0 obj +<</ArtBox[0.0 0.0 841.89 595.276]/MediaBox[0.0 0.0 841.89 595.276]/Type/Page/BleedBox[0.0 0.0 841.89 595.276]/Contents 63 0 R/CropBox[0.0 0.0 841.89 595.276]/Resources<</Font<</C2_2 58 0 R/C2_1 57 0 R/C2_0 56 0 R>>/ExtGState<</GS13 203 0 R/GS12 202 0 R/GS11 201 0 R/GS10 200 0 R/GS9 214 0 R/GS8 213 0 R/GS7 212 0 R/GS6 211 0 R/GS5 210 0 R/GS4 209 0 R/GS3 208 0 R/GS2 207 0 R/GS1 199 0 R/GS0 91 0 R/GS16 206 0 R/GS15 205 0 R/GS14 204 0 R>>/Shading<</Sh6 150 0 R/Sh5 149 0 R/Sh4 148 0 R/Sh3 147 0 R/Sh2 146 0 R/Sh1 140 0 R/Sh0 139 0 R/Sh14 145 0 R/Sh13 144 0 R/Sh12 143 0 R/Sh11 142 0 R/Sh10 141 0 R/Sh9 153 0 R/Sh8 152 0 R/Sh7 151 0 R>>/ProcSet[/PDF/Text]/ColorSpace<</CS0 85 0 R/CS1 100 0 R>>/Properties<</MC0<</Metadata 192 0 R>>>>/XObject<</Fm9 82 0 R/Fm8 81 0 R/Fm7 80 0 R/Fm6 79 0 R/Fm5 78 0 R/Fm4 77 0 R/Fm3 76 0 R/Fm2 75 0 R/Fm1 66 0 R/Fm0 65 0 R/Fm17 74 0 R/Fm16 73 0 R/Fm15 72 0 R/Fm14 71 0 R/Fm13 70 0 R/Fm12 69 0 R/Fm11 68 0 R/Fm10 67 0 R>>>>/Parent 3 0 R/Annots[342 0 R 359 0 R]/Group 64 0 R/TrimBox[0.0 0.0 841.89 595.276]>> +endobj +3 0 obj +<</Type/Pages/ITXT(4.1.6)/Kids[59 0 R 5 0 R]/Count 2>> +endobj +1 0 obj +<</Type/Catalog/Pages 3 0 R/DSS 356 0 R/AcroForm<</DA(/Helv 0 Tf 0 g )/Fields[342 0 R 359 0 R]/SigFlags 3/DR<</Font<</Helv 343 0 R/ZaDb 344 0 R>>>>>>/ViewerPreferences<</Direction/L2R>>/Metadata 2 0 R>> +endobj +55 0 obj +<</Creator(Adobe InDesign CS4 \(6.0.5\))/Producer(Adobe PDF Library 9.0; modified using iTextSharp 4.1.6 by 1T3XT)/CreationDate(D:20100702153226-07'00')/Trapped/False/ModDate(D:20130906162305+02'00')>> +endobj +xref +0 4 +0000000000 65535 f +0000457235 00000 n +0000411292 00000 n +0000457165 00000 n +55 1 +0000457453 00000 n +59 1 +0000456112 00000 n +357 3 +0000390428 00000 n +0000411086 00000 n +0000390296 00000 n +trailer +<</Size 360/ID [<c94cabd6d311d14656ede5448fcba052><8ab700b1cd51e5dc8899e4d7fb138f4b>]/Info 55 0 R/Prev 389780/Root 1 0 R>> +startxref +457671 +%%EOF diff --git a/xmlsecurity/qa/unit/pdfsigning/data/dict-bool.pdf b/xmlsecurity/qa/unit/pdfsigning/data/dict-bool.pdf Binary files differnew file mode 100644 index 0000000000..cd87f71ecf --- /dev/null +++ b/xmlsecurity/qa/unit/pdfsigning/data/dict-bool.pdf diff --git a/xmlsecurity/qa/unit/pdfsigning/data/forcepoint16.pdf b/xmlsecurity/qa/unit/pdfsigning/data/forcepoint16.pdf Binary files differnew file mode 100644 index 0000000000..9edccb47f4 --- /dev/null +++ b/xmlsecurity/qa/unit/pdfsigning/data/forcepoint16.pdf diff --git a/xmlsecurity/qa/unit/pdfsigning/data/good-custom-magic.pdf b/xmlsecurity/qa/unit/pdfsigning/data/good-custom-magic.pdf Binary files differnew file mode 100644 index 0000000000..2c532cbf6a --- /dev/null +++ b/xmlsecurity/qa/unit/pdfsigning/data/good-custom-magic.pdf diff --git a/xmlsecurity/qa/unit/pdfsigning/data/good-non-detached.pdf b/xmlsecurity/qa/unit/pdfsigning/data/good-non-detached.pdf Binary files differnew file mode 100644 index 0000000000..8e5b215115 --- /dev/null +++ b/xmlsecurity/qa/unit/pdfsigning/data/good-non-detached.pdf diff --git a/xmlsecurity/qa/unit/pdfsigning/data/good-pades.pdf b/xmlsecurity/qa/unit/pdfsigning/data/good-pades.pdf Binary files differnew file mode 100644 index 0000000000..987169eeee --- /dev/null +++ b/xmlsecurity/qa/unit/pdfsigning/data/good-pades.pdf diff --git a/xmlsecurity/qa/unit/pdfsigning/data/good.pdf b/xmlsecurity/qa/unit/pdfsigning/data/good.pdf Binary files differnew file mode 100644 index 0000000000..f28566442d --- /dev/null +++ b/xmlsecurity/qa/unit/pdfsigning/data/good.pdf diff --git a/xmlsecurity/qa/unit/pdfsigning/data/name-bracket.pdf b/xmlsecurity/qa/unit/pdfsigning/data/name-bracket.pdf new file mode 100644 index 0000000000..ac152793c1 --- /dev/null +++ b/xmlsecurity/qa/unit/pdfsigning/data/name-bracket.pdf @@ -0,0 +1,2241 @@ +%PDF-1.7 +%öäüß +1 0 obj +<< +/Metadata 2 0 R +/Outlines 3 0 R +/OutputIntents [4 0 R] +/PageLabels 5 0 R +/Pages 6 0 R +/Type /Catalog +/Extensions << +/ESIC << +/BaseVersion /1.7 +/ExtensionLevel 2 +>> +/LTUd << +/BaseVersion /1.7 +/ExtensionLevel 1 +>> +>> +>> +endobj +7 0 obj +<< +/Author (Petras) +/CreationDate (D:20120616164408+03'00') +/Creator (PScript5.dll Version 5.2.2) +/ModDate (D:20120616164534+03'00') +/Producer (Acrobat Distiller 10.1.3 \(Windows\)) +/Title (Untitled - Notepad) +>> +endobj +2 0 obj +<< +/Type /Metadata +/Subtype /XML +/Length 8 0 R +>> +stream
+<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?> +<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.1.0-jc003"> + <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> + <rdf:Description rdf:about="" + xmlns:pdfaExtension="http://www.aiim.org/pdfa/ns/extension/" + xmlns:pdfaSchema="http://www.aiim.org/pdfa/ns/schema#" + xmlns:pdfaProperty="http://www.aiim.org/pdfa/ns/property#" + xmlns:pdfaType="http://www.aiim.org/pdfa/ns/type#" + xmlns:pdfaField="http://www.aiim.org/pdfa/ns/field#"> + <pdfaExtension:schemas> + <rdf:Bag> + <rdf:li rdf:parseType="Resource"> + <pdfaSchema:schema>PDF-LT-V1.0 elektroninio dokumento metaduomenų plėtinio schema</pdfaSchema:schema> + <pdfaSchema:namespaceURI>http://archyvai.lt/pdf-ltud/2011/metadata/</pdfaSchema:namespaceURI> + <pdfaSchema:prefix>LTUd</pdfaSchema:prefix> + <pdfaSchema:property> + <rdf:Seq> + <rdf:li rdf:parseType="Resource"> + <pdfaProperty:name>standardVersion</pdfaProperty:name> + <pdfaProperty:valueType>closed Choice of Text</pdfaProperty:valueType> + <pdfaProperty:category>internal</pdfaProperty:category> + <pdfaProperty:description>Elektroninio dokumento specifikacijos identifikatorius (pvz., PDF-LT-V1.0)</pdfaProperty:description> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <pdfaProperty:name>authors</pdfaProperty:name> + <pdfaProperty:valueType>seq Entity</pdfaProperty:valueType> + <pdfaProperty:category>external</pdfaProperty:category> + <pdfaProperty:description>Dokumento sudarytojas (-ai)</pdfaProperty:description> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <pdfaProperty:name>recipients</pdfaProperty:name> + <pdfaProperty:valueType>seq Entity</pdfaProperty:valueType> + <pdfaProperty:category>external</pdfaProperty:category> + <pdfaProperty:description>Dokumento adresatas (-ai)</pdfaProperty:description> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <pdfaProperty:name>instanceIdentifier</pdfaProperty:name> + <pdfaProperty:valueType>Text</pdfaProperty:valueType> + <pdfaProperty:category>external</pdfaProperty:category> + <pdfaProperty:description>Dokumento egzemplioriaus identifikatorius</pdfaProperty:description> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <pdfaProperty:name>originalRegistrations</pdfaProperty:name> + <pdfaProperty:valueType>seq Registration</pdfaProperty:valueType> + <pdfaProperty:category>external</pdfaProperty:category> + <pdfaProperty:description>Originalaus dokumento registracija (-os) kopijoje</pdfaProperty:description> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <pdfaProperty:name>originalReceptions</pdfaProperty:name> + <pdfaProperty:valueType>seq Registration</pdfaProperty:valueType> + <pdfaProperty:category>external</pdfaProperty:category> + <pdfaProperty:description>Gauto originalaus dokumento registracija (-os) kopijoje</pdfaProperty:description> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <pdfaProperty:name>originalReceivers</pdfaProperty:name> + <pdfaProperty:valueType>seq Entity</pdfaProperty:valueType> + <pdfaProperty:category>external</pdfaProperty:category> + <pdfaProperty:description>Originalaus dokumento gavėjas (-ai) kopijoje</pdfaProperty:description> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <pdfaProperty:name>registration</pdfaProperty:name> + <pdfaProperty:valueType>Registration</pdfaProperty:valueType> + <pdfaProperty:category>external</pdfaProperty:category> + <pdfaProperty:description>Sudaryto dokumento registracija</pdfaProperty:description> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <pdfaProperty:name>reception</pdfaProperty:name> + <pdfaProperty:valueType>Registration</pdfaProperty:valueType> + <pdfaProperty:category>external</pdfaProperty:category> + <pdfaProperty:description>Gauto dokumento registracija</pdfaProperty:description> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <pdfaProperty:name>receiver</pdfaProperty:name> + <pdfaProperty:valueType>Entity</pdfaProperty:valueType> + <pdfaProperty:category>external</pdfaProperty:category> + <pdfaProperty:description>Dokumento gavėjas</pdfaProperty:description> + </rdf:li> + </rdf:Seq> + </pdfaSchema:property> + <pdfaSchema:valueType> + <rdf:Seq> + <rdf:li rdf:parseType="Resource"> + <pdfaType:description>Asmuo (sudarytojas, adresatas, gavėjas)</pdfaType:description> + <pdfaType:namespaceURI>http://archyvai.lt/pdf-ltud/2011/metadata/Entity/</pdfaType:namespaceURI> + <pdfaType:prefix>LTUdEnt</pdfaType:prefix> + <pdfaType:type>Entity</pdfaType:type> + <pdfaType:field> + <rdf:Seq> + <rdf:li rdf:parseType="Resource"> + <pdfaField:name>individual</pdfaField:name> + <pdfaField:valueType>Boolean</pdfaField:valueType> + <pdfaField:description>Požymis: fizinis (taip) ar juridinis (ne) asmuo</pdfaField:description> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <pdfaField:name>name</pdfaField:name> + <pdfaField:valueType>Text</pdfaField:valueType> + <pdfaField:description>Juridinio asmens pavadinimas arba fizinio asmens vardas ir pavardė</pdfaField:description> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <pdfaField:name>code</pdfaField:name> + <pdfaField:valueType>Text</pdfaField:valueType> + <pdfaField:description>Juridinio ar fizinio asmens kodas</pdfaField:description> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <pdfaField:name>address</pdfaField:name> + <pdfaField:valueType>Text</pdfaField:valueType> + <pdfaField:description>Adresas</pdfaField:description> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <pdfaField:name>eMail</pdfaField:name> + <pdfaField:valueType>Text</pdfaField:valueType> + <pdfaField:description>El. pašto adresas</pdfaField:description> + </rdf:li> + </rdf:Seq> + </pdfaType:field> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <pdfaType:description>Sudaryto ar gauto dokumento registracija</pdfaType:description> + <pdfaType:namespaceURI>http://archyvai.lt/pdf-ltud/2011/metadata/Registration/</pdfaType:namespaceURI> + <pdfaType:prefix>LTUdReg</pdfaType:prefix> + <pdfaType:type>Registration</pdfaType:type> + <pdfaType:field> + <rdf:Seq> + <rdf:li rdf:parseType="Resource"> + <pdfaField:name>date</pdfaField:name> + <pdfaField:valueType>Date</pdfaField:valueType> + <pdfaField:description>Registravimo data</pdfaField:description> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <pdfaField:name>number</pdfaField:name> + <pdfaField:valueType>Text</pdfaField:valueType> + <pdfaField:description>Registracijos numeris</pdfaField:description> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <pdfaField:name>code</pdfaField:name> + <pdfaField:valueType>Text</pdfaField:valueType> + <pdfaField:description>Juridinio ar fizinio asmens kodas</pdfaField:description> + </rdf:li> + </rdf:Seq> + </pdfaType:field> + </rdf:li> + </rdf:Seq> + </pdfaSchema:valueType> + </rdf:li> + </rdf:Bag> + </pdfaExtension:schemas> + </rdf:Description> + <rdf:Description rdf:about="" + xmlns:LTUd="http://archyvai.lt/pdf-ltud/2011/metadata/"> + <LTUd:standardVersion>PDF-LT-V1.0</LTUd:standardVersion> + </rdf:Description> + </rdf:RDF> +</x:xmpmeta> +<?xpacket end="r"?>
+endstream +endobj +3 0 obj +<< +/Count 0 +/Type /Outlines +>> +endobj +4 0 obj +<< +/DestOutputProfile 9 0 R +/Info (sRGB IEC61966-2.1) +/OutputCondition () +/OutputConditionIdentifier (Custom) +/RegistryName (http://www.color.org) +/S /GTS_PDFA1 +/Type /OutputIntent +>> +endobj +5 0 obj +<< +/Nums [0 10 0 R] +>> +endobj +6 0 obj +<< +/Count 1 +/Kids [11 0 R] +/MediaBox [0 0 595.2199707031 842] +/Type /Pages +>> +endobj +8 0 obj +9317 +endobj +9 0 obj +<< +/Filter /FlateDecode +/Length 2574 +/N 3 +/Range [0 1 0 1 0 1] +>> +stream
+H‰œ–yTSwÇoÉž•°Ãc
[€°5la‘QIBHØADED„ª•2ÖmtFOE.®cÖ}êÒõ0êè8´×Ž8GNg¦Óïï÷9÷wïïÝß½÷ó + +V³)gB£0ñiœWו8#©8wÕ©•õ8_Å٥ʨQãüÜ«QÊj@é&»A)/ÇÙgº>'K‚ó +€x¯Íú·¶Ò- +¨ê‡†¡Ðnè÷ÐQètº}MA ï —0Óal»Á¾°ŽSàx ¬‚kà&¸^Á£ð>ø0|>_ƒ'á‡ð,ÂG!"F$H:Rˆ”!z¤éF‘Qd?r9‹\A&‘GÈ”ˆrQ¢áhš‹ÊÑ´íE‡Ñ]èaô4zBgÐ×Á–àE#H ‹*B=¡‹0HØIøˆp†p0MxJ$ùD1„˜D, V›‰½ÄÄÄãÄKÄ»ÄY‰dEò"EÒI2’ÔEÚBÚGúŒt™4MzN¦‘Èþär!YKî ’÷?%_&ß#¿¢°(®”0J:EAi¤ôQÆ(Ç()Ó”WT6U@ æP+¨íÔ!ê~êêmêæD¥eÒÔ´å´!ÚïhŸÓ¦h/èº']B/¢éëèÒÓ¿¢?a0nŒhF!ÃÀXÇØÍ8ÅøšñÜŒkæc&5S˜µ™˜6»lö˜Iaº2c˜K™MÌAæ!æEæ#…åÆ’°d¬VÖë(ëk–Íe‹Øél
»—½‡}Ž}ŸCâ¸qâ9 +N'çÎ)Î].ÂuæJ¸rî +î÷wšGä xR^¯‡÷[ÞoÆœchžgÞ`>bþ‰ù$á»ñ¥ü*~ÿ ÿ:ÿ¥…EŒ…ÒbÅ~‹ËÏ,m,£-•–Ý–,¯Y¾´Â¬â*6X[ݱF=3ë·YŸ±~dó ·‘ÛtÛ´¹iÛzÚfÙ6Û~`{ÁvÖÎÞ.ÑNg·Åî”Ý#{¾}´}…ý€ý§ö¸‘j‡‡ÏþŠ™c1X6„Æfm“Ž;'_9 œr:œ8Ýq¦:‹ËœœO:ϸ8¸¤¹´¸ìu¹éJq»–»nv=ëúÌMà–ï¶ÊmÜí¾ÀR 4 ö +n»3Ü£ÜkÜGݯz=Ä•[=¾ô„=ƒ<Ë=G</zÁ^Á^j¯^—¼ Þ¡ÞZïQïBº0FX'Ü+œòáû¤útøŒû<öuñ-ôÝà{Ö÷µ__•ß˜ß-G”,ê}çïé/÷ñ¿ÀHh8ðm W 2p[àŸƒ¸AiA«‚Ný#8$X¼?øAˆKHIÈ{!7Ä<q†¸Wüy(!46´-ôãÐaÁa†°ƒa†W†ï ¿¿@°@¹`lÁݧYÄŽˆÉH,²$òýÈÉ(Ç(YÔhÔ7ÑÎÑŠèÑ÷b<b*böÅ<Žõ‹ÕÇ~ûL&Y&9‡Ä%ÆuÇMÄsâsã‡ã¿NpJP%ìM˜IJlN<žDHJIÚtCj'•KwKg’C’—%ŸN¡§d§§|“ꙪO=–§%§mL»½Ðu¡váx:H—¦oL¿“!ȨÉøC&13#s$ó/Y¢¬–¬³ÙÜìâì=ÙOsbsúrnåºçsOæ1óŠòvç=ËËïÏŸ\ä»hÙ¢óÖê‚#…¤Â¼Â…³‹ãoZ<]TÔUt}‰`IÃ’sK—V-ý¤˜Y,+>TB(É/ÙSòƒ,]6*›-•–¾W:#—È7Ë*¢ŠÊe¿ò^YDYÙ}U„j£êAyTù`ù#µD=¬þ¶"©b{ųÊôÊ+¬Ê¯: !kJ4Gµm¥ötµ}uCõ%—®K7YV³©fFŸ¢ßYÕ.©=bàá?SŒîÆ•Æ©ºÈº‘ºçõyõ‡Ø
Ú†žkï5%4ý¦m–7Ÿlqlio™Z³lG+ÔZÚz²Í¹³mzyâò]íÔöÊö?uøuôw|¿"űN»ÎåwW&®ÜÛe֥ﺱ*|ÕöÕèjõê‰5k¶¬yÝèþ¢Ç¯g°ç‡^yïkEk‡Öþ¸®lÝD_p߶õÄõÚõ×7DmØÕÏîoê¿»1mãál {àûMÅ›Î
nßLÝlÜ<9”úO +¾„¾ÿ¿z¿õÀpÀìÁgÁãÂ_ÂÛÃXÃÔÄQÄÎÅKÅÈÆFÆÃÇAÇ¿È=ȼÉ:ɹÊ8Ê·Ë6˶Ì5̵Í5͵Î6ζÏ7ϸÐ9кÑ<ѾÒ?ÒÁÓDÓÆÔIÔËÕNÕÑÖUÖØ×\×àØdØèÙlÙñÚvÚûÛ€ÜÜŠÝÝ–ÞÞ¢ß)߯à6à½áDáÌâSâÛãcãëäsäüå„æ
æ–çç©è2è¼éFéÐê[êåëpëûì†ííœî(î´ï@ïÌðXðåñrñÿòŒóó§ô4ôÂõPõÞömöû÷Šøø¨ù8ùÇúWúçûwüü˜ý)ýºþKþÜÿmÿÿ +endstream +endobj +10 0 obj +<< +/S /D +>> +endobj +11 0 obj +<< +/Contents 12 0 R +/Parent 6 0 R +/Resources << +/ColorSpace << +/CS0 [/ICCBased 13 0 R] +>> +/ExtGState << +/GS0 14 0 R +>> +/Font << +/TT0 15 0 R +>> +/ProcSet [/PDF /Text] +/XObject << +>> +>> +/Type /Page +>> +endobj +12 0 obj +<< +/Filter /FlateDecode +/Length 99 +>> +stream
+H‰Rp +áÒw6PH.æ2P +endstream +endobj +13 0 obj +<< +/Alternate /DeviceRGB +/Filter /FlateDecode +/Length 2574 +/N 3 +>> +stream
+H‰œ–yTSwÇoÉž•°Ãc
[€°5la‘QIBHØADED„ª•2ÖmtFOE.®cÖ}êÒõ0êè8´×Ž8GNg¦Óïï÷9÷wïïÝß½÷ó + +V³)gB£0ñiœWו8#©8wÕ©•õ8_Å٥ʨQãüÜ«QÊj@é&»A)/ÇÙgº>'K‚ó +€x¯Íú·¶Ò- +¨ê‡†¡Ðnè÷ÐQètº}MA ï —0Óal»Á¾°ŽSàx ¬‚kà&¸^Á£ð>ø0|>_ƒ'á‡ð,ÂG!"F$H:Rˆ”!z¤éF‘Qd?r9‹\A&‘GÈ”ˆrQ¢áhš‹ÊÑ´íE‡Ñ]èaô4zBgÐ×Á–àE#H ‹*B=¡‹0HØIøˆp†p0MxJ$ùD1„˜D, V›‰½ÄÄÄãÄKÄ»ÄY‰dEò"EÒI2’ÔEÚBÚGúŒt™4MzN¦‘Èþär!YKî ’÷?%_&ß#¿¢°(®”0J:EAi¤ôQÆ(Ç()Ó”WT6U@ æP+¨íÔ!ê~êêmêæD¥eÒÔ´å´!ÚïhŸÓ¦h/èº']B/¢éëèÒÓ¿¢?a0nŒhF!ÃÀXÇØÍ8ÅøšñÜŒkæc&5S˜µ™˜6»lö˜Iaº2c˜K™MÌAæ!æEæ#…åÆ’°d¬VÖë(ëk–Íe‹Øél
»—½‡}Ž}ŸCâ¸qâ9 +N'çÎ)Î].ÂuæJ¸rî +î÷wšGä xR^¯‡÷[ÞoÆœchžgÞ`>bþ‰ù$á»ñ¥ü*~ÿ ÿ:ÿ¥…EŒ…ÒbÅ~‹ËÏ,m,£-•–Ý–,¯Y¾´Â¬â*6X[ݱF=3ë·YŸ±~dó ·‘ÛtÛ´¹iÛzÚfÙ6Û~`{ÁvÖÎÞ.ÑNg·Åî”Ý#{¾}´}…ý€ý§ö¸‘j‡‡ÏþŠ™c1X6„Æfm“Ž;'_9 œr:œ8Ýq¦:‹ËœœO:ϸ8¸¤¹´¸ìu¹éJq»–»nv=ëúÌMà–ï¶ÊmÜí¾ÀR 4 ö +n»3Ü£ÜkÜGݯz=Ä•[=¾ô„=ƒ<Ë=G</zÁ^Á^j¯^—¼ Þ¡ÞZïQïBº0FX'Ü+œòáû¤útøŒû<öuñ-ôÝà{Ö÷µ__•ß˜ß-G”,ê}çïé/÷ñ¿ÀHh8ðm W 2p[àŸƒ¸AiA«‚Ný#8$X¼?øAˆKHIÈ{!7Ä<q†¸Wüy(!46´-ôãÐaÁa†°ƒa†W†ï ¿¿@°@¹`lÁݧYÄŽˆÉH,²$òýÈÉ(Ç(YÔhÔ7ÑÎÑŠèÑ÷b<b*böÅ<Žõ‹ÕÇ~ûL&Y&9‡Ä%ÆuÇMÄsâsã‡ã¿NpJP%ìM˜IJlN<žDHJIÚtCj'•KwKg’C’—%ŸN¡§d§§|“ꙪO=–§%§mL»½Ðu¡váx:H—¦oL¿“!ȨÉøC&13#s$ó/Y¢¬–¬³ÙÜìâì=ÙOsbsúrnåºçsOæ1óŠòvç=ËËïÏŸ\ä»hÙ¢óÖê‚#…¤Â¼Â…³‹ãoZ<]TÔUt}‰`IÃ’sK—V-ý¤˜Y,+>TB(É/ÙSòƒ,]6*›-•–¾W:#—È7Ë*¢ŠÊe¿ò^YDYÙ}U„j£êAyTù`ù#µD=¬þ¶"©b{ųÊôÊ+¬Ê¯: !kJ4Gµm¥ötµ}uCõ%—®K7YV³©fFŸ¢ßYÕ.©=bàá?SŒîÆ•Æ©ºÈº‘ºçõyõ‡Ø
Ú†žkï5%4ý¦m–7Ÿlqlio™Z³lG+ÔZÚz²Í¹³mzyâò]íÔöÊö?uøuôw|¿"űN»ÎåwW&®ÜÛe֥ﺱ*|ÕöÕèjõê‰5k¶¬yÝèþ¢Ç¯g°ç‡^yïkEk‡Öþ¸®lÝD_p߶õÄõÚõ×7DmØÕÏîoê¿»1mãál {àûMÅ›Î
nßLÝlÜ<9”úO +¾„¾ÿ¿z¿õÀpÀìÁgÁãÂ_ÂÛÃXÃÔÄQÄÎÅKÅÈÆFÆÃÇAÇ¿È=ȼÉ:ɹÊ8Ê·Ë6˶Ì5̵Í5͵Î6ζÏ7ϸÐ9кÑ<ѾÒ?ÒÁÓDÓÆÔIÔËÕNÕÑÖUÖØ×\×àØdØèÙlÙñÚvÚûÛ€ÜÜŠÝÝ–ÞÞ¢ß)߯à6à½áDáÌâSâÛãcãëäsäüå„æ
æ–çç©è2è¼éFéÐê[êåëpëûì†ííœî(î´ï@ïÌðXðåñrñÿòŒóó§ô4ôÂõPõÞömöû÷Šøø¨ù8ùÇúWúçûwüü˜ý)ýºþKþÜÿmÿÿ +endstream +endobj +14 0 obj +<< +/OP false +/OPM 1 +/SA false +/SM 0.0199999996 +/Type /ExtGState +/op false +>> +endobj +15 0 obj +<< +/BaseFont /CFCALL+CourierNewPSMT +/Encoding /WinAnsiEncoding +/FirstChar 32 +/FontDescriptor 16 0 R +/LastChar 255 +/Subtype /TrueType +/Type /Font +/Widths [600 600 600 600 600 600 600 600 600 600 +600 600 600 600 600 600 600 600 600 600 +600 600 600 600 600 600 600 600 600 600 +600 600 600 600 600 600 600 600 600 600 +600 600 600 600 600 600 600 600 600 600 +600 600 600 600 600 600 600 600 600 600 +600 600 600 600 600 600 600 600 600 600 +600 600 600 600 600 600 600 600 600 600 +600 600 600 600 600 600 600 600 600 600 +600 600 600 600 600 0 600 0 600 600 +600 600 600 600 600 600 600 600 600 0 +600 0 0 600 600 600 600 600 600 600 +600 600 600 600 600 0 600 600 0 600 +600 600 600 600 600 600 600 600 600 600 +600 0 600 600 600 600 600 600 600 0 +600 600 600 600 600 600 600 600 600 600 +600 600 600 600 600 600 600 600 600 600 +600 600 600 600 600 600 600 600 600 600 +600 600 600 600 600 600 600 600 600 600 +600 600 600 600 600 600 600 600 600 600 +600 600 600 600 600 600 600 600 600 600 +600 600 600 600 600 600 600 600 600 600 +600 600 600 600] +>> +endobj +16 0 obj +<< +/Ascent 832 +/CapHeight 1000 +/Descent -300 +/Flags 34 +/FontBBox [-122 -680 623 1021] +/FontFamily (Courier New) +/FontFile2 17 0 R +/FontName /CFCALL+CourierNewPSMT +/FontStretch /Normal +/FontWeight 400 +/ItalicAngle 0 +/StemV 42 +/Type /FontDescriptor +/XHeight 1000 +>> +endobj +17 0 obj +<< +/Filter /FlateDecode +/Length 50073 +/Length1 90748 +>> +stream
+hÞ¬{y`TEòU¿7™É$!“ƒœ$™Éä"“B2$’p…#@€„CB ®åQ!ÞPð¾‚÷*"“€Wv=ñZÄõøþð +ÚKç/¾úò+÷_C4èÑ7o45Ι÷aðÝ%Ä
˜op*¬ÏŒ
·à=iÉŠÕW•ÕŽÇ{Q¢uñÒ¹sBþð
±ó
]2gõ²Èôà1>
ýí¿›³¤ñ佫Æ_6H;²léò ä\&ç·/»²qÙž£±3‰²‰¬/‘¦çMd"‹éÓ@tKòåÚº\DšL¬aºþ eGiu9f R͸r;yÈn\пì\‹½=)æ{ˆ
ÃÀèýn¹Eë_¡œˆ<Yk d"ã”?“£d{g‡aˆ÷å”~ô=5€ûTZÃã|9Í£´„î¢-¨ÈoÒ“ õ'HcâZrÓ=t½GSŒ¢ÖAз”CC©Éè¤ZG|=‚FÒŸ©‘6 ·æÒ¿&¦lî¯íâ(³ÔÐfŠ¥·0c¶aÅû^‘„3¨]›mÉ1úÿÃGõWz˜Ýâ¤þ½Ag9U§ÎõÆ6c;õ¢sZRÇKF¾±£¦P=¤kAA3=HǹNGŒÛAS-hXGÏÓëìÒI¯§Hš„Þ7ÑVÚO‡é-úaæpÎâfþ3Ÿ0QDZÎcÆh£ÁXJ•4žª©IœÎebº6]Û½ßñyç'F2殡U´š®¡´‰vÑûô}Äš°Š1EÛM‰4Œ¦S¸yhz’^¥SláA\ľ…Ÿ«tãdG§Þàà(Åý»hxúí¡cô6½ƒ9ÿ žjÏ.žÂ3ù:¾™ïä{ù1~šŸá¯!8Ñ4ízýOú×'
«ñ€ñ$ÖM¤>¾8™B‹ó<NÃþ²9‡Kù]á9ë¡‘Æ:ãÆûä¤LôFØó8šª¯¦é ý cÓ›ôý +yžBßñ
Üšû#Î&M\Nº&æÒ Q‡S›#E?^9]Bë¹…r¸ƒÒâ.ÌÚáñY‚/œåVmµòú«ú«BÇL/‚›ýa=<G`#¦@3Z¤¦L"ò?p,Eˆó|XLx«öW~L”ÑjÔ–‹¼¹ó¼^¦
ÇÀš”
µÉmJÒáÄ¿¤Hã|Ü1Mú)Ó
²¬ýY;gÔŽÎÙ¦^Ópg¬ÛzèÒ(úcø2ž¨¢J7Œ©´KìÑ?6b9”ôŽ
ë|–ÝœfØù +#„'BÂ/z²ã~}½~³¾R¿wÓ°š·ÐÝô +ü¸ã.§…¨_ŽêZý¿•6Àl¦Çéñ”Ø¡9Ämâb•X@Ò‡ÚËš‡§Ò ýv}M¦4šÈQXyN)ã6Æj})Ö´ro|mœ4~ßñæ{´ß4œ¾*§,šÀßë lòŸRã)-æ..Z8¤`ÐÀùýóúå渲ûfef¤§9Sö”ä¤>‰ ñq±1½££"#lá½ÂBC¬ÁsI×SN¥sD½Ý›QïÕ3œ£FåÊwçTÌéVQïµ£jÄ¥}¼özÕÍ~iOz^Þ£§Ç×ÓÓÕ“mv7¹ssì•N»÷x…ÓÞÎÓ'Ö¢|G…³Îî=«ÊãTy“*‡¡ìp`€½2®©Âîåz{¥wĪ¦–Êú +L×b-w–7Zss¨Õ‚bJÞXç²VŽ-aU±•E‚,a ʛନôÆ;+$^-½rÎ<oõÄÚÊŠD‡£.7ÇËås
^r÷†»T*WËxƒÊ½fµŒ}Ü
··æmÙÐn£†zWè<ç¼93k½Úœ:¹F„ëVxcלŽ»øŠÉ#ËkoíÞš¨µTÆ-°Ë×––[íÞk»·:dZW‡90V¤¨o¥7€‰U“íXMÜ\Wëå›±¤]îDîÊ·¿Fg¥¬©_h÷;‡;›ZÖãhZ¼4éjG[B‚g¿ñ %TÚ[jjoi¢³nNEŸÖhj™tõÞx=þÒ–ÜœV[„±½Âý…аî…Æ®6URÝe©jRgYRä
ðÚçÚAI{*”Ic!µÌ-D7<uŒQÞy8‘Þàòú[‘¬—㽦t›ÓÞrž γß\Z3Ç_”n;O²(å¤KÔÐ({].ov¶s9Î4–¨÷‚ÜœUíbs™ÍŽì£jðvN]QØïpÈ^ßx›'ÖúÞíÔØFž<WWÔË–£–ÞSdKs ¥kx½’¼dÒÛkÉèún‹‰ªl*òrÌÿÒÜèk¯šì¬š8½Ö^ÙRïçmUÍ%o¾ö®6ÉU^«% +I$jªB9³«³|©
õêéø¤„z^»Ù©T5láµÕò¥uV‡ã7j7þ!G©ìâ0?™Þ"×¥ïÅ—¼_B^h‹‚õQU3½¥ÅzIÛX ––Nûˆ–ú–9íFsƒÓns¶ì‡’Ѳ¬²>p¢íÆõ‰Þê°‰&.‚´ +ÞêäÛ&¶zø¶ÉÓk÷ÛíÜVSÛߦ¼~x]kÚj÷Û‰<ªVÈZY)_ìò…ª‚ÞÏQöOÜï!jVºªPïsÛ™T%PÇ4·]øêl¾…2ÔBø®sÛu_‹'Ð[GÅW×ìëåïmA‹M¶€ÛF6úi5Êkj»ËƒR²º\’"&ïIx+Ç
³ñ®þ£ºKÜ-ý¸¼§e™ò×l…÷|ØÉŸŠYœKŸÑ&váŽ?ŸýZvÑKð+q$¢±/9Šs!nÊFº·Ýûˆa¦án{QÒDN‹0b<ÓfŠ£~Ô„»¾ -ûßL&¥ãžKï‰aô9bïÓXýâž\ŒX‹ï×B/Ð>:jzÃsºmÍh}wå*Æ]Þˆxó,ßñ^ô‰PcZi2fº»0Îü gÀ?\€gq×F^ª¨Vl_Šu"AëÌÔ@÷§“—\ˆ<ž O[d α!úø‚¿Æ>o‡qëÏ-Š¦&`$Ý…w/<žNÇ<Û@ù\pÞL‹D
bÏ(ødÇÁçO0—Œ1%Ö‚{>hR0YÁxBYÀ"AÜʸ˜O€{S±æ~pæ=:+ÜF]ÙïÃz¹8½^¼ +±Ï\ÿ‰Ës¹sÊÞë°O‰k3âÖܤðA¼w`õf…͘9€ýÀ7‰MàZ-ÆI”ólĉHœ.J +×a‡2b}–¿M×gï%b¿q½e +¿³‘îGlŸ$±_’L}x$©Þêù¥ò/?b~ ¾&øðœw¼]
””Q;v)°¿ºƒq*¨ÆyD›à¼€žlH8à’S×uá"Èî"øšgÀµ‹øFìƒd¯ülöó3ÀS?×tñ2€éwy¦ï«õ#!qÕ´Z)ëˆvÈ—›nõ¡èB‰Âù8Èò°Ÿ2ã{Ê6N îšÚˆßSZZnH½t̃Ü
s±B¼×3(5àÔÖ#ÞšÆ:€—¿]„CRÊàÇŽáJÐþ螆3¬¤•œ…Ò]À•J’×ö+9ÞENð?þtV‘Hk1†já¿_ ¿7-NбÈOÅ:P‘£è¨ƒç¬äÙMƒtÇ€ÞMàÝ5«éÈ£ñVXMám/Âê‹”%yô_…}Ž£ä +qüàÇüð5þˆ?ày°lçx×ðD‚fΤÍèý…ÃïðwÆ™“½¨¯ Bã‡ùQD¢Kxê¶s×CöÒU— +R=m C>›ÀyM}Í$²äó,å?hðèõ t +;øGHî~vA3âø2®Ð®£WÔøü?Æ/)w)ÈR`tÁ1p ûûEŽÞÀ®ûó·b÷»ãç𬒼3·ÃoÅž7Gwœ«üJä¿0†ó8šÎaaŸ£aGW+\hÀx‰Õì¾°ò¾š1äaÏàQ|0JÁUJ‹¤$¤±‡ýÖüµíW´ðgqp[7
ý%쩹¿¢Á?ÑØ_Ë¥FÐP~¹ßjúµü'yÀšþJÞe~!X‹_Ë»ø «¯ó;UF|¥ë\ á¥~kê?ÿUþ›`înòÆA4Q‹[å(ïVÜrÑd‰¢/BÍr~ƒW +"‘ö<… +öFôìÜЮŒÛ«<»cðî†e•þ²Z6½¤§ü‚àƒÌÝM¹ˆi¾¤FD€ôX ¯f€kAs9¯Ëøœrå€
xˆ6@V|ce›Ho³§íñÙ˜—x v àÝïø|Ú[èKEq`©ñY—Øi[šÃe+l!J2ž¯nø&ºp`=Š¾SÔwâàKJù ¢Êp®·Ÿ{Eè1·Ì]´\Á.pèc¤wÞBœ%áù唶ã<dLX†·³ˆÌ6ÐnHØ>õ÷š&ø‰·ªì§ßÁ³kV-V?4t•žD4 X¹œ
È¥¯p2|#DmÜ!z‰^ˆ·<* +\CkÄ`Ü(‡ºqO’wê±U›w"òÈ㸎؃w7¢?¤ˆdìV +Ý)f7F¿‡¼ ×H×âÕ\¾¾¼8›Ü«þ +Æ¢nöÚк=F¢‘ÈÝà`}è1N„ñX…Í +=>ÅI¹½«È1ÛÇŒcênêd¬ +IÞH;ilFKoïyš] +†åè…¼NâAœžPZ©Ó‘_ž¥|ÅåÏà{ê°"°#‘ˆ î‚[Bçá¼ç¿Hâ~ýùž¯¾l?"¿Ê/˜À€ÿæ»là¯øx¾Œ—Ñï âZcÕŽ¶MèiGV¤²½½Ò4Ë<$LåmÁKËò´£´¸øP§ÙH×ùk4JAZ +”µUûNí yGoeÍÔ@ÍÔ@M©ÖN¬=¯=×––‚¥÷íOðmY‚¶— ÐîÒÖãÂJÑ.óç³ýùFäÙÈ7ùó;´õmÅ)áeÁx‡( 5€{ÛÞ6r€ýª0Ä +Û5Ûö¢&¥,^Ûª¶ƒªí j;¨ú)cÖm¨ß†úm¨ß¦ê·«©}ýSùÛÛÂcü5(”Yµ:m*N-E«õçÓ´©mRŽ”ÕkS0õ•îÔjnTél•NPé:ÕºN•—ªòRU.UåRY¦yÝÒ•†ËT›¤M†Ç¢MÔƨ¼Z«„Φhð.óñð§e>N©ò±¨Ç-¥U¡_$ò1šòûµÑx¯@> +ï2©h«Hé_¶ï³Ñ&°ž¬¯ +@9 L+Ãæð ÅCšæ”J´´CßaH=š[íÑ^n¬ä¯Ü˜ÙãqãxÜdÖÜHíZõz€ÕÀz â-ãr@WVÈÑr¥h±7tŠf÷ç)b½Œµ´d±¾-9ÅS,öQ5°¸Ø,öµ™"ÃË¢ÑOöÍN +)«²½¸xÄß–ª„9U g*æJµyHKU)iŠ–Ú&‚ÃÛÁ_. +/+ß' +6ì(ØSp¤À|PÌÔ‹z•bb`\##, e6¡ÓL +ãÿ¨t·J¯T©G¥±ž„™a§g†½23ìþ™a÷Í«6~f؈™ay3ÃÚ¹Áë +ûȶÉ6Õ6ØVà +è +ëë ++‹@?
Îäa•Wé +{ë˜5?m÷®‘Ícœ´¦²¦¶u§±¢mŒgL¥sNEÝÞ‘s²w_²ÜíåZ³çüÌdsädÙr‘»¦y·l)×Ú-×Ú-×é©ÖRR±´Ððºò™¾|¯±B€ëuÃclËJ”4;âÖ&ЉO!®:o¨s¸7(›rËrËd´L6õ’?Üô7Å-v$àßû›l¨Žp§¸Êø·|¹¿ðÿ-—ÏŠË–_¦rõoùŠ•@yPòô +ÂÊB•UN}Ê2K‹,¶¶|yÝ +R§º|%ÉùVÈäâô]¥•˜™—wZÞó‘²á"bºå+½dÇ•~ÁY.ÿP‰iHéŸÍ'Ò盤7n¦AævÝ'˜Lº,hd
2¡ðœ¦‰„`³¬{Ž)Þ2áš8×xÛ9÷¸÷xÛ÷îq¶8î·Äüþ#éŽÇ|.ص£<&ú‘ìúQØ·¯ÏÄg&“òÇ'xÂO†œ ³•lµ"Ó?ï‰ +£„˜gl%l-Iz¦ÛÌæCb4Ù©“ÇSœËöý¬³§OÛNŸ¦ÒÒ³¶³9ÿòû#ÀÔ‚‚œ©™ZFÁ ÁÄôŽÖTäD-ªÄó"6"2V¤‹<§³_c¦kXI¶Lô»;¦Ûìâñ¸Ô~ýœÖ–a®÷°ì\·´ÉVñ„ö¢þ®ú›J}k/S»¸Åcekp0L¶õýàâQ +‡=¡öˆ#oEœŠø6Âq€cHˆÃ{-ü>µ‹GŸíoYŠ»à¸>â?©}œ;këÀnÎïÜ67ø‰m8ü»¸XÀZ#‚ìññö „(²—`7éïv&d¤¤dð¾'yÐX«G˜†#«â*ÏÀê¨ê>;¢w$î‰Þ“°'Ñ<’Fe¤.óÉÉ<c´'ª`ôsùÅù‚«œic,Á‘I}¢fŒi7Ž¶¥¨,Í—%©ì¹Ø‚1ÏņŶÉ&z†™vrÅNOß¹öi<£ŠfŒòÌR:£°dÈ QƒªEZgDψ(‰ôdoéI-ˆôÄ¡^0;’#ÛEµ'w\¿¹3§Ï6cLAÉàA£Uá1ƒ¢gDoŠÛ'ų́ŽÞ½3Z‹.‰ žLe‹Úµ3J‹:$þIcÁlj’çf¹¾™uv–í,JçÎ}ƒÜ¨Çó*ž;w!P}Úu”—gë=:Üò±©TÕu¯ÀÌâ.1’'’™QP(
‰ò‰ÖÀƒŒémÖº•|ÃNm f|(9!!ù D1"ÞqØ.âl‘ñlß#kŸÜž’ò°Ã_ù‚ê•ÀŽ½²µó»¢‹ÓÿŠŠŠíÌIŽÓÃÂùÍ‹%YÏ•žHŠ×mq¶ÎKjÔ¿ ³§2í+ÓDªá…ž©©¡¶Ò1Î1i«W§¡‚¦¤Þ”úlê³izÅîHu¦¥g˜3Sª'Œ7¶jŒyô¤Òvñz[á§#ÚyFÛ€Ùe¡âzêG½Å«Ô‹Ã #ÄŸÃòöáû,G°Øaõ=Ž¤‰ˆˆlç°½™æg·‹7Ÿ+=,3aê 2+:”‹1‡ü¥Ð²ˆëÛR†MzA,EHÿaŽy7Ck: 5çΞ…ÙõAÙ-•òÎÍrËÃ=w6OÖœ;E*1¿ùÕ÷Èš¤¾ééUI5)rT#›6ÚÃ#û"IžÜÇÃ5dŸ˜Š¦Ôê c2Æy8Í9vܨ¬ê›ms» œ] ¬¨z®¿þYÈä*oúÄéµûF&WEW6p«ßP0Ùø¦P=utÅ,Ød¿Mê;ØWŠVê
p¦õŽŽÑcc¤œ˜}
™ÑA¾’ƒæRc2•E+–‡ZQë済¨¸¸([ŒT8ié÷”åsqaõ„¶'dûÌ1a‘q±Q‘aÁ"hÇmw<ìödßò‡ª±êÏ,”ò¶0(%+>.!ùºä„Þñyƒoš<9'µ8Á¹zÊ•»#~=~°Nω +OH~491,8¥`é-uÅ5‰ñn÷ŠÅOÉ¿½4¾Ò£õ)„bÉECp–Ã=U¯ÄsP*/²øþω+»opŠ_¢2ƒ³’ãÆ¥8O9…ÓY ¥Ž³Å¿/âãµâ!FÙ¼ÞC4#|Hpèpˆ9$¨¿ôØ*’K‚²J +‡„çpŽQ2d@»øîùŠ`Ê™»+Î…ë€mߟíÀí +JPbü‚â Þ§¨OLŸ^}ÜeÁ.1ˆŠ¹
mœ.<RjØ'Jp̃|b"EÀdòÕ<$ÝwÑ™ƒ´_è+¾Ø²`áæÍnv/Ÿ8q¹D{áû^æ³)R³ö²XQHÙ²pÁtÚ2,ÐIû×â[/Þ²eñä+&ßîÐ#CÖ Þi[¼eë"Ù©fùŠÉ“V®À
ÔiœÒ:õÁêïêß{Š®5_|íÐ×ø
»©8{jÿùÎùyטo*¹½ìIóÃ%/•XÓòúz +òŠ<³2¦¥õÏÏw-C\ˆ“m÷älÈP˜ïtæç§Qp4ËÒ¸¿ìªýƽΉò~ÿ}g&ÉL®9’L2¹ÉäN6»›=`CfYEÅ"ŠkXÔ¢QØB½+(EQ¨WE°ÞZµr.*mmk=Z¼ªµý!¢u-Z´Ø²ÙÿûN’Ým?Ýûæw³Ëä{<ßçù¾ï$õ#S–ÌöÄbJ?toõ§UVÞ×"¾ +ÒÝ× —ƒ£öBßšÙPéÐ’eh?æ'ÎO¾ZøPµ „ê:TEâ§øcUÖ`ø€Kµ¸Ï‰@ålmíBþ\ƒ—9xŽ‘"Uyƒxf 4©®_ƒ×À>p1»íüñ+ðkÃnx'0‚‹ o1rƒZ*„`ͼpä+oy)BÂìÐÛÉhƶ ”X†t¨[5ƒ=(Ët„DáÊ>
Õó 7ÿ!G¨@ÙŽ>L,»ì2tO¯HBð° +QM¤p·ÍöbX‡P¤4T#ž(§þª¦=róIìÖëb×ůK<(±Ë¼5ÉX£X0·%©D$éOÙcþxñ0)ҧ ø/aH¤ât<)¸&žžÒƺUßÛQ3ªî¸¬ aˆD4ÃÍî~øÍVí>v!aŒ +šî0èk•´†gz½†ˆ•¸Ð}‚/ûfž¼òâÇ$=cæxçüçløP鹤òöÀÌvÚ®:ðù¢L/|èê²Ë`tr
Ìygõ¸s–,¼wŽÝßH!c[¶!bP¬©±±À“O–§D»Ú~ôËB×µÝNÝZ¸£íÁÂCm;mΗl/Ù_q¾kû‹ó3Û¿œÃ9ÿÞ6{9’ïGõ¢I‚fM©8Oæи€.â’?WÒ +…-Á î‡7mQŠMˆßÜ´M(ê#Å–~hQŽ"éõ¶“îq¹ä/qÍ“ÔÞ¤Ó[>€Ë«ÎÀòCæþýÓ¸ÈþSq`íG—XbøÔR +å‚¢bYªb¥ ±W¾L¥ÚÊ}m Šb½¯P£šÕ–R‡NíJóR=gªN"mK¯øªáÁ,ëä8ûÝOÜòÛs¶—ýnI:©ïÖõWqKšãM¼ëŒË×o|ù\âñæmçþìã³8s±Kv,>eÝ÷pnÁÕ=sÖu4Û'/žþÜOfÞjÕŸq~!Æê!ðªjAõ=HøC:_À+"³Øîó=+²¡ÎU«õYG0º€ s&‰P ˆ¿ƒ$)]Èoñ㎰¢b„ê—Ï‹SA,Zd?±Be¡ÎzÏ +°‰¯ó‹ú¤LM<$9ô:|ý©1E<Q+/àqCºrì=‡Œ}Û®òU`/ñþPÅùó8ΑåÒà¯jØäa¼a&!sé2‰S½‰‹w&þ ½ëú›‹–p‹8ˆmhâ Fh;”Å€|!ðăB¼ +÷«Œ¯HQF DmýðÿTÆY4º‹œˆ• A,܆ÞyATî‡ÙÁI™(e¬‡ð¨ÍýD6ªöW0éÄ}ÏR%éíZkÑëryuŒW‡ê¹‹AƒGïS¡D;G#¥p*Uîƒ|*°’;.r#aCÍÖtò²)×ï}óÐÖK/ž¦*.Ž·ýló{Z¾bEЂdÕ!Ô-•yÀ_·½p¤m
‰‚$Üô‡‡o~âÎ%ŒCBd]7B‘h€©ælØ.7‡ý)ȯ
Àð‡ªµ@§»¨SèÓ©³h}x²o°öÖ^#Írÿðª£úm™¶ô£ß\FQm§ì´B)tÒ6ÎvŠÇ¶Àv¹ízÛJy—m›üŽéáo› êhCP¯H¬Œ†æÏ]º<¾$·¸aKxWòÏæÌÂY4"A/mö€Ã/úœç²„l1GMŠ6äˆlU•„!•Ô9õV‹œG9òà¶L‘$O?ü«*Šv]¬ÈX\è‹ É%ƒÉ†$•|†x4ÊÀL<´#\l@ÂMÊï‚mðšŠWÆ
n¨¬ITD°¯÷W÷\Æ´W½Ñt0DÙ8–g–Ô›-&¡OSImá~øÕ#âvQ9N£Å”.£ÂÀ?1Á¨%¦‚„!¦‚±ã:4f‡qO+8{ª–ž
-RPÙÁ±R‹HàNê˜Ð§=8ﺽÏ>|Ñ3-]¥†Mo^5³Í%ò!QüMå9I¹Ñâ›æsVa[rñûÜñÍu7>ñÚ½×Ïß8/ÌJ‚Óh¯<ýqèÕí÷<µfÅ/¾×Š²òõá +ùg”•°üi†ÄÅ[ +Ièõ$ñ,c¶X.p +¹ÒEFj<N†à-²ÖóoÏÐÇ©š
™¼'À;(Ú/Uàµ#ʆhС2à"yhÈÐ9ä‘ะ~[Y€2,÷¾.|!5|pRèƒÜ‚D~UfйЕ΅fÏ K[³›Kz»¯9ðš¯#fÔoƒÙÉ4è[Ç4umcæ¤mþ…û6mÚwႳ“ãÞ¼ãgoŒKXîûÑÒû6^réFç/–/ÿÅË–=AÜØôðÜÛßyçöÞ‡›í3Î]ý§?>·{Ü'ï¾gÁ¹·ÞZ1,zà‹øÈ#m(.¢ v«M%
)}Lõ +ÉH
V,Vc³9Œ†F±)K;0c{ò ßDþ‘<œÕ=`£$þ~ìtùÿSЈì”A¿¥·oË?Ÿ=OÍ¡-2P¬æ˜)Î$‘D3‹‚,+'ŠFÆ3Õ˜C€fE‹2€0ËB<¤å"ë.¸?0ÓÏ€æQèâí׶ˆªÑ°¿4Xk!µW,–
G(‡Åj¶zÑgç(½.šdPŒÄM(FbJØ!c¤²Á,…Å'@‹V4D¸Zß2úÜv/PNaÀêƒ#†æZ’ÖÚ_5¶<¦æBsLuokù\ç–9gÜ?÷¹M?ÜÝÜÕ®ÜzöÕןÕîvñfg¬éMØh/l˜áÏ~þø%M!âwK–~ÿWÖݼê‰6_Ò}G®æ\¼ÓdƒM'ß~éÖ7Ý°EUSÈÏZï„<XÌ«»Y4Ñ›^ØE„ ·™L’äm¦tLåªJBëÓR±ý§Ëè@žÛÝ:~þZ;Òu!`Ûp’Ú]¸À™*¿Çº×ú6·Ïú wÈú
gp"’òØ–²ýÐ2èþØp¿©~(ªS³õ5V„â;Ð×î” ¶ \m‹
¢iµ{Ìí‘¡¨$fFÛ¦w·¢aÆÙ®|äxWP?æV_®4„¿Ãlúã\ÐIµSS‘®]¡úŸÖCšad +d¦õžxæ»+›ÓëygîìrÄsÒã?=ãñ« ~Ì?OH]‚rχ ά†n6Þ`º^¸Ávƒ}cm`mpuè¦ØêÄÚ¤U¹X0á
á‡)˜»bÛBDíôa¼5¹ÀíöŸ“&ðuA—ÐöR|4Ÿe~QôùtÊÏ0„Ÿ&d…Er‚
²ëΦý~DÞ&€”ÙÛ!=Ú÷M,yPhîÈü·
*”ÍÁ¤Ñae-¬™5±”^‰Æ¢ñh"Jém‚] ô¡hÒ(gaÐÉÂ(›Ê°ÈÖ¢x;³¶É‚êóØüÀÛØo†Q$Ô²kŘ–>í4|~ÁSÙé ßWžwm¥¯Ü
óv–%y¢¼fFåOµ¤8³wÁÔùK¯ùò¬‰8+VÿjÎÓŠ³»Ó'£|8ù#‡üQ€‚êî
,Ò/Ó“¼ÉšŸ)ì
"Ÿ—dô˜k±þ~UÓ¬TÒÏ"PU´»)›ÍçnÎâ +Þæwsv¸¹rg¡¥{ÝæÖ¯†ºÕ‹òvÖí6 9}§/œwsù’»^ý:‡ÈÅ.è´YDòè…(«¡¬ê‚¿VÍÂ}⓹-âs9ª*L–TM!¸ƒóç|З +ù|ÁÏnÔ–@æM¹\c“/Ý1/ql)P"J©®Rib—¯£ª#LúTMFTE„ILÔ4D*ªý$Êã)9ʾÔø^êm°-ÕÜÖVhö„ý +'ä´C²UŠx|¨|çÕ¾(ÿÏW‡«-ýžÃÍ +|ƒWš{ëï‘‹‰–ŠÿXÉ¡ù©pk}~T¬ÿÅÜGH€|‚b. +ÃÐX„òÓ9ÈIÁ5ï»F8ö:rvIkfü®ü.o}ë¼Î1
ÃñÓãÎììÓH¾Ö?¤&ŒkÔ˜}Gèû²›¾T¯ºš\f»Â~±†\k[m?"Òa²›äzbƒá1ÃÇÜGöD=ÅÏmç¶Û©FZ F +H`¥€÷]—Ë0°‚ÉD„€ÐÔåÄPªZøPÍ\i€ËÑÿ玳ç[ý4mÀ?0à,7@ƒÛ°¾Y+wˆÂaŒÝ?&±kÏÅ
âSÁ9„ß%ÂœH袼ŽE¨Ëê
6Ò™œa°H™*9ÔúsÉš€*׎xÆj';I¼ã‰õÒq–%ŸÚo¸°Á©?›rÚÉ=•8`‰ó«ÆrßµïŒó`‹¾_Nž÷ß<ƒ80¦;;!â]Èʉï«eWÆÕâî”› +M-“C=„v^ºªsµººó.õîΧ:wu¾ÔdcAKÓ Mg4Sl8ÕrbsgaVþùÒoÔ=´'ìÉÏÏÏßÖüTæÑ–ƒáo2ß´'¯Gsê˜h¶/ô6Q@}R²AkØ3ë2DCf2ëò™LCޗ̃j¬[Ꚏ w"<ÕpODðu·Â*¥A!•T×_"êlV[¨ÒÄpÀ +ÛC¡0åÃT6(Ɉ’L$¤|8Dù‚ÆE´µ*J%šæ•¡A?qÅÖPÈÅ4öÃ3w'щJã +â¼<„S¯kÊ +p^r¹ƒ›çèr¬tqÐ6tˆÕ-—;yKHäƒÕ¢VzÒÀ[[¼iõ"ªWÙlÁ; +Ç +ç]è^Ó¨odrÆ6K›ãr®I¡´%ËƸ˜++´"ÃÓ¶l×ãèqntí¶‰Ìc¶ÇÙ
Üï뺞™Ž3\%a-»Æ±ÚuŸpÈLrLrNrMNgÛf³grLRh±58ÍÂmSØIcÖ›¯ÞË$mqG܉ýdÒŒÃVEƒƒV{ÌDYc$´µ`Ð¥|Ì özÚ¯”ÂÂ&!oWÀ’@|%Oj£JX&6»L>{‘ë<Ú‹{¶oð«^N(ºHy€•÷]‚Ë_HcÄæ½×&’S‘^×7ø×ác3GŽŸ'½±Ò;H³“¼Oëû+ÑÎP7ÞÀ
$4*‡X¬ªôˆô¬³h©ôaUÙã¡7–0}{•‘c@ªï0Fv`äyDJ+Hœ›£/ºåӻ˻aa÷ŠOVLÿä™'AÆg>A•ÿ±Î‚Vhƒ3וÿùðŸaGùåw?*¿ 'ÙêÅ–d¶$P
Ž(í¡½† +j,G¥#Ò&ÚŠ5\1ÀM
±
ÜäIÓ@ª§ò¤iàëHõTž4
¤z*Oš4ŽÑÒY°¤3T(oÃy'•i %¥*µ˜2*ý%Zì¥ÁèÇ‹Ïj˜9½Mj™ì³pn“sJSCê®Iu?¸`o´îíø+7VðòkVoél{ÈåÜ›Y‰
»]'ð<{sNù€(|ù¡ògå/Ê@G«=R3"Ïb¯ð?¶ip§òÃ4>Í»…ñs +‹ê®ª£é–º)u³=3ë®]™¹ºpGaCꑺ=ò¾à¡ýò¾êOe»M6ÖM +vHWgnÞšùUðwÁG3»B/K‡ÒUíƒ_#°}«…8Ñ¡m±ÁP*-éÃÕ™H°4T¼ÓjÈÖ¥¯!ú^SÃ`ÇWN¥H|'¸
]ªÑ:¥ +à °¹˜ÈPÆâµy™o¥ã˜ÀçÂpZx]øµð‘0&€ØfWX˜e°ˆ›¦\vb¾¸´ä`é`IÞmSkU¼¡ò°!rJGgÿÍN8m#W‰1÷-¡mƒýøÉ÷oJ[ +® ÞŸzò¡:¼×±r+!fBeú~Òà:Á[Œå†
Öô“ýÆã÷¿yã}³»ïPÈÑâûí*ñÞzÏxøšònd*O9Ñl½ô³Ùkãïû\uÝÏΞvYÓÙ¿Áøs+F$<¶^§€*©q¹Ó½¹Rn©ë&×ÍžÞÛ›ï™h:5Ô1‘xxÂC÷¹¹¿p¼ä&B)똗V’ãZ=‚MÇØh¯P5y’e¶›E¹-oµ›CFãÄéæÛèšÛâù˜ÔNÑxó‘Ô”scl^ +€ž>¦ÔÉY™Ð•\–\™\›|"©KŠ“î߃£ÿc¸¨ÕµkyèJ":ÍØÕJ%ù¯Õz¨©ƒºZB”†j…õ˜$³Æd
’Á¬ð‡˜dl…¬—‡K?¨Õ ãÜP·~ùmÖœ>Ñ£fÌ:ôþvyºÚ™í<ðTǤÚß¼>wîm¤ÇûÈ"ý5@òÎ7<¯þÌ\ÐîóÇo=wÕîµäÔ$%=÷î.›xaÀé‰üà7.¯ÎJ¬ÝmêžþK%e3Z +$öH¢1ºÉœ9DWöíŇ½„•Iìƒ][XÖ +ªauTW×ÊnÒ²'IcU•Éè·k‘¸Ér®«Åö)"'“‚Ì™dÎŽü͆¥ + +7»… pºð.$»ûÐO”€ )§LÑL\–<ä/rÈUz¹Ê‚à³0 +u#ÛãòTÀÜi=ÃÔ64øqbÜ}ƒGžt±C`$J¥YR„0BÇD’ŽœÃ1fŽzsù'.ÿiP5¿MdÜÙõß×xùš=&AªxüOôøá,m˜Êú¯Q–xÖÅnÂ@9e
W€-RS¤Ð®X:]5šÎ°Ìs•jÎh:Ïò#×jÎkz fUÓÂ}\ŸÔ—ïkßÅí’våwµ¿>ÎZ<Üþ%ø~Ɔü±õk·sí6a¥|®Jù|;Çq)ÏKR¾>Ârl +µw ø6·÷—¥ÕÃ΃|§¼²ž½Oš³`Ì9,7õˆ-Ÿ2,7O£šaQ‰Ã·Gs2ö@•±¬àÝQi¾†‚ÜyÆóœó]‹MKÌ‹]ú>êôb~Ù‚”Û–@Yª ©NjµÔövº…²i(Àl<§²ék©ö¿´efmˆ²Óº€µ +qØý‚ŒM lŠ¿D_Þ&Ó$O5¿¡ÐÀãµË– !;a\@Š¼ªZ{»ÄdµM Û£ +žŠ•êëÑÅÖc+¯OÛèÞŸlƒŸ?‰¬C,7ÂMÚLñ¢„ÏÿÙ[éŸr[‹ˆ²Û4KP’¤ÂHõ¶]rBçPJ—*=2ð:Iߢ}ç åäé^K=cøRõÝN[z|¢ÆÈ@4®<@¡ßvСÈv³õs +o²ú—¶Âݤr3K*7÷ +X#†bäÁ
U2¢Ep 'r¼«üŸåÿtòxH–ëÜVNðÀîr·W䬪þ‚=ôŸËPª6æ@3Í‚ìIõžôšcëUI(Eq`ÏÈ^Ÿ¦(NW‡ïQ‹l`
ó
‹
Ýáiø9~ ,ÙÃø#Kø3ÝîÊϬD}PÕÇ.JälîEÜêü¯Š:3'ò¯b1t^5¸Ÿ>‡ê Ð +LÏÃÅÃj{¶t˜Ä4úÕpêPøÙÞ<f£¨ìÄ4í +pæS¯ÝýÈ7[néìî>ÿÉ‘u›¬î›¶¶g1±X/´.?õ©¸ôÇ—o_pÍoïéºv‹½eÒ¢f“ÀÙM6Oêþ{Õøéïìlg뙧_4cÉÿT㵟5Û0ú$q0WÌlVu.ÃU>9vˆY§(ºœa_À@AsH¶”Ì}pÁfY2†$Œo()ʇ÷'¬Š~ɆŸ<Ò{R‘³%ääIqïâ÷óØp'Ïýåèå ‹pp(µ†-&qžð~áìÁ +_ú{vmü„-•ÅPξÄk͵Ñɉs‡7DŸ‚[ÍO¶Äwêv3{éw™ƒº»‹®ƒõºqævØi>5pœ®+Jæ…p‘î2óUè:Óuk‚+Û‚Ï„7Ç\ØÒé1³‰¾Áž¨tk•8Úñ'H¸52&óZP–,LýæÍ>¨/¹ùÝÕ/ŒªNxà;ï|‡¼è÷Þx±üÅó;ËG^Ü@öz¼J,Úµöï_‹_&æiX3SàÈfÉd¶‘äîQ%ƒ/9ß½?< ýO죸!ꌻN MMO•b³ã—Ø./Ž-.’Ú½ÂÁÏrœã¼4¶(~Ô£Ó{DÖéI²I.湕½—ýµ°Æ³Á¹_‘9»Mä½jÅ•èskqpp‹]J̽´Þ÷;·1[[™Yë‚pUð¹ +z2¼$“E^'CB +©—vCÑ…Ÿã§ý(Ö… +m%ò¸ì’û\Œ‹ãÜ”û²IË4ŒÀÏÊ?§Ž%3r0 ÔMâóè]éØÇÒÁØ1©?ª¿4yyõ‚ì‚ܵU?M.ÉÝžìÎÝŸüUîÑäºÜ¶€1Äœ¯£NÇÃÒuBˆu‡ðZZ«ë¤)-Õ²iEz¨‡ †L&ָθÑHÙŒ$ñò„qQgôj¤îȪȺÈƽ#²'r r$BGÄ|꼄Uµ„ÍŠƒ€ìâAbR‹CõÄÍcŒÄ()Þ¼ƒýÀ3Øß“bêû¿ê 0€012L-é’–™¬veGÀA'ȆI†¼ÁŠ"•årÑ/+‚ +y.W?ÚtP×k{_TX<wªZàõÙ”¥q×Íû;vì±}7ï¾ãŽW^¹ãŽÝh×oU‹±õ쉙sjåÐ駦&ß +áæÍ”O»ëÕ?¯¾ëÏƺ0ëÂåXšà•ê{<ÇBˆ†N¸P•~¼ƒ¢°™6èoؤÛlxÑð–a¿ÇàaìnÕnÛø ø¹Ï»…°=™UOfnm&“
'Y“fï«`Õ\5©f5üjŽÍàצzr)dë +…úºp$¥³t2‘ÀËÝhkbŒ!q¿ ++$ëñêú˜W'¡ÇàÓTëä(fÀV ìß²y
ýÌÒrÐvµ°l£«®†c
ßE€gN[=çüsÏÅŽM°ü©B»áª¹²—®ýS5ã¢c3&OZÙ9ðå°þRs®-øxhBƒJX{ŸÁÒàÒÙ…ì2%ëEE<S\ ^).
Ž*v&q¬Þbœ©Ó…-.Ÿ¸Æ‰q,õêƒwmñé«,& +hÿO¯/W‘Pš<s渳Ë_¨Àxérr÷ÇUÍ_péªê ªø·_ˆµ|^×ÕX˨o+Hb1vU“¤2š·¨½ÒÉ™‹:~ï@;ó0ŧb5ÉT>QhŽcã’Åü%ü%ó"Œ8(Íw&ߎ½ÿ8öqþXìXži‰µä/‰^Rx”4¢" ™qó°
÷¥ß‚0$_ja‹¤WXŒ¼ƒs#Á`8öE@uNµµµùÚÚ\>\/ØÍêY³&«Õl +Û {P§^¸G%Õ‡½¼##“ùÉÉäÜX2)Ç™X4† +y¾PÈGxç@8 +Q^áVŸÏÙêÕË™\kuu&ƒÌœ0™xâB»"0òÛXtza\bx¦jq¾;BùÚüü<•'ÖÈßèÀ{?Þ}»ˆ5†Œµx@ö!½QlØïÝZºk¤D†%6jÉáþÕØìP>K-]«ðžÝÍ7Ó5ZŽÀ1¸·7ÐFH©{{}Z/Ök½»Zí{FŠc ©ŽQ#,„@ÿýåïŽðŽ½›²ì÷–É8ôz¢y^eÚÚóbqO~Ô,59‚ #AóLlÛàçØÛ?:ºâ_¯šV¹ê«Þ˜˜5UÂÆÄIÓ°GpÍpäXŽŸ”¸xz”³ø¼ êJ1ç•ûàÚóT*Õ2ÛZ¾þ¤|ë(×ñ˜!惌˟”g
–¯Àµk5J +ç
N>,3 fÄ(q&Aˆœà\c·‡€!€!;Ëv²;XŠÅÑÖÂﱂßiu¢ýûœØ¿!×a”QÇ¿Õ‰ëŒÉ:PJi³5Úš¬Í¶[›mœM±µÛ&9ÙÒ`ÙäíÉÐqØ +wÂá` k¨Õ&slå:²¹\m6ÜСÉö·ÃöŽb{»RWgõ¹¦:á÷é¡!Õ¨´‚}J¢<’ÑHb1§©Êr»”`¡ÖÕíB®ã²?ŠËäXî–‘||<ȆŠãI Œß1~Ïxj¼89õ˜0*f‚é¶án¸x¸RL:”+ášÁ¿Q\:¹ÜlHkôÄ +«`b,¨¨ ŠP")ˆ&3Ç’t<uzÑä„.„‚ÅCP†ZnIÆ¥†Þ‘bwÓà'€Æ/Ãà;ø»ÞÁàå!ì —¨ÆÅ@~g¼¾OëÉ/éÁ=Ðÿ§QS½Ø€Q‘É0‰ŒE*c•ôƒK/›p¾ÔtEËœ†É“UvÑs5‹&t¨Ãκê̸vuúŸjÕ„:¤ÎŸ~ŤŽŽI§ÏØL¤Ýœ=é‚7Ôñ¯Úgø“µƒgKùeXÊg`)o‚7+ûôû´S¿“Aë™}C-1tÐÃBf¡—º×»A®öÂMˆò/ " +¬ÐÚQÙ•4LË‚Cc€mU¡C¶õMz¸
+¼^¬R‘Ô'©³=·@¤ÁR1KÔÍŠKjÔM« >ÃÚgµG´ïiOh5Ú<¶Ï…¶ ªÝ‚„ÛØøà6°ãï;ÄÈ4ÖŒLÒ@ʼn“û9Ñ":NC÷Ø>³Ÿ÷Ÿ²'IØg""%â‚ÇîM›Õ_4Š¨Ð³¨ÐáÿDñ!O't‘wv‹¸°‰8) 4ñ‚" Ë"eM„UØJíß*ˆ}·UÿÌd/W¡<öÜå¿Aá…ç mÙû;v¼ðñ_—O@þÙ_C¾|â7?þÏw¸ÿ½w±ç¼|Y½u 6*ÅfÖÚC¿\ãYp5h¾ +ÙxÞÍè@ _§z¨wg’À"û>5³„ñI-“ïDµ«ºÞÇ +Äp&ÿÁק’OvÕ›ÒØîh$‰äfbª7OüǯbáÍ Å±k×^1"‰ý+—Ô_ú‚]W\÷Úååñ§ßÿž3žäRàÛ¶=ºý‡Géó·¯>gÓ‘£å‰'ËZ5¡éy¢]¼õÈ«wm}õöF"Ú=Šh)¸ð +)Âub-Ľõb¢„(ŸFYÕkÿ•0TÕ)™æÚõ[âI&þäòâÒ»íØSåqH?óÞmG·m;ŠÔá혂_þ¶JQø'!}b¢¼`ë‘#[·¾ú*Ž•`)ý/h··+âu˜4,b×Wß~ }À¦óªnœÀËëÍc?HíFÆŽ¢*FY¢÷XTß©¯¯‹„F‹h2"šhtfh¢…c#uyвE Cd‹a“ÌÃZu't”ÎÝD9b
„UÞ‰°6,%Çï8%UºŠAÇQ1¬Õ@ÖØ:þ§Ž¯‚ˆr|…r£6Ñâ¼U
ª²ê&£t_倥¨ÍZp£dc-¶pVjûѳpQÝ/ÃVü¿Ø(}þÑ{–]è¶I:[ؽò±r–GàÔSýæÈÄ»t²™ð¿•[Ä¢·‡‚Uàâ™»ä]m?mÅvxÆÚÞp¼ÑýÎŒÿ²Ï~4㟶“Ù/fF›Ö¡é6ÌØì{·gÆm¡{³‡¬Æ¶³Û/n_Ÿ¿¦ý†üwÛ¿›ÿ™¸WdïȨ³ô‰x8Ú¬t²n—Õ¢³›:@¶%fšZÍš—ò]]A>ØË–`n?-ã$(øÅm
A^·¬#¸È¡´ß=»yi8·,%H*«†ã0.ÍêÕÑÚ(4ž[Yr$Ū~q˜Àh°²Ó˜`wTTGÇ$\‡÷êÀÑ.¤°´·ÍdoÎÙm€¼§# + +_7÷’G.‰·ÿ—ˆ}íMtñš™ý©”œ]W¸t3¶:¿´<F³ƒÃJäK4{Üj';Ê>Çþ‘=Îj®´Üd¹×ò°åEãFSuxaàFÅ®g>9Ñ`ç/ˆÉ/Á‡ÞŸDtyÖ”Œâ-L þB“I½AŽ_^Î+{7xŸõjðÁ¾Flè!&:NÂ,'I8ŠÀ,ÆÇÔ@)I‚›*„q|ÅíaF·! + WÂê +çÅé!ªhnj¼ÅaGêþËD¸¶_1²ìÅ6Ñ̹Ìòç#wï&ЊabÐçãÅ=þïóÎÏÈf‰·šƒ}·^A¥ðÉ/p'<«Ñ<®¢Ï1´›XfÔAÕ; [o5ؔқL}ȪRžþJ 5ÄÇ #³åH$(‡bÐaå`ÄX§+ðûzCž³jÅ m”e +BYàEdeŠa +Þe·?ÀÙhŒzYd ?5ÀÇ ô€Ãv’ª@_ßú|)‚{ É’ë^‚{™˜¯´Tq/r
÷"O½ȓp/r÷ò,|™ë›¿½‡]™ð=%Ì€¥ÒK6–ºó²-oÖæMAY6›MÚat=/A†‚»%%“”úDVRêb¨ðùQ!¹Qaå³R^ª‡õ‡à#ðr›ât,£”æŽ,…ûQ¸¥p|–*ÁG³F²Cûó"s·˜×`WY:‡«}íYr˜PÑcHî@j4žÔèf¸V‡3«Qì¹Íš;5ÆÇPš§á1Ÿ´¦>¬Éþ1ŒÄôoœ +ÍÍMU +ëO‘|Cs>‘h° +H\a¸¯aÁiñÖ uiùÉï6Û3WÀÅ#”'6òmŸ^¢ˆéÐþ-˜í²/¢~¥²bÀSž)¼@ÿ
qœ|¬°ìŠ†zK==ñ0O|XÀ`»G—¢u:†±Â73m)«ÍÆYC¤J6[D³Ùb6Qè0S&h±ÊÀ‰ôgÙhbá “·²Evû%Çà° š$ד\}•¼êã5ØM%Û{ÐvɶC©Áy +‹{´¥‘íj¨þÓ^´§U·1××âu°& +V¤.˜ƒUüMŽ~cü6ªäuŒjãøgª¹`¼kžÒ—PÏmÄ— +#r¶¢¹2ƒàÄOÅl0":½d© ‘ +}ãØ€HDWÀPäݨ°hr1»ÿq3ž|ÍÕh;Fœï)ÿ“î x]±5„à5¡ß…þ¢
Ao²®1ëB‚S± †/„Š +¢†`Q Á¬Ÿ£È:D3+´ª4K¬V0õŸJ³ +¡Ü5Ò!I€HöõÈÀCÌ„˜ºB-µ:d¨Ãt«’¦™"¥n#ŒVéUAÆT©‰‰Y!X
ŠAˆImËðˆ|²Á,IÙ9½ÓéÉθj‰$™Ø*ù’Ýp]û|†6˜Á•™yAy!ŸM$ä+oCä³ &A´¼¨Ø÷ˆCpc£Þuàje~>jˆûéU¾õÜ6î@„ÑKÕûœ†vø<&½–
˜‚Ÿo5«YV^®ÖfZí¦¡•¦)ÚsHÑ54¥úÆOž?ŽQLhDKeÆi8IeŠ7˜plåãI »ãP“þ/ε{^ã9Ë:ò.Ÿ;ÜåC‰Ó=c]s| xa³k΀O¤îwqáŸfZCœ8'È:y.¸¸ëô3M`ì`žÕü‰Š‚út¸câahiE¤©T´özR=çõ÷lîÑö¸KŒÎM ƒªû u²2’ÿŠ*ƒ#¹\õNÚÞÚÞ™ø=øöÒT›*V³yƲ@îÈÁ»|w—ÊÏ(ìÜMôïl9@݆o×}î๹ºçàH‚Üusy³ù%ºkÝUþ¬À¡˜ ìh³ÌAØ¥—*ïz¯DïÒPïzò·}G±@® ¨Bäâ¹ 4ô +v¤¾Wu†½hDHA²,ŸÎ+ù<“÷=H»'ÌÕFúk#ß + ?I=›ˆQ14æòæ‘Óf}ú¸^ô¯b¢ö ¡ê¼©ÿŠ1þÚL)—b NB¦Éjý mÔþw0ˆ‹Ð3h*ã܆˜ˆ¦"Ó¸è Z)NÂE¯«_óØp¢¯€Rùýøë½ðÜÔú××ú÷îÿØu.Ü[>Co÷» +@‹$¦DEÑeX-I.Nœp5¯ã$¹ªÅ‘T
¤Æ«ù}g@•W‘î•„ëŠz +cŽÍ’òçjÊ5 žë±ñM[ÿùsR¯$à9¸€DàGÕøÏ¢N_§ù#Î<#§ØY.ˆÂ‡jªGQmEäƒÒ¨=IIm î5%äú¿à"UÉîÇ°äq¬‡5,{* +Ý&ª?‹†g=´qÓƒ]¾ñ¡ËÖÌžµfͬÙk˜g.ðÁË/èÁM³×¬™~Žl«4í üN‘šô‘Ëabµ¼>™
ÕɗȺÞ\W¢¾Ü'ëóL NŒ.rC÷2óAø1á/öfór ~±/Ír| îWõÛô:b ØÅà¶%åL&‹ŽFÛ¤üjB[ÅN«T8m|üäøøàØwœ¤Zò®ZS¯z¯Vü¹NO #êéô…A ‡ +o»;;¿Uãä#»%‘Ûo¬aÕìÅSaÓ3€uUË*J45*IºålÃbC(ï õW_v×¾½·ôÞÕbçGæŠÛq‡{ŸûæYŒö˜ >gæð¼[Úp;Ü…»¿}ããMqÞ)øäùú#øúáí»w|ó,4××aM‡Ùf¿)Ë›N6PLC¤a0½²™ih^2kí¬RøØ»Íov|ìü8ü0›èŠÌÊÎêňq{C¦¡·aazqÃòÌ
—¤4°»æÞŽ¦·®Ç£xi$J´F1¶$ë;CEñBo º÷[t¯±DÓX³…I²M}ìAø
´œ$%P×›”¾“KÖ½Æw=Áw[©Àfœ 3»ž¶°7ÝèžĊyNâ¸<@‹eàØÒŽ«™‰ètd\¡µxd'²Ôñ„·Nu‹ «ú¢¹SŒ¬"Ôpp»êwÀ%ÜDé¢9†rò‚´~Öø¿ÛåLDr¦?ái~¾c÷Uïts‚¸è’רÔïñÙƒl~i[Îå”Ä%Ã.wQÑÖ_/îmÆ$üÕÂköÜTo‘¤‹nXNè~ŽÏu燞Åy‚wNÜÀt¡¦,+톹±¹
ËÚl…t¾eAZg\Rç篵ÝjÓè s^Ÿ†Q9|O,––¹ôÒ¥óÛÒÝéôœ9ó»K°K1Ìëútp¥çãcO}}øõXÚ("Ž,JÛ÷¢Ýît"šN”àì½²(Á¿Œ®ÐëÒP2[q(O›Úº;Ò¦½½ik6¥²ÒŠ]¥*¬ +GæøX¥ÆÉFcªäCÛ]µÆ²_ªK!X™ýŠU®S]=U„=¨fÄ*V_›ê"¢µáSÃ*ÄÅ}¢ôœÙ—ìßX×úÆÈÎÖÖË/å¯(¯çÑi¸ò‚ó£™'¾µ»3¿ac¨pÅìŸYÄÁ?¾þG¬ý‚Hó¿uÙ +æ/oÙm6ûýf6'{®QÎí.ööœsù‘9ïà?¾ª=V.^paooW÷6“î¹tay==#ÞØÚ¶zÞÙíZHuÕE»—Ïë.`»|þ+}.½ íÆ- +€PO§Òµ½£#¤4&êSb:Zç1hZÜ’Ç_ç4ÄÒ¹¦`,¦ä‚pb„ºÛߣ°þ otƒ¢.Øò`0hµ@‹{žˆqbl{‡4wΖª'©ð¡êPGOM§àŽ¤ô„€ê6Š¶ÔŽÓa!H F3mÙÊQÚVº= +E¢"1DÖÕ<jµÄ¡ +/cB¨êI/ªxtZ+úÄônHýâ†Í{®ÌÍí{øÒsnp ‚jê"+.ìY¹ª}aÀÄIö®3[VŸ{…Lü¿¸XJߺþ'¿ºáúűƮ=úÂw×;$—Ô«ÿÕº%·.ˆK³—²}©[†gýóÊjþ6› +‡¥¡PHš?^ÁFjôÌy%(*ûÙt_´«Ëµ¸ßÞÛÙ£”¨C{Mgƒ•|B»\êw¹$tac: “%8¬°ÂÙZim˜u©º“"dûÆTYŠÿÆÇNž$¨~Q±PpHOâÆUá¸V’ß “ÓMÀšš È –ƒB-^gm‚f#*l{Ò‡Q‘¨pE‚ðÄ z<%·í"n×ÙÕäb-¡}%ÀךêbÖ9ˆ°®tC«h¢aæ¥ò}åñò}píx®Y~îØûåßÀâûÇ`÷øü•f£^o4¿¬VŠ¢ÖP^uÍ•™y‹ê*çW|Cùák†Ï›õ85·v+t[tr¿ç`÷3_h:I£1é´f
Õ¦5iÑÑÈœÌÙþЪïªG\HjI/ô~šeÆùúaËùÜøMÇ
–nDÜì0Á!Í%ºaã°y˜²
97À
šÍºÍÆÍæÍüÛ'GÏ¢çPmzDúÈÞæ–Ú†Tª·—¦ÁlÐïøö¨<;=›š]¢ìŠ¡ëÿÐ*S‚4z‡æ”lýShˆýdø“QÄ1ßÔ¦§(¦Þ·1‹Ì¥fºN±Çæ‹1ô689Ftæ±ã*h Ƈ1ÆLp3Áȧ1ÆLp3ÁáIL ¢Ñ¿‚þ5mZÍ/¬%Eºmr¬šzø5/?b1²fD"ƒ™¢Ó3–^ÐÙß…›V²F£éCËniõoûÖ¿|%…áç!Þjå¿c1êÌÖæHKqùú%—<p‰ÉÄz7-ÌÍûÆúg°ìe¨!æ0ó}àŠRæ/÷.ORüßòìg®.ÀPŸÔ4釒5k½&ùè_K²q…—¹Æû#ï’ôJßÊÆ“tƒ¯¡±œ—dš +^o‰Ú¢°MbccSÒïóáÃÞÆ$:Lºñçñ›yšçýÚçs‘H]V«ëDú\ ¡!§(M¦t¾S4PÐdlÔiuÍÆœ±DmVÜi:YGét©¦¦d2‘@³ëÀl¶àˬH5yóI_ ÑM7ÜáÞã¦ÜnhÃ'‚œ>n}ÖJ¥¬Eëf+mU–¬Õjb˜”¡h ˆ{µ +†é)W36[fÊ ŒÇÿŸû¤ôr¾4óáΆ†Ÿ64D.Ù±ã’iv2g•‚2ººçÎxüÕWãñ;ËOÂYå¥äÜ—_†íe+iïƺç!zœæ5Í€AÅhŽ¢7Ð[h
ýü;0+ühSØÄD_¢«ˆç¶ê:£¾sp¼dà>qâŠùWDI`9+©xìi(2
ôÌïÉÎÖ¢xè
ë»Ý lH›6˜(Ó¿
ZÉe +<ï§úDŠê£ø(Û'D¥~PÁû +îàIœâu’À9UTÑšúƈ[…è¨À]å§ábœ¬œL0)ö<xò…¯I›i™2î«ï28½«ŽÓ +8ŠˆÄMž† ¬åpòU;”¯dRל4a>¨ÆÓ¦°f]ðašZ[~gY+V2‰; Šß&¨ŠõØW¾þ!2Ç6þCp·†vêDŽïÆ=/]÷0¼µü»ª²Iÿ•ø÷^À—>*/ìÄn¼qÑQö=ç4j9Ú`“Ê%937SkÆ +HEÕ¥oáÞĘù„åºùN¡3ÚÒ¤K™c¼ìOE妢¹Å_D§¶ƒ{,¶7˜ãz–5ò¡x¼^ ¡¹™|^7l¼á=¡fÆg¢¡(œ:–nýA4„ɽ¦ô(Á•Š]HÖÉ‘:«´6U|œOö¥}c×)l¬Îôÿ÷ø(Ê»ÿç™Ùsö˜cÏÙ+;{e“ÝÍÙ#Én’I!@B¢ aŠ +¢mˆ"õZE`ÑzàQ¥µ^ „À‚úÚ¾µÖ¾jU¬ŠÿTkmZ-Hµ’Íÿyf„`û¾yžgžyž™gžçù]ß/Ÿp«i²ë T!e¤æúŠÛGÚÆ@ Xˆ
KÉ.±4O…Bñ‹6Îò¥*§Â[·’‘2úÞV¤˜8"
þ€«F§÷ëk@¤&Ú +="ëÛ#³æl$>Ë
œ7§÷û*U§ÇZãQ˜Y½‰v¬n/23ŒåjUÄ]WÛŒÆ'€Æç!4>Xg<$:Þ"Þ’Q¡>Ð}À¾fxÍ¢2®¤'ÆÂäFPÎ \Ô£‚.È™’fœð%”³ø’e&÷Ñaµ6Œ ¥ïsá+Ÿ;@9@[ai',ëŸRH«jÀ±Äl°AlÀ±Äl°Áé^Œ*¾6?]NG'ÚÿÃîÇÇi7ž{îø ¿Ù°s×%vîÜpÖ¦kÎ< $Ë™Éd¿ 7Ù`X"žkLxHO"I&ä|EW¢w¶ØwyÃ%}Ûèí
[zé»g?9›%RŠ~çŠíúûœ÷5ܹì!Å.ýã
£ŠúgO'žíÛ·ŒÝÖ²£…H¨œËóËdè«’„<Çw/p¸¤N8½ »©˜›'tuå”H*#:M7òõ+¹À-EÖ§Y¶ÝétÙåY“h2÷â¾ölÄqÀì‚l?&¯¯XÙ`Rµ¶•M7ž)øøw„ž +ÚOQìvÄ`SIsD3ÍNõB™Õ&av—dŒ·•KÑñcÉ‹wé#ù.‚‹üŸP,xüƒgÖ€%JÎðŸ^Ïò.åS’<Ó(ÐIc¦@·Nþuï"žp-.L~R¡ONk¥4…É¿î›kœÃ÷¸z§Ú€a˜†‚äœ +ãIˆŠš()Õud)y0+kKª*]Q–}JeuI?š‘ýbâ/ô³–üˆ£9‹.¶¦?×zyo*sÖµl[”=óªïF–†×¶ +k6
Ã;öµÍ¾¶&“è˜óÝ_/2žÞÒÕÞ2`Z9³îÖS´¤¢â"¸}ôüùëi+ÇÐÉÚþn¼¿Ez[Îܱ0sZ°E§»ªûB§MÇ3Œ«sÅÂAbâÇÛó]˶÷Òt§1{Y›+x!šŸë&“MŽ m¤DÁ?ųëTîZ†Q«w-˪ +„[¤ýÐi>Ð|¨‘iøX}•iPZÂÇòÙ>Žþ³hl 38]O”dš’‘”CɸŸž•ÕÄPØës8µ:¯Îï!gÄ}Z†õÞij¢_9¥&KúaU=4–ÕCEY=Ä‘((^mæ8«ùŠ+ ÿò#?¸Ê̱¼ùòË‹Ÿ¼üܲöºG>ùNûÚëùxeç5ÞÀ˜¯¾~÷³Ð°j“Ùj`,W]·û¹âßH8ÿ÷Þ4ÔÔûÇ{o½i…/%Ÿ#¿t žS×8n‹ßîxÐ!c¬Œƒ‰ó̃æµæó;þËý–ûOî£nµÃbÜk!Íú8ɹƒCjW‰§ÖÃ_©”ýÜÁqa5™ÜæfÂ,ÑÜc6'm‚Ý}-JFð³} !»©”ÏÀ/@#ñ1ñI)°3Ž¼ª‘…˜Ç«XR'Ð÷˜8–onfñÂ-SXOÓdÅ»§PVBãÓjJM‰/ +µ¶ÕãdÖ%߈<|mç%‹ðzØÞ°`ÁÏ_¹Œx¤µ>‚t°H¶¸ñ,´o8aÖЃ5ÁYøìònñ7w/ß‚dÍgÅ+ˆÈï¡q«ý"õß<D–½Ùj²²Që•Ö6ÍNÓ «M¶ÐMÐbîˆ[©(€€äµÀ”Þ±‰1l—«€S±ßgÆ«JkÝP
s—×âÁÉ~H¶ØàõF‰ûñ£ãW81@\ï¶ÙÜWX´ž†ˆŸÂ¯tÉZ‰‹Zö +›“Ÿç̨ȗãÿÁÆf1•FÒYÁÐ,ÍÑZ¦h4f@³%i:Ñ +À"MXcœâm5)+d#¯GO˜Œ\c#qî”LêUÿдøô¶+ˆë$Ó•KxGl“Õuù-ß¿|©‹H]/H¦þg05¾ze..>kþZìmÆ +Á¯ñI¡ê¾úІO‹_¡µÁ¡oùy
²Ñ“ îÁlªcâäe¥m¥{eä܆sb+ãCɵoÇ(WÚž©O×gÒDZ‘M_OÜ–Úœ¾%s'±U¿=µ=}oæŽì¹äÇcõ;B;";b»R»ÒOfÎî%FèQÇžØÓ©çÒ£™ÑìhÎÿ—Ч‘ãc_‡¾‰|W*¬TˆŠÈãŠF:kVØB¶ˆ!nkò+¡pÄoÈ$™ë•7Äo'ïPܺ?²-¾q{ÓÏÒO„žˆìˆïh|´i„|J±W9j{&ôLd4>ÒøLæ™l¸NeöÕµæRj”:Â)_®¹•ú•!ÕŠL@hB³rÁxÞ +‡œÐÉ· Jƒfʦ«‚óÐÔú8¦O_%’SJñL›(¹–ÊÐ<†–HȉÛÜ5»?âŽzA܆’WØcŽDEÓƺö4Ãmocdü'?ÉÉ¿ì®7Wì1¤UÂ|\„Äp9É$S”u…’%&m;ÓŒrÅ +09¢S¯#Q.šePçY‚uŠ¯œ¯p|Ci¾JˆÉ݈cç’BYzÝé’}Z€@¨¦· +¥ ®Ã‘¼SâÅŸV"¿äïKÍ¢ÅP%PÉ‹?•BÂÑ(’ÊC\ö;$•—•ý9PâHÅf?5›˜ÍýTâH¥§£úË̆U8² ñ«rÓøU%6ÀlÏ$6@çt= +a(ÁR¥,Ý%¨0aD ¯P +ö ˜J™”\k&£žÀž´kƒÁà" +º_zíÎúúúZRñî†v]ª!æÔ×Oì#"(=¬‚ʽ¿¹Ÿ3g_{×¢m»þÙåZêr½=?Ê65}Úܸ|ËšƒWIu»‹'ž5Õ²gÓ¸ùSla_€¥k$Û¢Kômש ZÙ + +ÿ|¦:%9#"IV2[ Z"¿ü+…¦L%/±c¤$Sì“tÈ]øž&…)G¤t®ôûKrÂPñiâuhB»s@¤JÛòQ´/Ë +~·¼G¡„Šej'~¾ºCÓÄ;>¼àÃâ ™iìX¾Í*NS’o†A-qn-”dgRX̹ ˆåÜ¿/ÝèX ‡q<?Sâ~›¨»ãTQAÑWu;Ë “ŸÉ6Ë&Ø@hsÁbp\%Ö¬ygr'=8qÂã„ÅÉwð…ò|9ï.ç]å¼³œ[ʹoC‹P¡ aÿr˜§èU/ û¢½©Þ¦¾¶þyê5Ôšæ5ýkÉÚÚ¶/Yª^Ö´t`ÙBehQäÔmtk4—Ê5µ¶µÏS÷P=Í=ý=‹dÎ>TŽ‘¾ ÊEMHZB!Y˲̂=;³ #Ó‚Ks2ÖŒ—¸Œ†Î€qp¯)£â…ŒŽžÚ½$3‡ß¨p:<ýÏm™(:Ý3+“)öŸ»@Өр§À…’nǪ2úãXR¸”R8šT9* +C¿a×4¢÷·xnµX#ØC¤Ð}S’c 1ý¾©Ê=%-"8M‹‰Åž{>ì!A»g ‡ìAwýɨ¤ÌžºmY™ÉKï’xé<ÒEÜ°Ó'ñÊ[g°Òÿ +8` +“Ý%fëÉO¶õ¼RêÙT~2³ô(ÈgD§S„0yÒ$Õ>uÕ>¥™é@ßÄaÜ ñdl;Åg5óN]“ÿõŠˆÜÔ +Ý›Z ·DJ'1)½WÅŽ«áÖw$4y6°‚•b“×”0‰¦Ó*Ó°i“II«µ‹Æ£&TòÅzTœÕtËz¬ +µŠÐÍö3áùÓ6–œ~˜L‚äyû¿àù) ŽÌqÉáSÖü‰mp–³V—M&CÂyÞ—.;ËgŸø‡±0²â +Êˬ”ÚÚJˆ8ÒÅs:óûGÌz–wÈ]ÿSBw=ú(˳&z¾ ù)ùsÙ~¤&®¿
jèÍ„šRØ4N²ÆncôZJIÕaÇîÛÐ舉ýÖ°n÷&²¨,Òjš¬!£$I¾oäÝ'ãúÆó€>6Žñ2c§Ç”›ctCòsHAòJ–×3:ñ»-î`«ÝÀY´¸ÚnqúÙmVš¥#NS¨‰·2¶`–_9K‡±*»ÉÏI»|‘ä#>MÔ˜Ew0©Ç‰Ëo”³8)˜$3¦ñÕ(QƒŒ¶ +q«^¡p9f—Õ]ëÚnº'¹í Ó“ÉÛžIîiÙÓöb–ÑhtN²¤kh7-Ы©¦Æév Ôón×¹]“*tQ@±§öæ„ÏD'¤?$Ä€;õC¿¿Y%A³à6ÇÌ¢™4+£ñÞ‰ˆŠÛÒƒ:[GN0ðbýÖÊ/‰W:ñ1¶zÆ°Ÿ(?.ñJqVšõ%lNÈlioLéMm¤¿Å”ó‚v%tÚ³Æf/lå^Ò—¥ˆ@Hic'ãøÊÌI˜ìyÎ@ VVA2fµå
œb“ÍfâÆÄØ7Ýtcñë7^*~ U/®Ø‘òÕV]W<d4X]Kn vÍ©u8ì×ÂåÏ~gÇ#ïÿœìŽ5ÚË5FûÕÅ#¯‹Å£Ph?”ÍjÚî¼ÿ’uf†¶ÛëÕFµœgë7–?±æ¾·Þ¾cù¾sªFEcÕÃx«´‹Ú®Ýì)Lž»·éÚ'E*+þLy¼ìÏÄ}nA»šÔ‡+LÞ-õÉLßÍ°'ÝgìÈ€/Dñ ö±ø“©gØCñC)E\¥„²´Jå„>—òû.‹Ó–6›ÎZP +œ !ÓhNg\”¨†´ºFM¨Ä×¢^€Ñ—±ßM¸Êf¸\NU£Ë&BgkV™]?ßtü²*ϸD3–˜ÞÅáÜDN*äqIÿûÊÅh¿XJc õŒžÕsz™"îOi#0f@IR›ŽÀ„>©DŒpœ1«(â2;TZÚ&ádHqyH„ò¼ 'Å
?„Þ'ß›“˜?Ðrfñk(ˆ‹vœ»l´ñ]¨Í?<ÿ±k‹oÉnÇëø¾ßÝ4p¿Éf¼g:CgVžØ}ú¥m«îDZ•úŠg!ÙâGkxTQû‹ÐÏ#?ËêT3u:=fÚĽ¤×{L5~OÔåò@]Ôê™2*h(³I¯@€ Ä›äaY'ëÝ.Ú9ä$œ|bù¦4rì”—Ôr ×üF׋×å””¼0F¡¤VYç…qu´‡+9VB%€[-Ûø£Ù§»êç?qÉ•¿¿¸8ñìoyEÅ¡Ê(Ú\ä}oÜu÷›oÞý“7eŸL|4¸lý«'÷xñ°ÊŸÇ¸c[_}mËÖ×^ÅúŸü|ž|À€cò„¨^ö½¤A†û!â00ÇhP‰#Ž^ +Õ£¡†ŠSñ 3]ÉZ¤®}Më)Ž·@Eñk3ϱf¨„r‹A5ß@%ªQ+(=¡CÍ”å«J3‹Ú£É¬Ú¿)~Úó2Fu±†<SŽö!ðó=œš.÷‹í6F«¥™NµŠÀ|”Ë Ø©21ø4vG†86ʪú¥Ø¢‰\Ÿm' +<ŸÎ@oÞ+—#}ï7@8:s{°0ùçQÊň†kWùà¹ÞbÍ¿ÜrJg– ©î´Úô”z·µ&\ó?úW¯Ôþ (åÈÙ¡; ‘UD
£!4 zÚZƒÔÏ݆Œ +-áWÆJÂûØóÃØÿ=ÆL ¿ñ<o/£Ó†á·ÛfU ¬TåÊ`¶wßþý9·óJM;äÏX{á9¼Ñdîïœ6guZgdŒa}çê+¬ùŠ}y|þÕ)^¥Ö0l|0•$ £Õ0ö´3<§™f(µöÿ³o%àQYøï™É’I$!W‡„3“„#lè„3Ç@¸Ê‘Cr¢“pÉå"""º„p™UÅE@6p%° ¨‘Ad%rÉ" *+Þ¿;, è®û}ûõô÷wWWWWÕ{ﯫ{ª‚CóL¡ÐÓM`8¢úV{FÔuºÏtßéAÓƒ
ÁAAÁ¾>^ùë}†ô‰ó
Šò ` +ÉŠŽŽŠ0GFFÅE÷*M1f98Yö +‘\¼,1.dx”Q-Ì”š¦u3õo‘æyÐÍæ Éå|Ðht«Â%‡!@J”clOê>H™¬®|&W®Çž4ª“H¨ëÊòºËê—êúÉöêÌêÚNåµ·a)uµ ,¾»÷5þéT¯Øàb³;ø!ýZQsgwoQ_®êæý;_Ýll\N
|½£«×m¾¾ÖÅËÝÓC×ÏÅÛÍóÚk>vNŽvî }„f݃;ìÖ©‰ÞÞÑ–œž rš,ƒj¹÷–K„YxLr¥³‡Æ›âÍL̶w”Þ7J_ßà `:Ål®ÚH]BÃ<BCÃhpCD?ß ¤dŸ`{t0‡î2gÅ„›º›ú›ôŦé¦?˜ô&S|Jò°®‰æ„„øƈ»Þ;aL¶Fò¸sû‡¥‡éÂâS†„Us¥&áá:ÄÄtMN +5w3Uë–K~I!!®½zézÍNŒ¨ˆ«HìÖµ¢C¤6VËÒ:Çã&Ý"ôCŠ0Dù"r=DÖÆÎ+³sG*ëÇÎ×/ìU¶€ÂGÞÉë×ø*E…s„wþ´1¶qÞ ë:2—0/•I¼àu¯ÀÏqÜýM)t¶·
+jvÛÚÞH7åÿ·;1lêµ1žÎî^úrOg7ïòºõ‚ç?ïfŽnMýü”âÕÊn€í¥ûáÕõ–1ÂËu£Üœì\ì&»9±°“³qPP·¨O›ÕÙ9(B¤v‰I:)QJ–ò¥‚ÔÄÔ¤ÔüÔ‚Œ¤ŒüŒ§.11¢ï!Iñù +w:%%{$%%K1ñ] +áï#åæu‰w÷7$í*ÈJKLÌÉÏ’<4'+=}”–—W+—jáÄ:÷,Ûv<J®²:ÚvDz²<Ê1H²J“ò2-mh^nRA·D…&¾¹}ûºfdé²fç¨^‘ÓmhEQËÀˆf#õÕº‘ë}ÊM9y.Ù ÌS_ù”©ðê¿‘÷¢I¸QÚÌ0¼‰&·äF¤¹•'ê_f¿4¬ÛüšL½ï'îÔµ1J\ +Ð/PÏÞ<$ÏÅxd<rߌäS6±†36eh?ÉÁÎß:û«Z8\5å^ÀÞ¼:F +_RK\í¼š:ðIT’YR’aQWY•*ì\,é%F•¨ï%}…aEKÔ;aý½ôg; +ôaÿ³€d̶֑̯ð©¸Äëi"0Œò<ôðpA9‡÷F°žÌ±Å:2x-óMàæfß²W +#ÜàŽ¦lµšÃ^ðFøÀ~ðG +¹_Ž™xÊ‹E8YxÏâ%¬Â«¼2‡ú}åøßá9žÏÅ7XŠÕ¸„‹¸ŒW°bþ‚,<‚yÈÆv|„]ø;ñ ¾Böb7ö ¹¸€2À>ìGþ¯ñ +BŒAÆbŠñ…%‡RŒÇœÁD<ŽI˜Œ©˜‚õxÓ1
Oà÷8‹sØ +ƒ„!S˜(L¦ óuÛtGŦ¢‡è%z‹-D_ÑOôE1Pl)¶;ˆ1bWqM`KY¦ÍÄ{h¤Œ¶]H»ß®‘Wî¡‘µ?£‘šÛ4ò‰U#ûoÒÈ‘{j䬪‘wÑÈÕ_§ùý/ž^+¡µ|þØçÃè§Aô±`ˆòEzxwù}1ˆžß‡g:ù¸þù;Hò1ù´|\¾$×ÉWä£ ï—#NþLÞG¿
F”|Rþ†~No—OÈçÈGƒ|V^*ï_b/Ê×å:ëà)/d?®ñ¾2¦7ÈWYÛ\%êÈ«å9òlùë~£ºúÆþŠºŸeÝo‘Wq?S~J>/_`Ù‘ÜfpKs¹yÔ¯_]Êí%n«js[Q›U»¬6»ö©Ú…µ3¹ü'èÿÝOÿ³%\è
å +nÜcÇÖ¨ÑH2]°^k&4±¦
L·´¦m™Ž¶¦í-¤(O7ƒƒR§ð¤5- ½pÞšÖÁEçiMëÑ^×Êš60Ýßš¶ez’5Íþè–ÓE²»þY$òY’Çø,ò SÌÞ3ÆNb¼UrzðÌ´²Ïd~¾Z"ŒW⛋xȼ\Þ_Ê謜eó˜ÍÒã¹Í’J
ãxž¯æŠô¬lÆo‘çJùL¢T{4óÇðhaÜyOÎ/é×*±S‡ŽÄÁyÙ¢¹xlqé¤G³ÅÅ–G‹-™¥ùÅcÃÄø¢"q`~n^i‰80»$Û2>{tXÞ=âSRBz³äg[úeOHdü +endstream +endobj +xref +0 18 +0000000000 65535 f
+0000000015 00000 n
+0000000479 00000 n
+0000009881 00000 n
+0000009927 00000 n
+0000010126 00000 n
+0000010164 00000 n
+0000000251 00000 n
+0000010257 00000 n
+0000010277 00000 n
+0000012952 00000 n
+0000012980 00000 n
+0000013194 00000 n
+0000013367 00000 n
+0000016044 00000 n
+0000016137 00000 n
+0000017189 00000 n
+0000017469 00000 n
+trailer +<< +/Size 18 +/Root 1 0 R +/Info 7 0 R +/ID [<1BB3350AE06F3BC804CB17F01927313C> <7D83F4207D693A4F93CFC07CDACF7461>] +>> +startxref +67634 +%%EOF +1 0 obj +<< +/Metadata 2 0 R +/Outlines 3 0 R +/OutputIntents [4 0 R] +/PageLabels 5 0 R +/Pages 6 0 R +/Type /Catalog +/Extensions << +/ESIC << +/BaseVersion /1.7 +/ExtensionLevel 2 +>> +/LTUd << +/BaseVersion /1.7 +/ExtensionLevel 1 +>> +>> +/AcroForm << +/Fields [18 0 R] +/SigFlags 3 +>> +>> +endobj +18 0 obj +<< +/FT /Sig +/F 132 +/T (padesSignature_0) +/Type /Annot +/Subtype /Widget +/V 19 0 R +/P 11 0 R +/Rect [0 0 0 0] +/AP << +/N 20 0 R +>> +>> +endobj +19 0 obj +<< +/Type /Sig +/Filter /Adobe.PPKLite +/SubFilter /ETSI.CAdES.detached +/Name <FEFF004D0069006B011700200050016B006B0075006F00740075006B00610073> +/Reason (signature) +/M (D:20141112123930+02'00') +/Contents <3082064706092A864886F70D010702A082063830820634020101310B300906052B0E03021A0500300B06092A864886F70D010701A082040B30820407308202EFA00302010202044B84F591300D06092A864886F70D0101050500306A310B300906035504061302454531223020060355040A1319415320536572746966697473656572696D69736B65736B75733121301F060355040B1318536572746966697473656572696D69737465656E75736564311430120603550403130B4549442D534B2032303037301E170D3130303232343039343635375A170D3135303232383039343635375A308196310B3009060355040613024C543110300E060355040A13074F4D4E4954454C31193017060355040B13106D6F62696C65207369676E617475726531223020060355040313195045544B55532C5045545241532C3337353033323530383839310F300D060355040413065045544B5553310F300D060355042A1306504554524153311430120603550405130B333735303332353038383930819F300D06092A864886F70D010101050003818D0030818902818100B6428770253983815FAC33A4628967D4B14C9846565294ABE790EDBF328EBFD990B9D17C3C713B991447A42274C8D77CF665FC1C68E46D560843C5914A5A209BD62793316F4608479CED12A14AA595DC4B3B2C6EC9ADDBED7410DF02EB280F9B9B63ECB1B00728D3CD5FA622D68C89CE1A20066F7937B32EDBFA24BDC68306210203010001A382010A30820106300E0603551D0F0101FF04040302064030360603551D1F042F302D302BA029A0278625687474703A2F2F7777772E736B2E65652F63726C732F6569642F656964323030372E63726C30540603551D20044D304B3049060A2B06010401CE1F0B0102303B301206082B0601050507020230061A046E6F6E65302506082B060105050702011619687474703A2F2F7777772E736B2E65652F6370732F6D69642F301806082B06010505070103040C300A3008060604008E460101301F0603551D230418301680141C07F49CBFA4256CB3B49E221F1F94481B587A8D301D0603551D0E0416041400B75CB9AA2A84AC54360E22CA7B52840969AB52300C0603551D130101FF04023000300D06092A864886F70D01010505000382010100A9D18876ED607C5678B19DD2622764C0ADAE37F4625DED79F1B91BC53F9D4C5F65A865D9143978AD1B174FC83C2E3A98F9CE02F5313450A5FAE6499DA958DE3C4BFE8CCEB71CFB50C104B456CA11F015622150CCC43D505F53BEBF652BC0EE50278EE54464FDD4DA94E1CE24753B8112A8E595E46B89CBBC1AB522177DC20B41FD7D8E2C2A552B037DDE1CE5D39480D6E0E48C5E68A0CECF0771DE529D1A11A31FBF8A16964F4CB5B577B0837962D172818C58BC806C92FF48EE52A3D3D14CABACC701B91966C39575F31E6A2A026AEF758C2B84E7B342F7172A8B5CBD8E9F34393763AF6A1520909884964EAD0CB9D2F033413E9140C17540DC093E2316A49631820204308202000201013072306A310B300906035504061302454531223020060355040A1319415320536572746966697473656572696D69736B65736B75733121301F060355040B1318536572746966697473656572696D69737465656E75736564311430120603550403130B4549442D534B203230303702044B84F591300906052B0E03021A0500A081E9301806092A864886F70D010903310B06092A864886F70D010701302306092A864886F70D010904311604141450A8C997893287B4B501179D178C0542AB0D733081A7060B2A864886F70D010910020C31819730819430819130818E0414B3B71275738D180A9A54A5E01C5EFCF39CFB07E43076306EA46C306A310B300906035504061302454531223020060355040A1319415320536572746966697473656572696D69736B65736B75733121301F060355040B1318536572746966697473656572696D69737465656E75736564311430120603550403130B4549442D534B203230303702044B84F591300D06092A864886F70D01010105000481806C4B61E3026064645B4F29B64050535F3B7028660F2F1C302323BD957A0BE25B60CBBE23CC6C01ADB8437495E879EE088A30803823BE9B005AD8DEE492C3C70FB1A817CD2CDB3BD1A071BACA9271E1994EBD8A6B4D91B2F8F3A6FC1E55318B51E92588B6B90EA8ECF39AB2B99242AB4E81A494113AFC4360925842979F5416B7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000> +/ByteRange [0 68786 74932 712] +>> +endobj +11 0 obj +<< +/Contents 12 0 R +/Parent 6 0 R +/Resources << +/ColorSpace << +/CS0 [/ICCBased 13 0 R] +>> +/ExtGState << +/GS0 14 0 R +>> +/Font << +/TT0 15 0 R +>> +/ProcSet [/PDF /Text] +/XObject << +>> +>> +/Type /Page +/Annots [18 0 R] +>> +endobj +20 0 obj +<< +/Subtype /Form +/BBox [0 0 0 0] +/Length 21 0 R +>> +stream
+
+endstream +endobj +21 0 obj +0 +endobj +xref +0 2 +0000000000 65535 f
+0000068149 00000 n
+11 1 +0000074991 00000 n
+18 4 +0000068430 00000 n
+0000068576 00000 n
+0000075222 00000 n
+0000075310 00000 n
+trailer +<< +/Size 22 +/Root 1 0 R +/Info 7 0 R +/ID [<BF432A7C56D5820F25CFC942E39B1593> <BF432A7C56D5820F25CFC942E39B1593>] +/Prev 67634 +>> +startxref +75328 +%%EOF +1 0 obj +<< +/Metadata 2 0 R +/Outlines 3 0 R +/OutputIntents [4 0 R] +/PageLabels 5 0 R +/Pages 6 0 R +/Type /Catalog +/Extensions << +/ESIC << +/BaseVersion /1.7 +/ExtensionLevel 2 +>> +/LTUd << +/BaseVersion /1.7 +/ExtensionLevel 1 +>> +/ADBE << +/BaseVersion /1.7 +/ExtensionLevel 5 +>> +>> +/AcroForm << +/Fields [18 0 R 22 0 R] +/SigFlags 3 +>> +/DSS 23 0 R +/Version /1.7 +>> +endobj +22 0 obj +<< +/FT /Sig +/F 132 +/T (padesDocumentTimeStamp_1) +/Type /Annot +/Subtype /Widget +/V 24 0 R +/P 11 0 R +/Rect [0 0 0 0] +/AP << +/N 25 0 R +>> +>> +endobj +23 0 obj +<< +/Type /DSS +/CRLs [26 0 R 27 0 R] +/Certs [28 0 R 29 0 R] +>> +endobj +24 0 obj +<< +/Type /DocTimeStamp +/Filter /Adobe.PPKLite +/SubFilter /ETSI.RFC3161 +/Contents <308006092A864886F70D010702A08030820DCD020103310F300D060960864801650304020105003081DE060B2A864886F70D0109100104A081CE0481CB3081C8020101060B2B0601040182AC180103013031300D0609608648016503040201050004201E400186AF27B68CCA8964104067934E92ABB645FE995FA01CE8E984B21D4AE4020310A336181332303134313131323133303034322E3433315A3004800200C802087CCC4BF048230D24A059A4573055310B3009060355040613024C543110300E0603550407130756696C6E69757331163014060355040A130D42616C547374616D7020554142311C301A0603550403131342616C547374616D7020515453412054535532A0820A7C308204B73082039FA003020102020A160E4D35000000000387300D06092A864886F70D0101050500307F310B3009060355040613024C54312B3029060355040A1322536B6169746D656E696E696F20736572746966696B6176696D6F2063656E747261733120301E060355040B131743657274696669636174696F6E20417574686F726974793121301F06035504031318535343205175616C696669656420436C6173732033204341301E170D3132303531353131333435345A170D3232303531353131333435345A3055310B3009060355040613024C543110300E0603550407130756696C6E69757331163014060355040A130D42616C547374616D7020554142311C301A0603550403131342616C547374616D702051545341205453553230820122300D06092A864886F70D01010105000382010F003082010A0282010100821C4FA052C55A990B6B62E5D59054B5EB08B7324C6B6C29048070A931DD58C90E33D92FDED48AD39C697C230A854ED7B7D9303F3A835E9220E4F4EE0D62D78D675B8E4A75E2B7EF513C9B47F21F38E7BCCD2428CC88E8116DC42330E2464B20518C68D850881EA2EB46EDE52B3896AF2128397F07EAF1A27B5F1AE9551557EF10AA6F2C56E5C265A4B443A470388D75BD9827EB4F6214AB522D015954F3F4325BAAFDCB0F7F39407A57AC1F0C2D46C4CBA568ED1A5B997B590D064CBE24FD6C55C1DB6D8B874E49425C61A7DA30996F183F4D8F2F0279D2B8875FF2E7F1E47B4E49DCD6DDC886AA7DCCCF04D480674D6520ED7190E879E1B64A046C559DAA0D0203010001A382015D30820159301D0603551D0E0416041451F4B16D4E550EDF93975C83236513707DF6AF3F301F0603551D2304183016801408C941FFE79B5633DAF0D7B361B4485C15A31B5A30370603551D1F0430302E302CA02AA0288626687474703A2F2F6E63726C2E7373632E6C742F636C617373336E71632F636163726C2E63726C306C06082B060105050701010460305E303606082B06010505073002862A687474703A2F2F7777772E7373632E6C742F6361636572742F7373635F636C617373336E71632E637274302406082B060105050730018618687474703A2F2F6F6373702D336E71632E7373632E6C742F30090603551D1304023000300E0603551D0F0101FF04040302064030160603551D250101FF040C300A06082B06010505070308303D0603551D20043630343032060B2B0601040181AF650102003023302106082B060105050702011615687474703A2F2F7777772E7373632E6C742F637073300D06092A864886F70D010105050003820101003ABB17DBAAED138816BD95DEAF9EA9555D0F6A93678DFBC092B389A621A34E7D87556A83908CA18E838AEE89B28B04918A08B15DFD2DA1FE3D4FDA9EFCAC3220F4B5A562591FA9E4ED594D45E3CA4EC28F5EAD80B7971A8B109491107B14B4588C8C4C2E05FFD66FD14F791F000B9DAAC92E1D8ABD6B0645C0D7B0798ADC15726ECF3BFC202056E375D1DE74C4271216D74586A7BDA7266C6AA6679CD29773D791B9FF10AE92464C8DFC525740FAFDA4E40D2D067AC93855EFBADC4615D495FB95A87C660659FEC75185C9EF599BAC277BB9D3AF5922D46B8980C84949FD8A04B377D953FD3478176E509C8BC012C003BA00D11F27E20755DC9CA7AE18211BDA308205BD308203A5A00302010202105891669CC008CA254070B327FF9C069E300D06092A864886F70D01010505003074310B3009060355040613024C54312B3029060355040A1322536B6169746D656E696E696F20736572746966696B6176696D6F2063656E747261733120301E060355040B131743657274696669636174696F6E20417574686F72697479311630140603550403130D53534320526F6F742043412041301E170D3132303330333131303031375A170D3236313032353132303530305A307F310B3009060355040613024C54312B3029060355040A1322536B6169746D656E696E696F20736572746966696B6176696D6F2063656E747261733120301E060355040B131743657274696669636174696F6E20417574686F726974793121301F06035504031318535343205175616C696669656420436C617373203320434130820122300D06092A864886F70D01010105000382010F003082010A02820101009DF52784E64FA593EDECD8AD94C3DDB503E58A6E709468A6185A54615E3153F487953057DB98B3735EF9E16E6E4E5E63E76005CBCAD78D82B9D184C4C8DB15AA7C8A5FC893C3C5B0B5B90CA2EC7286E520AB80478DAEF5381846FF6699F5D9404C2C514942DDA8C2B1BAA4555DB3765F38929257D8BDA92B2F788F6F062787B34A23878FF1B665F4D402EDFC93FB08947FCC8389BD289630B61CE0FF6A49E20CD6486B6A3865FCFC534E013DE7ECCDDDB656594AD6883CEE2273248CA46445EA61F9933F69792752AFFD72C189CF424D32D6766351E79A1A768CEC893C7B3D86F21DE481156E519C8B2C426D4D9C0C3791F02A93483D3CACC3E611C6B806E7D30203010001A382013E3082013A306406082B0601050507010104583056303306082B060105050730028627687474703A2F2F7777772E7373632E6C742F6361636572742F7373635F726F6F745F612E637274301F06082B060105050730018613687474703A2F2F6F637370322E7373632E6C74301F0603551D23041830168014CCBFDEA79077626A1D78692E0A389B77515303F0300C0603551D13040530030101FF303D0603551D20043630343032060B2B0601040181AF650102003023302106082B060105050702011615687474703A2F2F7777772E7373632E6C742F63707330350603551D1F042E302C302AA028A0268624687474703A2F2F7777772E7373632E6C742F63726C2F7373635F726F6F745F612E63726C300E0603551D0F0101FF040403020186301D0603551D0E0416041408C941FFE79B5633DAF0D7B361B4485C15A31B5A300D06092A864886F70D010105050003820201005C035DE76F88FF65493FE6221771C14922301FFBAD77F09D77C8155BABF3FC26CDEBEA2724D4F7A3A6630DA3903426CC201D23FF328FC40A7A4A7463CC72B2526EE97D4C361826526623680DC3B7940F545AF923C63DBD3194792986AD78527D609C7CDD03A5657DEA1D4F1E96CB5DD021D5C9782E29286AC56B5B10EC419B90EC5C429173264D8CF1433CB500753EDF3AB93668016F759DC2A2A1471F491E96FCC61482A8ADCAFD11AC895101627C9585362E2B98ADE4C1E015203AEA03C3777618CDD569E4A66CC415A489D9CFC4628BB24980C9F0318EB98776CACA9D9C0AE8BF9288B1A04F379DBCA2BE015C71706F16B5E90531CE335165DEF3B5369773727601E409AC35BD20573591C0C4484DFFAE39A28DA836433206511BBD4C35DA54182DAE632E57C47D13EF075AA10937EF3FDC5B4AF81FEB2001ACB344E71DF7C00AFC79322EDFBF08B888A2533CDF0C07E50D3F90187DA3F49F17032B1C552C8056073931D189B1D4904EE6373337734511A6F7E6A16965D208EB7E04BD945D10D4D5C1D8949760CF5911ECECDF7647F809BDE7C31C73607FF386D506B1D6C0A6E8258F4D69AAE37C93810BA095869095D52FDD3E52593E4A37EF067C42A51CAC7E781BA6000FC52570017433CF6B1008E1CB310F3A1EE078D2111107178FA337DC884CD15B90EB558A4FBBF6A68B6D2954C2F3905A380112D755D78AE6E829318202543082025002010130818D307F310B3009060355040613024C54312B3029060355040A1322536B6169746D656E696E696F20736572746966696B6176696D6F2063656E747261733120301E060355040B131743657274696669636174696F6E20417574686F726974793121301F06035504031318535343205175616C696669656420436C6173732033204341020A160E4D35000000000387300D06096086480165030402010500A08198301A06092A864886F70D010903310D060B2A864886F70D0109100104301C06092A864886F70D010905310F170D3134313131323133303034325A302B060B2A864886F70D010910020C311C301A30183016041420A352E2CE2E73070BB3CF9DDE8A4EFEF0F0A35B302F06092A864886F70D010904312204205898C2306F5547BEFD9098224368E435E535E8D79F7EC7E5DF858237742E85B2300D06092A864886F70D0101010500048201006CC546313E0309B6B1B26CE7BB222CAACB05AD8E1323F14442893FB4B716B480031EB7A8E3057C644B0EF465E4E3A6EF4DDF79C46EA3DBC1B5E54D385C753CC24C1333C7A52C3A6E3F38D2F669A4164BD62AF892CE3EB9D7E2DBF37A1AEBC2D09CDDD826303E364A22FD8919A4912EA67DCD75F29E640A907AF81CBA0A62BFF8B87B334B9516344CA8EAAB528393806E5562B0A6FE396A8E12A01219FD52D0F3D1B115046281E662C3457A24BDEEEBC0B656403F8271A698156AEC97306CADD39F819E445774F067DA5774BC82478EC4DF50CDD40095E7660778D8DFA97DDCD35A69B12CF7E37317F036C1C6F37ADCE938FD76BFAE02D80E04F2D3F8AB723F6200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000> +/ByteRange [0 76328 84522 316068] +>> +endobj +11 0 obj +<< +/Contents 12 0 R +/Parent 6 0 R +/Resources << +/ColorSpace << +/CS0 [/ICCBased 13 0 R] +>> +/ExtGState << +/GS0 14 0 R +>> +/Font << +/TT0 15 0 R +>> +/ProcSet [/PDF /Text] +/XObject << +>> +>> +/Type /Page +/Annots [18 0 R 22 0 R] +>> +endobj +25 0 obj +<< +/Subtype /Form +/BBox [0 0 0 0] +/Length 30 0 R +>> +stream
+
+endstream +endobj +26 0 obj +<< +/Filter [/FlateDecode] +/DL 1850683 +/Length 31 0 R +>> +stream
+xœŒtUÅÖÇ)!P\z¨ „So¡H @B±¡à³¡(*¢ öBUð¢ÈCTPD, ‚
D¥ØP°Š]±w‘þÍ>³Ïåç?ó¹üÖr½ßºs2eÏÞ{v±¦4í·¦4íÖ¬RÅŠVÍìjn)½eOÍŠ«T©`]lçXÕ²+Ÿš•W©¤Äneµ ÿ¨ž×¨×É-N9nüE\4þŠ‘#Ç]téEW\2òŠK®¼Âniå““×ðh`üÈ‘c®¼bäùv=«.!•órJú÷9þ䲎e%b5m϶mÇŠÛqÏþ§þS|`×:VëJY–ûR¬¦•ÿ›e%mßN
·jXÕÅï5«ŸU¹zÅ +ôÏC¿Š°-ÇI +Lü¼ +e1tÐ +cåA»Nlâ£TMQ x¤þÍnL-Øw“NC +eÁ¿u¾b!D‰ïÙ ý¤@x¸öÅrÓ‰%Ny)©ÛŸ¢@x8qðá)Ë·’NÜÅSà¯V <\üµ`2ãb«x¶çã¿£@xžRÿJÈv…Èõ|<\—Ê +„ÿº¿ò‘‡\ ø¯ëñ¯TºGBbûº~oßûg™@o“é Ñ*þïh©’ÅÐ× +äChðÅòÚÇS\M¾¡ëÈAÐÞz]ä‘ +Ä…xo½bhG°,¾ø'î¤ðáÜ[ïW‚2so³Ñ¡è±’®oÁyÚÛìZ¨åµ<Žò’NCÿU $„Z_Í[E\AnÒ…Ûwoë›
¦<\BL¥ôdòp…í
ÎíƒÉ æÁµà¹ÛÛ¹§áoJ=ÉjHBÇÁÃ¥6)žÌ.r$-®
„½]þ4€zËcîˆHÜ‹x«ôh +‡Û׿}Z`ø¾sô/e1ä@ÃçÖ”çºpYö
_n +ï–}×N“îæ$Vÿ÷]{·tãká4À}7¾k +äBhÁ+¬®‰Èsüá>T x·ì[’”à {K\dGkö<Ü’>Ð2ys&ÅÁLˆ€r|ß²Ï gþL;_\2ápÏV5€ÖlM«!Žícé»oÍw +„¥ïºÐL">¯²}ë¾T ¼UÖÿ
S1)±çð¼”e +1±,¾ à7íoVn +âM@Ê‚êÿvo+TF´¿þˆâ'Ä=þðö“.ð¢!lº‘ªÂ.“Eg+<ÁŽ‹/Å„Pµ5ÎáÇl +«µk/Ï„°|°n{6I¼À»†×®n\ðÚ商Ž3ÛñX=˜wŠ ÄÎ<’ˆb™5Ð/PÛÁ|¤vJˆh¼ÚS ¼:]+?9¶æì`§© +„‡ë¼€ØIäÊçî¼Dà-u°ó_|Q»VÊOà;ø UÁ +1Z`¡<@ùtxïBò©¬B³}|•‘›ÊƒGª¬BóBßTVá´ni!§@)0` +Ží{qx#èZˆuñÙI'q´Ó“§`À"hðM|Ì)˜ÇahŠtÝE¬<ÐÃc. Ñ +„FYÅéÍxY¼@(Â=^qzÂó´ð¾¨!z’ÐnÐÊLÚ-em“|`,Ûš²è=‚» Rq6/°g¥úŸTÝ +„ÿº ¶N¬‹Pà뤀<Bn¥¤ÁåA“ð^@ݯݤëc¡=!ÆÄ>i‚4Eºà(4áh. JSvgBP³/«tkK©øQä¥ÐìñŒßÚÖ +•óa `Y¥…•3!èŽÐéÉ$o¼9+-¼Hð²¬yŒ§€¶¯
S=®@øÃ7Õã«Ì“†j¨@H/«ôÅ^ ¹-°f¸/ª¼Vj=B +¡aAõ_@'*²Ë*¯O±è!3ɃŽuW ¸*o{š +‰@á†3^yÛÂÝû3YD'i@|Ì+¿»´£o:°ÔõÍ<í @x +v?{Ò¸'´Vð_÷û\†Èi’ÒLæïw)þëþ!'‹Í‚‡ûcd&„eAå?oDOµ‰5Êbh®t€ÂcìÀ\N9øÝ\@›
çü)ÊʂʇÇ(”Y2$_æ0T±¢Áá²²+ÄÂÀÒTTyÈb¨ŠTµq°,ra\l#dUmf +"q CH@(þ¥Þ³{Â
\ßx2{¯0€J¶²âç´ðpV)Ù®@ðÜU)}œ]p f[hµÔ¿Gè"å_ŠUú÷6€Õa!æÓÂý¬Bõ/ËIkÓ&®ÑØSå¤ 3«°Zë’ÓSs‚Ϭ¦@xíÎãx•àÑ8’žÅÃw¯tq?žÏ +ÛRÙ£7€.Än×69†NT (X³/Ÿ#Å!sç’hž4î9y•‘§ÃO`]%{ÜÐUÃD +熩+²ÿu׎8²é„ª×îÚ*4Ù7¸|¤H´&4{ü†„á]05|Þ¡D +ü4' ã [ÒÉgAà0téfßr›á)˜öB: Æó5¦[ö´
+„wÁô/åApŽXì>ÍžþãÓS½‰ë៓“ Á< ²ì»³±ìSjvXgß}²ô@ž‚ÀµŸ²¨@xû.á<j›‚85ædö’»
¥Ÿ‡âÐ&_,Þ*K¿V ¨g?ø*o:r0FBBh«´Bk$Ý P#zV,S ¨Óe¯üÕ;xxÄ[eåÂÛ÷I¹Ÿ„Ò'º«‘Oæ(>RO§‚bÙ‰@…Äáén™Öz²wý›Þ*BÑÆÆMö® +‡«új'^'x‡ËRõUÇ +QÅÕP üKç·¦€Œ\J‚2³úùwiiúRò³0T¦@xŒeǦp«Hà;/ËØ7ÊÌê×9éwÄe›ê×Å© ëCW%=`=³ú„ +„ÿº‰ÒO'ÓDâø¬úÄÞ +„g|Òñ|8æE"¬y +&9Ð-•ùÚˆ§ °¯~KU‚FõߧgŠ‚•áp3~΄ŽjahNW©†PŠ€°6Žš§l†NP 8„î•
”ñéëh«ß›0€–Íc÷)=«&5§eÙÝÐÓ\&x"Ðxª?½Û +V±Ä M8¨€Ú+^à^çH,Œ§;Á/lU ¼Ç7Ë”›Šz×Bh§ôÆV!T ¿ºUã°áµûþíô[dæbè]‚]ÎÔ¯Cvüä”3õ{‚Ãåü·‹h/pÇBù”óߘááfT•P„ò=£93ª+”*9sÚ°èIR€öEçÌi§@ø—æ=yÄÄu#QY=@ð¢ÎYp;ÎüÀ‘8gÁ¤Lû¢sJÕ(xÞq49(<Á9œÂÇ\¬›î!;çÓ
Mð¥( ¯'gÓã +„xËêôdŠ+;©r¶<«@xÆß‘YÉÀU™Âîøœw0€ÞŸ›6qã¾/ œ÷ïÊ„°¤ËÙQ'=¤jã×îœõŸ»²Ò%¶ eþâ]°ó*èçóyYâb_j®œŸG)Þ¾¿b9El˜æüZÉ +¶È‹ZÖ„§yo©Qðº49¬wH']<]cò• +÷SŸÊCG¬WKÐèçÿÈë5˜NGÖøùÂü÷2)¢]r2&ðÍYãïGÿÒž>,0hû¦4˲§Tð.Ø˃rG)Ü·7¦@ð›jVXŸNXGûŸ²Ú @ðpÖÌûŒ'Ó¥
Œoóšy_)Ü*5< …˜#ö’.˜¬fƒ¥ +„©™¼¨SŽG©‘8t f³µP‹V¡SÞùp¬QÍ +móšÎþ?dÛÁs +Î9l +„ï–Ëô£ äYó×]>Íú‹ž”PŒpá*Í7€®}–g®8RšG¾š×®3€®ŒU#7xSÃÛ÷ú'Ž
嶯›v-9ѸèŠ)œ§Ün»øJRá^ìúÎíö¥A5$·ûTŽ +/ht•Üî·(þ¦Ö²ˆN‘K{!sOxQà~Êí['“x,XsûVQ (¢sûfLJG!V±úŸÛ·šÔïG6$h#å¦BèW‚ò)·ÿ9¼}i2]¬±æö?_ð7
x†?œ‚]#·T5€†ÈêÅäc¦Œü×
¹É +½ ¤´æ¾Ë=³Y¤¹ïrÏä +kŠ|Ê=ó6‚o@¹#ñA™°Kð²ŒXb +„×nüÈpƒÚlø˜e +½X;îFÜx¸[ÞR üMÓ¹„C`àƱï0wz}è»lKcçþï'›nÞe¼À º~°I’;ï +ÂkwW®4Lƒ]lºåÞUWðdÞÕ?=œç{:h i¾‰+à +)d4,ó& ¿+‹î +jÉ =‹îU h·ä>ði,t}‹#ªÙ¾|©@ø˜/–*¤mõØw5‚uñhÕ©R`8d§`-®@ø—Vw’NUʽ$VFsW[ +„§à™baXš0J4ªÑ3½ Mý¥è$ƒÄ,7
Ì„°§=wKèi§dF[såo™o +„g|«¬H2®.%wë» +y‚¡é#åº5„†+\»Z“÷„J–mEsÝBh¿áá¦Ôfc9ˆ4Â×F)õÿu³i“DˆU,kÍêb +±ZwÜÊ[%)´‡HÃîŽ9ÐœëÂe×nd$ +7]{ö.ê¤âáî9d +”mŒU!× +U_u{|®@p?Õz85Œì‚ºBà<Õ–¾ÊÈQ…ﻺÃNÈ„4>Œ²m)¤$öaÔ=Kº¾SÁÛ†ƒ£àêžu¾4ª8€’”%ãkRëêŽ*U xZê^þs¨E/xPªÔ½ü7‚‚µî¸¶¡ÿI¬^ +gÊÔ×^ðŒOpÓw°ïGjzòpâ +„7ݤ°¥$µêÕ”&¨;iŸ4U*íÉ ÆN¤¶`m1€¦Mû})gïñéWš@CY äxÄR¡WŸ–;¿Ê˜LMDlÝ;¿S (XëÎÝŸÖ0RѬ<ÜÜà +„·ÊÂìñ#¿Jßuï« @ðn©ûÜ•|›{õ̺Ï]sl(ï†{Ù_ +Þàpy7Üo +åSÞÓ2ð=¨”fᦰš¨@x<ÃËêò¨û¥gú)þ¥çÎ7vÂr<ï¹sL 7…³æòž{Xð‘zi#o_ŠZÒø3ó^Úb +ä¼×GÈkƒâ-ÜéS@@o}˜Öì-·ÕÐ'Ð34ÖöEç}ðªá¿î3Ùˉ<ÔOoºÏžÎ„p`iÞW²ž½7TÐs +„wæ÷·†GŠ*æa;8ïû™ +„·ïO‡3¦ b,óüœ¥@x2½4ì,D?ÍmþëX“ùû/iï¼À¿ÿ¡@ð®Wk¾TC¬ ^)¾€êÕZh +/Ë„ð›býÊòU–¤ª(8¶¶~å‡nºú5‚¾nAð¿kiª^Ö¯±5Âr¼~wb¡gÔ‹fÓópµ>0€êüÊNírâø*«_çO¿TWöçLª?¼în‚R¥~Þïòp:^Ч::êçýe +Ÿçe :?ã×Éú…ë^Ôõ„Üt¤ÙºšÚ‚õî +T}›ûÛ2rOý³á=îŒL×ZŠ;Ö¢ë;—(>RÎ*y)RmA;‰
øúÎÓ +„)~^hNRŒ¶ÊêÇ/0€’ËÒF çkLÜúÉåPj“üp7ÈÇÅÏõS¯)Ô0êw™šnÉL,ĺLQ (ìë—Èp«x,èàÌ«ú%_(þëJdú¨#kkvfßJ +„©Ÿ”O¯BŒOp¿o¯]é#l&‘ŠQÿCh¥4H–¡r¸»*ë«@xƇwá+Ÿâu"½Uy¸á=Nfƒ–çò»²B(®AË‘ +ü]ì` +¨j¸¯«!Ô ‹o +„iêÁôd&H!4†n®¤@xY^Á==jêg6Xxµ´HN§èqßÁý^´Ú +2-q;bcÓOU <ÜYD»Tz¦±[ŠÃØ\îÏIùwnŒØÜ_
«ÒQº®¥ÑÇcžQ <OÏb÷DPN +„?ü©ê,)<(Rg”‡{*× +Ô¥US!öçÏÐ>)Åö¥[@±}ÃÎõBW,L$u…?üpÝcC
·ÜÎ[ŧ:Yøni¸e®Á]ÐðÕóÙXNUáÎløêE +wfÃ7¸µ]£faAÃ7@ÛF³!A™Æš¾$
·5€>|ŠUmÏv¢ <™>g +uºFMdh“„ÜiJ6jržáojšîvä…öá7½G fߨÙÛ±0À-áEÚÎópÍÞU ¼Z¦”'ÀFz@m*†Æ
…KâµFmª@mßaU›œÌš¬¹Fmß7€ÚÍJ›¸bãál‹FíîP ,ŠÚ¥M·À! +gãÆ\½Ø ªŒb¨qã© +EOã&'KõŸªUúaŸÅÐP‚wKãæ{ŽN[–Ö¸ù~¿ÔI–ÃódÓuìÆiÜ©o&„w¾R^e¶O*$¾w¾Và²4ö9°”ªïY÷Dc…AYиû«¡o%ýH÷vž‚îo@Å'ñ»A%<\ñ© +oÎÆåÛba@’ïkº6.Wð<
^ÀÇÜ·R~¤=øàE +eAãS®‡“2ùt]¡ŸrµtæFp£NN.öÏ|Uð/õ‹±yýHµYþð³¾Q (}Ÿ#¥oJáF"by¸sæ@ç¾–Vÿ='RÓ“‡;÷M‚zfãó*Èâoõq^–á]0ZV:0Yš$˜Æ£4€ÆÉb5¾K
h5u!»W jÔøÚ]¡I♂]º¯ýÒ +Op“Ùaøž'Ž”&P¹ÉìÐ}ÅÃižz›Ü×Oào²ú¾6è„ÆñmÞdõg +·J“ç_gÁJ}¸Rø¢nòüVhG™%í5º›lðOÁ{òI<H4v4™š¼w‡ô·L‹5Ñ5P“¿_W (¢›®²ƒêøzmºâi‚óÔtÕ]¼,T~$R¿ C÷(Ô›®ý+övСCÿ@/Ü—vw ¿å7}á‚êZÓ—Âb”k1ÝBè!hãÂðHQ¬ ~¦oºñhS)ĨNVôzå)Ø”¯@P4Ý&CâAz–…;5Ýv½´ýÂXøà/Ôc¬þ7Ý~‰ô~5žø×÷~®ô_AÝMѦuR <OßÊvê *aEžœB¨š ôqxåÓ‡cÝôÛ] +ï–¦ßßÄê?GG`h²A!ÖôׂXø”Büá¿vÈ„°/ºé3ðY¡Öjzƒ5ýc¶áoúók)0(Æ×TpkúçnÂÃí©-—…º¹šL™¦{ê)þ¥½²ÚGP
Û·píø¦{W 8™Í²¸Œ’ìHBͲÆ@U¦ÈÉ”7¾f¸*ÓL ]G /ÒS&„¾T 8OÍjNaÇÅ´hºm7«9Màd6«yoZ
I8‘ +„É›È +ô,ÿäݬ@ø—NjQÀ3õ‡Ã¡¼ÍOØo +ÎukÞï¨TÆŒÆ*V£I"n^:B ôm>ÐeÁJ€‘Ð&n`Rð~:å6LvŠÊæaèyhèyäS+ +äÄÐ(ètnsIîx[ÓjºùéO@Ãz§“ôÄ=͇•@glæíkË€9½®@xgž/
xa¾“ÃÁ®ÍÏ_¦@x?ú'í|¡¤O¼FíU ¼.^Æ“Ówñ#Ð¥%¡`¥çB¬ø5¿´¿t•˜¤ Ǥ§‰`l~Õ™ +„Oðõ\ÿ‰ŒeéÖüúû
‰²ê +ÿºüóeÞ«OMƒžüó/T Í/ÉÃI—bJ×:*ÿü·ÿÒ8™ g]Fvþ¸!Ðw°ª-6œ1¸Bè +¥Jþx©þ')<Æ‹4…
¡3
«oc\ÊòÜvXç_}§tÍűô¦ëc!ÿšK
dˆE*H4Ð<É¿aa&¤™ñ©òA ðM³øü©+ÏøÍy¬†ø~‹óoŽ@Ó”plçO[£@øÃg4æ¦.÷šž|ù3ò
Ùãù é`ÇYþì«Ÿ–;ÞcC‚‚]5©¿ùw|¤@xçU`MÁꚈŽüyU »ùù9(}q*ð¦»{·A]%±±H©BÇYþâ2è¡@ë Ô,atc“$ÿ¡§
‡«ÇÂGc×ÖI•‡k@+¸¾oe£é”¿âE§eeVd<+[gB¸Fþã2iÂñ“¶¦T}þãóÏÓ\‚=
·p\tþ×(ÔŸòŸØÁ +2éºýôħÐê½i§B\×Å'õAÂ;óiYÓ%M›Ì\8\/„ðd®yQG5ȃ‡[ó²A!ÿÅ i‡0–ð³jþ‹“
—ª°Ë$”èÃ;ó¥ãïÌ—.gåÁ +Qj ñ +¤îi¾)Ü*®QC^Zc +„/ê¥,¢ãÈǾ³<Òè*ßH9éx²‡†jQI–•D«®Ÿb‹J7gB¸"`‹Ò°ý<`á_*}Gà‘jÑß—®€ U3²ÀY¥2 HÈC+ƒä³@9ò…•¬+/5€V9Rñ£EûÊÌ«â +÷S‹gÞÍI;îFZD„Ð{г7IˆÊDÙ¥½Å³“
2Qž®DÇ”ºàÉÜðªA9ÞbÃÖÐ$¡¾“ØIÕbÃvèC†(XESk©Å†Ðk7ÊMçÄ)Í›$-^›¨@ð·xãyV×·¾æÃßXo +„·ÊÇR5JУ]ºQð/íXÇú›Ç±N×bÇKÐg'±°÷©œ¾[Z|vª t˜…XÒvu¥ [|^9Âr¼ÅפM7ê愇ûâzÂÃý%íJ8Iú µÔ⯠¿óÙI%D=µA„ÃýÝJ°8ü§Qh&Q9aœpÒâŸ|Â[eß»Gœ +Ô·ïCèÐ@VÓ<Ê´8tÒ±¡–•ä²¸A©‹H'˜š @𘷬´Ÿ/jr*h²œZV® @ø›*?Â0”½H(oP <\ÎøôöµýÈÚ…Ð5 +„ÿºZC䲉¨ö®µ¬uªáoª{Vzþð±Ø²noè¼´Áe9.ghY÷‚ÖF˺ÿÆÂÇJÞ×@ z=ÒÆ2õç„Ǽe½âÈÃI-ëOg…F¦Ñn¶!4Ë +m„–-sx2©xd¤ÙDå*-Í1~êµH!Å[Åz]ðiñ*ÆBçpÒÕ^héUU ¼,ÈGŠB]u²àï +„gü_ÙO‘‚5¨LTk[îxl¨UÖ‡¬®¹Ôù†i•µCà·ªSªÿv0ŸèÃ[Õ¬@𘷪ûC4œæQ¦UÝ¿ ÆÜ<—‚î¢ÕcBès¿ÔDF‘= +ÙªÉwPÓ×ø˜'í¤i¡Ì“ÙôM‚{¼Uó8 WM¯ÞVÍ»@ùMùÃÉù¢‰³o•Ÿ¯@PØ·j)snA&MͼV-ç+®m=>æ¥ãççVm@E„"šìiì8kUô á=Þ©+£Ô)]ÐݪSžäý–v-ù¾£™ï/Â3ÞåËPÕ&§<v™´êòÔµWú"¿>þð®%&,S8Mta³º¾ª@x«tO¥‹iùVd2C¨›ás×k*ØAwdlH´ê^¢@øÜu']V±"E¥ÃáÞW xm´ê)…}\–ºÀš}«ž»Þ-úJ‡PÐÑ×”phÕwˆáýÔ÷ût8Cð0ƒ¡Ÿ¯]é4v¾ÄéQûZ•Î0€Ô䫌Ҫ\T[ðÚ
(8"X=!Ñj@¨,;}¤<W£¶*ËQ ,UÊ€I¡>R¹8¬a´x“4$/Œ¦œÈó7$f +'³4'8þ9tšgpµV'N{Tð~:óy‘ÁåjJ‚´:ówh?<R‚«)4ÔjÄu +„é|iQ'©p´Iý` +„eÁÄ×C…†ÊáᘬVß6€¦4ãÉŒ/3XŸÒRðáœjKM ®øQ«©žtg‚
JGÖtŽmugWèõ×C'UПzÿ[½þÖ±¡Ög5;S gìžh}V‚² õUëX]KRÅ<üØúª—ž»ÖWÏÌ„°Ìl}õí +efëë7°ˆ¦Ô_M‘òÖ׿b +„§`ÒDV(ìChÓzÒTÂS0ã‚PÉ—¢¦sGë+”*çr `ÐÎʪQë¹ç@w•“)'A3w½` +—¥ÍÖÕépÇ×ô +&Ðç¡Ù-î1Mƒè6;¿:¹#C»_b%˱¾¦uT›ÝzÚ|/Ë(‘°òá‡È +„¯6o߉Íÿê@ª²O%Ž#î þð5Ïø°ÐµkÅ]MÉ¢66+®m¾Ìlà‚¸OÛü½P[Y½Øuƒnø¡mÛÞœmwÇîÓ¦Ã{¼íîL _ÓIŸv4õ7îOÂß´¿§Ü¾AkJ?d·ÝßçØPAE®¥KáVVdgf1t«Á.¨ÜNŠÃ <&R„‡«|¼ÁYP«Mú¢¦‡U(é +j*œÌ‚Z»®‡}=µ~6€êL:b,»U» ÎÍ +„§ ~ø˜\qWS¸ þ8‚Ò· év¾¤Ä1ˆcC¢ é~‚û© ,_4ë²5% +Ú|¤@xY:tM»O]_qVÐáÂóÔáð‘v4%DŠ² Žìž 0/Ò96„¦)þ¦Î5báãzÒÖt®¥@ø›ÓCAÍÈpÎMAb–A‹º ÛÑÉ 1þ¥nó Þ+bác(ùóð_×û Â]ÉVv¾ádØõ]P²Í +„÷Ó ^òp©¿I¬d*Q üKƒ¹úžXगÀ·yÁà¯3!ͦ²"}8}2(ápCžP <™C¥Á%Œ-j´†Ÿz†þl +pXšrÕè¿2á$pwyš¦Õÿœ a“¤`vgi’ÙK+˜í@s +Ò|v´âV)>ó¹%ÁXš~Ôó?S 8ã…¥Ÿ3DEì"§%„¾Î„p¨\aùűб/60>-…åcL ca¶ï9xí +Ë_΄ðÚæ†ãôH@ÿóÂÁÿ(|++<QæâRÑŒ¸£éÞ^xâY&#¢¶ó ÇÅ"ºðÄ-ÐÐê,ÄRA!;ü×
ÍU ü×
ë&) +?òÿØ +ƒ>G ¼v#9IO˜IqGcÀŽüÔ +Ço4€®^žV^¤X2øÕ)´¯íÆÛ—ÚPiÊç^ÛÓ +¯—ËB àŽ—Âµ¾¯ï«@ø˜ß°Ÿ§@ºãñA¸áaYpãèôãþÄÝ—+þënú¯¼€¬À©€õÌ›f@“ÿÅ!µAÁU, +'ÿc +„çéž„öŽ|ïÅÒ÷ž. +„?üÞ¿ÒÛ7åDò[xïÝ«@ø´,›xÚTy».~UðiY*Û\&‚Bך‚–…KhÙíRD“ +éiJ.›k +„g|Å»òz%³ÛÒt®øÐ +ß\ÍÛ7%Ô,÷Y.|óYè®,É[ #*|«Ç±¡vsO‘“Iÿèäx»¹§@ó¥Ã:AÑÓV¤hÍR xîÚÝ¿–?œÒ¼Ø*kwÿ‹™¶ÊÚ=ü;ÎljN‰…}»‡?U x·[‘ÍuJlgï´[QÍŠ¥‚åhú’´[ÑD ÆÚîñÚi÷DÊÓ¤´¶{¼ž´j+Èü“Ä!ôíVí2€ž’…Ó½àI\SS¡ÝSsÞRížÉccY/RÁ-„bкãÒerÝè&OÁº‚¢§ÝËÜÜÛñéK•v/_g +„eæG“åÈð£L».R ¼3wÈr.¤®Qy ,3wdBØ»ÖnÇ%dNO¬Ð´Ûq›á#µël©Ö®oM%©v»FdBøæl÷
7À ÄÑ´"k÷Í.è7~YL +½!í‡Û—^U=\6°Ýá +ŒöU=^îñVi_5a +„¿iÏn)0(ü'šB?@ž“›ŽìI?RŒ4„ÖêPñVרOOA‡ŠŸ@•ÿ惲’¾²•÷*Ô;T ;¢úvPÞ C
œkÃ`¥üH*TC7)4n:ä¼ÌPR\6vévÈÙ¤@xÆóÞgíɆÅúXð/Õ«K»ýH +"x½†PýÉiqHe¡TéPÿ¿Ôð-v3“«2bÀó‡7|Gð.hÄ¢‡#\M‚e‡F]L Ùü-IÙ¶¦¨O‡FK3!ìÕîÐ\V åÝHÒBýj +úTV ¼À}wH!&Û@b‹ºCßO
þ/³aêõŸðdößd +„Åaù¢#Á¤òd–?¨@Pê0h1»»Hyд÷è0èAÂ3>äI©†zìj#:yJðpC–[ÅN…†ð_7t…á¿nØ+±0.3<™Ã6+^»ákøpR@’&Õ ÃðuЙòV±©@Ãîpæ%йÿ Õ*í„ÖÎ=× +„ÿº²‹4 +~+Zq¯aù´2Áæ¤'fTS¤¼heèñ•¡âG
X±!Qôø“ +„ií#¡úOu°»«híã +„'sí1LF*¤æ‰ hí¯ÐËÜ7)¨ófcÝ·èålÂçnÛÞ* ¡GÞ9y«l{óØPÇù=|¸£éÌØq~‰tÏE,z(xZ“DÜñžK3!ìiï¸è9\ÐlOóÚÝqÑ3!Í/=ø,¦AIiülÑñÁç
‡Ž“†)õ³4–bLJj@dÄdù‘çše +?\ŸôÙqýÍÐkǧ'“¾Ê§Ž¯ÙÐÛ²Æ>5/ª~¶èøöT‚·TÇ6ð1§‡>MÅÒŽl4€>/Š…Ï; WóÔÛñóN +oóŽ?žv™PÓj¨<tüé?ÐïÜ96x,Œt¤¡û3!–ÖqO˜i‘s›Ý÷ÌT <‡d³Ó °ÔÒX@•+Þ™‡e³® Qˆ®šcÇÃ+Ž
__ÔT’IÓõ÷øú›Îã¿;%&Èâ”âƒã0Žÿîtè×Þé¦Ð5¸,ÇÿÚW TéT± Vz.Ô¸:UÌ7€²džbJW×Y¨S•,¿T5ìî$âôöNU +·o§Z+x«XúÊj=©@ðzí“Aœ)ê +K-Ÿ0tÀ +„÷øþ
ÍIñáI¬ wþÏ~è,‡'ÑãFº‰ðpg
2€FÈ`| +»šrSGÌV ,.ìÇÃQ¡U×÷í|a™ $ûR“¦¸—Â!Ï/’ áëµóø±¬´SñHMa˜Îã¯4¸/.E†ûqÍ1¿Ï +×Dï<çbÂçnÞê´À R²x¸yÏ@óI7x(Ò´³ê<¿©áyZò +„÷SP‘C,ÄÕOð’sŸà%_ðEMmu4EÖ’¯3!wh-e³› ÏÑlº¥OdBXÏ´¼0ôé;I¬þ[^¢@x¸•ï¹ÍC‘µr‡ás÷¸l,Jå„B£¬×Q Í/ +JqÇ퇬ÇG@O÷âMG…o4Q&ÖÓ}OæzI¥{SNÄ«Í[eÍdhmØÍš(à¹ö5Â;óù ³¡§¶‹ðߟ¯@xYÖÉíK¥ç|GFdÛ@ø—^x.:ö}í¿ð‚ácþB!ä>yüM/l6€Ö_('“ÊMÙ‘T(žÌõ+žñ
2‘Z{$\Mù2kChcÛ#¢ÇuŽvOðp;@›¹’‰Ca@ÕÈÚ<Kðlê†yC}4ûióß +„×î-7-0ÈœÀSðVBð¹{§½<œt½Š¥ÁBìN™æúP>¥ÈºÄš3Ö‡w(¾[>š“VÚIB£õÑ<èã7Óî‰%¹Ãá>Þf +OÔ»ZŸ<k +„‡ûæ>>$ 5yeÖ7(>Áß~$Õ5;x*Òûo?Q ¼évËÊÓ¹*í¸FWÙ}®áýôÏßá‡S¿L’õÏ^èÐœX躑‡ìºK vh×}ˆ…µ‘Ó<®ÛuW*œ'{k‚]&ÂPŽš“<ÜÖ® +„¿és®^L⮦«ýùè«Î,0<4à !× +qç‹-‡/8ÕÞ7€j-<råG»‰„Ð&Ð#¬B’6R#6„V@yòRŒ©ušB'ï|‚ÁiVQ¥bõš’jN›P‡|8“ték¶J‡×SçÁ,0‚âÔš=ÞùÈ
Âúƒ1—Øzuܳ ï«q›Â°ñ_çW4€º^Ë¢'(áŒd§ë
+„¿©øn^`™$!tŸÔïõ?®[ÔfÎ~o@d}_! éÑg8ê(ž‚¡“2gØ*s†NU ¨Ö:§‡ÅmIÞG>…P+èœñ¬ÖÒã•Núžstžt*PP°£sé:çÝk +IT:…2½ÐVq»o3€†H±¤)ËÅÃ
l +w¦÷ü8b¢ªy£öž¿:ÂoÔþÖÝì8£RC;8‹¡Ÿê™þ'ÇB—nà܇Ã}pšÁýäÿ1‘•¬xPÊsÿ© +§Àßó/pB¨£öþžŸÎxü¸)ÁÈæ¹
#~Ü4(÷V²‚ô,¼Uâ¹ÿË„°vo}/‹K妰g4ÞzŽTÔ6-Ä’^$™‘?¼¨ý±¡D½ïC%+˜xå'êý¢@Pf&:Jç0•uòüH’zÝ +„?¼_
¬>•Ã‰ò‰~µŠÃÄ`žqŠÁð#Ö<ÜàöÐI2Õ€\•v4R!„rÿu£–„ŽZoò‡Zf +„ÿºë~qx1™IX5J^÷·tC©Ð8&¥éE¼¡“4Qž;±,Â*ñðAHN¬¥@P>%§–¥Ûë²é“SN6€n¹‘•Q +EÑ-ð-“ i
ÓF 0•ñ NNkfýÉ›.i‰áðÍ™œ¶Ç +„÷ø'ÙÑA
3ãš+ÿ“BèS¹}ý@ˆYظI~:Û +„'sd˜ÉGq‘Œüá#_4€.žÎœ bÉØaÝõâ +„·ÊhYÏ>4Q°qP×Ñ'@7þ“Þ¾qa,k ½ +„ÿº a+
Ÿ*÷âp«®æ(–*·²çRˆaÊSpë–cCÝâ°ÁåÈ8N}¬@p?u;ýW)]~¤EÞíô? ‹öÊ+?H@<ÜE 1CùÚ ç¶¨»®@ø¯»Š;RˆHø)¼3»]5Kð7MRb&5¥Ý&ç™@ÏH狸ʨ ¥z>¾žnSJC#P‘f8!Tn +OË ]úÇBWe’RÀÑdžÐe Á»¥G›r=^`HÀoêÑf°Áoꑨ–>œI/’QÄÃ%r
ç·H–ã=R2!,Ç{tMÅ8TŽ +Tã²=ºv7€JÂZKN½…§ äIè<žLJ¯Œ6
+¡S2!Í_7N&RÄÉ=aÇqé¹ã^U ¼ÀãåõJ[¶§==ÆÇþu=OĆD3‡#ózžr’ÁK±ç¢Ì*Ï)œQÔsQ{héŸ|8“Ô$?Ðö\ºÇ +o©žoË©AÀ$Å*£ƒÐóím +OK¯;¥C(N‘®¦6s¯;@±mÕþp…^í1€V-b™•&Ͷת¥ +g¯§ï
r¡bf¯§—@/~Ì!hU‹µè^/~¢@píz½|ˆ‡Kˆá\lÀ÷z¥’ô¦|ä£0"OdÞëÍ;
íµØ„7áK±×özЮ1áA vêXöÚu…áyÚõ!„¸€RøHõÚõ‰A!Öë³l,{A6Ôzz}öŽÁû®wiv'e³x¼À½«œ¦@p?õ®VQ^¯$Ÿ£ »<\µ*ÍîÞÕF²°§Çõ8ѽ«2€jŽJ›Ý–®¼bïš—@¹kXi÷„Úça¨wî +„ç©öxVC‚`WìÒí]û“YG¾ºÅéUÙ¤´†Ð +7]ŸòϤÙMO´~$¾ „¾2€††+µÒ„ôÚL ÆÚç4Îᢧ+Ò%‹¡‡ áì‚&3R‰‡¾Uð7ñ;CT’ÉÆþ‚>gü@PØ÷9[ú})Ô±4õzúœ=Ä +«Åõ¡á}nzÑ +½F”‘ÂIÄ}f]b +Ö’Åls:¤†$°›¹dñ`hI]©þ‹HàÃ=^²¤¾A[ªdé:VµmJnÇZtÉÒ— ò¤èâÀO)%Ë**ÞË?±Ž®|͇/ÿÚ +Bž¡è)yí4‚PÉ;;C§‚¸Ê,œîWòÎgÐg%<Bº‘àŸêo +2õÜ\ ôí›õ
/‹¸îíHîdC»
ãZʧâlº,̾ǵ5€ª·es’Ú1h’…úVoo +„×nCØ–SÖ¾º*T!û~·Ÿ¯2?xÓ@‡
¿Þâ+?¨à†•‡¾m7€þ™‘¾ãnÄX¡ÙÐÁÓ.“„8æP>õ=øIä`=³ï¡•iGGÒŠò¡'¢ê]šr}2ù¥gŽýKýªs!4j¡+Ó¯úï +§ _ÎN6…¨«¾×/gWÒö1íWG¸ydHD}Ñ!´Oð_×àFbB‰ŒªF!4É +‡G0:ÅCbW@¿áõM~©‘òKø˜ŸqÎ$9)°!ÑïŒIÐ(ÖUÈ(õl\P ߨ®Ð8–*Ò¥‹À~ã¦@w?Éj-•($0…ÐS +ÿºÒRYÊУÉô\lN––ÎR ¸éJËd˜c ´Sr3†FgB8“¯´l|hNRæ/Þ¾¥e×(þ¦S7ódR"E¤ZZ½¡@Pª”þGƘ©iÚt¥ÿqnßÒs†ÇÂÇP_\‹ø›Î9[à~*½éFVCRÔÂ_e¥7MR xs–ξŽM\*1ÇžöÒÙ7)T×Jç~Á.!2¼ˆ'‹?|î×ÐÝg†!+!, <ÜÝç*ö¥>fa/TíhAúD T)]z+û >’fž–Î2€” +M"(ÇÑ]¥Ö1€–Kë•Ò‘=/utÔOæò"èñ+ÒÇ<0O1tôD؉ž4õ3KŸøL ^Pú?6©IÍ1ê=Âc‹,*MZ…ãá¶ü~l¨ÿÿ†ŠÕÞî€þó*@,…˜„oaè1è±ÓYÉ¢¤*îÛÿ±3 +Œþ?Ì.„)7ÅÃ=¾Â +b¤~&·£ƒôC¥#®%²ð0”m +§`ÀµcyÓ¥¨ÍVk\{•A=`;—;§+ÑÖÜw¶Ï0€>x—…“iJúøà#è›Î|• ÞMaßá€o\èÛwäØ´ƒ]¼U|ûÁ=>`wøšÂ›àµ1`÷ +„—å÷P÷%\¤‚øï]ÿu{No:¡Aâê öþ®@Pª8$›1§ä„Ÿ-zçØPYÖlHP +EtY
î›äP5>^Vc…Aý©¬æyRy R<ŽÆ-XVó(7,De¼5OÊr_V üáµ +Y`Ä©pºfžj)ž§Zs"ÚÕ¸LÊjÍ?y÷DYåR
¡àpGöQVçQ¨€5ngTYÁoP¡,Ý4ö¶8±¬p“áyêp‹CútM’²W)>-EOòdúÂLò°>^VôŒáy²šò$ÈÓ£™+ß +Ô€{CÊFÿe +„ø‚ ¡’4Ã|Á¿4:+}WSR|ôq +„×nìVF)uEï[>v¶tźPy®!<Ü/@WVf÷ãÑ$Ç–_™@xY®<Ys +¡·"Cè4ÂÝum¤{‚þõøQ¦üºvÐäòr‚V‰X5*Ÿ<Pð7MæR†ŽPþHVÞ¾“eB¸ßkù-yáõ¼ßA#°ü–ÐôÖì2jˆ¯›Ìéí [¹ƒ +‡6•ßZ` +„7Ý«²@ªË?¤þ964pÆ,0œ ì2üð3&)Üg/•5¹ö]º6pöCÐÅ|msÄñpÉìw”@s¶§”çkú˜œó4—ó¨é ø‘ÂZg +„éÁržLÊ´NâÚQ øF=ðÿ;ó8«ÿÿËV>JF¥’JQq/×u/Bû&c†fÛ`¬3Ö±Œ}0²…1–FL¡‘a쥢J)Ú(Z´©ô)Õ‡ßõ>ç}Ýîó½^ç7çñP=÷u͹Îyoç½,—±Q +Ú~ÕN\þ¦´j9¿8=3ˆ;q&®zIðÎ\çg³–ÜwMqlâºA!–¸~Wl«8 +‡×ðÍMâVÙ噂ž4Ê‚Äs ×Np@($rgñ;½ö[<„/hwãÇÙŽƒã©£æÇíáIâΩ,0ãH—“•¸s†ô~bì˜S‚^‚÷“M ®¼>€ƒy‰ï÷P ¼ŸÞϽà,4iŽ‰ï‡p0/ñ£]¬Êh´§¤•_ü£ÝÐʬ€¢Î¦`ç&ñÀÅЧ±±ŽÖ\¨%~z¿a©rh@§ÊQ—7è94œ)D»g¢'@X`Y“O¡`g*$Yf +„?ËÙl×£îÅ8k)ñìPÂã¬ÛÜ–úŒjû‰gÇ*Þÿuí'çÅ=“ÏøqÿŒP lýó¥´}EŽ¦7Nâ?ß”µ¬$ïi–HÄ»U\è´á_Ú| [$4'¸åæK
|D–“;Zîi +?pË.q}sòËð…ZË.3€>jÊþå«h¼²–=¨@ø¯;¸™ãOâþ;ð-n3€>îÆ/NÙÿšÊ«–÷V (zZÀQ#²ë-ˆmyh°tXÚãTOÑQhB¶<ü¤AÑòËÓ,0DmùåŸ +„wæ÷ÈÈÅÇË +Ö–ß?l +„éæ÷ÙŠ¦Æ¦QÒÍ)ܾI7KpoIÈÃJ1éæ
ºŸòV±œ‡il•¤º_(ÞOu9ÖCÑö &Ö“T÷ÂïtëvE('è‘*ü¸[w@·Õr= Ç„ÔTa&ÝvƒA2©^cþÀaº1År<©^3Âß®¾tIDiÐ3}”W?Ï +ĵóyñÍrRx®Á{„¤0Ol¦›Û3#Û…6*4’×`µa‹ñÏø×R üN÷r«z*ǶmiOjRAð:=Y–àæ„žLO~Ü“[ Ò¹¡~¬¢ã7†V@9 +)je<β)þ¥§Ü*ÌÔ¤9&=µPðOoÌnRDtÿ”ÞLð/uÿX4ÔIÊâhHR÷CP/Ñ·Vä*D-MFlR¯zPoD§:Ê]Ã[¥wš”É+îˆ*…*?)s‘A!)û«
ê>Ðè»ìo +û䋳RŒ’üÁ•
ÉU ¸NÉ—òøkêeâr¡ª +uKrŽìÜDɬÅ݈’ktQ (’Èâl\Š`ã!¹ÁQ¨a›!ŽRj#’Þ` +¤Ëˆ(^§^óV¡Š¢ +„·ï;¦M;Â|òKðb.Þ&'†…= äů+Þ*ËFðbF)c_cû.m +„×éùZüé‚@SÏÙêùîñV+[ó¶óX3ÿ®ÕÊ6Ъ2‡”‹®é_ÐjÕfhM¾4ÿ©²ÛÒô2iµf–á_Ú ‹-Qu£© lµ±¢AµÑj³LŒ(§I´iµùwhg
阊¹¸‡‹·³–Ák‹V;ݾT!ìÇý3[í` +„×é}nC i)>Í‘zÿè`‡qBb"*Þ¾‹Y¹½ãC";–CË
#ò>Øòý£Ù*G†+´0ZÙ+— H”§dÌ…>0€~”S¤E„€Gˆñ‹ÿ8Ø +5Îrë·G@û—±`
ûmÝ„“ÖûWÄCø6©õwò";D‚•ª'14Ç +ÜËPê$…?ËCó
‡o‘žÎTУ¨ùÅ®g +µTJ7ߦy@º$Δ¬t¨¯;½=BõϚܷá_¸Sö öxÊÀí +í‚”œ'ù E«U¼â9I +„W|ÄcljS.ºçB¦ŒxÒ +€…[̤Nm +„sÿ¿ ±Ð·nŒ\êþóÐÁ«X)hãøSêÁ +„OË—\ÕËSñþòIÂúî›L÷Å…Âø›~Ð÷<¨–Œ-Í5}ê÷ï)Öæ?Ê–ÙaªÅu¼üâ?ö3Ü–Ù”=áé–æBà ŸÏ±".°4Bì—Š +„÷øIùåiMá`êÉZ +„×ézñ¦6¦þQß +Xk~é÷•Ð_SÜ …¨p'Î6MW øNm+·å€èˆíñ¶•;@Uü‰ +.œŒß¶Šm +„ש@&'RÉ‘£4p\¥]ÁЬ:2¨@åȶ§«?nÖ&P)«ß +jŠÛÍÚ` +5QÛ=_!Âvf»…WÊáŠÕF»…5L i‰QÏaÇz†_»…ÿ(þÀÅ¢¡0ÿ©©â9 +ÕF»•½ò‰™ë¨TæZöA¿(ð€‹Y– @ÐÔn·Á‹Kqš>£í6¤@Û_Npƒè¾` +„wæÇðbÒ´HMÉX»?2€Ž¹#l"úÖ,æ±·nßöeËY°R'(v'Û—½d +Ç£8ÀØþøL‚Ǽý‰S®KB—´šÇ8£@0jÔþäËÂV£íOnP (ÛŸ– IbÖ\PÓm¶ýéoàßeh‰®vDó¿]ðg9ÓAn:QzÕ¼Ó™. +„ßé¯Öñ›7jÿWèüÿ¤‘EI`Þ¢ u¨PAà/u¨áwÐÌAO’Te†Æ@õvH’¶¥É…ìPï-¨Ù6×ì€VDwhöA›®C÷å¦sbЯ)"îÐ}eùPÇËÜ Ô°ÆcBºPè¦gä‘¢vS~ÍhàŽ7å+üÀ·æ@GTP#tlœª@pÅ;Þ{';\¨ÁEzï½Ç +„ßij «WŠ/y*e*3´Ò +Ï]§¼‹øpF(mk©NyUJºNSñA ÉÓK×…‚ +„—Ÿ!Mmj~äó\d3TpžµyX?@¬Ó¬Š +F§9iÒbuì‚€7Ç¿ÝœNP!§òR¸73Wx“ Äwùd©èº6u*LŽ‡p¶`§ç¾bL~°¦†«ÓsÇŠžNó'¹Ò—¬CÍŠÏŸj +
¿N¯ÊÊPªm ¦žø¿zÊ +PúÎkÙ™ÚXQ§ï¼Î +HÓS¡sƒ× /dË> r 8ìüÅ£ÐYŸÜtÔ™ÁÖÜmt>T ¨ïºTüR.NKWéRñk¨ +{Ôt¯‹Ùw©2[à‹w¹JZö”“åÓÝNv©^I æìR£§<4¾†z$¡Ò¥F–TGnß°¼çÄ!¸.uî6€î”³Uu(®” 8ìr§Ï +„שÃ˱cNí¢ñáìPf +ª+þ¥eòæÆ1ü·Ä-Œ.Ë:ÄCØÂèòMO6ÉMÒŒ³êòMŸxkó®aY¡&º†û5í_»†6€î} æÀ“º†aœ®÷>a +„×)½:/¦ã.;.<þ¥ôšPÆÅ n€Ñ±èð¥L׌K
nC8‡†&zá&Q]»
W ¼3»ÿÅ"šz*hæpuíþ¯Ô£«k†ˆ>;x zt7€x8€¸uj&RtÍ\¨@ÐÂèšu+È4ä]SÙ5«žá_p‚7M
ÿ¯#ÁŸeÀé8ÈÓ“Š¡rˆ§¬ša£ëÀÆ +„×iˆ´Ä¨7ªÌÞuÈ‚Zªë0Î|]T=ÙüâÃ@¹²] +¡ôíšûH<„åx×±²¢ˆÜq_76Ýs–©sµòÖ,ÁØh|€µêÊl»Ž·–I“¥ñ}¬±‘ÕuÒ3дKc†_ÀòôŽç%˜v¥”ŸÅaR®¶Fªä÷7€måðDÐqqý8Ͼë¢í +„åøÒ
T úÂŽ®u]ºYð·[%'ìúE×Ë æÛ²?nã&W`@Ô¨Û»<Ň"F~Ï^‚7(Öœo<çnˆ"éðqo@;ܾ!4JSÒuÇPhW×M¢£ ÑÁ»’/æ;ýÙYQžJéúN¶aÁº÷b6ÚcÔÒ¸n]÷^j +„_ü‰lЈ,Í‘zgª´ç~qÙ˜oß=‡Ê§Œ}eüEV%62ömR üKÊÑÀ!¿X|—ñáHÂëtð‘˜ëFƒcñ;| +¿¦(ô62N|Çaч‡ã3Nü¨@ø¯;³–U¾E=/5Û÷̺ò¡nU¤Ì¤úRª(‚ëV¥–á_ºž¯ŸiþƒÉWévý&‚Öa··Ä‰hMöi·_1€‚2!I\Êø4M캟Š‡°ÕÓñ[l G¨Ú\³w+ܾÝ~“áS›B>O_ü·>ñΤêö÷hvIüb^Ì¿Ç•u¿ˆ[ôù#¢3¤` +B÷ +>Ñ"Ë
C(Œ<tt“ÆC€æÀkú´wôR (0ºGG°À¢ ».4Fð.xà}ÑÔñÝ‹…º?ð‘ôH}i†Ï;¢Ù¾Üc +#¡™ +„wÁé‹Ü '…öñÎ<}™ô»lO DEG@|¤~ol +OK¯ãÒM¢À¾c¸c·»×ñ… +]·^gú±8ŒPê4‡½Î*ê]©;ê ˆSvzWd +÷xï{g±Àᇳ'zßûl<„cö½›È^p‚ÃØáêÝ$ß +t¸z7Ýd +½Ð +mºÞ½@Yì&"Ôï»n½³Z)bý¦±‘åˆÝÄÞýf@Ã䀞ÍX¶‚øF¢÷° +ufÃ[䦓|ø®,³áí +5B¦ÿl‚îrÜ$ÜL+Óÿ?‚]fãÿðP™g"ª]®@pgf6{†ö(íZÊl6C |Ê| ‡E4ÍáÒ\ƒe>0Ò +pÌË£¥\è~‚Š:3mžkÖ’øÁÖafÚÂ]{Ù÷?D†vPÓ !³}¿ԡnlûჩC=¿Ô/à†Lõê™ôÉKÐ/¤@PßeàNæTkEq=s@Ô +ˆBbü×|¨@øÅç½ÊŠš +4c¿²æ½¡@ø—溃Ü-\³œ5¾TäF!)§)Í*ÊP ¼Åò˜©ÙQ-ÐxÈ*Þ¯@ÐÈÊZÊVƒ4ØZÓ†2ki²T’'?%LZ~…Ì*™¨@xÅW½ÀF{Ô †°1šµêE‹¹j-`êdîÇŠ:kÕF‹Y6ƒ/!jqŒBYe +„W6/føÑD Í㊠2
›fòù½ó[\h‡á]ðUÞ¾°è“?ðWYбѶs‚¸ótÖ±vÐnÇñGpÏᬞR ¨ƒ³~Ífw’ú‰yªŸ]h¨á_:ÕF +1Ç\=Yß¼˜§Ú@§]ÓÈ1þa·ÊéA +„?ðÿÜ aj‚5gÖÿv@çÞu'™Zšw:·_à;õ©(;'ZÒXÃŽ>Ï*\§>Uêó1§bk'–ö©rTõ=Þ¾õ;ÄúTýÐ +mº>ŸÿÏUeòJ
¾ø¡ +ñvàûy‰Gø˜÷9²Ú +.h+3´Ú +—à©ÞP×ñ,zhfƒ¦`·oקˇú…Ú²KBE4r¼_¨c<„åx¿Ç«°B×…6–ý¯¦@øqÍïLpŒoxe†îR hj÷k%ûdÑtË[âãB7@™²7‡I5âÇež6€ú.dõjÓõ*ôë»Ø +ˆx…ðã†Ü¨@ø¯Â£iþ]ÀAv÷ž4J¸n27 Iví7ªŸôtxµ}Î~Oßj +@hÙ_¢’Vr»à‘ê¿ì‚+Þ¿¤¹xñˆ?JÓDp¼ I¢á_Úx9Ÿx4üúo¬n +w怣î-¥™kJ|f +·Ê€³·°£d
MB÷€³·ÇCø†k`Å
¬ò)‰SSv4°â¨êŠ„¸+'|—?°êj‚›n`Õsl<P2¨ç„¡‹/R ¨9^ö-úÀšDå—ýh +M¨2;}S<„Óˆ²»?'ƒ +~º×ôŽÏî^¤@P#d÷”£Èlú0–§XÈ… +ÿuƒeì’5Èá‹9xµ4œ{œ9gÜa8j”=<aÓ({Òê˜Ûm;_ª²ìI¥ÐäÛYRö€§)¢Õ7€ò¿æ%еªæçS ¼NsçsxBvWÇBlîóÐùíD³zK +È^°Ê +â~=ƒ²îS ø×
ê_?yïžÙô.tE<„Æ As.˜ÿÞÁX•*4€r×°s?Ç@Æ/ž»Î +„Oð^i ;2NÌG†ŠzÐÞè#®%qÄ…/¨û5è£&Ð&WØSÍ‘úh«A0èÀk……`Å;°Ã +ðáÜÁ—@Ûþæ#%*qqÆþàmç®ÓàWÖñã"T0„S迲Ñ:ˇÓáoüN¯ük +ûÁ'>”Wžëg:h +>“®5HÕµÃË)øR Ë™õ²ÜtŽ³lÛšÔ¦œYë
Õ2C(HM—}š)c9«ÿQ ¼eÇå³Ðx¯9e'¯Ó†ž®AC. 6Ús6d™@%lø‰áÞ8Ñ&gÃ*‚Ç<gS÷HDW&¸U6%)>‡®Oˆ]øû=Ågü¸C7ÅCX#ä|³•·¯5 +È9±Ñ +¥ïˆ'd{ ¿Ÿ®Ä5å#ž˜m +ðÎáâÅL©g +½]n +{~\Ï"Âï4䫘H!Fü¸!ß@CÏ%¸×ªÑ`§9ŽÌ©¨@PŸ&>ý²,Í°Ó‘ã;)^‚ RßEÅpJMÑÈ —@Ó>æŤ¢Ù6rÚ!›®TÖ·Pj“#.4ß®ô]hý nòßòXö.t@ði)+aã!*dhÐŒ,[i +±‘ïð?ÝÛX°Ž|ç9‚q•‘{þÃ!D}Óq väž+Út#?®ÄWÄ1YðqUÂûÆíÿX5P¸|hÔܽ1ó?jk’FÍý@à¦UT'fÖ:N7NºUt›Á%µ°ÄuEë@¨6F-\m +Åá¨
3Øðó‰öŠðpŽÚ0K èµ9vKB†‘æ³l>i +~k;Œz#Sð:íö1Dî&f?j·e +„_ü‚{JÎ^Ìl‚:xÔ2 +I›.jiú´úá„áÇø•MÈ°ß +Dpùè§ S¯ºF»£<=öy NíP ¼Ngnf3„ÚjúÐŒ:s›áýôO*/#}šñ£þi§@øqÿ»Š•bFJâÌáQÿ»VðüosLå‡-Í¥ñ¨ÿmS ü¸s'cãÞh„ý¹ÓåC£+¶äϤÙv8ùgtÅÖ +ÿºÑ—væ#Ea¢xûŽ¾´›t—Í. t‡LFß5€O&¸W”²?ðè@’á_ +çIUF©AOâ–MT ü×Ee –®ƒAÍD¯ÑÑKâ!ìßn2DN +xÙ!œ¬1ºÉ0èa?1Ÿ?Jð?l+Þ*_IcÔõÔ¬'ÚŒþªÈ +¥ï9-.d+~§‡[IÑCÇ*¨¹êópªáÇ5gÓH”ÜkL£1ÍÇ@-d
•Ù†l€1¦EU(Q¦†ÓŸï‘šÅL¥@x?¥¤³ÛMÂG“’¡@xÅÛ>ÉŸ… +îm¡Ó6Yðgi+¥ +ïÓ¤p¼˜m(ô^Çt¼–k€Bèøš~LÇëJß1ë°°ùVHsî:Þj +„igˆÓö[º&vcwF»d“rE渓Øê»ëMèÀæ˜z¥†qPfŽ=ðŠt“]eÙ6–¾cv1€¾¼™·/]ïx¢ÿüâ_Ö5€~¸Q~`QT¥‰ÙýሻaÓ 2Gá‹ÿi +Op^¤O‚›ÎvŽ'þ¥È +V2k°W–÷Ðn(™-?¹7š¨v^r¢”~±OœƒîÆìB—*ÔRy]d;ÑNØÒôÌëÒ@ TÉ빋?‹£^-Íø¼ž»àÌY•Ô2¿xæ‡ += ¼Søq>G‡ž¼ÓZ=y£‹ÝBA8Í½Ô +N|X•åÍ]b +„÷ÓÑ\D_¥h´Ÿòö<«@p?M>,
?j÷Ð4^˜|B À˜0GÉ‹Rø4¨)Ì™0çzè+j*”×ܽN˜ó‡4ÿ‘7eǧké?aþЋc!á˜`èRhÍ4WØS ÎÏœ°f†áuzµ7/¦c"ÛQ +˜ðj_è,†È)ñcÇtÂý }³ÊŠ#pgNØwÎ +Nø<Ýú]¨±Ô;(ÍÑjÕ
áï6€†£Ž«YÌ!ÃjÎI#F²Ú vI7iÄXÂûi”¥!Æe:›ï‚Q 1ãÜP¥ß;€•sÌÓ +ãO“òÜ; ›RQ°?)o¢47Ï
¾øƒº"âIs'+^§¹³Y°Ò¥±gü5¿øÜgú-“ʉ¹ItO„©¬¹á_ÚÊs'…‹«¹J™´u½Áo7¹^™T@”Ddyœ›Êm6€²e9² cÀùO“³·(”ã“Ç
cžô½¦vrò¸QÐÄ%Ò\“åB8ò0yâ2h’¼Å¥A]ŽäÁ[eò¤°Tpš· +][xºòbüi +5½×¿øö +åøä7ÆŽ©ùÀ;ë@oË* ŽXa¬[&”i”HEu¯x1W ¼˜ûØö¥>íž.Ï.d+Þ*GŽò ¦ˆ½æNqò‘o±oϳn¡è¡çî•×éX%èD}ÖæT·¡ñÍ'Ÿ¸Ç +o$¦V©ÁúŽ¦·kzRMrÁŸzIWŽÐP/GÏ¢õ0Þy¯þ@§ÇL½ä}‚K0µúÍ®§HBØŸZ½®Áý45!Ÿý–0M‹Ä~ËÔ„ÙPí½¼é¨ÛlD³˜µ?P ¼N·ºŒ$|<³Ÿy níc +„ÿºÙóÅbÒ¨®üaÚì…&¡¤nŽM®ö´ÙË
…‘˜‘E‡Šèi›(<œÓŠe@È/f€Dp‚Û´â·
eûùH mßiË(^ñÕò>8"ü„0¾Ÿ¶úKÂ+¾VÞp…}"ÕÇ0¦ma +4×`ÓvÞb +qxbÚ/—™@©|Zèº0ˆ›ŽMû¥}ùÐô +OH;ÓÑ>;Œ]·é
Jø³DE*´¢§WJU (}§_ÙGÚO$}½}\h ”uW‚扄$œ@2=Ëg +„·ïé¡ îå•ó;8£cúé +„·ÊÙ(jàÃIRÓÏ65Z»‘1檲égSM 7YƒŠ4©áÓÏÎ/šq;þšRÓ<Pe†þ0€xP--§Á½*g$Ì4€ê¸·¸ÔRMsK2£Îe +uËŒ[ºÅ¢!tI +„ßéNyÌ£ô>:3dÆ+þ¥²eX:÷$3|b +ÈïwÎ +ΛÑpœAõ:Ãïvþ¡¦ˆž¡.t…áÇÙr@H‡¬®4žaO0€B±¶74(O"žz9Âue3mäBþpÐ3\É…Ð2UÌ6וÙÎx"Ñ +„W|Ö% ±Ø¡O3ì4Ö¥ +„Oð9k.$†—5Ç|Á +„åøÚñ‘™¥ñÊò×>m +„©óù8‘¬,:³ó×PŽluá˜}ÂЂßnfN=(Õݾ”ªŒÍÚ™9i&ÐY6²,™Š€¡ÿ@¹GجuPPÓ®sfî× +-Œ™c¯g³–Zy†—ðãÆÞd +ÿºY×?[LËù,PŽÏº~±ÁÏ2ë†ß¢¶Ëš†³nøCà·›U·#«
ÑW‹èYu»(~ñ†îTr…¢)ŽÕp§á ”à^€P).þÀÜ«@ÐSœõˆ¨NI4¨i3ë‘jP"·˜ Ò^+êY‰M ŽßñP«UMÑ笎ǡf_ó5o:*©i»<ûšc +wæìzYå;VÀc´»P[¨Qv»i.®g$·õ‡p>Ýlÿ}ÒÔˆÃXDÏö?h½“à&kÐÍ^Lÿ»-ÇêPä;¤±5ÛN2€BÙr«(¸¤ Î
1€{+Á½¶ 0Ôæ³Û@P›ÏnÙ€³¶ÖÙ-ïQ xîf'q¥1A q¶àì¤>P[i«DØdߥme¨ý¬/cÛ¸XhvûåДþÒ4r4b8Á×`³§d+^ñéò–$#£Ý…Ò~–9½ž»ðYžÇ.´Ð +„¿ÝAÑa’ÃþùÞjl +<{í«P‰ D'¡˜ž5Å +„ßé–b":bk2ó +o9g +ø4-Õ +¿ª@ðÞÏEéAràm\mQxÿ=P+·Ì–šñDñá,lõ¾AÍYø'Ý‘3ôDCøqOUV ¼RîcÁJ
*B8¨0åaÂ/ž"º¶ THÍã>T |¤ÚoàÏ"Zb]Ø~³á%h¿÷Âbú4}Û¿¯@øÜuÅ®Ec5¥+…sã!Ígé'=E D©€ØÈ*ìwŸ4àêØ‹‹~çðÅ\«@øÜåTA9\I#Xs*›@IÒ4ò‰V«¸ì¨0§µ4ú5VŠ4hNãHŽ~Ó +'_«@x1ôf‡ËçM‡– +ô1€6.aG‚Ši4Å…—•Íkžå.¹ÝøBm^óþPR†èðÙÞâýÊõ0€rm~ Ö0>Áór#PžLë§r;¨Z=/o½4å#Þt4ÔL“k4oʧP‘´3C”0iÛø2t^QÕx_æ=ÿzìpüš¨ö¼çw*Ñóíe>JƒE±ˆž·è}h™báJøpàlÞ²<ˆ÷¸hOm{æóã6.W xîæmšÀ™4Ù…&+^§Wþ•Û7HŽ`~ó^9¯@øq;Ç\$LjºÊÍÛñˆ´kVJW÷4jt¡qÐvqÉh÷á¿yæ(Þ¾Ÿòüjöa…þoÚ‡Ýi +uËsÿJ¯,Dnw@3Vç¹OÆA¼3çW{‚¡ÿOCËùÕZ@7¤°¥«^œ$5ÿ†4‚šùw.¿àvSû4€fŸà&!P¡<\Ìù³+üÀóÿ•ƒgDvu@£¨çÿÛ_àgYPç¿1ç†ÚÂÚuÎ*Ü*ê`צÒ|ß² Þ*‚;sAýß\U&ÚMA½ þj©
Ûñ‘’åÈPô,hØÉ +Låƒ@×;šÆéÐјᱣ8,¸àá& +¤ù¥&ÐÛPÏ_]õ*ºAhAÏSИ9üY,jÓˆâŒ)T (éäeƹ$|Õ» ¯¯ÁoWÔ\¶É¥Ëõ(ÅãÑ5Ï0€Z´•Ø9>KÓe§¨E(‰ÛቜftTQrE¨ÛcŸÒv,,X‹Ú\g +µTÑî±\J$‚Ûw÷èÙRÍqG(ÑFó?)2€¾8ƒlŸ¦AjÑ?–=¿ßèwgc'ðùýo@¿®aG‚zÂ{Òc\h½t~tàÎ1xîò‹Ÿß…±¤[8£*›Fä#y|súO<„÷ø£‰,z(qVS>ºðh²áÇ}&$ÙX‹ž…߆ c}ج%ÁÂæÚÂcýÿu?sÖ·[í©Ë¯ÌÐx÷ZZxú(j ¢™…¹ðô·ÐYwКM» +„©ó7Œ#–ï‚ÎoÅCš]0à°<RA +Ãiz™,pÔ +ש8Ò•7]hzUGz(”OÅÍܱ"•›FÅͦ@ÍÅõ³HKó{‚0ܞÄÓ4û+nþ‘A‹µ¸ûw”†Mcé Ôµ¢Ô]ÎB"aRÓc¿¸{GÂ]V‚+0hˆ¾{-Ϊ@Pô‘½–(ÌìDqä¡xH¢ Ô:fЄtmÞŠ‡´Q h†wGiP}‡»Š‡¿¢@Ð.(#û‰YbÀ‡§òŠ7æèé6Ú#”üƒ¯œŠŸî©@ðR¦xòOTpÐ(ÅâÉ¿@S|ü8jäÔ<nJÐ +^LºxÕ$F,^qôREv'é¢7ŠCK‹_ª¢@x1×Ê\1ÀÞ{÷êBo@o–ê•Z ;Ÿº¸‹7Þª@ø¯ÛÌ}×âZ‹žÅ›ÿ4€¶îäàÙ–æo}Û +ìÂ?²P ²øøç¬Êd" ~Üñ# +_|Ii†Ð ×@ÐS#Q™¡VPS9Â]~;„K—4…±›´äë•lÖR{ß.ùzÁ%XòBE-+ˆÅá’o†+<œKN¹³-¢"ç’SSî§%¿õdçF¶[Õ@YÐ9965Ê ÝøÎ,z¡*_ÓS›!K3è…ª~–.ßà +ÈMÕà‹¿pù{ +·ÊW^ÌF–-¶/4k_¸òRè*9{‡¦øu“Ï^¸j©TÓÕ©‡ß“bÁÐ úëY•9ƨåI·â%¨¿Ñ +CWÇCšo×ï¨G‚†Òá%èð–áÙ‘;O;‚5ð\®óã:Î4€:K‹•.e¢AÏ$ÊP h?½Ð³nLåSÈDÕS ¼˜™®¦à‹æ2{@ƒ;». ÈØ‘xap7‚ºeiýçâ· +¾”YZÿy¨‘œ¦¾¶f~ËÒFuꖥщ„
Üícit¡ôÈ9>RÔîÜã·0ôh%èq9é3"M6D_úøz¨E„Ø…•RÀÅlqƒáoÃ#ÞilÍUïÒ6Ù +uËÒô«\•OV26—¦×P xÌ—v¹.òžq¡
auäA QºBù¥Ãn7€F4K@X)6ˆ?Ë¿áw)ûø9̶<¥u.4Û +{aŒj¢µKw¯@p?-ëe—$ Ÿ·¬(GÞK‘cJýáÎ\–óV<„Õë²gŸä% )ˆšÇËžm©@P·,[Ù™]Ü0Í2Å¡e+3.æ²ÍMy1©¡&•wÙæû
76³Ú MŸöeol5€vlçŤÁ3a…\¶c‡áϲ_^ƒEhÄ»7u€s©ô{ÅØV¡‚8¼é~¯b +µTÉÔ7YôP Æ ,™ú¶”Ï–˜ºèþ$¿©áuš9ŽE]Ïi2ÑKfNT ¼3gÕd—D$Ëi–`Öu +„Ô³2õ2$’É4ñ§’g?1€–|Î ñãðiÉ’/
’XQ +„iËålÖF„!©®2€^‘<¨|ÔGù€p1_T>´¢k„C”ìÄnÒŠ®M LY$ʶ}ѳ"ó”AY°"W^aRÐÓ1ÿqrâŠÜ½Ð¢ÑüC²IZÌ‹Æ)<R+–s8^t×D²V,¯§@pg®XᎠ¶\!œd¾bÅyhåúØP¶2´UV¬Üd +äX~Ü&÷¥Š!‚rü¥=c9@·X¾´'Ï +U3€jö‰hY +„ß©I÷7Ñƶ4CV6é@øqÍK‹ÆŸPKlvT –Zù°P¡¼ßÛöÆ…@É»\qHÑxœÚ´2y¯Ác¾êú+¥‘åH{›îüѬºþj¨öaþ,aÈð¯ª}Dð/ùßfc”VÀÆ÷-«ü{
+³_óå% +„_ü¸¨"ÊL7ŠlÍñw _dúžH»¤«>-Ž‡pPaÍec=‹~ÀÓ-?ðŸQ A^ówÞ¾«ƒo×üÝ£|hmÕÃ1õêóÞºÐWñÎ÷]{ùä¦#'ÂÒtÜZ{ù• +›µõÄÜIz'üKõ@MeA%F8æ(¾lXÛ4l +ÅaiàÒ>±ACS<÷æ.ô¯4êzi<Pø€&½¸tÔMPn¬ZU´À‚Gª4÷s‚qºÒ©w±Yë¨ê€Få—NmÙÿ÷nƒ¡‚®¢¦Û+¬[JVÅCšušû!¿¸*àøSé܃гýø˜Sa³'©Å…²
ÂC1í÷&»ò‹1€žãÁì”WôジÒù Åo²1Jø£ø*¥tñnhYNLˆQµ‡¥ËF@[¥Ar>LˆìHø¸—)^§Ãr² {ÇÀÙ]¥‡ß6€¾¿Âý,Îã¢Ø*ýþêò¡uöIãÁYN[×hÝ„¾Óºâó|ÌCb@4†W4x*¹ùäiæîB«ÿu/É>~¶Xà]™¡» |%NíÃÛx´Yôž~RÄ;µÎ…:@>eóßvÎzóÖ8¤@x1?uÅ¡Mi¸•áºOƒÐ!yÕ5'šhíºCÛ #1aOA(×yÖ +-±õçäM ãqSx_¯?—§@ðÛ•Uq'9Ïói>•UùWà‹—±ÃEù’”T_¼¬ê· +mº²jr¦-FkZ–UûQ æ,»¦q,<AI¡ø¯»æ>¨;+E›ŒQè(»¦·t§[GêÕsÌ/~ç +„—àîÚ œ$å9Æ(þ¥»ë˜@ñ‹SG³éÊî~Ì +÷¢‡.S¨±†zÇCÿ·Z•¡fÜÏâ4Ã)Ëš
ÇäUJ( FúâLϲÇn2€Ú´æcîíAO +½¥@íXŽû#¥Â™TeíV@¬Ø¦XžH»E ôkc®[ÔÛŽ_<ý:Âû©Ç'±MñféºÐ!¨÷å nâVЧi$[Ö»º4HÉ#_2`yj$øqƒT üí†ÄÆ7:1¬‡Cš*^§a¤©í—Í#ñAÖE –*.#Y–ó¼¥é_6¼‘á]0\Þ,Ó`Ѩc<`q8<a·lxSdøÙšÏ2ü~Â{<Ov)ŒP\ßq +ûM—üÍjÃù,TÀ·é’óЕO¸‚Õqn4®Û¦+[*~§3ÜÜ–’/ƒ¿eÓ™æñö[6É”Æ(4Ž8„[eÓ™¾ÐÙåì&ÑÅ£…ÍMgW(<w›«¾è +1T73tsÕ• +Ðæjâ&Pxma_‡à6W«®@0†±¹¦Ì>
Ó¸L‡q6לm +„_¼ãì^…ÀÀAôÍS ¨Í7÷š?‹LƇ'xsÿ)Ð@™µäI$~œÔ²yàqhÈŸì,‡H»âPÀæ!@9³Ýì(×n:¶9§°|hKÓ,0(dÁ:xKÓÕÐð¯\•O=qÞá–áß@ãä%•û…(ž8¸e\‚cK™ì©<4m¼·”ýT>´uê‰÷Â?иI[§ž6€æOfžúriÆm?Í +6IÈc©b1nIK´>‡¯WzõÍ|}]‚;sÜ–0_Š@o‰|·%f@ðz·ƒKP˶°%jÜŽ¾èPyåžðÒ,ÇǪl@xU׫—Þôµ¹Ôоâö<Œ;;Ÿ•QŠÿ²dò;»È€à</¥*µxA-®~ùøRE¨òÒ”[ +yŒ¯¼Ê€àŒÏP*
Å° +9>c®á_Êé`G,¹°µ1>ç ‚Bl|½¡)qt|jˆ†þm@píÆ7âàDz +
ûªìð²4J7 ¼vëÚ‚îêSÚ5t +~Ç“]*€·ò¥¨h¬´OÜ^²LA¢{ʸ‰F|)÷zB +¥¡}è-åc¥C1ù2žÌ·*žñwT;uJsm|ËÀßm@xâàJ… +ÛxÐmh„N§¡²\1Ë.1À€ðÚjÎnœDÈku‰¡á2UE™$¨ +žŽ$±ú?aúß%C{õäÃIy‹ž‰½ž@/\Å*$9b-ŽŽ‰/\'€úêûÎ5nÜ[^Ôû>a@PÒM|'S»'¨D5nî=ñ,4¨<o•¤ß—eâ Ê÷ÓÄAûSnœHÐ÷n®?wH +zâøý„eÁäí,ì©Ó€¯0nòn4¥}jû&mIŸ§t@ù¯§”ѸÿAMCý
¯ÝÌF¼Uè²ÄOœùTpD7Þ£Ëñ‰ 9eRêZ0Ãñ¾ç”5 ,׌L9:\;kL\ó + Ÿ±CÈÕÅ]î§)=¾@B¬ø©– ðHM5 xßMª#‡#äÆ>Ö)CO‡°uêË+ÕµöžR°nêËk
ÎøÔÁ¥yÓ½Ba?upYôÑ{¬Br3m
@ßÌMÑïÅ”§à›…ØÔïTÓjŠ|w·0~¶˜úÝÝhÚRmNzñL[i@ðOs/‹C¯i&>Sçt@ûÛôsaÂÿÞÂS°¿A]eZ£ÿòAðÊlb;xZ£?P×Jú*óÊ"Z ‚<mú@Vk©O{¦MO + ú椇G_J^–§ÐѱÒNMSC–}D +ZZ¶å7h&€vbÕ(¢‹nßü†]ÿu>VËBÏDшe2}j@Pä_ð²V! ÂÁ®ù¼ZŠb'z~“y)—I"bÉÈÎo²P +]V‚ZˆÅ°µ‘Åc¨åÕ,]u͉a\~ËV„§ åyY¨½‡/©JC‡°_%¿åÞ@Ê}jKýÍoy@ +Œ`ÁŒÁµ
ʧ¨R†T^1´T¡ŸñÁ4l{@?'mÅ#gxÕúÏAx?ýgjÓÅC–Ô•c@¿¢¯
÷s–b3~ÿ€ Æ:cÒ%¼ébÔ¤ »tgL + i7©ÃIªƒ´©im%ŠÏL寮¡Eh®*_æ…k„}†©†~@óÖƒ–]0o“ + + ïz±qã¹!_˜†zÔÇg/ÊUj¹KÉìÙ‹t¾Ì^>ŠÍîçÄŸ[þmÉÐœŸè »¸HùœŸÿ@ãU´ =îƒ<g|†Á‹zn&Ws¤ ›¥aÁÜÌëPÝ'L ؉>—Dk.˼ʵRªvØfâΫ\×€à~š—ס„üç¼¼{P£ZD»¬%Gb^£Óg|Þ%ëRjˆ5útÞ%›Ðå+•ºFÆaK(ʼË× + ‡á.pЖ<¯Å‚¢g^{eQǽTr_Ë6žÌöK
ÞóîxLs¯}c©ywô0 ¨dÍ»S—v¢Ò1l˜Î»³™ + îSØ€§p«.k:¯{¾ +å¥;/ËžUíyGžæÉÑ„Kçy®dh~kýÞ’´§dÌoýqqgdÏoÇ
éÂ^«lÏo×Ê€àõ:ÿvöBzÁ‰–Þôóo y<ð°À‡§ C#‚ÒwþÝY¬Ð8¤da›sþÝÙ•¬ùÏ«´È¸ã+œÎŸ{þ¨ +‚#ÐÑKØXŽ¸ÇÜÁ…† ¢çÕöxŽtl·,(z©dè¯\~~¦Æ¢Q‹°ÿ+÷Q´æ9†xé+pàyÙ€ ôýëtV½G>¬ ÿuº¬ +ðV‰º§Ü—K¢¡Ú%CË*-šZ¼;¶ÊøËþXr°>¾°\M>œ®¾áÉ\X®– + Ü/S—"h•¨¡‘¨yŽÒ`³{aƒÇPtsŠ âù0Z(€â¬±RÁN;P
@W°¤£¾ÀAKzÖÂ+ «RÝØh™qu†…WÕ2 ¼v[v(5„ü¥S4´Ç€ j´¨Êš£&M®:ƒåø¢6× + [Î9_\õ¿s.ºe»AKqQ»WYô8$3°U¶¨ÝOð¢ìA¦€aÇ2¦QÂcºk-.á…aã)¸kƒÁûnÑÝOJ»zN +òâñÐ~lp'’²Û¡ò°xÂ
è/.(à•> +â6¼‹ÿh@x25Ö—voš %k´q㌃¢gñ’õh7ñQAp‹ÀX¼íj´ïý”Bã¹b1ôAI·¤Ô&>æT2ÛRpwI©m÷Ó’ó¸ÖwØÆÆ’óî0 ¸Ç—TÛÁWy}µ'øsÕö‡ð‹Ä’¬Jy ¶„Ž¥#ê’¬(ç]I*ÁòÿË1ô¾ +ÍÒŒ^({Ë^Ó \Nxiö<tá%¬ÐP:c_eK/Œþ¥;”9I飶ð˜¥w<h@Pf.kÂõÇ]M
Uà/kr‰Áƒ°ì†ì +ðŽñ“ø².”@ºñLÌ%}%Ž5´À€ f¿ì¾[Sjˆ«„`Á²ûî4 8ãËоCjí`ñõ,{`£ +ÀZÚÅ,ÿâ‚“¹ü{UÿÉ¡ò
îàá.XþýwÁòŸ +ø¢N¸?cÙt˽'§sþ¥±+yàN(ã°åc× ?ždÁq¯ê0ND]þGo4ñ½ÀôD€“ª–Ol#tˆEÂËq‡²`ùÄ—ÐôX]Kƒ¶:È˧ÿ,€ò¹¸ºvâØ$YžßÏ€à1_>Ÿ[Dx!KK¤åóŸ@ËÃ,zbäÌÃî®åËÂûií|¤ÜÉt/E|¤Ö>-€¶ÞÏ›Ž:ˆY"b—oý§á¹upÊC¦>œ[?@»/æ#åŠ[ããå»›ž§¥•jDN…¨Ïƒ¬¡4tðýÔA rhhÉЊêñçÔtÛÁ+ª*€îä$½p,d-:¶âÎá_Ú¨v&=[¸×4vX¯Ø@;ââøÂO˜+vŽ5 ¸ŸVœ9Ɇ)Å $qgΖ,µ‚Ín +žŽà>+K@éòdÆ©X™ÞŀಬÌ(ÏsØÒneFeÔðú€v0’•‡•
o2 (Wðát•LJßÇÐ;T+;´IMA$ê+ÌïÐN +ÅŸñ» +¤®3D +VÇfÒê±w IÓµB|X÷]=©@ +…Qý
µ@{uÿ`¯-î#±zïÅ!ì_}H¥’Ç(¿ÇŸŽ¬¡«Ð©ÇS¼û5,3WŸêU2´¦Ì }½Ar¬††H U¿€Dk<ji´¶¦Ì¿P݉vz¡Dhš + {gÕ(î)4P®½·WÉкŽ§Ù B×¾n‘êsëî.U±ë^Wµ¼Ç«ˆÅ6_÷zÁµ[÷ÆjÞ¾!ª½€
Óuo–æÌÐf·Ys +У¿óá$ÉÂJ{á£ãÐK*ŒÃôz'³ð¥«J•ÂWtŸ@JÍ ã¨ð•Ñ¸ðU¥jÓ?îõŠ5ÖÂWûž§þÊ=áµCŠZâ¢ûw@óÚÝt™jh@Ðæ,ÈÍ)©UÐWmVCþœ×gY%ĹÖU +µ@Ÿ¼˜º]M_…Ÿô5 xßTÒNjì€=…UÞÁ…³Ÿç¦gìë)œý² +Ö¼Âaü(³~E + V:»’c¬ olu§:›ÎåÅ¢gc«¿
¾#ll[>¥jSª<ÁÛV@÷¨^)qOóóÕØç)¸§» +]n@xLïP†¾G,•Ì7¾wV +,M„}`4t¨dhS+%Huù›¥1ÔÝ€ ®²éþ[ÚIåê3XØoºÿ6ô”*ÈDÉBqdz驱h +Þä6(žéæS4ô˜ + Ž‹µ‰¢büpY¶v\f@PÏÜÚé(+ÈW
±äânítB + +2OÔ3w4¿W«ÚTä
;öw4ï$€ÂüΆ¨ŒÞá?ÏA_s + f³2špÍ$KñÎf§ÿR—լи椓Àɱ;»¬@¦§”‡hÔâˆÝùh5ôË/èÙ¢ºó±ëP÷¢s×kÐbQïìqž +ÏÓÀ5è}N ÚÔDzUÞ¿^ + _Ú§&3éÏÔÐh,—âQßp,äî±Ü»ÿT!`Ô͉Z. Ý@ÓÙë•ßðuîàO ™ñÀãta'úî™ ¹£Ï©kAß3=nî´”»Óx…¼-%v/=m@xž +›ðdR§E
Ù]Ø\ +ÜŠI¡ñ9:4ôš +!ñ=¥h¨P +jÁ û?™m@pLûg³K×Ýuî!·|nv´Wµ(¥0" +ü€ëþ½¹%Cq1/œÁ×kNCõЊ|)ºÿF,o¯V\#€Ö}¢„º†ÆÍu_ £o1DŠ_‡¥8úž + 'K\®™kqŸt²
ž»ƒñ¯Ù¸ñJÏᦃñÑèÖÚ)×’k`/äÁ[¼¨ÞÞ†¯¤KúÔZ
Ýf@P>ì°ŒÕÚˆ×2oßkнMÕ1÷ +5±çáབྷ”ºT_ŠžeŠŸœ]ZÅ€àjÙœ…½«Îø‹‹ðçZFP›!ìZ¢4K\Ï¡6#ÐíIv*P;©Ý~¥ +ÄÑ]‡^èo@PŽê?OÜ]•8<Ô‰AíðЗÛùp&<7¬‡¾Üc@xŒT}qU2£Ec=4òG4ùSµÀž;Þ—þÀS0ùK‚'øÐŒýäse4ž§kв§ +‡¬©u‡–=W2t8Ò•öÿ‘Þ~8ÒË€à<îõžL + +¶´ ?Ü+(€>Ñ÷•ZµXÔ‡?É3 ¸ŸšÀ[ÅUüÜûî§Ã£¦ÜO‡ÈeˆJ`Yöøá + 9×tàV"è3qy +æ´6 ¨jÞø«FÔ³"ß^oì!€ö¨ê¸E}*$nÏVtÀIó =ÂÏH‡°Æzøø%)2±´¼=|<"€NÈ&‰ +E,¡r‡O@E/ªMGéŒTM¼¨¯Aa$KÕW‰ÒE“¸é‘¬q¨Ö>^ŠÅ÷ÉL
@u†²Ë$AAn–×.€©–#qeLb}¤Ñ[¨¯®î¥øàMw¤ïwèÈë)‡PÈñ…ÇðçŽ@'Gñ1Ozj;”™GNŽ1 ¸UŽ©N*„Þ·ÀêZ2t´b36n¢®H´¼&@U”îKEǨí"ÑG«ä + u8©s<j +>š7 (Ç6š’Þ“?†ò
ÿÈå«ŒJ>úªj¨‘A™y´ÅàÔ碮ÖÂÑC
-~cU;NÔXªm1N +ÑPÌßm[C ½ª¬©jàÓU44¿dèxÝY
¡[¾Î¥!€ÜÏÛ7âµ ‡×Æñ
Ê‚ãG¸°ž÷Hë;Áª"€þVARqº7le”ŽÿýÁ|üÔWlHÄ<n•ã§F•¸(MôŒŸÄO\TA +>0 xZN&¸ñ‹[B +O&ÒÐåuYyˆÓ7q=Œ“—×/á°Ù“W~tNiXÂ>N^ù‚'øäÕJ>EU;¼À'¯¾Ð€ 8<yÍ¿X`P›p_µYþÜ5H Éü9ÇÝ*qÛç¦ ëƒ¬ø9ˆ¯“×GPëå|¢Ô‚£LN¶^e@ðF8ÙNùŸâ„àªkxíÚõ@·{c +Qú¸M§;yû*ôàcú*£ËAxðqÔóõ”ò +ŒÓ‹G ¥£SÎwð3Øé¥ß Ï{ŸKªÖ¢Ø$9½¢AÝ÷ôº¼}ô†Ôéu{‹AaË_W¨Þ€¨ÕO8d±òOŽ@›P#÷\KxL›: ýº‰UøŠã‹úôþ}šÓ‡TÍ—8iÛ
ÞÁ§¿¤ÔÏ ô¹qxàÇû + ²8¤†QìÕ>}¢KÉЙ2ªCœbµ´%<Sf›Ác~¦2×f&G^8Š_»ÏTn/ö°£Ã{ºÀ/Ëg*4 ¨gžÉTå_©<u’JèÀÏe.1 (éÎT¿A\T’Ö½ñÀ«·@µÕkï…£¾v <ðÚ ‚BìL£®)U;éÿ¿Í©¡nèâulHîg±Ï\¼I + «žQ‡3LeÓrÕ‹è†Ûø˜SqÛ.£tæ†èŽŸ”S!¢®
(XÏÜñ«ÁkãÌݹ¬Ö:Þâà_º»‘á_º§Of˜ob}æžÛДÒ,z¸(†Ê–
ä°èËøæ<¨c@pœ½l„6“\ïK5Hcè‚çîìA¾#Tš
»Ï^-aÆÙëuæ:µäc!vöúï
.ðÙ6*HŠÂ÷’¶ÎBgÛ<c@Ðz=ÛnΰJhÄЂ7çÙöë•Ò&+ŒS
ζßl@Púž½ÿ.>R!¯Ì1žÌûï5 ¼î›•vrRÅp!þ³÷2 (ŸÎvº+ ûI*/‚¡ûпT‘Jc[×î_—”ãgÞʆ)kDqxñÙ‡w GÎðAS„1¾€Î>ZÊ€ðVéV#åT w +NAQ¿IhÈ«Úµäð–êêECú óXÉ¢ÔŸ|ÒPC4l>_”ÆæÓÇ5´X +R?¼Í‹fý×€ vX4[y×bäôŒÆ°jT4»š +žñ¥X´âq´IGwQ2£åq½hÓdtÌ«üRíN£8DµèبhžÊðÁ%úŠŠ6—µ)5I¹O½2”a\üÈ…j + ü5Ú$ñ®ÑÎt¡õhî^–™o0‡Ë…~6 ´\h +<æM&Ú¾.”o@xLóÚ=A
Ä †áBµÐ¢£lHP»_‰c
@;ßg5Ä y±àÀw~`@HŽ»ÐT 4£ä{oaèàe¬dÅC4x<[ #Üb+L¡ïWw¡%èìË|¤"4x„àB¯œ‚Ò¥oâK1á^A (]èfÄ^H +º£GZt#¸ÐVTS.Lí`¹Ý*€’ƒõáGÜs +´ñe¥hˆsLCôè–´ÜRk_1~ ÏøÚ7Œ_ŸÛÀEì¼Âs¸Ì›õ@ëˆ>|Åu¡¿Ð®Î¼U¨ü¶O°òÀw=\2”Ö¾tê*‹FqÈŽU4 xZÒîPqbÞ¦ùÒ¶5TÓ€àÚ¥}õq"^³ËÀ¿™,€~»Y©Ú¤†¸Ê(Óo· + ?ñÀ©\MßÁi4@êút1T®SChÒ)Óͱ$é¹P4]Wþ‰zOsx +òK^»¹W»Ê" |8Óæ¶2 xîÒæ_ÉP<´”vr¡–„g|á^þÓ+=6$Ò@«¸X×° ߥ\èn´ö]6$(͸Ð`´®Aʵ”ˆà‚.t +&[xóShKZjÓ9®éBåÐÖ<%ÄÂÔXÔÁ—bÚÖ/Ë6îúKaŽîþàB¿¨;˜¼OÑÖ}Ó¶5~ ^ùiÛ~üÒß{Ï™I¡°e«ü}À€°|:®Q£ê%Žéx# ô/Åkø’ˆõç^@'ïe‡k + óU1¥’“v„—åü¨.×' jq•Û[ +Œ²
¯f(Š;øÖ…®@Ž°Àpÿ|÷‘p¡efÙ?eaOÊ(îyåB_ + È=)U›ò¡+yÀ€ T)+¬Ô•ÞeceÐ5ìÌ£‚LøÊ/{Í5Œ²w\Ç“éP%|½–½ãF‚c*Wþ5á©ÇØ™W®ü/(C™I^“O;Lcè´ +P÷Nz«xŸÃP÷ΨWNtUíD8ŽTåz4@½ö³8ŒcþGcžÌ^‡
ºã˽À-l¼Æì>¥?÷‹è•Îü9WdDq%zÈ€ðÀ_«¢¢püK¯U@¹—…3Dâ0|Ï…F—•o—Ëî 2'£ØRþ¶¯S^#Šòƒ‡³ümß\àòTí ŠÏ¤J樵 +MùgWbå_œ¨–…Tפr¡©è¥žjûz6'î÷êBOK %ìêHáÏç)xi³AAùW¹êe8áuÀ¿ôê¨?^–x(d3qË÷Ë€ RþƒzP"¢Þ©áPþƒ‡ÐÐO
xè—h˜ÚtŽÊ¶Àþå‡}&€†?ÐÞµH8†}=å‡?m@P/(ÿ‰Ž¥z‡Žåp~ò‡áyRÝž8¤žëx +T@w Ðç«Râ0ì$qìZùÏׇ°+ üçjûÆ( +=Œ)\h› + IºâÕÅ!ô.”.€&Øÿä)¿kb“k i[ùpƼ|)¬<LÛe@X5š¡ZRÈJÇŒ–Ÿ±Ø€ð.˜Íš˜×í5„ß9ËÏ>k@xg.+£?G¿»¹PY´|Ûæ^î$Ìár¡¡hz‘"êwzj¨CÉP…wt{YÚy§Â;w”ãF©dFjqÇqø^…QÍ%Î ¥x_v¡†è—[øŠQ6=þ©ðËh÷—¢]t°TaÜ| ´„U£8©Û0ÇÔ…V + ñËY°RJJIU¿Z +,Uþ7”ÿbJ…ŒF}W.¿ +"^'DËçb„åÓ_§”ÃSµ¸Uá¯"‚7g……[–~¶¨°p‚ +xžNž.ªXV•Ã£Þô efŲ/J vXSåÇ×ÚNî[TñQVÿ]ñìÚ¹PɪX±‡A¥½bºŠ÷“à¡ŒU8ðôŸP5}î긎oΊÕÎ@5.ÒÆúêk¨© +Ý.TÅ€à1¯X—«[QÅR×ìÆSP÷N§¥çå{uÃlmT¬w‘ +Ã.Ò.Ô®8+$¹î‹ë•žÀB¬R³i„OpPx
ýS ¡Ï
ÿR"•]Hê?Ñ•{
ÏøeSSS‰øjìkh¦ +.Kå~ÜÝÏ;æ¾R†:*€FÔ‚•JnaO{åÑÇÊñÊó{ñ²$¼Ú§PW©<ÿ™’¡ôAl˜†ƒ®Ñ
ÓôAs%º¨“ÞX¢–Ò-@vÓª½9aµ6ýÃÇÐ窀sÔ=…'3ýóîèÖŸ E;šÀþé_¼"€Föç«,F*~¼JùŽá¿ntež÷˜»{Îežñß›±è‰yY ð ¤ÿ@ãt<«qXú΀àAHŸÂukÉÈ
[²ŸÓ§´—@*ž‘6àÓ§| €feh§U ÁUQÒgU@Q6'îV±DX§$Jºô‚V,zT
F¼}Z ç\¡¨%o#}ÁX´ø{>”›´lºÅ? + ¥¥ô{¹WðJ_š&€–Wå‹š²n¢8€$}y
T8È0'¡ +™^ø +Ćâ°Ê™îÅ KúhF™)ç\KŽ¯À|C3PêiŽªÇX‚‚3Êö@•9ÝËX¶TŒÈ¨<_ +¢U â.c.4A +]ÇéÊâ^âm2j—@uî`Õˆzùž-xYêÜ#€êÞÆWÌ^w-£nG”«ºm‡½ + ÇŸäÉt…j0Œ33ï-€zVåëÕ½\#V×2zÖ@:|/äŠËSJFϺè‰BVkî'}qöÚ$€^öU +È;ЀðŒ²ZK›ÅR/:s\T +ùìá1¯ú +Wä +×°”•¨^¶© +2snßêµÿ`ÈKHÆÞµêµ' :¦D+£±g´z‹
ž–깺´“;™~YCî®FäutpÎrõÎ + ÆW©ë5”¤þ48Õ zãkÚ-Õ“9ìZr¼žŠøp&ëJ =|T{6Òv¡ƒèòÉ)C"öuúÔP¾á¿îŠs½baŸ3OCßS‹|¤¼ôì/¨ÞâtÝ¥…\©Ã®Êê×]!€n›®…˜w,Ð,tWR+4AP.AC—K –ú¢v•KbNõ»®@#©ÃéUÿ‡ËÒ1f@øzè VÚ•ÁU£ê=-€ºqqJ‚‰Z:6Wïö’Á1e%Ôã•×íȵ TÉJd ËVεøž05´F +é{1åÏ=½_aÕˆ.j‹‚œõôq“ùNêÄ–ÞÏYïœ@ï5L9:bQŸj¤¡‹ÐDZ’E¡¶]ðñ£„§`:gõF¨¨„?7½ZÉPáøŒ”Qì|©1|™ +¨¹éb´UÍ“W”ËŸZ§¡|´WÝœîUæ^ÖIì8«¹wá?X'uÌÝK{µkÌ3 (jNãeq¨ÌVhj®(€þ~Jð^wUÇò¹¿Ÿ@E*ßœ +îÒçðde´²KMcá5ÀÀ6Ù¥f‡°ž™¦ºmÇÜ#žt…¯jVÂQ&Ùåîgž\B¾B²¥ú§ +´”ÀÊ®XC + vØì¦}¾Æ3jm@ø¯{`*»L(×’þý@¾áýÔém†‚^Î'^àNƒÐ?ë²±ì𶆾ÙÿÌ@Y÷
SX?N÷Ë~Ì@óndu-Œ"©xàón5 x8yµ£FFX§ä=d@ø—ê N‚¢ø*4üLmÓêȵq@R á.Ô˜«3xÏ’Thœo@ø—šÝvnÓ-iÛfPTíJ_¢àðz
D£¨5GÇ{g,5Ÿ3 xn~D_ÔÞ…!pswt‡2q)Õ€’áAÜÑF +Gqè@ ïè•æ)GG$â‹úæϽ@oT`!§‚´ÿß-¨¡tÔoÖ¤÷†Þo +Å©P·Âhà¥d…“®ic‰°<"€Þ]ÇW>u +~$òú‘ÏÚ:ðk +~|E +…â°VÓ‡ÐK•ó… +Tû[¶¥1´N +'öÕ]ÓО'ª6ké°[;g‘¥®Dì2©³„ï–ÿQ¿ vŽ’™I2&ƒ–ÀÒÚ9+ŠPL>-µsV¦„møäT;g5Ÿ;ªùÅ2³vΚsG*ÃÙµsÖ¦´è„?çFŽkÄÒÀi'À_ªõ&C1/sOAwPžªŠB^ÈD4‚£»jçí5 ¨ŒÖ¾ð*µ}½ZK~Û¨}ᵨ±r}G\
õ5ð‹DíÆGnvêž`käÚºÙ)CøH5znSì7†>’@Ÿ±Nço›Ýµ›}e@x„·Ô{‹×Þ²ÀáÝ(¡œèTÄUþ-ç.ñ• +zS +Í›Ð{§Ú'wm)|½_Ê€ð}7¸YÊC“ŒÄq¨\íÁa4ŒKf« +±Ø¨=l³a1ú“”’s,½Ukþ¢8dÙ™ßÁ›Žj0Zütµ¿U2T§õ]¬Öº‡Ó b;NëûP×zÓ¹·FßœuºÞc@pÔéÞ?u½Fl;êt[qo0‚¢aœžU§ûP‚ÞÚ:½K§6åàÁY§wYôjc¾ã”…‰…XW› + þKRÊC"h‰ª¬Ó¥áe ¤oÌóXâ¢ëxÇ€ð_7xK@{ÿé] + +Œ:ƒw ¡^ïJ³DRÕúTq[u>>/u):!ß ÖPô¥ +EQ–µ:_•@“tP‹ãÅdAïÉe*4u¦^pÎö7
ÒPÂk7?Â#éÅhâý4?&€V¼Ä~/] +ûë¬xÅ€ð<¾AVŠ¡Ážö:«Û 5=Ùœ¤5Û‘ZÓ»8„ýOu +있Qó,l’Ô)¬#€ÖW“éÕ2ñuˆÓдï2m©Ç#ÞOûZ cüVæõ¹±tÕ¬sl¤ + þ\Y#LEìl +rÿ ụÿV6“è˜[Jcæöß%€ÞlÐáVaŽ„†®@¯çe¡ +4D—pU¨ƒä¼!ÕÏÓGmµ +¢ ox8ó>º] +nÞ%h¥*_–y…Óq@Rý• tº»¬®á‹&pá…ú§{œ§~È׆;§ Á…ÃP“×øÜQ¸¥›mƒ&ýPð^uî¨z8ŽÏ]ƒà(<…îN'…æÁ‡§—5|þF>œ¥k©dÞðù[Ðk{RêZ4ǯn
_Ûo@PkÔÞ+Ââ)ÛtØá4jÿ€ +÷õ9ÑÓzK +“rðãF¾$€Æ/Ëw¤¢88œ>~…AŸ3}²7¢ÔÖeÅqÍrúä7дÍ!uE@M[¡©>í 4Wöi zwBHŸÓ üë§|«'l2×ÒW@K®eS;J¢±ô%eЊìºÅ#¶m謑¾b° + ƒ3|aÇ,\ß’~pŽ +¨ü‘Чµ|aOÃÐè˜çv§è«8 +©òÇ”@^b)uª§æs†Ç
Õ ¨ÍË÷ˆ2FÑÅZªüwS5ÊÌò?¾œ§^#†^•å|M +|ÎÛ+¶× (Ÿ*”Ékã +.C‹0TTƒà·«pãs!uEà¨2èpã(½;–ˆ;(.f…ôž-Ö +½›@ªàŠ™5V¨ø‡ +{I-”AcàµE…ð
‹éæ–¤m(î¨é)€j{“½Qd1lþW¨]O +0ñôÛ£AÐÂÈØ€—€„}` +?n`c
‚–XÆ ½¬€l×h3@o ῨÅt´¡omÆð?4¿øÃýcNŸŸà‡'k>Ács•ëæ~¨€2Æn”@žn¡æl±àÀL½+€&táâvWÁ¡ïŒ =ÐÄ8«¸óò œÚ”11)€fñ•¸[,èÝ¥ Ýhö;!u]1¥agÌ> ÝsÖ°è‰R¤Ãð¸9ë$WÐRÐ3ØCH=n³áŸEHb݉*ºJƒ %–1ÿ:>4š&0Á’_|þ
„Ý"UŽ¥„Ã;-ªAX·,.ç}ê¯t˜TÐmH ÒHXÃ¥LÆò£„FvY>æ ºò7¼xöMhM5O$)o8kj õƒ9à¦ò”âúa„݆qêHEHµàc¾a’ +Â'xW
v“,ꊂ¯R2vÕÉa‡+c×»T 1r6 +zO +©@,×ÁÃYñåm„ó@½| +(úVPCtгlJ2BNÔ üë>îoߤmð9+|B +š-€Š·á 97vÝ2‹·× ,ŠŸðC)ÛÊ,þAY\` +X:!(èW
Âéò†ì’P–²…¯3/o"<ËÞr[$KpùT"ä}Jg°S8è™Y¢Œ + ²%}a‰Ìÿ̲¥4/fÙOØh§$‹(nö—Yö˜úB=ŽZ`á$©Ì²_kþK7Ï©P¥óQp9MæÍsP¹†yK`j¼Y®±A!ó–9Ê1u\oC«ÕÌ[æ ÛZó‹'ÌÅ3oË@é¿û/îì˧ÿ©AØx(ÿ¥ï’Ä¢S;³ü ”y3Θ³1ƒ*˼E +ȼkž +,
é1™c3ЄñJ•Q ÀàpM˜$€&¶y!8*KÂÄ{%P[å:&r0eNì ¼Ûn +.%/o߉Û4ï§I^v—;%Ð6Ü·dNZ+€¦,ä§dWÃدÌ)K5ûé*¿€>†qV@æôÛ5j„Ê-ïó¬d$…ï[*·l§AðÅ+·¾Ñß¾±h©ÊË ¬
ù6¡©Oå¬MèyO‘ñœâ“ÆШËãl®…Í3Š*wyJ +ìGƒÍÜùqkn•@B*› +'pêeå5]5ï‚u)SÛuKð_·Eƒð߬šiQVÀYVÐWhËGƱHÅâ0Nå-ÇÐÖý¼éî¼WhÓUÞzP +ÎÒ¥´ÙX±;®h,€®šë 1z\4‰C&w\µ@ +Q0TµÈÞ* ®„ÖU‹L@—¿ï+ ˜Â7ËU/?$€J`Ó(F—s8Áj©Õ(£ +/›Šs²ªf„PÛÛÙ¬¥ôD×ÜTm[±`(|——ÓžŒºíðð £ð]ÕóCØV ÷/=ñiXAù?¡l±Æܸ'þ,á†"S&+¥¡V«pÓE¦Ì@SÛ°Àˆ˜ÕFdj4/¯Ù_2’§ l
‚æZdÙ<6ÂTjB‘e‹òC†uZ›â€µN1”‰DÖÖÐ üëžyËT—äl:¼˜Ï@»¹¥?¥€ÅWü¸Ý‡4/æ«%Ùð£²È(Þ¾‘WKi´0"o{¹FTj¥p+žÈÛã5ÊñÈ×gB*a’Šcñ;}}N + NìºQ¥³œx:õÓ ¼N]ßô¥3D±h~\×wPO¯N1Ê3 +´]VÐR
‚«}òɼŴXfÚ'ŸÖ üYÎþæm_¨5t#²ÏþU0/<ˆõ© +®A0®ïíÉL*Œ˜®â½‹ ½ÇYôÄÅã{O Sù˜SY†a(GüÀôþe!•Ê›Œ¦°RŒ¿_BƒðŠóM + © +°ñœö~ÁPjN~ñ¤[º
eAjNÝ‚¡j%Rì,Óá[+¨º +@ïd±¹¡â3¡©öN{t€íL7½Ø0Ž¡Ú?ÐÁ®ü8*€ˆá¦ˆÕö@„ó©ü@º¿øQ
‚ç®ÚgXˆÙnXúæÕŽ’@YˆÅ¨!VùÕŽw× ¼Ÿ~ò +Àmwôf_UûéNô;Ï¿‹P'(Ž‰Uû=,€þð\ÛmáÂ)ôÕþØ¡Að³T¿ø>6!©ƒs`Ô´‚ÚkÔæÕ‹daï¨|ËмzÑèXk=Ž‹ã’ÖêÅîÓ ¸ª§÷ó7]ÒŽáû–êéƒ4êàê•šyÎÛ|.ƒÌ«Ô\ +
C!ju»§áow×}ì’Ð0ACÁIõ»ÚjÜO5Ü›@:Ô60ŽBbÐM-ýƒ°“¸¯Q›î@·rÛ›0æÜî4†ú ôV¬cTX‡Û”ÔH¿W +z)dèŠRcöÞ*)j…PÙã†j¦ñˆwGµÆÃb5Óz ¬u!uÕKYið×TåYÿ'ô º(J˜G¶Õ|pŠ +ê¦Aø/övA‚Œv@Øó¦[=E +§õ×¹ýwTQõ2IRܧ}Ô©ØNƒð;EÿãÐRØ;늖@½ù 8fHÔÐ?³N¬Ÿ + ¦·°©MM[
ƒŒê4½M +4 +-€NñjãmQzç©•ù!\yU÷uNQFÜU(Xë¾ÞY +Aø/õñjÝlºœsÞžà}ê ã}Uf¼%i0b¢ +ÄFÆæl
6î× (}lñ{O8ØÆ—W
¶¬Ö ¼ŸžHxÁ—°ÛªÎ<‘Ò h‰5xâ8+ÅmÆiðÄ—hǧî‹S.r|8w@o^Î|R,¼YRƒð·;¤æm8G<ÇŠºÁ¡ÐŒœ£YƒÖI5Üä½xÊ->3‡n*¥Að7|¾AÈOŠ`>ßD +ÿÇ[…ˆšÞßuÑEmº».åñÎA Ú3x8ïºôTòw^ËUp î*ù— +‚BÓØ%¡2ù8ã4 +ÍÖ x•¹Á3Üi1†!ÃÊÜ,€Òׇüô½HÀuã%HLy¥uÔ$Š.1áVi”þ“ +zK +k”MžõÖÉmk³°M×äÙwÐë¯óе…as“×ßÖ ¸}›^YG4ÔÚ/AÓ+ë 3kB\p±‰uÓ3†î¾õ‚2ÿ©t{Šwß–¦Ap î®ïuþIÐUŠÉ¿»»~B +¦"†¶ðÍêO@žáíë]€Ào׬ѳ¨é=Ê4¢1MøÜ5kÚJ + ÷’Ï + êq4lÂàpeØ(¾æà‹;§e8%€f¶åcNíH-ìNfÍì AxÅçðÍ5*Ö„‡3kÎ`
‚‚5kÁv¸h”†!’µà#”³$/<AÎ)|ñœlô¸wMŸŠPR°¡ÅqÖöê¼NQ·^§íuÐÎ-¾Ìt<3AÎÚù”Ἣ"¯Õ°f^eíª¬Ax1w?¡ìL*ÔľTÖî„ÿÒËË=éëØadB!–õr¶A!–õŠRù–!Ç{e« +jAp·ÏùÕ9æ®ÞiŸó§ +g0¶ßAxÅߊ*#Ëù¾ ³oÿVJ +p;“AK¬ýþ•uKûCoð¦£Å4\9µ?ô¶ +lB¶ÿó +
‹ù׃¬£”ù»Ç´ÿk ÁƒÐá%Õ€æpÅ°8ìðRUôÉvàcTáÑŸL—@ª±^„2ñ¥L‡OÎh\§ŸäŤý’À™ž>;¬AÐVép²mžÑn'p§ÃÉ„×éTKVùt#Ǫ¬Ã©¶ù!8ëðÝ¥òI(bÐá»\tº/&õ,µqÿ‚§³4 +±´bG•bøuÜ[0ԱР+ +éü¸8¹%8ãìþ +•4®Óý‹óÎ]ÊŠá,Ýû.êÔw=‡'Ü,]ìÀwêû˜ +†:ßåõD·¨›cÄÑÑù®¾Etç»ãÑ‹[Ø4ê|w5”«êÌ +t½Lch· +ŒÎ;'æƒ"8K·ó«CØÅ¥Š0CGåί@oܨI8¿ÓåÐÇmÙÅR€Ø°˜w@ǹˆØÍf˜µ +z] +Ú#€.¨^p–{O +Ú£Ap?õ(Ʀ‘ÛYÃÂÛ·G±4 +Ö7]æv"â!ø´ô¸)¤Aøq_y¾õJ‹Ø1úîñÕëù!…ìqr¦ÑõsÔÐé®Çɹè¯<ѳ’¸¾¥Ç_— s7°J¸}Ñ¡Ììqî¦üV@=.ìö9~Ðuëqáå‚¡ž—,U¦¶{5÷SÏKViÜO=‹vñ)êˆ!a²gѨä2ÏÅu¨{åÇ•\¡Aø×]Q4¤Òâaä…žW\––XÏë¯c3„„†!8ÜóúÐmE|ç&4?â¿íR
‚ú®çmÞP×gË᤻ž·@™êJÜ¢~€8èÙ3óQ
‚{¼§Õ‰Õ†M݈pÂdO«» +†z¬Â¦6õ…ŒâyÔ½VF†z_¶—MmËí¬…XïËö Sj +bÌ
ã@ÑÓûT\ƒ Òû7¯Ð‹4†#êq²FïßÖ ókCê¢(6ÄzzŸ__0Ô§hY%zÈYÆKЧèM·oŸkÚòg¡Ø~§Íö¹¦½ +
‚ß®oý7}¥Ž*´_ + ÅÞˆ-J0OÒL6@Ù×òãÈ95Äzúf—@kÔ¸˜ujÁ—
}׌@k_QKàÎ5†á‰¾k_@9^ÝkÜígŸÄ&dßœdøK^SDê©àNƒ[%ç¹üÎÏì»ù›ÿÉ¥@'°ïæóh›|ì(i+Ð BA7 =;X…Ýþ™øïùŸá=þê<= 7¿ø«†úM{×3Ú©Ì6fc—¤ß´Ch¡w›”¤~öC™H¿…Ðê˜Ó«Âý^(©Að÷Ûÿ;¦ÔÄà’ôÛÿ™ +Èëcƒy–8.€ª®áTZhèÝõàÁkЯŸ{B,ì +
,züõk
‚ŸåÁë<D7´4\¾ø…
CýÝͦ¶;5çÖö/Ô\ƒà;õ/|eHÑ“‘€‘Ås³qò ¸ú_ö2üa˜ a(úM¾#•Ä×ôý£? ºÿùÎr"fãt†þõ +K å9G!j˜&Ò¿ÞýhˆR¯îD/¸éúצAPúö¯7‹— EÛÇUú×›'óg¡‹ÃØŠþõŽ + ú7²è¡))l´÷¯‹A¨ýê¾ÑîœNœRØ¿~- Ô†@*¸Oâ4¢þõÛk>RõáB‰ïà°Z‚)¨A»J¡·mC3ˆþ
: {2Ùx ð’…Óúßs‡ +2†ô½AÍFh”*ƒöÌõ5%šCa?hÏ¢‚¡Á¥§²À q†0ÎàÒ³PÕ6l®ÑäØ0öïWm¯ApgŽ=REz±°…oIÇ^@ •€›p“ábN¬@µ”M³-e¶ƒký Aø×Õ®¯†#X
-³×¾K + )ÜŒÔÈLZPÐÄwÁ¬ž¹Fýìƒ%cüâ³F •ï…8G~ N&¼ò +l:}%€Ööå%p¨8T9dí +Œ¿Nc¨ª +¥ò‡Å±úU¶A-5ô«”¢¦ƒnxñ?Ê
+šÉÛ—Z5®-† zŸxÂ>ê~ßÿÿZ•Wï3Ôø2%¢£Ž8Än÷°Æ%4®Ó°æª—.:RØxÖüú‚¡áe^˷鳜Š0ô¦Áí;¼;\”RHe÷ú] +Ú—)¨ÁÅõÌZ›.x¨†nÒ èK
¯Å0ç:¬ã¿T«½ + iX)Rª†…CK#¦-Îá|•ÓÛ²*£y¨I1½£ + O±¹Fͦɉ +úN +Ejƒz†Ä‘»; WûzŸ%Jel \2òÕ5ÿ¥+EM%5Ø.ùñ%÷øÈO/óÀdÔP88òÓè›—•¢vTuæŒüæµüÎëù}Ve ñ|ßLƒ Fxøê£üY(½8w¨ c¨A†ï&E# ,n©APŽ?|ÏÜ<Áê,§š_04êŽqüY"î4q¸˜£î˜¬APˆŠÜBK·9†ZhüÀ£¬Q¾³ìÆ*ÑbŽ²Æ + V^àHÔ3k¡nÕ*)€º©>4n#4|÷:ªÛ4ã7VÔ©ˆí{¼N3þÐ hÙâÌa*…"Åh€~)Ýîu‡ÔÂÁÐxt»7P—6ldÅ(°MÈÑ]Ú n×*'0’°.Éène4îñÑCïäÃIåȆ£‡Þ%€†5f7a¾~=ìn4â„ÿâqËôYF|£Ap«ŒÇ…^t,Ã1=î-
‚ÒwôLo¶½{ÊJ`ãaô̈/×)¤5䌎ž¹Eƒ ,=÷%ŠG(h¯ +ÃV©¹]ƒðŠÙÝwàc¶áîuì—hþ,xŠ:Fê%ˆü¸ƒ†Æ¥}ïAnºzÇUÆ¥ý$€.ª¢œeºÁ©—ã. +k‡ã..Æ¡ +-JÜŠBß +J× üN=3„.Šì˜adÛ¸Îo䇲 kOßÈJS/ùq]{k~§nçóÔk,P>ª ÿPn_æ6·
”Üó‹÷_”2œàÞ$=Gº¦>Rž@3X`8¯œH¡ L4z·’¦ñ×ãFï@3¿Q!“e9B4næ÷h6Ê»M”l¤7{LÁÐø–¯²èˆú`óí4†ö + ®ùpºó=ð
×ø®÷ ^Þ='9%Q;p¡Æëõ™Á]0~‡O)é.8Œ™7lŒ +nß©Ö3(5–ƒ +n¯UÜxajj¼áÏRý~]§ÅpìpjõŸP-oÚ‘‹‚Oõ¤ +6óãvÑ (X§íšž'Ä"IìNNÛ5Kƒð:½x
»nqw°(^§¯@/Ý«98†òR
ÂK°/C-AÄŽÅp’Ô´}™CÓ'q©—uŒ,ø¸é“ž@38,Hm”,C'Îé3 y¿r(ÀM{Çr|ú¼?5¿Ó²ÒyÎrpûòã–•@k·óA ØY é=?níó(ç-9ŽMÌ Ê¦çü €žö¦®Ä©Ys¬àŸþôe÷øôíÝ}ÃÏÙ¼X>MßÞSƒð~ÚË™žî°ø@(@AWk~Ü73/öÜpAÜô›òC¸ûÞô÷ᜠ¤`<œrúûSÐ^Òù€îµ|Ü×iþu¨ný j1ƒ‡é4@¯bÃÏrÖà#õñZt|Wˆ/©6_¦I +ºY©ø8µ2„¦¿\ + slŒRÃs+0š…—àÜœ‚¡Ez„ÔˆeÒ°gé¥AP`Ì(:%¿Â¡¥Eg kx*?F΄!?sƵP™ÿâ Ë éf”)“Â’nÆ5'.U
¹µ34@ÇlþÀQw ~ñcI
‚ºeÆÏÞ݆å¦ZúÏøùetÚÍTˆ¸¡açãÏrz‰AÍ9ãÕ7ÄŽºÉ(ðq¿4Ó ¨ïfœóR +Ãîb®çÞ@ç½FCny»ièâŒóå +†f^4?‹M8¬€f^ôˆÁ_7³Ä‹žz¥;Έ¡½âÌ{4žà™W«+LhlH’šyõy
‚»`æµ³*KP»sì˜Î¼öl~ÇŸf^ë¥}Dxì†B…%Ðì˜Z”œˆÝ¤™¡è„/¢“á@q¬‚N凰,˜Yfo:2!#%ùÅˬ@7žçL·Æ†ñ²3½Ë† ›øÅÝt+Ã5ýÌ›¾× ¼{y£–7aÃUïÌŠ}Pæ_Q!j I¹‚ÎhŒdͬ«ÚÞDÝ~üëê~!€š_ém_g«€Næü¸æWÍjÕJ 1j}ƒS›fµºWƒ °ŸuoçJ›µ$3Ϻ·› +ˆRÀî伆Q
ÂëÔ8¬8º4VPa ´G„(÷[bóï@M2øÅÝF›80¯IeÔ"Ň“†¼ÌkQS +NSÐN4ñ'þ,žwÏÝü‰¿ i³tÎ] ¿ +/Á´ÑhæJ¶Ÿânc2¨æÏ|Tƒ Rœ¿Buyv«$p~ÁüPŽÅç.éùÔJ + Üå¬ïè.ß0Çt~n¶ +ˆ*'
ÙñÎl—@ÞpÊT$îÆìñ.8ó²á?{Ž½|rª±h~ÜÙ-Œ…—y5¦Üq–…—@—àÃéÆ~ñ¹[xùèz¯Ë35¿MÆñÌ…×7@e;ñÎL±†?ð²]4ÿº²_+ÓÈÍd…aaÙS(£GÈ77ä.ÌÈ@á¼ËPÛÔaa$Mƒà‘Zh]Ï~p„ú«àÆBë&tçüºGHg^ñܹ0?„-Œ…õ¦°ñ`Gá@+?®Þô‚¡E×qOtšÕk'q^Ï¢ëÞ@7åUd“SÝ¢›Îá+ñE·ªû‹Ü|Õ^të€ü6ÝÁÓÛ£T9g(Ž]tÇ$dmVŸ…&Ÿaƒf‘µE +*à„¤ÅÃß@”ÌŒºgÈ‹',Ô ès.žÚ“ +ãTÙ⩽5ªÅ³nõvŠ³âÅœu»á_ù ·}£aºKÂ.Éâ•P¶šJN÷Á†Xôâ죄ÿÒ‹^ +
õ½Å¤ª9+•âÒ
wi<œK7tõ?©Ex¤–nè¡Ap–ó;FPŠ&þKËŠÕÔ ü—®lÃJÑ¢1µ8óeÙ•íPÙݾáç¨ ,–•}YƒàŠ/»MÇ:ûÎ2ŒØZvÛßù!l.ÏRn]cã,“eáyÈŠ³¢¦+C²ë2«š + –ï,Ç. +(ˆn[1yXYò;t7Ñ+åÖK*CW^SZƒð:U¨Î¢‡.üM‹Y¡¦ + Ö³ìV[àBùUÏj>œí¸dÌÖHåUÐW¨g
Ve1 +žb•¿ªg-
‚Þ몎ñ¤(Í'nzàs4ð³<a.eV
ü\ + þ9,Ĩ÷D '/Aÿõ„ÏÝ@Þt$ìƒ ü¸Õ4Ô[‚údáúì‡ú Aó”¢Ã¾Tö ÍhØÿ|×-aÄ¡‚v ‘KC*ÄÙxa?r¹ +XÌ +\<òbxS +=ÍÇœºÊEðŠ¯)ô¬á¿tçaP(Àã`Þšë ÛT§–d”"ŒÐb]s[Uå”BÇfOÙU¦ &¨VÌw¸¢á@gWÅ5šFkîä¦÷nÛC×Ë5w–@›ð¦ó:qB±f`3ô¹è¨Ö¨!tÍç}†ÖVŸÍ&dÔÍMƒ[[}® +ˆÞ>aøvŸÖ øír"^W^÷6Å +4Nch +¢Z¬òs¾~Rƒ `Í9ý oŒ¦"D=”Â~KÎ/Þ&ÉŠ˜©é}Î/[Ðoj35s cÓ(ç·NèŽaDÜ\^Ããþh"€þö*×i®ªMWõš$€Î}¡Ä!…«qø4çÜ×è¼J|w +˜ô• + ž&B—Æv,ŽBëw7× ,0öýRéÅŽcŠ[‚¬ß÷ +'€n¬ÌƒÚ¼FMóbÞx‡ +è±´W5ú–“8ŠÒÓú^ +QhSZˆ6¥Ÿ´Š•¥”¤TJ%û:öm,#Û0vÃ`c_‡™±ÿ>çó9ïÏ|ß÷óz_§îí¯çãûþÌ{9ïsÎû,l&YÎ× Cè3N#£;jh‰4ì³Ö¨·Û^6DåBaìªÖ» +
7tDöó/µÃaCÜŒQŠ +5’@Ã^çcîØIØ6ì- ô•wÑ›1ž‚a}S!,†
›ÅÊC,”4y!‡
›+€Fö¶âŽõ§a£Ö + ´lâR*¹Á¥;,mŽâxJŽMÐáTÈ0O×z“™¤ò‘ºN +–õ¥RþI' o•¬#„xmEåž°Ïy;ö‡½Lƒð7í„X(öÕ…äÉ\ûµ + ãÓصäxì
Ðñ™ç††—šÃ¼½U(¾Có5ÿRinI…‚†ÆXÃK?+€.8PWQË7\)†ŠÐ‚¯DØ)}'€2ª(uÍ–s†.Ã3hñåf™Ò؆/þX +F\ÔM +
÷…}”bèVtm{6à)s?‚ÅáÈk_@ñŬB:éKX…_ªAxžê©È<Ûà¢}$€LS¼½,†¦‘N@ÍP“Iå„qÄÙȇf ¦Uª E(zF6*€Ú”ã'-CÃñ‘m"¨Ó»0D[ãa_‘Mµ× ü×µ}UH +üᘇ‘m;i^»ç¹s‡Sp7ˆ]K#Ÿ özÛ7Bí0t@ƒàm>ò•w*xšj*@gä+ï 7&±!³•ö°aYÞ˜.€:¹±k R¢†R«#;@rÏ'<Žíà‘~¯Axízfñ¥HÎ._;®çj
ÂóôE-umP%,¢G~q +BVGtŒì]^ƒ¿Ä!;Nc‡ºÙû]Ôw•2$(X—NÙwAëuä·¹ÇÜID5!Œüö_è7Õ·;éô"ÃËòÛôçu¬BRðOØópÞ €6pB\Ð)‚ŸœFn¸5®¥Q—\ÊÆM‚ß±wmÔ%—§@>¿ +C/~P qIӳŨ¿@/åɤGU_ÚøK…èö®Qé^ÛÄÁSðÊÑT+££^oɪ6%-øŽøëO ®Ü‰Êrù/E®kTƒàzWu`JPCü:êÝÛ4÷1ÇЃ?5ÄÐ)ÔÃíô Å‘ˆ¯Y—‚ + >16–)AËPtlTŸ¤áp’•[µáV£œ@ù€ŽSš ‰=Y£†—@#~WêZȾ5°™4jÄ_hÌT%ì©K©aYÆÌÐ x)ŽÛÞûLÅ£¾‚'<ÜØWÐ8Σ¦àĈ¡8Û¨qÐÄ’í·á£&†5ïñ‰÷°°'Þ÷hÌ>ñ>4õQv-Q`“Áà5õ14Ÿæ¨e©Yרy]Ђ’Bh””oóQr5OfÆH¾^I§õ«áá2ÆjÔzF-É*v‡[²F +¢´À8pkTN#
¾-WN +ÿÁÆͨmÛÐN•ÃE.tC†Ú¨a´ëµ€ +NŒ…
íFízC +ºJƒð<µRËâ´>À.“±žÑ (Æ>§’CÎ-Þ*Ï}-€Þº6 Ü’AŸaª ëP— qs`éØ.áTçºý°%o:z +h°pâà¸îïi\»qŸ»/ËŽ.bH÷y'ôÊVµÿñYŠ¥zI +±p +¾û¯
^–·î@]~ñ*(Œ‡ëò» +˜øI[4°¥çT°…Aô|R +¨çB +y†žöŸ¨áozè 7™±¡ÄqÚCè·LŒB,C/Ì´î@/¹žv'!hp-¥½T^ +[†p«´·Ž wØ6§RËÐ)í‹Ð»x¸$•vÂ)>iï^,€>¸ÆŽšQ 9†ê sD4v0¦}ÿ„ +¼ÃiI8œar¨š + +®fÃ4ê<ƒÁ‹zÊ×jž§jÓø*£SîKfäáªÍ@5ÝôQ{¿ÙÂÕðP4¥æ¿P]VF©}IÄ-8¥î‹
‰)7¬T-2ø˜O¹aÁ=>%6€U#r3‡±ŸnJì'
‚ZÏ”;¸%…)Sai8ÜKÐ}ϱ +™pâ”ñÜ÷b*„èSêuå«,r:̯÷¾ú……˜sªpÑ”z¿ wóA ƒ+ŽÕÚ)
î× (}§4P‰ò¶I‚ŸÄ§4!€-iÇ`‚Øe2åÑ+4Šè)s¥»pÒi!†—åñ¨•»UÈù‹úŠ”ó‡·Z&€^òDSb$~Þ™ÂEX„7]ûå|"Ôn—ÆœÒ~¥ + ªi5oŒbµvêÈR%ÝÔ1®ÀpÛ1øŠÕ(¨P +òÔ LUÈ#ä4øÀSÙZ +µÖwÈ~°™A3iz™Gé=”I?¼ + 3»Ôö¥P9ìØŸ~f﹡ç©[Ñû\•ešªApÆg”¾Z¹–h™±ò0£t
‚WÙŒêxf7ýÿÒuPåk¼N˜*'Ψ|zÌUh"NC_låϨÜJ + ë¾q‡£()Y.õ@Á{½#ò—â¬'€B—ó¦³lÒPÄnF( €"ù,“¸…Ó"gDv X?o¸Ãnæ±ïÐ7”[0ö?RÐè¡€ÙÛ?Ïx¨º +a¥}æÝ_ {Æyf¦ð˜Ï¼g‚Aõf½+y«P«é .©6³^5
‚‡sfƒ¦ÏÝeùB +y¸jžÌ‡¾óØ> XØÏ|è
ÂóÔd3»Lȱd0“f6ÉÕ ¨EÏ|TIJ8ñµ"ã)xt²áÉ|–û’Ø¢05”,šùl® +G’Y0äi
Âóôç‹žâg«Xøšùg{ô÷þÑcJ5˜ù÷a4v5O=dqºß̱ëЕh…íí‹•¬™K× ¨Î\é.K‚RîýI|VZç†f
(«Ü8´.8ÄbÖ€òÏݬd9æ4ëÂÃýøK*„#ögýšÇ¼jSñ*í@Üf€gÄ +c‡õ¬ßvk\»Y¿ÿÀÃÅ(8§BÍú} +½É$C ês*œ@•¿VÃ9µê/€.Ë(¹òýE¥y +.ûGƒ j4§ÊÃJ¥º>ø‘oN•f¨ª› +¯×¹ý ¡ÜqÒÛ)‚C;4 +û¹#¥˜I6IæŽüUƒð7ÍÏâeIPªbsç¯@Ërø˜S¹)CÓŹ˶ + ¬ì€JlŽX¾ó<\Öf´]5÷&çKÌ°Ÿ¶¿¯Ax?íãrÂŽK××¼DA“Ðár)“é{WP
ÂßTx75/1ÔŽŸ[xLƒ ª=÷ähoÓQa|NŽ× ¸}çUr51ûP ;üJ2¯R‘Á]0oéó•Ìµ|´¥j/€ŠrJSSëƒyE[5^eóNÊÛ×IÃVÙ¼Ó=Ï
ͯéFœ…Ü3Ø!4ŸSZÿ7ÔLe«†C R´àpÍ^Ô ¸Uæ·~ˬ!º£ø•d~ë.ÏÝü~n™\Ë6¹éQnºùý>7´ 6w¤r !CÈó‚ÚÏi”™nqC’Ná9CŠÏ‚[6 XZ@9΂¦rxbSÐw³ºfÎpoßwÞ+€êýê
G% TYPï7Tßk;LDcø/¨_(€öf7êT¨ÀÜðëT[ùžr» ºQï ìîZðT 4< BT; CcP;wHGÓð¼ ]OÔ>=ED'SÐ~žáƒðòqvD)Åû¼|J +•³‚©ÖÒÂrP +üáŠb¾kT@¡n•ôIJ2ž‚Ð'hÅ׬ŒÆ)™‡Ð/\ñÁµ[¸òþð‘àçç…+?@ëkz®€HØ U®¿6ÂReaÎeîáSáOƒZ»0§Š +6“q4Cد²¨á=,ĨèM›I‹Þ¯Ax2 +«MLZaü¸è¡¨á]ðеéœv{ð¢^ôÐAÔLµ"s\yØæ\ÔìA
“ÙZu8¡°R_ñH^–Ö– +zK +h”ã‹Ï¨„T|ÛÂO½‹Ï<}nhÉWA¦ÇBRü °_²àI
‚Nª%«]©â¶(õÙ +š+€Ö¶fs2F¥x°º¶dí“÷Ó’JÚ +²/MA‹ÐÎÖ¼U‚t™aÇÙ’O ½³=u͉U†S°w® +Z'€ŠŽ±èqbKŠN “n}:'4ì³[TW +¶6–Öj +akci!%Ã…
"zi¿PÜ+BnøZ + „«´ÇO³Ï£ ½ç†–EÜ4¶„S˜ËÂaYd£AnÙÜrÄ©Äohgµìb
‚WÙ²†{!f[Ip2—5lAp,{…K;9Mƒb8´iÙ+?jþ¦þ*k.²Õmì¡YÖÿ^
‚wpf{U†Ú\”öÌöG5ZŠ™oŽåíKAf¾9A +SaCŠOæž'Ðñž£ÃžNüx•y|÷¹¡ååÝŽ:…<IËË·@ÕöT1*KõÌåÕ + Éí•8´¯×N>[>ù4µ"7–ÂE˧þKƒàAXž>BËŽkŠÃåécЂ“ž +Iíðp¥Ð?ù¢N8)cP`,ÿç
‚WþòE®^“ò`pã,_4R + eùžºf‘ð¾l· +ᘇ>ÎËB%
WþŠ[ ‹T;PçîÀWþŠ‹ÒпÚ{†)Eõ[ñ¯WЕª¨4½4’ôV\¹[ +²Ó´Ïø'U5ÎxV|8NAK(X³jü¬ApdÕ˜ä Vê +=Ðƃš}V¢œá¿.y‹hw•ñ‡'k¦BX³Ïºë™€ +þ¡˜BüKw=›*IeÝ¥ÒÛ©¨t?øgÝõŠ +Ê@/¹Q&IGi7Äad½”£Axg¾´‡TÜ™Ã/íÓ <O/‡yûÒm«µY/GP‡GùÚSê +VF³:<&€:zy@¶¢e¨-˜ÕqªáýôJŒ·¯EqTØe’õÊí„¥ïÇ<(B¡6*@‡1³ØPx!«óHô¶››DIUäjÆãí±¨Ë>>œ)"†ïrP +8ãÏ>¨Aø´äUʨ#2ð Î.€6ÏõAS'˜•›hѹ\!)d+£þ*ª +š£Að¾[Un>o:Ë=Xh2W•ûG +(dÇäô\5§ +:?ÂŽ³Õ5¸¢2õD
š(¬®1P + ð'žT‰[¾šÃ<œê½ó?¡Ä%üáögÊ ¯N\¦AxïïÇz&Eì'pÇæÕ÷@»1ÈÇ·µC¼vo@ͳ'Xß-«›g + 7©áìE±ûéÍ_5î§5—/ñ¤/ÕT6@™Oðš+ž`ˆì`_€R=-€jVRZù°[Só2
‚k·¦Ö#)!Mf¨n]Ñ §ª®îM/Å57´âe¡~¾|NžÌž@7~äŠhǃÇ
}×ÜØ]ƒð‡/QžŠËÃä5ÁÊ/Å5ÉBO;Œ}•ÉtB +þŠh<-k‡³ÝQ
…d×ߣAø—&Õð„˜þ>|R-tJUߣ*`öø=Ð xîÖMç(8Ê¡Ž:¥¯›þ½AGìºùcØkwbÿñpóÇ %[ÔV¡HOìWY·$W +á‹z}À= ê—IM}áp¯²õÕݾ¸Ž“*”Àâp}õÕèß·³•Ÿ çgìD_ÿï»4îñõÿVý“îD`hˆ +vÁ
»”NçØx +nØ«Aðo¸Ñm±å4t;Úpc;t“;™”ÆF%wñŒßTYƒðŒßìf<:mŒB†€n.Ô (X7G+ÿ“c)àÉŽÓ <™wñl)ǬÆÐ_„günŽ|¡&¼ACe²
wß¡AxÆïûFmÇ6‡ÒwÃ}ß ûÝÄœ¤SR-Ží–
÷?%€š¿ð’`–Aô4o¯Að6ßÐÊM‘ŽF\ß +ÞÎ@ݧ'á>hð†lhÝQ +vA!»–œ „¸AØÞ¨AÐgŸýèe|¢¶ºfˆÌË~ôJ
‚Ò7»åYb¤øšäe·*Apd·*Wòáá$Ž;Ìnu + mþpr&±ï0{[5tà+~ôá¬õd(Ö ø×mì¯b"a§
†¾Ð (U6þújŠéfh··ñ×N÷øÆßJ{†DŒJÆa¨¬ú‰'LŠ +á<Å“²XRù²$.t½qÒ
Âó4w.›$qzvĪÑƹ4Ÿ–y™¬´'(«kç@^v?Ü>R1S‘¨^Õ ¼3ªú*q§É=þë¶Ö ü×-îâ9„ì#…#ó6.îªAX®êbpJ…m\õu +äpchu]u¤¨Œ#Ú¸ú& Ô…•Ñ¤“b‰÷Óê÷$ЧJ°Ú¾á)eãꞨŸ'0ì킯׫ûkþëÖÞÅêZ‚ +‚&sí½h]E¥dÙªQ«ÿ×U@[j3D-ocØq¶qK ô¡7™I+Š/·tÓ |òš°°'uÛÂ/ðóš§BøFØtÞYÏòg91Tº´ +ê AxY*¨ä}Ê"À§¥òïȤò¡‰¨¡Õô¦Êk%÷ +Ú¤AxÆ«ßê-°}‘a…fSõ + Z¥ÙìN†âÑ$N +ȹao:r-E± +™sÃ,tË:%É‹_¸rnÙ(€‚é’Tr?åç ;J®2jyeAÎ[4Ÿ–;]Õ(á”
ôE¾ðpw^“ +dÁÝAÏ€[†«,çî° + ÆÓNnA{÷âyj¼C +ùú½ò?ú€ + ·ï¨B‰°!D5çí»P׺ÊùB˱9™ÓõfÔgrOØ›ÎPj5§Oö¹¡ÍÍÆñdÙÆ…Ÿw67K@-ÞákÃQÚ±aº¹Å{è~t5Åñ¹Ûü̃ÈÝãŽ<¤'L8™›_n,€:°[¼ì!CY®Í¾@±2JoW1¬<lþà„ +rËüÌ“i[ACYÓÜ2¿ ²kY/°(M{ürËn@å\MÌ„N¿'øbš[îT¾ßw´}#xžrË7Ô <O]¯¶S£0ê«nÅÃU|W +Eð[~nƒ¨ +bŽÀÀ>ú˜áÉL{È[+š4¬]ÚÄ¿i2wú$‡<½.cèy4˵äTBbkóf…ÐüyÉ4¸òæÒ ¼Ÿ2T¦ŒåÄâá2ž@+¯ô” +Åß´²Ú¹¡mTË6êÃea‡Ð¶P—kÕ¥htŸ +ÉÃu¹Nƒà_··ògZT¨Û-Ûz7@}“„^pžòx +úæh\»mß¹1NGÍ¡Ëý¶ï‚„çièÃʸ¡¾ÝXúnÚTƒðdrTšËøMÃ÷ £ªV@"jè8¸mÄX4JÕT D¾¾^·j¨APôl›è¾pQ¼o2bxÝ6qƒážt‘'Ä("oºIÿ@Óoa9I*¤aY¦‡Ð7,Íéïgh·mØ&€6ÿ õÆf÷¶Í? + \Õ©Šº²œ¶å¾«Aø—v·c…†žº}uøÃww@n ¨¨%ËÔ zÛ +CD춣W + c®k)$õ8‰¯ümÇökžÌÂ7<å–ªFÛ +ßÔ |¤ŠÜä}Ê“‰ûc×x +Š’¨X•ž£Ìî n¶¸‚a©rœ»Ù’ˆŽúº´ò‡?‘ +fü¤ò<Ø +–e(+±íd
‚'x{©—®»+f7>ÑSŠ¡ö¨¬ +2·yØp·l/{B +á:YÛ+\ɡ§ñö +W ‹_ä%Å¿,o¿¸½ +@,ÅíÅ/ ã¥xYèÖª¹ýx
ÂûétM¾é2óuÌá?]ûÜÐŽÒî“ãŒb¡óeGéFè¢ïX…$áÁ!;;. €*¥ÔÃðWÖp§`Gåó4ÎøŽ+ +•ª´ÕZ,0v\q\ƒàßQµŽkHPY‚ ¡Ú쎪u%P›’íK +î9T]½KYN0+¼ÍwT%€j°k)â>ˆâ¯±_ƒðŒ×Š±jd+íö„Bù´£VRƒ ÀØqu3¾¨ƒn$+üð«[ ºÿçm[¡1l•º]5OAì)w©°=…ÁábÏ + »YD‡T+›I;8¨åCî+.Ips +Z¬AðnÉ¿ç€RmãÆÖŸÏa
‚ªvþîδÕ+{û¢OóX+€«¤<ıî›ßø
‚'8¿É쀪CcO&sÌo2O +(€Þw&“NÍ—¨A¼ÿ— +ëÅ©²±ØÙw@*„#Îvö›É¼c˜b#pg¿9„g¼?{ÃTÝ÷á<\ÿ«Ð Oøz%h(kºsPOô‹[ÂÔ+â
çá~雬üw ¨Œlû€âê1;ÿ~O +(\Ý0\•»ÐÞØt#‹2Œƒ]wíí!€öàMA0Áîø]û?Ö (ìwáò¯T×(l¨¸ëÈ×o„]…»ùzMPï,¬´ï*ܯAp?í*ú% œyÔ /KÑ`t¶'»œ6¼ØÜuö«sC»Ï/ï jO ‡Û}~
‚çnwŽî‡SêJÐÂÖÆîŠP¥*<™q + +ÆÆòîJÕ4.ðîJ9,zôàmóÝ•¶ + KÝÓX˜Ü8†.ˆ»/ý—Aa¿û27IO5÷6@gP•%!lx+Û]å” +]&€Úåðp '@ +ûÝí¶žÚS³£2IœÜHxZöÔ|UƒàßsÓ)“™Äaý{nj'€n¶Xñ’2Š+¾ï¹9.€Â×(ÓÍi§o©=áëPlðT³)ŠK‚ì‰í@q*GS`¨«½'ÞH +¢–öÔ_¦Aø¯k8Š•ËÔ²§áXôàep9aýPôìyð˜ +OÁ«WI 7•£Ã©š‡7Ý«PçIÞEŠ$±{bO穨‹×D!Dëk€Þ@]]-š’ȇ…}ׯ5ÏS×í¼}ãäØÇiÛ{ºîÔ h›ïyŸ³ÁœÞŒ üJ²çý‰„wÁ'+Ôµa¯¯¡ÂäžOV¦@qÃ}÷ù-ž2ê<Ë`(¤Axžz¹1íñ%eøJ8ðôj&€¾iÍê¿£Gbßážož@?¨^s´À¾''î‡/Ð@ÕŽž-E¥÷¬£Axž©=î™ÁNª=ƒºjÞ*¿öçMg_e~—?üׄo„áìÌs&
ïw{†ÿ¨AxgN੤ÔF,lmì™Ö ¸}÷^ö›¸Î¥iïehþ¥—6óUf_¯aCW¨½/åi\–½í¸ÿ*gèW¶·]ôŽëà ¼Ž¸¿ûƒ‚î@煮@ªè+L¬ ßPwnì@Î ÁàÚÛ} +úTƒð_·ÿŒ˜mR¡öî?#€ýÁqŽ9>‡þÖ ¼À'¯ô„=M&Þ¾'ÿAPëÙW–¸Ïœ‚}e¯@/•/¹€¨F†*hœ‚}“§{Ærد?)h¦ +©˜—eßÂ+Ð*×gq<B†7 }«îJJÖ¾M™ÊìvúâÂM·oÓ +´¥À3Éá5Ö}[ +P¾*á9'ápùå4¯Ý¡wÜA€Rô°}ß¡Ðág¼)H†
ÅEö~Nƒð<qŸæ"ŽËÚ´ÀGú ÂŒ€ +/&*Yû + bÎ{
%íŽãš/ûŠ« ã?ñö8½¡TÙwügt¢?qê•‚Ó‘÷˜ +áפý¥Ý ‰0•þ´°Ï~é + ê5ªHTÌߎ§ zmTûB†l2šøïSýK½ÆG[üáµ;¥@òþ:Cyû’C7‰ö×!ƺ¡09ãpÐýuÆkÞOÉužÁ• V÷ðÓн7³I'· VCöß{«áY6Τ=†ž
ûëÏ@OÔ÷Œ:èAô¬[üˆ‚î¨^?tXïöÔa¡»,TÄÁŠáp†ý–¤Bÿm˜ºÐò–Q÷QSÝÚåwÁê#Øà¢Ò)I|¤T%€n¬ÁF }Ý›ò[ÜXK + 7KÜlûz¾y +´´åNˆ y,¢©Ü9¹äápó~@]ïZ¹Ì|>na´RqçQOÁÊ÷S!\äàzˇtuà_ŸÔ ¼,›ÝBöÆ
E¾nžªAxgnSå©mÓ-ÁõÁmwK î)jH+·}¦Axïtk¾D)1jˆØ?¸óø¹¡CëÜ''Jo
…Û)€Ö»(?hrXZßCƒàV9´þ`À+kôóR@9\š€C-Ãü¡œ²eæ¡í*9JepØ¡í + ùo-vÚ±[ +
`™ÂlâX5:úñÜБZVF#Á¤-{à_w¤VU
‚Ý‘kê•\ŠQ_™·RýG +ºKƒàp¤Q3αUÈ#Ó (UŽ4¾š'“ÒÂ8´éHãkP“¼U,‚ב&£4ÿRKu#¸ONx«´ì¡APªiw²ä˜[>ÇOA»3„'³ƒÊÞIPéH|éÐ6ÂïÁG:°¤sŠšú²RÔp4ïÌ®uÚÈE±‰{¤ÃL
§¥“ºÊb¡¨©Sú‘Nå%Ð$VÜc…?¼ÓT
ÂËòw”wÚíÚ©y«´ + Wznùå“‚I Ç”Zk+È–aY^m%€Þ<Ä›Ž"øÕ°Þ<¢APA.è:ÍSFmõKß‚®é„÷¸[ßÉ + 4J‡‚VYA¯cèë›Ô¥h/‹!±¹àë[5ï§!µøR¤z«FC®@æ+×R(aŠ*øs—Á¨`hÿeÔÖBð‘:@ +‚ø¾+˜Ÿ#€ÿ Ž”=œ¯¢‚~J…°÷¿`1G0ÚBÚV
Ç|ñïh¹UsZGjR,¿O¹í¯#ÔJÃï`TPC
Â;s¹×Œ™®Xlº¬8OÕMQ×¥ç +VÜ(nãBª‘Ay(X@YC"¥=‚Ÿ0²† •n"*µ%ŒEñòp*„ŸÄV¹Õ÷ÈyJm±|Z•@‹Øœ¤@9“8\µTƒð¹[=%E…Œn©Õ3К)¡,WÁšÑhíW¬<Pyj_ vþðµ½ÐºF|¨çˆ¡òOÁºGÐúSJDÓV1lß
¥$ÐZu¤¨
¤áÚØ°A +î–çù¢NPkoƒ‚|ä¼T?¨m1Ž§€"]
eᶘ¤AðÃŽë.K8Náظ9:v¾AÅïè¸3ìr°ñŒ_ZƒàŒ_Ó[à¤e(*}t|m
ÂS0ٽʒÎÃcoߣ“Ë + ©!VÿcNqxÑ ¨j1!’Ò¾
@³Ý‚LTL˜Þ-à¦;:ûr4;óY“øÙâèü]hÑ®`u`„±î{tÑ3„wæR7XÃq.…
AÁG—nÔ xQ]æ9ˆæoÉÍÃ-»Jƒð‡/»ÍƒÈù‚²° + }øÊwܧX…<ºõ´‹ƒÌCœ6H•]«Ð~wíNƒ_=þðýQt¤b‰‚l߯xû¹äÜб²ªBœÚËâr¬ìzt~/†¢¤bá ©cç£Að>Æ¥
Œ•¬cèZÕÿ.ŒŠGòp×v@u¾óBÎc6®Î÷Èv:?D}ÏÔpc$òÐP¢¼¡…ͱ:3%·P¦È S›cuæI å¼,ô冖HÇê¬@×¹ßw|E4_ƒðŒ_¯Œå°SuOÁõi<ÁÇ®çø'*@2d9»~¬áýtý>T¨ÑPäØõÓ5ê*Çnâ Rý-C³øc7Ý©Aðn9þ# \•1j'3<T +-€Œfc9JïØX>Ö`l*„;ìk|O@µ> ¶‹P];Öø~Ôù€WB4bx£>ÖùýsC…ç7ð„}Äop•e¨‘ÁƒPXáïJ†µ– ++Ü"€.ªâ„d$›—^t¥ +I fªLÈi[§ Yô¸Jow +ñc%«ðñ?5ï‚–KØ ð½8~o)l™©Ax´ärS$®WØr› + Í*¨%A!nØ“U´ùg
Âó´•ké’õe«*è2”»Ö=h‚8‹r³5Ë‚ªE)]e¾ÖQ +Z+€váMGÏ…–Aôì>Oƒð_·—{ò‘GÈò¥±)è
‚›®¸ì'|•QY _a˜R}.€Þìm߸•ÀSPÜð6ô)—ž£–·ÑvŸºCƒàjêm_ûbÄÙŃZ !Ü·›R£ ,‹‡¼%º²{"Š„
W~ñ÷Ð0 ¡Ñ¤ŽÂá†5@#TDÅ^&±8,1EƒàÎ,5–'“&
ÁÅ£&hôÐOní©$\Áá&?%°2v +›âošü£ + …îpÔÊÕÑ àpW Ž`t݆ȗâÅ¿ ̆hŸÀ‹3¥BX÷-Îú“m9Ë 0²þÖ ü×eK1–ƒø‰ 8«X +~©rií—à.8^ÙËÅ¥ÒÛØqv¼òE„é²¥9],Ç_¶\ +NÁ‰R? + Ü䎕K\•'.è¬Ap +N\x«Ú§r +TµO\ø€ +Y´Æp¸žÓ x·œìÖ'ÂõÉný´_‚;óä×*Ä‚ššÅ°§ýä×ÃÐ÷ù*£¥q,UN~ÿš + ÍG=%+5˜¸'7iö§~äVTØ4’À.¸S?6× (éN
)£„==ã›óÔó%êëFŽï06qO
i'€þ.â#åÔÆ-¹Oý}<ž‡S#XP໩¬Ä©Ïj<-§Æs( +%ë-òŒ?¤APØŸš cdâbÁzjB+
‚7ç©å%7sؤw*㤒`(—Ó6$ð‡/j«ApûžZï&-XN“aC³øSëhS)Ij’‡HNm*snèt)7d‡”H +5‚"út©÷PÙež±l+~8pëtÙåè¯Xi§rç>³›‡»°·Aõt…’»N/m8\…nøte7ŒÈrvØéyºò\
ÂÃ]ö<›¸áS„~øe/ Ë÷¶o4j¨¥{úòV„wÁå/JÂÕ}…‰Õp/ ë¾æcn«YaÛâéëú =nFvŒ’ƒ†°þÓ{’„×îÐ0o©à^»C£4¯]¡ë뱜¢ †gúÓ…PQ”'“RÁO%Î
)u
Î(Í(º;Sª®ú€·/¥F°søL©n¨´ +)¤jˆî:Sú„Áy¦üGJ]&L
Δï®Ap«œ©TV]ùôÔ‹CvÎT*'6²BuràA8Ã}–ÿ7ty_ž‚½(âçç3—+€X`еahÌ~&ÐY +Ýa+”ŒžÏT_— +aåáL
Õõ—`$ÿŸ±3ó©þþøØfc²ÌÆm†Ïçsïý,¢UÖ"¡TúÒªÒ—"¥BiíÚÈ’V"¢hO«¥úR¢"K$*¿{î=ï;Ÿw÷õþÍyôÐ_ÏÇç¾ç½œ÷9ç}üÔ{¬I®â¾n”dkDZSáX“PóyÁÀ]†{€kþœá1µ¬V¦BÚ ¬®kYCƒðd¶<ÊË’p'ÀPº÷XË4ï§6¹
TX¿åJCh•ks‚ +Øñ“{h\»ã§p]m*_æ„‚ñt³áÏvVÙµ5,ðñÓhÜ*Ç{mL7Š(„Šßñ^;Pÿ¾ÁÀ#–ÁÄ=Þÿ,4´Œ˜×.李U$Pý`àŽÃ¯¸Ç‡6@*¥ÝMÄ&Éñk KJX°RÒBè]JA
Â|
קó›‘aµöø5{ÐuÜ[5FAi1lH¿î]
‚zÁññ«µ”Žšu@>a¥ÝK;Âjíñ ŸK e<•ŒÃз„ÏÝDÿ™>AÏ®<Ä<±¦á1Ýêk¬Int / ã·Þ¤Axí¦öT&.e â[êøÔÞèN?¹#E33½?~gÛt'¿óFÞtîUí +D<wÞ¬AxLÓTVWɲ
aiǧM@wOQê¿‹ÅpPËñ»ïÑ ¼Àw¿]¶U,Cªãw¿#€æLTj-¹P±ƒñøœI„ï»y_ñV¡²†`²ãó¾@K—ñÀ©Q¢¡—øñ¥+К³JD“–!Áòøš„vAïŒvþã•×Ô™Þù0TO +µo@ù•è‰Æc1ØáÄ…ò5^¯¶qO>*ãà˜,)€~P©È&.áBE„Θü¢ ¸,¼í@{‡±éF¥’øʯ°÷R
›îÀÒžpUmdNºÐ4„ +Gl…›äñÀ ?U3Òpù2ê¬AxLÇâl&YÔÖz²\¨£ÁÏU¬X—Åñ$4ðŠsPž§ˆ×nk‡«ä ªª_ÍÁF¨Xõ +úC + ÉwèNJÿ5@ŸjÞ™ÜÓ@9óâ.œîB÷ Ç +\&V4”ˆÊŸ{|OùP¥Ö¯±B÷šäAÑS©õJdíð¯2O}’UÐ/ÅJ]ãìZJzðpVêÚQƒ |ªÔÓvµ½tä8Ìrr¡Ndø¥“üöZrãÒâ.t²â~ež¯2Tð„§ g/tîkÁ»ö¶Í+»B +ïà*[°éF—uïÌ*[Ï@;Ïò¿˜í©FpûVÙ9P +ŠNà'(J +_e™EЉ×ñµAÝQ˜˜ãB7¤CXýÏlÛ'0I¨Ðb™mûiþœu§ÿ9/¹#ŽÕLë
‚u¦ÅUå¢^:
sÌ´J‡`¬vïÌNªÓ‚c~4Îì´&2ÌxéIawu?¼}K» ®“x«P"ª!81³ëät;_2»ßÍfÚ„ªõót¿W + Ö¾GàÂ[*«uËt¿Üdµ£¶ +…†cÇYV»ÿ + Nô¢ÄH(”WA + 3¹X2…#9¡ì<ð3 ž§§)~QXæÍ…z + ^ÕõJî.ü\˜Õ«‹A!–Õ—3-¯áöÐdõ%€ú](£T@®ß•BÖ@K©FQÛÆ.@ƒ÷Õ5¯Ln¨4Oæà£OpÖFJ¥Î…øFÈ’¯Aø¯» apQÇÝ;Oæè“Y
qnC³.<Mƒ Ö“uá¼,Þµ=Y¾$€†ícÑCËbx\Ïv@ƒ ôÍv˜M7×xBYÃþÐ ,z.iË!j·‡ëgºP{tY#¾ò©Bn,êBù½kYW<ÀÃöJ3ãµ»b¦ +‚cqøÜ
Â;sasµ}©`œa,l™vÁ¢ÉJÉ¢L–µhª +V½¨APi¯ú¦ê,D Cu×Ô_ +kFñ”]ëY4âõ + »XƼX9¼v[÷ ïüè.òr8–Á}šý]ô^ ´íp•þܳЮOËB®Á…Æ®/О÷ùprYD}¤AXªìùrϪÙ{~× ¼UöÕá‹:é¥á#µ¯žÁ›3{ÿ9Ë„šà1í$–±˜"ñƒŒÙûW y|¤¢æZÙš ƒœ&BQ +Q\€Ð…zjÔé²®”Ѹ¡g¨½%€Wc§58ŒøpM ´)MôàF!.ôµ +¾ª•ä + Sg³éFQü”RíÔg5ÿuˇžêÈâeY>Lƒà\={±2“HÄÎáêÙKPŽÌó ,lÜTopƒ +UXrGq‚eõ” +V/î,”âGe¥“†MW¼^ +òà)p
‚’®º£JyÃöuJ5ÚœÕ;õŸê1á#åÜ#€m÷9—àµQ=Q"€’þVq<s÷lp¡÷PG~¼òÚ£ÅñÃcõŽ5ïÌN6 +08=«wJ .×ò¥è^Õ–ƒ£«w¹Aƒ°À袚—P‘C4sõ._§CØì®~ŠK%© @Äàˆ~Ê
è4•J*dÔ°}O«*€z½¨”,Rþ°§½z¯W5©³Z°B5v8q¡V„'³ÿru¤Ü‹,bø\ÿ•„ÿº¾s¼d¡P©
Ô üKƒïäe‰Q¢öBV|·á[jÈÛ¾‰K%6ÜÁ…Þ@çEqè~'zU?Ï@ªúµ˜5èž.€®XY¦Eª_±J +W=Æ‚5çÞí„é¡LÞ¾äŽc·`ÎCÙ„ÿºGÛ¤)ÃEóh;ô¸¿3¯åˆS5s_©APÊ™s7ôÂ>±œ9$Ð%¢#Žm(×™3gž +3¤Üç,¸.ÂÊhÎ2¶è™ÈT+gY‰§\,‡_'s–MÐ ¼Ÿ–_í+4^ñ¹P)CžÌå£ÐÊ‚K154ÈY9N + ŸýûŽš{SÑ(0jü¼=ÂÑñ5öÍ
Ü8V÷us¡ùwfÃuË®×(n±åBõÐïw*—I4Kà »¿ßAp?Õ8î§Ó$hûÚ>5+øA-Ô +O@í|™é?;z9ÕâŽ^aïýÓ<ÅlÃ<u(@ÿIÜ{Ù8‰¸Vä;d«Êddâæo.TE +®
Ë1$XÖŠ"€N:³zx$•
OæI½P÷Ì4ÓÍ`˜Öêž-€zrÔ7Ý +¶Á[[«ç˨—êñHŽŽP£m× ,zzíç)H¸SÃ9ðµz@ç,ã›ÓKÇJVs^@ç>Á’.Nª6T®uîShÐ6àÉ4¤®Ôt« +Z©Axíæ
Œ›dľWkÞP´ G™!1FÔZÐ[ +OÁä|
‚›®ödvF<*>µ'ß*€f¶daïuÞÁŽØÚ3[K Ž„˜áR¬ÍmSÿè1Õ‡’¾öcÛЬ¼À1zòÇžöÚ³,ôôcÑdŒ¨ýô,ô|v*¸[%ŠýWÐ èåż,Tv9‚âj¿¼T +Míoúhþ¥íªÔ*F¢koÿ,Â}$joß̦‰û(~rª½ýk
ŸÛ5‚•÷Êpí|•í•’ôjº(m
í@kº¸|¨Î`®qFÇ<jc¯v´"v^=£. jôr¾(È@/
kœ¼è:_ƒà<ÕyÅb…t[q¬ÐÔyåZôj +£¶·JW#è5N°ŒQ€qÈwÈŸ{í3´r_eä¤2”Qª³ò`:d˜ÌÕ-‡P"ÜæRAÓ!ÃÚþ›îÕ +÷TÕÇÐ[ªL®MMб +YçÐÛ5PN*J”‡auÞž%€Þ™¡Bî¾KbçKwÔ <™g±`MF©6Þ*WÓ èy¨ó ‹CÏÿfx¯ÃýÍ•ö:Ÿý‡M2“ØÁX糈k*¸JèîªóÙ-„§à?¿…JAxþåJ Õ ÚOÀâð‹wÐ毒žÍñ¦Û¼MƒðVù¶O&u¦¥B)(W + ݱÒîÐÒ`§gÝÿ‘@Ü$J)†šTuvÒ ¨´×Ù·Ž/q¯\
žÌ}ïjÓ‘D™ZëšæP«s¤“ +Y×Y%€Îø…½Ejî¤W÷Œß5ÞuŸQnœ$µÀÀ…«ê>S,€Ž(7N2š²’ø¡¨î[ƒàAÈÍð)!JñÉ`ÈÑ 8¹Y«ý&3Däf½¥Apç6ð‹‹Dc)/ +î‚Ü×H X
¡f†¦°¹
Æ ‚âÀÑAŒxà4î§Üu̽Fy†y*8*€ŠÊ +|Q8/^ࢇP«&lº‘{"efn«f¨òÙ§ü&¬ºH +é• +Ã¥xr/ižñ$»ã½V‰†&/¹É¦dø%nߣ))í +ºY +•Iâ5‰€F`î-Pß›Xy°¼XW<ð¾4zrûùï^™7WŒáeéW"”ˆ¦Jü œ"Ûo¼á¿n2Ij•ˆµžÜA' !¾Eí%ïGCŽ}=$€Îó3ù(-2n”‡ÜóÎÕ <çùyÔœØl¸ÊÎ[/€.~˜…=•˜1ä›ç^üx:„ý*¹ÃSºf™Ú1äï¤AP¡ÉÅIU$ëPáø¨5OæØÙ<pW"FCBøscŸ•@{”‚L%ìp¹Îܱû4ÿÒ\·–îŸH»»rïì'€îÍæMGÍ&E6sïÍ)ª×Ç_;jʆBÃT*€Îµãob
Õ (}ë
ªŒ@/µÞõÓ üKç?¸'â‘Pó=*€.\æ_¯1ræÚÖ»ðut‘z£V¶¦e¹h› +r½É÷ )ï(—JàƒPoÊ„ÿº©M”8¤Í°¦6“@ðUfÓÓ’ª7õAtßÊÀµDí•ð¿o•á9ƒ›xz%w
=êÍ"€Vu²¯#þÜÃ+Ð#·Sà„€SðÈdô˜¯®Qãc2—ñVy¬¹baOI>áí@Ïr€›+žáÒ½<Ï~«Aø´ÌíÎjˆ+¤MMaëÍ==¾žzK—ªe!½Ö0¦¥/kÓZ•vD)>†ìÂzk³5Ž©þº,ÉMòþ+(¦ApgÖÿü@àZrçÀð¹Ï@û¸í*;Ô¥5ƒ¡>åC
rÊ"Ψð4nä\ €ì?Yõ£Ú¡¤k`ÿ¥Ap«4ˆûIz)j
6Ixàñ)èÊ_•ˆ²0tXƒ Ý`w„•‡-0ŽÏl°ÛÒ ¸žöŸÀÑá%¶bh¤ÁíÛð4ß’ô +§'ñ‘jxÚÃÞ°gM6“’^ä,œ§†=kkÜO
{¿ÇS@êšcCöþP +š/€®¸/E*,žÂÏô
¯˜ªAPWi8š- rÂÅ%³Žž§AxÆG¿ÄBŒZýJˆ6ýª +úTƒð˜nã˜, +Š°Lâ𶩄—åöø ØŠƒÞþ“ + §êÇܦT/ø¹§hüëÍåŒ"*Ydšx6šÛY + ½u¨P^ﶆ˲·ž +Z¬AXìgûŽ¬›H‡ò6ÚÿŠáMwh«ÚôÔÚ™<‡þ£Að˜7®|¦‚¼c7]ãʽP•l˜ÒçåðW¢Ap?5δ•ÀˆÆŽyhœ@YðÀT˜_Š³†iž§œÉ<ð”× + Opã¼>Opã&ªƒ%R2\e›œ'€šm,SµMmä7Û¬Aø¯ûéÁÀts¯2¬<4þéQ
ÂcÚ3šNí&Y÷Œ@‡w²Oá †óï@G¼·
ŠÃ&eíß6'/Ë‘Ãè(þôb +C
4DƒðVù[õP£b†2ÞÿÞ Axóã¢ãÞef(*ÝøXò¡¼JþS vºõádæUzB +}5$æ=Ón©¼Â…X^Ë"^`;æ%cèD
Â[¥ø
^` +·2´ŽÊ+^+€RAx±;t¿,ç¥þ@óX…ôÚËâ—å¼Î¨Ûÿøsþc¶J·mèô®l,{MU°Ÿwzw 4+0L혡@ÞéOjþ¥Œ˜»…
mòzÄЙªU"5D2¼ºå¹A +PßѬBÆÍJ{^ßë4©ÿL†(@Õ1ˆÃþ óù!æ¹¾q᪼ó@ÿù¯|rèz€äýç/tÉ?ê ¸©k]š!敦Ž!º+ïÒ…h +È1 +" y—¾¨AxLÃodÒ²ðç†OÐ ¼ŸF]Ç‚5NbÚ°ŸFÝ AøsWªv1d™F
GêÊ„?7FiÑ”²k(ž7æ<4±¬‚kµ`#0oâ‹èÕ`2“–é–š¸\ +™^{ÄqÑÔ¼„B#ðŸÿˆ +¥±9–¡‘vþØOÐÍÜ‘Â+Æcˆ/È¿y´a©ró¥d¹[ÅÚ”ó:4ÉÆñt;ÔtQA¥CøÅ4ÿ¶=ÁdÆ(JCû$ÐA^`WŠÙ†äØüÛ~@w²™B¦è®ü;W {T·mÛ•3@ëÐýSØ$I¹…yù÷ß%€ÈS@6¡’´ +,€fZÁ1·ÝCe€
ÂÝÌ“Ò>gÂ̓УcÙ¤ÛÕÆNôüGoÒ |•=í‡}8ôDàþþÜÓãТ)ÊùB
Ÿ“¹èn
Âó´ø;%¢É«kP×ï@K”ZkyxñÀ—Ü«Aø˜¿¤šçR©‹6'ó_Z"€^oÆëy‚Üò_o.€V{nAïxº—;Ï_}’ + +*VÐ xK«v T2à XŠ«k¼ƒŠÛ²À w|?«·× ¸Ç¬Þ,ìÉk0¬~×®ÀRÔ"/ô¯ 5ÿu“9ÿŽ\K1ƒ]0ù½tkÑÜÍ+üi2îý^ + Çü«,å•6lºÇÎ@•°÷60^–Ǿ@ó-µP6µD*x|–áÉœu…2LÉT¢§`Ö5é¶[ +žòËS'hÝÉÄ»à©_5ÏÓ‚í|Qǽ-|¤ü €žO‹Ž·IŸÏo@/MŒeÏÎ…âð¥IhÙ%<™®Ún:Ä,¡Ax2Wp“—ˆCIéØùR°b +W|/øî¨ +:K +¶o„ÂñáÀw·Ò ,¢÷¼«Ìn1´.Øó¾ +úÓ/åCM²ÎfÓÍv-·N5h’5Pƒ ÌlÚd+C ÷_k¬M›|'€z=\e)ÒÑÀ›özAƒàÍÙ¬·l£âl”{„¡‹5~®YÿÁV¡…1@«ÐÀŽaš´nœf»hø%³BãxS +ͤf—\*€ÆøeÉ¡K
áöm6f¥ +[½¨ÿNÄP4£°Õ2
‚ËR8²3_Ô""Ž½!…#» + [ÿaÕ(E ++£…“2Ð'›Ž¢ºñçîh¤Aø—¦ú™2^¢cx+œºJ +ê+€Ÿ THzÈÆ•§¿U +±Âç,´Äž¦ @js }Ñ…K¾Ò xß¾x«Ú~Iè8+|ñ?éî;YøÊUlpQÙÏPÀ$ü•Ñèµ+ù¢âe¡Â +ºF +ß©'€ÞÈÛ×kâ‰m©Âwk>ŽÔòéâ8^ƒðõúåÿøs®rMâ+¿ðËïÒ!ÃÀ¿ü•=¿‡KyY¾<,Ž²è¡ÂOVá— A\BpÑû + ¯>QGÊQCI¯>@[}¿/…Ÿw +·~ AxûnS]ƈ2¤#n‹ ïçʃí¤Wþ÷óÐÎoøR¤ðâP +gª) ×Pœ&RT¡—Á]PTé%0( ßÁE•žM‡ð\”é?[D©˜ÅÁ‰E™[P–ï£1îÚ6ðpe½ AP÷-ªª:ØT²‡^UAp튲»ñ1§„ƒó¥(ûTTƒÝ8îª|Õè®Ap«Õ +B›"TVÊ‚¢ZPƒ1J¡‰Æ,Ckà¢cPÃ%ü9’«)\…¾¨áK¨ç&Q‚OÄÐö«¨Ñ?¨ðÚ@…¤TyxŽ@|½€Úí¹Æ$NÕ,jÕIqÃqréÆÙ`En@mTô)=ïRZ‹Ú@íÚ°8Œzþ¨D +
~jñ´-€æ)!–¤4TìØo1¯Ÿ:‡˜,c†e™w® +p•îå?÷„ +úG +zGƒ ÖÓòýóƒk#j*MÐòý‹4ÏÓCÙ¸±É™gø¥.@r÷v2oÂ.ø‡ÐæÕ¬þ'¨„ƒaY6¯@_]Àì%–å«‹Ð×ø˜S'
ƒS¡å×ç + ï8 É+~j&ÈŸÛ~ ¸ƒSvç¶Üþ› +Ÿ`êÖkhìÐòÀé„Oð‘×Øz%¯vÌpåY.€Ž/âý” -Ú UŽ¿P>tâ§~•ºñN¨¹RCŸ /ý×IÛËm0TB8ñ˅؉›nL×Ä°-u⦛5Þ-'îäTMÚ*NH(¨DƒàŸøsõ4Û<T‡FA5ÐÁ¥ +¢Š¥X;ñàËè×g}œâñç~+€Ž4
¶JÒäW9ñHsôg¶9émÃ`’œøgo
‚·ù‰Ý n)ª3Š•¬ÿºI + z¾^@yŠŽc(0ߪ^±Á]Ъ¾ªA¾ÃÞt꿧AxžšrSXŠÌ‹„ú˜*¨Tƒð<5Sª½À2h[5k£Ax +šqd/_*‰ß[5;Kƒ ômÕªˆ!ÇЄâ°U«VÃcZµóÝ‚)Š‰Ž„Ši)è
¿cU;æP~£n;] +zl@=¯çϹ[.Ü'?×s¬Ás׺çQSÜa4ä`TÐÓ(O^|&œ‚Ö ’+}uͯ»†§ uÉÕéпeŠ¾|.aJ + nmXuÕ>WàyêV"€ú=¦<448Ưu¿§Ð +ºI +IõU’8~¼]æQ”ý +ÔWÅnÁv'Ü¡Að ´kìKߤ÷ÖÄÙ`íçI _`П«=áø‚v@MX…¤§X»ãÛ59Gƒ ,hwâaj‡ëÙ+èv
‚ò©]ë·ÔV‰x50´N + “ü''÷ìÒøÙ¢ÝIç îùâ÷×ý÷²(è
ÂçnÑ/Ê=A5
;sÑAtðÿ˜{â>hß;øX:dø_Õø¢Š¬†ú*íþª‘áâªJ–m[øR,>!G +üws¯_YÄP̽¸ ¦Á¨¸Mo:ºòC]Z3Ê@í†ú[ÅUk-JÃÐE¥Jq‡Qqã®2~x,îp• +uÌQÐ#龊»©Ž¨ô,cpÇwûL + ÞKÓn¨CSÜûet¶ßDz?»¾Í‹Ïž¦Aø—.Ê+û\ÄQ|Q ¤±yA`X°^ÔJ +KÁd®†T‡ú«Ð 7nœ„åà]Ðá„ „ç©ñT¥ÐP¨vwh| +*ŒcM¬C!ef‡+° +I•RøÚèpa4L9ö©¦BÄ°U†× <ð§UwïÑ_ùž^#€~M²Z›¤ðpl˜vøµcùP$«¬+¹åÊ0ø¹HÖ™¨_h~”É`è”{HAä +À½"¹GPÁÓ,XcTû/p¤`¶ÁciúYÙõê:6Gš~)€š©î~©#‚êZ¤Ù
ÂkW¸¥Ì©`ÌîHáÿЉ~²×óʽ¨áœxT +Õ•ñfhp TIð¹!7(ƒ+’ˆzG†Œ@ÃÇ¥9„XŠŸ €F°vÈ¡Ð쎌è®AxÆG<|.njUFFÌÑ ,Gªçg*šacïZdäF
Â3~Ù3e +²ŠžPÐ\
§el°ÀQò+àe›©AX`ŒõíêÅ–2¥ÓDÆÖÐ <¦q)Åú¨á +{ª’tü¹›³5êãÑ[ØôÂ>ï-Ñ[ {ždmÓ᯻ç4C½·Ä¼nGPôDgÔÕ <O³|;8Nþa5DA¿ ÙUX]ójàÂì,
Âûiö†2õ?üü¬ OÐœÇ5ıÑšó„ +ƙҎìÏk>-ç]]¦dY†·
û¼Ñ„é‚xÚ|bö)
ÂRå‚Ç!Få}ñV¹àItýÄ +ws…=õG0@7H 5|½¦"¶cº6^y[ƒðd®¨¥®2*†‡m)gE´îÌ@D“CÀ +5PV+£®ògÊ”$²š¦C8õ7‘Í-o)iÁ”GÈÎ’@—cœž‰ì+4îÌD5Õ£ˆœÌ_t¢ZëtËñD¶ü9j[a‰%¨¦¯û&È)N8áɬùŠÁèÓDÍwÊØNá0ÇDÍ÷Pîh5ð˜·Äº^ +º¶|(™ÁG*šˆ¸_Ãî‰dFD +Æ:]²`•Aå!ÙTõ¼¢NËñdÓ_PaÍÀ=‹„ÌnÕÖ (3“E5”{" +BåT[ƒðÚmI3“"ØtKýOƒð²´ª¨kVÌPö&Ù*Gƒð<µ™LfÂäN¶yX +V×’¶jÓß×÷ËÓáøÌä‡4î²ÙþõJ!®í
Ý‚I?‡«èšíB“²C—‚vjT’ÿý21S¦qò¿[4ÏÓ̓ƒvåv-%o>O +V>”êÑ™NÎ<C«ÄT®8ÕóR¸;™‘¶ƒS=GiüëR½}7sŠ’`¨/9Z–Tï‡Ò!¼À©>Ÿ(qHφ1õù\ƒ ÌLõý#¸€’®=‰'³ï?åSê~êõÚ‚Rçt@çþLf2f(zŸ:÷¨áüPÙU19H
~T + Ï2X°&£I+ŠÝ©Ï* ¯”]N¨01OæÆåéÎJImÞÉSà^Ô”¼?·yWùPÇTÉ"z"%Á(h +rç+ŸÕ ¼ŸÆ–ú¦›»Âq'b‚º••Æ»ò¦£²cìy(Ÿ¬Að¢.í¤"¬©„ƒ!å¾´SLƒà.(íTÖ¯Œþ C÷xiwUUÎkåŠK»ÿOƒà—žò-_ùî^1Œ+=e‡á)è³98œ®°Ç
¥}¾@ýª§‰CÔÒ~µ4îñÒ!+å!á°–yCƒà/½`$«kdn(+QzÁå袯•aJm
SpÑ6t ËL*3<9•^òš +tYÑ1cýñÒûoÓ ¼ðkP`„—DŠ¡=èÁ6eÛ7ê…© 4«Ì×C•õðV™µ'Â6Bé“-X5Š¸Û×ðü\úd«tÈðKOýê¶kÛ™žéKŸ® €Þ>Ê5%ì†J°³èyû
‚q]šû¹Ý‡<‚¯.Íj”O]š/&“BTá‘êÒ|¥Á=Þåºá¬B’+'T‚~Ý(
‚SÐe|] +<OŽÁaÝeü hÆ*†¨@((XAkÐCª¡/%¤°þÔå¡)OK—Y-±
2]fµ@Ïl „JQÐ4ûÕ2¥ÝT¿ Ëì×5éù^Á‘JšŒÀ.Ï÷Ó <¦XϤ¶Î¶á³Ë‡4ó.«&²B“Œ$lC‹.«n@o¾–vQ®ü.o®@]Ë[…Ü‹†ç.]¯Aø—¾¸’EtŠ¢‚±ZÛå‹«ÐæÛÒ/ Ø6OÑ <¦ï¦±ªM…Æ.ßÝ'€~â2 +ÌGâ¸ÏM—Cµ4Úw]¥+†²7]]-€Ž8lÜP’ž¡ìr—# t4?0“lÇÐê§ËÑfç©k¥û•+ šr?·o×J34Jß®_VžKÿ
e0ôZ:„ë®u-öŸœè©!éÄpÐ]×⃄~}Wž¿?ž‚ë»k”™]·ÜËBŒŠ +b¡Lcž‚E»ÐæïÙ‡a{Åü`M·Í?•õè¨ütÔ¯,Žuº§hÜã=†ðAH‘ÿËÌÛ + ©Ê*£š +†¾¸=¦Î@O¾ÄJV½òcXˆõxò5
‚kwæ`öĨž˜ÁnéYp¢R!]Òð@Û³ Aý©çÂef·© +XÏ…£Ê‡zUÎôÌhÌ`À÷ª\Uƒà¹ëý”ÁHMšÜmŽ×ÞOÕ xå÷Ëò_$(Ì‘Œ.¸ŸúeÝ €œo•™D<nvÚÏù>½UûõRE!•ÄjH¿^¿ + ¿Îà›Ó‹ŒÀ±kýþêY>tÖù¾ß7MRâ'¶ÊÎ:ÿ¸Á|Ö6$(°ÉIb'ÕYS¾@OúÆžV.UŸÁЩåCgwùU¦dºáÏÝåp:„#öÏî›Á’.I–96ÝÎî[Eƒà-Õÿñ!ÆJzÜãý¿H +Œ¾ò_]©ã.q(ÙZAo¤CØt»øì›X¡ñœyØ*»øì‰Eôųú0DšÂ1~Ï Apà—|9•/Ť«E†Rî3º·|èÒü
|åǽfñð¯»4ÿ
‚Ýð¦/¥ƒZ;¼ékhH)1zp +e€d0ÔM +‡¥]~÷©7Ýå?FX5r¨>œ—ÿh—þüW^ +ÀupTÀèÏ× ¸vמV‡ÕW¡±ì¿ö´úéº%~‡8òùÆb6Ñ×-y©|èú;š±`%?VÈÊ`¨…Á1]?+›Mòª_?+§|hL¥?Ø$!ë5ä¡É`è
‚r|LíVC"‘”ejS»RùÐ:‹Ne¹rü¿
,{¥zr²H¡ÁGj앇ˇÆïml:ËP§¿·XƒàOXvGpÌãT¶}n²;5Þ涞̧ þ6I&l=½|hb±—JîtJf„vËÄâíÈ®ÉÊă|¢]§|è–ùãYñó
o觻eþD
‚ÇüÖ*~0n;[«ü¡Aðn¹uç=,0è‘>ŽÓ³nÝ9½|è¶õüâ’cKñ¶
5ÞÁ·õ.L\2¼¡f[ïVèÍ~¼,)ô”R™¡'óö{8íÈkeÃ6çí÷¼[>4原Yi·¨i.—0åŽ}åCw
íÁ[%qÂV~C}Ó!܆÷®Ÿöó²P[PabýZ>t÷9çòµá˜Óî>ç<4¹‹hºôcÿV²øs“-t'·—¥öV¨±¨‚Ö•ÝÛnšÿ¹˜W +_¯÷¶»?ú·8ô¡ûJ*5„J§cµö¾’ßÒ!|·Üö÷|mPø´T÷Ÿý£ +”³Bí2ZX>´¨ôV¾^îUf(~´¨tŠÁÉ\Ì]îÝ æÞX÷]<¶ª +^s,uÑ ¨-yã»@¥f‘h§ +äÄ2KÖÐ (0–lø;€’V¨ñCŸd ]‘ÀàŠ:œ˜³d—á4¶>âú*^lq¨ø‘‚Æi¼ï^>¡.œj—…DOC'”-?ãƒ@ª‘á–Z~$®Apà¯×ÜÊ!æ]ŠpÓ½^ó;”·Œ/ J¬3”8~=o¥ +e´ž·f*z»ò—¬ÐP‚¡pÕÛ•· ÍŠz‘¬øs›—”oÜ;ÝÑ/ÅõÏ@ç¿ÃËBë1\žzýù¦A¡ sz÷›Gù xØ™÷î7O + ßoTæ¤çú†»àÝßÇkÜï}å·÷ Âsq;‰#_Þûêc
‚Sð‡«'-*jÁwð{ß>]>ôáüžÁUfÅ…<>œßWƒà.ø¨r +Þãú¿gC±ò¡
§½ËŸ£íbèõá´4Ê‚
³ï +ÌIÛ6´ŽÚ0û^ôÎYJ%3[ÔÞ9§|èóŸ‹Py[}V>ôEf}µ,¤þc#ð‹Ì†…ý—ûæ+ç%wà8Œ/÷=_>´±rCv™ø%-ááÜX¹@ƒ ÿicÑò2åÁ”J¾±heùЦa×ðá$m(w¾iØõÂæ7_gȦ„]´Rƒà.øºæ§Á‘¢“h£AÑóõCm!§Hg0T¬APªlm:‘¹C™tkùж¤ÿnžò¦Ó`pmKN,úvγÊtsÿ…Ô5Í@oNåÏ%©6$¾}óîò¡¯r¼Š'X-¬í|õóò¡ª¾©6]„J§ µ÷ø®õ#Ù$sÒÆ®Ê]ë¯(ÚÝ W`˜Ò?x‚w7è«Ap?íùâUÓ‘i ¥(èu
‚Ÿû¥MÞ¾)¯ø/mª kNcѧHx +~¹æt]+4®2ºSPuôØžÌ(ꧨ uåCz}Â̤P‚€‚>O‡p@÷¹oòÙ +’RÐÛéп-j†VdñöM‘ËKº+ª ±8Œ¸ßP‡æÀÇùhãS¼U¢:€ålœS>tð—¬@Õv5VÜa÷à/Õ4þuGzÎæe¡† !å!ƒ¡yåC¿·â°~/ Ðàý½ÕåC\ti01'´,@«áB‰ò×÷«¥Cøú¯k³Àˆ»‚Â_çj<N洞¥á=þçôÎåCG›qw¯uT¨¬©‚úiüëŽöÉê?]ù +>ÚgTùÐ_T&w앯 Âò¡ãµ.çϹâ"bPŽ×º&
+Å3to:BìPz»‚~.ꓱôUÞ*©ˆcc÷©½^>TáÃ,X®ø •/SÐé|ËïS±ñd>R]°PÏt¡»Ê‡*UèÁj-µS…†+¨wùP•‡+ódF©0lÀêBUˇªÞòO•Ûÿ;ZPAG4»>U¦‚eI…c!Ô¹|(û±M¬®Qy¨Q‚¾@Ë/ãƒà*3Ô²CW + úò'Iq‡á{.Ô¿|¨Ú:¥ÖRËñ(4“\èùò¡ÿãìNàm,×þ›B¦)džÅ3®¡A*°E%*’’YÒ$¢B#ÕiV¤D©4¡’94*%‡Ð (”H†2ýï{ë÷ìóþÛíµ®ß;>ç]ßóÜûyîy¸îríWGS¡]4,øG_fñ£á%«x6(|]mó#ï~ô ,ò£Gª£˜§6ýËjeþQùnÏ¡²7C·DÅfdþQ…WŸ’ì륮J,ðq^}6órŽŸ†ÁMAM>~ôüÿùQy¼â„ûäqŽ](*°å4?šœùG•º¸R¤ìA¯œÅb™T¹N˜~™vù2(øضùÑ)Yüè9,ÐÆìt^C\ó£DæåO û¦‚Ô¼šö~T`i©2¿lTa˜bP`“o~T>‹-j½z® ®¶ùѹ™Tõcœ +|™Ul+üG§+ѱJéThÌTÕê…©ÐsÿϪۮ^¢RõœT¬´ôïR'EÒüŠ‡iÞìÌ<Š'À»2ÜŽL,o~åç…ñÿÆ}ðµ¥yÇÚ•©Ä'Á«0ÜÎûZþÖ9ÇQ< +|"ÅÓOï\iîgêÄ;^\º…†Iq™1K,oîfË+-¬áÍ).O2¨ƒ–§.KñÁó(.OßÒÿTuâí¥Ä>x[ŠK÷ i×ZêÄ{a«ÿM»Ö¡¸”÷9ÃõÎôdà# îbýçø6Dâc21\ýæS\zVûr~ x +ã4R¡k†ž~Å¥ºøì·ô‰wc˜xùìw(.¶â'mŽõ¸ŠŸ´§¸TV‹+NSsÓÂa×ÇâŠÏS\ž¾ÉyJ̓0éF| +Å¥žß—û¤þÕ9 tÌöå>Mqùîûº>ÊpŒþÅ¥º(}KWmeåÚ0ÔIðnQ]´Ø†ÅÄXj!5ž‘ÇLçmœá/m\Þü–·¨yÌó°çd~ËÑ—½…yïÞv¼žØCnx9†ûò·×ØŽŽYÌ.ëØÜ”‰›N1VïÊpYÈ»nÙOjn*+®[ö3ÅÓ¯®sn3_Ëm·PªJÃc—!pí¯îO-ieþpñÔn|Åe×lì†#Ï7»ŽzºØ“Šaº/žeua/•ñ°÷à¤bµ).Sθjž°G‹Áo¢¸ô.†=õ°–Û;ÏpfdØS3;™[Jêyàa›VËA§Q\†íÚ§uf(䂤¸t¾µ°0^@·Ð‡ŠcUèà[K(.•U½/««¹àé†×¢¸<=œñ£úÕ%|8á8¶aïi§Î6öú +ÅãàÕ).{Λ.ÛuBqùÛsÖ|Gñ8øO—¿½òe% +ãñ!¶ÊY;˜§ã4n•³vQ\zVµÖ}ÏpœÆµŽzu˜!o=~5Åcàk(..ñT†KUiøE—×öíK)ïÉpì5j·¤Ð§ÿ[¦ÅnŸvKzQ\>ÜùSO Ÿg*+/zn¦x +íUþ+—šö +#(‚ßLqÉ´óKÅŽnóKšiÿ•Ë›_õõ@ŠÇÀ‡R\jÚÕ<†Kd!ÃCŠK‘ù|oMŠÇÁk3\NçuújçGLÅ µõMü+—÷͘ÝTâ“à{Ž›Ê>Eñ +u¶±‹ø‡—º®ÝI-ãTÔžyo.ο·;©5Å¥}«L'ý‡‹âÞ•âòæW}6Xýêl8nL÷}v-ÅåéǦìR'ÞT”˜â>6åŠËú¸Ãé3‡p†?Iqþ¿tñ_êWç˜þxüÁ=)ý
qÈÜóöÐðçž)¯¼ð^ ïù)‡!Â~)Å¥OÛmúõjóâèœt›>‚ᘣž¾»Á£•‘é»{P\ +ìÌäSjw°§Ôð)—ºnhò4=±MËð3Ž&2oÅ#Jnç`,“·âqŠË‡;0삘%>0¬'ÅCðÞO€ßÏp¿wlÞôxðT»Œñ*={ÿ:â^ŽâR`g-j®å6¶ÿ
oEq©ç±õ‰÷c–ˆ=Bq™|˜üîmzîD‘&¿;†âÒ@·»è(¸—e¶1eÑ2;µ»¸(Ã1{0zg’áض1zç—òþÑ°E…ñº…¾maq¿ÌGÖR\ºõÕSs?ŒcÊ«þ¡†—7dâmêWø¶¨™8šáøîuúê +桇Nu`8VÔÄ-' +žpp5á(.íûÈú…~¸yjê¼)Ååé}Ú ²Ê2.qêw8'eøcG‡¼Þ¾jîFñi
@plêØ®eiðt̉ÌÜ<×^Žâ2oóͦ±jîºIŒß¿ÙtÅ¥À^rožš›"ƒ{ɽQ\rÝ]KßUs3ÃÖÄ»–.¤¸TÔÓÎÕ÷À0[8íܲÇåw¥ï8IÍíîûx}ŠËwï¾I6…zYFŒôÂÔNqðc—§óÃ1ñr´ÎTêéòæ«Ï¯Að¨cV}~-ŠËê@Íœƒcê£fÎ!Š#ö~_tS±û2Ÿý7¿³1Ø}ð;).•Õ+³=-·7‡ãé¯ÌŽQ\j›FK‡éyà [ØhéŠËÓ[üq£úÕ™u]‹?n¡8vïñ†ž‡˜!7|ÅeÓH‘GΉv:=z-ñ –8µžšÇýÂa%NmLq)°Ý†¥/2Ñzœáë(.#èÙ0g•ŽÝ—¹™ÝÐ ]ð—®Ñû+.SóÀô͒ཎ»óÞXºGŸx'ßËplÇýèd&ñ~Ħ8®dêž; ™»0ü"ŠËw?®«œ‹ô²Œh~ç81D8îÂ"# +úàÏ_¤x|6ÃQÛ”tšªy<ˆª‹’NŠË«k7ÝÂTäÀl¸†° íæ5f8fÇO¼YͽüêbüÄQ—NéÆ¿§è¹ç‡ŸJpL6æ•Õ´0^ÀÄK,u/±Þ‚âéö½s•3ïP'ÞtJåÕ>ŽâRUV›¾M:’XæE¥¸z î«6ûfŠK=?ªÃM…ñ^]Ün©Â‘“Qn§¸Ô6Wœýu‰,'Zícb2ÝgømGh 1=©åæg!ž>æ¡gŽ§?xQ5uâ“ÑIdÃk1÷IM³VÍãañ¬¦ù/ÅåÕ{rµš‡AUå±'×P\æ.ro°ñ¬œT݆©Yÿ̉wpþÝðߎ öWG6),ñ“mü¨¦}ud‚#ìa§E¿íR¿º„‹‹BßCñh5°†>Óæ?0ŒÈó†ã¶Êûo&ªÄî3|Åeî¢z—OD3']¾§¸<ýô¡I†#ÔçéCO£¸Ì]Ü0{‰SG²ª*/@euÃðz—ñ{ó?{ªyþ½B†_Ép`?yiu5wô.¯EqIüŸ*ŒX]QŸÖð!G÷`s›ŠúçDA6·©Ìp³jØf‚þÕ…˜h5ü^†ãš’،߈Êô¾á{ŽnaÓW±U)™å²N2Õ¢¹à/R\ZØó¿ªæ1“i]ð×).•ÕñE^#¨‰†¿AqÙ +ÙÉì§6f¬.|»=ÎCäÀ1+.§¸´qt½OÍçãŸDqÜÜwN_"ñ lœØzÎ +ýîq;kƒmknpŽ-+5ŠU÷²}u~Úð—ý6/,úUÍc®‹¹ÊýÎp|¸"½©ç~nE>šGqéQÿkR±,—6Lip]…á).u]…ÊåÕÜ´îí[¡rEŠË‡s>¸XÍMc†Lë|Ѓâ2èðÝý«ó£Óy¾[Bqi&ºÞõ,‘xTV†O§¸äºIŸVóD~ì¾I§R\*«š÷UVóüHà†W£¸Äî®ß‘Ê´xg†£¶ÙÛ¯1“xB÷ökAqÙgÕ$O_Þãî7\_Þ-—lÓ±!Fб,§¸c®icppdž›).ö’Oâjžp/â§R\Êûøq=ÔÜWÜ;0~\OŠKâÓLÍí±Ê¼ÅѾßßXÍc¦ªtÀ[P\zVå÷•UóÐOäóŠã¢ÏMcõÎObUè®MwS\ž¾æŒæú"ãG]£5gœLq©*÷·< æö +×Uþ<Á=lŒ\=ba¼À—pp—á÷Çi;8ò
¸›OØ°2SjøvŠËìA“ë^ÓsA
“â2{ðÌáâjó=|÷g—$x´{¿Gƒ£jžt¢Ýû=¥¸L°/í¶>ñŠŒáí).O__ana¼€"cîÅ1 +ŸâÒ1›2¨;ñá¢ë&§êIq)ïÏ}QYd’n$±úÜÚ—).SÇmj¨M¼âÆeÖÇmjLq™|(Ûp°úÃaˆã6e^Kq)°_–nê8mæWgÆÞñüS™_~“âÒH½ñØF5·)]ðï(.Ueý^'‚gÞÖ>ÆCö°~¯Ú—!ð¸µÿQs¦%þ$Å¥®ËÁF)7}Ák¦ +ãXÏqp»áÓ(.‰ßï§N¼›\wW| ű"öÝyD¶qœˆw ¸TÔåÿÔ>=uÕ&ÖãÊÿ©}zú¦Niãê½Ð˜âx3ŠË¾÷ÉžúW`¾Îð+).ÝÂ*õþ +ã4оÝ4‚ÞÅ–9£).uÍfyêÄ›zGNj6Ó¿º ÝXž35mú²ËL—e¤¢ÇåGQËûÅeÖÈYY
<t1ÓE!öwž-¬8+kR\ž~ÕêMzn +lü;ŠKms}Ó–jîD›ÿ
w(.û´ï~Õr»mw Oûn7Å¥ª\8š:ñ&{£¢^8ÿy†cüg³Ö¨¹=;ÿšáIMœ“Ô'ÞG€YÃO¥¸Ôu?¾GýáLžCÔ…ßKqi&>?²S_dÂèžÐÏ좸ÜÑúç‡Xý7¼Á±úŸ÷è;O¨yàa=Îð)—þ|ùsNž¾è3îùa*¤ü9Õ(.îëK® +¢ng§çàw0u]ÅÿôRóXþ.îŠÿéÃp<Ý»iGa¼€ÊÊðh,cøo—9êzN׿:/Ú~ÿBÏ—lÓiñ±múWDÓû‹m§¸”¸¿¦æžoCq™¯;þ›ýêzùwë|ó7Åeü^æ”YD‘ÁÁÃgS\_iýjza>_IñôßÞ¹DŸ’Zž +‹?žâ8‰ü:fÌR[г¨*ãf0 {à¼>†â2ùàìî¤æöú9œƒÞÝ•â2åµú™6Zî$\\~gx[ŠKyoôÌo…ñŠLÜ./`Ê«Ñ3¿S\FR·Ä,qú‚×l^]Âô_}ðž—zþÈä=jF÷¾—âÒLä^xjz?s‘±—]&òùmÇDk³ŸWÆøp »´{…šýü1Å¥KœûM#ð¬.þ³<n½€7£¸¼º›ÿS/èÕ¹^´˜hø—§;o} N¼"*²á«(.ß½W¥ÕÜÞF¿™âò·ß×öý«ó¢ËqîkÛƒáèUÎjs¶š'Âäfµ9‡âRÓÖz¤úÕ%£¨†ŸIq©ikäÊ‘7}%SæÄ'ÝÔ¬øyÇ%)/–Us/ˆ!Fkƒs(.݃ŸW¬ÒrÓ9Á~ÃWS\²MÎà_Ô<DÓ}9ƒe86…ºŸ\R/ ÛØëçг2ü2ŠKâoºé$õ‡3u
fnº©>Å¥ºx1÷/õ«KØ +l…&²—ØËî8û;7Ê´†¿Oq©m6×?àv´n®ß–â2†=©ÖRðì>Ø{°hý¤Z+(.O¯3±½š'‚h¸ÎÄóŽUà'ž.£å¦¶ÀqZÃ+P\?{È…êÄ'£]^†w£¸ô¨ïù°³ž‡AXøC"ñaÔ¾ßÿ¦:ÛØMà˜)½ÿÍU—»qïjîzQ0®{÷S\ÞüÎ'Î%²Mœgç).s•-ßߪç¶ç¾âÒ!¯óZsp/[nÃà(.£‰¡Ts»¸ñ!—"³¢Ï‘Âø?»Fö<hþ‚ÚŠ«ŠR\#uËŽÏÅÁµ‰·‡mbÑ…P‡¿¦8b>t.«æ‰ Z‹lÒ9‡àÑ«›Ôý[=w±‹Ûð(Ž]ÜO¿£æ®ƒã6†/ ¸tN¿ºþÃùѽ§_}6Ãe§SǦ_žÝ3ó»Dw#^šâ’ë¿£šÇì̓à·P\*ê"»¨¹½”bw/¢¸dÚŠóNÑs/@̇ŠóÚ0^êÜÜHÍíŒ[Ä›Q\^ÝŽŽõ‰Äãê=ÛP\Æ°ÅÚè÷1½oxŠKº×YLôÒ3n¶=3'Z“êµà(Åå铸XÉ];dC$±Iô ¸Œ¤Â£Åõ‰wCÌœ„GKR\:¥ï—»SÍÝhmøŠK¶©ü\‚ØõQù¹Ö—ŽY¹
Q®s³å1ßGϪ܆£—îA£#Ÿky*x€þ%ÅQdpC«2ñøi—7uéiêÄ{ѽ†?OqIüØ2«ÔÜŒ!QÞÇ–ù”â2 +,¦¸_ú¨Åe8°õ³þJnÍnýlÃ1éTù—“Ô܆·×§¸¬€W_äé_]€°H†‡—6Î;s•Y§õìqZœD6|Å¥®ë\:Oˤ‹Ûç
¿âX—ºIÍ!º…†ÏpT“nœ¢æf DüYŠKmóz¯"úç$0‚~½W1ŠËr^ñ©_«ïÚ䃯§¸¬æöh©ÿp~å=·GkŠKyo9àM}¦îÂ6|Å%ñ]ÊÏÔsS`#þ2Å¥}?u(fÒG‰3æ5ÉŸ»0ütŠK]÷ÅiÕ<æcS¨áCŽßm©y`ƒ‚ŸJqi"¯íå蹩ë"î1we{¾‚š»®£2¼ÅåÕØu–S¿Ð)=±ÙOÇø·*_«¹ãá.lÃ71ÍDΛÛôÜA÷S\²Í¸j½µÜ. û¿šáˆáÖòè`5Oú8±bøµÇ”W8ï=â8•Î»”ḞÆ+*ûm¼ô¡ÎŒ¡m@eßÊWtÅ¥c–Ü>IËíf!tJ“ÛÿCqì£^"1Z½ô5%NFKÝŽ}ÔK^¢¸t[|ÿ…šûù÷Ë´øþ¿—~ÝÂùïéo~逿OqY
<ec¡{‹È6ê>¾–âRd~¼ôKuâã&Ü_Gq©¬Šß$÷ˆy©KR²Ø(e¯h Ñ!/~Ó·Çðÿü³Ž-©-Î?—â’ç'܈àQè¿I'7¥¸¼º%kÿ xtËÉ’µû).+Gr'2¯3¥Gr4R%Ïyšà^>–yóXTÚuOcp7KnÃ"a¹ëž¦—§¸â š›dñCÇ~Ú£}µÜ^çŒeÜœ£ý).sÔ查æñèþ8ÃÛSÁóûIøz/}È+ã6ló3†DÛ¤ßS—ö½õ
ßÆüp¡ù×øwGÏ*¹«»žG+#†_NqùÛO=è*y": â!Ãqðe{î&^6>‘áˆs²jÿÇzb7¯á«ŽÝ¼MÆ”w³u˜ö1ü†ci㱋ª¹`0bx ŠKûtëújnjy'â
)ŽÈSv«y"t£ÀSöR\ +ìöÇ>÷ܬº… 7î¡KløjŠKâ×V}UÍñ*
ƒáÑe—¸À½`^@Eðì¦ +㼺ÐÔÓ1=Øþè1ŠK¦ÝsÞruâC?€ï9o%Å¥²j¾»¦šÇ<ÜÜgøIG¸Œ{° ³ËçYq3Âð?çž?(.-ìÖÆû•Ü^ìmQÛÚøoŠãÎÄ+Ç빇ຆßCqI¤#Ãeõßð(.%®oIL¸ÅìBj†í¸iž“—Ñ·äŠKe5ùûaj÷XØð›(.Ù¦æµcµ<uôß¿›â²½ø§Cõ<ˆ‚qÿô:†cò¡âó3Õܳ׼‚¿LqI|ý›æ«yÅö1|ÅåéMŠ^¨æ®â:ª&E/¡¸$¾k¢šûà<]çQ÷Mü2\x:†›‘Ç'À)-ÃGR\zÃŽä)¹
THväBŠK+Óf}yp7ÕñÈ"ñ¶¸{à).Mä„?i¹kþá°&ŒØFñô«;¯s¬MÄSGJ3g;øO"Y½†S…'Róu™Ÿž0}›h{^½†Ï3\Ú¸ŽÇf¹jn¯›Àù¸YÁCÜ}ì½ÔÜu±jø,†ã~™cŠ<Ç[P’âÒ¾÷¹u©ð¤“yWgš'mÜDðÇ´Où¶ÆH|ê4.v6–`Å¥ºhÛ¿ÁL¼´í2Å%Ó¶œ•:rbk0óÿLµ]¹ùÀwËYÿϼ€žæò·?9ðd·Y¥yÂ.5~r¦Gqù\¢æI{0ü2ŠËßþã´[Ô<žôÓng8¦û¶M¹NÏÍh¿â’i[í@ç$YÐ]Zq×tŒpŸT«).n[ßÅjn×ÿ#¾œâ²2RkÚýjx¶iød†#ÐhéÒ³r,î“JÿÎïøÇ^£U¶Rs»>îQ\ŠÌÈákÀÝ,yêJ§ˆÅpô¬ÞéÚSÍãaí®½).‰_Ò³¹–›Œ…¯_Ò³%Å£«÷Ž+Œ—,(ñAů[ÑçxŠK‰«´ôrõ«3C…*-Õ¿yËe4á]#»yÓñ 37Ð6œ”éX!þü5yGy/™8EÉSeuÉÄé—l3òîµjîùÑUÚ#ï^Oqyóç¶øÜÍ–Çí-jàP\Æ2ŸT© å®=%€W¦¸¼ù:VsÏü0¿žâ2WYý—àØkx@qi"Îz_ÍmÈ|Å¥¶¹lèx57ÿˆºpÙÐ{(.³•Ë8ÕôgÇc¶K>ƒâ2gU¬M]5O„cnxŠË´ÏìsŸw³ãžâ>ƒáhß·žpDÏÃèÂÇUŠ0Ù&þË-·]ÄêŒÿ²‰âRוMÝà–ú·Sû¨?™æ6s;àë(.ƒÐŽûjžð|£¸TÔ:ÝI$sÔ†g8¼l]FÍÝ0mØ[kW xT]´Úo›Hûï&='}õJá/†NˆÑD«ýûþ/<,RÄ1šxᙾ…%¾@îyÑ%æ/<ÓâÒ»½”>Û„¸Úðã).L™ª¨¹©ª0Š,Sõ"†ãʆεåÔ†›ÞW™¹ºð]3Á¬QçÚó(.%nØŒaZî$„ˆ1|$Å¥ÀÎ?až{Heø†ãöãÖ©_]àDW¬>1n=Å%Ó¾2ì5wýh +îfÉÓÁ…?PŒâÒ-<¼ÝUóÀ‹n%>¼=¤8VÀ×ïVó¸þÇÀ÷Q\z•M¯{FËíÝ:Ø¢Öôºç)ŽÀÂS¯S'Þ§ÔðaDZ‹Òscjn†Á\Pzî)G‰«ýÅ£jžtp—áOR\Ú÷¹„§>dæöØE`vDî½—Ž^û.¸›-Oh¤_Åpìhrò“Zn÷»à ó“§P\š‰ ³Ö«¹ÝðbøFŠËÓߪ2LÍ(Ü¥á7R\ +ìE{WêïãÀ‹áQ\j›{ËÞ¥æ]ÓŸ@qˆåÔºNi“ѵ†g8nú¨Þ}µ>ñ&Z
_Cqlþo¾TÍ]7óþÅ¥k4¤¬¬ˆy^êÐGÆmZ^*lŠÌ²c(.òmOô/Œÿs0⥖V0ñ²í‰A—zþ„£¨i³ŒÁžº4gÀ
_Èpt.½©/xjšñÎ…Ô¥JÑ-'—Þ4€âÒHmïR¢0^`â“.Îþ~<Å¥º(þÉ
Ç*°á7R\z•'ÿ:CýêüÀ #>“â8Þî
u⦉Žø[G³ç¨¹éÕa%´Ñ‡ú§[.3f»®ž¬åvIuÝ®«£¸üíG?; æözZü0Å¥ªL<&k^:&sfnÆ¿Ñm•†¿Kqé]L»çY5OÅíŽâRU¶~´1x*JjÆ“J†'}œ›0¼9ÅåÍß<ãáÂxA‰·Ç÷±%õæR\ZØïKý¨çAˆs‘ß—ú™âòáŠÝu’–;‰¨?oxŠKU™×v‰:ñ®Ç6¯ír†ã4î+×¾¬ç~trá•k_£¸ÌU®œÓCýê’^"Ÿ_Nq|¹@Ÿm</M>,Ø©çö"ótU™ûÌx}â£/†ßËpìx™t'¡éÈÀÙ$>4EÆŽâÖqF5ùA>¯Hqyu×M_¯æq?ºôðºé›).%®E5Y‡õ +ŒŠ\ +Í6ÿÆe“X^üÈÕzí¯3¼Å%ûáú²ÓÉ‹e9õ3`Ìv8ÜàxŠKÇì¶ÆªyÜÅuT†ßMq©*—žZIËíÕ˜-\zê —ŽÙ§N¥¸>âRÛì½wš›q"Fî½w(ÅåÕ½<sV©
ð™ïÖIý.º†ìå!ƒ(ŽË26/ŒPQÇlüyÌœü¾¡Åe »í™3•‰7<Œ¡[ØöÌ—(.nÍÌËÀSaR2Bã©Ð‡x/ŠËHꛧ†ä
¿‰âòÝw¢å©0¥øõ—iŸJ]N òªÔ¥Å¥‰lâæ‰æ相U).O?½}ÅÂxE&n·.ÈÔ‡á…&þß8f‰{=†Qd–[‘Íc»E¼'ñ +ÜêÈ`5wƒa‘Z¹–âRÛœyÇEjnoêÁ»Q\z•Ë^øšû^èGüq†c!uÐ*¹ÍKm„Î ÜîôÉïÏZõÅ¥¼Ožv¢’Ç=SY [8yZŠKϪhï?À³ÖaãEKZE{ïg¸tóŽ5Ý¢æöÆF|+Åeøõ•èY¥·çeǸ“bøtŠËhâ„Qg€g*ÄüÎsp-‘áí(Ž#ä»/ +ÅeÛÆ®
©ÄG¼)ÃkèÙH|2uä$SàA/uiAˆFjèÙ§1³?nz«0^@⓶[ˆ^å›æ鹋Ø>OXÔÜÍn¢5™šx Á/¦¸4÷4½‹âø‚cu SÅ÷©¹ï†èÛTÜù ÅeÎjôÙ¿«yî3|/Ã1>xè;5{¸Ûð).£È¢[õOwó«‹¢[`¸t‰óZ·\¯u~‡ûZ·ÜÈp„p/šÌYÙPIY·±¿sÍ%ÁK2>Þ™÷šŽÛ«ïBl˜1üuŠKÇ,çÙõàvClæWg/ÖµøÁ7Q\Þ|ó/ªyÒTI𗎧Ÿ}ZnaüŸÍ„ÝigøÁ«Q׈o®®u.î‡5¼Å¥osìùÕÜÅBðK(.
tñËÇi¹ëùqÔóÅ/Oqyz£¹é¹é”ºàÿ¡¸Ì]\6¸‹š!ŽÏ~Å¥žoÙg„¾È¨.¿‰âÒ)½öþ¹znb.ø»—lóù–ㄧ¶ g€ÛÇXƒ6¼4Å¥²ú³Úwà©¥L¡ìc~Ïd8¢ãþ¹s‰š'½0Ÿ@qé_ä!=÷£
ÇyŒâRÞ'u{Bÿê¼ +OoÛÈØ=0ÿ7fO‘ƒ_Cqùîá–Ë•<ðbÃ-WP\ž¾ô÷zn+Kð›).Ó}Eo'^]ˆÐ¾†d8®P¿þô_Àí00‹lc·màšQÃ¥¸TÔã†ü¨æq?Ú,4nÈÏÇÄKÛ.Vs»12 +Å¥gÕÿW4‘ém™++óÖƒ8b6öÿuÁX¾ãF‘©ô,ŠLh7b#ÓÞqlÅ%Ó¾ÍiZn†Q$±÷¯iCq©¨—ŒóÔ‰œ(Äë’q!Ååo_[F"Ìx©eÜÌ›Àí%æöåÿDqYP»dÎÝà^¶Üb¨*/™sÃ1É|ë‡r¤ÔK/md\ÖI]ì‹m™†—¡¸$~ßéóãÿ<Øè¥zóxú¾ÓP\r]õÅ÷«ïèU>™á˜9Zå}-·1~Ze ñ}Ù…¾ù‚ïG7°/{à]ŠK‰ÛÜá}âM餸$~Ë€3Õ‰£†ŸMqùۯܢæ¾
ßJqi ‹Ö*¡uæ¿ðRǯÿWÍ“vQ
|#Å¥SÚòÔ¿Õ¯.ð±€nøŠËPèЖE±y
_Iq霜_™6‘]w/a^bMêürçR\öœlY¾AÍ“~ܶ,ßDpdÚŽGÚ×rÛ<ãÂÇ#ío¢¸tÌJÖÕ‰Oø ôiKÖ;…âRY}¡O¼\.ZKqia_ÛÿŠšÛèîrÿ†#Îɇm}¶q“Hõa›8Åe¢5ù^ÄSÇm2wÌöÀ
ú6É÷N£¸ÿß¾å>5¢/†O¢¸äùÕÔ'X܆7¦¸<}óE¿ë¹‡gø^Šc »îr5{ „MÈ»’âRU–¼^"B{éP·¬˜ß%Lm• +÷œl´úéˬq;m…K¿£¸tȯyúˆš'¢ã´¯™R”â2š˜¼o/‘ø8–q'ï;@qé–©ö¤š‡¾‰eª=CqIüiÓþîfs¤ÔþΉv÷¾‘àQ,îJïÖr'î!6¯áŽfbPË úÄhã¿—àñhÆlèEàYæM=ÆǹáÝ).¯nv…jîùÑDëìK(.±‡êUÔv)Êpì`ÏP\Íý{/Iq©ëÞ*‰l㧖ó2mU²¿¢ÜŸÄpŒaßi6NÍ]'Ž¾Í;Í™Ýݪæ±0‰náîFQ<ø‡Oœ+<È* +bg‘%Á/d8Ö&®X…ÑD˜Õ¯öw¦7e+VýÍpDQ+« åö2,Ôó%c¹—zþøz3ô‰·_ü%ŠË8®ÚSgª¹½º ~Å%Ûܱäw=7õtþÅ%Ïÿ´ã šûÎ~˜âØ|ãŸjnrmóáF}âm¦—úüçÞÒ¿º0Úísþsó)ž~ó+-øUŸøQ‘
ßÃpܾeÁMÂc©a`æŠ:昚c™-FQ\rÝUƒ(ŒÐHÅlŸûë®üÅ¥¶y¤ÞTmâMóìaõ#õ¦S\ŠÌËÇÆ«_]2ÿ÷ËÇ<ý›NV'>zÜ¡¸<}Ó¯ÅÕ‰OØðDà¥(.µM£·†é3
œ +l™³©yÂã°O™³›Q\jÚï‹MÖòÔ¥]>ø#—L{ëÌ%SS^™B…øéë&£+æüÅpl€?þıj„Q$ðãOOqI|™‡dêCBûfÚšè§v„:ØÝWæ¡ý—îA뺞š'œ¨sÒºnÈpì9é°u“ø0âQ\2íÜÑeÁ³:Èì§2|t
ÙÜÑ9—6®È[ýõÜÃ1jÃS\*«^w?-<½€ž™Ûó*8¼oøT†c8p¤ñ-·
Öß4>Lq)°¾UŸx×þʉb8Ö¤–ͼSø„ñqðñG×`FB¸—Ýzêw.b
fœFqie~ôêûm¯OqË´»ñ<ð¬Â˜[wÈ6ínìHqùp¹ºßüÛ^6Á÷Ò‰cÒ)÷ñÇÙÀNUŽUÑó Š WåX
ŠKçdX›3ÕÜþQd†µiGq©çßnªš{¦c?ƒâ’ç^ÛžàѲÎÂkϧ¸<}õä_ +ãÿœdvÓ›ð—ùŠa2käúY÷SÿùaÄëS\ÊûÜO‹ë¹í5šûiIŠË0ðøÍ‹Õ<æE‹JÇo^ÎpÄòš¾b«ž;Ñ +5¼$ñ¤µ¶Ýwjîº „ˆYÛî†ãTæÅ•¨¹Ýž‚¥¸´°Uçܪu.b°~;ÃQâ–îÞ!<–Ýa{Mà<†ÿÆpdÚ +ã*i¹½)ŸW§¸tK–¡N|ÆȤ8Nçm¯¬N|Ü‹¢¨UÜ^…âÒHÝ[éCuâí`$þ)Ãqðáàü"úlxˆ}p~q†K·°s¥£{©<€ ò¼ô¬M@3‘Úª”y[¦3Ýqì91¼Ã±÷ Çy%´ÜÎbž¶Çy¥(.‰¿½Øðì6ÌØ#Üf ˆë¨Š-¦¸L6æŒ9QÍíò$øI—)¯¼Ò¿/+Œ0ÝgyƒÐÒ¿¯`8–ójMÇz\"˘ýö”žCqyóžª2Ë®
ƒÍ†ßLqé|µü$‚;²ãÅðz—õÖ]Á³[¾7<nÚg¼ÅåéÇnòµ<u‘w<Îp,ã7RÍMm…na±q£(.ÃÀK»mÕs/ªë.í¶âX›x²¦š;A4^ødmŠËŠØê/Usßñ±|¿úãž—I§²sÿÐgA™ßÇpÉ6y5ÛÐsÓ–%Á1õ|‹ãÕOO]èì‚ÿEq©¨mO ¸‡ÕDÛêLm#':~Ñ%*ï©Ðý™»FI{‘6ŽÑåŠK‰zÖ*5ý8‚ç=ëŠËp TïYzn_øËGúç1õÔÜ£IæŸÇ4¦¸4ã×JÚs²›öñR»¬öpüÚ}G`á7v½ªæñ À&±7v½Nð§ï9ü†ž{¸BÝð¹G·ŸŽlTs»iÄÿ–â2G}ÚSÁS“'™=ûh'Ÿ?Oqyu“k§æ‹êÂðóŽû¤:þTs¸>ñ!Ž~ÃÇìÕyeˆÄG·¿:¯<Å%Ûìýì>ñù»÷÷~v”âòôcËÿ&^]Ò8ñtÃ¥ª¼¶Ki=7ï. +ÅÑÂÆ^`8"J•ŠÍ¤¸Ø:Šƒ§¦}2]æ§viáâ?ÃKR\ºFÍãËÕÜeÅð)ŽµÈ‡îÒr3†D QÃ'R\2ío=«y2ˆZ™ßz^GqéUW¦¨úÕyÑn㸌ãjVß O¼ÆIâ딟ÃpL}ÜÛ|¡žÛëmÁ—P\fæNn¯~u©0làç1‹Ÿì|KÏ=Lï>àÑôþî%{Õ¯.F£‰ÝKö1›ªŽ©*Üs²¹^Ö·{°ó:¦Ã±=Þ¡³–»1ßÃY¡x‡).µÍµÿ-®æöŠ˜8xi†£c6æYõÓÍÅ%ólI†c3ð’V•ÜKMu&Á3Mä+o ¶Ioϸ¸`¸
_JqIüÂOßQó¤‡Ý>†¿GqYD>ñ—¢jnÈÇÀKP\ò|µe;À½¬¶ß§®ÖņÃw1s·ÏVs›m“àsà°Ï÷©¹ïHü“(.³Ú½åpŸ—Ú —ñªû;»’™ +ÅüÿN95O†8žÆpõ‹Ëp¹yÿ²uà™xm$¢,èþe).ÕÅáÍÔ<ù¸‹Í‹(.7_¬„l£öc¦„ò³£ÿ4øuG¡-þÅ«G.nÃ_§x +½‹þÿßFÊü.‘¿˜Xk]5ŠË×|UwõÍ'äl4¼'ÅåêóÔÜü +«BókÉpôç·üÙBÍ~´½åϳ).©õ–¶f +-ŽÖ·ô†cuÛÛ®wc…çùöà=mo»ŽáÈ +_ܦÔp†£C¾óI}=ïš¡ ®¯i-—³W?¥æ¡©*ÓàÏ1çŒT¾ê+ý£,aW¾j3ÅeüžW¨0ñµ0¯PQŠË£«µvÁ‘ Æð—GWwâ¹÷°±±îD¢² +½(ñàŽË‰B⎼C?±ÇYá ï™3Õ<£àÿ]3õ”å2Ž±G–´üLiÈ<`†€¾ŸD”׈=Ë).»°O¾¯6x&t!g`¤¹LÊMc8pò}u).½ÊBGõWO‡IÌ:Ú€âè˜}p”àQç¤ÏP\¾¸ÄÇßjy¦sñ]—R÷ýSMô7列ˆ»GwÞÙñ{`#5cpû;ñ"¥.ocA†c²qêý)ž +Åea¥óí[Á½¸Üó¬Iu¾ýŠË“ß<ñy5‚ +µ{c²ž‡i…Ú½1•áè—ž=‰â!ø‹—ÕZK¾VrÏ.ìà4êZK¶Q\Ú÷‡+f8žüÕOe8Λ(Ôi¾ž»Ñv¡N).{ã*ûÀ3iNsNû˜ßÙ…Üü +÷J} å¦Jõpfâ
¥VR˸×I˜›Š·Ýü΋–ï
ŸCq)´ý»-d¸ñ%—fâ©KB-·Y‘2â©KÒ—ÎI•_꫹
Èx#†#ž¶ÎMÕÎ éd¸Cq¹ù/šTsÛ3rÁP\ŠMûråÁ3CàÜÁB)›)+¡íËUd8VB÷œVøßøÿMÎcÿH/‰±=§¥¸T¯¾ÕJx:V:kû»d”pÒðóŽ`àeó«¹yxøÞ—Íûâ2ZTòsâæq"³áëŽÍ¼ÝšÕ’j—1M×,¯CqyqŸçmÓr{8Âu>ÏÛIqé4nÑF}óI?J_߸Å(./îÝŠ7ª¹õ.ïEq™§-RèW57ÿ)kІÿIqyïU/¿&˽LJþÜ•U6œñŽº®Ÿû<Á}?×ÏLq„ +ÏL¸åü`
7Å™…Q\zÔgüg»š§\¾[Ï=F:Œõº–»®—Èç(.u³;===‰5»3Aq©*ïIÿ&<œ{š×³ÁÀ>*ê{ÒQ\þöŠ£ÿ_a™ÿ·6—I˜OÛ?FqéœÔïv¸ç¨M{ß2ÔïV‘âRæ'®‘)n/8‘³cfOÜö¢£¸&®Y@q©.~_—TsÏCMkxsŠKmS¤¾Œ"½˜¡6!“^¤þz‚Gg —-º‡¹:n¾lÑï©›—ö¼"UÁݘÜõ¢]™†×¤¸4R{7Ý åNÊ”m¼Å¥sòüËÕ<aþ; þÅ¥™Ø\¸žþæíþðF—¾MËAW¨¹ %TËAWS\ +ímú닇SÌ¿ƒârõ¥Æë_œž•áO3Òõ[ðÉñ6´zv’7‰)îõ[N§¸B—jä¾
ˆÅláñRm).³…ÍŽÍ!n>…¹‹fÇæR\FÐÇ›ÿ_òÿÑ@g¶´"ÚçxÓÇ^¡í«þÿ¯›·cÈè±íŸP\^Üý‰wÔÜÜ:ŠÍý‰—Y£zß> }t6ûßë}ûñ…ü器oÞ:ä†Lq©i§½“–;i/ZHö~ŠË,qÃC2gå…1b6ý¦¼/Fqé¬]Œq\6p"wUÚ%-®]<ŒâRæ/:pÓ¿ñÿQllò=±FèCqi&Ò};ioÞ4Ð!êºtßΗbóýÕkõ.ÀHÊðu—›ÿýü‰zb5Ððç).½ÊÛ$’ÙËÌä“ß…à{).ïý¦Þ*y6 ›ÞâRÛ<þߺ—VÆðÔÕe{ÿe÷ƒg‚r7Й\™HXqÿeS\Ú÷÷ÛwÖòÌfâ4øeÇ澶[ˀǀ›Ò‘¸ íÖ +—2ß½hJÍ}/Úûß½hŠK÷`ÆØjîú¨ëŸMquòÕÜŽ–“à †Ë£ëØhÝÍÄÍ»ÈCÞh]_†#«Rµ×$ÙKÆ;,Ã\ÆîÎóÁ—R\¾¸‹j|sâ%iÓe ÙE5~d8–6>}·¼–ÛÃ2P]|úneŠ#ÁìͽÕÜTÓ˜`Ÿsó-—wln}5·'‘¥À<šî;Ñ}‰úÅ¥¼”ñå—îAù!{ôÅ&L ü¾üï).m\ —O9±‘íeì +p4ϺO).µûÕl5½d>•â8žæµ©Â³‡Ûææí•â‹ëðÚtŠcÚç±¹jnOêôÀ_§¸t‰ß/}¦š¦oqâÒ@yøV57BD6~yx +<Vp ýãDñó…J¬¡¸D÷9?ÿ¦ææ@l¡óó_—«?²¤µ–›GÍÓ>²äŠKþõoõ{f ~ŒâòÞÞ\]Íí>æ +#©xÁÀa& ZѼåWm¥¸\}ıjî{HÖax!ŠK‡ÜoŸ7£}p9ðíï‚ +êy˜Äu™=…Žz~ãÍ݉G‡ÁˆáWR\êùéÏž
Ê]lìï¢ÔéÏ?AqéQúàgjn†ÿxïŸ>¸žâòÁn*8MÍ“¦#‘ŸÉp™»èðõÆòjº dMüzc%Š#Åkõô΋–uÊVÿ˜áÒ!ïXõ§6zîcmÂð(.ß{Ïç©y"H×ß¼åÒ9é[ +ÎVót€#ŸËpÙ‘Ú~Iûà^œÃmíe<ÓŸOßÉpLyœ?WÍC/ +M,8ÿMŠË{¯Wã÷ìAŸ9S؃>Ý4rq׫¹âÒ·)í¿«ç¶”þÅ¥cvñŸƒg&Ür†ç™ßÙT!.øÇÞÀoú©¹cš‰ˆßNq©¬–ï<¨åv/.‚–ï<Êp„a\y¦žûQ~›+]†cçÂuº©yÚóãåŒ:=Ž/¯Ð¿¸ +_\ÌÐD{™ÐC÷Þ¨ßåpÛ>\ÉÓ™„.øã—à)S1[˜
MÌÝ1KÛ‡¥Ì)SŸf8¦ûõ¼UÏ}Œa
Àpdúî‡
jî™ú"
þñ Öó–{³Ü‹—âÕpÏsbøýG@ì¼nyà™µœÛi=;Óè 8p^·—ÎIá&´ÜI‡þ%ŲR\†ÙcFsÄ<{ïÑ¢Róâ›.±G>-Apé¬|ZšáX—iÜ¢xf +?w”âRU–[ö3ÁL¼”[ÆÜ<R}¶uCoŠ§Áû1³•ÿ³CÍ6µønŠË|]í1¯g’ïåì›ßv{øë—«;“jhyfûgüt†c¼TR2‰y1“°Ù£uMûîÏ ¸ô¨ó”PsÓ-C:oÁiG3ÑdÅ-wMûŠ,©MV¦¸TŸÕç.FR†§8v"o¢qщN†× ¸TÔ»&´×óÀÅhbׄ‹Žfâpßyjžv“ +î;ŸâH¢¾éˆžG{ÿâ<ФûýjžÒ˜%nÒýa†£žo:EýÁšOÆÇáwM§”§¸”ùo—ÿÜ‹Ëͯ°}þÛåc).]£wSª¹ï{è¾›:FqytÕœS„Ç;N:s?:#µšS”â²á%¸ª§ž‡8WÈð+ +ôs½ÅJž
+M/e8VBÜ÷žûI,*=¸o7Å¥ÐVõxÌa``zÎ!ZØŠ££¸|q=î8¡æž›ÂÕ{*Èp4RGgìVsˆíOq€7NŒ']”“¹qâ)ŠËÕ×M¿TÍm¨’~Åeêã÷…O07t¿/CýíRê.|ÿáÙ ±œËy™ƒ¼q¶á·S\ÆqG~½‚à&™üz-Å¥•y¨J%%·áyö<T¥*Ã1}ô^à±Ë°¿³qZ ð¾—÷>çлjî Ì9ô>Á“ˆtj¸~·–›naéÔpý—÷üê£ê›·UeÄÿ`8fJ§ÝÒEÏ£n¡áÝ(.S^?7<¤~t)ß»áG(.“I;ë_œÔ9i úÑe¸”ùFÍevöóSÜ¡›±ÁÍð(.îÑù—©yÒG’Ã{P\êºUŸ•wcm)µ—ñ£qܪÏÊS\ú´%í¦æ©hMÊðžÇÕW,ßMÝ||/Å¥ºèVSÜñŽ¶¿3ƒ!»•ëCqi ï.)Ù6äpÛÜ<õϙһK¶¡¸4R_$]†£{ðE2`¸Duvh4~6ÁH(Ýhü—G×`ÆïÙÃms›”éG«
FU`8Â2NX®çn7?pÂû—ÊjÎM–»fíÒº)IðzÛÜê›ÏßhøAŠËx÷Îjžôq––á{(.KØyÎ\õ£³'´xà¯S\æç{Ôí«æŽù_xŠK¡=ãùˆg¦}r†.Øõg{\ø ŠKϪjn0BÔê.øƒâÒDVîSZÍš ÃËQ\†Å×âêÙ`¡Üni{mÙFmx9ŠK·©ÕWjnÚ(L¼ljµ…áèn^9ZÍ^ˆB»yåxŠK»»Ä;JžÊ$ç Àߧ¸TÔÁm3Ô7o;¥ø,ŠËÕg~^ŸxqÑ‘‹3?oÈpÄöÔ\¤æ© ÀLéžšKŽŒ}NyZ_lB<yߥ¸|ïå£G Q‹1K›ŠYR
ÿâØN›>¨æ®D›yÓG)Ž‰ÖËßÒòLºMümŠK31÷ý7Õ7XD6|Åå‹[ºãb5OzQºŒ¥;ºP\n~ûýMÕÜ·3p‡âR]üyˇúGgFÿ_Ið +8íÛ—ªrO¡jnš)'â(.àOíõ£þæCWº…† ¸4Ð3 ?f¦>rwN2‰‘EmÆ‚fGj EWO¤¸þÅå“éxOq=÷¢Ìï)Eq98 üiŽš'Ý„Œ&ŽÊj×ü’jžr\Nìš_†âÒ1_ÿ@ÍÝhzÇj‹ÿb¸L6þ7Å1ÙøúÇ—ªò¶/Vs?L`ÛÅm_>Jq‰ú¨1tõ¿ñBÿ‹V_Ëp¿és—úæmj |ÅeêcÅ¢zGl¡á(Ž£÷Îk'<s¢5aÃu°ûþÍó:Q\>Ø67|¦ç~˸mnXÇp4ÐåºOÔsW7ü9†K(rǺj¯f&Ø“àú«gþ%ƒ‘Ç:‚»1¹=ÈQ•»„áXÖéþëMjng>|ð[(.“Ž]®åN2@²Mï$¸‹<'›~%‹ü6†w¥¸üíûOþHÏÃhmbÿÉ«ŽµÈç+ž&<™Ùؘ»[h–pÛçùŠå).7ÿÓʯÔÜ÷’hã~Z¹™âÒ=X\ám=’òä
_Îpädþdk!-w“6xŠ'e8 ÉuU7ï'óùéG°Ð‰AŸ*mÒIæŸÜwbÐ:‚G'÷Ý°éIܼ'•w†ûÖ oØô,Å¥º8Xû3571|2k¯g8²*í»¿»š§mP,øǦwŽïÒsÓHE|/Å¥c6àË.ZnÏ‹D;àËnGÄË“]G¨¹ëD'><Ùõ ŠK©{ôñâz¤±wàÑÇK3;Ôªœó%ÑǬÊ9›õ<Äùï—: +~!Åeö Ä°*ZnºF¡ñj—Éƺïªé sbxŠgß{§âuë‹Mˆ=à†ßCqyï_#<k«‘ýíÛ$Á?c8>™ƒ¥Gi¹]Ķ‹ƒ¥ÇP\:fÎætJØEºXèi7áXÊüxpŠKúŒ^€Ç:®ÂþÎT83ñŒ^í).kRU™ +ž™hÍ,d7׶”V}d:Åeø_eçwÂ3r¹k7> ocø>ŠËðÅc¯ëyt(’á(.ŦÈýÕmñFŸvŠþêi7D2®j¹ëšþ¼þ6Å¥{ã -´›Ìð.Ûvåä^˜ÊçÝþžó{Ž©VÔ7ïÝ I£åòÞ‡ÕîæI'Jé<¬v?ŠË{ëTéšüX¬=,#JwëK)žïJð‚oZ›âÒ¾?Yi±š»¦šOƒ/c8&ÎZ^<^@¬ù'ôRË<ky)ŠË(²ëærjžÌoeºn®Hqù`Ÿ]AÍÍ׎ñûï³+S\J]»¿:ªyÚKbüÞî¯Î—6®Äø[µÜu£¾á·S\‘÷ºÜ‹sà£åATÏ~Å¥®[üÔ=7….ŸMqé×õ]ßAx6:ç´ùéa¦´ïú‹(.lÛõ÷ª¹
ËÀ¤¸|2•žh¯æ W7¼Å¥¶9|ä=7ï.ÞŸáÈÕùãúvjžÌ=øq½þo·\‚…ÊUÝ«ç!²ßþÅ¥º(zwÄcv™YB°±Ñðýpó®Rs7ô¤®3ü:ŠË÷×~Ápl»8ãÚ¯(Ž
/çVóÐM"wßæóÇS\fJÛT“v7»ñ!çržë{æö<ЦÚÇ@ì‘ÞCõܶgà#).}Ú™§tÕsÓ’Ê÷ÞûÑEGÙûÑ¥pó=).5íÉç5Tr»áI™oJqyt—Ý:<Þċበ+<ùêÉ—R×»©D¼Ô®
ZÁæ}ÃçQ<[lÚïX\ÍS!•^™âÒ5JÝô«šgÒnƒÿFqi߇?Ó@Ïm"uð¦—>íþKÞÖr›É÷ö_²œâRæ?ôoQsÓH#ÂíCd]ÐqD¸yT².¸ÙµÜKI;•±Œák).u]Íåha³!+¹++{DK+#5—¥¸FN?ï=LqŸ~ÞóÇŒY‡ž«¹©°°Ù§CÏÇ(.í{ƒ…#”<i÷Œ`5°ø¨årõ!«¯ ^œx›!«¯¦¸TV«ŸX£t^DüSŠË»zã|5w“N«7.¢¸´ï¥:§õ.±3±T糎zøñÁàn¼‰V{t=r6~/ÃÅ=uÞcjîÑéuSç
£¸¼÷å'¦êoÞCÆ Ã§Q\¾¸É—"h$íÄ9èÓþÎq¢cJ&_:‹áÈ4òÂøÛ³ÁB¹‹MÚ± ¹">âÒ¯Û;ê57ƒô.öŽÌp„.ü}Uk5OûÞ–âRêF¶z^Ë]ÇÅÖBÃ'S\n~öjnF°¨ëö×¹˜âˆX‚àÈŠlxŠK±¹hêB5ÏßNkø†#?í©›|=7
¬ž¤¸›g'ŸEp¤2¼Åe5°ìg’ÛÇËÆè§íòRϾ˜âòÅõÚvDÏèsÒkÛŸ—>m£‚£uÜËn›À¹BÇQg¨}Ó<“¬#çd£áfìáµošR\Ý‘7é¹EyYчâRæw¶¾\ÍÓÒ~%ñ}~à’'õÜE\¥áOS\ŠÍEÅ«êyà`3ïEÅ«S\Ú÷>Þ©ånþj†Çpì¹µõ©zîG'¸ÝÚºÃQÓŽyí"p/V2.{/ŠöóÚ%—Úæ¦!Á8wà¦Í).5íïëOUsûÿÁ/Iq¹ù&‡ÏRóÀæ»oEqyò{òdÇŠ—Mkƒ{v(äƒw§¸,"ìòž>&ÜvYÅpìTš3¹œ’»v{!‚æL®Dqyï箸üM¸ýß1æw¾‡sÀ
á¨ç÷Ôÿôßøÿºy7eˆ5|=ÅeØkß8-· à°”ÙkߊKºôßíÕ7oÇHùøwG‚ãhÝN%ZçQ¤“ák).îéñŸ÷bäm—9 +|ÅåÉŸ´lÁ£#NZö$ѽ8t<:vð¦¿(.Û¨ÏÙÍp<ºÆs¾g86´þüðÌ{ÎFF†N +3‡?¿•âR×/^…àiTÔÇ£~ŽKç$ü(OÏ]ox
ŠËÞÀÊÅ.Wó”ùa~ÅW™×”àˆö1Ü¡¸¼÷¥„z$Ñ»XzAšâòÅzÒ[jžŽö¾ˆâ2š8ó·W´Ü5-$1?ó·™G¡MÝõš{^€ ·Ô]»).½Ê
/"8²ã~)Åeö Ìï·{±6ûØËHÝoø@ŠË@lý»SÕÜn»Á§S\¾÷5w'y¾‡áh&–¯>GÍMÁËW·¦xöæ;•î‡23y¾ù]Âʼn†ï¦¸ôiûµ®¬æ©ütÖýZçQ\^\Û§ñÅùñ¶ÛËDÓû†_ÂpÔ6Ÿ×~OËM§4:/òóÚ2“N»o=MͽÀÍçå).ó6ÛÚÉ»— ËŒÑ1ìH̉ø;—6®î&T•1“¨ÛËø!R:×ÝtÅ¥žÿñ¯vàñ‚ÄÌe‚0@ÄË]Dqyt5Ç.Só„eˆ9ö]ŠãdŸÎÑr»ÁWoûBkŠËÕÏš®çѲŽá³)Ža`÷ÁêG—¢pOwBqi gÕYž ÏËýɘ߄ѯ³ê¬ ¸<ºÄaYÒò²iNs. [›ß1KnNqYL,3ë%·IV]ôçËÌjGqéÏ_}ä+†ûÿšâ2®úä‚û®úäxŠc®²ÆJ5Ï?²Áðµ—öý!l=Pp?Ê‚nøGŒÙÑ ªy¦_wtÂ0Š#ÇË÷ªy~ZcÃõ/Îri"ïøª®š'£ã¨oHqé<=zò™”¹»…™xˆŸ?xúpŠË@쥟¾Òrƒ‘u¡CIw’š›ª¤û"Å¥{°®ÖÝú¿=ð±©s]{).]£÷OºTÍÓÒÞáø`{,zWýèìiÔŸâRÓ&MWs7¢5yh6ÅåƒmökRÏÃ@Þ»áÍ)žÄ'³žúd¤?_¤»¤Iñ2‰…cL}$3SÜiðºÇêÏ8ó]‚#Q‰á+ŽÀ‰vÏüîÆJªluØT§à‡).uÝy¶éy~úyv0yJoéø³š›'néxˆâróÇvPótˆ¼…†ëŸ¼åرR·”–Û26¼2Åe!õÌÂŽ¡áU(Ž>í±+ÔÜó£,jU]Kq¹ù†?÷â-*Ùˤë£áeŽÎÉÊJSôÜ‹fJWVšAq™t:²FÎPó²!è¹f2[pÒÇ‘5ŽNé†ïWr~€oøøaŠK©«<ûÛãÿ#x •ÉH€ï¦¸<ù¯ÖÞ£¾ùdíc¸þÑY.©û+~|®š§¢¹ám).ÅæºþkôÜnôß@qùÞ+½pDÏ=iÐ*½ðÅåƒÝ3¦§ž‡ìsÅe8ðg•~àn¼ ö”Mõ™ÏûS\†ÿ›tSs;í_Nq/Û¦2Á£D£?´©Nqi&V,}ZÍóÓaþ,Ã1É\¥F=14¼Å¥?_üÚdgx+Šc vÚ5ÌxÀÿ†âòÉÌ®>mv³Oîi^»ÙÇÁ÷ìÚ‡Ž©ÎK‰à>6û\úûTŠË¼MÍo&xÔ¾×¼°/Å¥…=þÇÓÇÖƒã<ËpL°÷O&86÷~/Å¥Ô5ÿé6‚#ѨáwP\êºÞ{áhax)´8+³C“kÎQóÀ"š\s>ÅíSÒìv›ÜÕ…¹ŒŸD·´æc—¿=Qòz-wýge~#Ãù0ºÉ»ê›Oy)¼¸ÑMÞ§¸Üü—U×?:ÏÁ†—7.«Eq¹úþV%ÕÎTÓXýßߪÃ1K|bÜõÍÛƒRàÛŽdÅ‚!ê›wýºÅ‚(.Ó}yÆè‹eYÉ«0žâÒD¦*œ¡q.–ï
¯GqéQ_ò“ÌYùÙÔý1*+3Šò]òÓ!ŠË8î†z€ÇÛnãg‚q±¸pÃ×P\ +í˜Ý¯«yÒAð¿áó).Ãÿ‹ +깩¬TyQa†cÖè´“jù?oJq)6·œ><³Ý&çržå®'ÅÆð׎DdePϽhÚ§¬“d8FRÿM½¡ç¶Ï¾€âÒ£žç65÷£Õÿ¥¸4‘?Ö§æAþæýk<Iq©*KlÑ_=é#±áŽ›Q<Û@'ì±¹–uÌƒTÃË3ûawý@Ë]/JùhøJ†c\tî<áñ°¿sl×üM†c‹Ù3ÁÅà™@è\”ýi£0?ÿLÐ…áôkÛXËtö"ÞŒâÒD.x³µš'=tÌÿűúý}úGçâlâ¸ômFT¯žYÚÈ’š¹Œ‹ƒÀoBqlp«¶^Ï=œ^gøFŠË£×º™šùY•Æµö(.{µó¯#x +g W;ÿ&‚ãѵûkÇ5zî£kdø ŠË“oÜÉWóDˆãiOP\†BÕÇ/y¾ýݘœáÑÞÀ‰SŽÈ†Oc8Žh©R÷C‚‡NÄWQ\êºe“šªy]Ýðf—b³`~žšçgU2¼&ÅåÅ]Sî*ðlJª<bÙð뎈—qíçj¹iNpüœáoP\#é‚»ô<ô¬#]ð;ŠK×xpU5ûß®Áp¬Œ4ºòLá™äù1*+›<Ç”îR\èK«¨æ68 +µ}zÅñ²s³ž‡!΃þjç6ŠKûõüÕ/Î
¢eܯ篢¸4R¿
}VÍmSî?Oq™«,8ê þƒÍŸ«,8êW†£WYpü÷ÁTÔEÒ®þƒu£dÚEÒÑ9pÂSé¹]Þ +{Çéy´oÂð Ç*ð{çܦæi/:•ø½sn§¸Üü3ó鹟Ä{f^ŠËÍÿWVË]Çñ +^‘âò·÷x#¸çóÌe<dQ3¼Åå{?öÍ=¢Ø±ož¢¸ôi«qš{öI~=Åe4Ñi÷ÕÜT•v£¸t6ìîªæa´nxŠË“ÿ¼Æ7ÂÙÇòÿòÿ‚ž¹ŒMQ¾ƒâÒ-¬tAƒãÿãæÿM¬tA#ŠË‹ÛûæðXLj[žö£,©{ßÜGqûjŽš›1¡}5âw‘Wy©–›ï§v¨Yìu‚ûˆÝ;(OÏ}3¥÷ªAq)´{J_¡q2‰~ť̟rtš'ÌþÅeu Ú¸êGgºu^Ä7Q\úóu:¬¿yÏÁ8®NçO(.7ÕÀúgú®)ðŽóã–.ÇŒY¼£yìïòCR
?Fq©ç¿?ÜUÍmÌJ¼Ã±"Vs@M5·yx=ð3(.ýù–mÞÐs/ÚÈܲÍ[—mk'æ~´ fø6ŠË`¤îž´Ü‰!z¿îžÉ—'_fCZÏ»°ËlhAð +µMã½(.7lÛ‚ãÀG÷3¹ûNn±HËÍÏ¢ŽÙÉ-–2ÜÇÜE…4x¼e{™ +Þ’â2gÕ¥ý]jî»ØkøŠK©»UÎPSñh3¯á—0…vNïzF#è9½S\*êknQóÀwÑ5:°æ6†cÎêð}ôÜÄ|ð[).ŦÒ>é×¹ÙƒÀrÄ2JÓ؉\ißK—R·£zp7Öb¢½Œ›–xZûQ\ÊÜTUÍSa©enªÎpd9ñÂ&5·„ˆo¥¸Ì×5ùˆ–Ûä{Rh
Jq)´gÏtõ<ŒŸ=3 ¸4^næ6¼~Åå“ÙTlƒš‡a +Çl*öñ#µå{Kÿÿßàó;SË#¶°å{ï0õGŸ§Õ7o‰|~ÅeÝ¢ÇÂãC–´e6ô±s¡EÑG’ÕºM´Üü‘ ,ežW·Ååæ•8MɽLùˆW ¸üí³»<Ep{Äfwy†âRÛŸöÁ£ö}ø´¯Žö}ï ÿÆÿç'cúàÿZhÿ9ÎÛ7€úÛqŽØ¾A—õºõŸLà‡ßLq©iO¾p¸k»ùNÄ'S\ú6eO~IË ü^aûÍ—B;éš?Õ<F‘“®9Fq¹ù97”U?:[l}ð +—Fjë_ÿ%^\tõ¦¸|qU>Y¨~téI؛`zòÓL±‰Î9ùŠËß¾÷úúú›Ï?ðqïõxäïSÀc%U¶— Ì“÷ÀO¥¸ÌœÙ)!©nÌͼv;«….Ù9âRhÓJ¨¹
C¹i¥ Ž'ßaßW¿g7´æ\@·Ü¢ûö}Õ˜âRl¾?é-·ñ°ùüy‚û(u/ô|LÏýh)ó…ž#(.Ãêg
UsS¼óùH‚ˆ»˜øÈmzøù| +4×r×î>ðÁ[Q\ÞûžÛ©¹âø9Ãÿ¦¸ŒaûÜ=PÍ}
´áƒ)Žì±œÆJƒfÃãÌP(ˆøhŠËŒÙÅK¤“›=,gxž›Ùôˆ—‹/Aq霴©<XÍM“6•ï¡¸L}\²9/ [6ªÒøY—R×{üùZèhžÞãÛQ\ºÄ}v•Rß¼ïcÿ»áe).Åæ·š{öàCð&—ö/ApD°ÞœâÒÂ6î}*ñè\‰52¼Å¥wá·®çaàGüqŠK=ÿ¨óþ“ñAÎð]—'?òìuêO&åFÁÀ#Ïþ‚áˆpY3ý£3M\Üc8Â2ŸUHóND¼(Å¥þñHkõÍ'‚º…?iKqieþl2L_l¢Ã¬
×—yË¥[XaÓ¢¢FÚÿ§¸ÌÛ|7TýÞíB.Æ2ß
-Bq©iüŠ™ÒlzµÜòLú=?â¯P\þö:
oUs»´áßNqiã:t<Ü•xÐÍl¨Åj`‡ŽmŽ¥Ì³ž˜¢çB•ŸÎp,i5Yr·š'=|ï†ßOqéÓŽj³PÍÓö8kð%—`¡ßVÐs?%Uþ¶2Å¥‰Ü9ü-7MdtØÎáCuÏ[<‰ô{ÞCq¹ùó~ŒxÌi^s{
Oqyq¥/?_Í7À\eéËÛá÷íg¬kæ6]GüŠËwÏëϨ¹©¬ +Å¥kTú몂 ´ô¯R\>™w–"8Nâ6¼ÃQÓØ\—â ð—õÚ3'蹂»à)Ž<äKK€»qy2@·Ðð2ÇF§Cç_©æ)/šò:„C‘”\†÷ý¾NÏ/î¾ß¿`8Ò>{œ–ÛÔaÄ'P\f‰çwn¡çùQÜó;ŸMqi¤–žÕ]Ïýh²qéYW0K™œ
îÅÚ¼o/ãcqÁð¹G#uâÐH5·a#!øXŠg©N§ÈÜ…—ÙÔ‡{~”„Íð +—bóB“ÒJžÙÅõM´7Ÿá8ͪF¥:à™¥ÌœËyöÔAA¡†7 ¸´°sËQ\^öÈÅœ©†§ògNæžÉpœ‘Zëàðxá÷ž—Ùâ– +žAð$ä +¬Oq©iSwNÐsÙ6†àB•Œ +žY\È]Y%ì‘ÊA1‚â2?ß`ý«ZžÙ¼ñ7Žùº1˶¨¹¤??fÙ7—)îÇOºTÍí¶Ê +xf›U®5ËS>r÷>‹âòèJϯæéhÝð‰ÇºÃsµÜµ§Ï%ÁÛP\Ú÷ÿ®î§t–´¿âÒ)Ý×°úæíÞBrÚíTŠËÍŸ¹Cóæ%À÷P\z•¥O©¡æÉ "õß)µ 5Ð-«·TóDt~œáêB›áødz¿-<ˆ•þÎ^Æ&ÏOƒ/'x + èZÜwã,"ÛËd6€·`8#—ùMÍÃ(Í©áQ\~ªÛJÍ]?JÆõSÝÖ—¾Í¹’âUÃS!Î2ü!ŠK=? h¬tAõü€ )ÃQϨýºš{ÙÂåó).O~lÑîjxiL÷-zÅ¥®+Þp´ž»ÿà㎥Ì*Ó*©¹¤òyUŠ#9χ“õ…ÖÅ|áSŽ``÷ŽÚúÊʆj×e82ÿýÔs/ºzÐÿg†£²z¹G7p/N`¤½ŒéW¡SúrË).ï}ý¾÷Ôܦ¿KÈpÌ—ù¤·ð0Ö·”òñ¢T!e>éGqéÕÞ,Ë:n¼àËSAˆ½µ7Oe862‡s®“›Od‡#9¹mÝqX†á71û"_ÙöÁŒ _Ù¶‰â2.7q Á<`ø ŠKÜE“9€ÇÚjdyÚváÀ‡S\¦}.?óU-·^srù™¯S\nþÑåÝÕÜ^ï€_Nqéhô€š{A½_ Ñ×ê¢m÷êúDûãÚv¯EqùÛ'ö¿I}ón7±o‚»„¾<²þæ½"Z_Ù˜á8ŽªUjžÒnÄwQ\6û,¾ÜÕ?:óßiðÃQYýì9Ä£s$a…áÅ¥‘š×S^ /Þ’VÂ5£wìýŸ×!Åð špk¬æe+ýwSŠK+s·ô7ïcYÇðS.Û¬Úýù†I'ÞDkÒüƒãiKq€ýÏ•jn‹~3ÅeªóÏùÔ<
šá‹Ž€™åo$õ΋*êåo´ ¸Œß7|WOÍCóÁ:à
).7¿³ýýÍQʈígS\j›£VóÌV'ðߎQäÔ6ÕÜòÁ~„áòâÚ¯ø³FÙ©rWÔI×ñ†møCGÄË÷gtRsÏE`¤á]).Ŧà«ãõ7ïDû"¾úÅå‹Ô|–šÑÉ>†Ï¥¸›’ŸVÕ?ºè(mëS\º[§=#Ü/cqÏĶN›DqéþçÒ}àn<ž¹žü.ÝOqyòÛ[ÔUs»%+
^Ÿá(´óû×ß|Ô·é0¿ïÉ—WYòU*¸ëæ§ò®,ù*•‡Wúàq57](dîôÁh†cÜÆExqiœà‘“'óc6.jBqi¤ÊÝx²’§3'qùà§P\jÚcî`8Æ°Çf8*«ò#Ór>”Ù’âR×5{©/só¨.š½t+Å彿wáÅànœÔ™d?š»xïÂ.—ïý•Ô< ~ÞðÖG¢’Â-_Ró0ˆ2Àn9…âÒ5*>©¸o!5í&=Gº†_Eq¹úü[V«yècÖÈðO).³c¿½ æ6¥´þ2Å¥²êtd«žç‡¬t:²â2šøù‰õÜó³ñç'ÚS\fj¹DÍý +?»“âÒ9I9_Í“¡‡)îôÇz‡6?%8¦y
_Gq^íŸL±Á“ßyíß—z¾l»™jn!ÆÖvsÔ<s¢”tºÎVóüD£†Ï¥¸L><xÿX=wBt¼ÿ)ŠËÌÉÊŠ÷ê]€|†ßOqùÞ´—¥
7mgrpûÚHÜðG).T•]ÿQrßtDZ&ex†£…íyÙjžp££¸z^Ö›âÒH
<†z>š˜s¢ÕµA¡È8aø+—«:õ=ˆ³têû—îÁã¿LÐs©ŸÈp<º'w?¤æ¦CŽná“»£¸<º§¦´PsÓ¯ÂùSSΦ¸<ù5ýOSsÏņÃ+P\j›ù—vQódˆ8jûQ\fNö\£/6nmêÜsÍ$ŠK#Uå›/ˆG‡3ÿ$¸‹\^M^‘ºyœ#öú†£ªûfS-··Ž9ê±oº—O¦Q1tJ³Ð¹‡M<€CÌ»›àxòí{¬¯æ‰ +¿wm:¶þÅ¥Þã´Psßw=oÓ’â2N ;VÜL@lŒÊ*ù#
ïËp¬EŽª¾Zͽòµ—>íÑûJ7ïG‹÷Fqyq¥ûÝFpì¥û
¤¸tNê™=9áfˆ‰ÃÓ6>¾—âØF=ðQâæ=Ì”8Œâ2sÒü¤«Á3ḹ'ÜL¯*ÄžPïg8bÈ›xMσü«xƒá²o¢}ÇU[ÔÜ÷p¾ŒáßP\꺶݊«¹}o/MðèŒÔ^jîæ¯ +õ:˜"¸ï î^FË´ï!ƒÜÒîå)ŽÜ|G›(3ð¶ûŽþü©±¤3ØüήlD|#Å¥sRºM)p'Þ҆ᾛ/ݦÅåêU¾Œ‘^6\'çÍÛ£&£Ý¸†ï¦¸4á÷›Áãx6ß%v.¾•âÒ«,×±£šûÑñ4†_LqùdÜ$r/4’sÊËûç‘
†o¦¸¼÷òãþ"8BV?Nñì{ïTjè}àn¬a`&€1%«†?DqÞ8e»š§œhøÄ);ôÜüùÒ-<´è.-·©ÿüˆ«]†ËpàO÷E5÷ÌÅÓà/17Ÿ¨Ö
Ür‡ëxÿÌ‚nxOŠ#·ÏCÔܦeJƒ?Èp¬„>7fžû!¶Ó>7æs†#{c»õ<L༉ízS\:ä£*|©æ¦óŽpÜQ63\¦ûÚŸÿ‹dó²IVs6‘æwIÏA¤Óù¿Ô¦¸tÌ +WyWÍíü| +GÖ…‚íž%x´w `»(.}›Õ#Ïf8êùÕ#Ï!xTÏûéc=w±„ÝáÁsG3ÁžûÅ¥Ø8³l¦‘L“2Ûdãp|qÎ,çÿá¹»…åúøéææK\äÑÏ(ž_ÇpôçßÉ›¬æ©ü£¸ÞÉ›Bqi"ûŸ‰ öì’Vî©dfG«tû7;‰ávù§jîç¥=ìòÏeþk³š^tÔæ+m¡¸4‘çÜ¡æ¦Â'ÓyÎ]—ÎÉ®²‰Û‹¹˜è¥LE†µkc#ŠKùk×OÕÜÎÓ:à(.ßûÊöÔ<éyM\Ù¾0Ñ!öáBýô<ð½ˆßNqùÞ—>ú•š§\Ýð-—R·}æf=>É«{˜ÞïXyß\-·)+<D÷í{âŽ{´Úb†ccãÑjË(.õ8$VpÏMaAm\½ÇnÜé›ô<ŒÂïwNÿúÿãìNÀ¶œÖ¾7Ï£ÊSš)Íu÷€dÊÐ\dL +I™‡a÷Š’D"iÐhHRT2U¢DJE(JƒR‰Ô·Öýœÿõ8¾½÷}þßãØö>Þ}ÿöµžkXã¹ÎEqéœ<ÿ€dMòÓae +å§Ã‚Ú¯R‘ÌwßÂp U2ü6ŠËWiþ¹à¹%¤2ÜTUèVšßŽâÒ£^¼óºãÅþOºcÈïGqùdJÛ«.|:ÀvÃc8Ò"õ<»¢žÛ\`à•).m\Í2ýµÜöæ±Cf™Ž~Ý'Wž¤çQ:vüdŠKÏêí“Nù ©rá¾i*BðÍ—Øåý†èyˆpä¸ÌYí½¿²šÇ‘;–hïýU(.ýºªØ‰f´²O>ä/ˆ¡‘ªŠÈ:Ž}‘Õ¯(Dð +âëòP\Z™ç[Ts?ŠSú|ëQ—ïýû]ÇÔÜtaÐD~ÿKaŠËK[èËBê×&%q T¡/‹Q\¶—©y²þ¥µÉ¼Á›P\èzƒÔ»=Z±zƒŠR\ZØè¬^ú»D%ÑY×R\žû±Kï">ØîØ¥÷P\Ö&j®–=à¡ŸÛöºÐÿç2nÍÕƒ).W¿èÅÝO`òá¢÷1óóÏäÍ!¸;8à™¼yÌÕe(Ô±~½G ´áOP\î|ÏÏ綴axÊø`ø—±L½›;ÿÿïá€áQèz•õn¾ˆâ¸ú‡•Ô…OÄö€×û°Åå곿Ap·röW#).mÜâ×—)àÿ„âòÉ|á‡Zîûn(dxLqi¤ZN[«æžŸŽ_¯ç6¼0ŸŸqáê[—“h&θð&†£G}ÝÔ…Ïáþ
Å¥[xù‚;ÁsÇ
óÃ*LqyiûOßæ6Oi¾—âòÅ
?íc5·!è1ørŠË÷Qý—ô·.ÄY؆O"¸;»ÖŽÂjnÃBbáÅ).]£Ä¦×Õ<iïø›—ºÐÌü¸ì³‰F³ÌdŽ[Œ°ÁÍðã î¶Y•š½VÍ“¾A—šý5Ã1‚nêW÷sYÊ´¿3_¬KLä× ¸ÀïmVVÍí'ãW¤¸L°?pÈSsÓ>#<ïCñ”Ù¥Ô·Zî¥Ý@Ìð-GHêÎ{FªŸp '
Eqyî·Ü·.ôr9ÔØþÎÉW§¸T•ÍòŽ0“ͪb8‚¾¼ÿz%ÏdæõHq©ëʶŸ)<öE–ÿì ÅåÁu¸¶3¸ŸËŠåÉØ¥MèpíE—Aè‚ÅŸ©y"HáX¢‹WS\:']ÚŒTótäv wió$ÁÝôQc¯Ws3DáGíOqi&Îiw9xN‘ù—qÉ6Ïiw%Ãqú/z«y""ÇûPë°Zézn™0ÃZÝN"n]ÇÔêÖˆá¸u7å4½ŸÎ^ŸBÛaq†£oÓoÍ$5·9"ðW(.nÖÅåÕܦpÀ+R\®~ðø³îöŒ<¾-Å¥•¹Æ5ÍsO‚Oc8Γú¢Ü^ýk»±ÌåöS\†e»£‰Œ2ÐÙ;ä‘m ±Å¬l÷?)./7´9EÍ=Ï57´9âòÒþÙ|…–›Ê5á+).Óû…=®ç~„½ÿ…=ApL}tlzp¿úÖű›³jzPÿÚXŽª²ãÅÂãLÒ†\xÊÃ9à†_NqéYý]§¨’Ût—!š‰¿ë” ¸¼u§<QÀS\jÚ7¼¦¾uÉ(‰qÜÞd8‚ÄŠû<§Ü3—‰Ø;PdØa†#‘ø誯h¹]öŸAqi 'œSD]ø„M +Ä5ªNe8B–•‰õ.v'–•IQ\š ÿaýKùItÈý‡7S\zVþðÑÁÇR\êù{«¹Âç”ò13!¡_gø6ŠËk3{óCz`{áC)._Ü‘çªyÇ(ü‘ñ…Ž>m¹™‡˜[‡]ZåfþEq©i›?SMx"¿*ÈÊvº
çE6¦Åeu QƒôÜ´°>ø—/5)ƒ×¡xþ'Ó©šBko]|Å¥WY9ó󉜒uØß…‘;Ŭr^EŠK§´þÕÅÔÜ+¿×¿º$Å¥{pã´'Õ<ˆQÓþ4Å¥ªœ;ù55·É¼q.ðä9—º®è[ç'2ޑⲸP}Ò¾ãÿ4bç$¤ª>é +ýü1xë'“ð0?oø'—ÊêîBÕÜðâø†c,Sí‡?ÔܦYM€¡¸À'OÿŒàîÈÅÉÓWQ\®¾èƒCz^ð½/úàOŠË÷¾ç²mjž‘òÑð— +ÝÂ"æ¨yÂЯ+Òh>Å¥…YÝ.çÙžPÉž+³¤`Ƭn™ÉGø}ƒ9“˜;/®Áœi—>í µ£Ô<ŠÝÑ<ƒÖ>IqùÞï¿î5|—þîþë¶2IÒ½ë«?™d˜@=ŸîÝ€àÇm?ô3 Uò3›¸³§Œ°i\¢QÃwS\ž{ãg€û¹$˜µ<Y~ßxD[ŠËÕýcÕ<F8ÐÙ1Žâò½/<RË}Ïå¯3|4Å¥ºøü§ŽêÂgÒ6€w#¸;½®ñ9¨.2›:s*|æHgð™—á@öSÕÜ&çAf¡ö3ŽÌýfÈ.l?³±1‡O&a[8ìýï7c3ÅåÁÍjyHÍS¦®Áÿ¤¸þ×b˜)Íßr’çŸé¡¸TVW/½ÜÏåsû»Ðôi}ðë).+àÇ6×Us›ö
Þ€áÈŽ[tÝ•zîá@gÃ{3ìC5Rsß
ÿ
JqYƒ®xsY-÷R†'Á+0Gó¼Ðv¼þÖ™G— + +挥8’¨ÿñ¢šÛD)>øDŠËs¯òÆ2©'^ÌeBdÓ2üIŠË»¸Þ÷jnúãh ×ÛBqé]Ìùþx}ác—&eÎ÷5Ž1ìï³Uó(H"ËÊï³FP\zµ+c]&CmöÐÄtæ4+Ç;R\\‘ +çwŽ²óLþz¼Åå·è÷jž0geøOÇœÕGÑr{ø–u>®¾u.u]µ[©¹M0›ŽªòØ•}Õ·ÎôÇ‘úØ•ý).…ïßXö€ù›}²¾´6ZÇs¹yû7^Fqlòš¿<·ðû sŒ·Ûb6 ñɫÛÛ5ÕÜfeJƒ×!xˆ0WÌÑó +?õ¼#jnƒBå¹O=¿0Å¥s2eß)ZnðÑ)²ïtŠËÒÆàÁWs:ÐÙþ.¦±|?xpŠËTçonÏjœ½² +ýÈG„›á?Q\Ö&~q¾šÛB𗘓[ÏÙ¥ævÞ' þ+ÑX¸ãW§ +Ï„.dMì¡ ±ý°_Nq™9<ëF5·/w +wûÆÅ.õñƒ>¢¸Ô´‡/xHÍ£(™“Ã<Lq¹u·Ý§æ6“X~€âRÛܵ}Šž›¯+>ârõg¿î¤å6A2J=ûuWŠË;€-¥ŠÂ›Ÿ¡O{à×6ÇaÖ¥·_£æqáLäÒÛûP\Þù¦%%ÇKcò|{Ž–‡hÃe¸Ì”¶;üì{à~NIZ· +ø—O¦õ_-µ<slãÅå‹:åuáÓƒ‘¡SÎ¥¸Üº§mÕ?8ßm«|úØvŠK]7þÆßÕÜSàŽŒR/uš¡¿uém_êô*ÅåÖM™3UÍMÑ1s2eŽ¾º°\©Ùëê?»°žGqùÛ_=\MÍ“!ŽT6¼:ÅåoŸûà>=wA¡†ÿFq©.¾¸xQQ»<¥_\üÅå‹[³ÿ-¢ªôBÇç3C¡—ÑWAŒ©;/+Nq¹óÇ.x]_Qîλ`.Åeò¡ôß¿êyœ@t_é¿ÕUe†Ë|]ýQê«Êоþ¨ÿ0\©Ž
:LcªJ, 7è0“âÈ–Y¹”þÖ…æ*[U.Cq™£Nnm®¯.|Ô´†·¢¸Üº»æ¾ ¿u±»uwÍÈpl»˜^¥æ‘ïŽPŸ^Mqt‰o¿<Èi³¹Là§×¨ãíƒ).ã÷Û'÷QsûÒyàý).ÃÿßFMÕ>ti‘~5“âRU–{;Ep—6¡ÜÛ§1L“ŸÑߺ‚9ê&? ¸ôç/þøÛ}wdÃÅ»=#žšz«šûžM<5õŠKá'ݼBÍ£ +õ¸Oö ¸ÌYþÃj5#(uúk)Ž«ÿy@ÍmªüŠË¼M3¾Só8´¡Æú—Ör™p»²æ05|#nøp†#Úgñà‡)sWÏÿÛÛýµ¿=xfw–亙ßÙÄD ð‹).Wÿ»Ö%jîù)™¯3üZŠK=_øÄjž(8r±ð‰Å¥ª[ã=5|Œãÿ€âÒÊ<ýè Zn†ß.ßÅÓÖ¥¸TVn£.|àa Ûð3).“â¿Jp„.>‡âÒ9©øfâ\R>f~çF*¾Q†â²|_´ÏÇ’VÑ>gQ\ +Ÿwc’à¡ïø©—6®ø~ólÈ>õÛ-¥˜%.¾ÿ)ŠËªÐÔ1ëy˜ŒÑ!C\Ýp™%®7á!5Oûnw^½ S\©ß\¥å¾ÝRš¿†áˆ³ê´û°ž®oÓi÷1ŠËÕ'l;EÏ붵¦¸<÷ÉKÏÒóØóoKqéŸêjn”ÁŸ¤¸Ô´¿³àÈ8aø·—ÑDÍwèyä2Õ\X˜âRÛ̾ü}ð ‡c‰2<r9ÿá²å¤}©2óÕ<°¸`øBŠËs??çƒù'¼8¿ +ÌÂö¨MD¼¼ÿöŠË ´è¾çÕ<òprŸá(.MäŠÏÖëyˆé}Ã7R<¿ðíþü6%<³…([šÓÌï×!7ül‚ã4«öÕÔóüƒâòùŸG^£ŠGÕ<Æ.-R¥Âǃ«xß
jnºF¨m*Þw3Åå‹ë‘׃¸u¦>zä]ÅpÄ_×õ2æÁ!üþº®Lá}$\1ýj5O¿bzŠËû¶bs¦ðhã¾Ø’â2õQkêpæµÁv›ZS£¸´qí6ëÿöD€ù:Ã=†c%ô¥_:ƒ›†/—ªÒn»@6-Ã/¤¸<÷JK/×sÓAÀ{R\>™º-^Rs?p ä붘LqéY=ZñN=ÝDë£3‹‰Ïy[Í#Ñ}†¿ËptN–~W[Íã¬áõŽV槿¨yºôŸþº‘áÈWY²hc5O˜d¼ÅeZå†×´Üƒ°*7¼Aq©*óNz–(¼Û›wÒ‹—¿ýߪ1·óóïüvÅ“Ò-\Œõ¸´ÜåÂ3¿“¡á).3¥í;>¯æ¦[\À_d8¶¾rù¦ðŽ_QˆâRQ7™ß–(<²¬ÞŽá˜tÚ8~4Á‘ÎÚð1Çáw'…Ï{FÏüí²¸Ðñý‹W«y¹mVï_üÅe{Õþ[À}˳¤Êð8J#5ÐUûog8â.¶½:GÍS¡‹»Øöê<ŠKYt÷-÷M#àÀ¢»÷P\¾¸¥7ôU>x±ãý).ŸÌò²ú[g F–—]ÀpܺOúnPódäû¤ï&ŠËûá5÷à +øø®jžŠÓ¼;ÅqÌh¯IZîG‘›x9Ök*Å%l£å’]êÂ'C,a¾›âòÎ/þf¼ºð¡K“bøŠË'³îɱjn†BòÜ
ŽâòÜ›]Ž/Îü·9q»é#)»2
¿ƒâRU®Z‘àúó«‡Çpôç¿x¬3Å‘»ï±n—ÅÄÃÏ'Á}˳ÙÐ +g¬]VŽâ2‚nñ‡þo7Ý7ìPkñ‡þoOÙ-¹ù.½IB•üü Ðì…·!ŠÛðK(.ƒ‘'ŽQó0H SúÄÑâ—/ns¹?Ž/ns¹¿¨«KUÙ~F æ¦}ÆÄKûÅ¥wÑã€þÖ~Œ ‘J3 'ë>µ<3ñ’uIËüÎKZuŸÚOqé´r»šÛ• +Çjž(Ho[ªpZÍ3'ç~ÕçêycÏȪϣ¸ŒeR]Ò?8/|V©®?S\úó5a‚=•™`Ï>Í›²Á˜9©ÑèAŠc5p[u5·KZIðš÷ñÜ;íùNËmì²çuÚ³…âòÚLzžšGQ +}›iC/ ¸\}a«ªúÂûn²qa«<ŠËœÕ7sbⵉqë¾™“¢¸Ä6u®¡¿u¡K“²©s-Šcâ¥ëúÂGØjdøGê€u'©y:Laùþ÷u'S\bS÷éo]œFÂÉÆ©‡(.5m·W¯Uó8D3aøõ—;ßd/¦>ò7>d¦lJ&Ô6Mö®¥¸Üºªí»(yÚÄ0ü¯ÚþB†ãè½R—©yàc·Žá+Ž™“'–oVóÐøVŠË¤Ó²
CÕ.åcUÈðaGEÝþÔö!¸ŸSºù$«óÔöI‚'ÑL´P^Íý8…w¾í€JÇé´«Öh¹—p••áë(.õüÜáú«Û-/IpýÕ3§*å2‰SNTß:[W%ÀO¦¸¼6Ï|õ!xfãCö‰—´]TÂ<í3_-¥¸<÷'®ß–σüY+jó;3Ãn'®ßAq¹úüsÁý\y:N`øüóŽáÿôO«h¹ù8ÌÚð<ŠKeµƒš{é3'†×¤¸¬œÐQ*«ÀÄæ0ñØð,až¦¸\}ò”ºjîG¨*
?‰âòÖ-þu³šÛÝ:Žo¥¸<÷º[¤¢¶¹Or™ú2±xëên©Jq¹úiÿY¯ç¾«¬NûÏ·Ç@ì寂g¦û²ÌØßù ^Þù&ÃoóÉõyZnw„"žö“ëkR\º…Óše8r6NkRŠâÒ§}õ¥jžr¹÷
¿‚âò½ŸÔñðÀÏeˉùYÒt +>’âòκu®š‡¡‰£nÏpTÔëvlWó à °u;vQ±Fƒè&Z
Oøˆ«4üÅåƒzÛ…êÂG›æzÛÅ—…Ô*½K·ÎmhÒ»Ãqì`òPe5÷C¹hxUŠçw‰;•k½O_x)Ü
ßOqùâVí‘ì÷A˜™hÍÚ%Â̦¼"Åe8P¥ç8‚'0©Òó†ã¥=ZþI‚»Øƒ£åŸ¦¸~ïýyOáˆÕ½÷Ÿ@qé®úe5óà°¤µê—5Ôs—ná#»Ð)
s›t2¿Ã¶Q?²ëtŠËƒ«´ñl-·)+ +øy—ç~\ÙqêÂ{‘K,|\Ùñ—/.øñT5÷1~lMqéUÞ~a?õË,ì€d8®þÄØ&zî»SžÛŒâòÚìûªþÁ…zÔû~«Îp´q=½¤æ¦=Arž‡&Q<’Fê½wÔ·.ù&ò½E—náïÕdÞ&ˆìVŽ\xÆéØñeJnÏñ°'tiÍõO#<oiÍM—ö½ØžßÀsÛìc~g#±àŽÌBy7îÒóÀV™wã†#Žz奴ÜKzI¤ËXyigŠËÛqÑR=÷Sxp;.úŒá¿¯º&çq +³U×´f8öÇ}~xŸž‡.#ôç‡Õ/m†Ë¸ÁìGõ¯¹ó1øŠËƒëžÙè”}ÒÉa…Ž/g8Âï›–zRÍ“náOS\n?¢‘š'\n^ÛR\ºÍ®Ãƒ³›¼r€âL—ØIq©.ή²@Ív羈âòà¦÷š§‚¾÷©ÇýÃñ½L#nÛfõE0“âRø7£Ô<¿ù3Ÿ/¥¸<÷×ÆÏm³Í븃^ûÃѧíÒ·Ÿš‡QŒiŸ.}<à“’§ è?âÒ£žÔên-·f8iR«{).î–5çþ/ö¿ +_õaø—÷Y›ïÔ·.¹!ðgm6S\©ÅG0ù¿Õ(ëò}`·˜¹8êÅGêR\&¾{£3Á1’2üB†#†ü–qxn‚D&
šã1ÅeÞf̪sÔ<ã¤NÃÏ£¸Üº8¥4wn‡XX€SJ•\>Øu+¨Ÿ´‡´€Gqùâ/µC_øLjþÅ¥ðO
l¥pQ€ö©ú—Ör¹ó+xzºÅÄ•
"ŠK¯²D½úW°W¨D½FGªÏF%OR?8»%4®¾ºáØÀÞñå¹ËÔÜ4’¸úËs?%xÁÕß:¨¾uæ—H¢þò¼Â—7åõÒúÂ{®ðS^/Gq©ik7‘`¡ ›U.<¹ããk7iÂp™hm÷w‹Úà~NɸÌe"{Ð=xSŠK]÷ÌÁIZn†ÀÈ gøLŠK~I·mz^p4Ï’n;(.³…ËŒ' +`[¸ÌŠK¯òœ‘èÛ$ƒœ6÷ÙÁ·ïFq‰|(ršzägŸú°Ç”„üi†c,S&… öüð¼ì±´go²îQ\ZصÍïÓòž±²¶ùýG0ðwß«yàZXÃ7S\ZØåg¯VߺTè–ï—Ÿ½†â2SÚw+FÐù‘¹Þ´pèUöÝVˆâRÛ,zh¦šÇQ„t‹z•â2gõqü²žn¯ÐÇñ‚ûÒD¶ï¹OšÈÐËmêÃîð’ÈåÕs_%ŠËß^õËÕ<*X úNOŠË{>xŸ(<ŽÞ3ücŠËk³{…4Üw›¼¶`¯’Ë;Øc®š§"—"æ`—6îÒj'€ç6ùÚM¥Aäxm†#áä3_VsÛ¯óÀ§R\z•ÏÖ?YÍíq>xSŠËs?§äïj, ŸSòŠK¹§È%jîÔ´{Š\AqsÒyj1ZØ“NjGqia›û”þµ‰1KløÓÇæý_^í£/¼é$À¯§¸|°Ý_—ó"Ãü4æY»Ä6r!D¸áWR\bW]AÍM[*ƒÃ£¸üí#ïÔ>r™…FÞKqiãÚxµÔÜݪP¯.ñ*ôåèYÄ‹°œ÷åèWŽÅ…¼à +½ñà\ÞƒBï÷ ¸KvU¿u6Ý%²ç•ìª®.,Çr^zö§úÊÊÃÉ}†Îp̘½<çG5Oš®M¾â²:Ðaà¡ŸË6+»ž—Üu‡açR\*«°þ—Zn{¥ˆ%믥8®Þa”š^Qa‡1—ʪW¡Yê[—òݑʽ +½Fqéœ|ùÀeê›—™¿| ÅåÎw¼ì%𜀳<aê*|2ÅåÖ½5¬‰šÇ‘VæaÍ)ŽAèØŸôÜðÒ¾5vÅeêcڑ£œ1·¿“…ùü;‚§ðÚhš6Î$aË>ˆ3iÿœârë6TüYÏ7Ù¸¡âNŠË"rÏB»Õ<]p@LÏB¿1ã¸}ïÕó(…¾Í¾‰«.݃÷vzî6ûž ¸|qõ~ÊÓr›ü·®ÞO'P\š‰Š#ª¹]õÀo¢¸Œ on¹JÍC™ÿ
ÿ‚âÒ5Ðc¬ž±ÌÏþ,Åå{ì¥jÅ)TÔïíÁpTV“NyQÍゼ…“Ny‰âRQWXŒf"áå’ +ÌòDèÎH°x'ÃñòSÑþjž06üFŠË¶äcõ…÷‘AÎðn—צÒüJzî2^âRøã»%•<‘YØñÁO¡¸þÔ¶·ªŸ +ݦSÛÞNq¹ú%‡è殺Ñé’CÚ·.êT§Ôhp?—M^öw6»ãc(Ž3´Òr/í'GݪAÈplh¡/|ŒrÃ}†c!õ¸à=}áãf>¢8¾¸.ÓÕÜô§±&u|—WŽÉÆgw¦ô·Î…ß~ÃqõE7ŸHýíxêo—öýë?Û¨yÂeœ0ü,ŠËÕÖIÿÚ)\ýçaR\ÞºŸ_ü@Í£sV†ÌpÌYÝؼþÖ…)7ycóþÇ^à÷®SóTäá¤÷~ÃpD¼Ô;:<§m•ö2aèrûÔ;úÅ¥?S§Ô<aSä€ÿ‡âX;Eu?Âù°†e8¦ûØÑVÍåðã|~Åå“yèô"j¹,©†g8–°ç>Ð^ÍSvq¼#ÁÌÛ¬˜ö½þÖùIT•+¦ýDqE.¸ÿeýóÝA!îŸJq™`ÿà‰ñú6FbaÃ'R\fNvž©¿uq +uÝÎÁ¯2uÝÑkÞžÌ,ßûYy2óÉÆà‹).ÕÅëªèyŒpÃó(.쾯ƒç´Ýò”cWæ¾s).YRK/èKð@úu†d8ŽP·Ùh5·Û½cð±—švͦnzºùù5›ºS\®þJí£Zn×1‚~¥NŠK—xê#ÔÜÔÓ±ã#)Ž,+‰õzb®Òðo).Ó}Á§5Õ<4u]¼ÃQQWÿÏ%j¹è>Ã/£¸¼u³¿Y¦ævš9_Aq€?±ò_ßùÿšôVÚ?±ª(Ååo¯¨“ºð¦ªŽWW™ó¨åƒ™|[Ï}:3¹€ârç;7ž-<•Iéœ}Ò)i#¥ +ø—iŸ¼SÀ3«|Ù¹íSˆâÎ[1âRYU|d¨žnº¯â#P\Ú÷óÖnWs3äÓyk÷R™…þ +Ô¼`¶ÐðÅ¥C~ï4©œR…Xn×”Ò࣎¿ýÎî¦xü^†#ù–w>Us›X8 +ÅåÖí}³–š›w…ßû¦þÖY.l·›>rèÚ«Ä¡LyþÅe÷ý#þ%jžqD‹á—3Gë.ï^^Í£0…—vy÷JÇ™Jû×¼§åö° +ï_óÅ¥>ý°¯çæ.)ŽDâ£eÿ»za.‹‰öw~Ò¥1]Ÿârëª}?LÍý‚+Õ¾AqùÞßVQ_x/½Ào#n纫ÞJÞeé\õŠËß@pwèá†Ô ŠKû^º/UxœøPºïÝÔß._\ýÞf^yç
_Hq¬u¡þµ ÖØðK)ŽiÞm³Áý\Ž›´Ü<Ç_g8þ[1®¥š'#lt2< ¸~Ó³Óõ…/€ozvÃ1ᶵÁ/Zn:' L¸mm°âo³oñéê›^]ìx[‚‡8Ñ~ê•»Àƒ_ZÓ#F+cø^ŠK]÷Ÿi5ügxkŠËK{llüoü¿RÍï<S]à)ŠKM[kàr}áCä!7üSŠK¯ò³ËQYEvou]â(–éƒ÷ ¸<÷/?œ©æé‚ă_~ø*ÅeÆìãÛƒû9rßqôžá(Ž#Vý æÛkø—«·~m‚šÛpÚüeŠçWV +Õn¨æ±I#exŠËßÞpË^=Œl¸åW†c,³îæ6jžRžãgQ\¾÷µ×œ¯çÆï†w¤8Ž\ü^fÈmrò\ÐÍïìɺ!xkŠËÒÆßéǮ̿ÓßQ\÷nï¯æ^œFöÞíƒ(.=êÏtbxäxŠË'Ó¬üý3© +3õüÁ§kQ<¯Ap·K«Öß]Ô<i“Õ_Dqéܾs‚š§ì—1|2Å¥²Ú;ïgð̤Sö6mg¹1~ß;oÅ¥‘š>2OÏ#·_fúȚǩO¬æAœÂöù§šR\>™Ç[Uó(ƹ†£8#ŸÐóDÁ&î;Ÿxžâ²ŒûäkKóy™•Ûê;ÄüÉ×VP\æ*‡}W<$–u¢Õp{°p +¼Ã1š¨\è$=1ÑjxcŠËh¢ñ ñjnòøK—zkíÎZnêidY1üB†£žO¢¿u¡Ûà–<ð Åå‹{÷Fú[ç!_¥áÍ(.»ïË•Ð_=#µáú«[.ÏýžÁÒ1ìP¹=¸”}R†/£¸¼´K?(¡ä6*Ômæ]úAi†ãÈÅ°Ùjp?§$l™ó°\â‚°ÙW—®ÑRžš§ +Nd>P*Aqi ªÐBËmVg—a¦‚ºð–#ÃÌüÊ›Ž#™ÿâÒÆMÝÜ<“¨$ë4¯½Lä~3£«šÆ°†_Dq©i+~DÍÃ0(à#ŽLbsŸxšàn5p.:':.ƒ‘ŽM'Õó(DÒ†¦JR\:äGoøJÏcL÷þ
Å¥‘jÝåw5Üî<Ã1k3®Þ¦æ ßN;ãê]—I§Ž›vèy˜Dm³©Æý÷ºÝ:›jLc8V¦n¾€ªmüí»©¿]èJË<m`EÊaò!ó;¤2< ¸ÜºŽ,Ps߆F‚/¢¸„ë4j1\_xÏå=hÔb$Åe,S¼øhp?§”PæwAà&Z‹Kq©¬>j‘Òr3q¹û>jÑšâòÖ•mwºðQàòY•m×âòÒÎPU_ø‚³óæÈ£¸¼óó~ýC]ø8Jc–xÞ¯R\®¾ë=·SÂà2éë½Z^Íí@¼"Ñ|¯Ò‚2z ŠÛp¢ðA(ŸLÇã%iCŠœÛM±ôi
¿˜âR]xÏÎÔó†¿Fq'ýñ¹ZnšÈ4fÈ'~|űÑiB}5·µE +¹,©[kÜFÜ:w6îÖwR\Z™™£0È1ɪá)/ÂiV3G5b8úó³o{[ËMÙ‘Þðw).oݼr·¨¹MTâø—ná–§¿Ró0r§œlyúkŠK·°äÝ+ôÜV˜à+).ḵWܣ汗ÀÆÆÚ+†P\ª‹ëÑ£Ny9¥x5¿³’àO2ÛmÊÿ2HÍý‚SÌÊÿr;Å¥žßÛçB5·G¼Fà—P\ª‹#Ÿ¨äfèû¼1ñ vÆ)îê~N¡‰A*³$–oÈpIÒqâ¾ë˼á(.݃õ»^Qó Jb»~׆cÊk÷)³Ô<,èí>å5†ã‹ëÝ°‘žˆ|0¼ Åe¼p`eðÜb{˜tZ^ëQ\f·ô¨æÉS^†ëo8⨷&dÓGör +Ïl@l€•‘ÅO~BñøgG”W¢Ã1ì]7Ñ ¼wµ>ÇK{C¹ÇÔüÔ
åFS\&O˜9™(|„D%'ÌœNqi"?žØ™áè˜}<ñB†#TiØó1ÃQ]{þŠË`¤ßõwÜíTêwý}Ç`dï·çè¹ïö~{Å¥{Ðeþ¹›_áë2HÿÜ-—¯8_ÏÃúó+¾Kq¹úìçß!¸Kž?ûùE—צMéçÀsKok~ç…XÆ5üEŠ#T)š®ç’°>›ârë*Ô߮榉ƒ«PÿŠK÷Ô³Ô<i»1à¯1éï–}÷Í¿ñÿÞØh~—°ëÈàßS\îüî2;õ.ö°cew™Ý—1lâùîjžp‘†_JqÇ
šTKÍã (àõŽz~w1ÙZæo|È: +NöùáØ!†c8°mPo5÷ +Ž“Þ6¨Å¥²Z}ÈÕ68u6+OHgxoŠçqíŽnzƒà±¼´†¿Gqùâæl\ ç¡k"çl\Hqé×®\’à!:ä£+—a8ÐÃ’k¹o^[ì‡
K>JqY@?öö=÷CĘ{{ÅåÁ•X~¦ž‡¸ºáP\®¾áâ>ê—,8~nÃÅ×S\èþR¿6¾©¬0gõÁ_Ž9«®©ejFAþ)ÃѳZ::¿¶ 2oCËy†Û4-ø[—îA…›¶«y*F|á¿P\ú6ç,þXÍãùë_Nqdé¾ +ÜÏåðz{™´‹Þ7üŠK·ð»/×s‡×~%Åå¹wú|=\”W÷§ÛS\>Ø£¦ª¹]ø‹À§S\Æq¥^¤åf8„xÃß'8FK}7œà.åc©ï§¸ÜùO×îÏÌdKÚ`yàG¨¨?]»Ÿá8Ô¸òÒçÔ<,ÃV^úÃQÓnêyPÍý8‰ùºM=ÿ ¸|2ËšÌä” ÆüÎbÇʲ&³).o]Å£5…‡^.¡Èöwvצ¸FZ~¹HÍÍp +ß«ä45=—y WÉÇ@¬U™×õ<H¢‘jUFë,—x›:‰Âi©¬UÏCl·éп?j›Tf7nÀöïß„áÈíÓúƒ¾z^0OÛúƒ—w~{ËÂJnϲJ¢K¼½e1ŠKõ¼æR<
>ሣ~aãqzâl\Ãó(.“ÑèœygðC—îÁq…Ý÷áíï|›j4ŸWû¡Åå{/;ûÿ´Ü&ëÀ/;ûQŠK#uo·[Õ…·é6àwP\ª‹£}ºéyà6÷íÓâRQט^RÏ#ìÎ3¼Åeî¢þ;ÿÿ×6«wÓ}†w¦8Þ~“¾ð.PÊðÛ(.{‹Ë¨¹ÍÁîxy†ãÌ…¼éˆ»°Ûçsã±ï>ؼé_èy€SJ;¶îú‚šGá?øK—Wh=¡ùBeǵ¿KÅ!\¡õ£Ž(¯J£Ú+o·UºöJ£:S\¾÷¢“PÛØíuÙƒÀíïl"ñ4xw†£sRâ„ÏÕÜ„åUâ„5ǦΎeß8QÍm\füd†cÊ+,RTËM‰\†g¸ôçÛW%pßór9RÙþΆ&à—P\^Ú[ßبævs_|ÅeâåÐ';™Âð_Žôõ…+|Í…+P·{…Î|êp?§å{ó»L%øbŠËÕ<´@Ïãæ¨<´âÒ£n¼àG57¥G¢’ƶQ\ºÄ§µ¿”¸uneä´öWR\þöÞÇÿ¢æö ßKqi"Ó]®Ðr»|ŽF*Ý¥'Å¥sÒsFüü㨲."›Ÿ%]âû03f}?¨ æ)ßå5êûÁqDZ_ËÍ÷s9ŠË^ÆNzÅà(.
tÉ>W©y:@6l,¬É$x#·!+Ø$O¥¸´q›?®æ~ä6¼,l>ZÏcûYùnú›«ûàÝ)ŽÀÈ7$îÂN+äă̮Π+‚»ð¼ÂûVR\¡[V÷sšÞ·]33ôÁ«P\ÞùÞ¾¡æ)w,‘áó(.w¾jߣZîÛ#¤™¨z}!†c{ð6_Í1'†Ç—º®Hמzîœá½(.]âqc&ªyºVfܘ)G+Ó`Y35||2†·¤¸üíMÿ¼TÏcl)5ü +ŠË|ݬ»ÿRsSO#…û¬»1\ªÊŽ—»GÍAXÀ笠|26è#<ôÒQ"Úd\8ÄüÂý(.®îÃÍÕÜW‘÷(.ßû{ÓoWó„Û¼oø]—šöÇ>PóÐOa¢õÇ–2]£ò=?÷-Ï4b/§e’Ùð5ÇšÔ™kÚj¹Ÿ*83ñÌ5çS‡Y?¾KÍí°%ßKqùÛÇkæ™ã2ÀÏ ¸TV畽XÍÍÿ +õ|•+n ¸4R§?{Á#tÈO¶Å¥›<éTõKÆ.Îjò¤Ö—º®lÂjžþÇêâÇP¯Ú +/«¹é`¶pG…©—z¾c©{éy!gc©¯¥¸4‘õÞøLýàB›ÚüsŠKÇìò>! +#§Óå?¬¤¸ôm&?×VÿÒFnâeòsÄ'¹½#/~<øü¿CR
·Ébð—(./mçýþÿŸ…OF)|2÷?Lq©.ž¼¨’š§|wzÝ“Ua8fîn^e*3Å5ùžù]*H"+òÝ-Þ§¸<¸'ÿÓWÍM#%Ã@ÃP\îüˆ%ô<ð°¹oÄ’¦÷Q]øoÕß:Ïm¯óÞNq©mÆÌ8[ÍCÛ.?âÒÂFMg€g&Z³wNÌ×滓y£¦¯Q\ÜÌ3Rj„X—1üTŠËÕ7%¨ybmøG·Ðó´Ü<`|q†‡—·®ÒÊê‡q +Ø+Ôÿí–#oá媹Í7éøQ†c¾®Öðeú—ÖÀþ ÅåÖÕ^SUÍ3)©À«S\jÚ¼ö’`ÖOg–6²ó´=‘ m\^û).#©âGת¹o +œ…}ôkŠ#Åë_ÿGpkÐ¥þÆpdËlûçàv}3‡¸
¿O UHÛ?;R\VÖ—ÚæA¢ÒúR¿2ƒÐf]ŠéïaUÈð—z~yÍõz×hyÍo).kR_ñQx?t|þ£Æ"=w••áK(.u‹Ú¨ylÿ ~&ÃåuÍbiãL“m'^²¦Eòív›ðA—®Ñ=ƒ¦ê¸ý×1|ÃQø¡SšR<
Þ‚á84á™ÿ4Vߺ´çry=óŸæ—z¾Åª–Dá1sb¸ÏpÄö¾âb¢ðÈåeøeÔß.Óûaïõà~®…#¤¿3ü[†#ÎêÊQÔÜÎYEàR\þö¹ß徺¤
s¿—á˜ê¬·õNýóSIÕÛª.|†K÷Ào_ëoßHqi"·ÌÎSß:ßE÷~ÃñÅšx…ºðæÆá{/4ñ*†#ßE‹%mô…#×D.9‹âòÒ¶O½žY\È(eÿéb†/¦¸\ýãEÕ<amx ŠËôgÍkéy#ªó³æuŽ©ß-øFÍ#mø÷—ê¢ÖÌ=j']kæo—Qäó·]m"ì‹4¼Å1s2òu¢ð.iC‰‘sŽÚ¦ÅcuôÜO`u Åc'R\ž{݆øöˆ«ì[3»:Ý©Ä5vßËpìýï?¨9Áž7Èc8ú´ý'ÜÇÞå5šp?ÃñÉÜ^aÁ}\ýö +óŽ«Ïû-Ã¥[høùTáeƬåâ†÷ž×rqŠãX¢÷1¯
¦÷[¾·„âòÁz©Lákä¥nd8&£ã«P_œ^Ⲙ?˜¢>ØüTŠËKuþ‰á¨¨S·S\ +FpõÅ…àWP_œt®hÌeYÇðtÉT§á5(.ÕEµoVi¹
ÄÆÂJµoÖ0˸Ö~§æ^†Žÿ@qéÛÌþ¿Ûô…˜p›ýwR\Ú÷%Uæ¨y¢àŒÔ%UÞb8Z™¯JRsÓºcÇÊW¥3ÜíXùîc5·ÛCÿ„âò½7¸½þµ‰=[Ðàö~G=¿û úÂGîˆÕmÝë0±—6„›f/—‰VÃmòüx’áh¤ReÎPrû»0pülŠ#mBÙRà~Ž<³Õ(^žáØ>²ú5÷\sÃ÷P\fÌ~{ëC5]z[×3¹÷ó®SÍ{¢3øÛ—š¶ñôcú[%±2ÒxFŠËÕWUßJ½u>øvŠK·îÓÁú[»5©uŸa8*êÒdžéo窋ÒÇFP\:f'äý¬¿uf‰
×°†£SzBͯõÜO!Šû„šŽ®QõÇ1ídBÔ²O6Ú 5áVýñCÇþ¸No¿©æ‰Øí‡íôö|†#@nuÉ$äo!ÏÎÍïü8r|Å¥w±}J95Oî@çíS*R\ +mÓÀý¹Íè„E¥kkµ¡8Žm½HÍMŸL•ÖK(.5í½k¯e‘³&´ß…!bÌî];€âÒ!¹oš›š±‘û~%x'û,›\HÍC»Û¼Å%¦ô’jrô^¿ñ!k@¬m#b·ú’jP\ª‹Ñ%¨y%‘jt‰CÇ1dçÎ x„)¯æçÎ&xŒ„Òé-’Ò9Hd†ÙyÂ" +Wßpá
z¹“>6Pš)<Ô6PârçÞ:Bÿà|œViøã—^eõKôwÞôh#ÇõwÞpÌU&Ó°zÔ†—`8bžÈû<Èm˜4]bœkø—Êêç£mÕ<ŠCœþóÑv—·®ÄŸôÜmö1|;Å¥sҦƻjžŠÒØNÛ¦ÆbŠKûz‹Žjžöpç
ïBqi"ÓÏ•Ps›ÁÝñÒ—O¦õUóô/mâLäÖW- ¸¼ó׆ˆ5Êßf•}(”2uM8^—âÒ¾ÿ¾û57mœÀ
ïÁpL6žß¸¤¾ð¡‡˜“ó—a¸;ÁÍÃæÎSQ‘³ýßžŠÜAÞ»–zj¹ó&Žõ÷è²3Ô<±.cøÙ—×&µðoðÌÄKö%l{0;:µ¨Ååêo?ªåvƒ›Œ¤Ú_¼£Å±€Þj»ºð±‡ä<†ï¢¸üí¼EÍö@kð;Ž4§;Îú]Í£Ð%œÜqÖÇ÷^nÙ/Äkƒ9+Ã÷QÉu‹<Ep“NM‹<Íp,ièÚDÿÚÄnûüˆ®ÍŽõ¸×oüZÏÃPb‰
ßÈpìÊüiñÖÙ$tàÄ[góyå¿´ys䈖 s_öt{+løfŠK‡¼ÃêJn·UºMVÿÉpüí»¾©ç>N»0|,Åå“™Þc–šÇ¾ÛZ8½Çë—u™5oÑ>J!lcÍÛÏP\ž{[PÏçop˺¥ÔüÎÆÌà˜Ñ[î`8VW:KÍí:n¼-ÑPú„zŸé¹é’Gà«).ì
k~ª¿uA€Ä
k®¢xþÛ©ÔµcµÜKÙV +|Åeõ¿ùP9_&Ìßb–ÃKkº)$m>´Ååµy®UW5OFX7ü"†£›ÍCú›!xþ0Å¥¢ðÕà¹mö íðù¬ßFq¹u[ý‘zî +1|4Å¥™(ÞDÚ¸0? 6ë»]Cv¼~˜âM,óÕ<a?¬áñÙgô…÷®cø5—ç~ÿë©ÂÇà).ð¯N<8Œã_Cqißkµ-Opt
¯Lqiß«ïw·.³ –u³á)—×Èðï îcøÊ»®Qó´âÜ+ﺎâòÎ÷s…–Û£uÑ«ì=¦Å1åµg°žÇŽ-ø}ϊ˃;¶1æQ€%lÃ[S\¾¸S>ªmB„¨^—âR]´XB]xSOûŽ—¦¸ô.¾\TÍC+#†ëo¹Ô6EÒIýkã¹ÄÂEÒ§R\ +_â´#†ÛV70`¶E¥üßÙ“ûàÇ(.w¾Ö“{ôܼ´øo—áå.'©¹=ÁO¦8Ž)¹ xfò!n>Ø p¼Å¥®;8yžGH\`øo—Wìû¯Õ<Ø\ìûo(Ž£÷¶öPóÀ=wÃo¢¸|2.ÕÿíA¢®›péŠK=?cWK5Oygìò c¢uÑÄÞjžp{B
¿†âò·QSÿà"»¬~+Åó_›NÅÎí¥æiSQ§À¯c8‚Ë=3UxèeO‹”ÿ;Û)Á§S\ú6eîg?'ÿw6¡´ã£¡O›7î*-·;ÿ1á–7îŠË÷ÞxPeuámÿ$¯JqÇÝ^§æ¾]î¿žâò·/)ö¹úÖ¥BìÎ3üKŠË„[¼&m"wæB¼æTŠKmÓ¯Íã̴Ͽ/.Èeâ4öËôk3œáØzPÿò¶à9¤îÏ¿L¥Ç/ 8ο$RóØO»sÀ/IQ\^›™
ÿÔr{¨2Bf6<Jqù`?+X]øT„³u?Âp¤»,5»¼þÁÅiÈ•š]‰áÈkôQYâÁyîlÜÊžÆp\}÷»õ…S¼Ã1õQ÷ëzà™ðûœÈ¿LfG-xCŠË,ñ]ßTó¸`’ù®ƒo3»´Ž«ý‘ž»9j×S\Ú¸¯·—TóD€F†—c8âmN:wñàüoø[—6Ùú5·ù¤cð—öôi£õÜÇF'ÃÇ01'ÇFŸ-<ÎL´fo íÞy4†ŸGq™p|Ú¸8‡‰—üßÙ#“àI†#ò¡ØôÇ´ÜK{1|Å‘÷ M¨.¼ç¹žUƒ6 ŠË¼M·ï¨y"D§Ôð÷(.3'e.–-'~þ–Ò채íˤ“ácžÂ¶‹‹/A™Èa3/x8~Å¥gµ}׉jîň-4¼Å¥®+½õ-÷Òa•Ué_1É=õ…œ˜ÜÓ…âòΗûà9áÉLXæ¿/*åÿÎ~´>ø—Îɱ—0ÉììÎaª3ù 7ÃGQ\jÚIåúèyì6>L*×â2üo·k®šgYŸOqš0êM5·‘9þ6Å僽2ø„àÈløçGöûÛší"8–q
ßGq™t*Á}z¢SjøÇxÝKç«yÂC`¤á(žÿÚ´ûsRY57M©Du^‹â2®Ù½„ðT‡&äÿÎN¤ÁË2S^“oéJð$ÒœN¾åBŠËkÓåêëÔüa™]®îGq©ëVý\OÍãÐÕ´«~n@q©¬j¼{që|ätªñnŠËßÞ¹.¾÷Tfº/{™2—N`ݹîƒw#èx—ž›A¾‡âRÏŸ6tªšÛTâøŠËláˆTU=“Ø7"•Gq¹u_ú™þÖ….PêãK?g8êù£µ¶¨¹Š!’ùhGöë1_—ö²'ÎçI— ÆðÓ(.ò¦¿]¡æ)›Ð¼'ÅѯÛ<EÏÍh" >áh ß,[\Ïã=«73 èÔ\–ï;¶ò_SóD!™v+.ÅåÖ/çnïçÔ=HÛ5`¤ˆ)^nÅ¥_wÃEýôÜ
>áh"_l¹…à1"Z_l¹•âH²ZüS57#1¤ú¬VüsŠãdÞ—ÿÖr/¹}R
'b8¦¼õ¿uîà?ßb8šÈŠÏ²Ëebן¯8°-Å¥‹·¯Ró N¡Ooÿ’âH@wôo=÷‘Ãã ÇŠ0»qóZÈÔ‡Mè—÷ó%’WcûM—6õXc5O¸ÅDÛQ©û·d +åû¼ÏR»Ôu.}<3ÑšuÊËmøÈédøóG@쎟 îa=îØŽ]—;j\[ͽ Ddã©q}ŠËÕ»=«¹Ñ¨ç»=œ¢¸Ôówž¬æaè"îü +Ã4òóØõ.Ày‘†7 ¸Ló–[<]Ë=»‰Üñ™—¥
ï²êê›Q`¯ÉpĘuoDÜù(…¶{£“ŽCNWôš i#·º¢—þ¥5¹÷§ï”Þ…ÍæeÛè”ÿ;ó/ÿOßù4Ѹ`^•9JîÙá +r8¼^~çEîø¹^KŽ…ß]u#xGiçÿÎ\kß]u3ñÿýì¿«¹¤8qößÅŽAè _ž›½™°È Œ¤½ø&Å¥??µó`5÷ÂÏ}jç!G¯²Ö{=Õ<]F©Zï]Íp锶/ÖtµšÇvÊ
|-Åå{3«žfÆÌê@q©ë6Üþ¤žG.?móÛd¢ÕÏ£ÎÞ¯Mß}¶ÿìÿqv'`[MmßÀST*Í¥RŠŠFöx
)E‘†»BR)T”R"š”1’4 ™•Ò<R¡¢A„H„fB‰4ã[ëºÎÿ¾}ÇóϵÏÿñ¾<Ïq¼×ïÝëÞ{íµ×p®sœ¯æ6Ùf +|1Ãѧ-ºä1%ìR&Γ*ºd<ŸóO©è×™;_ˆºóRmFöê#u@ö2Éü¯#{u£¸l·)W·šÛïËpDq—ùužš§=3jøBŠK§ô³»¶ƒg&ÜrFšËx¦å‚隸tNjí[«ç>v¤¾âÒPïx¯ºšû¶o^“âÒP—z÷g‚ã”RÃ÷3‡&Œ¬ÙBÍÍÍCÚ„‘5/£¸4Ô»‹µf8^™ÝÅÚS\ê|Å[ôÏÝžñ³)._ØŠ‰Šzîý‹W!8öÇåíù±¶žûÈjx]†cæ¤Ç{ÝÕÜñÊôxïzŠËûì©ÔÜ|á0CþÙS}(.Òâû–©yÚNâ.¾ï}ŠËÕ¿ {] +~ÔHx"ÆAŸò;Q܆7a8BR_>VJÉ3蘯{ùXY†Ë|]›znsðÌ{Î0-s™d~sQϽ”áØ9vÁ'jžò’XÚ»àsŠKáË&W¨¹¤1Š,›\Eq™æY`¶–gö@¦Àç1Ë÷ußxBͽ(ñ á“)./××?MÍ}/ÀŠØõõËQ\:äëv>
sqÁÅݺu;§P\« +6«yÒI`8P¡Ó·ÇƒÛþôznn] +‡•Ós?”€XÃ+R\F‘\†HæìfŸ8<FB]pÙKGÊÇGJÒr×7#ÁøQ†ãÎW>І)|ñv—¥
§ë»jž]<w§ërŠcÒiÈoú[ç!zßð?).
õžÁ§ªoû6xqŠËß~(ñ¦ºðö¸¶ø;Gß{KIáÙN9Ôžðq”¶áå(.}Ús& Gvs蜽L*t–y΄åGö¼µÜ†…",3\1ˆâò·Ï{阞›qXüo†KkÓ¦ã@Ä”¦c¥å)Û+šâÒ%>¸·ššÛ,j>øY—‰—ó.Ðó;Ð
_LqԺdzÜsâ%ç1ÿ6¥GcÎø‡áر╖Jëe¡ss×èŒ7Î+}'Ååo¯¼é„šg’Oÿ² +ì6jÍ3îÖznc³|iï»ÔÜt °´±´÷0ŠË+sÛŠ§Á½XÁÿæ2¦sFüY‚G'¼¼ôÒl=±ÉËð¹—ÞEâP5OøQòüÄ¡b—ÏÄ]%0Òˆ*åÇ5¿Ë$n +3|"Å¥ð›žæƒ¸JÃk31äE·®RsÏOaÊ«èÖŽSJuܧæ~~oø†#¢uû×2[ègCVrFl§ÎÁvZÃçS\&Ø›ÓZͽ +?üNq™hбŸšç/ß~Åå+sFÓjnÏõø—¯Ì).ÖóüjsÊGks~ÿ©Zn§ƒˆÏ ¸¼°ÛÏîg¦¸ã>:ù|>Åå}/{yWðÿ+Üu‰3¿ËA/{ùµ—U¡v…Æ^#<È“»ð
Öфá×±…m&ö=<3ùkqÁË^MóNì[›á˜æ=tÉ]jndöÀGRiRÇ´ÜI™‡‡¤
©¿).ÝÂúcVªŸÑÕÇ|Hq¹ú›5—¨¹çâqÃßa8bÈwÜ£æ®t†ï¥¸¬þNVóÐŽP/œ>ÊpĘ]tåjnÞWÌœ\tåW—xÚ]×é_ØÀA¼Í®ƒ(.w¾×$Œ"ÃÌ„[®M™ßùañs(.ÕÞ{€Ç:>ÞþÎñqL‰áR\^ØÑÍjž92¼Åeºïþo'ª¹ÍYþÁ1g•×p:šÊЋ³ÁÍòT˜FØFÃ'S\ +ÿõ]O8qÒed~焲åÄð6°ï9p3xÌyÂvIqõ=<‰@©9Zë¹yr ðv—Niµy7<¶®Ú¼›(.W?2©®šÛá@Þ€â84¡ÙÉjn‡#Èü߬Ã1ŽkòÈ<5BD2¾ˆâò·—Ù~LÍùw¾Ìö¿(.¯Ì¢û==÷‘˜ÈðâöATÚ¤'T)ó»èè=ÃûS\ÜèäÇW&ùÑâµi8ç‡äâæßQDkÓpÅå¹Ï›×UÍÍ`c™y󮥸T›…î;úÂ>Ýå—ç¾áí)jn§yð(.ß÷¿îÓr'í;˜Þ/ðëï—¦²ôüOõÜ°ºôüÏ).ýù*'õÕ?8ÓÎ'ÀûS\þöQ·<¤.|*ðº0ê–Ç(.3äykO9q’çg~g7Ѓ¿Éplö ëWÐsÏÅuX¿Åå#ujÁJn6¢3O-Ø’â² 6u6æmRnœ P{™dèc-rêìZ—)¯ýÛ©¹}aC𗫯ü x¬5{ÏÇ7Ã?c8^™“?ýSÍC7Ê®sò§GŽ–öã¢ÏOg¦ûrÓ6Ákñ)ž}pÔ=k£“ý]h²…×+AqimÚ\¯åvÂ
³¶7R\*m¥Wª¹9 ÀS\bÕŸª¾u¾mö©þĆ#ëB²d5OúQC,Ù‹â˜1»¥½žGIZ¿‚âRëÞù\bì:Sœ v×±aøÏk3{Ävﬦåö9tÈwï¬Eq™òZ:Iú´öÀÞá:^öHeÄ–NZÆp‰%Ϋ=å +¿ûŽîzµ1üz†ckáî»+3…nÝÝU).•¶øíÕŽ®QñÛϦ8âiË×wÝX]b›Œ+ÀFæÊŸKqi¬š<:GË]›c5 ¾ârõ%-fêyµuKZÌe8ÂóÚ4”Õ7$–»¹0Ýé +øÇŸÕ§8Nê»QË3ià_03¥×7ÙîÅ +”²‡:HÆeøfŠKC4‘ÈÏ.eƛߙO4¢¼‚&Å¥cv~Ï~ànœCíï\/Aèù=o¡¸Ôºí¾¡åö¸ +œø°ýÁ·)Žð•ÒÞVë<TŽâ2¬»xšÛxXÄÓ.^Çp·
ºRÍmÿ5 ~ÑÊ{ÇʇÔδ³Hw¹cåŠKïbïÄKô…ÏÏSºwb+ŠK[wÒ®¾ð>¢y
÷ŽAè]¥Ô<éciÃð&Ç+óW£à1‡Bv6|5zŸá²ÞúØjIà%bv‰Ž=ýÎßBq4Vsú¨¹eU2üfŠãð»¶_©¹ýD'Á¿f¸|"ó÷”ž2B?2îYŠËÚÄWßWVó”—Ìçg2ûþG檹ÝLœ +YGœuþÖ…hç
¿žâÒÎ[úuµÉÏWix‚#_eÛm%>TÞü'}l+±–âRø}ßJ¼2Hcøí—na÷·P…wÀ¿c8ÔŠŒ:•xp¾ñÓ(.³F5~«.|˜¿¸P³à÷Çq“«%™3%”=Ü6H"¾®Øêñ—¶®Ü÷Ô<é²÷ßð<Š#oá]«ÕÜ4Ôœ˜w×Z†£¡^8´“þÖ¹iœF½phWŠKá:½¾ð^”ló§Ó;P\>õŽ|¡æé0Ú‰\ïÈfŠKSyû¤K´Ü5O]£Û'µ¤¸ÌÝ~€ºuið? Žøº6«†•ÏLqç7—I8„6¼"Ã1Á¾ì57=ò(ÝØ—.qª¹=a5â·3kÐ…òž% +ŸŒöŒä=Ïpì9£Í^5·~8c¥Í¯—vþ‚#Ùô8~¦“Ÿ{89aÕT¼7Åå3Ñ>ýŽš;a›¸Û§—S\êê³Ë‚ÇJƒfy*HcgbõÙ(.-í”!›´Ü.â¢K<eÈW—W¦ 7T_x‰‰Îpz¸ä®}½ÌÖÂ\Ë÷ö2)‘†`8>R%v¢Òz±R÷Ûˤ£(nÃP\ +ÿi¥mZž‰O€ï$8Ð[i[Ü‹³¸`yà‡2WixŠËû´Ãl5OI?âó(.w~õÑâÂýX/~&ÑgàF¼$Ã1)WçšÛ†Ö?JqùL¤:'ÕÜ&ÁQ\Z›ÆµUó0J_oøcÇ ìÅŸB[Äšò²¿sòSjÅå…ýö‚ jž9|ÅÑ=¨}HÏÝ”¼2†c8>ÐÏ¿<3ε°bçùQê€gŠßNqé],št³šaW¹hÒ-—çþk£êjnÈàgS\«_/œò¿øm5²¿³©‰ð(.•öÏ#Wiï¤Ì€w¦¸TÚâ
ÇéoŸ@ð@ñ†ã)ž½z»—¯Qs»÷ßÿ˜ârëvUŽnçy™iûœÜtߤCnxWŠKC=p×
zDawÝDqì/ðžðÐ.¹«Ð ¢qœá뎕ë~XÍ}?-f×ÿü(Ã%ý]Û-½Î¡x¼ÃñÒzuCŠàÅå}¿©hO=ðÂ~Á“˜â~ߩı…ï;U(.߸¢Eîw-Ï–i)'âC).“N¯Ü÷¾š{a4ÉüÊ}«Ž©Îy£ÊéïâtZÃOg8fÌæ¼ÔCÍM‡C¡9/õ¢¸TÚC{jyfò9܆ö¦¸F*Ÿ˜/|~–•Ê'æ1[ÈëŸÛO]ø´‹9à(.{ƒ[ëïajx;†£ð·ï¾W_øÀAèÂí»d8VFŠÛ%<aó@¹Â°íï\':̺ظŸ(.Q/ï}GÏÍF|9Ãq´nŸz×€gHîÎI±IÔðk).=ê…ÒrÓ\D)#6z˜âRm^½{¨¾ð>ry>’àQ.¯›úUn>º±>‘¦_¤4rS¿Ê—ÏÄúBÔ<¶aø!ŠËÕ7—›Kp¬¿¾âRëö›šÛô< ð?(./ìïg>ÆÜ:?sÃ1w±åY|ãlN2Æ@Ì‚–FN§-ÏÎg8v¬œQbˆšÛm.øpŠËÊH‘/_÷bòÌ„›>âò™¨páP=£¬.IqéÓ^¼ïZ‚#®Òðž—j3ý›ßÕ<p†šá‡(.S^Ç—ÏÒ>š91|>Åå…-ýç'jž©¸àŸS\:äcÊîTs×GÖÃwS±ÛÞÔߺ ZXùlÛ[—:ÿèGxp)'‘%ÉÁSNà§ÕùèG‹).{»I«¹âꆥ¸\ýÆSÏPsÓX`ÿû§V§8âižîZž»k”²qÒGá‡g2+#½çÏ×r7´{+ÁRioš¬æf$ƒm•·ÝôÅåÖM~øu5ìšølŠËgâÕùŽšÿ+ùÞ«ó†£ÒÖÔV_ø‹J†·£¸ôëµ¥æ~4Íkø¹÷ð™Ôç657-5¦}õ¹ƒâÒX=X¹¥¾Ò:Øèdx+ŠË,ñÏQ7© ÌO<¬n.,GÖ…EwMÔ?8óKü)ŠK¥]üâ…µ[nÀõM¥åRç¿-s¹þ…uòàË\Iq€o¼°¨š{n”iã…Å).ÕCÝRÂÓvGBŒXÚ.ì ÏÉCÝ. ¸4Ô³¿VÍSa”pröï=).ûügZi¹=–Èx;†ckáÞEŸ«ošiÌ×í]ô%Å¥¹x¶D}=w¢UàgKœOq©óU;ý¬¾uN”Êð}÷pbãñÏSÞ³“àųU»RîUsßn°Wÿí.}›-K[€g–qsO2§m*oô¬¶,mIq©´›KdS}Úô#©8Ó¼öwNt<Íæ—S\:'+×r¬ƒôÆŠ%).]â:_-ܵ¹j{Ìhƒ«óñ5—¹‹VG_ÓòLj |Å¥©Ìûþ#uáícøz†#Ýå°/n&nô°/R\:'ýZž§æ~˜DÔG¿–.Å¥ùâvõƒ³•ÖßIqùÛׯ®.|à e„ágQ\úu;Þ•)n{„¦yasB»62J~ˆârõƒßWóM}üþ4ŠË'²Ì›W€{1¹kÓ}¦À¯b8º…ÞÙÒ¯Ëtòc|&äø9¼'Å¥±:æf5Od8&^þøî6=·©FÁ4÷TÐߺ‡"^‰âˆŸ¿'¡çºÄ†§)Ž‰Ö[·h¹M‡0ÏnýŽârç¿|¨Žºð¡ŸÀVâ/ªÏplh-ýÜçú[ç…ØN[ú¹/).ýùÚs橹„F™Bç,b8þö¡'¯b*-ÎÆzòG—¿}ä}ÄD[ÌFÞG¼q†Ë`dßew3…—7Îðá—>í¹£e1Ñ$Ä™`·ÇšŸ¦Á_g86¸}tÛX57ÿ+bÝ6žâ2GýÑ=õ<Úvax†cu`˃ƒÔÜfŒÄ8îÁ;).“B£žÑs3J?Ïpäî[ôÔËZîøù§˜-zj*Åe»ÍÀËõÜNh(çj¹¼ï³¯¿âiðÁ£požn‡ÿ¹7¸™ËQ ”áPoÜÃÕ<ác7®áy—þüsËnÒÞ‹r°?·¬?Å¥©,5÷CáÙPäÜ
uøïͼ¥æ®¥¸4VçŸu@ÍÍ'Î?ëÅåê-Sï€Û‰—·.ŠŒjÓ2µœá˜=¸oÞz¤Âˆ¡¸|¤¾ß½LÍÍGAàßï~ŸáHkük£Ýjžðä9ùµÑÏGDëÛFèôaø(ŠËÔÇ/;iyfŠ;~ +Ñ]gϾýêÂÛ.yü Ã;ü|e1'^Næ¤ð;(.߸ZãÛÜCóZãÛQ\:'“S²SÉ͆&Æàö‰UàÉ©U—ÎɱÂßèy˜BáþŽáxeßÿ1xfÚ'wCmSB9˜9i|ÿ§Çv›S>é.<®ƒÛßyË<å“—ñ»ßæ5wÂ4Þw¿ÍMGö§o@:»Œ›3m‚=r1ôœˆ?Oq¹u=yš§¢ÐDûS\nÝæu¯©¹Ý7‘ŸÉpdœ¨ºp”–g¢q}ð)Ž@èZ«¹èdø'Gô~Û£5ÊO;±íe¢®‘áå).
u±Âß«y2ÿ¬b…·S\n]ÑUÀ3©¹§¸3©ˆ`/º£:Ñê³Øý빇Ý÷†_JqiëþF«yÚÒþ<ÊpÌ×}0êN}áƒ&Ü>5Œâ2ŽÛ0“Ì™%쯌=~.mæ5¦¸t‰¯›p½š¦oæƒ÷¢¸üÕŠàiüÕá¨ó;ÎRsÓ5Ãòý΂óôÜ4uÒ£ßTV…ÌG3gêÃü΋rû~ųµ®]™ëÞUsßþÅåÁUlu5xf8³[èÙ„ÌÑšTÅV×P\†ÿ—³ÕÆuÌàÎ ¼LQNn»óIðŽÿñ·[ŽÁȆËÔ…÷Ãè,ì!
WQ\æmîÿ 3q뢩û?èÆp¤ +)2âu¢ðÂq‹Œ˜Cql£Þüš'½r°ÏÙüÃ1Û>ê-wÒž‹
ÛG=Æp„*]td‡ðlèBÎÆÊüΞ'í€ï¡¸|¤jÝFð +]¨uÛOÇ1dmÿSn‚šûæê)ð' ]ý@É1Zn†BQdã’S\–2WNéo‹¨NÃ/ ¸\½VeÙ¡æÙ¯OŒF†'Ü„ñCÇpཙ€ÇÛؘ9øÙ6?Lqypk.{LÍíø=Ÿ@qùH=¼¹Œš{ùÁÀo®Hq©6=w¬Us߉V{îXOqù¾OîðŠš§ÌG»u:¼Fq¼ýjmðÌöºÜÝûÎ «’áu(.¯ÌE¯wPsr‚_AqàÞ]R…x™åûÜÓ¼^v &
Þ—á˜pK¼šTó J¾gxšá8W¨õï‹ÔÜ‘é÷%—Ö¦è_²°âeRsO´ÚRLs᯦¸T›j¯¶×ògŒ¬öê•Ç©§Ë*°—]ÎË9 +|$Åe8P¸JUáÙD%9ÃïÍï<;å^ƒáIUzô"-7È4¦y+=z ÃQi·¿®æ®ï¥£¡Ðë-).u~wßqjnžfw÷ÈpDûùòýƒ3]3|+Å¥©¬Ú{þÁ…¸u†¯§¸|"þöþÖy¸ó†a8îü˜øÂfs7Ôv11Úb6¦Ã†#gã±öÏ©¹0aWæ±ö/Q\nÝ´m€gÂïÓ9yÒ.gæóÑljNm®îÅäÿ:–ÈðûŽUà/jNp¤¿3üRŠËGªCùjîEÛ.ßCð +6u–y‹âÒ\¬}ï\5÷óóÛ¬}¯Ã‘ý™Z2šðíFÑ+†Û”)ð—Žè¾µËzƒg–urN6úÙ´F.x_ŠËgbòµÙ¹=|ÄùoþßFž0mU¼Ãñ·ÿ1ù©ÿÅÿÏÂ']¤t6üŠKSé\ù¦š'BÕƹòmŠK²Žr·¼žæ€Û˘ÆRº†/£¸Ÿ)Ð<³¸«ÒÚ˘ûŽÈ‡g +\Oq$—ƒÀ4<Èß÷Ê]).•¶î”>jîyQ«;¥/Å¥_W÷ð=úÂÛs³ÀüíÍ:Rs'Œ‘5ë\˜âRø÷w4Vó¤úoFqùL¬¼p„þÁEÃÃGQ\ú6:WîÅJ8iú‚;t®Iqyã:Þýž‡ÑÕ;Þ=†ârõ‚Œµ•ØþÎÔ™-4|Ã1[øù–ºZnºP2|¾¥!Å¥ÒîØSD]xÏ&ÿ/Æpt̪îO ÷cmê´¿3#p¤1¯º¿1Åeê£ä…Oª¹ ¦ÔðgŽ˜“ËêÌÑrûÄö²:(.cØQsg»2
ŸMqé”N:¯°š‡Q¾ÃO¥¸T›‹vl• +,³Ù|`#¾›âRë +=ÚAÍ3›Á¯¤¸T›aÓ=7]£< ¸4•·5ø@xàÄYHµ¿Ëd6|5Á±|ßæµûoÐs{pøM—:ÿüÖ¦zžšÕó[/¡¸|ßk—ÇG*È,açîØÀ‰(YíòO1óó/™£æ}và(.©ŸN]¥ç^ +Ÿ‰ŸN]Cð(`柉Ÿ«y¼3ÿ’â² +\fé¹ZnGqHñZfi=‚ãËk4s¡ºð¦cåEü
ŠËÚDÿËô•6LËÜ…áïS\^Ø;'LWóЖïïœ0‹âÒÚ¬¯×MýàÒa€Ã°Ö×ëAqi*ßÓ^x˜™tÊýMc•F‡üñ=W0g*ÍŸsXÉM• £ãeçÏ9NqIòWj +x¬Ðû;'J²jø|ŠË+üy-·Và[øs‡àÑÁ@ÕÇvRsSçÐ1«>¶+Ååo^¬°š'¢c‰/FqéQ^ÚMýàì–ü:ŠKÇìé;û©Ÿ£nOß9€áˆ·™~í½ú»X2ü‚§–¹lÓý+ãâlÇ1}›CåÔߺü©‡Ê?ÌpìH-ôiuáÝ …ðûBŸ¶¤¸|eÂ%#ÔÜ3ƒÈ$ø(‚£µi»¡ßß±¥2—±Gu +¿¹ÅåûÞshw5OºÈ{`xŠKßæNVsÓZäó¢—WfSs¼q‰Xìeì¡LiðáÇ–“é0ÁžˆµõÀ^Æ毋øQŠËZäŸåÎQsSk1û³\ŠË;6ÐÓs?åG<d8&Ãmø@'cÙ`çyÈŽkøµGžÒUª¹öqÁ×R\ú´^ctRNœ†Ûn!f¼Æ>Å¥o3ì`}ðXÉóíïì îøù—Y£Ò¿Ór'eÛjð¿).MÝåÓõ…£ó"ë.âòµì{uáíÁÂIðí—vúmCô·ÎK!AÍôÛ†S\®¾eðÃú[Mïþ(Å¥Úl´[]ø„æó½—ö¤:Ñûž™êÌÝ9±AE)sRŸâòà·}YÍÍðMeã¶Ó(.uþÎj5ÕÜnTJƒ×e8ê]g¯æ™äƒàÛ(.·îÐÕ? +OÇJXag*Öe]ý3Å%êcÚw;ÕܳÛÑÀõ…÷¢ØÂ65f!`&ë oËó—5<ârçK¯]¯åfé`=®ôÚÇz\¥™}ÔÜîûøÍ—)îk¾Sß:›ø;ЯùîrŠËÕûž[Qÿàl7¼Å¥¹6¾§ºðŽÍ» +®×sG¬Þ‹á˜ò:¸çðXÇQ>³´ö|Hq¹óÅUó ÀÄ‹áÇ).·®ö“3ÔÜô#ð«ýä,ŠËs_åÝHð«ÿ«¼›(.ÃÿAƒÑ\dCRsNqÛIÞ¨3|Å¥_7ûÇwÀ3a™9'mPfÆðöï2 jŠ¾ø½–ÛÔ2ocøŠK¥=u[wuá=?-¥§n»žâÒ³Ê[$Q^æŸX“N®Ýk-mä-º˜â²6ѱÖJîÙ”Ò^Ä_¦¸´6Û/xÜ5ñbþI‡8¦ÄðwŽ-fî qƒXØß™.±ñ —[טD¸¹™ ‘…þ=½ß؆£ktjâBðXÉ÷2¿s¢µSÍ).ó6÷4Òr'á{^Ä›P\ªM±+ÞUó´A»bÅqõ3ðܱÚË„nôÊ;c!ÃÑÒ–°NÍA{é Ž¸‹6ý¾ý/l¼‰VsSekÔïÛC÷±ú? AmÞµ”ixè!MŠáõ î¡{н|w=·3ðë).ß÷ûî)îÅë”&ì6–u0Ã1‚þ¡Êj5½tñµ—æâ·{ô…·»_Á÷R\ºû‹ß ææ#‰oÜþâ}Ž[Wõ¯¤ðdÌnaÒ1U©ªþÕ˜â˜hóšš;ùnÃæÌ¢¸<÷ekj¨y`ú´øÙ—«{éf5÷ó߸o/ý†áÈ_w÷Owû¤Fq þ?üº…ÉXi,O:ÑA`‡ßšJqi¨ÝÇë¹—ÀBªûøßG®NïÐ3ZnCбSÉ;ôÅe[³Yá™ ‘Ü|œÍ€ÀHqiëæ¼}£š{.Öß
ïÇpFJÔ¾<Þ&/ÃC~Å%L«LïBjž4Ñx=N|hów>ZîÚu™ˆßBqypáèºÄߎ€Ã<‰r|ž +ÿÑÅ_©o]*ÀqT†o¡¸¼27!IÔýì"rži*ÓàÃ1Ž«úôF7¿³ ©\ðM—‘Ô{×¥þvüqŠK¶Ìc6wcm!7—IG‡ÞŠâÒÎ_2ó5Oè˜Þ‡áHs&âsûo'â(._رG멹]WJƒ7d8VŒZù”úÖÙDhøÓ—¾ÍûÕÆCf¡‡^Gqùƽ^¹„þÖåäýzå’—«ï*ÐN_x/Êgµ«ÀÇa—¥®ùFÍÍPŸÈR×|OqùÊôyð€ž»Ñ~™>þIpœ›÷Ü›ÔÎÂ1üîÍ').Rn½XÍ3‹xK=÷Ñڮ茛‰æ—vÞð—á‡aët“6r!ô°ˆÜaØ'—Ö¦s»ìœU˜=Š+÷¶Ýÿm·€O£¸¼°cÿ^¯ç^ÙuÆþý Ååê‹wÞ¡çN4O»xç]—[·|sBσ茕å›Q\žûŠ¯ë«y¦¹?áÈ\bÞÓjzØ^gø³÷À7çˆþÅeæä‘ãýÁcMqÛˤ}Ç=rüV†cÒ©êŽâà^LnŸÃèUw”f8†Ç:ü¤ç3|Ã1HVv…gäÚNf¾!‘%+‡—‰—Ö›^wãfçiOÓzÓ4†Ëô~›iÅÞÒr›àÓ>ÓŠ-%8Þ¸63ïÍSó´›Ä†—™÷^Îp¬Ö·F}ë¼0Ê Wcc'†#@nôènjš7ο–â2C^á‡]jn»Lƒïe8¦y‹Œ_,<™«sbçØÀLð· Žµ6Cjâ
MÌÕ1³¿sݨg5¤æ0ŠËø}è×3ÔÜî«L‚Ï"xô·8Ý×r›,)#œž¢8¢÷Þ¤.¼gÁÁû3½‹¢#¯Ô>H ïAÑ‘Ž¼
¿üVÍa”5±á—ßQ\îüóÏ=®¯´æ_8Éë¹I—«¿Øã7}¥uÓCnøï—Ô—vÏ,çå +Ó²<é`ºÏð—9«o›7WóD}ã¾mÞ’â²{Kµ®jØÜýà×Q»q×<¯æa˜ÀÕç¬y™â2Á¾ãìõ…·yÁ×Q\¾°î$<Þáwöw^ˆ¥
Ãï ¸,aí8_Ïí€/¦¸|"-+,ÓþΣ¥ãG+1aZ½ÕÓó :ñ¡w£ó).#èMc_RsÇMb·iì«Ç~™ºë_Ñró‘Š^غë_£¸´ó?öˆºð6-±þÅ¥K|_¾Âã¥E²¿óÂ¥î«ÑŸâr||yï&5wÌ:
>€áRiÛ\´d§ðl€\®pÐO¢Öþ#ÃñÆ-Ü{‘š›ÿˆÞ_¸·9Ã¥±Ê«_þ€š§ü +?³eMâÖ%óymŠK¯ra¯ÕÜî¨Å¼Mo).ݱÛÛê¹ ØØííŽhÞŸ?h&Ü•Î:´ge˜¡˜Þ‚âò•és¬%x¬ö2^tØ¥ámŽ¿ýôY2‘#r.¨¹vÒ&ÊC~ú¬Ÿîa0Òok[5B!jý¶v¤¸ÜºK>l%Ü7±¿3ÑxÅ¥¥mûÖ*5wÌç=¾–áèÝ2º–Û.±ñ¢—Æê?/SóD~2í7þlCqyîç7ÿùM>œüݺDþ®Ìó›ï§¸,&¯Ò…÷⤳Ü4U˜£.^¥?Ã¥ðí*îüྃ4h;×R\Úº³ÇKð€/%Tæ$êü£÷Î?™âÒ5zb÷5Ïæ5|6Åe,óôχô…÷pæ‚áG).³å'¯Pó”="|%Å¥w±qZK5ÿ×zã´V—ÞE™ýÝõ…·Kýà×Q\Æ2GÞÖ?8/×Æ‘·ÿ"xtÊIúàà™¡P®
ìöw¾ŸDS™>8šàþ·yõ¯&jîE)#oFqéœ=\MËtè!‚½è᳎Èƛ֫x! +¿bÓ'O +¼Á±['ïÐÙMõ·ÎC¯Òð‹).Û.>N-<+}}æwnQ^§Îa8FRµ>Æ6Þ‘L™ß™6þÅ¥ðçmNj¹©4QæÀó6§).wþªªÔÜT›«ªv¦¸| Üÿ=xÌé>0ã _7àþí—ÑDƒEeõ<Œ’ë6XTžáh.Ò+†OÇ„¦íYÔ˜5J¯NqŒô¸T¦:cfNhÁÞ@ß%8ÖeÚte:¸ç@gËm—<>“áˆòöy¨æ© +oj³þGÁB†7§¸4“ÏVsÓ3Ķ‹Éç2;R÷¼x¹šûa2ÊÅýâ•—I§?koÖr'eÞÙˆCq?ÿ57E>ˆáE6>e‡úÖÙ`¥|Åѧí\ExÌå{›+ÃKù?“áX‹œÖñp7ÞÄ‹]ÂŽæ.¦u\NqyeÎ[ åN‹öI
œ·„âò+ÕGòœdæɽ„móöQµ)ÕçŠËkÚâ(xÌXÂS‚Í>M[œ ¸\}â•›ÔÜÆ‹§Á73+ÅšlTsßIK¼á_è¹Mm™}pwO˜¬æžàÔ»'<Ëpd]hw:&²ÇÓä®´I›0Ñ>íN_EqùL,›t·–›lÃÀe“†R[ßÛ®æv+p|'ÃѳÚ=ùTõK¨ó†—`8|¼kâ7ê‡~´¤u×Äï(./l¡ß0‰¹‘Ù˨Œ
ì…~«Oq–š~\Íæc*W/5£ +Cô.VÛMqùÊ4™ÚN_x/…T`M¦v`8BÙ½F_ø Š³úe÷:ŠK¯Ú¿që´ÁðΗ™Òµ½.$x€¼k{5§ž»ðšÍ§÷2“̹Bìïìë¿Nq„&n+'ÜwâL>ž9F‘Û*2Û.æÕ¬äöP¤jݼÚwR<[ëÚU¸b¨š'CD2>œâ2 +O8ñ¡f(æãê†oc8¶§×´TsÓ9ArÝôšÖ—Æj敃ÇÚØhgÑ#¾‘âòÊŒŸØXÍýü¥ñ/¤¸„.LØCËMçi
¿‘âÒ»(uíP5O˜§5ü†cž¶f©Nê[ç¸Q–•š¥ºR\zßăK:qŽ—µ¿sœhø?üÉ‹(.µîŒæÃñ…=£yŠâ¨óí/!xÔ!ß¾%Å¥¹hòzU%Ï$ CÈJ“׫S\ºÄ‡ïø\]xÏ2¾ã+ŠKµ){c%ðXÛi™ãç°:`xUŠKsqï™Í´ÜuB¬¿ÞœâÒڴ꘧ænD¢’V/§¸4V·>6K}ëL¥‘•PÃçR\æ*O{þq5à +ü‚GçÚ[…¸uH4jxu†c·NáGèï&$ÜðQÇÞ¯÷Ôs/:ÿ½ðë72ÝÂEw/l”º¿DÑŸ(.݃s‡¾Ä¼2¨óç}•á¨´u>ÄTœÿ^÷àŠËß~žwªžû!¦¸ÏóJP\¦¸ÏŸïͲaž ¸\Ý™rõ‘ +ÀϤ¸<wß»“øL$¼ˆc8ªÍ%/Ì¢^™4ø\†#¡të·•6úL´~ëÅåÁµ]À|ߣ¶í‚×™;¯LÞ-©TÞ–âRøv|F¼°É â›<ûÁ£W¦ó³/2<ºúsOè+çG3Ï=MqyezÏûi*QëzÏ[Çüí¨uý%‰W;Ô'º…ù±ÄfìÓó0D÷€P\nÝÀÍÕ¨6 ~ñsaÐS©¦2>ƒâRëîúSmpÌè=C—R\ +߸qTCŸÈpüí÷-ÙÆptÈï[²›à)\ýÁ½™±fNp3ÅåêãάÊtNÐTŽ;S_ç-—æbÂé©Ni +|ñ±qò@}ÇÌsNĉ÷ÝMDG.>Bµó.ø ŠËqú÷ÔÁ·S\Ü++ÿCõ¬ð)TC-wþÕŸÆ3…#®ïX./ìrïR¦©Äz¹×šêIµù áBb(ä8_Bqyp«=ßÈU‹ž§¸<¸Õo½J3Dv·^f8îüúö5˜é>µ¹¾}-†cÏÈgãn!ºFIô.>G´´aô…ÝòKêÖàÝ).…ß¾¸‚žÛ˜Á+1IÔÉëHL¸%±yÿ—¼Î—ÂÿqôOj8‚¥Þ8¹ó‡Æ¥©æ"Þ˜á¨óǯ' +å1;6x#Å%â唂RC¡ˆ_Lýí_wÊ^â}÷10üvª?/K™…}}§Ô…°Ý' +$pÔfш^¥þãdÞ˜¿=JP*˜ÍQÜ¥‚ÔªÜùÒuc*-R>–þèzŠËBj¹nÄìÍs +N¼ï†Ë;}dm¦ðÈO{úȺ—;_i 3GÑRi 3Gnmƒ6TÏ +g.m^ ê¼ðF‹0«¸uëW½ü0ìJÔ§n]ÄÏ£8bÖ¤«øÉG†™¦µõëïI»¼Åå}¿äâë¨qœ®/¼ýÛ%L«ÕÄÚKáêî8Nq¹z^ŸÇyàÄûîcQ©íÕë˜õwä91œèœxQ0ð
G~d:¥øDÞpägŠË{ó“ʼnÁHtÛÍO–¤¸¼ïýÒ¯A{ÑD«á{Žv~еÄÜ…ŸB¤Ó k'1¯Ì£‰ÅÄh_¤á#).…Wûw¦¡FF©qµ‰¡ð2þJj%Ô‹øŠËßþÊ j8€Ô¯"&<lânûê-ÄR¦ÿ¿zÑ%6\þöÙ£ô#hÏ‹x=J?‚¶\ +?÷Týü¼âN‚÷%8¦}Ú¾±¯(Uø48ÑTzѦÎwªëÿv'IJŽáýŽ\köu>Hâ…]³¨óAMåÆŽútÒ0ÞØQÿ6'~Y³…za‘çdÍVŠË~ØâÏ •0Š4üŠc»Mgýê€= ›}:ëW,—]™Þ&b²ÑtJ#NŒ £µ¼ êÕL¥ÅY™AÕ®—[׸1~÷¢MÜK0Ó}È~ŸwÅ'L¥uq +ùŸü@qÙøÐsÐiLçqÔ=•¦¸Üº>|EM6"?í#ßPs²Åìæwˆù:Û¬'&ܼè¬;vk‘^t²Ï»vP\žûÝÏ23fX1œ™1ÃÊHÞˆEúv/ÄPÈðo©u¹u#výÂpl9±k?Åå3q}[8ÑöùûûèÛ:Ñœgtù'™ÏöI.¯ò²\ +?aõ£LµÁYV3~tÚ+¥‰1{B
¯LqùÛ§NNQMeĉ©=ê¼yÕˆæ"J,lø†#íáÒjDkc +ïƒMˆÕÀ¼UŸK<8Äœ^âRøµMBâÖaÛ…áÌâŽÚÌÛ°ûA扣67ì~˜Z‘ç¾/ùóÊ ©Ü—\Kq©´û/'Ö&Â$²eî¿œxp†Ká,Öï\0M%zVGëw.XžýÛÛ•h§„Ú3œXÚð1KÜî´É‡‰iŸ Ÿëç¨ÝhÝ®üëÔPHjáú8êÌI²Y^a±é#Ä^!Ù5"ÛU*Fl1‹6ûÞ‚šæÍò6çÄÚ„ë +ŠËû¢Éz„Yù¢ÉŠKµùzSI5ò3~½©ÅeÂmÁ/ÛµÜn%Æúû‚_vR\æë>[¤~eÌ` :¥ô³Eë¹ç cV¥æ¯úÖÅÙ:†ï§¸ÌÓžÛj^&YGÎ1v ×AD«áû).Q^ãO ¦4fj_{,›F`äøoP\êüäW\5w|ÄO<¥Ìg¿ö¿øÉÿgáÃha¥ÇÙ3).oÜÔ¹o2…Gâ‚©sßa8†çý\SË„=¯¼6Åe{dÄKjžŒbÈ
ŸJq™Þo0ŸH/ÖÁ‰Ll_áÖ`ÖŠËWfäD¬ËdR:çN,lÿñÒˆ!9±Å¥Ú,ÙJÍÃèꆷe8’2V_Ém*ï´ÌY~Å¥Ú<Û·‹¾ð.â.ïNpÄ]äíh8Nσ4MØÑpÅ¥kÔ¿ +´|×&KÎýÊdNM@Á—¶nÃúÎZî¤?ˆø5—W¦ûrlhõM}üœ‰‰Ìe‚ü™»/ßLq©uǪTÓs'Ïk2gimxû í2Y˜®Qˆ¥Ì
ON§¸<¸îW`11pS±œ)z€<f†Hqi¬¾Yu‡ž‡ÑÕ¿Y5„ârç-:UËmò|d”úµèt†#$õÏÚ÷«¹é"êãÏÚQ\–´=v§š›ŸÉÖð»).Wx[Ït
_Nq)üoëÿvûÜ=ð¡—æâ÷‚#¨jモ¸Ìו«²PÍó1Kƒ¿IpœÔÙúD™“„‡Žiý½ÜC¡Ð±‘Ì/Iqé~qa+†ã…ýâÂ6—7kä!=wšhøQ†GIZº! ›ýŸLöÓÜCýfNÎïÖ‚â2Šì2ô^5÷m8øƒ—÷}Ô›ÿhù¿Nxɵ¤ Åeu ò"t‰m +Ï8ܦ9²ãV^ä0<ÊŽ{Õ½O€?Hqþ—í5I×NEåžxIº®©Þ)ð…Gôþg¿ÿ¤ç¦k‚ÿBqùÆ5»j–Û””jvÕDzN×-õÜÁ±Â†·b8r÷Uh×ܳ<wc•4â†BÚõ¡¸ô*Knªæí“*¹ýŠK¯òÂ3ë¹ÅÏ_xæ›Çø}HÛÞú[åŸ7¼/ÃñÜçžõ¸”MŸš;Á¬ùcþ‹~œâò•ù©ÙEjžÙhxŠË¼Í7Ï~¨æ)Ó+Á×R\R}®„uÊMÅzaS6õŸ|ãßLq¹u†}§æ~è#Ùæ€aÛ).Ï}àâ«Ô<á"Ýð.—¹‹Û®¨§åöÐCd¸íŠ†—~Ý+cŽé\˜ÄöùWÆüCq–qHuóDúÈ¡¿(.]â¢O¤/¼¥p/úôzŠKÇì´ã¨¹gwZ¥¸¾l•þêj“6=£$ø——wFø¤þÁ¹!z•g„OS\z•Îç¨6i{ÄWŒÅ…”=n½ç‹—Niß«Ž|V}|Dq)üñáÛ•<mûã8üîøð]O`†¼êÛï3…÷#NÝ:ÃæÕòÚ0;:äµ¼öÇ[wÕ‹TáSà¯RµNºFïª.| ²2ð÷î—¾Íã‘œ'm§ÒÂœÇU˜ß9>p7|Á“²”Ùvñ×Õ<ppÚ…áÍ(.“Ìÿôª«æž-¨ýÓ«Å¥Ú»u¤–;)½JÃ笠<¸3*IžR/ÓÏŽ±š¶ÝD}œ1p™š'BþÅåêÕOkAs•mG§åö…Åá8£?hÏp™pk»h@/uáMo=«EH{¨äRç·¿ü–Ž{™Yì¾ßþòRŠK¥}ïí£ê‡6êüÃÑÒ»ö9p׉33—ñì ³à/Q\êþ%›é¹ƒ8+Ã[è¹ë`¢uæåý´<{Tø +ÄD†_CqdÇýx›š».²¬¾‡âÒ·yúÚjê[çQkóôµgQ\–°¼ô—š'Mµ¹ +Oïÿ¨¹`QéžÞÏ<j¬Þ?'½u®ã¦±WèýsS\º…M^˜¦çº†Ï 8BÓ[ôÜT|+Ååêá×_R•Öÿšáˆêì?ç$5OåÄöŸs2âööªÇ…{±¶œ˜ß9 ?@XæÛ«&1Ë:›êzZnœƒÌ›êG.î¯O_ .|Ò|â’à‹Žˆ—'öÏÏtÈs-*e†éž‡]ZOìŸÇp\ýµq¨¹©^ˆ9ymÜE—¯ï_[ÍC7Êé´¾ŠKcÕâD/5ÌhÑ¿™âHå}[A5Ï?$ÅðS(.ï{åŸÏ.ëäîøNÚEºKÃ?§8N³zb«–gN%NÿÀp¼ïu¦µSsÇ‹I©3ÃQmêñþÿ?º6aE€Ö¦Þ‘áˆíùÀuáý0JDÖó{Ž«¿º¢€þÖ9iYP3¼Å¥Ú¬iø¾ðѦNÃ?¢¸ÔùMyשyÂEÆHÃ{1S^
ª e‚(ø¿áC§S<û··>:õ3áAf(”kêÃþÎó=é”þÅ¥KMùJËmL'ÔRS¾¡¸\=ïçÃê»ö¥?NqŽ“·NÍ}/j*_ÉÛ@qiëÞ{ô)}áÝ4úuï=ú4ÃQø½É–ú‡>^ؽÉv—u™ÚïÑWZáy†_Kq™5jÿëÄ‹ò×µÿ•¨´æ?¥s2uÞiú[ÅÓ^šâÒ«¼®&ÂLz®)¯ÌZ\€3ÃWP\fZ^€o\˜ Ãκ`/“üoø)—«˜øŒš›N1ÚºŸ£¸¼°_®/¼½°_»‡âò‘jæôÐs3‹ø
—ø f_©¹Ms’ +½‹.߬£¸üí‡TÑ>ˆâç/¨Fq©u5ú߯åN2ˆ&^jôˆâRiÜ·™â ðo).£Èv¯]æi?:»Ýk×S\þöñ£¿Ós'ÊG=~ô6ŠKSyÖ˜lJ礛ÝКk×^&R¿?kLŠËÿ¡Æ:nçx8™÷‡).ß÷Îw.wcuÌO˜‹§Á—0“Ìw\<CÍà :g䎋gS\Æ2ìsþÿï‰V»™Ö‹Ò×?²Ï§¸¼°ó‚åà™.qÎ ·Ìá8i¤Œ˜|Àp¤ë8ißÿâÿWáÝT”Úðß)Ž7ne?}á½/gÀpôçwü½Px¼M^öw660‹âò¾§—–Só0pÐT¦—V¤¸ÔºUUs{ T>‚âò·ïn#3fnvƒ[Ρëe¶Û$À¯¥¸4Vçöÿ–áˆê<·ÿ—ÞEçû*¹û¯5†÷§¸¼°s +|o fêDuÎ)°âRißØÒOËÍ?Ñöù7¶ xˆ©ÎÃÐÞq?øу—ÉÆvži.|‹€+ðL;ŠË÷}æM7Ç[D¶Ë¨¦©FƉ›úS¥îl«æA”{ÿÿqvçq7UíÿÀ•y¼Cf…Œ·!{<gC¥Lá6”LÉT)D$™z¨ô ¢9 +¥(¡ÌS†¢©(™2F†Ìá·Ö>×gÝÏëÛósöu½zÑíw{½×^óº–â-Dœò|Ûò(i]+RØÖÑãMOê›I_I8Ä~3éO ñiŽÕ}…î·£,EÖ×Ù&ȪâDœrÝ©·ær¹ÞFÒæÔ[EœZ•=¢ñ:Uíêh +©›ÄžŽ±‚6í±Û¸\uXÁ®øN!ñù%‰Ç)¥ù·•"®Š¿ä6Ù”w»f}]þm7‹85Ç€Û¶Ÿú °ð:ÇGg$qü˜„£û߮Ƨ\® +ÀŸqªejO}xà5uÜq,õܱs¡öÔ·EœŠÊ¬“–s¹9¥±‹B5`sÛ
pBk¡šíEœ>™‰‡†ð»nÕ‚?#âTPì?‚xË5£Fû¿"â.^Ü2Ñ‹£~Üñgƒ#àPJî9&Øæñg–‰85‰«eËÉæ¾ç"×UË–UÄ©~ß|¾q7ZWH]çøqìùOÿOÙÜw]Gñi"Žc‰6$Þœùø†R"àÑ¥‹õãnxµ6ÈSvÕu®‹ÈÀŠqê¤ÿ|šÍ=לN›þóŸ"Nneê–$ÞÆ>è2u+Š8">8ŽÍõ–*¬>y7ÆçºGĕ$
³ªG)hƒ“œ@OêS]§ªHìÂΨV (Ÿ»1ôeª($â43’eÃV.G¼ò$ß.àfBK5lÇæ® (ø"žÀ‹ë!zqTIå¬Û˜xréBꆙgÇÌô½âÍEœ2m㇘<$Žþ{ãGDœê÷ÇW›Ä)*î¸8Õ(£f¶ÏÙ<f™žTÍl3EœfoÝÍ癧U^¼u¿€Ç9ËÉq‚Ä[hf9ù¦ˆÇñâ*‰^Eªð%¸1Û¨*ÆìÆ-–1™Íã~ìÅ2&Š85NÕ›ÀO¼»+>IÄãxt‹%5l™Î4FíDœHÕ!ÜuG|µ„ãØ‚EÅlwLàÁEÅëˆ8•6+û›ÄGìëc̱žVñµŽÆÉÜ`>›;f{]FÚå\nªGaŸËëDœºÿõfMaó„ëàxÙz³>q**›Ý[Tx: Ù½%Eœ +«–Öûìç»èI)þˆS¦ÍSp9›»¾‡y +~%âT\L™þ›Û.ÎPS|¢€›^çsEŸ6u~Fkt€ðH
³00Æ*ÛÏÌ"âÔ8ÙðyŒÍUY…%è>¯%âôÁV*¶<xI9Ô©¯ó\¬òªTlˆÓ'Óñ#\.spÁ‹8µëŽÍ1'ö¤L¼ç`¿Œâ§Dœ*©=÷Ô%NçEö lõ¿À÷¾çžÛEœr]© ûˆG`W×¹Ÿ1<K]6×Ó°>xBÄ©Eý]öê×âÿܧc2[æôºï²ÛŽvÝ¥u+؉·¬)Uük§‚ºÛÌÑlîXf{]·™cEœrÝÎ+ùܵ°Ojgþo×ñ¬šuàr+бÁ;‰8N|Xò ?ñ>ÖÛ(>SÄ1ø0a·èƒ¥L;s#ÍA»É)x„<Ÿð±ªSñ]ž +ºéÞùó¯ÅÿgâãžÙÌ»wþB§\wª|-.ÿO•¿MÄiNªÂGÅE<^Z©¨ÌÈ5ì4¸î€§ÞV©nÏ<;¯ÞñOØܱcˆ¢VïøÇ"NÝÀl¥_pLe*>J±LëÁnâr[´ +ÀËJ8N`?7áCvâc®9 +÷Š8ÍË\¬üoâ~8…ji¢¾Î²Lis±òh§Ò¦×›Ø<na3¯âM%½‰³±\|î#Ä«âyE«>DQ©Ws¤úÐ×ÅœÀ¬9ypˆS¶)öðcîc„¼ØË85ÈK–w¹ÜJxXCžaíɾ»×appk:yÔe6·ôL⣯“p^÷DœýèÇãZ÷D- ÇÝɵÿâÌ÷®øAG܃ÁƒøÎóÑ,Lü´„c¤ôé¹ýÙ\Ÿíãñ8>[ôÉÐ÷>nz±°œª®¯s¼¾÷qºˆ8åºå
´í"¼Îò°Ùgcù‡E-àr}¤2N«¬P¥-›ûæÔBÅï‘pŒ”Þ½v)û·ë¡Îø + ÇoÏ5ëi>7ÇÏ)þœ„#šV©–$/Áóo]¾
Ü‰Ö …1¥ðÝ"Ž³2µÙ\ÿ<ðÛEœÊºÅ÷&;¡©‡¼âª÷nM(7â›ûžyqåFœqlŸ_ø
›ë èXù°pƒˆûxt$µLñ£w‚‡‘T©ú:u{ÄxyÕZÀæ®Ã.Ÿ#âôä[6Êæ1VÄ<ºÛDŽ~û/¥p÷ÀŠ²tAñp#œ>LÄ©´)²5xØ
LuLI~²˜¾oöL»›¹\Ÿ7Ä?Ó®”ˆÓ{¿2"Áæ¶ëbáÄ•uEÜÅ£k)zt”ø}÷OD +§®Ó÷GGìÏ5}¸\5Èãžá‰8=:k_;ñ 7A‘…/$âÔºx ÃÁ£3ám yX.GÀɾ;E/¹®Ü‹I®ˆÔ$ÖKV,ÌM\)7JÀm4êö¹Ni¥Ì´:x¾9ÅLñ+"NCß7ïÉæú(oÃ{K8Š‹¹OÌ$žÞOYP‡I71^æ>ñ…ˆÓ¼Ì¡zð¹gc-ñ¡z‹8•´=»gsýðR`ka®±–€c·ŽâžˆÓ'Sú“ùÄ“S)¥aè~Ó<(ýÉb§ââÈ×3Ù<pÌùzŽ„#ŠZéWoaó¸Çl`éW+I8ÖY=ûÕ>×gÿ%ßû†
<ÍûfÔq“ø]¢ÄÓ8íK}ðH©ôu®ClÞ–Ù÷ó¹Ç`cËì»Eœ*©>‹±¹9ôÑgñ¿Dœ>™aëop†·Eœ?fXO6¹X’ªxo Ç”ÖÕé'ØÜq5Qñ¿DÜC¦å?:ié‹ÛX©q7쌤lÙúØ‚BÀm¬t¯ˆS»nòûÙÀuƒ<åµð:ÛÄ»˜ü~.7ñ.ÖÞ{Ÿ»¦#¶öÞzŽ¶é;·¾ÌåªùŠåyŠ–pŒZýže'ÞòL”•~·L`sÕ‹Ã2ì~·¼%â”mò¼ûĵø?èÓ.Lü:ÅŸ’p³úÊóìÄ{&pâ/‰85ÇdYÄïnìc²,qjUîÈù›.¢ß+>IÄcÈ´O‹2-}qEÒª÷¢umO7 +ñÞ‹¤Ù"Nï}×''Ù<ð=ÌçÎw™Í3ó¼â—Dœ¾¸à‹Ø<îš-fÁÓEœ]ëŸñ¹‡²NñÏEœ'ÿ©¹„Íc +Q|¹ˆ'mþdl·ñwæ´ø_ß&fY8•øƒËƒÙÜÓ9|€ˆÓ“óŽÉ×âÿ£ öl½n">UÄ©¬+”–‡ŸxÇtÀ¥ð +ÍuIï âTPgíø0Ÿë (ð"N/5›ŒfsßÆ +vÅÇJ8åù&ç¦cŒ:¹t!õð¾>D=AsRŠ["NMânž6}¯ô°M8ën‰8
6þgõÍ|®7Bƒ—qú`ïk+àæ¬
Å+K8ÏÙºPxÄ`W|‰„c\ƒ)4}oÑÀÛÉž\ +Ÿ[ˆÑš‘ó•×âÿ£mÓ¡FÃ׉8åùŒŸ°s°WñÁ"Ç£«$ztôÞ¿ßž
<Òdb"ŒÁnÖU~¿=§ˆÓàÃÚÄ=l÷ìÚX›h#âÔ4ªðb_6÷\sè¡ÿùul®‰">ûŠˆSiÓöòs‚'ï ¸h{ù GËêæw›³¹gåƒóß»æ1¼¸ÇD/ŽzR÷çkK<) +nGä:J*ÞûŽ²×³¹>üŽú°;Ê\q‰Ÿ/J<
´>øMmØ'Ôl½'Ôv
ß,âTÎÏky<ÒÒD}—¹éc^˃"Në¨ÏíšÀåú‡ÈB»>qZO;fà#ìÄë‰xO§vÝëo~ÅO¼ $žQ==+ÿÉëXààYDœ~ûÎ7²¯wê'ÀŸ–py½þærÉ££Öf_®ØJÜÖÒ×9˜›P|›ˆS9·íÏl®ä8r1סÝ\®zræX¢\‡vŠ¸Iü&Qâ©q’vµ +H8^–d),áXCžóé¹ü÷î:L”óé…"n²
ÿî:ÛP-Óí_—ˆÇ#ø˜ƒr&°æ¤Û3׉8•uÖ1tãaÓ(Õ6êð:×wVÄéÉo+Ó…Í=ÛŒÛ\•àrUÇ™hØWùŽƒB–uºÍ¡ÿo/âôä¼³›«²ëm~¼³¦ˆÓÝ/MkÈqf2Qñ&"Nyþ§Gø\µç]ðc"î#Óv’dZ¬`?»…xéÈ}å"ÀlFÞ`›ÛŽƒHbyƒïEÜCâˈO“J¥Mw¢u‚p˜ÂÿHÂQIõÿ(x"l§n˜©ëì“R¼†„#ÂÌÈû²ñ¹X†çqzqÅzdó˜ëcR©X¯c"N¥Í˜ÖyÁ#×<ác)²âi"N…Õ©ú¿p¹ðÂ,ð©ú;Dœå‰ëØ<\ОMÄ©´)¾ù›;NM£â›Ïˆ8ݽÊÐÙ\ÇôÀ?qjYµäÿÑéÙ ð¿EœÝû¥w³¹å™€Òï—Þ/âTEžQ˜ŸxÏGð½Ó#ŠŠ8ÍI¥UºÊÿ`-³70rV§Zff‘ŸŒçþo§Ò¦ë‡üÄV‡wý0‡ˆ'ßärÖḋ„Ne¦^†Ì:Ø¡¦ø` Çþ¸Û¾&âqð—DœJÿ…ràáÀKÊ®úÛ¶ÔqþDœ¾÷]õÒ¹\½6“‰×a£ãî–ƒ
ìŠwq‰¯(J<ñ÷fíRnpS‡V€ïqª".?KÜŽtÈ©¾ÎVí:Ã/ˆx2ñÍ‹,¥‘'ânŒUŸ¦þ§ˆSë¢cÚðâ$·ÛDàºû°HóŒ’pDEns_\Äá}Š[èƒWqúâ²?!àff$ëð3"N_\áò“¸\5ȱo¢yžÓØ<P¥þŽ„S7°Ùû®ñxQⱶü{¢GGÙfúŽ¯À£uÕm<mÅ¿qÊ6…û?Í掇ùwÅŸq*¬¦d+I<â´Ž¾ÎõÊ{J¶›Dœ¿þ|%>w¬-\>]±T©cÃLŠÊ†EDœšÄéÜmRI¿5Ëó¦ÿÑ@ÄéÑýpy'›[~@3bŠïq*ënÛ\‘Í=Ë,¿¿mse G¦zk6÷]„€S<¿ˆÓ£{17Y9~´Åê:Õ¢õŸ!â4Ü7ûÇi|nű¶pöŸŠ8m1ûrþv>÷-SñŽ/®ÍC]À#…ËÐ\5Î0ÐúΩ|l®òîþΩ<ŽcȾ½ú Ÿ[.¦°¿½Ú]Ä»¯i.>÷b&r`Ó¼"žÀ‹ë zqÔ
¬Yc.¸3â‡jTXÙãžæsÇÃzZ{Ü`·ø/D‰§»ç-CSZNr=uWHõcÌPgÆùáãùÜãåüð1"nï‹OcŸ[ +¹É)¹>Êò0¥U¸ÑOŽå:…+å¶:kŒ0§%þjÃåzÆçKüuˆÓ{ox±›«6>4¼Ø_Äé“9ûé3ìGS-«ø0 ÇÐGÑ.– ñ¦I\´‹'âôÁþ°d;ñz¹áóDå|Ýv|îbÇŠâ÷‹¸ƒO&‡ä“A³°÷‹·€G +²ªoól)íýbEO˜–Õ•¥|î›° E®,qjTÚ1ËõѾ(.*í"âÔûuر- +ñš‚‡×Å\«¼Æ~]DÄq®Ðélþ~YÄ©]ôßåÀÇð:½çˆõß%âTMÔv;›{V,“ß%âTÖ¬µŒÍ}'†’vd•"NÅÅ#ý'ž\<bÀ-ÜCWpÁ‰xò“iž{Xv6ׇûºàYEœ2íŠKÛ¸\%QÐß)â4'ußìÅl®·óàË$‹Oo>ÀçNçËœÞ|XÂͼÌÜ»ùÜ7Á6ÛÌm&âôä~|ŽxrÉJžð}ÌŒýøoG¶/îeò°MŒ’öàmDœÚ6ç÷¬e'><"|ƒˆS-3ÿàgàv„
ámt'˜&«®yŠÍׄ˨º¦Ÿˆã„—ƒŸˆOôQåÁ£læ
osJ¼âUDœ>ØxûîlîY&.q¼}7§ï=ßéŠÄ½(‹ÿÃë¬Ìp—ùN§‹8e›Ç×åes73ÞÅãërŠ8uÄž¼}x”å¸áu1; «OÞ¾GÄéî#‡œcsË7ƒN#‡\’pì¾ÿ´Ö[\UvÁ'ˆ8
u–yj'›'\³¢µÌS{EœŠ‹KƒŸa?:_$þœˆÓlàu‡‹±¹n—¹à¥Dœ>™¸ cÞaà`§¢²KÕlîš!/Å›I8âYå=Äÿí®*l|ð~"N¹®ÂÜ^Äc»1ÕF@iÅ{‹8½¸Ueë4À®¯³b¾ ÂvªÄ96WíyÔ§JœqÄâ¾ìs¹æÅæ¾r—ŽšÝy”ŸxÕ¢·À‹8½÷+…~ã'Þ7Ò+…ö‰¸‹lˆ²
uÀ³ŽìI<9±’b€=¼>æ4 +«=
¸Ù¼¿§Á§ÒfùÖJlî{ˆxU§ß¾º}>w±WHñB"N…Õú]$/‘ÄÖïj*à˜iºkÈi6w,×6ü¼„#ðàβ%‰Çúº#£ÊJ8ªÈ#£nqªãr´é$àæ·çhÓMÄiÐ)í¡%Ü3üc§Äû‹jK¾wDMôÝ&â4ôѲäkì’6ðml§mYòm Gw`æ ~aåeÆtš9(]Ä}|2íEŸ}°ßœ¥JÊŽ´…<¼.³y ø +”½¾è“¡÷^~âíàQŽ) yÌ2!ËO¼KÄ)ø^õ/³¹ç"Ó6+ñ[ŒÍUË×1¼–ˆûHü¢ÄS®kµ¸'›û¾ñºV‹qjœ¼ùăÄÃ1~Ê%èú:3Z¨ø£"NcVÿ½ŠÍãz"ük§/n÷ñæl®²,ö¿Ÿ¿«:›ëÊد"âô½Ï»é¤„#Ïϻ錈SI»xa?þ£³L$ðň¸yqME/ŽÊºæo—`6¼ÎvqzâåEœFw5¸•ÍõAÜÔºh[¾Èµøÿ¶^§CV:àÅEœ>ØÜÖ<vâß}䶖‰8
ó^ñ›+Œ»_1\ÄxqÕD/Ž>™²›^$)@MxÞÞg¿,âTMl»sx”#“×98sAñÝ"NÙæL…Élî:âzpùŧU|ŸˆSqQï“ìÄ{6ˆQ|°ˆS¦uh3›ëñdü?"NõÝåJð¹çbBíîreDœÿç«…ùÙ&sJëÏW‹‰x€Lûž(ÓÒá¶?lI<¹ 6uÃ,°-s¦’âDÑ°_|•Ë¸oÑÀKF¥-3øÜÅY™ŠOqªãÞ´ŠÍñ¬_#âôÅUyáIþ“÷cX$Vå…"žÀ‹-zq4è413àÉ%©©yBû`õþÄŒ‡%f&½p…Ïm„þSü¢€Ç‘ißT!ÉõŒ²l#üKR¯,âôä½r–ËÃe¡ ðŽ ÊmËÔ¶lCý÷Œ·-SOÄ©œ_Ô—>X'ⶣNXŽá«EœF~ìð1x”ÃëT)oþ©ˆS-S´ÅI.W?2¦QÑÇDœÚóõGÒr'y||ÊF©¾Î6ëiëüAÂÑêÝ%›«VF{wÉ%âTMLz¹.Ÿ{qÄ|˜ôr= Ç€[ÛÝ
ùÎu1>?ɳDw÷Àkˆ8uÿ«|åZ<ÇÿÈuú›Ão¯ZðUwðèî=:ª ·Ü˜<Úâ½/Ю̌ŸWeáòÿêdü¼òo§O&ÖüÄgFIÍ_§ˆÓ£ëzt1;ñ1s¬°â+E<—[ôâ¨uQ÷0QG;¦D_gŽ sÚïJ6Oø8,Cñ¥"NÕDÕuØ<ž9û_µÀm"ŽÙÿ÷òïZX[xôý»EœÖ]”øn?ñz×ø +w‘mj‹²
=º#¿·×¥Ü䥇Ë\DUʸpv"Ÿ›¸FŠ¿#âÔ<ÈùÕulÓÛÀsH¸™\hû¨(ñ1ðÇD<Ž÷µèÅQ⹞ÖÑñ4);#꺘Š¯qjÜѲ6›ÇUyéƒß.âÉ'ß<-?ÿ·ë#•]ðU"Nu\öú•Àõ‰]!*ƒŠW•p¬§mX§—‡»q)Ó6*7‚ÍUwám•&â_V”xê +½|žÆ.’…DèŒèµlT|ˆˆS5‘kÝ«\®ƒm"LJÅù®Åÿ9µ¡ïž¹ÂâŠ<"NmÚ}‡þowLø»}‡j‰8–ç-zt4Ä=õ…¬àa÷?uƒÜ·½Ìè÷Ën¾Ìæ‹™‘¦ËÊ\'âÔ²Z5£³ ñ S_È!ùíØ;°jFGÑÝ©»xwœxòˆ–ÔMb=•é`ÕâݵEœÆ¬¦Õ?Á掇cF?#âÔ4Ê}î(x´ðá9#6Z•7\èÄç"ÿ+~¿ˆ£û¿¾ +Ÿ»&fcÛõÕEœŠ‹e%+³¹eãH&Å«‰8}q›ªÝ-à6~û¦jÍDÜA¶9,Ê6ôÛ;õJ<bxGψ™Pz¼ â”iO]Íçª7cƒ¿$á8‘yÅ!ZÁîDΣxà™9è‡ +‰8µ¬*A-“T’ºYè¡°¸òœ|îY˜\(ñí4>÷-ÌA—øvªˆÓ'sÃσˆ‡S©—¬8:ÒÆçZÄé“iÕ¿–€£=¯xLÄ©°ZÓ%mryê*2aÇlsVæšEœš…¹/p3©”ëðbÑÝ)וûôQ6·<fq¾Wu6·m3Ôy¾W§\·|ÉÏ\®#áà½/_²UÄ]<º‡E.Ù¶iòw~jœÐa)¹KA^‰¸NÂET“t6·§Ï—jRMÄ©–¹iJ>7ë*Ï&â4JÜ4í_àÑ–"‡×™–UÓ´çDœN\:±€Íõæ¾ø§®ÐÅ‘¯€;Q¹..<ð‹8´h™ñà +]«ûÒÓ‰8=ºú#†r¹ªamÌ€×ñŒˆS{~Ýo°ï¸q#¥ìfß=pšýW|§ˆÇøq¢ÄÓ£{¼Û'ÄHË6Ôuúh[Ôqw›%âôÞ_>Û‹Í¢a+þ¸ˆSg¤ÆtOÀÍÞÿÓ㎩m¶Nw"r;°MÝfë'"NÃ}ÿ*Ÿ¸)l‚¾ÎóãèMütp=ŸÛn&_+âŸU”xªß»í=AÜ‹rÀkx*0ÃO‰8bû,ª"áhí]TUÄ©ú{£§øÜŽaõ8½÷ÓÓÛGö ¯óÌɼ§§ß/âÔ(Í÷SI.·â¶9Ryïß°ïî¨þ^ük÷‘øb¢ÄS%õš;܉pÄjx½}ž*©w>«Àæ¾™“R¼Œ„£¤}Í,J<•ó£F%î‡è©&•ôuž‹èyÍóÕêËçªPöÀ»‹8}°Õ¼©l®ø'"N™ö¡K³ÙÜQ? +Œ—¯ú]`s×±MY×»&ñwˆO_ܸÃÁ#¦oã;¦{up=6w\¬%V¼®ˆÓ€[“£›Ù\o›ˆÿGÄi6°o¶×Ø<0íyÅßqj”þ8»-›{ž94áÇÙ÷‹8õ߃†uø/Îà®ø"G¦/Ê´”m?&D:‚M_çzh*~TÄéÉïZÿ›{¶‰K¼ký7"ŽæÁæRl®‰YàÅ$áqwE5DÚj¤¹^ë‚qzq²óïž°0Ъø_"Ž˜Ì +\‹ÿc¯¾NåY”uí:q*m¾X¹…ÿèL÷_ñí"N¹®ìâü\®êG”óŠß âÔ,üôÛüÄ{f)ò§ß–qìƒ^챯[ô6x-§Ofýó3oâÛºžýÞmßÂéuŠÿ"âA”xúí]c#‰'¬(aNõm"Fññ"NÍ™_\nGã õËMë¢H›6\®þ6gmiÓ^Ä=$>»$ñX¶á]ÿŸû1ú`"âvOw Gýþæ==Dœê÷™V°¹oVï+þ•„c6çÖ9àzr!嶋p·ƒ“>_ â´¼êjÏë0[Q>X½CÌÃzFëÜ÷³¹å'°ÿ½uî¶"N_Ü[ÞE>÷°áEñ+"NO~Fášà‘ÖU†ÎPÎÏ(ìˆ8}ïå¾ÍN¼íàÑ)>FÄq<Í‘Z¢lC'>-²xrÑHªÌáu®…RŸÒ)f\Ž‘“~¿*îè9mGåd+å$r²Ž‰ÿٟƽ»žÿÎäyEœ~{飅Ø\Õ1–áEEœJÚz?UpœÄxºˆSI»ºjw6™ÐŠ÷qê +e<ñ!;שÖFJ3žøDÄ©I¼hP+6wU-cß+âÔ®;ÜèAâ}Çðu"NîÙÏò³oÎÿcö0ÇHi¿_DÅEòÉ79û~Gº»m¸Oeícœâ=Eœª‰JçZp¹.«QTžÚ}÷¸> +ÙñH!5ëí¼àÅD<y÷&ç$.‰0>.˜A,¯s^p9i6s÷m|îz¶áõDœšñ´·Ù<<
;É/ö>+à–gø) Gt}6wìV÷õè\KÄ©U¹ú¥…ü'¯ž]|‰ˆSyôB6Wù±£îqêÎÌþd¬„é{ŇJ8>™MÇÙ‰w?§8ÿ½+Ž +ú×Üò³ª ±+3w/§G÷ç×Kù<ó<©?¿^.â6Š‹7$,?£æ “äRó„Ž+„“¸g´úLÄ©'µ¼]W&ìÀO ¨\Þîa§ÖÅÅñ%ÀíH¡ÔuŽáOþö‰OßËæ–ƒ´â-$ý÷j«s¹Þ3‚xµÆ¶ˆÓ£{1ë#|îyÔ—Q¼—€ûX²rqü¢GOþl‡[Á¨<æžáŽˆÓ(ñÄî%ØÜóANñ›Dœ^\ÉúÍ“Ü ×˜¥žÒ +‡YmüW²þ="Ž¶Í™ül××&y3+›»Ž9§™•UÄé“Ù]7—ˆàüß®£çQ®›ÐµÿÉ[–&Nèz«ˆ#ØË›Ù<0»uÿYÄ©z}ûüGçáì<ÅGŠx™6(ÓRâóÜÜÜŽ´ÁÑÓa&‚\ž››H8âQþbsñ‘]‰éø܉ãÅ•˜þ¶ˆSa5âóqlîZ1ì
ñùë"Ny~óûSØÜ·chÓn~ª„ãÐô¡×±y\ua]ðl"î#Ûœe**«|KìN2ô_ʆ™“<'$þ¨„c‘Øû•þ`sÏ‚¦ø §<ß°ÿ·»®9ݦa«GDœÚóÛ7?nG +º^gQ§øó"NÙæÉ}¸\•qÌŒœÜÔ„}wÕ²ÁÝOnj(â471ñ±^ìÄ*Ë;à½EœîþåÝù‰÷p¤²âEœÊºïÊod'>á!Ó*¾IÄéî?H°ïºN&¯#âÔª,¸j…€»ôÞ_%â4Bn=ú=›ë‡gøf§Ò¦vÁúlîdnú¨]°‘„£qò䊢₆>ÒÇÐÞ'¹,3uÃLOhy(¨ù˜ÍÝÌsùPÄi„¼rWx5låq§¢²È
eÙ\õbQP¹¡¼ˆûxq•E/Žš…ÓÝ-t€¾Lõ&iäP}§vÝÃëØ\€wÁ¿q*çO5(Ææê¹£A^½íB6×G:ÇÀ犸‡Äß(J<½÷|‡PI%—¨¥\$¦O%ö=,QËwh“ˆÓݯôšÃçú0ð"Nw&—bóðˆWð2"NyþÏã.›;.V}dÔ¯ü›ë…܆q*ißp—ë½ÿ(ißÐ^ÄéÅí]Љx×÷q÷½ºŠ8¥ÕgsËG,nÅ‹85‰ÇÔ¨.H¼‹Ø¼cjÜ*â&ÓZ¢LK‰÷îšI<¹$5åb!Ž”ü§’6møƒàv4®£Ç›¦QÚð®ŽÀD¯_܉4±¢¸oŒPüv ljj}Ñ¢ö#/«¯³Î“ªÖwˆS®Ë7‘Ï&¢”âë$Mâœv!ÓFΣt¶b(isvÚ#â”ë쟋±¸fñ€ýóŽí6Ë*/RNmèC¯=sÄjP¯.›«F%¥A½Z"Nu³G°¹ã{X8ÑìÇQŽìÛ¬šlî;fáÄ6Ëq/n©èÅÑ»´Åæu’‹ÄRV1½WS™KuqÄ1±™Ï³Áˆ-"N£/ùF”ø +)>RÄ©†Íòúl®'`¨Žó?ÛÎæž9†Lñ"NÝÀ¢-®gsWý,ðì"Nl©:µ¹ÜJø1L¬”ªs»ˆ{xqãE/ŽŠ‹2
_"îêÉa7Õ¢}^½Oïý ã¸\uA-|qL-â?L”xeº÷âž®ø"|°ú|,kv¤·Ïæ…»+‡Äß,J<Õïó;nGéˆéë,/èyó;/âôä›7ùƒË¸ãã?$áØà–AÑ°9<pñÞ_%âôɔןŸxq2'Ÿ»V¸ÝwÏ£Ž@%¥þý5ÿ½«ÖM +¶™¼Î¶¯&âTÚ<šö²ˆÛà£%õ{¿øoàáàCªÍ>N¸‰çE*¾_Äé·÷³: +¸©eúY]$ÅE£âëØÜÎ<¡µQñŽžTûÖ¿³¹ò?$âTX/}?ñžx_º¬ˆSãä‰q7€‡ƒ)—m„:†'ÿĸ"Ž'ãOµˆ‡Ë´"|2:üï~»ˆSqñL÷ñ¹™ÖQü97¡ûG\Ïç¾|qùM§1«Mïbs×Æê>ŇŠ8Õïž(/âxe ÇÄJßßmðpð!uÓȱ= qj×åz·'›ëðÄ+§gsÕºÀÚƒÊécEœ2í7{ø¿ÝÒßxm§þû„ÁWøÜAäf†dq/îQÑ‹£lsüºq×ò#Ôzf! Vñ„ˆÓ'3bÒp=ä¡a¦¯3ÇUŒ˜ô‘ˆS£4û=ØÜrã(ë²ßóƒˆSY÷KñÆlîèxÉß^Iq6wÄ=P¼ˆˆSâ;.ÏO¼s¯(âq<ºú¢G‡—çâÉ…‘)ÀÛº˜ŽQè +[]ø˜VÜqª&Ž¼×NÀÍšÒ#ïuqjÛX³o»B©+è¸sÂ(ñüµØ\¥Èæψ‰8Ë:]âr+¡*xüªˆc·NûìÄǼ8"…Îk?PÄ)Ó^ÉÓ‚ÿâ,ÙæJžV"n²ÍÍ’lƒi¹h'²„]à”[NÂ)ä +[ñ
"Nl¶1ÃÙ<pD]ñE<Ž¶µäƒÅ£{ë ´¨ÃeZªHuúü5§îÀ÷«N³yÌC ++Å"NÕÄ÷ëãs?ÀQ›ß¯{\Ä=¼¸}¢‡x?¢¸H†€KÝt›Íƒö?qúÞ7YOó¹ÞÊ>DÄé“ÉÛ +áÅM–¼8L&Öî€1«x¸L+uÓ(n¹ª‚ÆÀK‡"NeÝŒÆ]ÙÜ×µÀqzò…ªŸÌ¤þ`“×9àgDœ†¼ò>~–Í=è2¾Û¼šÍ-¼*¾JÂQX5MßÇç¾Y¦Õ4ý ˆÓÝwä\Î媎ÃaŠ%âT¿—)_€xÇ7Ó¸eÊqêÇMÝ°Žø„9éCñ
"NŸÌçE~e'Þv°ÑIñ"ŽQâñ…ùÙF•wØ}?¾¸„cÿ{ÞÇO‹>XêMÔìV‚x`¥>r‘®³ÌÑ{5»•qzòZݘ<n«G¡XÄéÉ—*t†Íãæ¼ ÅOˆ8mtúàòp;õfÞämâ.Ödl¿þ6OØ&vßöë7H8âUŽz›»¾•ÉÛ‹8Õ2u‡ásÇÄæ;¼„„cSç—7I^Ž!kuƒÌA„ +»èe>·bˆé´»Øõ"NõæOÞesßr°Åló'ï‹8•6>~”x"<fôÚA•é:¿]ñ^"Ž*·Srš¼Î5gm(^ZÄ©y°uS>6Wå´mxA§/.çC·±y\Oeƒ×q|øfiS6w|Ú÷›¥Dœ>Ø÷.QQ©2ð¢gÐ]´*3´|„ÍõFfÃñ +V(þ©ˆSA½ºJ'ðaR’\7Kðn"NcÔî
¸ÜŽYh](ÞXÄéƒ
Ê5gsßÁö:Å[‰8•6‹gìcsÏ„öUü€ˆSëâöüÙÜñLôÛó/qŒœLÌÆæªXÃBèš³H8FÈÿåö!î[©ÌÒu:Ä,øŽ–Õá,¿‚‡ÍÂÔ…•ºNÇÛ +'¯SÅ4¢çeÏÖaòÌìÙ¶ü)â”ç‡LZ!à&ªÒI_‹¸‹G7Cô訸hчÆi'B¶äužêT¼Ž€c3oÓ-*yc!¼m³g†ÔbsqÒ‹¸…Ä?,J<Õï?0‡xrˆ;5×CÜŒøøù"N%íS}¾gr½½‹Bß âô½.1<ÂQ›ÉëôÒDü_"NüӲ-çrUXÅ°'tZ¶eŽá¾&—σGkèƒloz²Þsl®ÚÔ¨ßOÖ,âÿ—(ñTPœ»#ñääBê*ÒÓÓ:ˆšøqîN"N™6öåp;u´äu¾ƒ£yß/á˜Pë6yª€›ÈÝ&,â4©”çÆ\n¾@£ynœ-â´,³>æã‰y>UЊó_œæôÞïªþ-Ÿ[æÈÅ»°üžÉiVhïXZ~ï$‡yS~8" +ç?WÍã¾9W(ÿ¹t§õ¹Ø\õe,ÃqÊóÃœÊt6zЊOq/®”èÅQ«ò£1hF\†®SìøhÌ §Z¦yÑ,ùÜ3ªxg§ZæÁ}¨ß#´†!ÍžÐ÷Ý*âTÚ,_”‡Íõ,p +‚‡‘”ƒ:&³ºŒ¦ïûîœÄå:X'Îê»s¢ˆSž¿qëmlî˜}‘Šß)âÔ,<>òeö£TÎ3|”ˆÓì@Ù.7°o9ˆñ¢xwmòK²
ŽÖí±o9¸õîzxÊÿJÄéƒ;¢
›ë¨TA×ùq<›«¶ ŽŸ«óãX÷‘ø{E‰§¢²]lñˆ‹ÿ]½õ öv±—øܳР/Óâ6××ùàEDœê÷êww`sÕtÇÌHõ»; +¸ƒVåÞj#Øü¿ú2ëª_ÝÝ?#úíq$þAâM_æà(<Ú5W/n1g*å‰8e›Ê•«²¹g¶]4ϵé.×'¤ÒoW|½ˆS¦W¿ŸÏ},UR¼“„cÙÆ5–²“9bvG/Eœºo;Ìæ:ì¡~TÄéÉ÷nØŠÍmÕ*L€·–plp»Ò²›ë ~£ˆÇðÉT}2Ô›;*¹#Õ —B§úÐ×y¾Y8ϺŸÏ-t…ß-âÉÄ7¹8ìz6wÌñsŠqjf/²…Íõrs|›ˆÓÝkvù”Í-7ŽÈ5»Ìñ²McQ¶¡Jêõow¬(“ÈámôîðwDœ>™<Y¶³yÜëøo"NYßá0¬äuªŠy™¬oÿKÄ©†½áÜ +mBThiʫηÀ¨Üqp%SÊÛ•ª³¹í"ð âÕ¥Tâ—ŠO}›JFw#mþOþÎÁBj¥#E7}t˜ éªMËgËqRóUùƒÍM;†•Ð|UΊ8Ú\•òðoÁyrUÊ/âôô’)¯ñ¹ƒ0æŠ/–p„ø¹Ã+¢G݃¦§÷".ðlQS|ªˆS»°bðÿÃ`DGÇuÐÆåΗ÷ßø?=ÝŸðC÷|7‹8µqeGTàrUM#ð âUDœ:¥cßü‘Íõ4oü„„ãèÁ+Mbó˜c¥ñWDÜB±©'*6˜¯Û\<Rè +Lærœƒ‘D Ž¯eÓgv´ÐÒ?1h=sÿ×lîÚA#uæþM"N=«|gg²¹ÿÉÏq*´OÕø‰Ím7ŽÄ?U㤈Sï"~çH6·\|2ŠñŠMQ±¡êbïlÚíc%6†W¶ÝdÀ‰8UEŸø™Ëõߎ&²è'Dœz˲ ëœHa‘ôï,ÛÁ’Ö²,™EœÆq¿¦ïÂåªM#©y¿ü”ÍãFÛ°ó~ù±„#Pɯé;Š•‘—Ñ·q"…5öœLTüg ÇœUÛ›hün%§¸Ãh×?T"âÔ¾_øm›'tu¾GÄiºoáë}ØÜvƒ6náëDœÆ°ßœÿŽÍõ9hŒŒª¸Œÿt'8ø0ªâb §§¿_”xšöYz¤)x¤€Òúwj‡å¼¥Gš‹8
¿ŸœŸÍu´ªmþÊ™•ÍU—Yÿ•3£ˆÓ×kf^þßîؘ§í5³€ˆÓ`$èãln!à?)â”uÙ~éÄÏ:õæcà‹8=½Ä·§Ù\ßã‚ÿ&â +mQ¡¥ÎÉ›'ï#‹¶%U_Qbãì@jìË’\nÚvÐÂƾ,&â×èjÙln: š«Tüm§/®DUvⓧFÀoqªiWojÁN¼jf0õ±zÓƒ"N“oîesÇ +.Ãú¦á~§f"ÏžÕì¬ó|ñ8>™TÉ'Cûi›æmãO«Œ¨Ç86u‰¯)â4~e欒Cœè +\*ÝÛl·‚+J¥[)â4’šÞåA~âíÚ¸é]»âT],þ¥ ëLŒ ß,âôâV”ï+H¼‡¨+Êp”º¯Þ/à˜pS¼¥ˆ#FkÍ~’O{ìO:Ìk%´†WÔq=–Á·ØŸG$Q•îùz›;ºß&âô·¿üF‘É%ìðÊÊŸ±B|›—ù^Ä©G}ü‘O(¾^Ä©²:yKò¶>ÆbGÙ¦å?#)ʼn8uÌŠ>Ó<Ò´ÿ;} ¼ŸˆS©»Q‰·#]#®ï;8䕺âž\nú+Hà›EÜCâŠO¼f¥3ÄH+ôcTçÕEÍJ¿K8ªÊÑUŸt9Žÿ;#ˆ(5ºêÓ"NÃÀËNq¹ +ñ˜ec¤íßÃ&pŧ‹8½¸=/}nE¹^ÖÖAØ\DˆU|•ˆS]7tM{âže£”þ]Ì Ž]ÓEÄéÅUÌ1ÜŸÞï”êt0ùP1ǧɇÉ-Ƴ¹Žñ’ +®èÎæ¶j mð>"N]£ZÏ$ØÜ1‚P!µž©#â4LsÍM3Ž¬K›^Ä-<=“„#ëRçdqš-,vK.7⪪¶aOe?ݲ|°eÓOqjeªfxGxZÅW‰8}ïO}Fx‘žþúG@ªŒgÙ‰OXÁLéþŒçD<bSPTl¨o³wç.âÉ…•Ð˜iþ-„»â{%Çi?¼ã(¸eC¬æª‘ÄTç‡wq*´gGåæsìŠçpL°7ibÞ +4ªwqg¢â%Dœþv¯øh6÷\\n«ø8§B;7qÜ +…g>–ƒPÞŠ/âTæçy·³¹c[ض1Ï«-âôô¿`sW
ÿàE$/™ÙÜÐ'vÀ³‰8uÌR>ÆÏ:'ˆ¢6ꙧÙܶÐ=PüqGßæà`Qâ©g5µÅ +âv¤Ã}êwFBýÃOÄ©Ø\¨ö›ÿí¬Ð_eà?Ý¢*ýõQ:GÇ,Åü`8—›¶DÃ6?xVÄéƒ<«›[v°ëcò¬ž"Žö½viÁ‹K ¶Ï‡µ+ˆ8=ý×Æ]Ù‰×7‰aY§qw·PhO‹ +-}q•°€n&7N„nYÑ7¬¨vèv
‘pšúH}qY6WÝqD +}qE§w¨`
ðHZõïTŸ…öPASÄéé3Îu6õaú÷=Ðh¢i·±¹kà(±âUDœêùyÓ²yÌ–qçMo$âTQOéïòï`›–â 7ñâ:Š^5RöÄ“Ëy¡júw¦‰á€=d·€[4ió>›»i1ZãcV‹8uÈï<ò ›ûõx§/nÕÉ›Øܶ]lˆ]u2ˆÓÓ'UqˆÇü +鬣VLðƒ"N}Ú&ís3yÂø[Ù¤}~§bóê %ìÄ{.¶¬(þ¦ˆÓßÞ¨Ip3J6ýõµc¿Mçž¹\¯ÀãŒXçžíE<†Äw—$nü‰narÃL”§ë–Æ°‡jµas5Áô¡ZŠ¸‹Äw%žêºêÖ$¹åo× Ÿx±ôv,.(þ™ˆS⫶Þî_ŽºILýÓ¶ãØ(UbóÓl®ƒ6 ÒÈæa"n#ñ[D‰O›ÆWl'ž\Â}q–¾ià OFñ#Ž#¥ÅÛÓÄ‹eEº²AÿN
EhÎJñL"Nu]†‰xqþ’VîŸóÀŸqj¤2ßžžÍõ‹x&§Ú¦ËîËÄýÅ…Ü_•ÂFè¬Óæ°¹¡ïŒ +ql +Ýz3— ÇÃÌIÃyD<ȺßEYGì“û¸çD˜îÓ'2ƒ±ŒâÏ‹8›¡
høïÇ¥‹Rl\}ÓÎm0\Âiq!¥\ë‘à~,ÆÐá@2Lžð"NÒ½/?®·KÚá
´^Ö fÌö¾ÜSÄ)ë¼ÐˆÍÕx¡ˆc[fsô¬bª,Gɺ˜â˜)¾EÂ1wq¥$r^o®víðŠZeBuÑôæyÓØÜ6±6¡ød7‘ø΢ÄS{ m×±ôá(Õ…§ô0üÿ,ÇT.×éoW|’ˆã¶‹{¿`'^Ú°Á7‹8 ¿Xœ‘Í
Ç.Ï"âÔHÚÍud!¼§ˆãB¨ýÅÀ5I‘¸>F¥™ˆû‹BØü?#—„ã´Î'Ÿíâr#îᬯ]êϺ…>â½DÜDâ·‰Ÿ|zã‹»ú€ë[ªÃ·¤êð8vœúóŠqzqCj•eó¸j!cà%EœZ™™é—O^$žÐá2p[åÌôËEœ†ÿSFî’p7à{ç¤R¿_R›ÏÍ ¦Ó÷KêŠ85RO¹îwC·iéß©.\À¯Š8õië}y››V° +üC™ƒl®¿:|ŸˆS#Unûp~âí pA¹íω¸‡¬Ë%Ê:ª*¿z‡Öau|¯(Í„Ž‡eY˜Ÿ¯Ôê6·ô*(â_G”xˆU5hçƒê¬%¢Fô¦ ÃơΪÆ|§Væ™O²y,8#¦x}Çf¡Î¥ÁýNièÆH=Åk™8äucÎ6·,L:)¾UÄ©_7¤Ï‡lîZXÚP|ˆÛȺ[EYG+Ùv'Çïªåð;faÝÿw&vy)>VÄ©[¸ät67-”ù¦¹kŸár}3eâ?‹8½¸†ŸüÆO¼í`ý½á'çEœ¡…j–e'>æ&°=¯PÍŠ"NŸÌ}-ʳï_Ò^IÀmœ[Þu†çºøÞ—w¸$âÔ³Êìä39êÌnQ§/®Z¿í‚Äã~XÅw‰8â˜e<ÍçV&%žñw¡ºÈ,©.p›U¥=C‰ëÞHùÝá` [ñ§DœÆ2ñ¥
ÁýXX×HÿÎ0‚ó2•Žàr½E!¡*{SÄ]$¾®(ñ4’úú+Ô´–?›pÓ<fÛ´vìØÆ枃踊oqÊù—?ÌÀæþ¥àYDœJ]+Ÿw"+žMÄãxq'E/ŽÚ÷ÍÆ"â¶ezßÿ…ëe_*â”u5VÕ`ó˜…먯"âÔ®ŸµÜ +…&rü-Ó6fÖÏúVÄ©‘zå™×ÙÜq]J¼âóEÜÒ$>Ü¥•î¬„ãV£Æ__$ž¼#+lòAÿÌ1ƒ+æârÓrp•¶âïˆ8&^¹¾U’x3à;Dœ>™¹+N x°ùîŠÓ¢œ§‰Ö×Vð¹ÇúkïK8Îän´ÏU5oƒïqª.*Õ¯ÃæqÇÁšT¥úwJ8VÄnÿn6»Ð6F*>_Â1_7-ï AÖYFÀ‡ˆ8uÈÝwnð¯7%_™^Ä]TVçEŸ}q¹Ïþ nEYDÖq]»y?¸v˜Í´ÕÀ®q‰ÿ]”xœ‡=‰çú“NáY§CûÆnÆ©›Dœ^œ‘§ŸÛ8بx/§©ÎKïõas+¸Kñ"N“œ?Í"óba“Núw–ªmlð9"NO/¾ûŸ» TÔÅwqª¨¿ß™¸ç£pýÁšà]EœÊüw•72¹§Æ žþ]å¯Dœêº|pÄ«Tü7§AèNvp¶uÁ¿_ÅÆž“Ô<Ïds5Å'“ç¹[DÜDⳈOOßv© ñ¸? [\пsu| ðf"NõñWÞ´¬£§w™àˆ8ÇŸ:EÀqœâÓEœFR%=Èæ±à"°¦… +¿Îæ:n‚¾PÂ÷`Ы¿³¹a%Ð1ôêŸ"Žp?Zlnbw%µMÞ5/q¹.õ˜«Ì»æe¡ØÜ/*6ôÞ³õH<{žCxB7ä4_§x_§Eä^«÷ƒ[Ñ:¥ ýÁâ\d¯Õ߉8µ2ïV˜Àæú“uÁÇŠ8Õ6å'$7Jéai¤®‘ëw"—ŸÐAÄ©osfÊbp9/ôÅ™~ì|ô¬ÎLy]ÄéÅ¥.*F\oé÷OÕ‡póo#¿UÂQ泎©Àæú6¼ŠˆSïbnßMl’Iñ"Nu]›¡²¹ž¥Ž,â4Í;k¦ÁO¼c£žŸ5Óqª*3]¼Îæúš{šdÎt)½ˆSÎß\¶ ¸¥y貎©Ø8‚°Ý\6¯€£wÑäÏæÔ»Ð;Ilÿ´e·’Ux Ç´ÏøýEÀÍX¤¬³t\%FÆï/&âÔ1k0°6q›ÍﳄpÛïàuEœêù{+ ºP=Û=nãøÈâso…ÛDœ©r‹Šr¹^Q£ÍŠß*á8ÐÚ,_â:ДŸ£!ÜñW\]ðÁ"NUå—×z³¹m'Eò…¸ÜH¨†×Ó\h!áFøî¢ÄÓÓËíI\ÏûkË!ÜUYçaa¥Üþ"Ne¾GId]Ì0"U®¶‰bÓ£dk§W|ð1&éɇ`Úgð)§ªò1·ðïxïŒÉ%âôÉŒ»\Üo¤B‡¦¾FÜB§tÜeSÄiüþC–blw<\½÷C–[Eœ:¥·z]Ù\5XH]zùk>w‚ï}éåMŽkJnõ:‹OûÙwßØ=ˆù·]P31-ß!6÷¨ïq‰_!J<5‘{?¡Mb¦çwNB§÷Õï,Õ–»à•Eœ^Ü™›KGìœxúJ( +—‘úò˜Å\îøB§Xæú³¹áÄP×eþh°„c%ô™mÙ\‡Ó +xG§6nZ§¬lnÙØÕ©xvÇýïØÅFµq%ÓâeDœþöýyó»´/!â |2n¢Ø4I}Cà¸îGèÅÕkaYê›ëïMž{f¸ß%â6õlapqÀsƜ˩‰|©ìsÄ:b„ŽYB%{ROhÆ玃/'¤H8æ¬^*û´(ñÔʼ3b<¸ß%¯¨ºx!¤ó;#^q꽕-#›N‰Ïºª)››ªªL€7q‰O'J<•ùî¡©ý/£pËÐJ°Aîƒ{2‹8µ°oXÎæz/q|‰ˆÓŽÖG¾¤Ed+9ñÚ!·Tã8óÈ—óE”IÓ¼Vrê#œ[~€¼„£ÔkÕ¸?õëëÒp×FêúùËÙÜs]ô*×Ï_"âÔ@_Ï}›Ç‚Ä+nˆxY×K”uTÛšD+à–ãW•¡Ãõ»˜2¯øïŽõ¸×ŠòŸ®2ŽjZÅÏŠ8õi_Ú‰Í=ÇB\£Ç—¶qžþ2¸®*çû,i·œQËÕÖ0ž_Ä©{P¢òlžÐgµÀK‹8eÝäâøYç"´¯â™E<†7Aòâ‚Íÿcï%®ïë‰Ð)U¿³LìöQü>§Õÿ<O¯aó´CŠ*á8—½â6p¿‰æµôÒB=«ZUrq¹¾çKصªäqêQ?™q5?ñ6By+þ‰ˆS™_5Õd'^uüiø¯¸-âTæwî~ˆø¸jj\ðn"î¡Ø|-)6ˆÙ¸'?mŒ´’S¡Ã(Ø?¯xF Ghß,ïç÷'ܯƒø8VÀˆ8Bûîú–Ëõ±Ä§Í¶ë€ˆÓ'Ó)o>â^Än¡“‚]^ŠqjãÆm¼Àåªkä ÌÛxEÄi41îËŽÚFñÎ"N‰¿œm;ël7¸)¾WÄ©¶©[ +ÒäÔGx3×ÃLq×^ߌÏõ5äà-DÜEâ»K;ó¿ºÜŸx dVqÒ&Zó¿ú–ˆÓ{O}añäÔG8OèÐùFÀ_‘p¼¸7—~ÆæqËyŠ¯qzq¯Îæúú;Üqš|¸;÷ëàþÔGx±Iø—ïyàKDœFÐÕš,ãrÕ£6ÏêõyÝÙO׋ðqð‡EœJÝÍÙ׳¹kµÍÍÙ¿q*6W˜ÈæV°óAñÉ"Ž¾Í-UùïÝN¤f¿¥º„Ó›š{è6×»2>Oıý¾nqþ‹³â¸¥4_Ý[EÜÁ'³HôÉ`]Z¾·
#R§ÔÖ½Gœ‡Uü´ˆÓ÷Ý&°¹a¸˜h½;Ã$§í¸é·Õ$ž^œâ–ˆSâ÷wè I<÷wè"áXLü°^^ðh[VtX$½¹&YêZýñ3—ë¹Lï·úㄈÓt_o+ñ¹hñmU§Šú%ØYg8XÒR|ˆ{xq¹D/Žr¾ÂÁäÑB׿Õ=Ârž~ŒŽ{
~TÄ©•ùéHðHÛ6ôcTßÂø½"Nc™]»³ONï‡-mèßéMÜ”uñùÜ
n9‰÷Ø/â.ŸY”x*´Cr.!m[¦þi%0’s¹„c«Ò¦§Êƒ[Q¦÷]ÿú;—elzªŠ„ãš’ +ýïasUM;OqªçköN<9íöɨßùgÀpKÄѳºw6ŸÛzVýî}ƒËuXc+à$œZ™”–c«±¹Ž[pƒÏm¬¤¼Tz;ëTß«B/•Þ/âôÁ²7?ëŒ`8püÉ~"G±™!)6¨iGµ~—xr²1¼¢vu€ÌYj½JÄ)ñÍ?ìî7a›Fôc<û*SéÂ扴ŅÃE:ˆ8"J½q”ÍuÇ2àÇEœf‰¿ýŸÛA+süí‰"îâÅõ–¼89©6ix¤Íú1np»Mê“W‹°¹^3qêæò.ð¹lËå]qú`ºïó³ÎÀŽÅW‹8½÷"t‘ÃÍ´ûeŠ|rQÄc(6¯ˆŠ
wtG±ñ7ÄFèyúvïïè^\Ä)ç;îÃæz%Ôï/âT]œO7ûD¼J[q/—"
Ï9O÷û´á߻ގkÑŽVÅŸðàör&³¹ìhU|ªˆÓÄKû‡ÇðyÚ…í'á8Rzáv\®{•˜x¹ðV'§ÎI¹®¿ó_œ…Y#ÅÏK8:fŠa'>¡¾øx1aöü“ÕÙ‰W#9¬€Ï?iˆ8åügEÿdsà "J}Vô’„#çOŒŸ.ª.¨¦PÃä’VØÔ‡þaç 1$Ó¼…ßÏÀæjH5mÓ‚ïÝÊåFÜupŒºà{EEœrþÇ…õø\ýüNÇå¶ï§euR붷¢M>èûaƒï=µn[§ø‰¹˜5J.¨…wz†¹‹ssK8rþÄ‘bl·°)Tñ"N݃ßÎ÷có¿
üí|o§bóؾ·ÀÍ(K™®8Â7ÍкŸ[1|qZqjaózËU5ì!Ï·j´ˆSU¹2]96׋.xG¯òú4vÖÅ]m\Çë³DœúóM¶e'^oÉ2ÀKŠ¸B»DThiù>{™dh_}ýe”é}½ªw‚²—9-âÔ³*µÃbsÿBipWÄéo?êþÆO¼í‚_Zÿ$ÿé6ÂY+þ„ˆ{Hü/‚Äã.”Û¾¡Y# +X¶Œëê€:x§švqÅnl·Wñ"Nì•<ÍÙ\Ñ°ÁSDœZ؉vOëý`Íd +ðÿvñ¼ˆˆY×W”uTYe™ú<q=·a©§>.|´„#ìaûe#À#mŒL.h[VÚ/)áôô”N¼Ë榪¨ãà«$Û°÷ÅåFÌE +m³º‹Eœ¶&N¹¾‹ÍãFЩ%–7bs]>ÞPÂi¢U%~›$ñØWi_Ç›<ä:ñbê+#âØõñÓÁúl®ªiì«üé`mÇ}‘CÖòyÚÕ{C†¬qêœÜ”i¾ ñ6®âº)Ók"Ç‹ë%yqTQ7¾Vi3x¤ƒÌúw1gF_Äé‹ËÕtq9B¡Õ‹ÈÁE!¹š>#âTU^©ÿ—ë¹Jl +±è;öÓci7}ÌXt@Äéooñl#vâÍ Ä«â©"NO?¼¸/;ñº¦5ÀŠ8õ¨3e|“Í–‡=f™2²ß»Ïq%Ó¼*ì¬Óû}°þ>¯šˆS¡}0ß5O`ù`þt|n!b®Ôgç¼?½O‰¯Ô}+qÛF$î¨ö,à;$1Ü.>Ö<RÀIý˜¸aàt‰•O±¹êŽã„Z‰•CEœr~ye›Í¶.ñòÊžˆS±YÑ»+?ñú€ xw§ï}íþ‹‹AD©µî“p›ã¶ò³ÎN¨ï´]Äã(´MD…–ºÄùà§>ô·8öQç;`‹8
SÀƒó2=›ßÊæŽG=ß³yq§¿½fú®ln¹XÎS¼§ˆ'uYEYGí{Ó‹oOaŸlôÔ8ñç_)áEž½c,ŸÛÁ•
gï˜ â”óEòc4á¯AGh&<=ƶ"ùïqúâM.Âæz/ âôÞs^\Èæz-2¾HÂqµn©Ë/ó¹DE.uù ÇìA….³ÙÜ0ƒàùºÌqtȯ¾ËçÁ+Š âôÞoéI[‘)[ø„[\Ÿ–Aþ–žDûmÞÙ
é0¯~Œk!˜¶âß +xÊ»ÎÁMlî˜Á4ï¡ g«QRª\CăÄ.J<Õ6
wÑÉ +> +鬧«Kœý_¼UÂÑÆeý’6ÀSxÛÿSl2þ/wÕè=he²~ù«ˆÓû•†v!”úÊb^®|4PÄéƒ-µð¸%À¬~L,-Œy©…DœºÄçž¹ÂævÚZä¹g.‰85R™7<H<y&4<ëT‘U1¼ˆÓßÞqÿ}\n$ÅïqzúÆÙ}؉WlÚ8»ŸˆÓTg•«§Ù‰÷ôþƒ$ïÐ''›ÇMÄ1S<»ˆÓxK™9üœwZñ"Ž€Òk_ágCµlk§‹8½¸ÂOμw\ðª8;ë|N݃3º±¹œÒR¼·ˆ;(´?‹ +-Õ6ù¶`©¯™ŠÒHÅuØC¬„æÛòˆS÷àÇžbrÏô\[xìY§Šúþ‡ŠEdÅK‹8î@/¹ôßø?4О^RCâÏ”\$âThÓíÞî/aGH¼/âDªâ%œâ˜¥d^6ËÕÃÀ”Ç&½À~º©ïê!âÔ·)uà0?ñª‰Ã¶G%›FÊí®ÈæqQЯ*â.^Ü,Ñ‹£œÏýê8p+Êåwú1¶ˆ)ËktasËv1åµ¼FGwøÑ¢ÄSU¹¥çGģ׿Ókbø§"N³ø„Íõ@Ìç'^szú•:À#UÖ¿Ó-¼ÞNĩ̧îü‰ÍMaRŒÙÛØܱbøÛÙ_K8îÒ*9m—q5pÁßñ8²îQÖQ¯2WZ\ Ê¡‹~PåX_$âÔ5ºmL-6·ì¶ëÜ6¦®„c +Ùf´0§:–ÞÆ
žQÄ©Ìg®¿ÜŒr¸~LÜ ¶ef®¿_Äi +‹£²Ê±`®ˆSÖÕmqƒÍÿvALÝûoqª*çO}…ÏMÔ6)ïÍMð¹…ûãwE<†Ä¿,J<¶ 1‚¸>"l᳘ÞÃ#䣾xZÄ©…Ñy¸©yxcÇm>Íö—ë3b¸[çÓlCEœ*êÍÇÏñ¹‹§+~QÄ©ØŒ4²¹‘Ö-iqjß'׬Éæz³Q¼¶ˆS©Ûû~y6×{Ü\ðJ"NOÿePs6×a‰]ðEÜÃ'³YôÉP©ûóìÄ=Õðû½†îù[Ðð\"Ž•‘>KÁMÍÃ++O>Ä +íYQ¡¥¶ç€ä’–ê3è)73 +»qFzX*âÔD>aw×Û1›H}hÂŒcûÎÇD<~TÄ©Ðfø´—ëž7:'>Mq*óÙÊ×ás3¸ª#[ùú"Ž+™N”aó„\©\äDywPlÚˆ^ÍQ_˜Ü\ŸÍ6Bà:ä·ÜØxaò@§Úæ¾A·³¹m;MÜ7¨–ˆS™O·u/Ÿ»±`ŸÕÖ"N{É›Û7ÍHƒP?”wpÕÜÄr6·]„„R|‰ˆS¿nÐñóln86í»Pü¢ˆS©[´d›»n‚ZXÅwJ86È+¼Gôâ¨wQ0&â–? æõ?ëàƒ-˜?›ˆS#µzh)67‚KÌ/+á¨iGÌùÜŒ„WVªM;‘z&ãrõ—#À¬â–ˆÓÌIæyß³yLo»ÿQÄ©Ìçûc›«î8}äûcšˆ{xq—D/Ž#ï|ò
q½(R±Ñq¾CÄéoÏØl¸Û~¼‹8øh§µ‰kw.gó„>d†Ùƒ{ùO7±”©x Gìýkw.%7¼Ì\1Büî.³.x›ÇƒˆRŠoqZëõú«ln»XÊT|¾ˆSe•õðA>7öÉzø{wñâ–‰^•º‡žCuᘑ&Ôïl×Cþ¡ç® x°]gÙÀélŸ%â4Š|hO6wluÝC{ò‹8½¸cMÇòoNÀÇ‹8
Bsnd?ýïQ•rn|IÄ©ž¯Øï$qWÀ#ZõŠŸqZÖ)±+'xĘ}R•Ø•[Ä©²2ÿ|Œxr‚=<ëb:Ô(Mû(>Lıeey6××M`«Òòþ"ŽØûmLâÉ)îð˜>‡û wE÷MTëÏåêÅüÞñ¹*56øû"NÒ*9'²¹Lu*>E±œg®ÙÉÎyÏ
î7×|+âÔºOf'^oø6À׈8µ2½ºÜÂ/uf“½ºqúÛ÷·kÆæq'ØÁ¾¿Ý"Nß{–.Ù<¦².Þ^ă¶èƒEØ„oѺFž¾ +O¨ÿtÁ÷Š8½÷×7´ârõâ‚Û¬^9´„ÍÕBÆÀßq„EZý>?ñÉžw’¯–pœnßu#›»v0ÙؾëW"N“s»Úð³Îqq÷Ü®"n¡Ø´›äÓ_N}›xra%¼‰ôTׇ÷ÿPÀØõñN¤2¸áƃ½³[³¹?óþ ˆSû^èÁÓÍ SZèƒö"N½Ê +ñl®û6¸n2>JÄ©•)ŸÁå:¾
:‹¿*âTU¶=ö‚€»ØGÝöûo÷¹Bk‰ +-5‘?ž¤ãuVrY'|òA¯ +á ³âCD×¾|žÍÕI‡û¿(âTên»xÜŒÆãFÜ +b6Þvñ¤ˆÓ7áx6×—ãPzU³œŽ³UͲ‹¸‰Äß-J<vûüò¸?ɺ^=F‡frÀ¯‹8•ºîV6÷/>ß!â”ó_ÃÄKĉVõ;õÉ`ø«q1 G€YcMØÉÉÆСúì9Q|™ˆSM»sàQ.7bÁÍ>©{îjÁ~ºêÐ"²âM%«;%žJ]íþÕÀHÛóüÇ«B‹oÈ涃«:ï-⸶à“ZlîÙ6#™?©+âT]d˜»œÍõÎÊø[ŽØû©ŽÄØ\_µ™ +NmÌÀ殂*Ï,â¸|Ë]lîXØ«ø="N¥nj¦+à‘Vôcb*ñ6ø5§ï½/Å%ær¼¯ˆSYyË0p^]è`›Á©ÌÊ[†‹8M¼ÌØÍuü¼x! Çö¼õï`óX0g¥ø"N=«ÌþE<yÈ+lÊK‡ìòÔGƒ±Ì£×ÿ¶3#—«ÑD‰¶3›ˆS©«3û;Qâ-ðDœ¾¸½kßb'>xQü]§fbùà3Ä“K™aSžl3ØÁ¾|ðo"Nã¸9Ç^ärà +ÎI)þ’ˆSu‘ç•«à‘RýǸ–6òLM/â4íÓj>Øä$sx3áùÁd<ð»DœºFlær½‹Ì[Dœúu׫ìàs×I+¾G±˜ØfWkâѶ «ßéFÝÂ6»ÚK8bG›ÜÍæ ½É
¼±ˆS±ÙPRÏÓÚê¿ÒGÃýÝa\g1æ*7”Ü!â4©sê"ï7Rá“q=ŒC[çÔ_Žu™M%‹³¹íšØG½©ä"NÍıKÙÜ0㸽îÀØ·$õ|Ö=?OD:ħ/úôÀOŠ85튎äs#ÈùvELj85™s¬bsKoÿPı*Ô'¹IÌ3£MqûaBTe…5©>ßI8îD.úç£lîOzqªmŒÞ›Àý&24ëüKăûeŒÞ[Dœ©Îµ°¹eZ¸»síã"Ž
—°¹cèÇ2¾)⸅ü
Íh#ýVó´•Ï¦qʺçæ¿Áæfp{âËDœŠÍ†R¿q¹úd];àçDœÚ¸"gK°o[ù¨xi §µÈ”ëó\Á¦ø)§Ú涩(uÉé¾ÐΉÛq±.3-½ˆSMûæLje(,Rh‡\wdlÛ +øh§O¦Ôú¾àÑhõU]`çC©õDœ¿uÖ,6wçe¶Îš+âô½|g?ñh!bt·]†‹'âÔ»sÙÜvy)qj"kdoÂæ‰à:*Å›Š8uÌî¿ý<ñdxœÿóâþw’Yß÷vöÿþÛ/‰8µï[2zàÑàú1:šxM§ªr_©)\®ªµàÞ}¥¦Š8ÍÛ´Ûo³¹aà~XÅÙYçs*6ÛŸ&É:„5ÞþûL§/îæKCÀ(A™üÇ8A +¢"}ñ¢ˆÓÓüá—«—nãzš¸"â4Éœ~0ÍYQh ð¹ß)NãJ8àñ—F3yüoW´(>NÄiîbʇèÆÿi öÒ¸ê’✔âuDœêù|-ÖÿÿÇÄëÐD1ð"NÅæ×ôŸ²¹¥º68?ñš#äã–ͺäžý7^_Ä©{Ðï:'zŠ;ÂÆ ýËÄƉ~×^p“OÜ‘›ÍU·Ì +x¾ÿŸÞø›ëË6ðë"N_ÜÆN6wƒfBñ½Ž öYýlIâPzV¿¸ˆS‡|í¢“ŽáÀÚE§Eœ*«g_Ç6œ'¼s’ГØÙøìë3$+by¶7#r=Epž<[‹8=ýÊmKùÜÆZñ·DœÊüšqTUZɥЎ™¥W”°ßFñ"NO/|nñˆ~ÀŠ`XøÜX§¾Í±:°¹¯bkâ±:I8›Ô|¶s¹ +aºâ»%—¤_Cûi#mð’A)´øšn"NÅæó³#Øܲ9Pñ‘Ž+Ôs<—Ííà|œâ7K8žž÷Ûü¬³¨¨óîK/âÔ³:øuÈ#¬P¿ó?Úø5 Ç:ìçFƒG +ݯ£7>Vĩлü0›ÛŽK̇]îþxjŽçŸes=qÁŸqA?X²3›ÇÒÖe,ÙUĩ븟†ÀêŽrùþ ÅÁ»xó;nþ‚Íõ» ¾YÄißŦ2)àѶ&êÇ×Ç+ÞL±ËkdÿûØÜSݪmê™Èæ ×Ãß^çȧqܱºõ¹ÜÔׄ?Üí2›ÛA0.ůŠ8ãÊTîË殉ûß(â1¼w~©óÒz•ÇêÞ!Êyªi¶û˜xrz?¼[¨§÷ÛGñÏDœþöVm2±¹åz˜«lÕ&›ˆÓ ´g´2ɉÖðª2fÆÒNçõ¬ÓCÄ1å•e>9ù:³T‘q4~M±i¤~®¹l®£ï[àEœVÄ2ÔºÁO|Ú1êµ3ˆ8M°çkØ‚Ÿø †›â-ÿöƒàhÕ¾™^ß÷x“OBû…úrÛ`çC‚§Dœú´=N·ár½Ë ++b=N·qjef÷¾Í¶€“³{? âÔ=xúõWØ\oŽÏqê˜Åz&ïHõlvø䃼Aݯ-âTU\õ—"L:Ùúf^.P|¹ˆÓP¨Öˆ8›[vm£ÖˆšŽnž¯Âåú’TŒã.<›„£?ÿÅëíÀ£mËÔÑ‘ÈÁ;Š8%¾øÀ"ÄÍHáïôïŒ`¢Uñ[Eœú´¯ÈËæ–ìxyu@~ÇŽ—oîes[UVØñòM§·¢Uðh‡÷ÕïÛCzE«n"N‰ïÕ?7—‰`9Oñ|"NÍÄ£·&Ã&Äuè–…VýNoT²žWÄ©Cþõâ\®¯öÅ)¯oÜ*âˆåua;ŸÛ¶¬üxa·€›“RçË.l®>ì§óeW§Wþ‡¬ÄH™5¹8û¯xN§¡ÐŽ–}À#-&ú[;Ô´ŠqÌgÛ!àI)¾[Ä©ª,²½&q;ÒÒ†þc³…E¶×qŒLëøqÇ_Ú›öÑ¿S•%樧uüI±½Vi6W1AVk•>)â¸éã÷ØÜsPÏ+>FÄi$Õ|â +b¸¥83•ÍUožŽÛ(>SÄi +ÜaÛ7ĽHá2ô²JÂÁî>ÅwŠ8¤:^|ÍcVÿ_-âôÁölSÍUûŠ§÷lSYÄq9Ó³|îÓ¼E2½ âôÉÌÌmñ¹™Àø}fnWÄ©ÌÊXš_l‚k‰/ÿx“/v +›«ÎFR;kNp¤J]Ñ“q#ÊÖý;Û*êÇŠ8
BÇí)nF¹fTÿÎqƒÕÿq{*H8ÎÇjŽÍ]Ç@Y¨u&§áÀ•¬YÙ<fà½+žSÀƒ÷~Ó¤K\®óÜ€ÿ%â4Ùøaõ؉·ƒ#äŠ.â´.Sé3Bf”`Ú:VÂuQ]Túì!Ç2nŽßøÜN`ù>–㧿½X34R‰H‹‰ú1ž…pŠ×qjeR†WOrf*Ê·jÊâ–ƒï=e¸-á8È|õäf.×Ç?ÑD^=¹EÂéé/úŽxra%t¢U¯êظNZñŸE<¸}q+Z÷@%²c¨.²^&â4 +“J_/qšd~ïÙ›ˆÇ#pÓ¿s¸¿÷l&§Ú¦á/kÀ#mAû¡lŒaþò©„ãäB«Ûð dD«ÛqêQ?U/•Íõ´MÀïqÚí3ktM67u<ð:"NÅ桯æñ¹ãbù¡¯Š8M:½9¨*Ÿ[}¼9¨ºˆS±y¸¦}t Š(ŸL‡å€{"NOŸS°²€˜³šS°º„#ÚÆÓÜÅäqiÃo$âTæ+Ÿ?nF9r¢£z6øÞ+Ÿ¿,âôôšÙ +q¹úd°]ñb"N_\É‚yÙ‰ˆ©x Ç×s_á'Þ–6®ç¾.âÔ1+ýÄx~âíà¢ÏÒOLp“·ï[À窌ƒ¿&áØéôÀ]Ùܶâ83òÀ=Eœª‹1moêS?&n;Ži[FÄé½—˜ß”ÍU‰¿½Äüæ"NŦ§yÙÜv‚Û¬*|š_ÄqCëú×ù<-lÂmë—ˆ8õ¬~ù.x0n%B›HKßkâäÂ/ßý%á(óÅëoâòä¢ø×"N½‹¶Ç÷7#]3ªg½JÅ‹8Úlµas#ˆÝ§xG§gf)n:‘²N_•yZÅ+ˆ85R£_œÅåúÊìòýâ§wá‰yìÄ«ñi/<±Pı"¶ª#›«íöQ¼³ˆÓ¼Í++óïËy¯¬|TÄé½ç?ô4q¡,|âÅÿ]p<ÿ¡"Nƒ‘R+1¹iz¶ß+^U±èn˜,J|ü DZÊì%·€ûSáÕ…½‡Ë.ß&âˆþHðHõc¬´ÀÂ×É!âôântûLÀ3àŸ‹x²Ì7¾tçwlîÕ…âgDœ&^z|ƒÍ=7†ø´½.ñdmÓ4ï1Ô6Éå¼Ðm–îšx´ˆ¬ø"Ž@£»OƒG[ÚP\µ¯&Âœî>+âTYU~k—뀓˜î«üÖH§§W¿¼—Ï-DEV|¿ˆS=ãÈcì¬K¸¸Zña"N
ôÅ·ÙYg$lä/¾=V±E-Þk;ëlõyÅÁÙO÷9}ï=*Ðò½åpß,¤¸§^;b¼T8#âTÏ/¨ˆV&yÄ,¼‘rýFÊß&âôÞs<´ŸÍc2+~HÄ©Ð6¸-;›ëã´øÍ"N=«¬o”¶ILñ„…¸…ŠWqJ|§¹\_Æeü/§¿}ÔG‡ØÜHÒ2ê£ïEœ:äY&ncs5øGÜÂ,wŠ8-ã¾Wçñä1«ðbó·¨QûþÞéE<Yl_vzƒ›Q.ŒÐ<á&¶&:‰8îÊì?•Ëõæú`Ÿ!â4~?ãÜÃN¼>tb§Š8UVo— È–gDÚ¨ã¹6¦>Þ.qBÄ©‰\¹µ/x´‰–¾“8HüÊDœ& +um‹šå_ˆ~]¡®oˆ8õmržoÉæ–‰2¯x§ŽYó-¨.â»ÄÉë*Lð="Nngd7#-"[z!Õ¡×4_雸\"c/u]Ä)ñyz?!I<&™óô~RÄ©_W¼}O6WŸ«…{ÄÚ÷qúÛKlŸÄO¼m!~]‰íS%AÔ‡ßö&ûÅéõ|…ˆÓ”×ò2øÜÀýqŠoñ>™ô¢O†z•™ëÐrž¥R£À¢–¹N§ÞÅ“ù»ƒÿÓÅÿ{ÀÍÒW;wm<™¿—„ãðìeþÿÇÄ«LƱÊ:WárS3Á+H8:äÙËô%žÔº¾p+Òq?ئƒñr+ù<¸~Nñ·DÜDâ{ŠO|êbÚ(å‡rŒÐHùA-ê]¤~•ˆñ¹k™·DÜBâß%ž†…?
éÂÿ1.®OÖµ—ë“ÿX›¨Öµ”ˆSÇì¾Ïop³û>7Eœ:f6Íggj&0ŠÌ°é
G¿îó_;ò_œª.Lð."n£ØÜ.*6TUî:¿–xrY'ôƒU¿Ó½_/âôÅUu“G‰†éFÂ?½°b¡ÐVugI8v¼z¦2x¤Áˆ~LÂB¤ÅË‹8¤2<RÍ]Ë +¤´Lá?]UÔ1ðûD<H|UQâ都1±)¸åÅéǸ.¦}RK¿ü›®lzù§tË=ØÜJíÛrO& ÇmV7&6e½¸eÅðâ¬HAõïlÇÃÔlj)·ñ¹³ŠWqêýT£›fpðO5*ˆ8Õu
†¤°ùß"B7r¯ˆ[xq•D/Ž¦yß.þq;Ò&1õ;ò…Þ{¾—k²yŠ˜â 7øå¢ÄÓH*{½6àV”¥
ý˜˜ƒ~]jîñ¿³¹¥wúƒŸ•pijÚv ›ÛB(^IÄ]d]KQÖÑwwÁÄ#Ê·þçÆì€?*âÔ!ÿå‹â|n!‚œâ¥Dœ&™¿[GøV¾[_ÄñÅ¥vcs=¡^åºÄœÃ-+¸–èJ¾ßDÜEâ–$áq®ºÄáSúwžl€?0tœˆSßæ›O6q¹êYÅ°‹û›£ß²ŸnÛA]÷ÍÑÝ"NÕE“؉×{0
ð§aà²ى×W¸yà‹DœºFmÏ×â'^¯Êß)âÔ«ÜpOvâUM‹î)&â +íç¢BK<wÄ]11lë‚ÿUÙ¸àsDœžþÖÿ‚›Q6ÄêÇè -?+â´ó¡Çñãÿ3Õ©yÂÂf`Åk‹8uæ(ÌM¼7‰ï}îb"N£È¥…ßâgëçç?ð”7çNá'^õçMði"NMdæ\G‰ÇI¥Ô<CžäsÛÆvž!Oˆ8Ã]Pÿ·QVo â.²î°(ë¨Ðö›sŒ¸¢¥²Šé«¬±1²ßœSŽAh‡‹o‚G€Çô¥Æ0Ûáâ;"Në2Eãù‰{f”0)úw†šàyǬR”¬A<nF9>¯§çh(tK
|œÎS|ˆc›VÉj’Ä£ØL¹ +<ÒµƒþcÒFÓF~(â”øνRÜÃÑÂν‰8UÔ%?Éæz«”þ‹ˆS¡í^<ñÄ?mû‡&R_¤í ºè^ü§—«Vp‚=lWÿÎ0ƒAh®Z-Eœ"Ê1—Íõ9ê€/qšŸÏzøi6×·¬âž‘Ãω8u̦?Ö‘ÍueIï}È°’îâøaEDÜAâÛŠO½‹m“û.~”锞†·â¸}~DÛI"N+MÞþ
ÜŒúOÿÎrâ8jtèôÛ\n¸Ž‹ƒ‡N/p[ÔvÄò ob·#V@Ä©‘Ê{¶°€#b¤âÅDÜÄ‹;#zqÔ¯›·u)q3ÒQ£äï¬MÌÛº\Ä铱íõLîß[…ùyÛþBÄéé¿ÖëÈå:Ö +m±âÛùÜvp¨³Xñ"$¾ ñAhß…æEp9/´[¨~æ_`Ÿle2dÝÏæV0õ¡ø·ø?E‰§€“O¥€[Q.öÕ±`#ôÅS–ˆÓ‹‹¿s7qÂÓ
ïùÁ.«3åLÃ[Ø\‡ú°ÁóH8vïÇßi(J<U3oünFä: +ypËÉo™øÜ@(oÅoñR”xêœl2~&®ÆäŽzœ6ᇻ´0é´É8#âô½ß~t/›ëPŸ&ø>§1ì³"¸©yx#å_üg¼ªˆÓ7lÆ66×'©Mð-"Ne¾g1š·1}÷I„¬óÿ'0SÚ³Øc"N¥îHóìàVD®'È1õq¤yf G§tWKZHUƒ»˜â¡Ë:úw6n»PüO§NilÛ<.÷ƒ‰›à¯‹8Õ´MËVaó„caYçÀàÜ|nãæ>ÅsŠx‰/+J<åü¥«´QJO9%»ù!\ÿÎ +‚ë^$âôÉ\ìTÜ´’ñɸ›àü.§ònï`,³4ï˜é£FqlI-ÿes6Ù.Îþ—ÿò^ G+Ó¨{k~âö7êÞ^Ä]dÝbQÖÑÓDëù“ðçé‹Èг^.›«®¶ë/—QÂ1Ù8`àqIâqù«5ƒÁ͈\¯#ÊÊž2w°¹úâÌ€×qʺékßç'ÞÂ]N_»ZÄé{oL#6wÒ°¿7¦‰ˆ/n€èÅÑ®r^!÷;'áÜo¢0ÁþÔW¸\µðÁ…POýð§ˆSmo÷;ñž…
rŠ/qª.ÆþY›Íuò
ðú"ŽÚ¦Ø]ì¬Ó£Èxc Ç@lúôÌœ—™>=«ˆÓ÷~õÐ6×Ã|›ˆS[ôRCI¡Åy™¢—‰8õmJ?v?Ÿ¸ÅLñÖ"˜(ª.¨^Ôe$ñ„aDj L¤ø‹"NŦËêŽ%ì.«ßqÊù³Ž0¹¾¡¼?&âTÓæ9Ša`†w‰õïL¤Êst˜ˆSUÙåÕ\®—ï1õÑåÕ;Dœž^kmup^hõ 5Soí}HÀq Uñ¶Ží:µÖV%žšÈÄéd Q}¸.R÷€B†Q×èÑVuÙ<nÄPÓ>Úª¦ˆS]áûs‚Ä›ˆ[XáûK¢¿ÝDÖÍqªmÎœîwÌB§>,'/ˆ²rnäK"Neþ¥Õ´uÁrüê"t +^œ…“ßüà·£,aû¿³
C¡î¯ýÉæþ€ÿ.à¸S©ñµŒC¹\ÏÒß®øËÜJœºµ$Ÿ»8¬xÇIdõâLÑ‹£ï}YŽãÄ#-ë$ãÚ0»,ÇŽEäì7?eê#ù;3¥{Æs¹a«DÆÁ_qêßÒ7›'‚%-ųI8î Í~󢬣ªò¥>¹À£lA÷¹e«^ã¿ØÜs‚)n¯ñE Çü|Ñf}Ø\·Åqð"NOOi×’Ÿø`Ÿ•âEœzÏ}¼‚ÿâôáð÷DÜE±É!)6h"s•îL<ÒxÿwºÐß?ò:›»n!Wüªˆ;H|{QâÑHå}“xr|øÓû*i(¤ø|§‹B®^_ÊçÂÛ*þžˆSÖ~k›ÇÝà´Î7dårSÿ_<“ˆ{HüW¢ÄÓ÷þêIÝ£Öׯ9¦cù!{CŸ®ª*D„~õd=§vÂX”ùäÂJxâý»¬¨}Wü¢„ã^à¡Þ÷;¥!+>OXV…†x_Äi7âè.÷³Î'â4Ùx¥Ï1âÉE¥ð¹Ž²âb×ÇMw.är}6ŽÏßtç<Qm“£+›'̽8ÅýÞÄØÑ“u¶…Ë°ï'âÔ=¸ðB'>·±"¦øÃ"n¢Øü(*6TÓþ9oñäbbÈÆ ý;Ãs± –š¯B:>n»HÍWþšˆSmóÀ‹Í6BF(qj&¾Ý^‡ËMÃÂ`Dñz"Žy›y_‹^ãîºü4x”
±þcœ´Ã>w]~NÄ©~ÿm*u~qôç$þ›þìV…Þ{§ˆSu1hMe÷À«‹8õë®VH€›Š;¡¬~Œƒ¡¿KÄ©Øäÿ`—«â–Å'‹8
þ|q=›³C‹Ž^gÛï3ÔÙÇå:.¯ÏPgˆSÇ,×ó-ù‰bu*ÞVÄ©•9|ù6×k‘&xk§êâà©¢GUåžš5ò7cDùdL½Ÿ5Ÿq*6ÖÁâ+„[ªžÇQbÅ_qôm²7·Œäîì0nÚú +Å5øGM;-OY§Fja*².f:É#Âa\7åØ»0µ³ˆÓ'S¯ÑÃl®×RiüÞ}ð-\nè_zà¹Eœ +íÐÍ=Ø\÷ÞGÄ©Øïõ›'‚àùŠŸqzúÐñÃØܳƒ¨ÈCÇ?%â.ŠM'Q±¡¿½X±ÝÄ=#ÚÔ‡÷÷ ÊÅŠíq…¾ßÊäúpŽÓ*¾]Ä©WyùyB=ý¯"TVžá.ªÊËÏÏqM¼tWC>w9åHí3\nê¬÷ÀqšŸ¿vs#ÉßNcXÅqšæíõQNAâQÓ*žGÄ-¼¸ú¢~wp+êÓuð|¬ŒÜ=ˆÏ]Äîk|-ss6·]\S¢ÿ€(ñÿ°(ñ´u¡Ëâ>ln¸ L}tYÜ_©Цœy´››6ö*~§ˆc†<sÉ‹Ãw˹Ó/.XHm9w¶ˆÓêÀ¥†±¹ã"uê¿Èæ^îRñ‘"N}ÚG +r‘F/"âÔL,íÓŸuú +¸òÍäÞ!pûR#8×&¿ÅažÖš°‹ÊE—TÇMÖ„=,í»å@4™kŠ¹.c9`gq(ï?U¼¼-h¤ýa Ǭ›ñ´[8Ë{Ã*X\P¼a~‡1XÆÞEê,½ÊÞ7×R¹±‹óó½on`qh";E5"÷ÀÛŸöq—"á´O§¨fÇ;VT‰Ì½¡È‡¸¼äsäŠSNo0²„¼–ñ™øyI™;tó̇ç‹6ѹ¬ùøV‡ŽY~êûŒßŽQ‚—±8TÔ݃ï£sM÷ñáŽqé‘*™kº¹Å,=ÒÁâf¶y€“m0×ÛKmËyí/.¸$ÑmÇWWÿîE*—U¯)¼™Ãqãƒ{M6™C!÷šy,O—1–Ìu3\ðñ,OßýDýÕSäÈãY\Áló2+Û@#eIýpï2®SnïvùEÇÞEÏäþmtRÚ®`SÇ°8ÌÛå¾Eå²d&^ðwXÞüYuäÄ;}w.™ÕÀâЧ}ð“27ö|èÈ?aq·æOEî]Dn¿{à–EóŒSùY,Ë#mt.~€y‡ã«· +ž%sÕ|« ›Ãñ²ËNS¿oãjÛv»KZª÷ø&,2¦^eq(2ö鯑¹n¾ŽÅ¡È”÷D檢⸼ŸÎâçoÌë†Ü¿
/ªq®±™çoÌ‹dqxú/¶_È\M,†awíÌâЧ
œ/“ùo®) œ¯³8Ä]œÆà:î
to\FóŠ†ó´î/±8…Ö̦rã´
ŒdîR“ÃáX]䮼FN¼&ÆrxZæÊV‡ò¾:ÜNæb0‚«Ã£Y\Ål3”•m ¢®³f +å]?‡ÎusòÁSŸÃâø7‡]%¿:·æ€7/x‡ã›?2‚œx£#¡#Íâ4RsÝFæÆýo +òî,õüõ”7È\–~=e;‹CM»¨ì ýÕÉxæƒà‡9gNvÆï¥Xó¾HÁ?dqh¤ö
?Ju*ÞÔ)øqÇß~:é<=Û˜«‚7s8>ýê)ú›wèx¶àû9wa×M¦'ÞÜN+ø4‡"ôz[X¦·Ùõ“;|õ|ÐëÍ,¯n]m/:7NïCÞ‡Åa¾®hFƒKxçBÑŒY&Üê_Z@æÆ1'0ñ2ôòkd®éx›à+X~û®h‰þÛ\Ò\aqøp5³†“¹SÓðY²¸Œ.‡õá Ž^³¹ìOP¨÷ï$‡dò"‡7_î<BåbçÄàrg-‹cp`TrÅßÄ«f˜–àCY#™sÇй‚‹‚'±84R=^ÙKæ²ì2ïSÏ“¹¤;p7nŒZÇáx×Æ•#è‰WU(q‚fq€—VØÉ\×]¸”YZÍâ0í2ô¯ôÄ+:Öu!CSXÜÌ6ÿbeÜÔÙypEöç¨OãïÄX2ùó,Ž³…wœdqþßQÏâÐÆ4ô%sE1›È ¾it®›çUõ}’Å!ÛX³É\ä9¬.¬Ùc9ªñê"Y¯ +ì@ÏBàªäOˆšwÎËwÖ@O.‡ãi.|LäÆ
n涋>eq¨.Â&ËŒÄ;ñÃ…MÖ9ëù°Œ+ŽÇÛ +~Å¡™°¬ÀÚF•ýYÆm8ñV#ËŠl‡iŸð7ߣrïñ82òÝ,¿86ˆ‘xŒöñü¤aýv y
‡ãœ•gY_òowkN<°Â³l +ÇýÝ+—άëÃ1¶ð‹cVu=ê®I·#÷kùÞà¢!Ç Ð®I=Yª‹¸ÎÉ\÷]z×9”Å¡k4©ø&™{÷ë´ñ£¿ž§sÑ5R‘Ÿcq¨¬î¯}þæÍå{ÁËX*«ÔOóÈ\ôê°}OýôEÇÔín§s
‡‚ïdqøpÖ¯bäys’¹Ãú5,5mìRúÓMÃ)¯Ø¥ëXÜEæ«È@®³V—×ü::@ö^rŠ‡¨þ‹Ãoÿ!¤šÌ¾C•ãŽ
sã8˜h;@ç*^ì+xG×0ñQ¬ÄÛ·õ«£¿:Ù¼#ÕÖ¯‘Å¡žïQ¹–ÌÅ\‹ìQ¹Å¡²ñ6=ש +Þf5"â]‡7_7r™k +n-|ƒãÆÆÄ&ûëd.*KM¼˜Ãq‚=<`.™ëš‚‹áϱ8Ôó:ßKO¼®âºÌ‚α,ñ6ÅMÿæ”wìœ7ѬÁ¡‘ªÝx'£Èàî‚÷aq
+êìŠfnÌÁ9+]ÖüêË ²§±8..D>Jæ’f&þfd +‹Cž?ùíTnÜ™ˆ“WþL~ºb,N ÆâЯ»¨G‘ïôsrQïÏâPd¦4xoÞ#è)
q8î:ùmwևð̲³ÀÞÅÄö'Zuc²¥º”5°8|8Ûøtnþ|‹ã³“¹®(x
YþÆT‡f¢Ùó#ë0ã ½öƒËx®Qèµ<‡Äg†§sÕ\
ÌI`q¨¬²N”‘¹¦cЈàåŽá:ÍžïY²MÌȽKØímd6cL°»W2¸¯Vš‡¹[—p-RiÆâ0’jN~’Ì]šûuÍÉ“XZ™^v'qÊK$^ÆÃ÷§N°·qøî–éñ˜xÅŸmÔÆÔ7žn™®²8d›àŒÉdn\±¢ ŸÎâ0Š¼mõwt®«Ð«ôôèWEç +Î#øA‡6n–¶ŒÌIfòW9Ÿ¾¾ª˜Ìª¹û~}Õ6Wð€šÖÃd®™q‚W³8J,!ô<ï;m£ÄbãpìYUÕž g
ï—ü‹»±È4±Š<½0ôœ’?GB'*œ¯++apó|ZëRœpsúu¤³÷ï$<Zðý,¿ÝÚ˜MåF3q•Öƹ,]£Øó[ɉW$ó΅دKÉOw·ÝßÆßeq¿…“x(q£[w_"sã{7ò[Ž£‰4wWzâ5w¨¥¹»±8Ô´yGƹjÆÓ +>î÷ð–í‡Ü¼¶ e{çéØLĤ‘‹ŒèB¹ÍàÀ´ù,³7XÕ…‚¼‹Ã@¬ËãŸÑ_j'l&s1ŠÄÅ{ÂÇÕÿÙ‹î£WF„òá,•ÕbûÆw—0¢u±=ƒÅÝøájYJܨµ8wáò3TÉ)ª*×&F]ÌâÐDÖ'(t.;0p¢>Agq8{ÿFÖlä²?—&'Ë.s¦4k!‹C=?xÚ_¨\Äpý]ð ,ßýäŒß®»qx)ã+úÓÍf?ÁâLüLVâáÍoNÆÑ„Kñ—kª¹[gsò;,•Õ”Ÿg“¹ñ3M>ÃqÚçð¹kdîPqýݺª€ÎEí@¾„ÅuLüVâáÃY`à„[öçÈãïtñ(“ïdqøp)¶¹C‘ñzšKÏ!sMÃÄ^ÍâP`s†‘¹±Ùï =؃Åa(4‡Ê%·îÂå¼ø ù,n~¸õ¬•UÈxÈóÞ]®~L¸µÅ|à^àñ,Ž±w}Cæ’¦`ð€í®z‡yDžƒÊÅËS°¢ŽÈÄâðÛŽ¬ '^Ö\0Óm¹‹üt§Œq‚k,EffÉ\úoW̳}f–Ìgq'¾ºrÖ«ƒ<ß¡úÀe¿Ûô>Fuc®ëPÃâëºY—’¹oUHðå,]âðÁÆV#!®¦äÝaü[ÞñÿqQÏâuøàÊÿá?9FÚ^¦'^5¯ÒNØa§¿y]Ū2aG‹C¶Ih\ÆH<^C&ø«,í{Ò¹d:×4Yüo,vùýu¬\çDÞÈâðÛ÷ZHæ./<—Å¡žÿòt==ñÆéÿÈ¿]1odŽÜ´Ÿ‘xóFæÈM‡XÜ…¶€U`!Ï'>r¹÷hßöŽþ3þÌí; &ñ‘‡I§ïJvÒ¹êÂC¾+ÙÍâðÝ-™ó+þklü£if3aÉ\ÀáØ1³éGÉ\ÖÍ5›~œÃñÃŧ¿Hæ’ª`‰‹O‰Å¡•iÔ¿"sc_#Öqi™ëª¹|i‹Ã‡³/^ÇH¼†—ßÙodqh&Æeî¡'Þk4.³‚Å!ñiÉEô<oN´ +þ‡ã”W}z&ýÕ)ª?Ãâ0[˜}ê<½Ä™Ûmofq˜ê<ýÔFâqï€à±¸ìINÅHæ>Ø«T$¿&™§˜çϾ’Åõ‰[¦IS¤.Æÿ{{ÇŽË°Rénã_úvì)…/º½·õꆋúgþsצ¨»ïþÇÈ^r–KNãzÞê+Eo¹w‹=¿ÿÔììƒâãçÌ™—•—ž?iffV|ú´4ãFK'þƒd +˜?2¿ÅØ©S@‡ÜÀÀ€¨ªÏ¿V^±L[PSýhQÝé3Jï}Dz<UØ%¯ôžÇê²^8ÑtmêˆÃ=ß?½àÐÌoº¹¶'ñzMDÞãA9—Z¬î˜½“ZGæu÷œØtÅ3¯òòܼ'.LÞ:¶ÿ…”3ý=ìDØãúTÅ:þöc¡‰êi÷;LÚº´ÏÏ99‹>*>³·¼C×POôÓ!_÷¹î—ooûñè‡vÇþ©iZøÌÊ1ÓOŒk;_S±°pßÑMeSÌ:{nïŠÃ/Ox?sI™uT`Ú#gzOyѵcç'?«œ¼¹¥.beij¿ö‹ëû²Õ’¶]î:£vés±œ±”~1þ½ZÛ†mzYÞ÷Dý©äÂýÅéçÎôú/H
+endstream +endobj +27 0 obj +<< +/Filter [/FlateDecode] +/DL 788 +/Length 32 0 R +>> +stream
+xœ3hb0hbüÁÄÈhÀËÆ©ÕæÑö—‘‘••Á ÖPÂ@.ÄÉ(ÆYéPœ—šjÈmÀÉÆÊÂ&Ìäêj¨d +ðÔ0³{•–é{‹óšXšXšZF¸††FÆP.ÐIÊL,Ö}!â¼Æ@)CKc3cƒ(. Q²¢,Ì\Œ¬ E®³g?*270*42´0BSÄ +endstream +endobj +28 0 obj +<< +/Filter [/FlateDecode] +/DL 1258 +/Length 33 0 R +>> +stream
+xœ3hbyfÐÄ|n3#‹uŸ÷^6N6¶ï¼ŒŒ¬¬±†bp!NF1΂ìL‡âl½ÔTCnN6æP6a&WWC%‡KXÒ1X!8µ¨$3-³¤85µ(37³8;µ8»´ØPÀ€¤†Y˜Ý«´´H7ØÛ@Nœ×ÀÐÀÂØÀÐÄHD‰óšX™A¹´¶¾‰Q ÙÃŒ¬ÌMŒü@q.¦&FF†ÆB3;cök
z…ëÊÜNŸ—Ü”`è6½íË·%‡R]Ï_v¨y¥´B ÂøLÇÆË^ß’Ä«ã}¹ô.œïV~çÏä·û5ß©½É/dzÊôÚ>øÿ*åéôö3ëy¸8¤‚—+>´ð¾Ö,½v}Ê¡Ÿ2U=i¾iò\ìv˳§NnÝ)µaç‘ß¼‚ß¾^û)}\G{»Dà¿ÕßVx¬Ï±ö×ÿ㢻œZø‡@YãiÿßGÚÞò½(jrü•½˜GõD™g~Û¬v7O={ãÿ!çôÛÛ'?PjÒÛ÷5C£yçAëÌj…[~srî:Û_•³Séz7÷m™«QjѼ^=M¸0ÿŸé}{&fFÆÅMŒk€!²Â€z²ÂŒŒÿYX
˜PP$¤ÀÒÄÈäp1+—6#ã9y`p4~3h¼ÀÆaeegb2h<,×x€!˜!ŠdC C&Cg3$a P<Ÿ!H–1<aÈaÈŠEA2¥)@qG ~] úb ;Å„°‰ ‘L†\°Šl D–‚U'ÍKÊèõyã´?hÈuÙ@Vf‚m‡˜— +-6P„ûˆQL4£¤¤ÀJ_¿¼¼\œ,õ“Šõ
´Aá"Ï¢b +endstream +endobj +29 0 obj +<< +/Filter [/FlateDecode] +/DL 998 +/Length 34 0 R +>> +stream
+xœ3hb~dÐÄtj3#‹ë<õU¼lœZmmßyYYb
%ÄàBœŒbœÙ™ÅÙz©©†ÜœlÌ¡,lÂL®®†J + —°¤c°BpjQIfZfIqjjQfnfqvjqvi±¡€H
³0»Wii‘n°·œ8¯¹¡©¡‘©‰Y”8¯¡™…‘™¡‰‘±a”Aé–(ȃÔpK +(IMÍ+-NM11‚¸ƒÛÕÓè# +š•}ÏÈÊÀÜÄÈÏ +¬ôõËËËõÀ)H?¹(§X?˜@,= Ǭ20Ñ5ˆ°¬ªr_ü¤s½Ôy.‡åöùï_Öî3)àcc‘aÿ2gÿÕœÍ[æ)ÉËOñŽ¨êEK¾Ì x[$Xýãúä…o8Ø-l¸Ü•]W|òx¡©£³5fBy[ìýîÜøMá2QëÚ4&t»ß;$[ò¥)In½ú•ï] +œ£v™DNŒ™ê|p½‹Îɵ~wU”w¼fÔ7cûföô¶ãNF-“ð@íú“+Þ¼Óo:£%gù}‚áùî—Vü‹ÿ[âi/·vÇäOçöíÚ[6ùkÓÆÓ‡‹ÙÍ:·ïìlÓ–¶)c¸àæ¸+?mý¬mW4,òÏoÍ7^íþ#~õ"³ÜWÏwÇØÝÙð4Q¢põë+œoŸšÕž¼FÖiïŠckžåÿx𶾵êñ’3;¹•Ø„b¬§ï½<9t+ +endstream +endobj +30 0 obj +0 +endobj +31 0 obj +312198 +endobj +32 0 obj +606 +endobj +33 0 obj +1013 +endobj +34 0 obj +909 +endobj +xref +0 2 +0000000000 65535 f
+0000075644 00000 n
+11 1 +0000084581 00000 n
+22 13 +0000076006 00000 n
+0000076160 00000 n
+0000076238 00000 n
+0000084819 00000 n
+0000084907 00000 n
+0000397197 00000 n
+0000397891 00000 n
+0000398993 00000 n
+0000399990 00000 n
+0000400008 00000 n
+0000400031 00000 n
+0000400051 00000 n
+0000400072 00000 n
+trailer +<< +/Size 35 +/Root 1 0 R +/Info 7 0 R +/ID [<63038667617ACEE5E29014FD3093D783> <63038667617ACEE5E29014FD3093D783>] +/Prev 75328 +>> +startxref +400092 +%%EOF +1 0 obj +<< +/Metadata 2 0 R +/Outlines 3 0 R +/OutputIntents [4 0 R] +/PageLabels 5 0 R +/Pages 6 0 R +/Type /Catalog +/Extensions << +/ESIC << +/BaseVersion /1.7 +/ExtensionLevel 2 +>> +/LTUd << +/BaseVersion /1.7 +/ExtensionLevel 1 +>> +/ADBE << +/BaseVersion /1.7 +/ExtensionLevel 5 +>> +>> +/AcroForm << +/Fields [18 0 R 22 0 R 35 0 R] +/SigFlags 3 +>> +/DSS 23 0 R +/Version /1.7 +>> +endobj +35 0 obj +<< +/FT /Sig +/F 132 +/T (padesDocumentTimeStamp_2) +/Type /Annot +/Subtype /Widget +/V 36 0 R +/P 11 0 R +/Rect [0 0 0 0] +/AP << +/N 37 0 R +>> +>> +endobj +36 0 obj +<< +/Type /DocTimeStamp +/Filter /Adobe.PPKLite +/SubFilter /ETSI.RFC3161 +/Contents <308006092A864886F70D010702A08030820DCD020103310F300D060960864801650304020105003081DE060B2A864886F70D0109100104A081CE0481CB3081C8020101060B2B0601040182AC180103013031300D060960864801650304020105000420313A5072F0F67C45A9B91780D1E1F424996CF7C1A2DE65DB8BB65959A004CB14020310A33B181332303134313131323133303134372E3432375A3004800200C8020860482CEA3941B545A059A4573055310B3009060355040613024C543110300E0603550407130756696C6E69757331163014060355040A130D42616C547374616D7020554142311C301A0603550403131342616C547374616D7020515453412054535532A0820A7C308204B73082039FA003020102020A160E4D35000000000387300D06092A864886F70D0101050500307F310B3009060355040613024C54312B3029060355040A1322536B6169746D656E696E696F20736572746966696B6176696D6F2063656E747261733120301E060355040B131743657274696669636174696F6E20417574686F726974793121301F06035504031318535343205175616C696669656420436C6173732033204341301E170D3132303531353131333435345A170D3232303531353131333435345A3055310B3009060355040613024C543110300E0603550407130756696C6E69757331163014060355040A130D42616C547374616D7020554142311C301A0603550403131342616C547374616D702051545341205453553230820122300D06092A864886F70D01010105000382010F003082010A0282010100821C4FA052C55A990B6B62E5D59054B5EB08B7324C6B6C29048070A931DD58C90E33D92FDED48AD39C697C230A854ED7B7D9303F3A835E9220E4F4EE0D62D78D675B8E4A75E2B7EF513C9B47F21F38E7BCCD2428CC88E8116DC42330E2464B20518C68D850881EA2EB46EDE52B3896AF2128397F07EAF1A27B5F1AE9551557EF10AA6F2C56E5C265A4B443A470388D75BD9827EB4F6214AB522D015954F3F4325BAAFDCB0F7F39407A57AC1F0C2D46C4CBA568ED1A5B997B590D064CBE24FD6C55C1DB6D8B874E49425C61A7DA30996F183F4D8F2F0279D2B8875FF2E7F1E47B4E49DCD6DDC886AA7DCCCF04D480674D6520ED7190E879E1B64A046C559DAA0D0203010001A382015D30820159301D0603551D0E0416041451F4B16D4E550EDF93975C83236513707DF6AF3F301F0603551D2304183016801408C941FFE79B5633DAF0D7B361B4485C15A31B5A30370603551D1F0430302E302CA02AA0288626687474703A2F2F6E63726C2E7373632E6C742F636C617373336E71632F636163726C2E63726C306C06082B060105050701010460305E303606082B06010505073002862A687474703A2F2F7777772E7373632E6C742F6361636572742F7373635F636C617373336E71632E637274302406082B060105050730018618687474703A2F2F6F6373702D336E71632E7373632E6C742F30090603551D1304023000300E0603551D0F0101FF04040302064030160603551D250101FF040C300A06082B06010505070308303D0603551D20043630343032060B2B0601040181AF650102003023302106082B060105050702011615687474703A2F2F7777772E7373632E6C742F637073300D06092A864886F70D010105050003820101003ABB17DBAAED138816BD95DEAF9EA9555D0F6A93678DFBC092B389A621A34E7D87556A83908CA18E838AEE89B28B04918A08B15DFD2DA1FE3D4FDA9EFCAC3220F4B5A562591FA9E4ED594D45E3CA4EC28F5EAD80B7971A8B109491107B14B4588C8C4C2E05FFD66FD14F791F000B9DAAC92E1D8ABD6B0645C0D7B0798ADC15726ECF3BFC202056E375D1DE74C4271216D74586A7BDA7266C6AA6679CD29773D791B9FF10AE92464C8DFC525740FAFDA4E40D2D067AC93855EFBADC4615D495FB95A87C660659FEC75185C9EF599BAC277BB9D3AF5922D46B8980C84949FD8A04B377D953FD3478176E509C8BC012C003BA00D11F27E20755DC9CA7AE18211BDA308205BD308203A5A00302010202105891669CC008CA254070B327FF9C069E300D06092A864886F70D01010505003074310B3009060355040613024C54312B3029060355040A1322536B6169746D656E696E696F20736572746966696B6176696D6F2063656E747261733120301E060355040B131743657274696669636174696F6E20417574686F72697479311630140603550403130D53534320526F6F742043412041301E170D3132303330333131303031375A170D3236313032353132303530305A307F310B3009060355040613024C54312B3029060355040A1322536B6169746D656E696E696F20736572746966696B6176696D6F2063656E747261733120301E060355040B131743657274696669636174696F6E20417574686F726974793121301F06035504031318535343205175616C696669656420436C617373203320434130820122300D06092A864886F70D01010105000382010F003082010A02820101009DF52784E64FA593EDECD8AD94C3DDB503E58A6E709468A6185A54615E3153F487953057DB98B3735EF9E16E6E4E5E63E76005CBCAD78D82B9D184C4C8DB15AA7C8A5FC893C3C5B0B5B90CA2EC7286E520AB80478DAEF5381846FF6699F5D9404C2C514942DDA8C2B1BAA4555DB3765F38929257D8BDA92B2F788F6F062787B34A23878FF1B665F4D402EDFC93FB08947FCC8389BD289630B61CE0FF6A49E20CD6486B6A3865FCFC534E013DE7ECCDDDB656594AD6883CEE2273248CA46445EA61F9933F69792752AFFD72C189CF424D32D6766351E79A1A768CEC893C7B3D86F21DE481156E519C8B2C426D4D9C0C3791F02A93483D3CACC3E611C6B806E7D30203010001A382013E3082013A306406082B0601050507010104583056303306082B060105050730028627687474703A2F2F7777772E7373632E6C742F6361636572742F7373635F726F6F745F612E637274301F06082B060105050730018613687474703A2F2F6F637370322E7373632E6C74301F0603551D23041830168014CCBFDEA79077626A1D78692E0A389B77515303F0300C0603551D13040530030101FF303D0603551D20043630343032060B2B0601040181AF650102003023302106082B060105050702011615687474703A2F2F7777772E7373632E6C742F63707330350603551D1F042E302C302AA028A0268624687474703A2F2F7777772E7373632E6C742F63726C2F7373635F726F6F745F612E63726C300E0603551D0F0101FF040403020186301D0603551D0E0416041408C941FFE79B5633DAF0D7B361B4485C15A31B5A300D06092A864886F70D010105050003820201005C035DE76F88FF65493FE6221771C14922301FFBAD77F09D77C8155BABF3FC26CDEBEA2724D4F7A3A6630DA3903426CC201D23FF328FC40A7A4A7463CC72B2526EE97D4C361826526623680DC3B7940F545AF923C63DBD3194792986AD78527D609C7CDD03A5657DEA1D4F1E96CB5DD021D5C9782E29286AC56B5B10EC419B90EC5C429173264D8CF1433CB500753EDF3AB93668016F759DC2A2A1471F491E96FCC61482A8ADCAFD11AC895101627C9585362E2B98ADE4C1E015203AEA03C3777618CDD569E4A66CC415A489D9CFC4628BB24980C9F0318EB98776CACA9D9C0AE8BF9288B1A04F379DBCA2BE015C71706F16B5E90531CE335165DEF3B5369773727601E409AC35BD20573591C0C4484DFFAE39A28DA836433206511BBD4C35DA54182DAE632E57C47D13EF075AA10937EF3FDC5B4AF81FEB2001ACB344E71DF7C00AFC79322EDFBF08B888A2533CDF0C07E50D3F90187DA3F49F17032B1C552C8056073931D189B1D4904EE6373337734511A6F7E6A16965D208EB7E04BD945D10D4D5C1D8949760CF5911ECECDF7647F809BDE7C31C73607FF386D506B1D6C0A6E8258F4D69AAE37C93810BA095869095D52FDD3E52593E4A37EF067C42A51CAC7E781BA6000FC52570017433CF6B1008E1CB310F3A1EE078D2111107178FA337DC884CD15B90EB558A4FBBF6A68B6D2954C2F3905A380112D755D78AE6E829318202543082025002010130818D307F310B3009060355040613024C54312B3029060355040A1322536B6169746D656E696E696F20736572746966696B6176696D6F2063656E747261733120301E060355040B131743657274696669636174696F6E20417574686F726974793121301F06035504031318535343205175616C696669656420436C6173732033204341020A160E4D35000000000387300D06096086480165030402010500A08198301A06092A864886F70D010903310D060B2A864886F70D0109100104301C06092A864886F70D010905310F170D3134313131323133303134375A302B060B2A864886F70D010910020C311C301A30183016041420A352E2CE2E73070BB3CF9DDE8A4EFEF0F0A35B302F06092A864886F70D0109043122042020E05DC47F569C22254622500EA640A2270476D484D5FFD44646D04BCA4EFC94300D06092A864886F70D0101010500048201000D6C4FBC93BDF02A2A93BB32D2B5D0A7F35E9FAC9E21249F6279020EEE1C37E623D0FCDAD3E4FA209B0B606BDBA2457EB475AE05262C907B19A41B69C99568E0C766E1018BD7761BFEC5852E267DA68CC110779A959073958FDCAB548AFCB1182AF85C53E81E755310D7684A6D380182FDD94F44B7FEACA9E4F307C3201E39BB51A0295DB65260703B499AD717B3834293B797CA7C17566496A828704BFB375309C50A58C711FF31531A823C66BBCCE4CF31D5B3E74BC70EB73A85A9301000C87E789D3A5E0903D6670402C64F496C3D071890AAC39732863FDDE517E4C78D401FE325B27389194E0223A7DCEEAB98902CD0DE0ED77E3B81632EE8E42D5139D700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000> +/ByteRange [0 401203 409397 728] +>> +endobj +11 0 obj +<< +/Contents 12 0 R +/Parent 6 0 R +/Resources << +/ColorSpace << +/CS0 [/ICCBased 13 0 R] +>> +/ExtGState << +/GS0 14 0 R +>> +/Font << +/TT0 15 0 R +>> +/ProcSet [/PDF /Text] +/XObject << +>> +>> +/Type /Page +/Annots [18 0 R 22 0 R 35 0 R] +>> +endobj +37 0 obj +<< +/Subtype /Form +/BBox [0 0 0 0] +/Length 38 0 R +>> +stream
+
+endstream +endobj +38 0 obj +0 +endobj +xref +0 2 +0000000000 65535 f
+0000400590 00000 n
+11 1 +0000409456 00000 n
+35 4 +0000400959 00000 n
+0000401113 00000 n
+0000409701 00000 n
+0000409789 00000 n
+trailer +<< +/Size 39 +/Root 1 0 R +/Info 7 0 R +/ID [<28FEE2FFDDF79E7D236ADEBEDEB883FE> <28FEE2FFDDF79E7D236ADEBEDEB883FE>] +/Prev 400092 +>> +startxref +409807 +%%EOF diff --git a/xmlsecurity/qa/unit/pdfsigning/data/no-eof.pdf b/xmlsecurity/qa/unit/pdfsigning/data/no-eof.pdf Binary files differnew file mode 100644 index 0000000000..9ae7e23bb0 --- /dev/null +++ b/xmlsecurity/qa/unit/pdfsigning/data/no-eof.pdf diff --git a/xmlsecurity/qa/unit/pdfsigning/data/no.pdf b/xmlsecurity/qa/unit/pdfsigning/data/no.pdf Binary files differnew file mode 100644 index 0000000000..5d552421a4 --- /dev/null +++ b/xmlsecurity/qa/unit/pdfsigning/data/no.pdf diff --git a/xmlsecurity/qa/unit/pdfsigning/data/noeol.pdf b/xmlsecurity/qa/unit/pdfsigning/data/noeol.pdf Binary files differnew file mode 100644 index 0000000000..d870f896ca --- /dev/null +++ b/xmlsecurity/qa/unit/pdfsigning/data/noeol.pdf diff --git a/xmlsecurity/qa/unit/pdfsigning/data/partial-in-between.pdf b/xmlsecurity/qa/unit/pdfsigning/data/partial-in-between.pdf Binary files differnew file mode 100644 index 0000000000..211a111cb3 --- /dev/null +++ b/xmlsecurity/qa/unit/pdfsigning/data/partial-in-between.pdf diff --git a/xmlsecurity/qa/unit/pdfsigning/data/partial.pdf b/xmlsecurity/qa/unit/pdfsigning/data/partial.pdf Binary files differnew file mode 100644 index 0000000000..890f56217d --- /dev/null +++ b/xmlsecurity/qa/unit/pdfsigning/data/partial.pdf diff --git a/xmlsecurity/qa/unit/pdfsigning/data/pdf14adobe.pdf b/xmlsecurity/qa/unit/pdfsigning/data/pdf14adobe.pdf Binary files differnew file mode 100644 index 0000000000..58aadb492c --- /dev/null +++ b/xmlsecurity/qa/unit/pdfsigning/data/pdf14adobe.pdf diff --git a/xmlsecurity/qa/unit/pdfsigning/data/pdf14lowin.pdf b/xmlsecurity/qa/unit/pdfsigning/data/pdf14lowin.pdf Binary files differnew file mode 100644 index 0000000000..5270151ebc --- /dev/null +++ b/xmlsecurity/qa/unit/pdfsigning/data/pdf14lowin.pdf diff --git a/xmlsecurity/qa/unit/pdfsigning/data/pdf16adobe.pdf b/xmlsecurity/qa/unit/pdfsigning/data/pdf16adobe.pdf Binary files differnew file mode 100644 index 0000000000..ac1c5f37b9 --- /dev/null +++ b/xmlsecurity/qa/unit/pdfsigning/data/pdf16adobe.pdf diff --git a/xmlsecurity/qa/unit/pdfsigning/data/small.pdf b/xmlsecurity/qa/unit/pdfsigning/data/small.pdf Binary files differnew file mode 100644 index 0000000000..60675454f9 --- /dev/null +++ b/xmlsecurity/qa/unit/pdfsigning/data/small.pdf diff --git a/xmlsecurity/qa/unit/pdfsigning/data/tdf107149.pdf b/xmlsecurity/qa/unit/pdfsigning/data/tdf107149.pdf new file mode 100644 index 0000000000..db063f366a --- /dev/null +++ b/xmlsecurity/qa/unit/pdfsigning/data/tdf107149.pdf @@ -0,0 +1,97 @@ +%PDF-1.2 +%âãÏÓ +3 0 obj +<< +/Length 61 +>> +stream + BT + /F1 24 Tf + 1 0 0 1 260 254 Tm + (Hello Worl2)Tj + ET + +endstream +endobj xref +0 7 +0000000000 65535 f +0000000312 00000 n +0000000532 00000 n +0000000015 00000 n +0000000660 00000 n +0000000578 00000 n +0000000743 00000 n +trailer + +<< +/Root 6 0 R +/Size 7 +>> +1 0 obj +<< +/Resources 2 0 R +/Contents 3 0 R +/Parent 4 0 R +/Type /Page +/MediaBox [0 0 612 446] +>> +endobj +3 0 obj +<< +/Length 61 +>> +stream + BT + /F1 24 Tf + 1 0 0 1 260 254 Tm + (Hello World)Tj + ET + +endstream +endobj +2 0 obj +<< +/Font +<< +/F1 5 0 R +>> +>> +endobj +5 0 obj +<< +/Subtype /Type1 +/Name /F1 +/Type /Font +/BaseFont /Helvetica +>> +endobj +4 0 obj +<< +/Kids [1 0 R] +/Type /Pages +/MediaBox [0 0 612 446] +/Count 1 +>> +endobj +6 0 obj +<< +/Type /Catalog +/Pages 4 0 R +>> +endobj xref +0 7 +0000000000 65535 f +0000000015 00000 n +0000000235 00000 n +0000000121 00000 n +0000000363 00000 n +0000000281 00000 n +0000000446 00000 n +trailer + +<< +/Size 7 +>> +startxref +128 +%%EOF diff --git a/xmlsecurity/qa/unit/pdfsigning/data/tdf107782.pdf b/xmlsecurity/qa/unit/pdfsigning/data/tdf107782.pdf Binary files differnew file mode 100644 index 0000000000..086e18eedc --- /dev/null +++ b/xmlsecurity/qa/unit/pdfsigning/data/tdf107782.pdf diff --git a/xmlsecurity/qa/unit/pdfsigning/data/tdf114460.pdf b/xmlsecurity/qa/unit/pdfsigning/data/tdf114460.pdf Binary files differnew file mode 100644 index 0000000000..a736e5bb90 --- /dev/null +++ b/xmlsecurity/qa/unit/pdfsigning/data/tdf114460.pdf diff --git a/xmlsecurity/qa/unit/pdfsigning/data/tdf145312.pdf b/xmlsecurity/qa/unit/pdfsigning/data/tdf145312.pdf Binary files differnew file mode 100644 index 0000000000..6ff43f87e7 --- /dev/null +++ b/xmlsecurity/qa/unit/pdfsigning/data/tdf145312.pdf diff --git a/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx b/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx new file mode 100644 index 0000000000..0196a4707b --- /dev/null +++ b/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx @@ -0,0 +1,646 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <sal/config.h> + +#include <config_crypto.h> + +#if USE_CRYPTO_NSS +#include <secoid.h> +#endif + +#include <string_view> + +#include <com/sun/star/xml/crypto/SEInitializer.hpp> +#include <com/sun/star/security/DocumentSignatureInformation.hpp> + +#include <osl/file.hxx> +#include <sal/log.hxx> +#include <test/bootstrapfixture.hxx> +#include <unotest/macros_test.hxx> +#include <tools/datetime.hxx> +#include <unotools/streamwrap.hxx> +#include <unotools/ucbstreamhelper.hxx> +#include <vcl/filter/pdfdocument.hxx> +#include <vcl/filter/PDFiumLibrary.hxx> + +#include <documentsignaturemanager.hxx> +#include <pdfsignaturehelper.hxx> + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#endif + +using namespace com::sun::star; + +namespace +{ +constexpr OUString DATA_DIRECTORY = u"/xmlsecurity/qa/unit/pdfsigning/data/"_ustr; +} + +/// Testsuite for the PDF signing feature. +class PDFSigningTest : public test::BootstrapFixture, public unotest::MacrosTest +{ +protected: + /** + * Sign rInURL once and save the result as rOutURL, asserting that rInURL + * had nOriginalSignatureCount signatures. + */ + bool sign(const OUString& rInURL, const OUString& rOutURL, size_t nOriginalSignatureCount); + /** + * Read a pdf and make sure that it has the expected number of valid + * signatures. + */ + std::vector<SignatureInformation> verify(const OUString& rURL, size_t nCount); + +public: + PDFSigningTest(); + void setUp() override; + void tearDown() override; +}; + +PDFSigningTest::PDFSigningTest() {} + +void PDFSigningTest::setUp() +{ + test::BootstrapFixture::setUp(); + MacrosTest::setUpNssGpg(m_directories, "xmlsecurity_pdfsigning"); + + uno::Reference<xml::crypto::XSEInitializer> xSEInitializer + = xml::crypto::SEInitializer::create(mxComponentContext); + uno::Reference<xml::crypto::XXMLSecurityContext> xSecurityContext + = xSEInitializer->createSecurityContext(OUString()); +#if USE_CRYPTO_NSS +#ifdef NSS_USE_ALG_IN_ANY_SIGNATURE + // policy may disallow using SHA1 for signatures but unit test documents + // have such existing signatures (call this after createSecurityContext!) + NSS_SetAlgorithmPolicy(SEC_OID_SHA1, NSS_USE_ALG_IN_ANY_SIGNATURE, 0); +#endif +#endif +} + +void PDFSigningTest::tearDown() +{ + MacrosTest::tearDownNssGpg(); + test::BootstrapFixture::tearDown(); +} + +std::vector<SignatureInformation> PDFSigningTest::verify(const OUString& rURL, size_t nCount) +{ + uno::Reference<xml::crypto::XSEInitializer> xSEInitializer + = xml::crypto::SEInitializer::create(mxComponentContext); + uno::Reference<xml::crypto::XXMLSecurityContext> xSecurityContext + = xSEInitializer->createSecurityContext(OUString()); + std::vector<SignatureInformation> aRet; + + SvFileStream aStream(rURL, StreamMode::READ); + PDFSignatureHelper aHelper; + CPPUNIT_ASSERT(aHelper.ReadAndVerifySignatureSvStream(aStream)); + + std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get(); + if (pPDFium) + { + CPPUNIT_ASSERT_EQUAL(nCount, aHelper.GetSignatureInformations().size()); + } + for (size_t i = 0; i < aHelper.GetSignatureInformations().size(); ++i) + { + const SignatureInformation& rInfo = aHelper.GetSignatureInformations()[i]; + aRet.push_back(rInfo); + } + + return aRet; +} + +bool PDFSigningTest::sign(const OUString& rInURL, const OUString& rOutURL, + size_t nOriginalSignatureCount) +{ + // Make sure that input has nOriginalSignatureCount signatures. + uno::Reference<xml::crypto::XSEInitializer> xSEInitializer + = xml::crypto::SEInitializer::create(mxComponentContext); + uno::Reference<xml::crypto::XXMLSecurityContext> xSecurityContext + = xSEInitializer->createSecurityContext(OUString()); + vcl::filter::PDFDocument aDocument; + { + SvFileStream aStream(rInURL, StreamMode::READ); + CPPUNIT_ASSERT(aDocument.Read(aStream)); + std::vector<vcl::filter::PDFObjectElement*> aSignatures = aDocument.GetSignatureWidgets(); + CPPUNIT_ASSERT_EQUAL(nOriginalSignatureCount, aSignatures.size()); + } + + bool bSignSuccessful = false; + // Sign it and write out the result. + { + uno::Reference<xml::crypto::XSecurityEnvironment> xSecurityEnvironment + = xSecurityContext->getSecurityEnvironment(); + uno::Sequence<uno::Reference<security::XCertificate>> aCertificates + = xSecurityEnvironment->getPersonalCertificates(); + DateTime now(DateTime::SYSTEM); + for (auto& cert : asNonConstRange(aCertificates)) + { + css::util::DateTime aNotValidAfter = cert->getNotValidAfter(); + css::util::DateTime aNotValidBefore = cert->getNotValidBefore(); + + // Only try certificates that are already active and not expired + if ((now > aNotValidAfter) || (now < aNotValidBefore)) + { + SAL_WARN("xmlsecurity.qa", + "Skipping a certificate that is not yet valid or already not valid"); + } + else + { + bool bSignResult = aDocument.Sign(cert, "test", /*bAdES=*/true); +#ifdef _WIN32 + if (!bSignResult) + { + DWORD dwErr = GetLastError(); + if (HRESULT_FROM_WIN32(dwErr) == CRYPT_E_NO_KEY_PROPERTY) + { + SAL_WARN("xmlsecurity.qa", "Skipping a certificate without a private key"); + continue; // The certificate does not have a private key - not a valid certificate + } + } +#endif + CPPUNIT_ASSERT(bSignResult); + SvFileStream aOutStream(rOutURL, StreamMode::WRITE | StreamMode::TRUNC); + CPPUNIT_ASSERT(aDocument.Write(aOutStream)); + bSignSuccessful = true; + break; + } + } + } + + // This was nOriginalSignatureCount when PDFDocument::Sign() silently returned success, without doing anything. + if (bSignSuccessful) + verify(rOutURL, nOriginalSignatureCount + 1); + + // May return false if NSS failed to parse its own profile or Windows has no valid certificates installed. + return bSignSuccessful; +} + +/// Test adding a new signature to a previously unsigned file. +CPPUNIT_TEST_FIXTURE(PDFSigningTest, testPDFAdd) +{ + std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get(); + if (!pPDFium) + { + return; + } + + OUString aSourceDir = m_directories.getURLFromSrc(DATA_DIRECTORY); + OUString aInURL = aSourceDir + "no.pdf"; + OUString aTargetDir + = m_directories.getURLFromWorkdir(u"/CppunitTest/xmlsecurity_pdfsigning.test.user/"); + OUString aOutURL = aTargetDir + "add.pdf"; + bool bHadCertificates = sign(aInURL, aOutURL, 0); + + if (bHadCertificates) + { + // Assert that the SubFilter is not adbe.pkcs7.detached in the bAdES case. + std::vector<SignatureInformation> aInfos = verify(aOutURL, 1); + CPPUNIT_ASSERT(aInfos[0].bHasSigningCertificate); + // Make sure the timestamp is correct. + DateTime aDateTime(DateTime::SYSTEM); + // This was 0 (on Windows), as neither the /M key nor the PKCS#7 blob contained a timestamp. + CPPUNIT_ASSERT_EQUAL(aDateTime.GetYear(), aInfos[0].stDateTime.Year); + // Assert that the digest algorithm is not SHA-1 in the bAdES case. + CPPUNIT_ASSERT_EQUAL(xml::crypto::DigestID::SHA256, aInfos[0].nDigestID); + } +} + +/// Test signing a previously unsigned file twice. +CPPUNIT_TEST_FIXTURE(PDFSigningTest, testPDFAdd2) +{ + // Sign. + OUString aSourceDir = m_directories.getURLFromSrc(DATA_DIRECTORY); + OUString aInURL = aSourceDir + "no.pdf"; + OUString aTargetDir + = m_directories.getURLFromWorkdir(u"/CppunitTest/xmlsecurity_pdfsigning.test.user/"); + OUString aOutURL = aTargetDir + "add.pdf"; + bool bHadCertificates = sign(aInURL, aOutURL, 0); + + // Sign again. + aInURL = aTargetDir + "add.pdf"; + aOutURL = aTargetDir + "add2.pdf"; + // This failed with "second range end is not the end of the file" for the + // first signature. + if (bHadCertificates) + sign(aInURL, aOutURL, 1); +} + +/// Test removing a signature from a previously signed file. +CPPUNIT_TEST_FIXTURE(PDFSigningTest, testPDFRemove) +{ + std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get(); + if (!pPDFium) + { + return; + } + + // Make sure that good.pdf has 1 valid signature. + uno::Reference<xml::crypto::XSEInitializer> xSEInitializer + = xml::crypto::SEInitializer::create(mxComponentContext); + uno::Reference<xml::crypto::XXMLSecurityContext> xSecurityContext + = xSEInitializer->createSecurityContext(OUString()); + vcl::filter::PDFDocument aDocument; + OUString aSourceDir = m_directories.getURLFromSrc(DATA_DIRECTORY); + OUString aInURL = aSourceDir + "good.pdf"; + { + SvFileStream aStream(aInURL, StreamMode::READ); + PDFSignatureHelper aHelper; + aHelper.ReadAndVerifySignatureSvStream(aStream); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aHelper.GetSignatureInformations().size()); + } + + // Remove the signature and write out the result as remove.pdf. + OUString aTargetDir + = m_directories.getURLFromWorkdir(u"/CppunitTest/xmlsecurity_pdfsigning.test.user/"); + OUString aOutURL = aTargetDir + "remove.pdf"; + osl::File::copy(aInURL, aOutURL); + { + uno::Reference<io::XInputStream> xInputStream; + std::unique_ptr<SvStream> pStream + = utl::UcbStreamHelper::CreateStream(aOutURL, StreamMode::READWRITE); + uno::Reference<io::XStream> xStream(new utl::OStreamWrapper(std::move(pStream))); + xInputStream.set(xStream, uno::UNO_QUERY); + PDFSignatureHelper::RemoveSignature(xInputStream, 0); + } + + // Read back the pdf and make sure that it no longer has signatures. + // This failed when PDFDocument::RemoveSignature() silently returned + // success, without doing anything. + verify(aOutURL, 0); +} + +/// Test removing all signatures from a previously multi-signed file. +CPPUNIT_TEST_FIXTURE(PDFSigningTest, testPDFRemoveAll) +{ + std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get(); + if (!pPDFium) + { + return; + } + + // Make sure that good2.pdf has 2 valid signatures. Unlike in + // testPDFRemove(), here intentionally test DocumentSignatureManager and + // PDFSignatureHelper code as well. + uno::Reference<xml::crypto::XSEInitializer> xSEInitializer + = xml::crypto::SEInitializer::create(mxComponentContext); + uno::Reference<xml::crypto::XXMLSecurityContext> xSecurityContext + = xSEInitializer->createSecurityContext(OUString()); + + // Copy the test document to a temporary file, as it'll be modified. + OUString aTargetDir + = m_directories.getURLFromWorkdir(u"/CppunitTest/xmlsecurity_pdfsigning.test.user/"); + OUString aOutURL = aTargetDir + "remove-all.pdf"; + CPPUNIT_ASSERT_EQUAL( + osl::File::RC::E_None, + osl::File::copy(m_directories.getURLFromSrc(DATA_DIRECTORY) + "2good.pdf", aOutURL)); + // Load the test document as a storage and read its two signatures. + DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content); + std::unique_ptr<SvStream> pStream + = utl::UcbStreamHelper::CreateStream(aOutURL, StreamMode::READ | StreamMode::WRITE); + uno::Reference<io::XStream> xStream(new utl::OStreamWrapper(std::move(pStream))); + aManager.setSignatureStream(xStream); + aManager.read(/*bUseTempStream=*/false); + std::vector<SignatureInformation>& rInformations = aManager.getCurrentSignatureInformations(); + // This was 1 when NSS_CMSSignerInfo_GetSigningCertificate() failed, which + // means that we only used the locally imported certificates for + // verification, not the ones provided in the PDF signature data. + CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(2), rInformations.size()); + + // Request removal of the first signature, should imply removal of the + // second chained signature as well. + aManager.remove(0); + // This was 2, Manager didn't write anything to disk when removal succeeded + // (instead of doing that when removal failed). + // Then this was 1, when the chained signature wasn't removed. + CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(0), rInformations.size()); +} + +CPPUNIT_TEST_FIXTURE(PDFSigningTest, testTdf107782) +{ + uno::Reference<xml::crypto::XSEInitializer> xSEInitializer + = xml::crypto::SEInitializer::create(mxComponentContext); + uno::Reference<xml::crypto::XXMLSecurityContext> xSecurityContext + = xSEInitializer->createSecurityContext(OUString()); + + // Load the test document as a storage and read its signatures. + DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content); + OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "tdf107782.pdf"; + std::unique_ptr<SvStream> pStream + = utl::UcbStreamHelper::CreateStream(aURL, StreamMode::READ | StreamMode::WRITE); + uno::Reference<io::XStream> xStream(new utl::OStreamWrapper(std::move(pStream))); + aManager.setSignatureStream(xStream); + aManager.read(/*bUseTempStream=*/false); + CPPUNIT_ASSERT(aManager.hasPDFSignatureHelper()); + + // This failed with an std::bad_alloc exception on Windows. + aManager.getPDFSignatureHelper().GetDocumentSignatureInformations( + aManager.getSecurityEnvironment()); +} + +/// Test a PDF 1.4 document, signed by Adobe. +CPPUNIT_TEST_FIXTURE(PDFSigningTest, testPDF14Adobe) +{ + std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get(); + if (!pPDFium) + { + return; + } + + // Two signatures, first is SHA1, the second is SHA256. + // This was 0, as we failed to find the Annots key's value when it was a + // reference-to-array, not an array. + std::vector<SignatureInformation> aInfos + = verify(m_directories.getURLFromSrc(DATA_DIRECTORY) + "pdf14adobe.pdf", 2); + // This was 0, out-of-PKCS#7 signature date wasn't read. + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(2016), aInfos[1].stDateTime.Year); +} + +/// Test a PDF 1.6 document, signed by Adobe. +CPPUNIT_TEST_FIXTURE(PDFSigningTest, testPDF16Adobe) +{ + // Contains a cross-reference stream, object streams and a compressed + // stream with a predictor. And a valid signature. + // Found signatures was 0, as parsing failed due to lack of support for + // these features. + verify(m_directories.getURLFromSrc(DATA_DIRECTORY) + "pdf16adobe.pdf", 1); +} + +CPPUNIT_TEST_FIXTURE(PDFSigningTest, testTdf145312) +{ + // Without the fix in place, this test would have crashed + verify(m_directories.getURLFromSrc(DATA_DIRECTORY) + "tdf145312.pdf", 2); +} + +/// Test adding a signature to a PDF 1.6 document. +CPPUNIT_TEST_FIXTURE(PDFSigningTest, testPDF16Add) +{ + // Contains PDF 1.6 features, make sure we can add a signature using that + // markup correctly. + OUString aSourceDir = m_directories.getURLFromSrc(DATA_DIRECTORY); + OUString aInURL = aSourceDir + "pdf16adobe.pdf"; + OUString aTargetDir + = m_directories.getURLFromWorkdir(u"/CppunitTest/xmlsecurity_pdfsigning.test.user/"); + OUString aOutURL = aTargetDir + "add.pdf"; + // This failed: verification broke as incorrect xref stream was written as + // part of the new signature. + bool bHadCertificates = sign(aInURL, aOutURL, 1); + + // Sign again. + aInURL = aTargetDir + "add.pdf"; + aOutURL = aTargetDir + "add2.pdf"; + // This failed as non-compressed AcroForm wasn't handled. + if (bHadCertificates) + sign(aInURL, aOutURL, 2); +} + +/// Test a PDF 1.4 document, signed by LO on Windows. +CPPUNIT_TEST_FIXTURE(PDFSigningTest, testPDF14LOWin) +{ + // mscrypto used SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION as a digest + // algorithm when it meant SEC_OID_SHA1, make sure we tolerate that on all + // platforms. + // This failed, as NSS HASH_Create() didn't handle the sign algorithm. + verify(m_directories.getURLFromSrc(DATA_DIRECTORY) + "pdf14lowin.pdf", 1); +} + +/// Test a PAdES document, signed by LO on Linux. +CPPUNIT_TEST_FIXTURE(PDFSigningTest, testPDFPAdESGood) +{ + std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get(); + if (!pPDFium) + { + return; + } + + std::vector<SignatureInformation> aInfos + = verify(m_directories.getURLFromSrc(DATA_DIRECTORY) + "good-pades.pdf", 1); + CPPUNIT_ASSERT(aInfos[0].bHasSigningCertificate); +} + +/// Test a valid signature that does not cover the whole file. +CPPUNIT_TEST_FIXTURE(PDFSigningTest, testPartial) +{ + std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get(); + if (!pPDFium) + { + return; + } + + std::vector<SignatureInformation> aInfos + = verify(m_directories.getURLFromSrc(DATA_DIRECTORY) + "partial.pdf", 1); + CPPUNIT_ASSERT(!aInfos.empty()); + SignatureInformation& rInformation = aInfos[0]; + CPPUNIT_ASSERT(rInformation.bPartialDocumentSignature); +} + +CPPUNIT_TEST_FIXTURE(PDFSigningTest, testPartialInBetween) +{ + std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get(); + if (!pPDFium) + { + return; + } + + std::vector<SignatureInformation> aInfos + = verify(m_directories.getURLFromSrc(DATA_DIRECTORY) + "partial-in-between.pdf", 2); + CPPUNIT_ASSERT(!aInfos.empty()); + SignatureInformation& rInformation = aInfos[0]; + // Without the accompanying fix in place, this test would have failed, as unsigned incremental + // update between two signatures were not detected. + CPPUNIT_ASSERT(rInformation.bPartialDocumentSignature); +} + +CPPUNIT_TEST_FIXTURE(PDFSigningTest, testBadCertP1) +{ + std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get(); + if (!pPDFium) + { + return; + } + + std::vector<SignatureInformation> aInfos + = verify(m_directories.getURLFromSrc(DATA_DIRECTORY) + "bad-cert-p1.pdf", 1); + CPPUNIT_ASSERT(!aInfos.empty()); + SignatureInformation& rInformation = aInfos[0]; + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 0 (SecurityOperationStatus_UNKNOWN) + // - Actual : 1 (SecurityOperationStatus_OPERATION_SUCCEEDED) + // i.e. annotation after a P1 signature was not considered as a bad modification. + CPPUNIT_ASSERT_EQUAL(xml::crypto::SecurityOperationStatus::SecurityOperationStatus_UNKNOWN, + rInformation.nStatus); +} + +CPPUNIT_TEST_FIXTURE(PDFSigningTest, testBadCertP3Stamp) +{ + std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get(); + if (!pPDFium) + { + return; + } + + std::vector<SignatureInformation> aInfos + = verify(m_directories.getURLFromSrc(DATA_DIRECTORY) + "bad-cert-p3-stamp.pdf", 1); + CPPUNIT_ASSERT(!aInfos.empty()); + SignatureInformation& rInformation = aInfos[0]; + + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 0 (SecurityOperationStatus_UNKNOWN) + // - Actual : 1 (SecurityOperationStatus_OPERATION_SUCCEEDED) + // i.e. adding a stamp annotation was not considered as a bad modification. + CPPUNIT_ASSERT_EQUAL(xml::crypto::SecurityOperationStatus::SecurityOperationStatus_UNKNOWN, + rInformation.nStatus); +} + +/// Test writing a PAdES signature. +CPPUNIT_TEST_FIXTURE(PDFSigningTest, testSigningCertificateAttribute) +{ + std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get(); + if (!pPDFium) + { + return; + } + + // Create a new signature. + OUString aSourceDir = m_directories.getURLFromSrc(DATA_DIRECTORY); + OUString aInURL = aSourceDir + "no.pdf"; + OUString aTargetDir + = m_directories.getURLFromWorkdir(u"/CppunitTest/xmlsecurity_pdfsigning.test.user/"); + OUString aOutURL = aTargetDir + "signing-certificate-attribute.pdf"; + bool bHadCertificates = sign(aInURL, aOutURL, 0); + if (!bHadCertificates) + return; + + // Verify it. + std::vector<SignatureInformation> aInfos = verify(aOutURL, 1); + CPPUNIT_ASSERT(!aInfos.empty()); + SignatureInformation& rInformation = aInfos[0]; + // Assert that it has a signed signingCertificateV2 attribute. + CPPUNIT_ASSERT(rInformation.bHasSigningCertificate); +} + +/// Test that we accept files which are supposed to be good. +CPPUNIT_TEST_FIXTURE(PDFSigningTest, testGood) +{ + std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get(); + if (!pPDFium) + { + return; + } + + const std::initializer_list<std::u16string_view> aNames = { + // We failed to determine if this is good or bad. + u"good-non-detached.pdf", + // Boolean value for dictionary key caused read error. + u"dict-bool.pdf", + }; + + for (const auto& rName : aNames) + { + std::vector<SignatureInformation> aInfos + = verify(m_directories.getURLFromSrc(DATA_DIRECTORY) + rName, 1); + CPPUNIT_ASSERT(!aInfos.empty()); + SignatureInformation& rInformation = aInfos[0]; + CPPUNIT_ASSERT_EQUAL(int(xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED), + static_cast<int>(rInformation.nStatus)); + } +} + +/// Test that we don't crash / loop while tokenizing these files. +CPPUNIT_TEST_FIXTURE(PDFSigningTest, testTokenize) +{ + const std::initializer_list<std::u16string_view> aNames = { + // We looped on this broken input. + u"no-eof.pdf", + // ']' in a name token was mishandled. + u"name-bracket.pdf", + // %%EOF at the end wasn't followed by a newline. + u"noeol.pdf", + // File that's intentionally smaller than 1024 bytes. + u"small.pdf", + u"tdf107149.pdf", + // Nested parentheses were not handled. + u"tdf114460.pdf", + // Valgrind was unhappy about this. + u"forcepoint16.pdf", + }; + + for (const auto& rName : aNames) + { + SvFileStream aStream(m_directories.getURLFromSrc(DATA_DIRECTORY) + rName, StreamMode::READ); + vcl::filter::PDFDocument aDocument; + // Just make sure the tokenizer finishes without an error, don't look at the signature. + CPPUNIT_ASSERT(aDocument.Read(aStream)); + + if (rName == u"tdf107149.pdf") + // This failed, page list was empty. + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aDocument.GetPages().size()); + } +} + +/// Test handling of unknown SubFilter values. +CPPUNIT_TEST_FIXTURE(PDFSigningTest, testUnknownSubFilter) +{ + std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get(); + if (!pPDFium) + { + return; + } + + // Tokenize the bugdoc. + uno::Reference<xml::crypto::XSEInitializer> xSEInitializer + = xml::crypto::SEInitializer::create(mxComponentContext); + uno::Reference<xml::crypto::XXMLSecurityContext> xSecurityContext + = xSEInitializer->createSecurityContext(OUString()); + std::unique_ptr<SvStream> pStream = utl::UcbStreamHelper::CreateStream( + m_directories.getURLFromSrc(DATA_DIRECTORY) + "cr-comment.pdf", StreamMode::STD_READ); + uno::Reference<io::XStream> xStream(new utl::OStreamWrapper(std::move(pStream))); + DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content); + aManager.setSignatureStream(xStream); + aManager.read(/*bUseTempStream=*/false); + + // Make sure we find both signatures, even if the second has unknown SubFilter. + std::vector<SignatureInformation>& rInformations = aManager.getCurrentSignatureInformations(); + CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(2), rInformations.size()); +} + +CPPUNIT_TEST_FIXTURE(PDFSigningTest, testGoodCustomMagic) +{ + std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get(); + if (!pPDFium) + { + return; + } + + // Tokenize the bugdoc. + uno::Reference<xml::crypto::XSEInitializer> xSEInitializer + = xml::crypto::SEInitializer::create(mxComponentContext); + uno::Reference<xml::crypto::XXMLSecurityContext> xSecurityContext + = xSEInitializer->createSecurityContext(OUString()); + std::unique_ptr<SvStream> pStream = utl::UcbStreamHelper::CreateStream( + m_directories.getURLFromSrc(DATA_DIRECTORY) + "good-custom-magic.pdf", + StreamMode::STD_READ); + uno::Reference<io::XStream> xStream(new utl::OStreamWrapper(std::move(pStream))); + DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content); + aManager.setSignatureStream(xStream); + aManager.read(/*bUseTempStream=*/false); + + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 1 (SecurityOperationStatus_OPERATION_SUCCEEDED) + // - Actual : 0 (SecurityOperationStatus_UNKNOWN) + // i.e. no signatures were found due to a custom non-comment magic after the header. + std::vector<SignatureInformation>& rInformations = aManager.getCurrentSignatureInformations(); + CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(1), rInformations.size()); +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/qa/unit/signing/data/02_doc_macros_signed_by_attacker_manipulated.odt b/xmlsecurity/qa/unit/signing/data/02_doc_macros_signed_by_attacker_manipulated.odt Binary files differnew file mode 100644 index 0000000000..d63e4b6b7b --- /dev/null +++ b/xmlsecurity/qa/unit/signing/data/02_doc_macros_signed_by_attacker_manipulated.odt diff --git a/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_attacker_manipulated.odt b/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_attacker_manipulated.odt Binary files differnew file mode 100644 index 0000000000..0190abb00f --- /dev/null +++ b/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_attacker_manipulated.odt diff --git a/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_attacker_manipulated2.odt b/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_attacker_manipulated2.odt Binary files differnew file mode 100644 index 0000000000..f4b4198f94 --- /dev/null +++ b/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_attacker_manipulated2.odt diff --git a/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_attacker_manipulated_triple.odt b/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_attacker_manipulated_triple.odt Binary files differnew file mode 100644 index 0000000000..558bdee47e --- /dev/null +++ b/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_attacker_manipulated_triple.odt diff --git a/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_trusted_person_manipulated.odt b/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_trusted_person_manipulated.odt Binary files differnew file mode 100644 index 0000000000..4136b32e56 --- /dev/null +++ b/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_trusted_person_manipulated.odt diff --git a/xmlsecurity/qa/unit/signing/data/add-visible-signature.pdf b/xmlsecurity/qa/unit/signing/data/add-visible-signature.pdf Binary files differnew file mode 100644 index 0000000000..8dedb6998b --- /dev/null +++ b/xmlsecurity/qa/unit/signing/data/add-visible-signature.pdf diff --git a/xmlsecurity/qa/unit/signing/data/bad.docx b/xmlsecurity/qa/unit/signing/data/bad.docx Binary files differnew file mode 100644 index 0000000000..86d0eda49b --- /dev/null +++ b/xmlsecurity/qa/unit/signing/data/bad.docx diff --git a/xmlsecurity/qa/unit/signing/data/bad.odt b/xmlsecurity/qa/unit/signing/data/bad.odt Binary files differnew file mode 100644 index 0000000000..75c39d5d83 --- /dev/null +++ b/xmlsecurity/qa/unit/signing/data/bad.odt diff --git a/xmlsecurity/qa/unit/signing/data/bad.pdf b/xmlsecurity/qa/unit/signing/data/bad.pdf Binary files differnew file mode 100644 index 0000000000..f3f056f2bf --- /dev/null +++ b/xmlsecurity/qa/unit/signing/data/bad.pdf diff --git a/xmlsecurity/qa/unit/signing/data/badDsigGPG.odt b/xmlsecurity/qa/unit/signing/data/badDsigGPG.odt Binary files differnew file mode 100644 index 0000000000..032ddbf7a2 --- /dev/null +++ b/xmlsecurity/qa/unit/signing/data/badDsigGPG.odt diff --git a/xmlsecurity/qa/unit/signing/data/badStreamGPG.odt b/xmlsecurity/qa/unit/signing/data/badStreamGPG.odt Binary files differnew file mode 100644 index 0000000000..252ea26b00 --- /dev/null +++ b/xmlsecurity/qa/unit/signing/data/badStreamGPG.odt diff --git a/xmlsecurity/qa/unit/signing/data/encryptedGPG.odt b/xmlsecurity/qa/unit/signing/data/encryptedGPG.odt Binary files differnew file mode 100644 index 0000000000..9490a0ce58 --- /dev/null +++ b/xmlsecurity/qa/unit/signing/data/encryptedGPG.odt diff --git a/xmlsecurity/qa/unit/signing/data/encryptedGPG_odf13.odt b/xmlsecurity/qa/unit/signing/data/encryptedGPG_odf13.odt Binary files differnew file mode 100644 index 0000000000..e738c2f6df --- /dev/null +++ b/xmlsecurity/qa/unit/signing/data/encryptedGPG_odf13.odt diff --git a/xmlsecurity/qa/unit/signing/data/good-xades.odt b/xmlsecurity/qa/unit/signing/data/good-xades.odt Binary files differnew file mode 100644 index 0000000000..4f96d4bd89 --- /dev/null +++ b/xmlsecurity/qa/unit/signing/data/good-xades.odt diff --git a/xmlsecurity/qa/unit/signing/data/good.odt b/xmlsecurity/qa/unit/signing/data/good.odt Binary files differnew file mode 100644 index 0000000000..8c6019d0ac --- /dev/null +++ b/xmlsecurity/qa/unit/signing/data/good.odt diff --git a/xmlsecurity/qa/unit/signing/data/good.pdf b/xmlsecurity/qa/unit/signing/data/good.pdf Binary files differnew file mode 100644 index 0000000000..4a506c1e11 --- /dev/null +++ b/xmlsecurity/qa/unit/signing/data/good.pdf diff --git a/xmlsecurity/qa/unit/signing/data/goodGPG.odt b/xmlsecurity/qa/unit/signing/data/goodGPG.odt Binary files differnew file mode 100644 index 0000000000..a02af30169 --- /dev/null +++ b/xmlsecurity/qa/unit/signing/data/goodGPG.odt diff --git a/xmlsecurity/qa/unit/signing/data/hide-and-replace-shadow-file-signed-2.pdf b/xmlsecurity/qa/unit/signing/data/hide-and-replace-shadow-file-signed-2.pdf Binary files differnew file mode 100644 index 0000000000..f2b1a71096 --- /dev/null +++ b/xmlsecurity/qa/unit/signing/data/hide-and-replace-shadow-file-signed-2.pdf diff --git a/xmlsecurity/qa/unit/signing/data/multi.docx b/xmlsecurity/qa/unit/signing/data/multi.docx Binary files differnew file mode 100644 index 0000000000..aba69508e2 --- /dev/null +++ b/xmlsecurity/qa/unit/signing/data/multi.docx diff --git a/xmlsecurity/qa/unit/signing/data/no.odt b/xmlsecurity/qa/unit/signing/data/no.odt Binary files differnew file mode 100644 index 0000000000..22cf7683a0 --- /dev/null +++ b/xmlsecurity/qa/unit/signing/data/no.odt diff --git a/xmlsecurity/qa/unit/signing/data/no.pdf b/xmlsecurity/qa/unit/signing/data/no.pdf Binary files differnew file mode 100644 index 0000000000..5d552421a4 --- /dev/null +++ b/xmlsecurity/qa/unit/signing/data/no.pdf diff --git a/xmlsecurity/qa/unit/signing/data/notype-xades.odt b/xmlsecurity/qa/unit/signing/data/notype-xades.odt Binary files differnew file mode 100644 index 0000000000..4f96d4bd89 --- /dev/null +++ b/xmlsecurity/qa/unit/signing/data/notype-xades.odt diff --git a/xmlsecurity/qa/unit/signing/data/odb_signed_macros.odb b/xmlsecurity/qa/unit/signing/data/odb_signed_macros.odb Binary files differnew file mode 100644 index 0000000000..3e90f45145 --- /dev/null +++ b/xmlsecurity/qa/unit/signing/data/odb_signed_macros.odb diff --git a/xmlsecurity/qa/unit/signing/data/partial.docx b/xmlsecurity/qa/unit/signing/data/partial.docx Binary files differnew file mode 100644 index 0000000000..3d6ca46851 --- /dev/null +++ b/xmlsecurity/qa/unit/signing/data/partial.docx diff --git a/xmlsecurity/qa/unit/signing/data/signatureline.docx b/xmlsecurity/qa/unit/signing/data/signatureline.docx Binary files differnew file mode 100644 index 0000000000..e1dae66989 --- /dev/null +++ b/xmlsecurity/qa/unit/signing/data/signatureline.docx diff --git a/xmlsecurity/qa/unit/signing/data/signatureline.odt b/xmlsecurity/qa/unit/signing/data/signatureline.odt Binary files differnew file mode 100644 index 0000000000..d3a3e4671e --- /dev/null +++ b/xmlsecurity/qa/unit/signing/data/signatureline.odt diff --git a/xmlsecurity/qa/unit/signing/data/signed_with_x509certificate_chain.odt b/xmlsecurity/qa/unit/signing/data/signed_with_x509certificate_chain.odt Binary files differnew file mode 100644 index 0000000000..5e519dd8b7 --- /dev/null +++ b/xmlsecurity/qa/unit/signing/data/signed_with_x509certificate_chain.odt diff --git a/xmlsecurity/qa/unit/signing/data/tdf42316.ott b/xmlsecurity/qa/unit/signing/data/tdf42316.ott Binary files differnew file mode 100644 index 0000000000..95162a6271 --- /dev/null +++ b/xmlsecurity/qa/unit/signing/data/tdf42316.ott diff --git a/xmlsecurity/qa/unit/signing/data/tdf42316_odt12.ott b/xmlsecurity/qa/unit/signing/data/tdf42316_odt12.ott Binary files differnew file mode 100644 index 0000000000..ecff487091 --- /dev/null +++ b/xmlsecurity/qa/unit/signing/data/tdf42316_odt12.ott diff --git a/xmlsecurity/qa/unit/signing/data/tdf96097.ods b/xmlsecurity/qa/unit/signing/data/tdf96097.ods Binary files differnew file mode 100644 index 0000000000..58d1b2c771 --- /dev/null +++ b/xmlsecurity/qa/unit/signing/data/tdf96097.ods diff --git a/xmlsecurity/qa/unit/signing/data/tdf96097.odt b/xmlsecurity/qa/unit/signing/data/tdf96097.odt Binary files differnew file mode 100644 index 0000000000..f0356513c3 --- /dev/null +++ b/xmlsecurity/qa/unit/signing/data/tdf96097.odt diff --git a/xmlsecurity/qa/unit/signing/data/untrustedGoodGPG.odt b/xmlsecurity/qa/unit/signing/data/untrustedGoodGPG.odt Binary files differnew file mode 100644 index 0000000000..e1b36d5441 --- /dev/null +++ b/xmlsecurity/qa/unit/signing/data/untrustedGoodGPG.odt diff --git a/xmlsecurity/qa/unit/signing/signing.cxx b/xmlsecurity/qa/unit/signing/signing.cxx new file mode 100644 index 0000000000..9f449d26d6 --- /dev/null +++ b/xmlsecurity/qa/unit/signing/signing.cxx @@ -0,0 +1,1473 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <config_crypto.h> +#include <config_features.h> +#include <config_gpgme.h> + +#include <sal/config.h> + +#if USE_CRYPTO_NSS +#include <secoid.h> +#endif + +#include <test/unoapixml_test.hxx> + +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/embed/XStorage.hpp> +#include <com/sun/star/embed/XTransactedObject.hpp> +#include <com/sun/star/frame/XStorable.hpp> +#include <com/sun/star/security/CertificateValidity.hpp> +#include <com/sun/star/security/DocumentDigitalSignatures.hpp> +#include <com/sun/star/security/XDocumentDigitalSignatures.hpp> +#include <com/sun/star/xml/crypto/SEInitializer.hpp> +#include <com/sun/star/drawing/XDrawPagesSupplier.hpp> +#include <com/sun/star/view/XSelectionSupplier.hpp> + +#include <comphelper/processfactory.hxx> +#include <comphelper/propertysequence.hxx> +#include <unotools/tempfile.hxx> +#include <unotools/ucbstreamhelper.hxx> +#include <comphelper/storagehelper.hxx> +#include <sfx2/sfxbasemodel.hxx> +#include <sfx2/objsh.hxx> +#include <osl/thread.hxx> +#include <comphelper/ofopxmlhelper.hxx> +#include <unotools/streamwrap.hxx> + +#include <documentsignaturehelper.hxx> +#include <xmlsignaturehelper.hxx> +#include <documentsignaturemanager.hxx> +#include <biginteger.hxx> +#include <certificate.hxx> +#include <xsecctl.hxx> +#include <sfx2/docfile.hxx> +#include <sfx2/docfilt.hxx> +#include <officecfg/Office/Common.hxx> +#include <comphelper/configuration.hxx> +#include <svx/signaturelinehelper.hxx> +#include <sfx2/viewsh.hxx> +#include <comphelper/propertyvalue.hxx> +#include <vcl/filter/PDFiumLibrary.hxx> +#include <vcl/scheduler.hxx> + +using namespace com::sun::star; + +/// Testsuite for the document signing feature. +class SigningTest : public UnoApiXmlTest +{ +protected: + uno::Reference<xml::crypto::XSEInitializer> mxSEInitializer; + uno::Reference<xml::crypto::XXMLSecurityContext> mxSecurityContext; + +public: + SigningTest(); + virtual void setUp() override; + virtual void tearDown() override; + void registerNamespaces(xmlXPathContextPtr& pXmlXpathCtx) override; + +protected: + uno::Reference<security::XCertificate> + getCertificate(DocumentSignatureManager& rSignatureManager, + svl::crypto::SignatureMethodAlgorithm eAlgo); +#if HAVE_FEATURE_GPGVERIFY + SfxObjectShell* assertDocument(const ::CppUnit::SourceLine aSrcLine, + const OUString& rFilterName, const SignatureState nDocSign, + const SignatureState nMacroSign, const OUString& sVersion); +#endif +}; + +SigningTest::SigningTest() + : UnoApiXmlTest("/xmlsecurity/qa/unit/signing/data/") +{ +} + +void SigningTest::setUp() +{ + UnoApiXmlTest::setUp(); + + MacrosTest::setUpNssGpg(m_directories, "xmlsecurity_signing"); + + // Initialize crypto after setting up the environment variables. + mxSEInitializer = xml::crypto::SEInitializer::create(mxComponentContext); + mxSecurityContext = mxSEInitializer->createSecurityContext(OUString()); +#if USE_CRYPTO_NSS +#ifdef NSS_USE_ALG_IN_ANY_SIGNATURE + // policy may disallow using SHA1 for signatures but unit test documents + // have such existing signatures (call this after createSecurityContext!) + NSS_SetAlgorithmPolicy(SEC_OID_SHA1, NSS_USE_ALG_IN_ANY_SIGNATURE, 0); +#endif +#endif +} + +void SigningTest::tearDown() +{ + MacrosTest::tearDownNssGpg(); + + UnoApiXmlTest::tearDown(); +} + +uno::Reference<security::XCertificate> +SigningTest::getCertificate(DocumentSignatureManager& rSignatureManager, + svl::crypto::SignatureMethodAlgorithm eAlgo) +{ + uno::Reference<xml::crypto::XSecurityEnvironment> xSecurityEnvironment + = rSignatureManager.getSecurityEnvironment(); + const uno::Sequence<uno::Reference<security::XCertificate>> aCertificates + = xSecurityEnvironment->getPersonalCertificates(); + + for (const auto& xCertificate : aCertificates) + { + auto pCertificate = dynamic_cast<xmlsecurity::Certificate*>(xCertificate.get()); + CPPUNIT_ASSERT(pCertificate); + if (pCertificate->getSignatureMethodAlgorithm() == eAlgo + && IsValid(xCertificate, xSecurityEnvironment)) + return xCertificate; + } + return uno::Reference<security::XCertificate>(); +} + +CPPUNIT_TEST_FIXTURE(SigningTest, testDescription) +{ + // Create an empty document and store it to a tempfile, finally load it as a storage. + load("private:factory/swriter"); + + save("writer8"); + + DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content); + CPPUNIT_ASSERT(aManager.init()); + uno::Reference<embed::XStorage> xStorage + = comphelper::OStorageHelper::GetStorageOfFormatFromURL( + ZIP_STORAGE_FORMAT_STRING, maTempFile.GetURL(), embed::ElementModes::READWRITE); + CPPUNIT_ASSERT(xStorage.is()); + aManager.setStore(xStorage); + aManager.getSignatureHelper().SetStorage(xStorage, u"1.2"); + + // Then add a signature document. + uno::Reference<security::XCertificate> xCertificate + = getCertificate(aManager, svl::crypto::SignatureMethodAlgorithm::RSA); + if (!xCertificate.is()) + return; + OUString aDescription("SigningTest::testDescription"); + sal_Int32 nSecurityId; + aManager.add(xCertificate, mxSecurityContext, aDescription, nSecurityId, false); + + // Read back the signature and make sure that the description survives the roundtrip. + aManager.read(/*bUseTempStream=*/true); + std::vector<SignatureInformation>& rInformations = aManager.getCurrentSignatureInformations(); + CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(1), rInformations.size()); + CPPUNIT_ASSERT_EQUAL(aDescription, rInformations[0].ouDescription); +} + +CPPUNIT_TEST_FIXTURE(SigningTest, testECDSA) +{ + // Create an empty document and store it to a tempfile, finally load it as a storage. + load("private:factory/swriter"); + + save("writer8"); + + DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content); + CPPUNIT_ASSERT(aManager.init()); + uno::Reference<embed::XStorage> xStorage + = comphelper::OStorageHelper::GetStorageOfFormatFromURL( + ZIP_STORAGE_FORMAT_STRING, maTempFile.GetURL(), embed::ElementModes::READWRITE); + CPPUNIT_ASSERT(xStorage.is()); + aManager.setStore(xStorage); + aManager.getSignatureHelper().SetStorage(xStorage, u"1.2"); + + // Then add a signature. + uno::Reference<security::XCertificate> xCertificate + = getCertificate(aManager, svl::crypto::SignatureMethodAlgorithm::ECDSA); + if (!xCertificate.is()) + return; + sal_Int32 nSecurityId; + aManager.add(xCertificate, mxSecurityContext, "", nSecurityId, false); + + // Read back the signature and make sure that it's valid. + aManager.read(/*bUseTempStream=*/true); + std::vector<SignatureInformation>& rInformations = aManager.getCurrentSignatureInformations(); + CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(1), rInformations.size()); + // This was SecurityOperationStatus_UNKNOWN, signing with an ECDSA key was + // broken. + CPPUNIT_ASSERT_EQUAL(css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED, + rInformations[0].nStatus); +} + +CPPUNIT_TEST_FIXTURE(SigningTest, testECDSAOOXML) +{ + // Create an empty document and store it to a tempfile, finally load it as a storage. + load("private:factory/swriter"); + + save("MS Word 2007 XML"); + + DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content); + CPPUNIT_ASSERT(aManager.init()); + uno::Reference<embed::XStorage> xStorage + = comphelper::OStorageHelper::GetStorageOfFormatFromURL( + ZIP_STORAGE_FORMAT_STRING, maTempFile.GetURL(), embed::ElementModes::READWRITE); + CPPUNIT_ASSERT(xStorage.is()); + aManager.setStore(xStorage); + aManager.getSignatureHelper().SetStorage(xStorage, u"1.2"); + + // Then add a document signature. + uno::Reference<security::XCertificate> xCertificate + = getCertificate(aManager, svl::crypto::SignatureMethodAlgorithm::ECDSA); + if (!xCertificate.is()) + return; + sal_Int32 nSecurityId; + aManager.add(xCertificate, mxSecurityContext, "", nSecurityId, + /*bAdESCompliant=*/false); + + // Read back the signature and make sure that it's valid. + aManager.read(/*bUseTempStream=*/true); + std::vector<SignatureInformation>& rInformations = aManager.getCurrentSignatureInformations(); + CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(1), rInformations.size()); + // This was SecurityOperationStatus_UNKNOWN, signing with an ECDSA key was + // broken. + CPPUNIT_ASSERT_EQUAL(css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED, + rInformations[0].nStatus); +} + +CPPUNIT_TEST_FIXTURE(SigningTest, testECDSAPDF) +{ + // Create an empty document and store it to a tempfile, finally load it as + // a stream. + load("private:factory/swriter"); + + save("writer_pdf_Export"); + + DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content); + CPPUNIT_ASSERT(aManager.init()); + std::unique_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream( + maTempFile.GetURL(), StreamMode::READ | StreamMode::WRITE)); + uno::Reference<io::XStream> xStream(new utl::OStreamWrapper(*pStream)); + CPPUNIT_ASSERT(xStream.is()); + aManager.setSignatureStream(xStream); + + // Then add a document signature. + uno::Reference<security::XCertificate> xCertificate + = getCertificate(aManager, svl::crypto::SignatureMethodAlgorithm::ECDSA); + if (!xCertificate.is()) + return; + sal_Int32 nSecurityId; + aManager.add(xCertificate, mxSecurityContext, "", nSecurityId, + /*bAdESCompliant=*/true); + + // Read back the signature and make sure that it's valid. + aManager.read(/*bUseTempStream=*/false); + std::vector<SignatureInformation>& rInformations = aManager.getCurrentSignatureInformations(); + std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get(); + if (!pPDFium) + { + return; + } + + CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(1), rInformations.size()); + // This was SecurityOperationStatus_UNKNOWN, signing with an ECDSA key was + // broken. + CPPUNIT_ASSERT_EQUAL(css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED, + rInformations[0].nStatus); +} + +CPPUNIT_TEST_FIXTURE(SigningTest, testOOXMLDescription) +{ + // Create an empty document and store it to a tempfile, finally load it as a storage. + load("private:factory/swriter"); + + save("MS Word 2007 XML"); + + DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content); + CPPUNIT_ASSERT(aManager.init()); + uno::Reference<embed::XStorage> xStorage + = comphelper::OStorageHelper::GetStorageOfFormatFromURL( + ZIP_STORAGE_FORMAT_STRING, maTempFile.GetURL(), embed::ElementModes::READWRITE); + CPPUNIT_ASSERT(xStorage.is()); + aManager.setStore(xStorage); + aManager.getSignatureHelper().SetStorage(xStorage, u"1.2"); + + // Then add a document signature. + uno::Reference<security::XCertificate> xCertificate + = getCertificate(aManager, svl::crypto::SignatureMethodAlgorithm::RSA); + if (!xCertificate.is()) + return; + OUString aDescription("SigningTest::testDescription"); + sal_Int32 nSecurityId; + aManager.add(xCertificate, mxSecurityContext, aDescription, nSecurityId, false); + + // Read back the signature and make sure that the description survives the roundtrip. + aManager.read(/*bUseTempStream=*/true); + std::vector<SignatureInformation>& rInformations = aManager.getCurrentSignatureInformations(); + CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(1), rInformations.size()); + CPPUNIT_ASSERT_EQUAL(aDescription, rInformations[0].ouDescription); +} + +/// Test appending a new signature next to an existing one. +CPPUNIT_TEST_FIXTURE(SigningTest, testOOXMLAppend) +{ + // Copy the test document to a temporary file, as it'll be modified. + createTempCopy(u"partial.docx"); + // Load the test document as a storage and read its single signature. + DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content); + CPPUNIT_ASSERT(aManager.init()); + uno::Reference<embed::XStorage> xStorage + = comphelper::OStorageHelper::GetStorageOfFormatFromURL( + ZIP_STORAGE_FORMAT_STRING, maTempFile.GetURL(), embed::ElementModes::READWRITE); + CPPUNIT_ASSERT(xStorage.is()); + aManager.setStore(xStorage); + aManager.getSignatureHelper().SetStorage(xStorage, u"1.2"); + aManager.read(/*bUseTempStream=*/false); + std::vector<SignatureInformation>& rInformations = aManager.getCurrentSignatureInformations(); + CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(1), rInformations.size()); + + // Then add a second document signature. + uno::Reference<security::XCertificate> xCertificate + = getCertificate(aManager, svl::crypto::SignatureMethodAlgorithm::RSA); + if (!xCertificate.is()) + return; + sal_Int32 nSecurityId; + aManager.add(xCertificate, mxSecurityContext, OUString(), nSecurityId, false); + + // Read back the signatures and make sure that we have the expected amount. + aManager.read(/*bUseTempStream=*/true); + // This was 1: the original signature was lost. + CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(2), rInformations.size()); +} + +/// Test removing a signature from existing ones. +CPPUNIT_TEST_FIXTURE(SigningTest, testOOXMLRemove) +{ + // Load the test document as a storage and read its signatures: purpose1 and purpose2. + DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content); + CPPUNIT_ASSERT(aManager.init()); + createTempCopy(u"multi.docx"); + uno::Reference<embed::XStorage> xStorage + = comphelper::OStorageHelper::GetStorageOfFormatFromURL( + ZIP_STORAGE_FORMAT_STRING, maTempFile.GetURL(), embed::ElementModes::READWRITE); + CPPUNIT_ASSERT(xStorage.is()); + aManager.setStore(xStorage); + aManager.getSignatureHelper().SetStorage(xStorage, u"1.2"); + aManager.read(/*bUseTempStream=*/false); + std::vector<SignatureInformation>& rInformations = aManager.getCurrentSignatureInformations(); + CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(2), rInformations.size()); + + // Then remove the last added signature. + uno::Reference<security::XCertificate> xCertificate + = getCertificate(aManager, svl::crypto::SignatureMethodAlgorithm::RSA); + if (!xCertificate.is()) + return; + aManager.remove(0); + + // Read back the signatures and make sure that only purpose1 is left. + aManager.read(/*bUseTempStream=*/true); + CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(1), rInformations.size()); + CPPUNIT_ASSERT_EQUAL(OUString("purpose1"), rInformations[0].ouDescription); +} + +/// Test removing all signatures from a document. +CPPUNIT_TEST_FIXTURE(SigningTest, testOOXMLRemoveAll) +{ + // Copy the test document to a temporary file, as it'll be modified. + createTempCopy(u"partial.docx"); + // Load the test document as a storage and read its single signature. + DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content); + CPPUNIT_ASSERT(aManager.init()); + uno::Reference<embed::XStorage> xStorage + = comphelper::OStorageHelper::GetStorageOfFormatFromURL( + ZIP_STORAGE_FORMAT_STRING, maTempFile.GetURL(), embed::ElementModes::READWRITE); + CPPUNIT_ASSERT(xStorage.is()); + aManager.setStore(xStorage); + aManager.getSignatureHelper().SetStorage(xStorage, u"1.2"); + aManager.read(/*bUseTempStream=*/false); + std::vector<SignatureInformation>& rInformations = aManager.getCurrentSignatureInformations(); + CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(1), rInformations.size()); + + // Then remove the only signature in the document. + uno::Reference<security::XCertificate> xCertificate + = getCertificate(aManager, svl::crypto::SignatureMethodAlgorithm::RSA); + if (!xCertificate.is()) + return; + aManager.remove(0); + aManager.read(/*bUseTempStream=*/true); + aManager.write(/*bXAdESCompliantIfODF=*/false); + + // Make sure that the signature count is zero and the whole signature storage is removed completely. + CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(0), rInformations.size()); + CPPUNIT_ASSERT(!xStorage->hasByName("_xmlsignatures")); + + // And that content types no longer contains signature types. + uno::Reference<io::XStream> xStream + = xStorage->openStreamElement("[Content_Types].xml", embed::ElementModes::READWRITE); + uno::Reference<io::XInputStream> xInputStream = xStream->getInputStream(); + uno::Sequence<uno::Sequence<beans::StringPair>> aContentTypeInfo + = comphelper::OFOPXMLHelper::ReadContentTypeSequence(xInputStream, mxComponentContext); + const uno::Sequence<beans::StringPair>& rOverrides = aContentTypeInfo[1]; + CPPUNIT_ASSERT( + std::none_of(rOverrides.begin(), rOverrides.end(), [](const beans::StringPair& rPair) { + return rPair.First.startsWith("/_xmlsignatures/sig"); + })); +} + +/// Test a typical ODF where all streams are signed. +CPPUNIT_TEST_FIXTURE(SigningTest, testODFGood) +{ + loadFromFile(u"good.odt"); + SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + // We expect NOTVALIDATED in case the root CA is not imported on the system, and OK otherwise, so accept both. + SignatureState nActual = pObjectShell->GetDocumentSignatureState(); + CPPUNIT_ASSERT_MESSAGE( + (OString::number(o3tl::to_underlying(nActual)).getStr()), + (nActual == SignatureState::NOTVALIDATED || nActual == SignatureState::OK)); +} + +/// Test a typical broken ODF signature where one stream is corrupted. +CPPUNIT_TEST_FIXTURE(SigningTest, testODFBroken) +{ + loadFromFile(u"bad.odt"); + SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + CPPUNIT_ASSERT_EQUAL(static_cast<int>(SignatureState::BROKEN), + static_cast<int>(pObjectShell->GetDocumentSignatureState())); +} + +// Document has a signature stream, but no actual signatures. +CPPUNIT_TEST_FIXTURE(SigningTest, testODFNo) +{ + loadFromFile(u"no.odt"); + SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + CPPUNIT_ASSERT_EQUAL(static_cast<int>(SignatureState::NOSIGNATURES), + static_cast<int>(pObjectShell->GetDocumentSignatureState())); +} + +// document has one signed timestamp and one unsigned timestamp +CPPUNIT_TEST_FIXTURE(SigningTest, testODFUnsignedTimestamp) +{ + loadFromFile(u"02_doc_signed_by_trusted_person_manipulated.odt"); + SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + SignatureState nActual = pObjectShell->GetDocumentSignatureState(); + CPPUNIT_ASSERT_MESSAGE( + (OString::number(o3tl::to_underlying(nActual)).getStr()), + (nActual == SignatureState::NOTVALIDATED || nActual == SignatureState::OK)); + uno::Sequence<security::DocumentSignatureInformation> const infos( + pObjectShell->GetDocumentSignatureInformation(false)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), infos.getLength()); + // was: 66666666 + CPPUNIT_ASSERT_EQUAL(sal_Int32(20210126), infos[0].SignatureDate); + // was: 0 + CPPUNIT_ASSERT_EQUAL(sal_Int32(18183742), infos[0].SignatureTime); +} + +// FIXME: For some unknown reason, this test fails on tml's Mac unless it is the only or the first +// test that is run in this CppunitTest program. When using our patched bundled cppunit library (as +// we obviously always do on macOS), the CPPUNIT_TEST_FIXTUREs are run in lexicographical order so +// use a name for this test that makes it the first one to run. + +CPPUNIT_TEST_FIXTURE(SigningTest, aaa_testODFX509CertificateChain) +{ + loadFromFile(u"signed_with_x509certificate_chain.odt"); + SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + SignatureState nActual = pObjectShell->GetDocumentSignatureState(); + CPPUNIT_ASSERT_MESSAGE( + (OString::number(o3tl::to_underlying(nActual)).getStr()), + (nActual == SignatureState::NOTVALIDATED || nActual == SignatureState::OK)); + uno::Sequence<security::DocumentSignatureInformation> const infos( + pObjectShell->GetDocumentSignatureInformation(false)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), infos.getLength()); + // check that the signing certificate was picked, not one of the 2 CA ones + CPPUNIT_ASSERT_EQUAL(security::CertificateValidity::VALID, infos[0].CertificateStatus); + CPPUNIT_ASSERT(infos[0].Signer.is()); + CPPUNIT_ASSERT_EQUAL( + OUString("CN=Xmlsecurity RSA Test example Alice,O=Xmlsecurity RSA Test,ST=England,C=UK"), + // CryptoAPI puts a space after comma, NSS does not... + infos[0].Signer->getSubjectName().replaceAll(", ", ",")); +} + +CPPUNIT_TEST_FIXTURE(SigningTest, testODFDoubleX509Data) +{ + loadFromFile(u"02_doc_signed_by_attacker_manipulated.odt"); + SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + SignatureState nActual = pObjectShell->GetDocumentSignatureState(); + CPPUNIT_ASSERT_MESSAGE( + (OString::number(o3tl::to_underlying(nActual)).getStr()), + (nActual == SignatureState::NOTVALIDATED || nActual == SignatureState::OK)); + uno::Sequence<security::DocumentSignatureInformation> const infos( + pObjectShell->GetDocumentSignatureInformation(false)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), infos.getLength()); + // the signature in this manipulated document is technically valid but we can't tell who signed + // it, so make sure no misleading info is shown to the user + CPPUNIT_ASSERT_EQUAL(security::CertificateValidity::INVALID, infos[0].CertificateStatus); + CPPUNIT_ASSERT(!infos[0].Signer.is()); +} + +CPPUNIT_TEST_FIXTURE(SigningTest, testODFTripleX509Data) +{ + loadFromFile(u"02_doc_signed_by_attacker_manipulated_triple.odt"); + SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + SignatureState nActual = pObjectShell->GetDocumentSignatureState(); + // here, libxmlsec will pick the 1st X509Data but signing key is the 2nd + CPPUNIT_ASSERT_EQUAL_MESSAGE((OString::number(o3tl::to_underlying(nActual)).getStr()), + SignatureState::BROKEN, nActual); + uno::Sequence<security::DocumentSignatureInformation> const infos( + pObjectShell->GetDocumentSignatureInformation(false)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), infos.getLength()); + // the signature in this manipulated document is technically valid but we can't tell who signed + // it, so make sure no misleading info is shown to the user + CPPUNIT_ASSERT_EQUAL(security::CertificateValidity::INVALID, infos[0].CertificateStatus); + CPPUNIT_ASSERT(!infos[0].Signer.is()); +} + +CPPUNIT_TEST_FIXTURE(SigningTest, testODFMacroDoubleX509Data) +{ + loadFromFile(u"02_doc_macros_signed_by_attacker_manipulated.odt"); + SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + SignatureState nActual = pObjectShell->GetScriptingSignatureState(); + CPPUNIT_ASSERT_MESSAGE( + (OString::number(o3tl::to_underlying(nActual)).getStr()), + (nActual == SignatureState::NOTVALIDATED || nActual == SignatureState::OK)); + uno::Sequence<security::DocumentSignatureInformation> const infos( + pObjectShell->GetDocumentSignatureInformation(true)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), infos.getLength()); + // the signature in this manipulated document is technically valid but we can't tell who signed + // it, so make sure no misleading info is shown to the user + CPPUNIT_ASSERT_EQUAL(security::CertificateValidity::INVALID, infos[0].CertificateStatus); + CPPUNIT_ASSERT(!infos[0].Signer.is()); +} + +CPPUNIT_TEST_FIXTURE(SigningTest, testODFDoubleX509Certificate) +{ + loadFromFile(u"02_doc_signed_by_attacker_manipulated2.odt"); + SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + SignatureState nActual = pObjectShell->GetDocumentSignatureState(); + bool const nTemp((nActual == SignatureState::NOTVALIDATED + || nActual == SignatureState::OK +#if defined(_WIN32) + // oddly BCryptVerifySignature returns STATUS_INVALID_SIGNATURE + // while the same succeeds with NSS _SGN_VerifyPKCS1DigestInfo + || nActual == SignatureState::BROKEN +#endif + )); + CPPUNIT_ASSERT_MESSAGE((OString::number(o3tl::to_underlying(nActual)).getStr()), nTemp); + uno::Sequence<security::DocumentSignatureInformation> const infos( + pObjectShell->GetDocumentSignatureInformation(false)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), infos.getLength()); + // the signature in this manipulated document is technically valid but we can't tell who signed + // it, so make sure no misleading info is shown to the user + CPPUNIT_ASSERT_EQUAL(security::CertificateValidity::INVALID, infos[0].CertificateStatus); + CPPUNIT_ASSERT(!infos[0].Signer.is()); +} + +CPPUNIT_TEST_FIXTURE(SigningTest, testDNCompatibility) +{ + OUString constexpr msDN(u"CN=\"\"\"ABC\"\".\", O=\"Enterprise \"\"ABC\"\"\""_ustr); + OUString constexpr nssDN(u"CN=\\\"ABC\\\".,O=Enterprise \\\"ABC\\\""_ustr); + // this is just the status quo, possibly either NSS or CryptoAPI might change + CPPUNIT_ASSERT(!xmlsecurity::EqualDistinguishedNames(msDN, nssDN, xmlsecurity::NOCOMPAT)); + CPPUNIT_ASSERT(!xmlsecurity::EqualDistinguishedNames(nssDN, msDN, xmlsecurity::NOCOMPAT)); + // with compat flag it should work, with the string one 2nd and the native one 1st +#ifdef _WIN32 + CPPUNIT_ASSERT(xmlsecurity::EqualDistinguishedNames(msDN, nssDN, xmlsecurity::COMPAT_2ND)); +#else + CPPUNIT_ASSERT(xmlsecurity::EqualDistinguishedNames(nssDN, msDN, xmlsecurity::COMPAT_2ND)); +#endif +} + +/// Test a typical OOXML where a number of (but not all) streams are signed. +CPPUNIT_TEST_FIXTURE(SigningTest, testOOXMLPartial) +{ + loadFromFile(u"partial.docx"); + SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + // This was SignatureState::BROKEN due to missing RelationshipTransform and SHA-256 support. + // We expect NOTVALIDATED_PARTIAL_OK in case the root CA is not imported on the system, and PARTIAL_OK otherwise, so accept both. + // But reject NOTVALIDATED, hiding incompleteness is not OK. + SignatureState nActual = pObjectShell->GetDocumentSignatureState(); + CPPUNIT_ASSERT_MESSAGE((OString::number(o3tl::to_underlying(nActual)).getStr()), + (nActual == SignatureState::NOTVALIDATED_PARTIAL_OK + || nActual == SignatureState::PARTIAL_OK)); +} + +/// Test a typical broken OOXML signature where one stream is corrupted. +CPPUNIT_TEST_FIXTURE(SigningTest, testOOXMLBroken) +{ + loadFromFile(u"bad.docx"); + SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + // This was SignatureState::NOTVALIDATED/PARTIAL_OK as we did not validate manifest references. + CPPUNIT_ASSERT_EQUAL(static_cast<int>(SignatureState::BROKEN), + static_cast<int>(pObjectShell->GetDocumentSignatureState())); +} + +#if HAVE_FEATURE_PDFIMPORT + +/// Test a typical PDF where the signature is good. +CPPUNIT_TEST_FIXTURE(SigningTest, testPDFGood) +{ + loadFromFile(u"good.pdf"); + SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + // We expect NOTVALIDATED in case the root CA is not imported on the system, and OK otherwise, so accept both. + SignatureState nActual = pObjectShell->GetDocumentSignatureState(); + std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get(); + if (!pPDFium) + { + return; + } + + CPPUNIT_ASSERT_MESSAGE( + (OString::number(o3tl::to_underlying(nActual)).getStr()), + (nActual == SignatureState::NOTVALIDATED || nActual == SignatureState::OK)); +} + +/// Test a typical PDF where the signature is bad. +CPPUNIT_TEST_FIXTURE(SigningTest, testPDFBad) +{ + loadFromFile(u"bad.pdf"); + SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get(); + if (!pPDFium) + { + return; + } + + CPPUNIT_ASSERT_EQUAL(static_cast<int>(SignatureState::BROKEN), + static_cast<int>(pObjectShell->GetDocumentSignatureState())); +} + +CPPUNIT_TEST_FIXTURE(SigningTest, testPDFHideAndReplace) +{ + loadFromFile(u"hide-and-replace-shadow-file-signed-2.pdf"); + SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get(); + if (!pPDFium) + { + return; + } + + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 2 (BROKEN) + // - Actual : 6 (NOTVALIDATED_PARTIAL_OK) + // i.e. a non-commenting update after a signature was not marked as invalid. + CPPUNIT_ASSERT_EQUAL(static_cast<int>(SignatureState::BROKEN), + static_cast<int>(pObjectShell->GetDocumentSignatureState())); +} + +/// Test a typical PDF which is not signed. +CPPUNIT_TEST_FIXTURE(SigningTest, testPDFNo) +{ + loadFromFile(u"no.pdf"); + SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + CPPUNIT_ASSERT_EQUAL(static_cast<int>(SignatureState::NOSIGNATURES), + static_cast<int>(pObjectShell->GetDocumentSignatureState())); +} + +#endif + +CPPUNIT_TEST_FIXTURE(SigningTest, testPDFAddVisibleSignature) +{ + std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get(); + if (!pPDFium) + { + return; + } + + // FIXME: the DPI check should be removed when either (1) the test is fixed to work with + // non-default DPI; or (2) unit tests on Windows are made to use svp VCL plugin. + if (!IsDefaultDPI()) + return; + // Given: copy the test document to a temporary file, as it'll be modified. + createTempCopy(u"add-visible-signature.pdf"); + + // Open it. + uno::Sequence<beans::PropertyValue> aArgs = { comphelper::makePropertyValue("ReadOnly", true) }; + mxComponent + = loadFromDesktop(maTempFile.GetURL(), "com.sun.star.drawing.DrawingDocument", aArgs); + SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + + // Add a signature line. + uno::Reference<lang::XMultiServiceFactory> xFactory(mxComponent, uno::UNO_QUERY); + uno::Reference<drawing::XShape> xShape( + xFactory->createInstance("com.sun.star.drawing.GraphicObjectShape"), uno::UNO_QUERY); + xShape->setPosition(awt::Point(1000, 15000)); + xShape->setSize(awt::Size(10000, 10000)); + uno::Reference<drawing::XDrawPagesSupplier> xSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference<drawing::XDrawPages> xDrawPages = xSupplier->getDrawPages(); + uno::Reference<drawing::XDrawPage> xDrawPage(xDrawPages->getByIndex(0), uno::UNO_QUERY); + xDrawPage->add(xShape); + + // Select it and assign a certificate. + uno::Reference<view::XSelectionSupplier> xSelectionSupplier(pBaseModel->getCurrentController(), + uno::UNO_QUERY); + xSelectionSupplier->select(uno::Any(xShape)); + uno::Sequence<uno::Reference<security::XCertificate>> aCertificates + = mxSecurityContext->getSecurityEnvironment()->getPersonalCertificates(); + if (!aCertificates.hasElements()) + { + return; + } + SdrView* pView = SfxViewShell::Current()->GetDrawView(); + svx::SignatureLineHelper::setShapeCertificate(pView, aCertificates[0]); + + // the document is modified now, but Sign function can't show SaveAs dialog + // in unit test, so just clear the modified + pObjectShell->SetModified(false); + + // When: do the actual signing. + pObjectShell->SignDocumentContentUsingCertificate(aCertificates[0]); + + // Then: count the # of shapes on the signature widget/annotation. + std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parsePDFExport(); + + std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(/*nIndex=*/0); + CPPUNIT_ASSERT_EQUAL(1, pPdfPage->getAnnotationCount()); + std::unique_ptr<vcl::pdf::PDFiumAnnotation> pAnnot = pPdfPage->getAnnotation(/*nIndex=*/0); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 4 + // - Actual : 0 + // i.e. the signature was there, but it was empty / not visible. + CPPUNIT_ASSERT_EQUAL(4, pAnnot->getObjectCount()); +} + +CPPUNIT_TEST_FIXTURE(SigningTest, test96097Calc) +{ + loadFromFile(u"tdf96097.ods"); + SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get()); + CPPUNIT_ASSERT_MESSAGE("Failed to access document base model", pBaseModel); + + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT_MESSAGE("Failed to access document shell", pObjectShell); + + SignatureState nActual = pObjectShell->GetScriptingSignatureState(); + CPPUNIT_ASSERT_MESSAGE((OString::number(o3tl::to_underlying(nActual)).getStr()), + (nActual == SignatureState::OK || nActual == SignatureState::NOTVALIDATED + || nActual == SignatureState::INVALID)); + + uno::Reference<frame::XStorable> xDocStorable(mxComponent, uno::UNO_QUERY_THROW); + + // Save a copy + uno::Sequence<beans::PropertyValue> descSaveACopy(comphelper::InitPropertySequence( + { { "SaveACopy", uno::Any(true) }, { "FilterName", uno::Any(OUString("calc8")) } })); + xDocStorable->storeToURL(maTempFile.GetURL(), descSaveACopy); + + // FIXME: Error: element "document-signatures" is missing "version" attribute + skipValidation(); + + // Save As + save("calc8"); +} + +CPPUNIT_TEST_FIXTURE(SigningTest, test96097Doc) +{ + loadFromFile(u"tdf96097.odt"); + SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + + SignatureState nActual = pObjectShell->GetScriptingSignatureState(); + CPPUNIT_ASSERT_MESSAGE((OString::number(o3tl::to_underlying(nActual)).getStr()), + (nActual == SignatureState::OK || nActual == SignatureState::NOTVALIDATED + || nActual == SignatureState::INVALID)); + + uno::Reference<frame::XStorable> xDocStorable(mxComponent, uno::UNO_QUERY_THROW); + + // Save a copy + uno::Sequence<beans::PropertyValue> descSaveACopy(comphelper::InitPropertySequence( + { { "SaveACopy", uno::Any(true) }, { "FilterName", uno::Any(OUString("writer8")) } })); + xDocStorable->storeToURL(maTempFile.GetURL(), descSaveACopy); + + // FIXME: Error: element "document-signatures" is missing "version" attribute + skipValidation(); + + // Save As + save("writer8"); +} + +CPPUNIT_TEST_FIXTURE(SigningTest, testXAdESNotype) +{ + // Create a working copy. + createTempCopy(u"notype-xades.odt"); + + // Read existing signature. + DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content); + CPPUNIT_ASSERT(aManager.init()); + uno::Reference<embed::XStorage> xStorage + = comphelper::OStorageHelper::GetStorageOfFormatFromURL( + ZIP_STORAGE_FORMAT_STRING, maTempFile.GetURL(), embed::ElementModes::READWRITE); + CPPUNIT_ASSERT(xStorage.is()); + aManager.setStore(xStorage); + aManager.getSignatureHelper().SetStorage(xStorage, u"1.2"); + aManager.read(/*bUseTempStream=*/false); + + // Create a new signature. + uno::Reference<security::XCertificate> xCertificate + = getCertificate(aManager, svl::crypto::SignatureMethodAlgorithm::RSA); + if (!xCertificate.is()) + return; + sal_Int32 nSecurityId; + aManager.add(xCertificate, mxSecurityContext, /*rDescription=*/OUString(), nSecurityId, + /*bAdESCompliant=*/true); + + // Write to storage. + aManager.read(/*bUseTempStream=*/true); + aManager.write(/*bXAdESCompliantIfODF=*/true); + uno::Reference<embed::XTransactedObject> xTransactedObject(xStorage, uno::UNO_QUERY); + xTransactedObject->commit(); + + // Parse the resulting XML. + uno::Reference<embed::XStorage> xMetaInf + = xStorage->openStorageElement("META-INF", embed::ElementModes::READ); + uno::Reference<io::XInputStream> xInputStream( + xMetaInf->openStreamElement("documentsignatures.xml", embed::ElementModes::READ), + uno::UNO_QUERY); + std::unique_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(xInputStream, true)); + xmlDocUniquePtr pXmlDoc = parseXmlStream(pStream.get()); + + // Without the accompanying fix in place, this test would have failed with "unexpected 'Type' + // attribute", i.e. the signature without such an attribute was not preserved correctly. + assertXPathNoAttribute(pXmlDoc, + "/odfds:document-signatures/dsig:Signature[1]/dsig:SignedInfo/" + "dsig:Reference[starts-with(@URI, '#idSignedProperties')]"_ostr, + "Type"_ostr); + + // New signature always has the Type attribute. + assertXPath(pXmlDoc, + "/odfds:document-signatures/dsig:Signature[2]/dsig:SignedInfo/" + "dsig:Reference[starts-with(@URI, '#idSignedProperties')]"_ostr, + "Type"_ostr, "http://uri.etsi.org/01903#SignedProperties"); +} + +/// Creates a XAdES signature from scratch. +CPPUNIT_TEST_FIXTURE(SigningTest, testXAdES) +{ + // Create an empty document, store it to a tempfile and load it as a storage. + load("private:factory/swriter"); + + save("writer8"); + + DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content); + CPPUNIT_ASSERT(aManager.init()); + uno::Reference<embed::XStorage> xStorage + = comphelper::OStorageHelper::GetStorageOfFormatFromURL( + ZIP_STORAGE_FORMAT_STRING, maTempFile.GetURL(), embed::ElementModes::READWRITE); + CPPUNIT_ASSERT(xStorage.is()); + aManager.setStore(xStorage); + aManager.getSignatureHelper().SetStorage(xStorage, u"1.2"); + + // Create a signature. + uno::Reference<security::XCertificate> xCertificate + = getCertificate(aManager, svl::crypto::SignatureMethodAlgorithm::RSA); + if (!xCertificate.is()) + return; + sal_Int32 nSecurityId; + aManager.add(xCertificate, mxSecurityContext, /*rDescription=*/OUString(), nSecurityId, + /*bAdESCompliant=*/true); + + // Write to storage. + aManager.read(/*bUseTempStream=*/true); + aManager.write(/*bXAdESCompliantIfODF=*/true); + uno::Reference<embed::XTransactedObject> xTransactedObject(xStorage, uno::UNO_QUERY); + xTransactedObject->commit(); + + // Parse the resulting XML. + uno::Reference<embed::XStorage> xMetaInf + = xStorage->openStorageElement("META-INF", embed::ElementModes::READ); + uno::Reference<io::XInputStream> xInputStream( + xMetaInf->openStreamElement("documentsignatures.xml", embed::ElementModes::READ), + uno::UNO_QUERY); + std::unique_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(xInputStream, true)); + xmlDocUniquePtr pXmlDoc = parseXmlStream(pStream.get()); + + // Assert that the digest algorithm is SHA-256 in the bAdESCompliant case, not SHA-1. + assertXPath(pXmlDoc, + "/odfds:document-signatures/dsig:Signature/dsig:SignedInfo/" + "dsig:Reference[@URI='content.xml']/dsig:DigestMethod"_ostr, + "Algorithm"_ostr, ALGO_XMLDSIGSHA256); + + // Assert that the digest of the signing certificate is included. + assertXPath(pXmlDoc, "//xd:CertDigest"_ostr, 1); + + // Assert that the Type attribute is set on all URI's that start with #idSignedProperties + assertXPath(pXmlDoc, "//dsig:Reference[starts-with(@URI, '#idSignedProperties')]"_ostr, + "Type"_ostr, "http://uri.etsi.org/01903#SignedProperties"); +} + +CPPUNIT_TEST_FIXTURE(SigningTest, testSigningMultipleTimes_ODT) +{ + load("private:factory/swriter"); + + save("writer8"); + { + DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content); + CPPUNIT_ASSERT(aManager.init()); + uno::Reference<embed::XStorage> xStorage + = comphelper::OStorageHelper::GetStorageOfFormatFromURL( + ZIP_STORAGE_FORMAT_STRING, maTempFile.GetURL(), embed::ElementModes::READWRITE); + CPPUNIT_ASSERT(xStorage.is()); + aManager.setStore(xStorage); + aManager.getSignatureHelper().SetStorage(xStorage, u"1.2"); + + // Create a signature. + uno::Reference<security::XCertificate> xCertificate + = getCertificate(aManager, svl::crypto::SignatureMethodAlgorithm::RSA); + + if (!xCertificate.is()) + return; + sal_Int32 nSecurityId; + aManager.add(xCertificate, mxSecurityContext, /*rDescription=*/OUString(), nSecurityId, + /*bAdESCompliant=*/true); + + // Read back the signature and make sure that it's valid. + aManager.read(/*bUseTempStream=*/true); + { + std::vector<SignatureInformation>& rInformations + = aManager.getCurrentSignatureInformations(); + CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(1), rInformations.size()); + CPPUNIT_ASSERT_EQUAL(css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED, + rInformations[0].nStatus); + } + + aManager.add(xCertificate, mxSecurityContext, /*rDescription=*/OUString(), nSecurityId, + /*bAdESCompliant=*/true); + aManager.read(/*bUseTempStream=*/true); + { + std::vector<SignatureInformation>& rInformations + = aManager.getCurrentSignatureInformations(); + CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(2), rInformations.size()); + CPPUNIT_ASSERT_EQUAL(css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED, + rInformations[1].nStatus); + } + + aManager.add(xCertificate, mxSecurityContext, /*rDescription=*/OUString(), nSecurityId, + /*bAdESCompliant=*/true); + aManager.read(/*bUseTempStream=*/true); + { + std::vector<SignatureInformation>& rInformations + = aManager.getCurrentSignatureInformations(); + CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(3), rInformations.size()); + CPPUNIT_ASSERT_EQUAL(css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED, + rInformations[2].nStatus); + } + + aManager.write(/*bXAdESCompliantIfODF=*/true); + uno::Reference<embed::XTransactedObject> xTransactedObject(xStorage, uno::UNO_QUERY); + xTransactedObject->commit(); + } + + Scheduler::ProcessEventsToIdle(); + + load(maTempFile.GetURL()); + + SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + CPPUNIT_ASSERT_EQUAL(SignatureState::OK, pObjectShell->GetDocumentSignatureState()); +} + +CPPUNIT_TEST_FIXTURE(SigningTest, testSigningMultipleTimes_OOXML) +{ + load("private:factory/swriter"); + + save("MS Word 2007 XML"); + { + DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content); + CPPUNIT_ASSERT(aManager.init()); + uno::Reference<embed::XStorage> xStorage + = comphelper::OStorageHelper::GetStorageOfFormatFromURL( + ZIP_STORAGE_FORMAT_STRING, maTempFile.GetURL(), embed::ElementModes::READWRITE); + CPPUNIT_ASSERT(xStorage.is()); + aManager.setStore(xStorage); + aManager.getSignatureHelper().SetStorage(xStorage, u"1.2"); + + // Create a signature. + uno::Reference<security::XCertificate> xCertificate + = getCertificate(aManager, svl::crypto::SignatureMethodAlgorithm::ECDSA); + if (!xCertificate.is()) + return; + + sal_Int32 nSecurityId; + aManager.add(xCertificate, mxSecurityContext, "", nSecurityId, /*bAdESCompliant=*/false); + aManager.read(/*bUseTempStream=*/true); + { + std::vector<SignatureInformation>& rInformations + = aManager.getCurrentSignatureInformations(); + CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(1), rInformations.size()); + CPPUNIT_ASSERT_EQUAL(css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED, + rInformations[0].nStatus); + } + + aManager.add(xCertificate, mxSecurityContext, "", nSecurityId, /*bAdESCompliant=*/false); + aManager.read(/*bUseTempStream=*/true); + { + std::vector<SignatureInformation>& rInformations + = aManager.getCurrentSignatureInformations(); + CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(2), rInformations.size()); + CPPUNIT_ASSERT_EQUAL(css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED, + rInformations[1].nStatus); + } + + aManager.add(xCertificate, mxSecurityContext, "", nSecurityId, /*bAdESCompliant=*/false); + aManager.read(/*bUseTempStream=*/true); + { + std::vector<SignatureInformation>& rInformations + = aManager.getCurrentSignatureInformations(); + CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(3), rInformations.size()); + CPPUNIT_ASSERT_EQUAL(css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED, + rInformations[2].nStatus); + } + + aManager.write(/*bXAdESCompliantIfODF=*/true); + uno::Reference<embed::XTransactedObject> xTransactedObject(xStorage, uno::UNO_QUERY); + xTransactedObject->commit(); + } + + Scheduler::ProcessEventsToIdle(); + + load(maTempFile.GetURL()); + + SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + CPPUNIT_ASSERT_EQUAL(SignatureState::PARTIAL_OK, pObjectShell->GetDocumentSignatureState()); +} + +/// Works with an existing good XAdES signature. +CPPUNIT_TEST_FIXTURE(SigningTest, testXAdESGood) +{ + loadFromFile(u"good-xades.odt"); + SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + // We expect NOTVALIDATED in case the root CA is not imported on the system, and OK otherwise, so accept both. + SignatureState nActual = pObjectShell->GetDocumentSignatureState(); + CPPUNIT_ASSERT_MESSAGE( + (OString::number(o3tl::to_underlying(nActual)).getStr()), + (nActual == SignatureState::NOTVALIDATED || nActual == SignatureState::OK)); +} + +/// Test importing of signature line +CPPUNIT_TEST_FIXTURE(SigningTest, testSignatureLineOOXML) +{ + // Given: A document (docx) with a signature line and a valid signature + uno::Reference<security::XDocumentDigitalSignatures> xSignatures( + security::DocumentDigitalSignatures::createDefault( + comphelper::getProcessComponentContext())); + + uno::Reference<embed::XStorage> xStorage + = comphelper::OStorageHelper::GetStorageOfFormatFromURL( + ZIP_STORAGE_FORMAT_STRING, createFileURL(u"signatureline.docx"), + embed::ElementModes::READ); + CPPUNIT_ASSERT(xStorage.is()); + + uno::Sequence<security::DocumentSignatureInformation> xSignatureInfo + = xSignatures->verifyScriptingContentSignatures(xStorage, + uno::Reference<io::XInputStream>()); + + CPPUNIT_ASSERT(xSignatureInfo.getLength()); + + // The signature should have a valid signature, and signature line with two valid images + CPPUNIT_ASSERT(xSignatureInfo[0].SignatureIsValid); + CPPUNIT_ASSERT_EQUAL(OUString("{DEE0514B-13E8-4674-A831-46E3CDB18BB4}"), + xSignatureInfo[0].SignatureLineId); + CPPUNIT_ASSERT(xSignatureInfo[0].ValidSignatureLineImage.is()); + CPPUNIT_ASSERT(xSignatureInfo[0].InvalidSignatureLineImage.is()); +} + +CPPUNIT_TEST_FIXTURE(SigningTest, testSignatureLineODF) +{ + loadFromFile(u"signatureline.odt"); + SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + + uno::Sequence<security::DocumentSignatureInformation> xSignatureInfo + = pObjectShell->GetDocumentSignatureInformation(false); + + CPPUNIT_ASSERT(xSignatureInfo.getLength()); + + CPPUNIT_ASSERT(xSignatureInfo[0].SignatureIsValid); + CPPUNIT_ASSERT_EQUAL(OUString("{41CF56EE-331B-4125-97D8-2F5669DD3AAC}"), + xSignatureInfo[0].SignatureLineId); + CPPUNIT_ASSERT(xSignatureInfo[0].ValidSignatureLineImage.is()); + CPPUNIT_ASSERT(xSignatureInfo[0].InvalidSignatureLineImage.is()); +} + +#if HAVE_FEATURE_GPGVERIFY +/// Test a typical ODF where all streams are GPG-signed. +CPPUNIT_TEST_FIXTURE(SigningTest, testODFGoodGPG) +{ + loadFromFile(u"goodGPG.odt"); + SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + // Our local gpg config fully trusts the signing cert, so in + // contrast to the X509 test we can fail on NOTVALIDATED here + SignatureState nActual = pObjectShell->GetDocumentSignatureState(); + CPPUNIT_ASSERT_EQUAL_MESSAGE((OString::number(o3tl::to_underlying(nActual)).getStr()), + SignatureState::OK, nActual); +} + +/// Test a typical ODF where all streams are GPG-signed, but we don't trust the signature. +CPPUNIT_TEST_FIXTURE(SigningTest, testODFUntrustedGoodGPG) +{ + loadFromFile(u"untrustedGoodGPG.odt"); + SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + // Our local gpg config does _not_ trust the signing cert, so in + // contrast to the X509 test we can fail everything but + // NOTVALIDATED here + SignatureState nActual = pObjectShell->GetDocumentSignatureState(); + CPPUNIT_ASSERT_EQUAL_MESSAGE((OString::number(o3tl::to_underlying(nActual)).getStr()), + SignatureState::NOTVALIDATED, nActual); +} + +/// Test a typical broken ODF signature where one stream is corrupted. +CPPUNIT_TEST_FIXTURE(SigningTest, testODFBrokenStreamGPG) +{ + loadFromFile(u"badStreamGPG.odt"); + SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + CPPUNIT_ASSERT_EQUAL(static_cast<int>(SignatureState::BROKEN), + static_cast<int>(pObjectShell->GetDocumentSignatureState())); +} + +/// Test a typical broken ODF signature where the XML dsig hash is corrupted. +CPPUNIT_TEST_FIXTURE(SigningTest, testODFBrokenDsigGPG) +{ + loadFromFile(u"badDsigGPG.odt"); + SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + CPPUNIT_ASSERT_EQUAL(static_cast<int>(SignatureState::BROKEN), + static_cast<int>(pObjectShell->GetDocumentSignatureState())); +} + +#if HAVE_GPGCONF_SOCKETDIR + +/// Test loading an encrypted ODF document +CPPUNIT_TEST_FIXTURE(SigningTest, testODFEncryptedGPG) +{ + // ODF1.2 + loext flavour + loadFromFile(u"encryptedGPG.odt"); + SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + + // ODF1.3 flavour + loadFromFile(u"encryptedGPG_odf13.odt"); + pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + + // export and import again + saveAndReload("writer8"); + + pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); +} + +#endif + +SfxObjectShell* SigningTest::assertDocument(const ::CppUnit::SourceLine aSrcLine, + const OUString& rFilterName, + const SignatureState nDocSign, + const SignatureState nMacroSign, + const OUString& sVersion) +{ + std::string sPos = aSrcLine.fileName() + ":" + OString::number(aSrcLine.lineNumber()).getStr(); + + SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get()); + CPPUNIT_ASSERT_MESSAGE(sPos, pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT_MESSAGE(sPos, pObjectShell); + + CPPUNIT_ASSERT_EQUAL_MESSAGE(sPos, rFilterName, + pObjectShell->GetMedium()->GetFilter()->GetFilterName()); + SignatureState nActual = pObjectShell->GetDocumentSignatureState(); + CPPUNIT_ASSERT_EQUAL_MESSAGE(sPos, nDocSign, nActual); + nActual = pObjectShell->GetScriptingSignatureState(); + CPPUNIT_ASSERT_EQUAL_MESSAGE(sPos, nMacroSign, nActual); + + OUString aODFVersion; + uno::Reference<beans::XPropertySet> xPropSet(pObjectShell->GetStorage(), uno::UNO_QUERY_THROW); + xPropSet->getPropertyValue("Version") >>= aODFVersion; + CPPUNIT_ASSERT_EQUAL(sVersion, aODFVersion); + + return pObjectShell; +} + +/// Test if a macro signature from a OTT 1.2 template is preserved for ODT 1.2 +CPPUNIT_TEST_FIXTURE(SigningTest, testPreserveMacroTemplateSignature12_ODF) +{ + const OUString aFormats[] = { "writer8", "writer8_template" }; + + for (OUString const& sFormat : aFormats) + { + const OUString aURL(createFileURL(u"tdf42316_odt12.ott")); + const OUString sLoadMessage = "loading failed: " + aURL; + + // load the template as-is to validate signatures + mxComponent = loadFromDesktop( + aURL, OUString(), + comphelper::InitPropertySequence({ { "AsTemplate", uno::Any(false) } })); + + // we are a template, and have a valid document and macro signature + assertDocument(CPPUNIT_SOURCELINE(), "writer8_template", SignatureState::OK, + SignatureState::OK, ODFVER_012_TEXT); + + // create new document from template + load(aURL); + CPPUNIT_ASSERT_MESSAGE(OUStringToOString(sLoadMessage, RTL_TEXTENCODING_UTF8).getStr(), + mxComponent.is()); + + // we are somehow a template (?), and have just a valid macro signature + assertDocument(CPPUNIT_SOURCELINE(), "writer8_template", SignatureState::NOSIGNATURES, + SignatureState::OK, ODFVER_012_TEXT); + + // FIXME: Error: element "document-signatures" is missing "version" attribute + skipValidation(); + + if (sFormat == "writer8") + // save as new ODT document + saveAndReload(sFormat); + else + { + // save as new OTT template + save("writer8_template"); + + // load the saved OTT template as-is to validate signatures + mxComponent->dispose(); + mxComponent = loadFromDesktop( + maTempFile.GetURL(), OUString(), + comphelper::InitPropertySequence({ { "AsTemplate", uno::Any(false) } })); + } + + // the loaded document is a OTT/ODT with a macro signature + assertDocument(CPPUNIT_SOURCELINE(), sFormat, SignatureState::NOSIGNATURES, + SignatureState::OK, ODFVER_013_TEXT); + + // save as new OTT template + save("writer8_template"); + + // load the template as-is to validate signatures + mxComponent->dispose(); + mxComponent = loadFromDesktop( + maTempFile.GetURL(), OUString(), + comphelper::InitPropertySequence({ { "AsTemplate", uno::Any(false) } })); + + // the loaded document is a OTT with a valid macro signature + assertDocument(CPPUNIT_SOURCELINE(), "writer8_template", SignatureState::NOSIGNATURES, + SignatureState::OK, ODFVER_013_TEXT); + + mxComponent->dispose(); + mxComponent.clear(); + } +} + +/// Test if a macro signature from an OTT 1.0 is dropped for ODT 1.2 +CPPUNIT_TEST_FIXTURE(SigningTest, testDropMacroTemplateSignature) +{ + const OUString aURL(createFileURL(u"tdf42316.ott")); + const OUString sLoadMessage = "loading failed: " + aURL; + + // load the template as-is to validate signatures + mxComponent = loadFromDesktop( + aURL, OUString(), comphelper::InitPropertySequence({ { "AsTemplate", uno::Any(false) } })); + + // we are a template, and have a non-invalid macro signature + assertDocument(CPPUNIT_SOURCELINE(), "writer8_template", SignatureState::NOSIGNATURES, + SignatureState::NOTVALIDATED, OUString()); + + // create new document from template + load(aURL); + CPPUNIT_ASSERT_MESSAGE(OUStringToOString(sLoadMessage, RTL_TEXTENCODING_UTF8).getStr(), + mxComponent.is()); + + // we are somehow a template (?), and have just a valid macro signature + assertDocument(CPPUNIT_SOURCELINE(), "writer8_template", SignatureState::NOSIGNATURES, + SignatureState::NOTVALIDATED, OUString()); + + // save as new ODT document + saveAndReload("writer8"); + + // the loaded document is a 1.2 ODT without any signatures + assertDocument(CPPUNIT_SOURCELINE(), "writer8", SignatureState::NOSIGNATURES, + SignatureState::NOSIGNATURES, ODFVER_013_TEXT); + + // load the template as-is to validate signatures + mxComponent->dispose(); + mxComponent = loadFromDesktop( + aURL, OUString(), comphelper::InitPropertySequence({ { "AsTemplate", uno::Any(false) } })); + + // we are a template, and have a non-invalid macro signature + assertDocument(CPPUNIT_SOURCELINE(), "writer8_template", SignatureState::NOSIGNATURES, + SignatureState::NOTVALIDATED, OUString()); + + // save as new OTT template + save("writer8_template"); + + // load the template as-is to validate signatures + mxComponent->dispose(); + mxComponent + = loadFromDesktop(maTempFile.GetURL(), OUString(), + comphelper::InitPropertySequence({ { "AsTemplate", uno::Any(false) } })); + + // the loaded document is a 1.2 OTT without any signatures + assertDocument(CPPUNIT_SOURCELINE(), "writer8_template", SignatureState::NOSIGNATURES, + SignatureState::NOSIGNATURES, ODFVER_013_TEXT); +} + +/// Test if a macro signature from a OTT 1.0 template is preserved for ODT 1.0 +CPPUNIT_TEST_FIXTURE(SigningTest, testPreserveMacroTemplateSignature10) +{ + // set ODF version 1.0 / 1.1 as default + Resetter _([]() { + std::shared_ptr<comphelper::ConfigurationChanges> pBatch( + comphelper::ConfigurationChanges::create()); + officecfg::Office::Common::Save::ODF::DefaultVersion::set(3, pBatch); + return pBatch->commit(); + }); + std::shared_ptr<comphelper::ConfigurationChanges> pBatch( + comphelper::ConfigurationChanges::create()); + officecfg::Office::Common::Save::ODF::DefaultVersion::set(2, pBatch); + pBatch->commit(); + + const OUString aFormats[] = { "writer8", "writer8_template" }; + + for (OUString const& sFormat : aFormats) + { + const OUString aURL(createFileURL(u"tdf42316.ott")); + const OUString sLoadMessage = "loading failed: " + aURL; + + // load the template as-is to validate signatures + mxComponent = loadFromDesktop( + aURL, OUString(), + comphelper::InitPropertySequence({ { "AsTemplate", uno::Any(false) } })); + + // we are a template, and have a non-invalid macro signature + assertDocument(CPPUNIT_SOURCELINE(), "writer8_template", SignatureState::NOSIGNATURES, + SignatureState::NOTVALIDATED, OUString()); + + // create new document from template + load(aURL); + CPPUNIT_ASSERT_MESSAGE(OUStringToOString(sLoadMessage, RTL_TEXTENCODING_UTF8).getStr(), + mxComponent.is()); + + // we are somehow a template (?), and have just a valid macro signature + assertDocument(CPPUNIT_SOURCELINE(), "writer8_template", SignatureState::NOSIGNATURES, + SignatureState::NOTVALIDATED, OUString()); + + // FIXME: Error: element "manifest:manifest" is missing "version" attribute + skipValidation(); + + if (sFormat == "writer8") + // save as new ODT document + saveAndReload(sFormat); + else + { + // save as new OTT template + save("writer8_template"); + + // load the saved OTT template as-is to validate signatures + mxComponent->dispose(); + mxComponent = loadFromDesktop( + maTempFile.GetURL(), OUString(), + comphelper::InitPropertySequence({ { "AsTemplate", uno::Any(false) } })); + } + + assertDocument(CPPUNIT_SOURCELINE(), sFormat, SignatureState::NOSIGNATURES, + SignatureState::NOTVALIDATED, OUString()); + + save("writer8_template"); + + // load the template as-is to validate signatures + mxComponent->dispose(); + mxComponent = loadFromDesktop( + maTempFile.GetURL(), OUString(), + comphelper::InitPropertySequence({ { "AsTemplate", uno::Any(false) } })); + + // the loaded document is a OTT with a non-invalid macro signature + assertDocument(CPPUNIT_SOURCELINE(), "writer8_template", SignatureState::NOSIGNATURES, + SignatureState::NOTVALIDATED, OUString()); + + mxComponent->dispose(); + mxComponent.clear(); + } +} + +#endif + +void SigningTest::registerNamespaces(xmlXPathContextPtr& pXmlXpathCtx) +{ + xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("odfds"), + BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:digitalsignature:1.0")); + xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("dsig"), + BAD_CAST("http://www.w3.org/2000/09/xmldsig#")); + xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("xd"), BAD_CAST("http://uri.etsi.org/01903/v1.3.2#")); +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/qa/unit/signing/signing2.cxx b/xmlsecurity/qa/unit/signing/signing2.cxx new file mode 100644 index 0000000000..aef3c7f088 --- /dev/null +++ b/xmlsecurity/qa/unit/signing/signing2.cxx @@ -0,0 +1,80 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <sal/config.h> + +#include <test/unoapixml_test.hxx> + +#include <com/sun/star/embed/XStorage.hpp> +#include <com/sun/star/frame/Desktop.hpp> +#include <com/sun/star/frame/XStorable.hpp> +#include <com/sun/star/util/XCloseable.hpp> +#include <com/sun/star/xml/crypto/SEInitializer.hpp> + +#include <comphelper/propertysequence.hxx> +#include <unotools/tempfile.hxx> +#include <unotools/ucbstreamhelper.hxx> +#include <comphelper/storagehelper.hxx> +#include <osl/file.hxx> +#include <osl/process.h> +#include <osl/thread.hxx> + +using namespace css; + +/// Testsuite for the document signing feature. +class SigningTest2 : public UnoApiXmlTest +{ +public: + SigningTest2(); + void registerNamespaces(xmlXPathContextPtr& pXmlXpathCtx) override; +}; + +SigningTest2::SigningTest2() + : UnoApiXmlTest("/xmlsecurity/qa/unit/signing/data/") +{ +} + +/// Test if a macro signature from a ODF Database is preserved when saving +CPPUNIT_TEST_FIXTURE(SigningTest2, testPreserveMacroSignatureODB) +{ + loadFromFile(u"odb_signed_macros.odb"); + + // save as ODB + save("StarOffice XML (Base)"); + + // Parse the resulting XML. + uno::Reference<embed::XStorage> xStorage + = comphelper::OStorageHelper::GetStorageOfFormatFromURL( + ZIP_STORAGE_FORMAT_STRING, maTempFile.GetURL(), embed::ElementModes::READ); + CPPUNIT_ASSERT(xStorage.is()); + uno::Reference<embed::XStorage> xMetaInf + = xStorage->openStorageElement("META-INF", embed::ElementModes::READ); + uno::Reference<io::XInputStream> xInputStream( + xMetaInf->openStreamElement("macrosignatures.xml", embed::ElementModes::READ), + uno::UNO_QUERY); + std::unique_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(xInputStream, true)); + xmlDocUniquePtr pXmlDoc = parseXmlStream(pStream.get()); + + // Make sure the signature is still there + assertXPath(pXmlDoc, "//dsig:Signature"_ostr, "Id"_ostr, + "ID_00a7002f009000bc00ce00f7004400460080002f002e00e400e0003700df00e8"); +} + +void SigningTest2::registerNamespaces(xmlXPathContextPtr& pXmlXpathCtx) +{ + xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("odfds"), + BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:digitalsignature:1.0")); + xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("dsig"), + BAD_CAST("http://www.w3.org/2000/09/xmldsig#")); + xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("xd"), BAD_CAST("http://uri.etsi.org/01903/v1.3.2#")); +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/qa/unit/xmlsecurity-dialogs-test.cxx b/xmlsecurity/qa/unit/xmlsecurity-dialogs-test.cxx new file mode 100644 index 0000000000..b5b16c3a72 --- /dev/null +++ b/xmlsecurity/qa/unit/xmlsecurity-dialogs-test.cxx @@ -0,0 +1,61 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <sal/config.h> +#include <test/screenshot_test.hxx> +#include <vcl/abstdlg.hxx> + +using namespace ::com::sun::star; + +/// Test opening a dialog in xmlsecurity +class XmlsecurityDialogsTest : public ScreenshotTest +{ +private: + /// helper method to populate KnownDialogs, called in setUp(). Needs to be + /// written and has to add entries to KnownDialogs + virtual void registerKnownDialogsByID(mapType& rKnownDialogs) override; + + /// dialog creation for known dialogs by ID. Has to be implemented for + /// each registered known dialog + virtual VclPtr<VclAbstractDialog> createDialogByID(sal_uInt32 nID) override; + +public: + XmlsecurityDialogsTest(); + + // try to open a dialog + void openAnyDialog(); + + CPPUNIT_TEST_SUITE(XmlsecurityDialogsTest); + CPPUNIT_TEST(openAnyDialog); + CPPUNIT_TEST_SUITE_END(); +}; + +XmlsecurityDialogsTest::XmlsecurityDialogsTest() {} + +void XmlsecurityDialogsTest::registerKnownDialogsByID(mapType& /*rKnownDialogs*/) +{ + // fill map of known dialogs +} + +VclPtr<VclAbstractDialog> XmlsecurityDialogsTest::createDialogByID(sal_uInt32 /*nID*/) +{ + return nullptr; +} + +void XmlsecurityDialogsTest::openAnyDialog() +{ + /// process input file containing the UXMLDescriptions of the dialogs to dump + processDialogBatchFile(u"xmlsecurity/qa/unit/data/xmlsecurity-dialogs-test.txt"); +} + +CPPUNIT_TEST_SUITE_REGISTRATION(XmlsecurityDialogsTest); + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/component/certificatecontainer.cxx b/xmlsecurity/source/component/certificatecontainer.cxx new file mode 100644 index 0000000000..e230c7b2ce --- /dev/null +++ b/xmlsecurity/source/component/certificatecontainer.cxx @@ -0,0 +1,152 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <map> + +#include <cppuhelper/implbase.hxx> +#include <com/sun/star/security/XCertificateContainer.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> + +#include <cppuhelper/supportsservice.hxx> +#include <rtl/ref.hxx> + +#include <sal/config.h> + +namespace com::sun::star::uno { class XComponentContext; } + +using namespace ::com::sun::star; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; + +namespace { + +class CertificateContainer + : public ::cppu::WeakImplHelper<css::lang::XServiceInfo, css::security::XCertificateContainer> +{ +private: + typedef std::map<OUString, OUString> Map; + Map certMap; + Map certTrustMap; + + static bool searchMap(const OUString& url, std::u16string_view certificate_name, Map& _certMap); + /// @throws css::uno::RuntimeException + bool isTemporaryCertificate(const OUString& url, std::u16string_view certificate_name); + /// @throws css::uno::RuntimeException + bool isCertificateTrust(const OUString& url, std::u16string_view certificate_name); + +public: + explicit CertificateContainer(const uno::Reference<uno::XComponentContext>&) {} + virtual sal_Bool SAL_CALL addCertificate(const OUString& url, const OUString& certificate_name, + sal_Bool trust) override; + virtual css::security::CertificateContainerStatus SAL_CALL + hasCertificate(const OUString& url, const OUString& certificate_name) override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override; + + virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override; +}; + +} + +bool +CertificateContainer::searchMap( const OUString & url, std::u16string_view certificate_name, Map &_certMap ) +{ + Map::iterator p = _certMap.find(url); + + bool ret = false; + + while( p != _certMap.end() ) + { + ret = (*p).second == certificate_name; + if( ret ) + break; + ++p; + } + + return ret; +} + +bool +CertificateContainer::isTemporaryCertificate ( const OUString & url, std::u16string_view certificate_name ) +{ + return searchMap( url, certificate_name, certMap); +} + +bool +CertificateContainer::isCertificateTrust ( const OUString & url, std::u16string_view certificate_name ) +{ + return searchMap( url, certificate_name, certTrustMap); +} + +sal_Bool +CertificateContainer::addCertificate( const OUString & url, const OUString & certificate_name, sal_Bool trust ) +{ + certMap.emplace( url, certificate_name ); + + //remember that the cert is trusted + if (trust) + certTrustMap.emplace( url, certificate_name ); + + return true; +} + +::security::CertificateContainerStatus +CertificateContainer::hasCertificate( const OUString & url, const OUString & certificate_name ) +{ + if ( isTemporaryCertificate( url, certificate_name ) ) + { + if ( isCertificateTrust( url, certificate_name ) ) + return security::CertificateContainerStatus_TRUSTED; + else + return security::CertificateContainerStatus_UNTRUSTED; + } else + { + return security::CertificateContainerStatus_NOCERT; + } +} + +OUString SAL_CALL +CertificateContainer::getImplementationName( ) +{ + return "com.sun.star.security.CertificateContainer"; +} + +sal_Bool SAL_CALL +CertificateContainer::supportsService( const OUString& ServiceName ) +{ + return cppu::supportsService( this, ServiceName ); +} + +Sequence< OUString > SAL_CALL +CertificateContainer::getSupportedServiceNames( ) +{ + return { "com.sun.star.security.CertificateContainer" }; +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +com_sun_star_security_CertificateContainer_get_implementation( + css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&) +{ + static rtl::Reference<CertificateContainer> gContainer = new CertificateContainer(context); + return cppu::acquire(gContainer.get()); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/component/documentdigitalsignatures.cxx b/xmlsecurity/source/component/documentdigitalsignatures.cxx new file mode 100644 index 0000000000..4ad63b36ed --- /dev/null +++ b/xmlsecurity/source/component/documentdigitalsignatures.cxx @@ -0,0 +1,906 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <resourcemanager.hxx> + +#include <certificate.hxx> +#include <certificatechooser.hxx> +#include <certificateviewer.hxx> +#include <digitalsignaturesdialog.hxx> +#include <macrosecurity.hxx> +#include <biginteger.hxx> +#include <strings.hrc> +#include <pdfsignaturehelper.hxx> +#include <sax/tools/converter.hxx> + +#include <com/sun/star/embed/XStorage.hpp> +#include <com/sun/star/embed/StorageFormats.hpp> +#include <com/sun/star/embed/XTransactedObject.hpp> +#include <com/sun/star/embed/ElementModes.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/ucb/XContent.hpp> +#include <com/sun/star/ucb/XContentIdentifierFactory.hpp> +#include <com/sun/star/ucb/XCommandEnvironment.hpp> +#include <com/sun/star/ucb/XCommandProcessor.hpp> +#include <com/sun/star/ucb/Command.hpp> +#include <com/sun/star/uno/SecurityException.hpp> +#include <vcl/weld.hxx> +#include <vcl/svapp.hxx> +#include <tools/date.hxx> +#include <tools/time.hxx> +#include <unotools/securityoptions.hxx> +#include <com/sun/star/security/CertificateValidity.hpp> +#include <com/sun/star/security/CertificateKind.hpp> +#include <comphelper/base64.hxx> +#include <comphelper/documentconstants.hxx> +#include <comphelper/propertyvalue.hxx> +#include <comphelper/sequence.hxx> +#include <cppuhelper/implbase.hxx> +#include <comphelper/xmlsechelper.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <sal/log.hxx> +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <com/sun/star/security/XDocumentDigitalSignatures.hpp> +#include <com/sun/star/xml/crypto/XXMLSecurityContext.hpp> +#include <sfx2/digitalsignatures.hxx> + +#include <map> + +using namespace css; +using namespace css::uno; +using namespace css::lang; +using namespace css::security; +using namespace css::xml::crypto; + +namespace { +class DocumentDigitalSignatures + : public cppu::WeakImplHelper<css::security::XDocumentDigitalSignatures, + css::lang::XInitialization, css::lang::XServiceInfo>, + public sfx2::DigitalSignatures +{ +private: + css::uno::Reference<css::uno::XComponentContext> mxCtx; + css::uno::Reference<css::awt::XWindow> mxParentWindow; + + /// will be set by XInitialization. If not we assume true. false means an earlier version (whatever that means, + /// this is a string, not a boolean). + /// Note that the code talks about "ODF version" even if this class is also used to sign OOXML. + OUString m_sODFVersion; + /// The number of arguments which were passed in XInitialization::initialize + int m_nArgumentsCount; + /// Indicates if the document already contains a document signature + bool m_bHasDocumentSignature; + + /// @throws css::uno::RuntimeException + bool ImplViewSignatures(const css::uno::Reference<css::embed::XStorage>& rxStorage, + const css::uno::Reference<css::io::XStream>& xSignStream, + DocumentSignatureMode eMode, bool bReadOnly); + /// @throws css::uno::RuntimeException + void ImplViewSignatures(const css::uno::Reference<css::embed::XStorage>& rxStorage, + const css::uno::Reference<css::io::XInputStream>& xSignStream, + DocumentSignatureMode eMode, bool bReadOnly); + /// @throws css::uno::RuntimeException + css::uno::Sequence<css::security::DocumentSignatureInformation> + ImplVerifySignatures(const css::uno::Reference<css::embed::XStorage>& rxStorage, + const ::com::sun::star::uno::Reference<css::io::XInputStream>& xSignStream, + DocumentSignatureMode eMode); + + css::uno::Sequence<css::uno::Reference<css::security::XCertificate>> + chooseCertificatesImpl(std::map<OUString, OUString>& rProperties, const UserAction eAction, + const CertificateKind certificateKind=CertificateKind_NONE); + + bool + signWithCertificateImpl(const uno::Reference<frame::XModel>& /*xModel*/, + css::uno::Reference<css::security::XCertificate> const& xCertificate, + css::uno::Reference<css::embed::XStorage> const& xStorage, + css::uno::Reference<css::io::XStream> const& xStream, + DocumentSignatureMode eMode); + +public: + explicit DocumentDigitalSignatures( + const css::uno::Reference<css::uno::XComponentContext>& rxCtx); + + //XInitialization + void SAL_CALL initialize(const css::uno::Sequence<css::uno::Any>& aArguments) override; + + OUString SAL_CALL getImplementationName() override; + + sal_Bool SAL_CALL supportsService(OUString const& ServiceName) override; + + css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override; + + // XDocumentDigitalSignatures + sal_Bool SAL_CALL + signDocumentContent(const css::uno::Reference<css::embed::XStorage>& xStorage, + const css::uno::Reference<css::io::XStream>& xSignStream) override; + sal_Bool SAL_CALL signSignatureLine( + const css::uno::Reference<css::embed::XStorage>& Storage, + const css::uno::Reference<css::io::XStream>& xSignStream, const OUString& aSignatureLineId, + const Reference<css::security::XCertificate>& xCertificate, + const Reference<css::graphic::XGraphic>& xValidGraphic, + const Reference<css::graphic::XGraphic>& xInvalidGraphic, + const OUString& aComment) override; + css::uno::Sequence<css::security::DocumentSignatureInformation> + SAL_CALL verifyDocumentContentSignatures( + const css::uno::Reference<css::embed::XStorage>& xStorage, + const css::uno::Reference<css::io::XInputStream>& xSignInStream) override; + void SAL_CALL showDocumentContentSignatures( + const css::uno::Reference<css::embed::XStorage>& xStorage, + const css::uno::Reference<css::io::XInputStream>& xSignInStream) override; + OUString SAL_CALL getDocumentContentSignatureDefaultStreamName() override; + sal_Bool SAL_CALL + signScriptingContent(const css::uno::Reference<css::embed::XStorage>& xStorage, + const css::uno::Reference<css::io::XStream>& xSignStream) override; + css::uno::Sequence<css::security::DocumentSignatureInformation> + SAL_CALL verifyScriptingContentSignatures( + const css::uno::Reference<css::embed::XStorage>& xStorage, + const css::uno::Reference<css::io::XInputStream>& xSignInStream) override; + void SAL_CALL showScriptingContentSignatures( + const css::uno::Reference<css::embed::XStorage>& xStorage, + const css::uno::Reference<css::io::XInputStream>& xSignInStream) override; + OUString SAL_CALL getScriptingContentSignatureDefaultStreamName() override; + sal_Bool SAL_CALL + signPackage(const css::uno::Reference<css::embed::XStorage>& Storage, + const css::uno::Reference<css::io::XStream>& xSignStream) override; + css::uno::Sequence<css::security::DocumentSignatureInformation> + SAL_CALL verifyPackageSignatures( + const css::uno::Reference<css::embed::XStorage>& Storage, + const css::uno::Reference<css::io::XInputStream>& xSignInStream) override; + void SAL_CALL + showPackageSignatures(const css::uno::Reference<css::embed::XStorage>& xStorage, + const css::uno::Reference<css::io::XInputStream>& xSignInStream) override; + OUString SAL_CALL getPackageSignatureDefaultStreamName() override; + void SAL_CALL + showCertificate(const css::uno::Reference<css::security::XCertificate>& Certificate) override; + void SAL_CALL manageTrustedSources() override; + sal_Bool SAL_CALL + isAuthorTrusted(const css::uno::Reference<css::security::XCertificate>& Author) override; + sal_Bool SAL_CALL isLocationTrusted(const OUString& Location) override; + void SAL_CALL addAuthorToTrustedSources( + const css::uno::Reference<css::security::XCertificate>& Author) override; + void SAL_CALL addLocationToTrustedSources(const OUString& Location) override; + + css::uno::Reference<css::security::XCertificate> + SAL_CALL chooseCertificate(OUString& rDescription) override; + css::uno::Reference<css::security::XCertificate> + SAL_CALL chooseSigningCertificate(OUString& rDescription) override; + css::uno::Reference<css::security::XCertificate> + SAL_CALL selectSigningCertificate(OUString& rDescription) override; + css::uno::Reference<css::security::XCertificate> + SAL_CALL selectSigningCertificateWithType(const CertificateKind certificateKind, + OUString& rDescription) override; + css::uno::Sequence<css::uno::Reference<css::security::XCertificate>> + SAL_CALL chooseEncryptionCertificate() override; + css::uno::Reference<css::security::XCertificate> SAL_CALL chooseCertificateWithProps( + css::uno::Sequence<::com::sun::star::beans::PropertyValue>& Properties) override; + + sal_Bool SAL_CALL signDocumentWithCertificate( + css::uno::Reference<css::security::XCertificate> const & xCertificate, + css::uno::Reference<css::embed::XStorage> const & xStoragexStorage, + css::uno::Reference<css::io::XStream> const & xStream) override; + + sal_Bool SAL_CALL signPackageWithCertificate( + css::uno::Reference<css::security::XCertificate> const& xCertificate, + css::uno::Reference<css::embed::XStorage> const& xStoragexStorage, + css::uno::Reference<css::io::XStream> const& xStream) override; + + sal_Bool SAL_CALL signScriptingContentWithCertificate( + css::uno::Reference<css::security::XCertificate> const& xCertificate, + css::uno::Reference<css::embed::XStorage> const& xStoragexStorage, + css::uno::Reference<css::io::XStream> const& xStream) override; + + void SAL_CALL setParentWindow(const css::uno::Reference<css::awt::XWindow>& rParentwindow) override + { + mxParentWindow = rParentwindow; + } + + /// See sfx2::DigitalSignatures::SignModelWithCertificate(). + bool + SignModelWithCertificate(const css::uno::Reference<css::frame::XModel>& xModel, + const css::uno::Reference<css::security::XCertificate>& xCertificate, + const css::uno::Reference<css::embed::XStorage>& xStorage, + const css::uno::Reference<css::io::XStream>& xStream) override; +}; + +} + +DocumentDigitalSignatures::DocumentDigitalSignatures( const Reference< XComponentContext >& rxCtx ): + mxCtx(rxCtx), + m_sODFVersion(ODFVER_013_TEXT), + m_nArgumentsCount(0), + m_bHasDocumentSignature(false) +{ +} + +void DocumentDigitalSignatures::initialize( const Sequence< Any >& aArguments) +{ + if (aArguments.getLength() > 2) + throw css::lang::IllegalArgumentException( + "DocumentDigitalSignatures::initialize requires zero, one, or two arguments", + static_cast<XInitialization*>(this), 0); + + m_nArgumentsCount = aArguments.getLength(); + + if (!aArguments.hasElements()) + return; + + if (!(aArguments[0] >>= m_sODFVersion)) + throw css::lang::IllegalArgumentException( + "DocumentDigitalSignatures::initialize: the first arguments must be a string", + static_cast<XInitialization*>(this), 0); + + if (aArguments.getLength() == 2 + && !(aArguments[1] >>= m_bHasDocumentSignature)) + throw css::lang::IllegalArgumentException( + "DocumentDigitalSignatures::initialize: the second arguments must be a bool", + static_cast<XInitialization*>(this), 1); + + //the Version is supported as of ODF1.2, so for and 1.1 document or older we will receive the + //an empty string. In this case we set it to ODFVER_010_TEXT. Then we can later check easily + //if initialize was called. Only then m_sODFVersion.getLength() is greater than 0 + if (m_sODFVersion.isEmpty()) + m_sODFVersion = ODFVER_010_TEXT; +} + +OUString DocumentDigitalSignatures::getImplementationName() +{ + return "com.sun.star.security.DocumentDigitalSignatures"; +} + +sal_Bool DocumentDigitalSignatures::supportsService( + OUString const & ServiceName) +{ + return cppu::supportsService(this, ServiceName); +} + +css::uno::Sequence<OUString> +DocumentDigitalSignatures::getSupportedServiceNames() +{ + Sequence<OUString> aRet{ "com.sun.star.security.DocumentDigitalSignatures" }; + return aRet; +} + +sal_Bool DocumentDigitalSignatures::signDocumentContent( + const Reference< css::embed::XStorage >& rxStorage, + const Reference< css::io::XStream >& xSignStream) +{ + OSL_ENSURE(!m_sODFVersion.isEmpty(), "DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2"); + return ImplViewSignatures( rxStorage, xSignStream, DocumentSignatureMode::Content, false ); +} + +sal_Bool DocumentDigitalSignatures::signSignatureLine( + const Reference<css::embed::XStorage>& rxStorage, + const Reference<css::io::XStream>& xSignStream, + const OUString& aSignatureLineId, + const Reference<css::security::XCertificate>& xCertificate, + const Reference<css::graphic::XGraphic>& xValidGraphic, + const Reference<css::graphic::XGraphic>& xInvalidGraphic, + const OUString& aComment) +{ + OSL_ENSURE(!m_sODFVersion.isEmpty(), + "DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2"); + + DocumentSignatureManager aSignatureManager(mxCtx, DocumentSignatureMode::Content); + + if (!aSignatureManager.init()) + return false; + + aSignatureManager.setStore(rxStorage); + aSignatureManager.getSignatureHelper().SetStorage(rxStorage, m_sODFVersion); + aSignatureManager.setSignatureStream(xSignStream); + + Reference<XXMLSecurityContext> xSecurityContext; + Reference<XServiceInfo> xServiceInfo(xCertificate, UNO_QUERY); + if (xServiceInfo->getImplementationName() + == "com.sun.star.xml.security.gpg.XCertificate_GpgImpl") + xSecurityContext = aSignatureManager.getGpgSecurityContext(); + else + xSecurityContext = aSignatureManager.getSecurityContext(); + + sal_Int32 nSecurityId; + bool bSuccess = aSignatureManager.add(xCertificate, xSecurityContext, aComment, nSecurityId, + true, aSignatureLineId, xValidGraphic, xInvalidGraphic); + if (!bSuccess) + return false; + + // Need to have this to verify the signature + aSignatureManager.read(/*bUseTempStream=*/true, /*bCacheLastSignature=*/false); + aSignatureManager.write(true); + + if (rxStorage.is() && !xSignStream.is()) + { + uno::Reference<embed::XTransactedObject> xTrans(rxStorage, uno::UNO_QUERY); + xTrans->commit(); + } + + return true; +} + +Sequence< css::security::DocumentSignatureInformation > +DocumentDigitalSignatures::verifyDocumentContentSignatures( + const Reference< css::embed::XStorage >& rxStorage, + const Reference< css::io::XInputStream >& xSignInStream ) +{ + OSL_ENSURE(!m_sODFVersion.isEmpty(),"DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2"); + return ImplVerifySignatures( rxStorage, xSignInStream, DocumentSignatureMode::Content ); +} + +void DocumentDigitalSignatures::showDocumentContentSignatures( + const Reference< css::embed::XStorage >& rxStorage, + const Reference< css::io::XInputStream >& xSignInStream ) +{ + OSL_ENSURE(!m_sODFVersion.isEmpty(),"DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2"); + ImplViewSignatures( rxStorage, xSignInStream, DocumentSignatureMode::Content, true ); +} + +OUString DocumentDigitalSignatures::getDocumentContentSignatureDefaultStreamName() +{ + return DocumentSignatureHelper::GetDocumentContentSignatureDefaultStreamName(); +} + +sal_Bool DocumentDigitalSignatures::signScriptingContent( + const Reference< css::embed::XStorage >& rxStorage, + const Reference< css::io::XStream >& xSignStream ) +{ + OSL_ENSURE(!m_sODFVersion.isEmpty(),"DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2"); + OSL_ENSURE(m_nArgumentsCount == 2, "DocumentDigitalSignatures: Service was not initialized properly"); + return ImplViewSignatures( rxStorage, xSignStream, DocumentSignatureMode::Macros, false ); +} + +Sequence< css::security::DocumentSignatureInformation > +DocumentDigitalSignatures::verifyScriptingContentSignatures( + const Reference< css::embed::XStorage >& rxStorage, + const Reference< css::io::XInputStream >& xSignInStream ) +{ + OSL_ENSURE(!m_sODFVersion.isEmpty(),"DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2"); + return ImplVerifySignatures( rxStorage, xSignInStream, DocumentSignatureMode::Macros ); +} + +void DocumentDigitalSignatures::showScriptingContentSignatures( + const Reference< css::embed::XStorage >& rxStorage, + const Reference< css::io::XInputStream >& xSignInStream ) +{ + OSL_ENSURE(!m_sODFVersion.isEmpty(),"DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2"); + ImplViewSignatures( rxStorage, xSignInStream, DocumentSignatureMode::Macros, true ); +} + +OUString DocumentDigitalSignatures::getScriptingContentSignatureDefaultStreamName() +{ + return DocumentSignatureHelper::GetScriptingContentSignatureDefaultStreamName(); +} + + +sal_Bool DocumentDigitalSignatures::signPackage( + const Reference< css::embed::XStorage >& rxStorage, + const Reference< css::io::XStream >& xSignStream ) +{ + OSL_ENSURE(!m_sODFVersion.isEmpty(),"DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2"); + return ImplViewSignatures( rxStorage, xSignStream, DocumentSignatureMode::Package, false ); +} + +Sequence< css::security::DocumentSignatureInformation > +DocumentDigitalSignatures::verifyPackageSignatures( + const Reference< css::embed::XStorage >& rxStorage, + const Reference< css::io::XInputStream >& xSignInStream ) +{ + OSL_ENSURE(!m_sODFVersion.isEmpty(),"DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2"); + return ImplVerifySignatures( rxStorage, xSignInStream, DocumentSignatureMode::Package ); +} + +void DocumentDigitalSignatures::showPackageSignatures( + const Reference< css::embed::XStorage >& rxStorage, + const Reference< css::io::XInputStream >& xSignInStream ) +{ + OSL_ENSURE(!m_sODFVersion.isEmpty(),"DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2"); + ImplViewSignatures( rxStorage, xSignInStream, DocumentSignatureMode::Package, true ); +} + +OUString DocumentDigitalSignatures::getPackageSignatureDefaultStreamName( ) +{ + return DocumentSignatureHelper::GetPackageSignatureDefaultStreamName(); +} + + +void DocumentDigitalSignatures::ImplViewSignatures( + const Reference< css::embed::XStorage >& rxStorage, + const Reference< css::io::XInputStream >& xSignStream, + DocumentSignatureMode eMode, bool bReadOnly ) +{ + Reference< io::XStream > xStream; + if ( xSignStream.is() ) + xStream.set( xSignStream, UNO_QUERY ); + ImplViewSignatures( rxStorage, xStream, eMode, bReadOnly ); +} + +bool DocumentDigitalSignatures::ImplViewSignatures( + const Reference< css::embed::XStorage >& rxStorage, const Reference< css::io::XStream >& xSignStream, + DocumentSignatureMode eMode, bool bReadOnly ) +{ + bool bChanges = false; + auto xSignaturesDialog = std::make_shared<DigitalSignaturesDialog>( + Application::GetFrameWeld(mxParentWindow), mxCtx, eMode, bReadOnly, m_sODFVersion, + m_bHasDocumentSignature); + bool bInit = xSignaturesDialog->Init(); + SAL_WARN_IF( !bInit, "xmlsecurity.comp", "Error initializing security context!" ); + if ( bInit ) + { + xSignaturesDialog->SetStorage(rxStorage); + + xSignaturesDialog->SetSignatureStream( xSignStream ); + + if (bReadOnly) + { + xSignaturesDialog->beforeRun(); + weld::DialogController::runAsync(xSignaturesDialog, [] (sal_Int32) {}); + return false; + } + else if (xSignaturesDialog->run() == RET_OK) + { + if (xSignaturesDialog->SignaturesChanged()) + { + bChanges = true; + // If we have a storage and no stream, we are responsible for commit + if ( rxStorage.is() && !xSignStream.is() ) + { + uno::Reference< embed::XTransactedObject > xTrans( rxStorage, uno::UNO_QUERY ); + xTrans->commit(); + } + } + } + } + else + { + std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(Application::GetFrameWeld(mxParentWindow), + VclMessageType::Warning, VclButtonsType::Ok, + XsResId(RID_XMLSECWB_NO_MOZILLA_PROFILE))); + xBox->run(); + } + + return bChanges; +} + +Sequence< css::security::DocumentSignatureInformation > +DocumentDigitalSignatures::ImplVerifySignatures( + const Reference< css::embed::XStorage >& rxStorage, + const Reference< css::io::XInputStream >& xSignStream, DocumentSignatureMode eMode ) +{ + DocumentSignatureManager aSignatureManager(mxCtx, eMode); + + bool bInit = aSignatureManager.init(); + + SAL_WARN_IF(!bInit, "xmlsecurity.comp", "Error initializing security context!"); + + if (!bInit) + return {}; + + if (!rxStorage.is()) + { + if (xSignStream.is()) + { + // Something not ZIP-based, try PDF. + PDFSignatureHelper& rSignatureHelper = aSignatureManager.getPDFSignatureHelper(); + if (rSignatureHelper.ReadAndVerifySignature(xSignStream)) + return rSignatureHelper.GetDocumentSignatureInformations(aSignatureManager.getSecurityEnvironment()); + } + + SAL_WARN( "xmlsecurity.comp", "Error, no XStorage provided"); + return Sequence<css::security::DocumentSignatureInformation>(); + } + // First check for the InputStream, to avoid unnecessary initialization of the security environment... + SignatureStreamHelper aStreamHelper; + Reference< io::XInputStream > xInputStream = xSignStream; + + if ( !xInputStream.is() ) + { + aStreamHelper = DocumentSignatureHelper::OpenSignatureStream( rxStorage, embed::ElementModes::READ, eMode ); + if ( aStreamHelper.xSignatureStream.is() ) + xInputStream.set( aStreamHelper.xSignatureStream, UNO_QUERY ); + } + + if (!xInputStream.is() && aStreamHelper.nStorageFormat != embed::StorageFormats::OFOPXML) + return {}; + + + XMLSignatureHelper& rSignatureHelper = aSignatureManager.getSignatureHelper(); + rSignatureHelper.SetStorage(rxStorage, m_sODFVersion); + + rSignatureHelper.StartMission(aSignatureManager.getSecurityContext()); + + if (xInputStream.is()) + rSignatureHelper.ReadAndVerifySignature(xInputStream); + else if (aStreamHelper.nStorageFormat == embed::StorageFormats::OFOPXML) + rSignatureHelper.ReadAndVerifySignatureStorage(aStreamHelper.xSignatureStorage); + + rSignatureHelper.EndMission(); + + uno::Reference<xml::crypto::XSecurityEnvironment> xSecEnv = aSignatureManager.getSecurityEnvironment(); + uno::Reference<xml::crypto::XSecurityEnvironment> xGpgSecEnv = aSignatureManager.getGpgSecurityEnvironment(); + + SignatureInformations aSignInfos = rSignatureHelper.GetSignatureInformations(); + int nInfos = aSignInfos.size(); + Sequence< css::security::DocumentSignatureInformation > aInfos(nInfos); + css::security::DocumentSignatureInformation* arInfos = aInfos.getArray(); + + for (int n = 0; n < nInfos; ++n) + { + DocumentSignatureAlgorithm mode + = DocumentSignatureHelper::getDocumentAlgorithm(m_sODFVersion, aSignInfos[n]); + const std::vector<OUString> aElementsToBeVerified + = DocumentSignatureHelper::CreateElementList(rxStorage, eMode, mode); + + const SignatureInformation& rInfo = aSignInfos[n]; + css::security::DocumentSignatureInformation& rSigInfo = arInfos[n]; + + if (!rInfo.X509Datas.empty()) // X.509 + { + std::vector<uno::Reference<XCertificate>> certs( + rSignatureHelper.CheckAndUpdateSignatureInformation( + xSecEnv, rInfo)); + if (certs.empty()) + { + rSigInfo.CertificateStatus = css::security::CertificateValidity::INVALID; + } + else + { + rSigInfo.Signer = certs.back(); + // get only intermediates + certs.pop_back(); + // On Windows checking the certificate path is buggy. It does name matching (issuer, subject name) + // to find the parent certificate. It does not take into account that there can be several certificates + // with the same subject name. + try + { + rSigInfo.CertificateStatus = xSecEnv->verifyCertificate( + rSigInfo.Signer, comphelper::containerToSequence(certs)); + } + catch (SecurityException&) + { + SAL_WARN("xmlsecurity.comp", "Verification of certificate failed"); + rSigInfo.CertificateStatus = css::security::CertificateValidity::INVALID; + } + } + } + else if (!rInfo.ouGpgCertificate.isEmpty() && xGpgSecEnv.is()) // GPG + { + // TODO not ideal to retrieve cert by keyID, might + // collide, or PGPKeyID format might change - can't we + // keep the xCert itself in rInfo? + rSigInfo.Signer = xGpgSecEnv->getCertificate( + rInfo.ouGpgKeyID, xmlsecurity::numericStringToBigInteger(u"")); + rSigInfo.CertificateStatus = xGpgSecEnv->verifyCertificate( + rSigInfo.Signer, Sequence<Reference<css::security::XCertificate>>()); + } + + // Time support again (#i38744#) + Date aDate(rInfo.stDateTime.Day, rInfo.stDateTime.Month, rInfo.stDateTime.Year); + tools::Time aTime(rInfo.stDateTime.Hours, rInfo.stDateTime.Minutes, + rInfo.stDateTime.Seconds, rInfo.stDateTime.NanoSeconds); + rSigInfo.SignatureDate = aDate.GetDate(); + rSigInfo.SignatureTime = aTime.GetTime() / tools::Time::nanoPerCenti; + + rSigInfo.SignatureIsValid + = (rInfo.nStatus == css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED); + + // Signature line info (ID + Images) + if (!rInfo.ouSignatureLineId.isEmpty()) + rSigInfo.SignatureLineId = rInfo.ouSignatureLineId; + + if (rInfo.aValidSignatureImage.is()) + rSigInfo.ValidSignatureLineImage = rInfo.aValidSignatureImage; + + if (rInfo.aInvalidSignatureImage.is()) + rSigInfo.InvalidSignatureLineImage = rInfo.aInvalidSignatureImage; + + // OOXML intentionally doesn't sign metadata. + if (rSigInfo.SignatureIsValid + && aStreamHelper.nStorageFormat != embed::StorageFormats::OFOPXML) + { + rSigInfo.SignatureIsValid = DocumentSignatureHelper::checkIfAllFilesAreSigned( + aElementsToBeVerified, rInfo, mode); + } + if (eMode == DocumentSignatureMode::Content) + { + if (aStreamHelper.nStorageFormat == embed::StorageFormats::OFOPXML) + rSigInfo.PartialDocumentSignature = true; + else + rSigInfo.PartialDocumentSignature + = !DocumentSignatureHelper::isOOo3_2_Signature(aSignInfos[n]); + } + } + + return aInfos; + +} + +void DocumentDigitalSignatures::manageTrustedSources( ) +{ + // MT: i45295 + // SecEnv is only needed to display certificate information from trusted sources. + // Macro Security also has some options where no security environment is needed, so raise dialog anyway. + // Later I should change the code so the Dialog creates the SecEnv on demand... + + Reference< css::xml::crypto::XSecurityEnvironment > xSecEnv; + + DocumentSignatureManager aSignatureManager(mxCtx, {}); + if (aSignatureManager.init()) + xSecEnv = aSignatureManager.getSecurityEnvironment(); + + MacroSecurity aDlg(Application::GetFrameWeld(mxParentWindow), xSecEnv); + aDlg.run(); +} + +void DocumentDigitalSignatures::showCertificate( + const Reference< css::security::XCertificate >& Certificate ) +{ + DocumentSignatureManager aSignatureManager(mxCtx, {}); + + bool bInit = aSignatureManager.init(); + + SAL_WARN_IF( !bInit, "xmlsecurity.comp", "Error initializing security context!" ); + + if ( bInit ) + { + CertificateViewer aViewer(Application::GetFrameWeld(mxParentWindow), aSignatureManager.getSecurityEnvironment(), Certificate, false, nullptr); + aViewer.run(); + } +} + +sal_Bool DocumentDigitalSignatures::isAuthorTrusted( + const Reference<css::security::XCertificate>& xAuthor) +{ + if (!xAuthor.is()) + { + return false; + } + OUString sSerialNum = xmlsecurity::bigIntegerToNumericString(xAuthor->getSerialNumber()); + + std::vector< SvtSecurityOptions::Certificate > aTrustedAuthors = SvtSecurityOptions::GetTrustedAuthors(); + + return std::any_of(aTrustedAuthors.begin(), aTrustedAuthors.end(), + [this, &xAuthor, &sSerialNum](const SvtSecurityOptions::Certificate& rAuthor) { + if (!xmlsecurity::EqualDistinguishedNames(rAuthor.SubjectName, xAuthor->getIssuerName(), xmlsecurity::NOCOMPAT)) + return false; + if (rAuthor.SerialNumber != sSerialNum) + return false; + + DocumentSignatureManager aSignatureManager(mxCtx, {}); + if (!aSignatureManager.init()) + return false; + uno::Reference<css::security::XCertificate> xCert = aSignatureManager.getSecurityEnvironment()->createCertificateFromAscii(rAuthor.RawData); + + auto pAuthor = dynamic_cast<xmlsecurity::Certificate*>(xAuthor.get()); + auto pCert = dynamic_cast<xmlsecurity::Certificate*>(xCert.get()); + if (pAuthor && pCert) + return pCert->getSHA256Thumbprint() == pAuthor->getSHA256Thumbprint(); + + return xCert->getSHA1Thumbprint() == xAuthor->getSHA1Thumbprint(); + }); +} + +uno::Sequence<Reference<css::security::XCertificate>> +DocumentDigitalSignatures::chooseCertificatesImpl(std::map<OUString, OUString>& rProperties, + const UserAction eAction, + const CertificateKind certificateKind) +{ + std::vector< Reference< css::xml::crypto::XXMLSecurityContext > > xSecContexts; + + DocumentSignatureManager aSignatureManager(mxCtx, {}); + if (aSignatureManager.init()) { + xSecContexts.push_back(aSignatureManager.getSecurityContext()); + // Don't include OpenPGP if only X.509 certs are requested + if (certificateKind == CertificateKind_NONE || certificateKind == CertificateKind_OPENPGP) + xSecContexts.push_back(aSignatureManager.getGpgSecurityContext()); + } + + CertificateChooser* aChooser = CertificateChooser::getInstance(Application::GetFrameWeld(mxParentWindow), std::move(xSecContexts), eAction); + + if (aChooser->run() != RET_OK) + return { Reference< css::security::XCertificate >(nullptr) }; + + uno::Sequence< Reference< css::security::XCertificate > > xCerts = aChooser->GetSelectedCertificates(); + rProperties["Description"] = aChooser->GetDescription(); + rProperties["Usage"] = aChooser->GetUsageText(); + + return xCerts; +} + +Reference< css::security::XCertificate > DocumentDigitalSignatures::chooseCertificate(OUString& rDescription) +{ + return chooseSigningCertificate( rDescription ); +} + +Reference< css::security::XCertificate > DocumentDigitalSignatures::chooseSigningCertificate(OUString& rDescription) +{ + std::map<OUString, OUString> aProperties; + Reference< css::security::XCertificate > xCert = chooseCertificatesImpl( aProperties, UserAction::Sign )[0]; + rDescription = aProperties["Description"]; + return xCert; +} + +Reference< css::security::XCertificate > DocumentDigitalSignatures::selectSigningCertificate(OUString& rDescription) +{ + std::map<OUString, OUString> aProperties; + Reference< css::security::XCertificate > xCert = chooseCertificatesImpl( aProperties, UserAction::SelectSign )[0]; + rDescription = aProperties["Description"]; + return xCert; +} + +Reference<css::security::XCertificate> +DocumentDigitalSignatures::selectSigningCertificateWithType(const CertificateKind certificateKind, + OUString& rDescription) +{ + std::map<OUString, OUString> aProperties; + Reference<css::security::XCertificate> xCert + = chooseCertificatesImpl(aProperties, UserAction::SelectSign, certificateKind)[0]; + rDescription = aProperties["Description"]; + return xCert; +} + +css::uno::Sequence< Reference< css::security::XCertificate > > DocumentDigitalSignatures::chooseEncryptionCertificate() +{ + std::map<OUString, OUString> aProperties; + uno::Sequence< Reference< css::security::XCertificate > > aCerts= + chooseCertificatesImpl( aProperties, UserAction::Encrypt ); + if (aCerts.getLength() == 1 && !aCerts[0].is()) + // our error case contract is: empty sequence, so map that! + return uno::Sequence< Reference< css::security::XCertificate > >(); + else + return aCerts; +} + +css::uno::Reference< css::security::XCertificate > DocumentDigitalSignatures::chooseCertificateWithProps(Sequence<::com::sun::star::beans::PropertyValue>& rProperties) +{ + std::map<OUString, OUString> aProperties; + auto xCert = chooseCertificatesImpl( aProperties, UserAction::Sign )[0]; + + std::vector<css::beans::PropertyValue> vec; + vec.reserve(aProperties.size()); + for (const auto& pair : aProperties) + { + vec.emplace_back(comphelper::makePropertyValue(pair.first, pair.second)); + } + + rProperties = comphelper::containerToSequence(vec); + return xCert; +} + +sal_Bool DocumentDigitalSignatures::isLocationTrusted( const OUString& Location ) +{ + return SvtSecurityOptions::isTrustedLocationUri(Location); +} + +void DocumentDigitalSignatures::addAuthorToTrustedSources( + const Reference< css::security::XCertificate >& Author ) +{ + SvtSecurityOptions::Certificate aNewCert; + aNewCert.SubjectName = Author->getIssuerName(); + aNewCert.SerialNumber = xmlsecurity::bigIntegerToNumericString( Author->getSerialNumber() ); + + OUStringBuffer aStrBuffer; + ::comphelper::Base64::encode(aStrBuffer, Author->getEncoded()); + aNewCert.RawData = aStrBuffer.makeStringAndClear(); + + std::vector< SvtSecurityOptions::Certificate > aTrustedAuthors = SvtSecurityOptions::GetTrustedAuthors(); + aTrustedAuthors.push_back( aNewCert ); + SvtSecurityOptions::SetTrustedAuthors( aTrustedAuthors ); +} + +void DocumentDigitalSignatures::addLocationToTrustedSources( const OUString& Location ) +{ + std::vector< OUString > aSecURLs = SvtSecurityOptions::GetSecureURLs(); + aSecURLs.push_back(Location); + + SvtSecurityOptions::SetSecureURLs( std::move(aSecURLs) ); +} + +sal_Bool DocumentDigitalSignatures::signDocumentWithCertificate( + css::uno::Reference<css::security::XCertificate> const & xCertificate, + css::uno::Reference<css::embed::XStorage> const & xStorage, + css::uno::Reference<css::io::XStream> const & xStream) +{ + uno::Reference<frame::XModel> xModel; + return signWithCertificateImpl(xModel, xCertificate, xStorage, xStream, + DocumentSignatureMode::Content); +} + +bool DocumentDigitalSignatures::SignModelWithCertificate( + const uno::Reference<frame::XModel>& xModel, + const css::uno::Reference<css::security::XCertificate>& xCertificate, + const css::uno::Reference<css::embed::XStorage>& xStorage, + const css::uno::Reference<css::io::XStream>& xStream) +{ + return signWithCertificateImpl(xModel, xCertificate, xStorage, xStream, + DocumentSignatureMode::Content); +} + +sal_Bool DocumentDigitalSignatures::signPackageWithCertificate( + css::uno::Reference<css::security::XCertificate> const& xCertificate, + css::uno::Reference<css::embed::XStorage> const& xStorage, + css::uno::Reference<css::io::XStream> const& xStream) +{ + uno::Reference<frame::XModel> xModel; + return signWithCertificateImpl(xModel, xCertificate, xStorage, xStream, + DocumentSignatureMode::Package); +} + +sal_Bool DocumentDigitalSignatures::signScriptingContentWithCertificate( + css::uno::Reference<css::security::XCertificate> const& xCertificate, + css::uno::Reference<css::embed::XStorage> const& xStorage, + css::uno::Reference<css::io::XStream> const& xStream) +{ + uno::Reference<frame::XModel> xModel; + return signWithCertificateImpl(xModel, xCertificate, xStorage, xStream, + DocumentSignatureMode::Macros); +} + +bool DocumentDigitalSignatures::signWithCertificateImpl( + const uno::Reference<frame::XModel>& xModel, + css::uno::Reference<css::security::XCertificate> const& xCertificate, + css::uno::Reference<css::embed::XStorage> const& xStorage, + css::uno::Reference<css::io::XStream> const& xStream, DocumentSignatureMode eMode) +{ + OSL_ENSURE(!m_sODFVersion.isEmpty(), + "DocumentDigitalSignatures: ODF Version not set, assuming minimum 1.2"); + + DocumentSignatureManager aSignatureManager(mxCtx, eMode); + + if (!aSignatureManager.init()) + return false; + + aSignatureManager.setStore(xStorage); + aSignatureManager.getSignatureHelper().SetStorage(xStorage, m_sODFVersion); + aSignatureManager.setSignatureStream(xStream); + aSignatureManager.setModel(xModel); + + Reference<XXMLSecurityContext> xSecurityContext; + Reference<XServiceInfo> xServiceInfo(xCertificate, UNO_QUERY); + if (xServiceInfo->getImplementationName() + == "com.sun.star.xml.security.gpg.XCertificate_GpgImpl") + xSecurityContext = aSignatureManager.getGpgSecurityContext(); + else + xSecurityContext = aSignatureManager.getSecurityContext(); + + sal_Int32 nSecurityId; + + bool bSuccess = aSignatureManager.add(xCertificate, xSecurityContext, "", nSecurityId, true); + if (!bSuccess) + return false; + + aSignatureManager.read(/*bUseTempStream=*/true, /*bCacheLastSignature=*/false); + aSignatureManager.write(true); + + if (xStorage.is() && !xStream.is()) + { + uno::Reference<embed::XTransactedObject> xTransaction(xStorage, uno::UNO_QUERY); + xTransaction->commit(); + } + + return true; +} + +extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface* +com_sun_star_security_DocumentDigitalSignatures_get_implementation( + uno::XComponentContext* pCtx, uno::Sequence<uno::Any> const& /*rSeq*/) +{ + return cppu::acquire( + new DocumentDigitalSignatures(uno::Reference<uno::XComponentContext>(pCtx))); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/dialogs/certificatechooser.cxx b/xmlsecurity/source/dialogs/certificatechooser.cxx new file mode 100644 index 0000000000..9dba3e9e90 --- /dev/null +++ b/xmlsecurity/source/dialogs/certificatechooser.cxx @@ -0,0 +1,377 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <config_gpgme.h> +#include <certificatechooser.hxx> +#include <certificateviewer.hxx> +#include <com/sun/star/xml/crypto/XSecurityEnvironment.hpp> +#include <com/sun/star/xml/crypto/XXMLSecurityContext.hpp> +#include <comphelper/sequence.hxx> +#include <comphelper/xmlsechelper.hxx> + +#include <com/sun/star/security/NoPasswordException.hpp> +#include <com/sun/star/security/CertificateCharacters.hpp> + +#include <o3tl/safeint.hxx> +#include <unotools/datetime.hxx> +#include <unotools/charclass.hxx> + + +#include <resourcemanager.hxx> +#include <strings.hrc> + +using namespace comphelper; +using namespace css; + +CertificateChooser::CertificateChooser(weld::Window* _pParent, + std::vector< css::uno::Reference< css::xml::crypto::XXMLSecurityContext > > && rxSecurityContexts, + UserAction eAction) + : GenericDialogController(_pParent, "xmlsec/ui/selectcertificatedialog.ui", "SelectCertificateDialog") + , meAction(eAction) + , m_xFTSign(m_xBuilder->weld_label("sign")) + , m_xFTEncrypt(m_xBuilder->weld_label("encrypt")) + , m_xCertLB(m_xBuilder->weld_tree_view("signatures")) + , m_xViewBtn(m_xBuilder->weld_button("viewcert")) + , m_xOKBtn(m_xBuilder->weld_button("ok")) + , m_xFTDescription(m_xBuilder->weld_label("description-label")) + , m_xDescriptionED(m_xBuilder->weld_entry("description")) + , m_xSearchBox(m_xBuilder->weld_entry("searchbox")) + , m_xReloadBtn(m_xBuilder->weld_button("reloadcert")) +{ + auto nControlWidth = m_xCertLB->get_approximate_digit_width() * 105; + m_xCertLB->set_size_request(nControlWidth, m_xCertLB->get_height_rows(12)); + m_xCertLB->make_sorted(); + + m_xCertLB->connect_changed( LINK( this, CertificateChooser, CertificateHighlightHdl ) ); + m_xCertLB->connect_row_activated( LINK( this, CertificateChooser, CertificateSelectHdl ) ); + m_xViewBtn->connect_clicked( LINK( this, CertificateChooser, ViewButtonHdl ) ); + m_xSearchBox->connect_changed(LINK(this, CertificateChooser, SearchModifyHdl)); + m_xReloadBtn->connect_clicked( LINK( this, CertificateChooser, ReloadButtonHdl ) ); + + mxSecurityContexts = std::move(rxSecurityContexts); + mbInitialized = false; + + // disable buttons + CertificateHighlightHdl(*m_xCertLB); +} + +CertificateChooser::~CertificateChooser() +{ +} + +short CertificateChooser::run() +{ + // #i48432# + // We can't check for personal certificates before raising this dialog, + // because the mozilla implementation throws a NoPassword exception, + // if the user pressed cancel, and also if the database does not exist! + // But in the later case, the is no password query, and the user is confused + // that nothing happens when pressing "Add..." in the SignatureDialog. + + // PostUserEvent( LINK( this, CertificateChooser, Initialize ) ); + + // PostUserLink behavior is too slow, so do it directly before Execute(). + // Problem: This Dialog should be visible right now, and the parent should not be accessible. + // Show, Update, DisableInput... + + m_xDialog->show(); + ImplInitialize(); + return GenericDialogController::run(); +} + +void CertificateChooser::HandleOneUsageBit(OUString& string, int& bits, int bit, TranslateId pResId) +{ + if (bits & bit) + { + if (!string.isEmpty()) + string += ", "; + string += XsResId(pResId); + bits &= ~bit; + } +} + +OUString CertificateChooser::UsageInClearText(int bits) +{ + OUString result; + + HandleOneUsageBit(result, bits, 0x80, STR_DIGITAL_SIGNATURE); + HandleOneUsageBit(result, bits, 0x40, STR_NON_REPUDIATION); + HandleOneUsageBit(result, bits, 0x20, STR_KEY_ENCIPHERMENT); + HandleOneUsageBit(result, bits, 0x10, STR_DATA_ENCIPHERMENT); + HandleOneUsageBit(result, bits, 0x08, STR_KEY_AGREEMENT); + HandleOneUsageBit(result, bits, 0x04, STR_KEY_CERT_SIGN); + HandleOneUsageBit(result, bits, 0x02, STR_CRL_SIGN); + HandleOneUsageBit(result, bits, 0x01, STR_ENCIPHER_ONLY); + + // Check for mystery leftover bits + if (bits != 0) + { + if (!result.isEmpty()) + result += ", "; + result += "0x" + OUString::number(bits, 16); + } + + return result; +} + +void CertificateChooser::ImplInitialize(bool mbSearch) +{ + if (mbInitialized && !mbSearch) + return; + + m_xCertLB->clear(); + m_xCertLB->freeze(); + + SvtUserOptions aUserOpts; + + SvtSysLocale aSysLocale; + const CharClass& rCharClass = aSysLocale.GetCharClass(); + const OUString aSearchStr(rCharClass.uppercase(m_xSearchBox->get_text())); + + switch (meAction) + { + case UserAction::Sign: + m_xFTSign->show(); + m_xOKBtn->set_label(XsResId(STR_SIGN)); + msPreferredKey = aUserOpts.GetSigningKey(); + break; + + case UserAction::SelectSign: + m_xFTSign->show(); + m_xOKBtn->set_label(XsResId(STR_SELECTSIGN)); + msPreferredKey = aUserOpts.GetSigningKey(); + break; + + case UserAction::Encrypt: + m_xFTEncrypt->show(); + m_xFTDescription->hide(); + m_xDescriptionED->hide(); + m_xCertLB->set_selection_mode(SelectionMode::Multiple); + m_xOKBtn->set_label(XsResId(STR_ENCRYPT)); + msPreferredKey = aUserOpts.GetEncryptionKey(); + break; + + } + + ::std::optional<int> oSelectRow; + uno::Sequence<uno::Reference< security::XCertificate>> xCerts; + for (auto& secContext : mxSecurityContexts) + { + if (!secContext.is()) + continue; + auto secEnvironment = secContext->getSecurityEnvironment(); + if (!secEnvironment.is()) + continue; + + try + { + if (xMemCerts.count(secContext)) + { + xCerts = xMemCerts[secContext]; + } + else + { + if (meAction == UserAction::Sign || meAction == UserAction::SelectSign) + xCerts = secEnvironment->getPersonalCertificates(); + else + xCerts = secEnvironment->getAllCertificates(); + + for (sal_Int32 nCert = xCerts.getLength(); nCert;) + { + uno::Reference< security::XCertificate > xCert = xCerts[ --nCert ]; + // Check if we have a private key for this... + tools::Long nCertificateCharacters = secEnvironment->getCertificateCharacters(xCert); + + if (!(nCertificateCharacters & security::CertificateCharacters::HAS_PRIVATE_KEY)) + { + ::comphelper::removeElementAt( xCerts, nCert ); + } + } + xMemCerts[secContext] = xCerts; + } + } + catch (security::NoPasswordException&) + { + } + + // fill list of certificates; the first entry will be selected + for (const auto& xCert : std::as_const(xCerts)) + { + std::shared_ptr<UserData> userData = std::make_shared<UserData>(); + userData->xCertificate = xCert; + userData->xSecurityContext = secContext; + userData->xSecurityEnvironment = secEnvironment; + mvUserData.push_back(userData); + + OUString sIssuer = xmlsec::GetContentPart( xCert->getIssuerName(), xCert->getCertificateKind()); + OUString sExpDate = utl::GetDateString(xCert->getNotValidAfter()); + + // If we are searching and there is no match skip + if (mbSearch + && rCharClass.uppercase(sIssuer).indexOf(aSearchStr) < 0 + && rCharClass.uppercase(sIssuer).indexOf(aSearchStr) < 0 + && !aSearchStr.isEmpty()) + continue; + + m_xCertLB->append(); + int nRow = m_xCertLB->n_children() - 1; + OUString sId(weld::toId(userData.get())); + m_xCertLB->set_id(nRow, sId); + m_xCertLB->set_text(nRow, xmlsec::GetContentPart(xCert->getSubjectName(), xCert->getCertificateKind()), 0); + m_xCertLB->set_text(nRow, sIssuer, 1); + m_xCertLB->set_text(nRow, sExpDate, 2); + +#if HAVE_FEATURE_GPGME + // only GPG has preferred keys + if ( !sIssuer.isEmpty() && !msPreferredKey.isEmpty() ) { + if ( sIssuer == msPreferredKey ) + { + if ( meAction == UserAction::Sign || meAction == UserAction::SelectSign ) + { + oSelectRow.emplace(nRow); + } + else if ( meAction == UserAction::Encrypt && + aUserOpts.GetEncryptToSelf() ) + mxEncryptToSelf = xCert; + } + } +#endif + } + } + + m_xCertLB->thaw(); + m_xCertLB->unselect_all(); + + if (oSelectRow) + { + m_xCertLB->select(*oSelectRow); + } + + CertificateHighlightHdl(*m_xCertLB); + mbInitialized = true; +} + +uno::Sequence<uno::Reference< css::security::XCertificate > > CertificateChooser::GetSelectedCertificates() +{ + std::vector< uno::Reference< css::security::XCertificate > > aRet; + if (meAction == UserAction::Encrypt) + { + // for encryption, multiselection is enabled + m_xCertLB->selected_foreach([this, &aRet](weld::TreeIter& rEntry){ + UserData* userData = weld::fromId<UserData*>(m_xCertLB->get_id(rEntry)); + aRet.push_back( userData->xCertificate ); + return false; + }); + } + else + { + uno::Reference< css::security::XCertificate > xCert; + int nSel = m_xCertLB->get_selected_index(); + if (nSel != -1) + { + UserData* userData = weld::fromId<UserData*>(m_xCertLB->get_id(nSel)); + xCert = userData->xCertificate; + } + aRet.push_back( xCert ); + } + +#if HAVE_FEATURE_GPGME + if ( mxEncryptToSelf.is()) + aRet.push_back( mxEncryptToSelf ); +#endif + + return comphelper::containerToSequence(aRet); +} + +uno::Reference<xml::crypto::XXMLSecurityContext> CertificateChooser::GetSelectedSecurityContext() const +{ + int nSel = m_xCertLB->get_selected_index(); + if (nSel == -1) + return uno::Reference<xml::crypto::XXMLSecurityContext>(); + + UserData* userData = weld::fromId<UserData*>(m_xCertLB->get_id(nSel)); + uno::Reference<xml::crypto::XXMLSecurityContext> xCert = userData->xSecurityContext; + return xCert; +} + +OUString CertificateChooser::GetDescription() const +{ + return m_xDescriptionED->get_text(); +} + +OUString CertificateChooser::GetUsageText() +{ + uno::Sequence< uno::Reference<css::security::XCertificate> > xCerts = + GetSelectedCertificates(); + return (xCerts.hasElements() && xCerts[0].is()) ? + UsageInClearText(xCerts[0]->getCertificateUsage()) : OUString(); +} + +void CertificateChooser::ImplReloadCertificates() +{ + xMemCerts.clear(); +} + +IMPL_LINK_NOARG(CertificateChooser, ReloadButtonHdl, weld::Button&, void) +{ + ImplReloadCertificates(); + mbInitialized = false; + ImplInitialize(); +} + +IMPL_LINK_NOARG(CertificateChooser, SearchModifyHdl, weld::Entry&, void) +{ + ImplInitialize(true); +} + +IMPL_LINK_NOARG(CertificateChooser, CertificateHighlightHdl, weld::TreeView&, void) +{ + bool bEnable = m_xCertLB->get_selected_index() != -1; + m_xViewBtn->set_sensitive(bEnable); + m_xOKBtn->set_sensitive(bEnable); + m_xDescriptionED->set_sensitive(bEnable); +} + +IMPL_LINK_NOARG(CertificateChooser, CertificateSelectHdl, weld::TreeView&, bool) +{ + m_xDialog->response(RET_OK); + return true; +} + +IMPL_LINK_NOARG(CertificateChooser, ViewButtonHdl, weld::Button&, void) +{ + ImplShowCertificateDetails(); +} + +void CertificateChooser::ImplShowCertificateDetails() +{ + int nSel = m_xCertLB->get_selected_index(); + if (nSel == -1) + return; + + UserData* userData = weld::fromId<UserData*>(m_xCertLB->get_id(nSel)); + + if (!userData->xSecurityEnvironment.is() || !userData->xCertificate.is()) + return; + + CertificateViewer aViewer(m_xDialog.get(), userData->xSecurityEnvironment, userData->xCertificate, true, this); + aViewer.run(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/dialogs/certificateviewer.cxx b/xmlsecurity/source/dialogs/certificateviewer.cxx new file mode 100644 index 0000000000..62de673c00 --- /dev/null +++ b/xmlsecurity/source/dialogs/certificateviewer.cxx @@ -0,0 +1,377 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include <string_view> + +#include <certificatechooser.hxx> +#include <certificateviewer.hxx> +#include <com/sun/star/security/XCertificate.hpp> + +#include <com/sun/star/security/CertificateCharacters.hpp> +#include <com/sun/star/xml/crypto/XSecurityEnvironment.hpp> +#include <com/sun/star/security/CertificateValidity.hpp> + +#include <unotools/localedatawrapper.hxx> +#include <unotools/datetime.hxx> + +#include <strings.hrc> +#include <resourcemanager.hxx> +#include <comphelper/xmlsechelper.hxx> +#include <tools/datetime.hxx> +#include <bitmaps.hlst> + +#include <vcl/settings.hxx> +#include <vcl/svapp.hxx> + +using namespace comphelper; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + +CertificateViewer::CertificateViewer(weld::Window* _pParent, + const css::uno::Reference< css::xml::crypto::XSecurityEnvironment >& _rxSecurityEnvironment, + const css::uno::Reference< css::security::XCertificate >& _rXCert, bool bCheckForPrivateKey, + CertificateChooser* pParentChooser) + : GenericDialogController(_pParent, "xmlsec/ui/viewcertdialog.ui", "ViewCertDialog") + , mbCheckForPrivateKey(bCheckForPrivateKey) + , mpParentChooser(pParentChooser) + , mxTabCtrl(m_xBuilder->weld_notebook("tabcontrol")) +{ + mxTabCtrl->connect_enter_page(LINK(this, CertificateViewer, ActivatePageHdl)); + + mxSecurityEnvironment = _rxSecurityEnvironment; + mxCert = _rXCert; + + mxGeneralPage.reset(new CertificateViewerGeneralTP(mxTabCtrl->get_page("general"), this)); + mxDetailsPage.reset(new CertificateViewerDetailsTP(mxTabCtrl->get_page("details"), this)); + if (!mxSecurityEnvironment->buildCertificatePath(mxCert).hasElements()) + mxTabCtrl->remove_page("path"); + else + mxPathId.reset(new CertificateViewerCertPathTP(mxTabCtrl->get_page("path"), this)); + mxTabCtrl->set_current_page("general"); +} + +IMPL_LINK(CertificateViewer, ActivatePageHdl, const OUString&, rPage, void) +{ + if (rPage == "path") + mxPathId->ActivatePage(); +} + +CertificateViewerTP::CertificateViewerTP(weld::Container* pParent, const OUString& rUIXMLDescription, + const OUString& rID, CertificateViewer* pDlg) + : mxBuilder(Application::CreateBuilder(pParent, rUIXMLDescription)) + , mxContainer(mxBuilder->weld_container(rID)) + , mpDlg(pDlg) +{ +} + +CertificateViewerGeneralTP::CertificateViewerGeneralTP(weld::Container* pParent, CertificateViewer* pDlg) + : CertificateViewerTP(pParent, "xmlsec/ui/certgeneral.ui", "CertGeneral", pDlg) + , m_xCertImg(mxBuilder->weld_image("certimage")) + , m_xHintNotTrustedFT(mxBuilder->weld_label("hintnotrust")) + , m_xIssuedToLabelFT(mxBuilder->weld_label("issued_to")) + , m_xIssuedToFT(mxBuilder->weld_label("issued_to_value")) + , m_xIssuedByLabelFT(mxBuilder->weld_label("issued_by")) + , m_xIssuedByFT(mxBuilder->weld_label("issued_by_value")) + , m_xValidFromDateFT(mxBuilder->weld_label("valid_from_value")) + , m_xValidToDateFT(mxBuilder->weld_label("valid_to_value")) + , m_xKeyImg(mxBuilder->weld_image("keyimage")) + , m_xHintCorrespPrivKeyFT(mxBuilder->weld_label("privatekey")) +{ + //Verify the certificate + sal_Int32 certStatus = mpDlg->mxSecurityEnvironment->verifyCertificate(mpDlg->mxCert, + Sequence<Reference<css::security::XCertificate> >()); + + bool bCertValid = certStatus == css::security::CertificateValidity::VALID; + + if ( !bCertValid ) + { + m_xCertImg->set_from_icon_name(BMP_STATE_NOT_VALIDATED); + m_xHintNotTrustedFT->set_label(XsResId(STR_CERTIFICATE_NOT_VALIDATED)); + } + + // insert data + css::uno::Reference< css::security::XCertificate > xCert = mpDlg->mxCert; + + OUString sSubjectName(xmlsec::GetContentPart(xCert->getSubjectName(), xCert->getCertificateKind())); + if (!sSubjectName.isEmpty()) + m_xIssuedToFT->set_label(sSubjectName); + else + m_xIssuedToLabelFT->hide(); + OUString sIssuerName(xmlsec::GetContentPart(xCert->getIssuerName(), xCert->getCertificateKind())); + if (!sIssuerName.isEmpty()) + m_xIssuedByFT->set_label(sIssuerName); + else + m_xIssuedByLabelFT->hide(); + + DateTime aDateTimeStart( DateTime::EMPTY ); + DateTime aDateTimeEnd( DateTime::EMPTY ); + utl::typeConvert( xCert->getNotValidBefore(), aDateTimeStart ); + utl::typeConvert( xCert->getNotValidAfter(), aDateTimeEnd ); + + OUString sValidFromDate = Application::GetSettings().GetUILocaleDataWrapper().getDate(Date(aDateTimeStart.GetDate())); + OUString sValidToDate = Application::GetSettings().GetUILocaleDataWrapper().getDate(Date(aDateTimeEnd.GetDate())); + + m_xValidFromDateFT->set_label(sValidFromDate); + m_xValidToDateFT->set_label(sValidToDate); + + // Check if we have the private key... + bool bHasPrivateKey = false; + // #i41270# Check only if we have that certificate in our security environment + if (pDlg->mbCheckForPrivateKey) + { + tools::Long nCertificateCharacters = pDlg->mxSecurityEnvironment->getCertificateCharacters(xCert); + bHasPrivateKey = (nCertificateCharacters & security::CertificateCharacters::HAS_PRIVATE_KEY); + } + if (!bHasPrivateKey) + { + m_xKeyImg->hide(); + m_xHintCorrespPrivKeyFT->hide(); + } +} + +void CertificateViewerDetailsTP::InsertElement(const OUString& rField, const OUString& rValue, + const OUString& rDetails, bool bFixedWidthFont) +{ + m_aUserData.emplace_back(std::make_unique<Details_UserDatat>(rDetails, bFixedWidthFont)); + OUString sId(weld::toId(m_aUserData.back().get())); + m_xElementsLB->append(sId, rField); + m_xElementsLB->set_text(m_xElementsLB->n_children() -1, rValue, 1); +} + +CertificateViewerDetailsTP::CertificateViewerDetailsTP(weld::Container* pParent, CertificateViewer* pDlg) + : CertificateViewerTP(pParent, "xmlsec/ui/certdetails.ui", "CertDetails", pDlg) + , m_xElementsLB(mxBuilder->weld_tree_view("tablecontainer")) + , m_xValueDetails(mxBuilder->weld_text_view("valuedetails")) +{ + const int nWidth = m_xElementsLB->get_approximate_digit_width() * 60; + const int nHeight = m_xElementsLB->get_height_rows(8); + m_xElementsLB->set_size_request(nWidth, nHeight); + m_xValueDetails->set_size_request(nWidth, nHeight); + m_xElementsLB->set_column_fixed_widths( { nWidth / 2 } ); + + // fill list box + Reference< security::XCertificate > xCert = mpDlg->mxCert; + sal_uInt16 nLineBreak = 16; + const char* const pHexSep = " "; + OUString aLBEntry; + OUString aDetails; + // Certificate Versions are reported wrong (#i35107#) - 0 == "V1", 1 == "V2", ..., n = "V(n+1)" + aLBEntry = "V" + OUString::number( xCert->getVersion() + 1 ); + InsertElement( XsResId( STR_VERSION ), aLBEntry, aLBEntry ); + Sequence< sal_Int8 > aSeq = xCert->getSerialNumber(); + aLBEntry = xmlsec::GetHexString( aSeq, pHexSep ); + aDetails = xmlsec::GetHexString( aSeq, pHexSep, nLineBreak ); + InsertElement( XsResId( STR_SERIALNUM ), aLBEntry, aDetails, true ); + + std::pair< OUString, OUString> pairIssuer = + xmlsec::GetDNForCertDetailsView(xCert->getIssuerName()); + aLBEntry = pairIssuer.first; + aDetails = pairIssuer.second; + InsertElement( XsResId( STR_ISSUER ), aLBEntry, aDetails ); + + DateTime aDateTime( DateTime::EMPTY ); + utl::typeConvert( xCert->getNotValidBefore(), aDateTime ); + aLBEntry = Application::GetSettings().GetUILocaleDataWrapper().getDate(Date(aDateTime.GetDate())) + " "; + aLBEntry += Application::GetSettings().GetUILocaleDataWrapper().getTime(tools::Time(aDateTime.GetTime())); + InsertElement( XsResId( STR_VALIDFROM ), aLBEntry, aLBEntry ); + utl::typeConvert( xCert->getNotValidAfter(), aDateTime ); + aLBEntry = Application::GetSettings().GetUILocaleDataWrapper().getDate(Date(aDateTime.GetDate()) ) + " "; + aLBEntry += Application::GetSettings().GetUILocaleDataWrapper().getTime(tools::Time(aDateTime.GetTime())); + InsertElement( XsResId( STR_VALIDTO ), aLBEntry, aLBEntry ); + + std::pair< OUString, OUString > pairSubject = + xmlsec::GetDNForCertDetailsView(xCert->getSubjectName()); + aLBEntry = pairSubject.first; + aDetails = pairSubject.second; + InsertElement( XsResId( STR_SUBJECT ), aLBEntry, aDetails ); + + aLBEntry = aDetails = xCert->getSubjectPublicKeyAlgorithm(); + InsertElement( XsResId( STR_SUBJECT_PUBKEY_ALGO ), aLBEntry, aDetails ); + aSeq = xCert->getSubjectPublicKeyValue(); + aLBEntry = xmlsec::GetHexString( aSeq, pHexSep ); + aDetails = xmlsec::GetHexString( aSeq, pHexSep, nLineBreak ); + InsertElement( XsResId( STR_SUBJECT_PUBKEY_VAL ), aLBEntry, aDetails, true ); + + aLBEntry = aDetails = xCert->getSignatureAlgorithm(); + InsertElement( XsResId( STR_SIGNATURE_ALGO ), aLBEntry, aDetails ); + + CertificateChooser* pChooser = mpDlg->GetParentChooser(); + if (pChooser) + { + aLBEntry = CertificateChooser::UsageInClearText( mpDlg->mxCert->getCertificateUsage() ); + InsertElement( XsResId( STR_USE ), aLBEntry, aLBEntry ); + } + + aSeq = xCert->getSHA1Thumbprint(); + aLBEntry = xmlsec::GetHexString( aSeq, pHexSep ); + aDetails = xmlsec::GetHexString( aSeq, pHexSep, nLineBreak ); + InsertElement( XsResId( STR_THUMBPRINT_SHA1 ), aLBEntry, aDetails, true ); + + aSeq = xCert->getMD5Thumbprint(); + aLBEntry = xmlsec::GetHexString( aSeq, pHexSep ); + aDetails = xmlsec::GetHexString( aSeq, pHexSep, nLineBreak ); + InsertElement( XsResId( STR_THUMBPRINT_MD5 ), aLBEntry, aDetails, true ); + + m_xElementsLB->connect_changed(LINK(this, CertificateViewerDetailsTP, ElementSelectHdl)); +} + +IMPL_LINK_NOARG(CertificateViewerDetailsTP, ElementSelectHdl, weld::TreeView&, void) +{ + int nEntry = m_xElementsLB->get_selected_index(); + OUString aElementText; + bool bFixedWidthFont; + if (nEntry != -1) + { + const Details_UserDatat* p = weld::fromId<Details_UserDatat*>(m_xElementsLB->get_id(nEntry)); + aElementText = p->maTxt; + bFixedWidthFont = p->mbFixedWidthFont; + } + else + bFixedWidthFont = false; + + m_xValueDetails->set_monospace(bFixedWidthFont); + m_xValueDetails->set_text(aElementText); +} + +CertificateViewerCertPathTP::CertificateViewerCertPathTP(weld::Container* pParent, CertificateViewer* pDlg) + : CertificateViewerTP(pParent, "xmlsec/ui/certpage.ui", "CertPage", pDlg) + , mpParent(pDlg) + , mbFirstActivateDone(false) + , mxCertPathLB(mxBuilder->weld_tree_view("signatures")) + , mxScratchIter(mxCertPathLB->make_iterator()) + , mxViewCertPB(mxBuilder->weld_button("viewcert")) + , mxCertStatusML(mxBuilder->weld_text_view("status")) + , mxCertOK(mxBuilder->weld_label("certok")) + , mxCertNotValidated(mxBuilder->weld_label("certnotok")) +{ + const int nWidth = mxCertPathLB->get_approximate_digit_width() * 60; + const int nHeight = mxCertPathLB->get_height_rows(6); + mxCertPathLB->set_size_request(nWidth, nHeight); + mxCertStatusML->set_size_request(nWidth, nHeight); + + mxCertPathLB->connect_changed( LINK( this, CertificateViewerCertPathTP, CertSelectHdl ) ); + mxViewCertPB->connect_clicked( LINK( this, CertificateViewerCertPathTP, ViewCertHdl ) ); +} + +CertificateViewerCertPathTP::~CertificateViewerCertPathTP() +{ + if (mxCertificateViewer) + mxCertificateViewer->response(RET_OK); +} + +void CertificateViewerCertPathTP::ActivatePage() +{ + if ( mbFirstActivateDone ) + return; + + mbFirstActivateDone = true; + Sequence< Reference< security::XCertificate > > aCertPath = + mpParent->mxSecurityEnvironment->buildCertificatePath( mpParent->mxCert ); + const Reference< security::XCertificate >* pCertPath = aCertPath.getConstArray(); + + sal_Int32 i, nCnt = aCertPath.getLength(); + std::unique_ptr<weld::TreeIter> xParent; + for (i = nCnt-1; i >= 0; i--) + { + const Reference< security::XCertificate > rCert = pCertPath[ i ]; + OUString sName = xmlsec::GetContentPart( rCert->getSubjectName(), rCert->getCertificateKind() ); + //Verify the certificate + sal_Int32 certStatus = mpDlg->mxSecurityEnvironment->verifyCertificate(rCert, + Sequence<Reference<css::security::XCertificate> >()); + bool bCertValid = certStatus == css::security::CertificateValidity::VALID; + InsertCert(xParent.get(), sName, rCert, bCertValid); + if (!xParent) + { + xParent = mxCertPathLB->make_iterator(); + (void)mxCertPathLB->get_iter_first(*xParent); + } + else + { + (void)mxCertPathLB->iter_children(*xParent); + } + } + + if (xParent) + mxCertPathLB->select(*xParent); + mxViewCertPB->set_sensitive(false); // Own certificate selected + + while (xParent) + { + mxCertPathLB->expand_row(*xParent); + if (!mxCertPathLB->iter_parent(*xParent)) + xParent.reset(); + } + + CertSelectHdl(*mxCertPathLB); +} + +IMPL_LINK_NOARG(CertificateViewerCertPathTP, ViewCertHdl, weld::Button&, void) +{ + std::unique_ptr<weld::TreeIter> xIter = mxCertPathLB->make_iterator(); + if (mxCertPathLB->get_selected(xIter.get())) + { + if (mxCertificateViewer) + mxCertificateViewer->response(RET_OK); + + CertPath_UserData* pData = weld::fromId<CertPath_UserData*>(mxCertPathLB->get_id(*xIter)); + mxCertificateViewer = std::make_shared<CertificateViewer>(mpDlg->getDialog(), mpDlg->mxSecurityEnvironment, + pData->mxCert, false, nullptr); + weld::DialogController::runAsync(mxCertificateViewer, [this] (sal_Int32) { mxCertificateViewer = nullptr; }); + } +} + +IMPL_LINK_NOARG(CertificateViewerCertPathTP, CertSelectHdl, weld::TreeView&, void) +{ + OUString sStatus; + + std::unique_ptr<weld::TreeIter> xIter = mxCertPathLB->make_iterator(); + bool bEntry = mxCertPathLB->get_selected(xIter.get()); + if (bEntry) + { + CertPath_UserData* pData = weld::fromId<CertPath_UserData*>(mxCertPathLB->get_id(*xIter)); + if (pData) + sStatus = pData->mbValid ? mxCertOK->get_label() : mxCertNotValidated->get_label(); + } + + mxCertStatusML->set_text(sStatus); + + bool bSensitive = false; + if (bEntry) + { + // if has children, so not the last one in the chain + if (mxCertPathLB->iter_children(*xIter)) + bSensitive = true; + } + mxViewCertPB->set_sensitive(bSensitive); +} + +void CertificateViewerCertPathTP::InsertCert(const weld::TreeIter* pParent, const OUString& rName, + const css::uno::Reference< css::security::XCertificate >& rxCert, + bool bValid) +{ + auto const sImage = bValid ? std::u16string_view(u"" BMP_CERT_OK) : std::u16string_view(u"" BMP_CERT_NOT_OK); + maUserData.emplace_back(std::make_unique<CertPath_UserData>(rxCert, bValid)); + OUString sId(weld::toId(maUserData.back().get())); + mxCertPathLB->insert(pParent, -1, &rName, &sId, nullptr, nullptr, false, mxScratchIter.get()); + mxCertPathLB->set_image(*mxScratchIter, OUString(sImage)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx b/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx new file mode 100644 index 0000000000..3cd13c6060 --- /dev/null +++ b/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx @@ -0,0 +1,826 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <rtl/ustring.hxx> +#include <sal/config.h> + +#include <string_view> + +#include <digitalsignaturesdialog.hxx> +#include <certificatechooser.hxx> +#include <certificateviewer.hxx> +#include <biginteger.hxx> +#include <sax/tools/converter.hxx> +#include <comphelper/diagnose_ex.hxx> +#include <comphelper/configuration.hxx> +#include <officecfg/Office/Common.hxx> + +#include <com/sun/star/embed/XStorage.hpp> +#include <com/sun/star/embed/ElementModes.hpp> +#include <com/sun/star/embed/StorageFormats.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/security/NoPasswordException.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/security/CertificateValidity.hpp> +#include <com/sun/star/packages/WrongPasswordException.hpp> +#include <com/sun/star/security/CertificateKind.hpp> +#include <com/sun/star/security/XDocumentDigitalSignatures.hpp> +#include <com/sun/star/system/SystemShellExecute.hpp> +#include <com/sun/star/system/SystemShellExecuteFlags.hpp> +#include <com/sun/star/system/SystemShellExecuteException.hpp> + +#include <osl/file.hxx> +#include <rtl/ustrbuf.hxx> +#include <rtl/uri.hxx> +#include <sal/log.hxx> + +#include <tools/date.hxx> +#include <tools/time.hxx> +#include <unotools/datetime.hxx> + +#include <bitmaps.hlst> +#include <strings.hrc> +#include <resourcemanager.hxx> +#include <comphelper/lok.hxx> +#include <comphelper/xmlsechelper.hxx> +#include <comphelper/processfactory.hxx> + +#include <utility> +#include <vcl/weld.hxx> +#include <vcl/svapp.hxx> +#include <unotools/configitem.hxx> + +#ifdef _WIN32 +#include <o3tl/char16_t2wchar_t.hxx> +#include <systools/win32/comtools.hxx> +#include <Shlobj.h> +#endif + +using namespace comphelper; +using namespace css::security; +using namespace css::uno; +using namespace css; + +namespace +{ + class SaveODFItem: public utl::ConfigItem + { + private: + virtual void ImplCommit() override; + + public: + virtual void Notify( const css::uno::Sequence< OUString >& aPropertyNames ) override; + SaveODFItem(); + }; + + void SaveODFItem::ImplCommit() {} + void SaveODFItem::Notify( const css::uno::Sequence< OUString >& ) {} + + SaveODFItem::SaveODFItem(): utl::ConfigItem("Office.Common/Save") + { + OUString sDef("ODF/DefaultVersion"); + Sequence< css::uno::Any > aValues = GetProperties( Sequence<OUString>(&sDef,1) ); + if ( aValues.getLength() != 1) + throw uno::RuntimeException( + "[xmlsecurity] Could not open property Office.Common/Save/ODF/DefaultVersion", + nullptr); + + sal_Int16 nTmp = 0; + if ( !(aValues[0] >>= nTmp) ) + throw uno::RuntimeException( + "[xmlsecurity]SaveODFItem::SaveODFItem(): Wrong Type!", + nullptr ); + } + +#ifdef _WIN32 + constexpr std::u16string_view aGUIServers[] + = { u"Gpg4win\\kleopatra.exe", + u"Gpg4win\\bin\\kleopatra.exe", + u"GNU\\GnuPG\\kleopatra.exe", + u"GNU\\GnuPG\\launch-gpa.exe", + u"GNU\\GnuPG\\gpa.exe", + u"GnuPG\\bin\\gpa.exe", + u"GNU\\GnuPG\\bin\\kleopatra.exe", + u"GNU\\GnuPG\\bin\\launch-gpa.exe", + u"GNU\\GnuPG\\bin\\gpa.exe"}; +#else + constexpr std::u16string_view aGUIServers[] + = { u"kleopatra", u"seahorse", u"gpa", u"kgpg"}; +#endif + +bool GetPathAllOS(OUString& aPath) +{ +#ifdef _WIN32 + sal::systools::CoTaskMemAllocated<wchar_t> sPath; + HRESULT hr + = SHGetKnownFolderPath(FOLDERID_ProgramFilesX86, KF_FLAG_DEFAULT, nullptr, &sPath); + + if (FAILED(hr)) + return false; + aPath = o3tl::toU(sPath); +#else + const char* cPath = getenv("PATH"); + if (!cPath) + return false; + aPath = OUString(cPath, strlen(cPath), osl_getThreadTextEncoding()); +#endif + return (!aPath.isEmpty()); +} + +void GetCertificateManager(OUString& sExecutable) +{ + OUString aPath, aFoundGUIServer; + if (!GetPathAllOS(aPath)) + return; + + OUString aCetMgrConfig = officecfg::Office::Common::Security::Scripting::CertMgrPath::get(); + if (!aCetMgrConfig.isEmpty()) + { +#ifdef _WIN32 + sal_Int32 nLastBackslashIndex = aCetMgrConfig.lastIndexOf('\\'); +#else + sal_Int32 nLastBackslashIndex = aCetMgrConfig.lastIndexOf('/'); +#endif + osl::FileBase::RC searchError = osl::File::searchFileURL( + aCetMgrConfig.copy(0, nLastBackslashIndex + 1), aPath, + aFoundGUIServer); + if (searchError == osl::FileBase::E_None) + return; + } + + for (const auto& rServer: aGUIServers) + { + osl::FileBase::RC searchError = osl::File::searchFileURL( + OUString(rServer), aPath, + aFoundGUIServer); + if (searchError == osl::FileBase::E_None) + { + osl::File::getSystemPathFromFileURL(aFoundGUIServer, sExecutable); + std::shared_ptr<comphelper::ConfigurationChanges> pBatch( + comphelper::ConfigurationChanges::create()); + officecfg::Office::Common::Security::Scripting::CertMgrPath::set(sExecutable, + pBatch); + pBatch->commit(); + + return; + } + } +} + +bool IsThereCertificateMgr() +{ + OUString sExecutable; + GetCertificateManager(sExecutable); + return (!sExecutable.isEmpty()); +} +}//anonymous namespace + +DigitalSignaturesDialog::DigitalSignaturesDialog( + weld::Window* pParent, + const uno::Reference< uno::XComponentContext >& rxCtx, DocumentSignatureMode eMode, + bool bReadOnly, OUString sODFVersion, bool bHasDocumentSignature) + : GenericDialogController(pParent, "xmlsec/ui/digitalsignaturesdialog.ui", "DigitalSignaturesDialog") + , maSignatureManager(rxCtx, eMode) + , m_sODFVersion (std::move(sODFVersion)) + , m_bHasDocumentSignature(bHasDocumentSignature) + , m_bWarningShowSignMacro(false) + , m_xHintDocFT(m_xBuilder->weld_label("dochint")) + , m_xHintBasicFT(m_xBuilder->weld_label("macrohint")) + , m_xHintPackageFT(m_xBuilder->weld_label("packagehint")) + , m_xSignaturesLB(m_xBuilder->weld_tree_view("signatures")) + , m_xSigsValidImg(m_xBuilder->weld_image("validimg")) + , m_xSigsValidFI(m_xBuilder->weld_label("validft")) + , m_xSigsInvalidImg(m_xBuilder->weld_image("invalidimg")) + , m_xSigsInvalidFI(m_xBuilder->weld_label("invalidft")) + , m_xSigsNotvalidatedImg(m_xBuilder->weld_image("notvalidatedimg")) + , m_xSigsNotvalidatedFI(m_xBuilder->weld_label("notvalidatedft")) + , m_xSigsOldSignatureImg(m_xBuilder->weld_image("oldsignatureimg")) + , m_xSigsOldSignatureFI(m_xBuilder->weld_label("oldsignatureft")) + , m_xViewBtn(m_xBuilder->weld_button("view")) + , m_xAddBtn(m_xBuilder->weld_button("sign")) + , m_xRemoveBtn(m_xBuilder->weld_button("remove")) + , m_xStartCertMgrBtn(m_xBuilder->weld_button("start_certmanager")) + , m_xCloseBtn(m_xBuilder->weld_button("close")) +{ + auto nControlWidth = m_xSignaturesLB->get_approximate_digit_width() * 105; + m_xSignaturesLB->set_size_request(nControlWidth, m_xSignaturesLB->get_height_rows(10)); + + // Give the first column 6 percent, try to distribute the rest equally. + std::vector<int> aWidths; + aWidths.push_back(6*nControlWidth/100); + auto nColWidth = (nControlWidth - aWidths[0]) / 4; + aWidths.push_back(nColWidth); + aWidths.push_back(nColWidth); + aWidths.push_back(nColWidth); + m_xSignaturesLB->set_column_fixed_widths(aWidths); + + mbVerifySignatures = true; + mbSignaturesChanged = false; + + m_xSignaturesLB->connect_changed( LINK( this, DigitalSignaturesDialog, SignatureHighlightHdl ) ); + m_xSignaturesLB->connect_row_activated( LINK( this, DigitalSignaturesDialog, SignatureSelectHdl ) ); + + m_xViewBtn->connect_clicked( LINK( this, DigitalSignaturesDialog, ViewButtonHdl ) ); + m_xViewBtn->set_sensitive(false); + + m_xAddBtn->connect_clicked( LINK( this, DigitalSignaturesDialog, AddButtonHdl ) ); + if ( bReadOnly ) + m_xAddBtn->set_sensitive(false); + + m_xRemoveBtn->connect_clicked( LINK( this, DigitalSignaturesDialog, RemoveButtonHdl ) ); + m_xRemoveBtn->set_sensitive(false); + + m_xStartCertMgrBtn->connect_clicked( LINK( this, DigitalSignaturesDialog, CertMgrButtonHdl ) ); + + m_xCloseBtn->connect_clicked( LINK( this, DigitalSignaturesDialog, OKButtonHdl) ); + + switch( maSignatureManager.getSignatureMode() ) + { + case DocumentSignatureMode::Content: + m_xHintDocFT->show(); + break; + case DocumentSignatureMode::Macros: + m_xHintBasicFT->show(); + break; + case DocumentSignatureMode::Package: + m_xHintPackageFT->show(); + break; + } + + if (comphelper::LibreOfficeKit::isActive()) + { + m_xAddBtn->hide(); + m_xRemoveBtn->hide(); + m_xStartCertMgrBtn->hide(); + } + + if (!IsThereCertificateMgr()) + { + m_xStartCertMgrBtn->set_sensitive(false); + } +} + +DigitalSignaturesDialog::~DigitalSignaturesDialog() +{ + if (m_xViewer) + m_xViewer->response(RET_OK); + + if (m_xInfoBox) + m_xInfoBox->response(RET_OK); +} + +bool DigitalSignaturesDialog::Init() +{ + bool bInit = maSignatureManager.init(); + + SAL_WARN_IF( !bInit, "xmlsecurity.dialogs", "Error initializing security context!" ); + + if ( bInit ) + { + maSignatureManager.getSignatureHelper().SetStartVerifySignatureHdl( LINK( this, DigitalSignaturesDialog, StartVerifySignatureHdl ) ); + } + + return bInit; +} + +void DigitalSignaturesDialog::SetStorage( const css::uno::Reference < css::embed::XStorage >& rxStore ) +{ + if (!rxStore.is()) + { + // PDF supports AdES. + m_bAdESCompliant = true; + return; + } + + // only ODF 1.1 wants to be non-XAdES (m_sODFVersion="1.0" for OOXML somehow?) + m_bAdESCompliant = !rxStore->hasByName("META-INF") // it's a Zip storage + || !DocumentSignatureHelper::isODFPre_1_2(m_sODFVersion); + + maSignatureManager.setStore(rxStore); + maSignatureManager.getSignatureHelper().SetStorage( maSignatureManager.getStore(), m_sODFVersion); +} + +void DigitalSignaturesDialog::SetSignatureStream( const css::uno::Reference < css::io::XStream >& rxStream ) +{ + maSignatureManager.setSignatureStream(rxStream); +} + +bool DigitalSignaturesDialog::canAddRemove() +{ + //FIXME: this func needs some cleanup, such as real split between + //'canAdd' and 'canRemove' case + uno::Reference<container::XNameAccess> xNameAccess = maSignatureManager.getStore(); + if (xNameAccess.is() && xNameAccess->hasByName("[Content_Types].xml")) + // It's always possible to append an OOXML signature. + return true; + + if (!maSignatureManager.getStore().is()) + // It's always possible to append a PDF signature. + return true; + + OSL_ASSERT(maSignatureManager.getStore().is()); + bool bDoc1_1 = DocumentSignatureHelper::isODFPre_1_2(m_sODFVersion); + SaveODFItem item; + + // see specification + //cvs: specs/www/appwide/security/Electronic_Signatures_and_Security.sxw + //Paragraph 'Behavior with regard to ODF 1.2' + //For both, macro and document + if ( bDoc1_1 ) + { + //#4 + std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Warning, VclButtonsType::Ok, + XsResId(STR_XMLSECDLG_OLD_ODF_FORMAT))); + xBox->run(); + return false; + } + + //As of OOo 3.2 the document signature includes in macrosignatures.xml. That is + //adding a macro signature will break an existing document signature. + //The sfx2 will remove the documentsignature when the user adds a macro signature + if (maSignatureManager.getSignatureMode() == DocumentSignatureMode::Macros) + { + if (m_bHasDocumentSignature && !m_bWarningShowSignMacro) + { + //The warning says that the document signatures will be removed if the user + //continues. He can then either press 'OK' or 'NO' + //It the user presses 'Add' or 'Remove' several times then, then the warning + //is shown every time until the user presses 'OK'. From then on, the warning + //is not displayed anymore as long as the signatures dialog is alive. + std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog( + m_xDialog.get(), VclMessageType::Question, VclButtonsType::YesNo, + XsResId(STR_XMLSECDLG_QUERY_REMOVEDOCSIGNBEFORESIGN))); + if (xBox->run() == RET_NO) + return false; + + m_bWarningShowSignMacro = true; + } + } + return true; +} + +bool DigitalSignaturesDialog::canAdd() { return canAddRemove(); } + +bool DigitalSignaturesDialog::canRemove() +{ + bool bRet = true; + + if ( maSignatureManager.getSignatureMode() == DocumentSignatureMode::Content ) + { + std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Question, VclButtonsType::YesNo, + XsResId(STR_XMLSECDLG_QUERY_REALLYREMOVE))); + short nDlgRet = xBox->run(); + bRet = ( nDlgRet == RET_YES ); + } + + return (bRet && canAddRemove()); +} + +void DigitalSignaturesDialog::beforeRun() +{ + // Verify Signatures and add certificates to ListBox... + mbVerifySignatures = true; + ImplGetSignatureInformations(/*bUseTempStream=*/false, /*bCacheLastSignature=*/true); + ImplFillSignaturesBox(); + + // FIXME: Disable the "Use XAdES compliant signatures" checkbox if it is irrelevant. If it is + // enabled, set its initial state based on existing signatures, if any. + + // If it is OOXML, the checkbox is irrelevant. + + // How to find out here whether it is OOXML? I don't want to create a SignatureStreamHelper and + // check its nStorageFormat as that seems overly complicated and seems to have weird indirect + // consequences, as I noticed when I tried to use DocumentSignatureManager::IsXAdESRelevant() + // (which now is in #if 0). + + if (!maSignatureManager.getCurrentSignatureInformations().empty()) + { + // If the document has only SHA-1 signatures we probably want it to stay that way? + } + + // Only verify once, content will not change. + // But for refreshing signature information, StartVerifySignatureHdl will be called after each add/remove + mbVerifySignatures = false; +} + +short DigitalSignaturesDialog::run() +{ + beforeRun(); + return GenericDialogController::run(); +} + +IMPL_LINK_NOARG(DigitalSignaturesDialog, SignatureHighlightHdl, weld::TreeView&, void) +{ + bool bSel = m_xSignaturesLB->get_selected_index() != -1; + m_xViewBtn->set_sensitive( bSel ); + if ( m_xAddBtn->get_sensitive() ) // not read only + m_xRemoveBtn->set_sensitive( bSel ); +} + +IMPL_LINK_NOARG(DigitalSignaturesDialog, OKButtonHdl, weld::Button&, void) +{ + if (mbSignaturesChanged) + maSignatureManager.write(m_bAdESCompliant); + + m_xDialog->response(RET_OK); +} + +IMPL_LINK_NOARG(DigitalSignaturesDialog, SignatureSelectHdl, weld::TreeView&, bool) +{ + ImplShowSignaturesDetails(); + return true; +} + +IMPL_LINK_NOARG(DigitalSignaturesDialog, ViewButtonHdl, weld::Button&, void) +{ + ImplShowSignaturesDetails(); +} + +IMPL_LINK_NOARG(DigitalSignaturesDialog, AddButtonHdl, weld::Button&, void) +{ + if( ! canAdd()) + return; + try + { + std::vector<uno::Reference<xml::crypto::XXMLSecurityContext>> xSecContexts + { + maSignatureManager.getSecurityContext() + }; + // Gpg signing is only possible with ODF >= 1.2 documents + if (DocumentSignatureHelper::CanSignWithGPG(maSignatureManager.getStore(), m_sODFVersion)) + xSecContexts.push_back(maSignatureManager.getGpgSecurityContext()); + + CertificateChooser* aChooser = CertificateChooser::getInstance(m_xDialog.get(), std::move(xSecContexts), UserAction::Sign); + if (aChooser->run() == RET_OK) + { + sal_Int32 nSecurityId; + if (!maSignatureManager.add(aChooser->GetSelectedCertificates()[0], aChooser->GetSelectedSecurityContext(), + aChooser->GetDescription(), nSecurityId, m_bAdESCompliant)) + return; + mbSignaturesChanged = true; + + xml::crypto::SecurityOperationStatus nStatus = xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED; + + if (maSignatureManager.getStore().is()) + // In the PDF case the signature information is only available after parsing. + nStatus = maSignatureManager.getSignatureHelper().GetSignatureInformation( nSecurityId ).nStatus; + + if ( nStatus == css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED ) + { + mbSignaturesChanged = true; + + // Can't simply remember current information, need parsing for getting full information :( + // We need to verify the signatures again, otherwise the status in the signature information + // will not contain + // SecurityOperationStatus_OPERATION_SUCCEEDED + mbVerifySignatures = true; + ImplGetSignatureInformations(/*bUseTempStream=*/true, /*bCacheLastSignature=*/false); + ImplFillSignaturesBox(); + } + } + } + catch ( uno::Exception& ) + { + TOOLS_WARN_EXCEPTION( "xmlsecurity.dialogs", "adding a signature!" ); + std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Error, VclButtonsType::Ok, + XsResId(STR_XMLSECDLG_SIGNING_FAILED))); + xBox->run(); + // Don't keep invalid entries... + ImplGetSignatureInformations(/*bUseTempStream=*/true, /*bCacheLastSignature=*/false); + ImplFillSignaturesBox(); + } +} + +IMPL_LINK_NOARG(DigitalSignaturesDialog, RemoveButtonHdl, weld::Button&, void) +{ + if (!canRemove()) + return; + int nEntry = m_xSignaturesLB->get_selected_index(); + if (nEntry == -1) + return; + + try + { + sal_uInt16 nSelected = m_xSignaturesLB->get_id(nEntry).toUInt32(); + maSignatureManager.remove(nSelected); + + mbSignaturesChanged = true; + + ImplFillSignaturesBox(); + } + catch ( uno::Exception& ) + { + TOOLS_WARN_EXCEPTION( "xmlsecurity.dialogs", "Exception while removing a signature!" ); + // Don't keep invalid entries... + ImplGetSignatureInformations(/*bUseTempStream=*/true, /*bCacheLastSignature=*/true); + ImplFillSignaturesBox(); + } +} + + +IMPL_LINK_NOARG(DigitalSignaturesDialog, CertMgrButtonHdl, weld::Button&, void) +{ + OUString sExecutable; + GetCertificateManager(sExecutable); + + if (!sExecutable.isEmpty()) + { + uno::Reference<uno::XComponentContext> xContext + = ::comphelper::getProcessComponentContext(); + uno::Reference<css::system::XSystemShellExecute> xSystemShell( + css::system::SystemShellExecute::create(xContext)); + + xSystemShell->execute(sExecutable, OUString(), + css::system::SystemShellExecuteFlags::DEFAULTS); + } + + OUString sDialogText = (sExecutable.isEmpty() ? + XsResId(STR_XMLSECDLG_NO_CERT_MANAGER) : XsResId(STR_XMLSECDLG_OPENED_CRTMGR) + sExecutable); + + std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog( + m_xDialog.get(), VclMessageType::Info, VclButtonsType::Ok, + sDialogText)); + xInfoBox->run(); +} + +IMPL_LINK_NOARG(DigitalSignaturesDialog, StartVerifySignatureHdl, LinkParamNone*, bool) +{ + return mbVerifySignatures; +} + +void DigitalSignaturesDialog::ImplFillSignaturesBox() +{ + m_xSignaturesLB->clear(); + + size_t nInfos = maSignatureManager.getCurrentSignatureInformations().size(); + size_t nValidSigs = 0, nValidCerts = 0; + bool bAllNewSignatures = true; + bool bSomePartial = false; + + if( nInfos ) + { + for( size_t n = 0; n < nInfos; ++n ) + { + DocumentSignatureAlgorithm mode = DocumentSignatureHelper::getDocumentAlgorithm( + m_sODFVersion, maSignatureManager.getCurrentSignatureInformations()[n]); + std::vector< OUString > aElementsToBeVerified; + if (maSignatureManager.getStore().is()) + aElementsToBeVerified = DocumentSignatureHelper::CreateElementList(maSignatureManager.getStore(), maSignatureManager.getSignatureMode(), mode); + + const SignatureInformation& rInfo = maSignatureManager.getCurrentSignatureInformations()[n]; + uno::Reference< css::security::XCertificate > xCert = getCertificate(rInfo); + + OUString aSubject; + OUString aIssuer; + OUString aDateTimeStr; + OUString aDescription; + OUString aType; + + bool bCertValid = false; + if( xCert.is() ) + { + //check the validity of the cert + try { + sal_Int32 certResult = getSecurityEnvironmentForCertificate(xCert)->verifyCertificate(xCert, + Sequence<uno::Reference<security::XCertificate> >()); + + bCertValid = certResult == css::security::CertificateValidity::VALID; + if ( bCertValid ) + nValidCerts++; + + } catch (css::uno::SecurityException& ) { + OSL_FAIL("Verification of certificate failed"); + bCertValid = false; + } + + aSubject = xmlsec::GetContentPart( xCert->getSubjectName(), xCert->getCertificateKind() ); + aIssuer = xmlsec::GetContentPart( xCert->getIssuerName(), xCert->getCertificateKind() ); + } + else if (!rInfo.ouGpgCertificate.isEmpty()) + { + // In case we don't have the gpg key locally, get some data from the document + aIssuer = rInfo.ouGpgOwner; + } + + aDateTimeStr = utl::GetDateTimeString( rInfo.stDateTime ); + aDescription = rInfo.ouDescription; + + // Decide type string. + if (maSignatureManager.getStore().is()) + { + // OpenPGP + if (!rInfo.ouGpgCertificate.isEmpty()) + aType = "OpenPGP"; + // XML based: XAdES or not. + else if (rInfo.GetSigningCertificate() && !rInfo.GetSigningCertificate()->CertDigest.isEmpty()) + aType = "XAdES"; + else + aType = "XML-DSig"; + } + else + { + // Assume PDF: PAdES or not. + if (rInfo.bHasSigningCertificate) + aType = "PAdES"; + else + aType = "PDF"; + } + + bool bSigValid = rInfo.nStatus == css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED; + + if ( bSigValid ) + { + if (maSignatureManager.getStore().is()) + { + // ZIP based. + bSigValid = DocumentSignatureHelper::checkIfAllFilesAreSigned( + aElementsToBeVerified, rInfo, mode); + } + else + { + // Assume PDF. + bSigValid = !rInfo.bPartialDocumentSignature; + } + + if( bSigValid ) + nValidSigs++; + else + { + bSomePartial = true; + } + } + + OUString sImage; + if (!bSigValid) + { + sImage = BMP_SIG_INVALID; + } + else if (!bCertValid) + { + sImage = BMP_SIG_NOT_VALIDATED; + } + //Check if the signature is a "old" document signature, that is, which was created + //by a version of OOo previous to 3.2 + // If there is no storage, then it's pointless to check storage + // stream references. + else if (maSignatureManager.getSignatureMode() == DocumentSignatureMode::Content + && (maSignatureManager.getStore().is() && !DocumentSignatureHelper::isOOo3_2_Signature( + maSignatureManager.getCurrentSignatureInformations()[n]))) + { + sImage = BMP_SIG_NOT_VALIDATED; + bAllNewSignatures = false; + } + else if (maSignatureManager.getSignatureMode() == DocumentSignatureMode::Content + && DocumentSignatureHelper::isOOo3_2_Signature( + maSignatureManager.getCurrentSignatureInformations()[n])) + { + sImage = BMP_SIG_VALID; + } + else if (maSignatureManager.getSignatureMode() == DocumentSignatureMode::Macros) + { + sImage = BMP_SIG_VALID; + } + + m_xSignaturesLB->insert(nullptr, n, nullptr, nullptr, + &sImage, nullptr, false, nullptr); + m_xSignaturesLB->set_text(n, aSubject, 1); + m_xSignaturesLB->set_text(n, aIssuer, 2); + m_xSignaturesLB->set_text(n, aDateTimeStr, 3); + m_xSignaturesLB->set_text(n, aDescription, 4); + m_xSignaturesLB->set_text(n, aType, 5); + m_xSignaturesLB->set_id(n, OUString::number(n)); // misuse user data as index + } + } + + bool bAllSigsValid = (nValidSigs == nInfos); + bool bAllCertsValid = (nValidCerts == nInfos); + bool bShowValidState = nInfos && (bAllSigsValid && bAllCertsValid && bAllNewSignatures); + + m_xSigsValidImg->set_visible( bShowValidState); + m_xSigsValidFI->set_visible( bShowValidState ); + + bool bShowInvalidState = nInfos && !bAllSigsValid; + + m_xSigsInvalidImg->set_visible( bShowInvalidState && !bSomePartial); + m_xSigsInvalidFI->set_visible( bShowInvalidState && !bSomePartial); + + bool bShowNotValidatedState = nInfos && bAllSigsValid && !bAllCertsValid; + + m_xSigsNotvalidatedImg->set_visible(bShowNotValidatedState); + m_xSigsNotvalidatedFI->set_visible(bShowNotValidatedState); + + //bAllNewSignatures is always true if we are not in document mode + bool bShowOldSignature = nInfos && bAllSigsValid && bAllCertsValid && !bAllNewSignatures; + m_xSigsOldSignatureImg->set_visible(bShowOldSignature || bSomePartial); + m_xSigsOldSignatureFI->set_visible(bShowOldSignature || bSomePartial); + + SignatureHighlightHdl(*m_xSignaturesLB); +} + +uno::Reference<security::XCertificate> DigitalSignaturesDialog::getCertificate(const SignatureInformation& rInfo) +{ + uno::Reference<xml::crypto::XSecurityEnvironment> xSecEnv = maSignatureManager.getSecurityEnvironment(); + uno::Reference<xml::crypto::XSecurityEnvironment> xGpgSecEnv = maSignatureManager.getGpgSecurityEnvironment(); + uno::Reference<security::XCertificate> xCert; + + //First we try to get the certificate which is embedded in the XML Signature + if (xSecEnv.is() && rInfo.GetSigningCertificate() && !rInfo.GetSigningCertificate()->X509Certificate.isEmpty()) + xCert = xSecEnv->createCertificateFromAscii(rInfo.GetSigningCertificate()->X509Certificate); + else { + //There must be an embedded certificate because we use it to get the + //issuer name. We cannot use /Signature/KeyInfo/X509Data/X509IssuerName + //because it could be modified by an attacker. The issuer is displayed + //in the digital signature dialog. + //Comparing the X509IssuerName with the one from the X509Certificate in order + //to find out if the X509IssuerName was modified does not work. See #i62684 + SAL_WARN( "xmlsecurity.dialogs", "Could not find embedded certificate!"); + } + + //In case there is no embedded certificate we try to get it from a local store + if (!xCert.is() && xSecEnv.is() && rInfo.GetSigningCertificate()) + { + xCert = xSecEnv->getCertificate(rInfo.GetSigningCertificate()->X509IssuerName, + xmlsecurity::numericStringToBigInteger(rInfo.GetSigningCertificate()->X509SerialNumber)); + } + if (!xCert.is() && xGpgSecEnv.is() && !rInfo.ouGpgKeyID.isEmpty()) + xCert = xGpgSecEnv->getCertificate( rInfo.ouGpgKeyID, xmlsecurity::numericStringToBigInteger(u"") ); + + SAL_WARN_IF( !xCert.is(), "xmlsecurity.dialogs", "Certificate not found and can't be created!" ); + + return xCert; +} + +uno::Reference<xml::crypto::XSecurityEnvironment> DigitalSignaturesDialog::getSecurityEnvironmentForCertificate(const uno::Reference<security::XCertificate>& xCert) +{ + switch(xCert->getCertificateKind()) + { + case CertificateKind_OPENPGP: + return maSignatureManager.getGpgSecurityEnvironment(); + case CertificateKind_X509: + return maSignatureManager.getSecurityEnvironment(); + default: + throw RuntimeException("Unknown certificate kind"); + } +} + +//If bUseTempStream is true then the temporary signature stream is used. +//Otherwise the real signature stream is used. +void DigitalSignaturesDialog::ImplGetSignatureInformations(bool bUseTempStream, bool bCacheLastSignature) +{ + maSignatureManager.read(bUseTempStream, bCacheLastSignature); + mbVerifySignatures = false; +} + +void DigitalSignaturesDialog::ImplShowSignaturesDetails() +{ + int nEntry = m_xSignaturesLB->get_selected_index(); + if (nEntry == -1) + return; + + sal_uInt16 nSelected = m_xSignaturesLB->get_id(nEntry).toUInt32(); + const SignatureInformation& rInfo = maSignatureManager.getCurrentSignatureInformations()[ nSelected ]; + uno::Reference<security::XCertificate> xCert = getCertificate(rInfo); + + if ( xCert.is() ) + { + if (m_xViewer) + m_xViewer->response(RET_OK); + + uno::Reference<xml::crypto::XSecurityEnvironment> xSecEnv = getSecurityEnvironmentForCertificate(xCert); + m_xViewer = std::make_shared<CertificateViewer>(m_xDialog.get(), xSecEnv, xCert, false, nullptr); + weld::DialogController::runAsync(m_xViewer, [this] (sal_Int32) { m_xViewer = nullptr; }); + } + else + { + if (m_xInfoBox) + m_xInfoBox->response(RET_OK); + + m_xInfoBox = std::shared_ptr<weld::MessageDialog>(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Info, VclButtonsType::Ok, + XsResId(STR_XMLSECDLG_NO_CERT_FOUND))); + m_xInfoBox->runAsync(m_xInfoBox, [this] (sal_Int32) { m_xInfoBox = nullptr; }); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/dialogs/macrosecurity.cxx b/xmlsecurity/source/dialogs/macrosecurity.cxx new file mode 100644 index 0000000000..ca4df4e64c --- /dev/null +++ b/xmlsecurity/source/dialogs/macrosecurity.cxx @@ -0,0 +1,447 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include <macrosecurity.hxx> +#include <certificateviewer.hxx> +#include <biginteger.hxx> +#include <resourcemanager.hxx> +#include <strings.hrc> + +#include <o3tl/safeint.hxx> +#include <osl/file.hxx> +#include <sal/log.hxx> + +#include <com/sun/star/xml/crypto/XSecurityEnvironment.hpp> +#include <comphelper/sequence.hxx> +#include <comphelper/processfactory.hxx> +#include <comphelper/xmlsechelper.hxx> +#include <com/sun/star/uno/Exception.hpp> +#include <com/sun/star/ui/dialogs/FolderPicker.hpp> +#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp> +#include <sfx2/filedlghelper.hxx> +#include <comphelper/diagnose_ex.hxx> +#include <tools/urlobj.hxx> +#include <unotools/datetime.hxx> + +#include <utility> +#include <vcl/svapp.hxx> + +using namespace comphelper; +using namespace ::com::sun::star; + + +IMPL_LINK_NOARG(MacroSecurity, OkBtnHdl, weld::Button&, void) +{ + m_xLevelTP->ClosePage(); + m_xTrustSrcTP->ClosePage(); + m_xDialog->response(RET_OK); +} + +MacroSecurity::MacroSecurity(weld::Window* pParent, + css::uno::Reference<css::xml::crypto::XSecurityEnvironment> xSecurityEnvironment) + : GenericDialogController(pParent, "xmlsec/ui/macrosecuritydialog.ui", "MacroSecurityDialog") + , m_xSecurityEnvironment(std::move(xSecurityEnvironment)) + , m_xTabCtrl(m_xBuilder->weld_notebook("tabcontrol")) + , m_xOkBtn(m_xBuilder->weld_button("ok")) + , m_xResetBtn(m_xBuilder->weld_button("reset")) +{ + m_xTabCtrl->connect_enter_page(LINK(this, MacroSecurity, ActivatePageHdl)); + + m_xLevelTP.reset(new MacroSecurityLevelTP(m_xTabCtrl->get_page("SecurityLevelPage"), this)); + m_xTrustSrcTP.reset(new MacroSecurityTrustedSourcesTP(m_xTabCtrl->get_page("SecurityTrustPage"), this)); + + m_xTabCtrl->set_current_page("SecurityLevelPage"); + m_xOkBtn->connect_clicked(LINK(this, MacroSecurity, OkBtnHdl)); +} + +IMPL_LINK(MacroSecurity, ActivatePageHdl, const OUString&, rPage, void) +{ + if (rPage == "SecurityLevelPage") + m_xLevelTP->ActivatePage(); + else if (rPage == "SecurityTrustPage") + m_xTrustSrcTP->ActivatePage(); +} + +MacroSecurityTP::MacroSecurityTP(weld::Container* pParent, const OUString& rUIXMLDescription, + const OUString& rID, MacroSecurity* pDlg) + : m_xBuilder(Application::CreateBuilder(pParent, rUIXMLDescription)) + , m_xContainer(m_xBuilder->weld_container(rID)) + , m_pDlg(pDlg) +{ +} + +void MacroSecurityTP::ActivatePage() +{ +} + +MacroSecurityTP::~MacroSecurityTP() +{ +} + +MacroSecurityLevelTP::MacroSecurityLevelTP(weld::Container* pParent, MacroSecurity* pDlg) + : MacroSecurityTP(pParent, "xmlsec/ui/securitylevelpage.ui", "SecurityLevelPage", pDlg) + , m_xVeryHighRB(m_xBuilder->weld_radio_button("vhigh")) + , m_xHighRB(m_xBuilder->weld_radio_button("high")) + , m_xMediumRB(m_xBuilder->weld_radio_button("med")) + , m_xLowRB(m_xBuilder->weld_radio_button("low")) + , m_xVHighImg(m_xBuilder->weld_widget("vhighimg")) + , m_xHighImg(m_xBuilder->weld_widget("highimg")) + , m_xMedImg(m_xBuilder->weld_widget("medimg")) + , m_xLowImg(m_xBuilder->weld_widget("lowimg")) +{ + m_xLowRB->connect_toggled( LINK( this, MacroSecurityLevelTP, RadioButtonHdl ) ); + m_xMediumRB->connect_toggled( LINK( this, MacroSecurityLevelTP, RadioButtonHdl ) ); + m_xHighRB->connect_toggled( LINK( this, MacroSecurityLevelTP, RadioButtonHdl ) ); + m_xVeryHighRB->connect_toggled( LINK( this, MacroSecurityLevelTP, RadioButtonHdl ) ); + + int nPrefWidth(std::max({m_xVeryHighRB->get_preferred_size().Width(), + m_xHighRB->get_preferred_size().Width(), + m_xMediumRB->get_preferred_size().Width(), + m_xLowRB->get_preferred_size().Width()})); + int nMaxWidth = m_xLowRB->get_approximate_digit_width() * 60; + if (nPrefWidth > nMaxWidth) + { + m_xLowRB->set_label_wrap(true); + m_xLowRB->set_size_request(nMaxWidth, -1); + m_xMediumRB->set_label_wrap(true); + m_xMediumRB->set_size_request(nMaxWidth, -1); + m_xHighRB->set_label_wrap(true); + m_xHighRB->set_size_request(nMaxWidth, -1); + m_xVeryHighRB->set_label_wrap(true); + m_xVeryHighRB->set_size_request(nMaxWidth, -1); + } + + mnCurLevel = static_cast<sal_uInt16>(SvtSecurityOptions::GetMacroSecurityLevel()); + bool bReadonly = SvtSecurityOptions::IsReadOnly( SvtSecurityOptions::EOption::MacroSecLevel ); + + weld::RadioButton* pCheck = nullptr; + weld::Widget* pImage = nullptr; + switch (mnCurLevel) + { + case 3: + pCheck = m_xVeryHighRB.get(); + pImage = m_xVHighImg.get(); + break; + case 2: + pCheck = m_xHighRB.get(); + pImage = m_xHighImg.get(); + break; + case 1: + pCheck = m_xMediumRB.get(); + pImage = m_xMedImg.get(); + break; + case 0: + pCheck = m_xLowRB.get(); + pImage = m_xLowImg.get(); + break; + } + if (pCheck) + pCheck->set_active(true); + else + { + OSL_FAIL("illegal macro security level"); + } + if (bReadonly && pImage) + { + pImage->show(); + m_xVeryHighRB->set_sensitive(false); + m_xHighRB->set_sensitive(false); + m_xMediumRB->set_sensitive(false); + m_xLowRB->set_sensitive(false); + } +} + +IMPL_LINK_NOARG(MacroSecurityLevelTP, RadioButtonHdl, weld::Toggleable&, void) +{ + sal_uInt16 nNewLevel = 0; + if( m_xVeryHighRB->get_active() ) + nNewLevel = 3; + else if( m_xHighRB->get_active() ) + nNewLevel = 2; + else if( m_xMediumRB->get_active() ) + nNewLevel = 1; + + if ( nNewLevel != mnCurLevel ) + { + mnCurLevel = nNewLevel; + m_pDlg->EnableReset(); + } +} + +void MacroSecurityLevelTP::ClosePage() +{ + SvtSecurityOptions::SetMacroSecurityLevel( mnCurLevel ); +} + +void MacroSecurityTrustedSourcesTP::ImplCheckButtons() +{ + bool bCertSelected = m_xTrustCertLB->get_selected_index() != -1; + m_xViewCertPB->set_sensitive( bCertSelected ); + m_xRemoveCertPB->set_sensitive( bCertSelected && !mbAuthorsReadonly); + + bool bLocationSelected = m_xTrustFileLocLB->get_selected_index() != -1; + m_xRemoveLocPB->set_sensitive( bLocationSelected && !mbURLsReadonly); +} + +void MacroSecurityTrustedSourcesTP::ShowBrokenCertificateError(std::u16string_view rData) +{ + OUString aMsg = XsResId(STR_BROKEN_MACRO_CERTIFICATE_DATA); + aMsg = aMsg.replaceFirst("%{data}", rData); + std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(m_pDlg->getDialog(), + VclMessageType::Error, VclButtonsType::Ok, aMsg)); + xErrorBox->run(); +} + +IMPL_LINK_NOARG(MacroSecurityTrustedSourcesTP, ViewCertPBHdl, weld::Button&, void) +{ + int nEntry = m_xTrustCertLB->get_selected_index(); + if (nEntry == -1) + return; + + const sal_uInt16 nSelected = m_xTrustCertLB->get_id(nEntry).toUInt32(); + uno::Reference< css::security::XCertificate > xCert; + try + { + xCert = m_pDlg->m_xSecurityEnvironment->getCertificate(m_aTrustedAuthors[nSelected].SubjectName, + xmlsecurity::numericStringToBigInteger(m_aTrustedAuthors[nSelected].SerialNumber)); + } + catch (...) + { + TOOLS_WARN_EXCEPTION("xmlsecurity.dialogs", "matching certificate not found for: " << m_aTrustedAuthors[nSelected].SubjectName); + } + + if (!xCert.is()) + { + try + { + xCert = m_pDlg->m_xSecurityEnvironment->createCertificateFromAscii(m_aTrustedAuthors[nSelected].RawData); + } + catch (...) + { + TOOLS_WARN_EXCEPTION("xmlsecurity.dialogs", "certificate data couldn't be parsed: " << m_aTrustedAuthors[nSelected].RawData); + } + } + + if ( xCert.is() ) + { + CertificateViewer aViewer(m_pDlg->getDialog(), m_pDlg->m_xSecurityEnvironment, xCert, false, nullptr); + aViewer.run(); + } + else + // should never happen, as we parsed the certificate data when we added it! + ShowBrokenCertificateError(m_aTrustedAuthors[nSelected].RawData); +} + +IMPL_LINK_NOARG(MacroSecurityTrustedSourcesTP, RemoveCertPBHdl, weld::Button&, void) +{ + int nEntry = m_xTrustCertLB->get_selected_index(); + if (nEntry != -1) + { + sal_uInt16 nAuthor = m_xTrustCertLB->get_id(nEntry).toUInt32(); + m_aTrustedAuthors.erase(m_aTrustedAuthors.begin() + nAuthor); + + FillCertLB(); + ImplCheckButtons(); + } +} + +IMPL_LINK_NOARG(MacroSecurityTrustedSourcesTP, AddLocPBHdl, weld::Button&, void) +{ + try + { + uno::Reference < uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() ); + uno::Reference < ui::dialogs::XFolderPicker2 > xFolderPicker = sfx2::createFolderPicker(xContext, m_pDlg->getDialog()); + + short nRet = xFolderPicker->execute(); + + if( ui::dialogs::ExecutableDialogResults::OK != nRet ) + return; + + OUString aPathStr = xFolderPicker->getDirectory(); + INetURLObject aNewObj( aPathStr ); + aNewObj.removeFinalSlash(); + + // then the new path also a URL else system path + OUString aSystemFileURL = ( aNewObj.GetProtocol() != INetProtocol::NotValid ) ? + aPathStr : aNewObj.getFSysPath( FSysStyle::Detect ); + + OUString aNewPathStr(aSystemFileURL); + + if ( osl::FileBase::getSystemPathFromFileURL( aSystemFileURL, aSystemFileURL ) == osl::FileBase::E_None ) + aNewPathStr = aSystemFileURL; + + if (m_xTrustFileLocLB->find_text(aNewPathStr) == -1) + m_xTrustFileLocLB->append_text(aNewPathStr); + + ImplCheckButtons(); + } + catch( uno::Exception& ) + { + TOOLS_WARN_EXCEPTION( "xmlsecurity.dialogs", "MacroSecurityTrustedSourcesTP::AddLocPBHdl(): exception from folder picker" ); + } +} + +IMPL_LINK_NOARG(MacroSecurityTrustedSourcesTP, RemoveLocPBHdl, weld::Button&, void) +{ + sal_Int32 nSel = m_xTrustFileLocLB->get_selected_index(); + if (nSel == -1) + return; + + m_xTrustFileLocLB->remove(nSel); + // Trusted Path could not be removed (#i33584#) + // after remove an entry, select another one if exists + int nNewCount = m_xTrustFileLocLB->n_children(); + if (nNewCount > 0) + { + if (nSel >= nNewCount) + nSel = nNewCount - 1; + m_xTrustFileLocLB->select(nSel); + } + ImplCheckButtons(); +} + +IMPL_LINK_NOARG(MacroSecurityTrustedSourcesTP, TrustCertLBSelectHdl, weld::TreeView&, void) +{ + ImplCheckButtons(); +} + +IMPL_LINK_NOARG(MacroSecurityTrustedSourcesTP, TrustFileLocLBSelectHdl, weld::TreeView&, void) +{ + ImplCheckButtons(); +} + +void MacroSecurityTrustedSourcesTP::FillCertLB(const bool bShowWarnings) +{ + m_xTrustCertLB->clear(); + + sal_uInt32 nEntries = m_aTrustedAuthors.size(); + + if ( !(nEntries && m_pDlg->m_xSecurityEnvironment.is()) ) + return; + + for( sal_uInt32 nEntry = 0 ; nEntry < nEntries ; ++nEntry ) + { + SvtSecurityOptions::Certificate& rEntry = m_aTrustedAuthors[ nEntry ]; + + try + { + // create from RawData + uno::Reference< css::security::XCertificate > xCert = m_pDlg->m_xSecurityEnvironment->createCertificateFromAscii(rEntry.RawData); + m_xTrustCertLB->append(OUString::number(nEntry), xmlsec::GetContentPart(xCert->getSubjectName(), xCert->getCertificateKind())); + m_xTrustCertLB->set_text(nEntry, xmlsec::GetContentPart(xCert->getIssuerName(), xCert->getCertificateKind()), 1); + m_xTrustCertLB->set_text(nEntry, utl::GetDateTimeString(xCert->getNotValidAfter()), 2); + } + catch (...) + { + if (bShowWarnings) + { + TOOLS_WARN_EXCEPTION("xmlsecurity.dialogs", "certificate data couldn't be parsed: " << rEntry.RawData); + OUString sData = rEntry.RawData; + css::uno::Any tools_warn_exception(DbgGetCaughtException()); + OUString sException = OStringToOUString(exceptionToString(tools_warn_exception), RTL_TEXTENCODING_UTF8); + if (!sException.isEmpty()) + sData += " / " + sException; + ShowBrokenCertificateError(sData); + } + } + } +} + +MacroSecurityTrustedSourcesTP::MacroSecurityTrustedSourcesTP(weld::Container* pParent, MacroSecurity* pDlg) + : MacroSecurityTP(pParent, "xmlsec/ui/securitytrustpage.ui", "SecurityTrustPage", pDlg) + , m_xTrustCertROFI(m_xBuilder->weld_image("lockcertimg")) + , m_xTrustCertLB(m_xBuilder->weld_tree_view("certificates")) + , m_xViewCertPB(m_xBuilder->weld_button("viewcert")) + , m_xRemoveCertPB(m_xBuilder->weld_button("removecert")) + , m_xTrustFileROFI(m_xBuilder->weld_image("lockfileimg")) + , m_xTrustFileLocLB(m_xBuilder->weld_tree_view("locations")) + , m_xAddLocPB(m_xBuilder->weld_button("addfile")) + , m_xRemoveLocPB(m_xBuilder->weld_button("removefile")) +{ + auto nColWidth = m_xTrustCertLB->get_approximate_digit_width() * 12; + std::vector<int> aWidths + { + o3tl::narrowing<int>(nColWidth * 2), + o3tl::narrowing<int>(nColWidth * 2) + }; + m_xTrustCertLB->set_column_fixed_widths(aWidths); + m_xTrustCertLB->set_size_request(nColWidth * 5.5, m_xTrustCertLB->get_height_rows(5)); + + m_xTrustCertLB->connect_changed( LINK( this, MacroSecurityTrustedSourcesTP, TrustCertLBSelectHdl ) ); + m_xViewCertPB->connect_clicked( LINK( this, MacroSecurityTrustedSourcesTP, ViewCertPBHdl ) ); + m_xViewCertPB->set_sensitive(false); + m_xRemoveCertPB->connect_clicked( LINK( this, MacroSecurityTrustedSourcesTP, RemoveCertPBHdl ) ); + m_xRemoveCertPB->set_sensitive(false); + + m_xTrustFileLocLB->connect_changed( LINK( this, MacroSecurityTrustedSourcesTP, TrustFileLocLBSelectHdl ) ); + m_xTrustFileLocLB->set_size_request(nColWidth * 5, m_xTrustFileLocLB->get_height_rows(5)); + m_xAddLocPB->connect_clicked( LINK( this, MacroSecurityTrustedSourcesTP, AddLocPBHdl ) ); + m_xRemoveLocPB->connect_clicked( LINK( this, MacroSecurityTrustedSourcesTP, RemoveLocPBHdl ) ); + m_xRemoveLocPB->set_sensitive(false); + + m_aTrustedAuthors = SvtSecurityOptions::GetTrustedAuthors(); + mbAuthorsReadonly = SvtSecurityOptions::IsReadOnly( SvtSecurityOptions::EOption::MacroTrustedAuthors ); + m_xTrustCertROFI->set_visible(mbAuthorsReadonly); + + FillCertLB(true); + + std::vector< OUString > aSecureURLs = SvtSecurityOptions::GetSecureURLs(); + mbURLsReadonly = SvtSecurityOptions::IsReadOnly( SvtSecurityOptions::EOption::SecureUrls ); + m_xTrustFileROFI->set_visible(mbURLsReadonly); + m_xAddLocPB->set_sensitive(!mbURLsReadonly); + + for (const auto& rSecureURL : aSecureURLs) + { + OUString aSystemFileURL( rSecureURL ); + osl::FileBase::getSystemPathFromFileURL( aSystemFileURL, aSystemFileURL ); + m_xTrustFileLocLB->append_text(aSystemFileURL); + } +} + +void MacroSecurityTrustedSourcesTP::ActivatePage() +{ + m_pDlg->EnableReset( false ); + FillCertLB(); +} + +void MacroSecurityTrustedSourcesTP::ClosePage() +{ + sal_Int32 nEntryCnt = m_xTrustFileLocLB->n_children(); + if( nEntryCnt ) + { + std::vector< OUString > aSecureURLs; + for (sal_Int32 i = 0; i < nEntryCnt; ++i) + { + OUString aURL(m_xTrustFileLocLB->get_text(i)); + osl::FileBase::getFileURLFromSystemPath( aURL, aURL ); + aSecureURLs.push_back(aURL); + } + + SvtSecurityOptions::SetSecureURLs( std::move(aSecureURLs) ); + } + // Trusted Path could not be removed (#i33584#) + // don't forget to remove the old saved SecureURLs + else + SvtSecurityOptions::SetSecureURLs( std::vector< OUString >() ); + + SvtSecurityOptions::SetTrustedAuthors( m_aTrustedAuthors ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/framework/buffernode.cxx b/xmlsecurity/source/framework/buffernode.cxx new file mode 100644 index 0000000000..4dfa9fbfe2 --- /dev/null +++ b/xmlsecurity/source/framework/buffernode.cxx @@ -0,0 +1,887 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "elementmark.hxx" +#include "elementcollector.hxx" +#include "buffernode.hxx" +#include <com/sun/star/xml/crypto/sax/ConstOfSecurityId.hpp> +#include <osl/diagnose.h> +#include <rtl/ustrbuf.hxx> +#include <utility> + +BufferNode::BufferNode( css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > xXMLElement ) + :m_pParent(nullptr), + m_pBlocker(nullptr), + m_bAllReceived(false), + m_xXMLElement(std::move(xXMLElement)) +{ +} + +bool BufferNode::isECOfBeforeModifyIncluded(sal_Int32 nIgnoredSecurityId) const +/****** BufferNode/isECOfBeforeModifyIncluded ******************************** + * + * NAME + * isECOfBeforeModifyIncluded -- checks whether there is some + * ElementCollector on this BufferNode, that has BEFORE-MODIFY priority. + * + * SYNOPSIS + * bExist = isECOfBeforeModifyIncluded(nIgnoredSecurityId); + * + * FUNCTION + * checks each ElementCollector on this BufferNode, if all following + * conditions are satisfied, then returns true: + * 1. the ElementCollector's priority is BEFOREMODIFY; + * 2. the ElementCollector's securityId can't be ignored. + * otherwise, returns false. + * + * INPUTS + * nIgnoredSecurityId - the security Id to be ignored. If it equals + * to UNDEFINEDSECURITYID, then no security Id + * will be ignored. + * + * RESULT + * bExist - true if a match found, false otherwise + ******************************************************************************/ +{ + return std::any_of(m_vElementCollectors.cbegin(), m_vElementCollectors.cend(), + [nIgnoredSecurityId](const ElementCollector* pElementCollector) { + return (nIgnoredSecurityId == css::xml::crypto::sax::ConstOfSecurityId::UNDEFINEDSECURITYID || + pElementCollector->getSecurityId() != nIgnoredSecurityId) && + (pElementCollector->getPriority() == css::xml::crypto::sax::ElementMarkPriority_BEFOREMODIFY); + }); +} + +void BufferNode::setReceivedAll() +/****** BufferNode/setReceiveAll ********************************************* + * + * NAME + * setReceivedAll -- indicates that the element in this BufferNode has + * been completely buffered. + * + * SYNOPSIS + * setReceivedAll(); + * + * FUNCTION + * sets the all-received flag and launches ElementCollector's notify + * process. + * + * INPUTS + * empty + * + * RESULT + * empty + ******************************************************************************/ +{ + m_bAllReceived = true; + elementCollectorNotify(); +} + + +void BufferNode::addElementCollector(const ElementCollector* pElementCollector) +/****** BufferNode/addElementCollector *************************************** + * + * NAME + * addElementCollector -- adds a new ElementCollector to this BufferNode. + * + * SYNOPSIS + * addElementCollector(pElementCollector); + * + * FUNCTION + * see NAME + * + * INPUTS + * pElementCollector - the ElementCollector to be added + * + * RESULT + * empty + ******************************************************************************/ +{ + m_vElementCollectors.push_back( pElementCollector ); + const_cast<ElementCollector*>(pElementCollector)->setBufferNode(this); +} + +void BufferNode::removeElementCollector(const ElementCollector* pElementCollector) +/****** BufferNode/removeElementCollector ************************************ + * + * NAME + * removeElementCollector -- removes an ElementCollector from this + * BufferNode. + * + * SYNOPSIS + * removeElementCollector(pElementCollector); + * + * FUNCTION + * see NAME + * + * INPUTS + * pElementCollector - the ElementCollector to be removed + * + * RESULT + * empty + ******************************************************************************/ +{ + auto ii = std::find(m_vElementCollectors.begin(), m_vElementCollectors.end(), pElementCollector); + if (ii != m_vElementCollectors.end()) + { + m_vElementCollectors.erase( ii ); + const_cast<ElementCollector*>(pElementCollector)->setBufferNode(nullptr); + } +} + + +void BufferNode::setBlocker(const ElementMark* pBlocker) +/****** BufferNode/setBlocker ************************************************ + * + * NAME + * setBlocker -- adds a blocker to this BufferNode. + * + * SYNOPSIS + * setBlocker(pBlocker); + * + * FUNCTION + * see NAME + * + * INPUTS + * pBlocker - the new blocker to be attached + * + * RESULT + * empty + * + * NOTES + * Because there is only one blocker permitted for a BufferNode, so the + * old blocker on this BufferNode, if there is one, will be overcasted. + ******************************************************************************/ +{ + OSL_ASSERT(!(m_pBlocker != nullptr && pBlocker != nullptr)); + + m_pBlocker = const_cast<ElementMark*>(pBlocker); + if (m_pBlocker != nullptr) + { + m_pBlocker->setBufferNode(this); + } +} + +OUString BufferNode::printChildren() const +/****** BufferNode/printChildren ********************************************* + * + * NAME + * printChildren -- prints children information into a string. + * + * SYNOPSIS + * result = printChildren(); + * + * FUNCTION + * see NAME + * + * INPUTS + * empty + * + * RESULT + * result - the information string + ******************************************************************************/ +{ + OUStringBuffer rc; + + for( const ElementCollector* ii : m_vElementCollectors ) + { + rc.append("BufID=" + OUString::number(ii->getBufferId())); + + if (ii->getModify()) + { + rc.append("[M]"); + } + + rc.append(",Pri="); + + switch (ii->getPriority()) + { + case css::xml::crypto::sax::ElementMarkPriority_BEFOREMODIFY: + rc.append("BEFOREMODIFY"); + break; + case css::xml::crypto::sax::ElementMarkPriority_AFTERMODIFY: + rc.append("AFTERMODIFY"); + break; + default: + rc.append("UNKNOWN"); + break; + } + + rc.append("(SecID=" + OUString::number(ii->getSecurityId()) + ") "); + } + + return rc.makeStringAndClear(); +} + +bool BufferNode::hasAnything() const +/****** BufferNode/hasAnything *********************************************** + * + * NAME + * hasAnything -- checks whether there is any ElementCollector or blocker + * on this BufferNode. + * + * SYNOPSIS + * bExist = hasAnything(); + * + * FUNCTION + * see NAME + * + * INPUTS + * empty + * + * RESULT + * bExist - true if there is, false otherwise. + ******************************************************************************/ +{ + return (m_pBlocker || !m_vElementCollectors.empty()); +} + +bool BufferNode::hasChildren() const +/****** BufferNode/hasChildren *********************************************** + * + * NAME + * hasChildren -- checks whether this BufferNode has any child + * BufferNode. + * + * SYNOPSIS + * bExist = hasChildren(); + * + * FUNCTION + * see NAME + * + * INPUTS + * empty + * + * RESULT + * bExist - true if there is, false otherwise. + ******************************************************************************/ +{ + return (!m_vChildren.empty()); +} + +std::vector< std::unique_ptr<BufferNode> > const & BufferNode::getChildren() const +{ + return m_vChildren; +} + +std::vector< std::unique_ptr<BufferNode> > BufferNode::releaseChildren() +{ + return std::move(m_vChildren); +} + +const BufferNode* BufferNode::getFirstChild() const +/****** BufferNode/getFirstChild ********************************************* + * + * NAME + * getFirstChild -- retrieves the first child BufferNode. + * + * SYNOPSIS + * child = getFirstChild(); + * + * FUNCTION + * see NAME + * + * INPUTS + * empty + * + * RESULT + * child - the first child BufferNode, or NULL if there is no child + * BufferNode. + ******************************************************************************/ +{ + BufferNode* rc = nullptr; + + if (!m_vChildren.empty()) + { + rc = m_vChildren.front().get(); + } + + return rc; +} + +void BufferNode::addChild(std::unique_ptr<BufferNode> pChild, sal_Int32 nPosition) +/****** BufferNode/addChild(pChild,nPosition) ******************************** + * + * NAME + * addChild -- inserts a child BufferNode at specific position. + * + * SYNOPSIS + * addChild(pChild, nPosition); + * + * FUNCTION + * see NAME + * + * INPUTS + * pChild - the child BufferNode to be added. + * nPosition - the position where the new child locates. + * + * RESULT + * empty + * + * NOTES + * If the nPosition is -1, then the new child BufferNode is appended + * at the end. + ******************************************************************************/ +{ + if (nPosition == -1) + { + m_vChildren.push_back( std::move(pChild) ); + } + else + { + m_vChildren.insert(m_vChildren.begin() + nPosition, std::move(pChild)); + } +} + +void BufferNode::addChild(std::unique_ptr<BufferNode> pChild) +/****** BufferNode/addChild() ************************************************ + * + * NAME + * addChild -- add a new child BufferNode. + * + * SYNOPSIS + * addChild(pChild); + * + * FUNCTION + * see NAME + * + * INPUTS + * pChild - the child BufferNode to be added. + * + * RESULT + * empty + * + * NOTES + * The new child BufferNode is appended at the end. + ******************************************************************************/ +{ + addChild(std::move(pChild), -1); +} + +void BufferNode::removeChild(const BufferNode* pChild) +/****** BufferNode/removeChild *********************************************** + * + * NAME + * removeChild -- removes and deletes a child BufferNode from the children list. + * + * SYNOPSIS + * removeChild(pChild); + * + * FUNCTION + * see NAME + * + * INPUTS + * pChild - the child BufferNode to be removed + * + * RESULT + * empty + ******************************************************************************/ +{ + auto ii = std::find_if(m_vChildren.begin(), m_vChildren.end(), + [pChild] (const std::unique_ptr<BufferNode>& i) + { return i.get() == pChild; }); + if (ii != m_vChildren.end()) + m_vChildren.erase( ii ); +} + +sal_Int32 BufferNode::indexOfChild(const BufferNode* pChild) const +/****** BufferNode/indexOfChild ********************************************** + * + * NAME + * indexOfChild -- gets the index of a child BufferNode. + * + * SYNOPSIS + * index = indexOfChild(pChild); + * + * FUNCTION + * see NAME + * + * INPUTS + * pChild - the child BufferNode whose index to be gotten + * + * RESULT + * index - the index of that child BufferNode. If that child BufferNode + * is not found, -1 is returned. + ******************************************************************************/ +{ + auto ii = std::find_if(m_vChildren.begin(), m_vChildren.end(), + [pChild] (const std::unique_ptr<BufferNode>& i) + { return i.get() == pChild; }); + if (ii == m_vChildren.end()) + return -1; + + return std::distance(m_vChildren.begin(), ii); +} + + +void BufferNode::setParent(const BufferNode* pParent) +{ + m_pParent = const_cast<BufferNode*>(pParent); +} + +const BufferNode* BufferNode::getNextSibling() const +/****** BufferNode/getNextSibling ******************************************** + * + * NAME + * getNextSibling -- retrieves the next sibling BufferNode. + * + * SYNOPSIS + * sibling = getNextSibling(); + * + * FUNCTION + * see NAME + * + * INPUTS + * empty + * + * RESULT + * sibling - the next sibling BufferNode, or NULL if there is none. + ******************************************************************************/ +{ + BufferNode* rc = nullptr; + + if (m_pParent != nullptr) + { + rc = const_cast<BufferNode*>(m_pParent->getNextChild(this)); + } + + return rc; +} + +const BufferNode* BufferNode::isAncestor(const BufferNode* pDescendant) const +/****** BufferNode/isAncestor ************************************************ + * + * NAME + * isAncestor -- checks whether this BufferNode is an ancestor of another + * BufferNode. + * + * SYNOPSIS + * bIs = isAncestor(pDescendant); + * + * FUNCTION + * see NAME + * + * INPUTS + * pDescendant - the BufferNode to be checked as a descendant + * + * RESULT + * bIs - true if this BufferNode is an ancestor of the pDescendant, + * false otherwise. + ******************************************************************************/ +{ + BufferNode* rc = nullptr; + + if (pDescendant != nullptr) + { + auto ii = std::find_if(m_vChildren.cbegin(), m_vChildren.cend(), + [&pDescendant](const std::unique_ptr<BufferNode>& pChild) { + return (pChild.get() == pDescendant) || (pChild->isAncestor(pDescendant) != nullptr); + }); + + if (ii != m_vChildren.end()) + rc = ii->get(); + } + + return rc; +} + +bool BufferNode::isPrevious(const BufferNode* pFollowing) const +/****** BufferNode/isPrevious ************************************************ + * + * NAME + * isPrevious -- checks whether this BufferNode is ahead of another + * BufferNode in the tree order. + * + * SYNOPSIS + * bIs = isPrevious(pFollowing); + * + * FUNCTION + * see NAME + * + * INPUTS + * pFollowing - the BufferNode to be checked as a following + * + * RESULT + * bIs - true if this BufferNode is ahead in the tree order, false + * otherwise. + ******************************************************************************/ +{ + bool rc = false; + + BufferNode* pNextBufferNode = const_cast<BufferNode*>(getNextNodeByTreeOrder()); + while (pNextBufferNode != nullptr) + { + if (pNextBufferNode == pFollowing) + { + rc = true; + break; + } + + pNextBufferNode = const_cast<BufferNode*>(pNextBufferNode->getNextNodeByTreeOrder()); + } + + return rc; +} + +const BufferNode* BufferNode::getNextNodeByTreeOrder() const +/****** BufferNode/getNextNodeByTreeOrder ************************************ + * + * NAME + * getNextNodeByTreeOrder -- retrieves the next BufferNode in the tree + * order. + * + * SYNOPSIS + * next = getNextNodeByTreeOrder(); + * + * FUNCTION + * see NAME + * + * INPUTS + * empty + * + * RESULT + * next - the BufferNode following this BufferNode in the tree order, + * or NULL if there is none. + * + * NOTES + * The "next" node in tree order is defined as: + * 1. If a node has children, then the first child is; + * 2. otherwise, if it has a following sibling, then this sibling node is; + * 3. otherwise, if it has a parent node, the parent's next sibling + * node is; + * 4. otherwise, no "next" node exists. + ******************************************************************************/ +{ + /* + * If this buffer node has m_vChildren, then return the first + * child. + */ + if (hasChildren()) + { + return getFirstChild(); + } + + /* + * Otherwise, it this buffer node has a following sibling, + * then return that sibling. + */ + BufferNode* pNextSibling = const_cast<BufferNode*>(getNextSibling()); + if (pNextSibling != nullptr) + { + return pNextSibling; + } + + /* + * Otherwise, it this buffer node has parent, then return + * its parent's following sibling. + */ + BufferNode* pNode = const_cast<BufferNode*>(this); + BufferNode* pParent; + BufferNode* pNextSiblingParent = nullptr; + + do + { + if (pNode == nullptr) + { + break; + } + + pParent = const_cast<BufferNode*>(pNode->getParent()); + if (pParent != nullptr) + { + pNextSiblingParent = const_cast<BufferNode*>(pParent->getNextSibling()); + } + pNode = pParent; + + } while (pNextSiblingParent == nullptr); + + return pNextSiblingParent; +} + + +void BufferNode::setXMLElement( const css::uno::Reference< css::xml::wrapper::XXMLElementWrapper >& xXMLElement ) +{ + m_xXMLElement = xXMLElement; +} + +void BufferNode::notifyBranch() +/****** BufferNode/notifyBranch ********************************************** + * + * NAME + * notifyBranch -- notifies each BufferNode in the branch of this + * BufferNode in the tree order. + * + * SYNOPSIS + * notifyBranch(); + * + * FUNCTION + * see NAME + * + * INPUTS + * empty + * + * RESULT + * empty + ******************************************************************************/ +{ + for( std::unique_ptr<BufferNode>& pBufferNode : m_vChildren ) + { + pBufferNode->elementCollectorNotify(); + pBufferNode->notifyBranch(); + } +} + +void BufferNode::elementCollectorNotify() +/****** BufferNode/elementCollectorNotify ************************************ + * + * NAME + * elementCollectorNotify -- notifies this BufferNode. + * + * SYNOPSIS + * elementCollectorNotify(); + * + * FUNCTION + * Notifies this BufferNode if the notification is not suppressed. + * + * INPUTS + * empty + * + * RESULT + * child - the first child BufferNode, or NULL if there is no child + * BufferNode. + ******************************************************************************/ +{ + if (m_vElementCollectors.empty()) + return; + + css::xml::crypto::sax::ElementMarkPriority nMaxPriority = css::xml::crypto::sax::ElementMarkPriority_MINIMUM; + css::xml::crypto::sax::ElementMarkPriority nPriority; + + /* + * get the max priority among ElementCollectors on this BufferNode + */ + for( const ElementCollector* pElementCollector : m_vElementCollectors ) + { + nPriority = pElementCollector->getPriority(); + if (nPriority > nMaxPriority) + { + nMaxPriority = nPriority; + } + } + + std::vector< const ElementCollector* > vElementCollectors( m_vElementCollectors ); + + for( const ElementCollector* ii : vElementCollectors ) + { + ElementCollector* pElementCollector = const_cast<ElementCollector*>(ii); + nPriority = pElementCollector->getPriority(); + bool bToModify = pElementCollector->getModify(); + + /* + * Only ElementCollector with the max priority can + * perform notify operation. + * Moreover, if any blocker exists in the subtree of + * this BufferNode, this ElementCollector can't do notify + * unless its priority is BEFOREMODIFY. + */ + if (nPriority == nMaxPriority && + (nPriority == css::xml::crypto::sax::ElementMarkPriority_BEFOREMODIFY || + !isBlockerInSubTreeIncluded(pElementCollector->getSecurityId()))) + { + /* + * If this ElementCollector will modify the buffered element, then + * special attention must be paid. + * + * If there is any ElementCollector in the subtree or any ancestor + * ElementCollector with PRI_BEFPREMODIFY priority, this + * ElementCollector can't perform notify operation, otherwise, it + * will destroy the buffered element, in turn, ElementCollectors + * mentioned above can't perform their mission. + */ + //if (!(nMaxPriority == css::xml::crypto::sax::ElementMarkPriority_PRI_MODIFY && + if (!(bToModify && + (isECInSubTreeIncluded(pElementCollector->getSecurityId()) || + isECOfBeforeModifyInAncestorIncluded(pElementCollector->getSecurityId())) + )) + { + pElementCollector->notifyListener(); + } + } + } +} + +bool BufferNode::isECInSubTreeIncluded(sal_Int32 nIgnoredSecurityId) const +/****** BufferNode/isECInSubTreeIncluded ************************************* + * + * NAME + * isECInSubTreeIncluded -- checks whether there is any ElementCollector + * in the branch of this BufferNode. + * + * SYNOPSIS + * bExist = isECInSubTreeIncluded(nIgnoredSecurityId); + * + * FUNCTION + * checks each BufferNode in the branch of this BufferNode, if there is + * an ElementCollector whose signatureId is not ignored, then return + * true, otherwise, false returned. + * + * INPUTS + * nIgnoredSecurityId - the security Id to be ignored. If it equals + * to UNDEFINEDSECURITYID, then no security Id + * will be ignored. + * + * RESULT + * bExist - true if a match found, false otherwise. + ******************************************************************************/ +{ + bool rc = std::any_of(m_vElementCollectors.begin(), m_vElementCollectors.end(), + [nIgnoredSecurityId](const ElementCollector* pElementCollector) { + return nIgnoredSecurityId == css::xml::crypto::sax::ConstOfSecurityId::UNDEFINEDSECURITYID || + pElementCollector->getSecurityId() != nIgnoredSecurityId; + }); + + if ( !rc ) + { + rc = std::any_of(m_vChildren.begin(), m_vChildren.end(), + [nIgnoredSecurityId](const std::unique_ptr<BufferNode>& pBufferNode) { + return pBufferNode->isECInSubTreeIncluded(nIgnoredSecurityId); + }); + } + + return rc; +} + +bool BufferNode::isECOfBeforeModifyInAncestorIncluded(sal_Int32 nIgnoredSecurityId) const +/****** BufferNode/isECOfBeforeModifyInAncestorIncluded ********************** + * + * NAME + * isECOfBeforeModifyInAncestorIncluded -- checks whether there is some + * ancestor BufferNode which has ElementCollector with PRI_BEFPREMODIFY + * priority. + * + * SYNOPSIS + * bExist = isECOfBeforeModifyInAncestorIncluded(nIgnoredSecurityId); + * + * FUNCTION + * checks each ancestor BufferNode through the parent link, if there is + * an ElementCollector with PRI_BEFPREMODIFY priority and its + * signatureId is not ignored, then return true, otherwise, false + * returned. + * + * INPUTS + * nIgnoredSecurityId - the security Id to be ignored. If it equals + * to UNDEFINEDSECURITYID, then no security Id + * will be ignored. + * + * RESULT + * bExist - true if a match found, false otherwise. + ******************************************************************************/ +{ + bool rc = false; + + BufferNode* pParentNode = m_pParent; + while (pParentNode != nullptr) + { + if (pParentNode->isECOfBeforeModifyIncluded(nIgnoredSecurityId)) + { + rc = true; + break; + } + + pParentNode = const_cast<BufferNode*>(pParentNode->getParent()); + } + + return rc; +} + +bool BufferNode::isBlockerInSubTreeIncluded(sal_Int32 nIgnoredSecurityId) const +/****** BufferNode/isBlockerInSubTreeIncluded ******************************** + * + * NAME + * isBlockerInSubTreeIncluded -- checks whether there is some BufferNode + * which has blocker on it + * + * SYNOPSIS + * bExist = isBlockerInSubTreeIncluded(nIgnoredSecurityId); + * + * FUNCTION + * checks each BufferNode in the branch of this BufferNode, if one has + * a blocker on it, and the blocker's securityId is not ignored, then + * returns true; otherwise, false returns. + * + * INPUTS + * nIgnoredSecurityId - the security Id to be ignored. If it equals + * to UNDEFINEDSECURITYID, then no security Id + * will be ignored. + * + * RESULT + * bExist - true if a match found, false otherwise. + ******************************************************************************/ +{ + return std::any_of(m_vChildren.begin(), m_vChildren.end(), + [nIgnoredSecurityId](const std::unique_ptr<BufferNode>& pBufferNode) { + ElementMark* pBlocker = pBufferNode->getBlocker(); + return (pBlocker != nullptr && + (nIgnoredSecurityId == css::xml::crypto::sax::ConstOfSecurityId::UNDEFINEDSECURITYID || + pBlocker->getSecurityId() != nIgnoredSecurityId )) || + pBufferNode->isBlockerInSubTreeIncluded(nIgnoredSecurityId); + }); +} + +const BufferNode* BufferNode::getNextChild(const BufferNode* pChild) const +/****** BufferNode/getNextChild ********************************************** + * + * NAME + * getNextChild -- get the next child BufferNode. + * + * SYNOPSIS + * nextChild = getNextChild(); + * + * FUNCTION + * see NAME + * + * INPUTS + * pChild - the child BufferNode whose next node is retrieved. + * + * RESULT + * nextChild - the next child BufferNode after the pChild, or NULL if + * there is none. + ******************************************************************************/ +{ + BufferNode* rc = nullptr; + bool bChildFound = false; + + for( std::unique_ptr<BufferNode> const & i : m_vChildren ) + { + if (bChildFound) + { + rc = i.get(); + break; + } + + if( i.get() == pChild ) + { + bChildFound = true; + } + } + + return rc; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/framework/buffernode.hxx b/xmlsecurity/source/framework/buffernode.hxx new file mode 100644 index 0000000000..f59ae2f816 --- /dev/null +++ b/xmlsecurity/source/framework/buffernode.hxx @@ -0,0 +1,118 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <com/sun/star/uno/Reference.hxx> + +#include <memory> +#include <vector> + +namespace com::sun::star::xml::wrapper +{ +class XXMLElementWrapper; +} + +class ElementMark; +class ElementCollector; + +class BufferNode final +/****** buffernode.hxx/CLASS BufferNode *************************************** + * + * NAME + * BufferNode -- Class to maintain the tree of buffered elements + * + * FUNCTION + * One BufferNode object represents a buffered element in the document + * wrapper component. + * All BufferNode objects construct a tree which has the same structure + * of all buffered elements. That is to say, if one buffered element is + * an ancestor of another buffered element, then the corresponding + * BufferNode objects are also in ancestor/descendant relationship. + * This class is used to manipulate the tree of buffered elements. + ******************************************************************************/ +{ +private: + /* the parent BufferNode */ + BufferNode* m_pParent; + + /* all child BufferNodes */ + std::vector<std::unique_ptr<BufferNode>> m_vChildren; + + /* all ElementCollector holding this BufferNode */ + std::vector<const ElementCollector*> m_vElementCollectors; + + /* + * the blocker holding this BufferNode, one BufferNode can have one + * blocker at most + */ + ElementMark* m_pBlocker; + + /* + * whether the element has completely buffered by the document wrapper + * component + */ + bool m_bAllReceived; + + /* the XMLElementWrapper of the buffered element */ + css::uno::Reference<css::xml::wrapper::XXMLElementWrapper> m_xXMLElement; + +private: + bool isECInSubTreeIncluded(sal_Int32 nIgnoredSecurityId) const; + bool isECOfBeforeModifyInAncestorIncluded(sal_Int32 nIgnoredSecurityId) const; + bool isBlockerInSubTreeIncluded(sal_Int32 nIgnoredSecurityId) const; + const BufferNode* getNextChild(const BufferNode* pChild) const; + +public: + explicit BufferNode(css::uno::Reference<css::xml::wrapper::XXMLElementWrapper> xXMLElement); + + bool isECOfBeforeModifyIncluded(sal_Int32 nIgnoredSecurityId) const; + void setReceivedAll(); + bool isAllReceived() const { return m_bAllReceived; } + void addElementCollector(const ElementCollector* pElementCollector); + void removeElementCollector(const ElementCollector* pElementCollector); + ElementMark* getBlocker() const { return m_pBlocker; } + void setBlocker(const ElementMark* pBlocker); + OUString printChildren() const; + bool hasAnything() const; + bool hasChildren() const; + std::vector<std::unique_ptr<BufferNode>> const& getChildren() const; + std::vector<std::unique_ptr<BufferNode>> releaseChildren(); + const BufferNode* getFirstChild() const; + void addChild(std::unique_ptr<BufferNode> pChild, sal_Int32 nPosition); + void addChild(std::unique_ptr<BufferNode> pChild); + void removeChild(const BufferNode* pChild); + sal_Int32 indexOfChild(const BufferNode* pChild) const; + const BufferNode* getParent() const { return m_pParent; } + void setParent(const BufferNode* pParent); + const BufferNode* getNextSibling() const; + const BufferNode* isAncestor(const BufferNode* pDescendant) const; + bool isPrevious(const BufferNode* pFollowing) const; + const BufferNode* getNextNodeByTreeOrder() const; + const css::uno::Reference<css::xml::wrapper::XXMLElementWrapper>& getXMLElement() const + { + return m_xXMLElement; + } + void + setXMLElement(const css::uno::Reference<css::xml::wrapper::XXMLElementWrapper>& xXMLElement); + void notifyBranch(); + void elementCollectorNotify(); +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/framework/elementcollector.cxx b/xmlsecurity/source/framework/elementcollector.cxx new file mode 100644 index 0000000000..d8f7fb04e7 --- /dev/null +++ b/xmlsecurity/source/framework/elementcollector.cxx @@ -0,0 +1,138 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "elementmark.hxx" +#include "elementcollector.hxx" +#include <com/sun/star/xml/crypto/sax/ConstOfSecurityId.hpp> +#include <com/sun/star/xml/crypto/sax/XReferenceResolvedListener.hpp> +#include <utility> + +ElementCollector::ElementCollector( + sal_Int32 nBufferId, + css::xml::crypto::sax::ElementMarkPriority nPriority, + bool bToModify, + css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > xReferenceResolvedListener) + :ElementMark(css::xml::crypto::sax::ConstOfSecurityId::UNDEFINEDSECURITYID, nBufferId), + m_nPriority(nPriority), + m_bToModify(bToModify), + m_bAbleToNotify(false), + m_bNotified(false), + m_xReferenceResolvedListener(std::move(xReferenceResolvedListener)) +/****** ElementCollector/ElementCollector ************************************* + * + * NAME + * ElementCollector -- constructor method + * + * SYNOPSIS + * ElementCollector(nSecurityId, nBufferId, nPriority, bToModify + * xReferenceResolvedListener); + * + * FUNCTION + * construct an ElementCollector object. + * + * INPUTS + * nSecurityId - represents which security entity the buffer node is + * related with. Either a signature or an encryption is + * a security entity. + * nBufferId - the id of the element buffered in the document + * wrapper component. The document wrapper component + * uses this id to search the particular buffered + * element. + * nPriority - the priority value. ElementCollector with lower + * priority value can't notify until all ElementCollectors + * with higher priority value have notified. + * bToModify - A flag representing whether this ElementCollector + * notification will cause the modification of its working + * element. + * xReferenceResolvedListener + * - the listener that this ElementCollector notifies to. + ******************************************************************************/ +{ + m_type = css::xml::crypto::sax::ElementMarkType_ELEMENTCOLLECTOR; +} + + +void ElementCollector::notifyListener() +/****** ElementCollector/notifyListener *************************************** + * + * NAME + * notifyListener -- enable the ability to notify the listener + * + * SYNOPSIS + * notifyListener(); + * + * FUNCTION + * enable the ability to notify the listener and try to notify then. + ******************************************************************************/ +{ + m_bAbleToNotify = true; + doNotify(); +} + +void ElementCollector::setReferenceResolvedListener( + const css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener >& xReferenceResolvedListener) +/****** ElementCollector/setReferenceResolvedListener ************************* + * + * NAME + * setReferenceResolvedListener -- configures a listener for the buffer + * node in this object + * + * SYNOPSIS + * setReferenceResolvedListener(xReferenceResolvedListener); + * + * FUNCTION + * configures a new listener and try to notify then. + * + * INPUTS + * xReferenceResolvedListener - the new listener + ******************************************************************************/ +{ + m_xReferenceResolvedListener = xReferenceResolvedListener; + doNotify(); +} + +void ElementCollector::doNotify() +/****** ElementCollector/doNotify ********************************************* + * + * NAME + * doNotify -- tries to notify the listener + * + * SYNOPSIS + * doNotify(); + * + * FUNCTION + * notifies the listener when all below conditions are satisfied: + * the listener has not been notified; + * the notify right is granted; + * the listener has already been configured; + * the security id has already been configure + ******************************************************************************/ +{ + if (!m_bNotified && + m_bAbleToNotify && + m_xReferenceResolvedListener.is() && + m_nSecurityId != css::xml::crypto::sax::ConstOfSecurityId::UNDEFINEDSECURITYID) + { + m_bNotified = true; + m_xReferenceResolvedListener->referenceResolved(m_nBufferId); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/framework/elementcollector.hxx b/xmlsecurity/source/framework/elementcollector.hxx new file mode 100644 index 0000000000..29447e882b --- /dev/null +++ b/xmlsecurity/source/framework/elementcollector.hxx @@ -0,0 +1,80 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include "elementmark.hxx" +#include <com/sun/star/xml/crypto/sax/ElementMarkPriority.hpp> +#include <com/sun/star/uno/Reference.hxx> + +namespace com::sun::star::xml::crypto::sax { class XReferenceResolvedListener; } + +class ElementCollector : public ElementMark +/****** elementcollector.hxx/CLASS ElementCollector *************************** + * + * NAME + * ElementCollector -- Class to manipulate an element collector + * + * FUNCTION + * This class is derived from the ElementMark class. Beyond the function + * of the ElementMark class, this class also maintains the priority, and + * manages the notify process + ******************************************************************************/ +{ +private: + /* + * the notify priority, is one of following values: + * AFTERMODIFY - this ElementCollector will notify after all + * internal modifications have finished. + * BEFOREMODIFY - this ElementCollector must notify before any + * internal modification happens. + */ + css::xml::crypto::sax::ElementMarkPriority const m_nPriority; + + /* + * the modify flag, representing whether which elementcollector will + * modify its data. + */ + bool const m_bToModify; + + /* the notify enable flag, see notifyListener method */ + bool m_bAbleToNotify; + + /* whether the listener has been notified */ + bool m_bNotified; + + /* the listener to be notified */ + css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > m_xReferenceResolvedListener; + +public: + ElementCollector( + sal_Int32 nBufferId, + css::xml::crypto::sax::ElementMarkPriority nPriority, + bool bToModify, + css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > xReferenceResolvedListener); + + css::xml::crypto::sax::ElementMarkPriority getPriority() const { return m_nPriority;} + bool getModify() const { return m_bToModify;} + void notifyListener(); + void setReferenceResolvedListener( + const css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener >& referenceResolvedListener); + void doNotify(); +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/framework/elementmark.cxx b/xmlsecurity/source/framework/elementmark.cxx new file mode 100644 index 0000000000..71444d7cd3 --- /dev/null +++ b/xmlsecurity/source/framework/elementmark.cxx @@ -0,0 +1,64 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "elementmark.hxx" + +ElementMark::ElementMark(sal_Int32 nSecurityId, sal_Int32 nBufferId) + :m_pBufferNode(nullptr), + m_nSecurityId(nSecurityId), + m_nBufferId(nBufferId), + m_type(css::xml::crypto::sax::ElementMarkType_ELEMENTMARK) +/****** ElementMark/ElementMark *********************************************** + * + * NAME + * ElementMark -- constructor method + * + * SYNOPSIS + * ElementMark(nSecurityId, nBufferId); + * + * FUNCTION + * construct an ElementMark object. + * + * INPUTS + * nSecurityId - represents which security entity the buffer node is + * related with. Either a signature or an encryption is + * a security entity. + * nBufferId - the id of the element buffered in the document + * wrapper component. The document wrapper component + * uses this id to search the particular buffered + * element. + ******************************************************************************/ +{ +} + + +void ElementMark::setBufferNode(const BufferNode* pBufferNode) +{ + m_pBufferNode = const_cast<BufferNode*>(pBufferNode); +} + + +void ElementMark::setSecurityId(sal_Int32 nSecurityId) +{ + m_nSecurityId = nSecurityId; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/framework/elementmark.hxx b/xmlsecurity/source/framework/elementmark.hxx new file mode 100644 index 0000000000..94ca71fdfb --- /dev/null +++ b/xmlsecurity/source/framework/elementmark.hxx @@ -0,0 +1,67 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <com/sun/star/xml/crypto/sax/ElementMarkType.hpp> + +class BufferNode; + +class ElementMark +/****** elementmark.hxx/CLASS ElementMark ************************************* + * + * NAME + * ElementMark -- Class to manipulate an element mark + * + * FUNCTION + * This class maintains the security id, buffer id and its type for a + * buffer node. + ******************************************************************************/ +{ +protected: + /* the BufferNode maintained by this object */ + BufferNode* m_pBufferNode; + + /* the security Id */ + sal_Int32 m_nSecurityId; + + /* the buffer Id */ + sal_Int32 const m_nBufferId; + + /* + * the type value, is one of following values: + * TYPEOFELEMENTMARK - the default value, represents a blocker if + * not changed + * TYPEOFELEMENTCOLLECTOR - represents an ElementCollector + */ + css::xml::crypto::sax::ElementMarkType m_type; + +public: + ElementMark(sal_Int32 nSecurityId, sal_Int32 nBufferId); + virtual ~ElementMark(){}; + + BufferNode* getBufferNode() const { return m_pBufferNode; } + void setBufferNode(const BufferNode* pBufferNode); + sal_Int32 getSecurityId() const { return m_nSecurityId; } + void setSecurityId(sal_Int32 nSecurityId); + css::xml::crypto::sax::ElementMarkType getType() const { return m_type; } + sal_Int32 getBufferId() const { return m_nBufferId; } +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/framework/saxeventkeeperimpl.cxx b/xmlsecurity/source/framework/saxeventkeeperimpl.cxx new file mode 100644 index 0000000000..b5a7f02728 --- /dev/null +++ b/xmlsecurity/source/framework/saxeventkeeperimpl.cxx @@ -0,0 +1,1152 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include <framework/saxeventkeeperimpl.hxx> +#include "buffernode.hxx" +#include "elementmark.hxx" +#include "elementcollector.hxx" +#include <com/sun/star/xml/sax/XDocumentHandler.hpp> +#include <com/sun/star/xml/crypto/sax/ConstOfSecurityId.hpp> +#include <com/sun/star/xml/wrapper/XXMLDocumentWrapper.hpp> +#include <com/sun/star/xml/csax/XCompressedDocumentHandler.hpp> +#include <cppuhelper/supportsservice.hxx> +#include <osl/diagnose.h> +#include <rtl/ustrbuf.hxx> + +#include <algorithm> + +SAXEventKeeperImpl::SAXEventKeeperImpl( ) + :m_pCurrentBufferNode(nullptr), + m_nNextElementMarkId(1), + m_pNewBlocker(nullptr), + m_pCurrentBlockingBufferNode(nullptr), + m_bIsReleasing(false), + m_bIsForwarding(false) +{ + m_vElementMarkBuffers.reserve(2); + m_vNewElementCollectors.reserve(2); + m_vReleasedElementMarkBuffers.reserve(2); +} + +SAXEventKeeperImpl::~SAXEventKeeperImpl() +{ + /* + * delete the BufferNode tree + */ + m_pRootBufferNode.reset(); + + m_pCurrentBufferNode = m_pCurrentBlockingBufferNode = nullptr; + + /* + * delete all unfreed ElementMarks + */ + m_vNewElementCollectors.clear(); + m_pNewBlocker = nullptr; +} + +void SAXEventKeeperImpl::setCurrentBufferNode(BufferNode* pBufferNode) +/****** SAXEventKeeperImpl/setCurrentBufferNode ****************************** + * + * NAME + * setCurrentBufferNode -- set a new active BufferNode. + * + * SYNOPSIS + * setCurrentBufferNode( pBufferNode ); + * + * FUNCTION + * connects this BufferNode into the BufferNode tree as a child of the + * current active BufferNode. Then makes this BufferNode as the current + * active BufferNode. + * If the previous active BufferNode points to the root + * BufferNode, which means that no buffering operation was proceeding, + * then notifies the status change listener that buffering operation + * will begin at once. + * + * INPUTS + * pBufferNode - a BufferNode which will be the new active BufferNode + ******************************************************************************/ +{ + if (pBufferNode == m_pCurrentBufferNode) + return; + + if ( m_pCurrentBufferNode == m_pRootBufferNode.get() && + m_xSAXEventKeeperStatusChangeListener.is()) + { + m_xSAXEventKeeperStatusChangeListener->collectionStatusChanged(true); + } + + if (pBufferNode->getParent() == nullptr) + { + m_pCurrentBufferNode->addChild(std::unique_ptr<BufferNode>(pBufferNode)); + pBufferNode->setParent(m_pCurrentBufferNode); + } + + m_pCurrentBufferNode = pBufferNode; +} + +BufferNode* SAXEventKeeperImpl::addNewElementMarkBuffers() +/****** SAXEventKeeperImpl/addNewElementMarkBuffers ************************** + * + * NAME + * addNewElementMarkBuffers -- add new ElementCollectors and new Blocker. + * + * SYNOPSIS + * pBufferNode = addNewElementMarkBuffers( ); + * + * FUNCTION + * if there are new ElementCollector or new Blocker to be added, then + * connect all of them with the current BufferNode. In case of the + * current BufferNode doesn't exist, creates one. + * Clears up the new ElementCollector list and the new Blocker pointer. + * + * RESULT + * pBufferNode - the BufferNode that has been connected with both new + * ElementCollectors and new Blocker. + ******************************************************************************/ +{ + BufferNode* pBufferNode = nullptr; + + if (m_pNewBlocker || !m_vNewElementCollectors.empty() ) + { + /* + * When the current BufferNode is right pointing to the current + * working element in the XMLDocumentWrapper component, then + * no new BufferNode is needed to create. + * This situation can only happen in the "Forwarding" mode. + */ + if ( (m_pCurrentBufferNode != nullptr) && + (m_xXMLDocument->isCurrent(m_pCurrentBufferNode->getXMLElement()))) + { + pBufferNode = m_pCurrentBufferNode; + } + else + { + pBufferNode = new BufferNode(m_xXMLDocument->getCurrentElement()); + } + + if (m_pNewBlocker != nullptr) + { + pBufferNode->setBlocker(m_pNewBlocker); + + /* + * If no blocking before, then notify the status change listener that + * the SAXEventKeeper has entered "blocking" status, during which, no + * SAX events will be forwarded to the next document handler. + */ + if (m_pCurrentBlockingBufferNode == nullptr) + { + m_pCurrentBlockingBufferNode = pBufferNode; + + if (m_xSAXEventKeeperStatusChangeListener.is()) + { + m_xSAXEventKeeperStatusChangeListener->blockingStatusChanged(true); + } + } + + m_pNewBlocker = nullptr; + } + + for( const auto& i : m_vNewElementCollectors ) + { + pBufferNode->addElementCollector(i); + } + m_vNewElementCollectors.clear(); + } + + return pBufferNode; +} + +ElementMark* SAXEventKeeperImpl::findElementMarkBuffer(sal_Int32 nId) const +/****** SAXEventKeeperImpl/findElementMarkBuffer ***************************** + * + * NAME + * findElementMarkBuffer -- finds an ElementMark. + * + * SYNOPSIS + * pElementMark = findElementMarkBuffer( nId ); + * + * FUNCTION + * searches an ElementMark with the particular Id in the ElementMark + * list. + * + * INPUTS + * nId - the Id of the ElementMark to be searched. + * + * RESULT + * pElementMark - the ElementMark with the particular Id, or NULL when + * no such Id exists. + ******************************************************************************/ +{ + ElementMark* pElementMark = nullptr; + + for( auto&& ii : m_vElementMarkBuffers ) + { + if ( nId == ii->getBufferId()) + { + pElementMark = const_cast<ElementMark*>(ii.get()); + break; + } + } + + return pElementMark; +} + +void SAXEventKeeperImpl::removeElementMarkBuffer(sal_Int32 nId) +/****** SAXEventKeeperImpl/removeElementMarkBuffer *************************** + * + * NAME + * removeElementMarkBuffer -- removes an ElementMark + * + * SYNOPSIS + * removeElementMarkBuffer( nId ); + * + * FUNCTION + * removes an ElementMark with the particular Id in the ElementMark list. + * + * INPUTS + * nId - the Id of the ElementMark to be removed. + ******************************************************************************/ +{ + auto ii = std::find_if(m_vElementMarkBuffers.begin(), m_vElementMarkBuffers.end(), + [nId](std::unique_ptr<const ElementMark>& rElementMark) { return nId == rElementMark->getBufferId(); } + ); + if (ii == m_vElementMarkBuffers.end()) + return; + + /* + * checks whether this ElementMark still in the new ElementCollect array + */ + auto jj = std::find_if(m_vNewElementCollectors.begin(), m_vNewElementCollectors.end(), + [&ii](const ElementCollector* pElementCollector) { return ii->get() == pElementCollector; } + ); + if (jj != m_vNewElementCollectors.end()) + m_vNewElementCollectors.erase(jj); + + /* + * checks whether this ElementMark is the new Blocker + */ + if (ii->get() == m_pNewBlocker) + { + m_pNewBlocker = nullptr; + } + + m_vElementMarkBuffers.erase( ii ); +} + +OUString SAXEventKeeperImpl::printBufferNode( + BufferNode const * pBufferNode, sal_Int32 nIndent) const +/****** SAXEventKeeperImpl/printBufferNode *********************************** + * + * NAME + * printBufferNode -- retrieves the information of a BufferNode and its + * branch. + * + * SYNOPSIS + * info = printBufferNode( pBufferNode, nIndent ); + * + * FUNCTION + * all retrieved information includes: + * 1. whether it is the current BufferNode; + * 2. whether it is the current blocking BufferNode; + * 3. the name of the parent element; + * 4. the name of this element; + * 5. all ElementCollectors working on this BufferNode; + * 6. the Blocker working on this BufferNode; + * 7. all child BufferNodes' information. + * + * INPUTS + * pBufferNode - the BufferNode from where information will be retrieved. + * nIndent - how many space characters prefixed before the output + * message. + * + * RESULT + * info - the information string + ******************************************************************************/ +{ + OUStringBuffer rc; + + for ( int i=0; i<nIndent; ++i ) + { + rc.append(" "); + } + + if (pBufferNode == m_pCurrentBufferNode) + { + rc.append("[%]"); + } + + if (pBufferNode == m_pCurrentBlockingBufferNode) + { + rc.append("[B]"); + } + + rc.append(" " + m_xXMLDocument->getNodeName(pBufferNode->getXMLElement())); + + BufferNode* pParent = const_cast<BufferNode*>(pBufferNode->getParent()); + if (pParent != nullptr) + { + rc.append("[" + m_xXMLDocument->getNodeName(pParent->getXMLElement()) + "]"); + } + + rc.append(":EC=" + pBufferNode->printChildren() + " BR="); + + ElementMark * pBlocker = pBufferNode->getBlocker(); + if (pBlocker != nullptr) + { + rc.append( OUString::number(pBlocker->getBufferId()) + + "(SecId=" + OUString::number( pBlocker->getSecurityId() ) + ") "); + } + rc.append("\n"); + + std::vector< std::unique_ptr<BufferNode> > const & vChildren = pBufferNode->getChildren(); + for( const auto& jj : vChildren ) + { + rc.append(printBufferNode(jj.get(), nIndent+4)); + } + + return rc.makeStringAndClear(); +} + +css::uno::Sequence< css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > > + SAXEventKeeperImpl::collectChildWorkingElement(BufferNode const * pBufferNode) +/****** SAXEventKeeperImpl/collectChildWorkingElement ************************ + * + * NAME + * collectChildWorkingElement -- collects a BufferNode's all child + * Elements. + * + * SYNOPSIS + * list = collectChildWorkingElement( pBufferNode ); + * + * INPUTS + * pBufferNode - the BufferNode whose child Elements will be collected. + * + * RESULT + * list - the child Elements list. + ******************************************************************************/ +{ + std::vector< std::unique_ptr<BufferNode> > const & vChildren = pBufferNode->getChildren(); + + css::uno::Sequence < css::uno::Reference< + css::xml::wrapper::XXMLElementWrapper > > aChildrenCollection ( vChildren.size()); + + std::transform(vChildren.begin(), vChildren.end(), aChildrenCollection.getArray(), + [](const auto& i) { return i->getXMLElement(); }); + + return aChildrenCollection; +} + +void SAXEventKeeperImpl::smashBufferNode( + BufferNode* pBufferNode, bool bClearRoot) const +/****** SAXEventKeeperImpl/smashBufferNode *********************************** + * + * NAME + * smashBufferNode -- removes a BufferNode along with its working + * element. + * + * SYNOPSIS + * smashBufferNode( pBufferNode, bClearRoot ); + * + * FUNCTION + * removes the BufferNode's working element from the DOM document, while + * reserves all ancestor paths for its child BufferNodes. + * when any of the BufferNode's ancestor element is useless, removes it + * too. + * removes the BufferNode from the BufferNode tree. + * + * INPUTS + * pBufferNode - the BufferNode to be removed + * bClearRoot - whether the root element also needs to be cleared up. + * + * NOTES + * when removing a Blocker's BufferNode, the bClearRoot flag should be + * true. Because a Blocker can buffer many SAX events which are not used + * by any other ElementCollector or Blocker. + * When the bClearRoot is set to true, the root BufferNode will be first + * cleared, with a stop flag setting at the next Blocking BufferNode. This + * operation can delete all useless buffered SAX events which are only + * needed by the Blocker to be deleted. + ******************************************************************************/ +{ + if (pBufferNode->hasAnything()) + return; + + BufferNode* pParent = const_cast<BufferNode*>(pBufferNode->getParent()); + + /* + * delete the XML data + */ + if (pParent == m_pRootBufferNode.get()) + { + bool bIsNotBlocking = (m_pCurrentBlockingBufferNode == nullptr); + bool bIsBlockInside = false; + bool bIsBlockingAfterward = false; + + /* + * If this is a blocker, then remove any out-element data + * which caused by blocking. The removal process will stop + * at the next blocker to avoid removing any useful data. + */ + if (bClearRoot) + { + css::uno::Sequence< css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > > + aChildElements = collectChildWorkingElement(m_pRootBufferNode.get()); + + /* + * the clearUselessData only clearup the content in the + * node, not the node itself. + */ + m_xXMLDocument->clearUselessData(m_pRootBufferNode->getXMLElement(), + aChildElements, + bIsNotBlocking?nullptr: + (m_pCurrentBlockingBufferNode->getXMLElement())); + + /* + * remove the node if it is empty, then if its parent is also + * empty, remove it, then if the next parent is also empty, + * remove it,..., until parent become null. + */ + m_xXMLDocument->collapse( m_pRootBufferNode->getXMLElement() ); + } + + /* + * if blocking, check the relationship between this BufferNode and + * the current blocking BufferNode. + */ + if ( !bIsNotBlocking ) + { + /* + * the current blocking BufferNode is a descendant of this BufferNode. + */ + bIsBlockInside = (nullptr != pBufferNode->isAncestor(m_pCurrentBlockingBufferNode)); + + /* + * the current blocking BufferNode locates behind this BufferNode in tree + * order. + */ + bIsBlockingAfterward = pBufferNode->isPrevious(m_pCurrentBlockingBufferNode); + } + + /* + * this BufferNode's working element needs to be deleted only when + * 1. there is no blocking, or + * 2. the current blocking BufferNode is a descendant of this BufferNode, + * (then in the BufferNode's working element, the useless data before the blocking + * element should be deleted.) or + * 3. the current blocking BufferNode is locates behind this BufferNode in tree, + * (then the useless data between the blocking element and the working element + * should be deleted.). + * Otherwise, this working element should not be deleted. + */ + if ( bIsNotBlocking || bIsBlockInside || bIsBlockingAfterward ) + { + css::uno::Sequence< css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > > + aChildElements = collectChildWorkingElement(pBufferNode); + + /* + * the clearUselessData only clearup the content in the + * node, not the node itself. + */ + m_xXMLDocument->clearUselessData(pBufferNode->getXMLElement(), + aChildElements, + bIsBlockInside?(m_pCurrentBlockingBufferNode->getXMLElement()): + nullptr); + + /* + * remove the node if it is empty, then if its parent is also + * empty, remove it, then if the next parent is also empty, + * remove it,..., until parent become null. + */ + m_xXMLDocument->collapse( pBufferNode->getXMLElement() ); + } + } + + sal_Int32 nIndex = pParent->indexOfChild(pBufferNode); + + std::vector< std::unique_ptr<BufferNode> > vChildren = pBufferNode->releaseChildren(); + pParent->removeChild(pBufferNode); // delete buffernode + + for( auto& i : vChildren ) + { + i->setParent(pParent); + pParent->addChild(std::move(i), nIndex); + nIndex++; + } +} + +BufferNode* SAXEventKeeperImpl::findNextBlockingBufferNode( + BufferNode* pStartBufferNode) +/****** SAXEventKeeperImpl/findNextBlockingBufferNode ************************ + * + * NAME + * findNextBlockingBufferNode -- finds the next blocking BufferNode + * behind the particular BufferNode. + * + * SYNOPSIS + * pBufferNode = findNextBlockingBufferNode( pStartBufferNode ); + * + * INPUTS + * pStartBufferNode - the BufferNode from where to search the next + * blocking BufferNode. + * + * RESULT + * pBufferNode - the next blocking BufferNode, or NULL if no such + * BufferNode exists. + ******************************************************************************/ +{ + BufferNode* pNext = nullptr; + + if (pStartBufferNode != nullptr) + { + pNext = pStartBufferNode; + + while (nullptr != (pNext = const_cast<BufferNode*>(pNext->getNextNodeByTreeOrder()))) + { + if (pNext->getBlocker() != nullptr) + { + break; + } + } + } + + return pNext; +} + +void SAXEventKeeperImpl::diffuse(BufferNode* pBufferNode) +/****** SAXEventKeeperImpl/diffuse ******************************************* + * + * NAME + * diffuse -- diffuse the notification. + * + * SYNOPSIS + * diffuse( pBufferNode ); + * + * FUNCTION + * diffuse the collecting completion notification from the specific + * BufferNode along its parent link, until an ancestor which is not + * completely received is met. + * + * INPUTS + * pBufferNode - the BufferNode from which the notification will be + * diffused. + ******************************************************************************/ +{ + BufferNode* pParent = pBufferNode; + + while(pParent->isAllReceived()) + { + pParent->elementCollectorNotify(); + pParent = const_cast<BufferNode*>(pParent->getParent()); + } +} + +void SAXEventKeeperImpl::releaseElementMarkBuffer() +/****** SAXEventKeeperImpl/releaseElementMarkBuffer ************************** + * + * NAME + * releaseElementMarkBuffer -- releases useless ElementMarks + * + * SYNOPSIS + * releaseElementMarkBuffer( ); + * + * FUNCTION + * releases each ElementMark in the releasing list + * m_vReleasedElementMarkBuffers. + * The operation differs between an ElementCollector and a Blocker. + ******************************************************************************/ +{ + m_bIsReleasing = true; + while (!m_vReleasedElementMarkBuffers.empty()) + { + auto pId = m_vReleasedElementMarkBuffers.begin(); + sal_Int32 nId = *pId; + m_vReleasedElementMarkBuffers.erase( pId ); + + ElementMark* pElementMark = findElementMarkBuffer(nId); + + if (pElementMark != nullptr) + { + if (css::xml::crypto::sax::ElementMarkType_ELEMENTCOLLECTOR + == pElementMark->getType()) + /* + * it is a EC + */ + { + ElementCollector* pElementCollector = static_cast<ElementCollector*>(pElementMark); + + css::xml::crypto::sax::ElementMarkPriority nPriority = pElementCollector->getPriority(); + /* + * Delete the EC from the buffer node. + */ + BufferNode* pBufferNode = pElementCollector->getBufferNode(); + pBufferNode->removeElementCollector(pElementCollector); + + if ( nPriority == css::xml::crypto::sax::ElementMarkPriority_BEFOREMODIFY) + { + pBufferNode->notifyBranch(); + } + + /* + * delete the ElementMark + */ + pElementCollector = nullptr; + pElementMark = nullptr; + removeElementMarkBuffer(nId); + + /* + * delete the BufferNode + */ + diffuse(pBufferNode); + smashBufferNode(pBufferNode, false); + } + else + /* + * it is a Blocker + */ + { + /* + * Delete the TH from the buffer node. + */ + BufferNode *pBufferNode = pElementMark->getBufferNode(); + pBufferNode->setBlocker(nullptr); + + /* + * If there is a following handler and no blocking now, then + * forward this event + */ + if (m_pCurrentBlockingBufferNode == pBufferNode) + { + /* + * Before forwarding, the next blocking point needs to be + * found. + */ + m_pCurrentBlockingBufferNode = findNextBlockingBufferNode(pBufferNode); + + /* + * Forward the blocked events between these two STHs. + */ + if (m_xNextHandler.is()) + { + BufferNode* pTempCurrentBufferNode = m_pCurrentBufferNode; + BufferNode* pTempCurrentBlockingBufferNode = m_pCurrentBlockingBufferNode; + + m_pCurrentBufferNode = pBufferNode; + m_pCurrentBlockingBufferNode = nullptr; + + m_bIsForwarding = true; + + m_xXMLDocument->generateSAXEvents( + m_xNextHandler, + this, + pBufferNode->getXMLElement(), + (pTempCurrentBlockingBufferNode == nullptr)?nullptr:(pTempCurrentBlockingBufferNode->getXMLElement())); + + m_bIsForwarding = false; + + m_pCurrentBufferNode = pTempCurrentBufferNode; + if (m_pCurrentBlockingBufferNode == nullptr) + { + m_pCurrentBlockingBufferNode = pTempCurrentBlockingBufferNode; + } + } + + if (m_pCurrentBlockingBufferNode == nullptr && + m_xSAXEventKeeperStatusChangeListener.is()) + { + m_xSAXEventKeeperStatusChangeListener->blockingStatusChanged(false); + } + } + + /* + * delete the ElementMark + */ + pElementMark = nullptr; + removeElementMarkBuffer(nId); + + /* + * delete the BufferNode + */ + diffuse(pBufferNode); + smashBufferNode(pBufferNode, true); + } + } + } + + m_bIsReleasing = false; + + if (!m_pRootBufferNode->hasAnything() && + !m_pRootBufferNode->hasChildren() && + m_xSAXEventKeeperStatusChangeListener.is()) + { + m_xSAXEventKeeperStatusChangeListener->bufferStatusChanged(true); + } +} + +void SAXEventKeeperImpl::markElementMarkBuffer(sal_Int32 nId) +/****** SAXEventKeeperImpl/markElementMarkBuffer ***************************** + * + * NAME + * markElementMarkBuffer -- marks an ElementMark to be released + * + * SYNOPSIS + * markElementMarkBuffer( nId ); + * + * FUNCTION + * puts the ElementMark with the particular Id into the releasing list, + * checks whether the releasing process is running, if not then launch + * this process. + * + * INPUTS + * nId - the Id of the ElementMark which will be released + ******************************************************************************/ +{ + m_vReleasedElementMarkBuffers.push_back( nId ); + if ( !m_bIsReleasing ) + { + releaseElementMarkBuffer(); + } +} + +sal_Int32 SAXEventKeeperImpl::createElementCollector( + css::xml::crypto::sax::ElementMarkPriority nPriority, + bool bModifyElement, + const css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener >& xReferenceResolvedListener) +/****** SAXEventKeeperImpl/createElementCollector **************************** + * + * NAME + * createElementCollector -- creates a new ElementCollector on the + * incoming element. + * + * SYNOPSIS + * nId = createElementCollector( nSecurityId, nPriority, + * bModifyElement, + * xReferenceResolvedListener ); + * + * FUNCTION + * allocs a new Id, then create an ElementCollector with this Id value. + * Add the new created ElementCollector to the new ElementCollecotor list. + * + * INPUTS + * nPriority - the priority of the new ElementCollector + * bModifyElement -whether this BufferNode will modify the content of + * the corresponding element it works on + * xReferenceResolvedListener - the listener for the new ElementCollector. + * + * RESULT + * nId - the Id of the new ElementCollector + ******************************************************************************/ +{ + sal_Int32 nId = m_nNextElementMarkId; + m_nNextElementMarkId ++; + + ElementCollector* pElementCollector + = new ElementCollector( + nId, + nPriority, + bModifyElement, + xReferenceResolvedListener); + + m_vElementMarkBuffers.push_back( + std::unique_ptr<const ElementMark>(pElementCollector)); + + /* + * All the new EC to initial EC array. + */ + m_vNewElementCollectors.push_back( pElementCollector ); + + return nId; +} + + +sal_Int32 SAXEventKeeperImpl::createBlocker() +/****** SAXEventKeeperImpl/createBlocker ************************************* + * + * NAME + * createBlocker -- creates a new Blocker on the incoming element. + * + * SYNOPSIS + * nId = createBlocker( nSecurityId ); + * + * RESULT + * nId - the Id of the new Blocker + ******************************************************************************/ +{ + sal_Int32 nId = m_nNextElementMarkId; + m_nNextElementMarkId ++; + + OSL_ASSERT(m_pNewBlocker == nullptr); + + m_pNewBlocker = new ElementMark(css::xml::crypto::sax::ConstOfSecurityId::UNDEFINEDSECURITYID, nId); + m_vElementMarkBuffers.push_back( + std::unique_ptr<const ElementMark>(m_pNewBlocker)); + + return nId; +} + +/* XSAXEventKeeper */ +sal_Int32 SAL_CALL SAXEventKeeperImpl::addElementCollector( ) +{ + return createElementCollector( + css::xml::crypto::sax::ElementMarkPriority_AFTERMODIFY, + false, + nullptr); +} + +void SAL_CALL SAXEventKeeperImpl::removeElementCollector( sal_Int32 id ) +{ + markElementMarkBuffer(id); +} + +sal_Int32 SAL_CALL SAXEventKeeperImpl::addBlocker( ) +{ + return createBlocker(); +} + +void SAL_CALL SAXEventKeeperImpl::removeBlocker( sal_Int32 id ) +{ + markElementMarkBuffer(id); +} + +sal_Bool SAL_CALL SAXEventKeeperImpl::isBlocking( ) +{ + return (m_pCurrentBlockingBufferNode != nullptr); +} + +css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > SAL_CALL + SAXEventKeeperImpl::getElement( sal_Int32 id ) +{ + css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > rc; + + ElementMark* pElementMark = findElementMarkBuffer(id); + if (pElementMark != nullptr) + { + rc = pElementMark->getBufferNode()->getXMLElement(); + } + + return rc; +} + +void SAL_CALL SAXEventKeeperImpl::setElement( + sal_Int32 id, + const css::uno::Reference< css::xml::wrapper::XXMLElementWrapper >& aElement ) +{ + if (aElement.is()) + { + m_xXMLDocument->rebuildIDLink(aElement); + + ElementMark* pElementMark = findElementMarkBuffer(id); + + if (pElementMark != nullptr) + { + BufferNode* pBufferNode = pElementMark->getBufferNode(); + if (pBufferNode != nullptr) + { + const bool bIsCurrent = m_xXMLDocument->isCurrent(pBufferNode->getXMLElement()); + pBufferNode->setXMLElement(aElement); + + if (bIsCurrent) + { + m_xXMLDocument->setCurrentElement(aElement); + } + } + } + } + else + { + removeElementCollector( id ); + } +} + +css::uno::Reference< css::xml::sax::XDocumentHandler > SAL_CALL SAXEventKeeperImpl::setNextHandler( + const css::uno::Reference< css::xml::sax::XDocumentHandler >& xNewHandler ) +{ + css::uno::Reference< css::xml::sax::XDocumentHandler > xOldHandler = m_xNextHandler; + + m_xNextHandler = xNewHandler; + return xOldHandler; +} + +OUString SAL_CALL SAXEventKeeperImpl::printBufferNodeTree() +{ + OUString rc = "ElementMarkBuffers: size = " + + OUString::number(m_vElementMarkBuffers.size()) + + "\nCurrentBufferNode: " + + m_xXMLDocument->getNodeName(m_pCurrentBufferNode->getXMLElement()) + + "\n" + printBufferNode(m_pRootBufferNode.get(), 0); + + return rc; +} + +css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > SAL_CALL SAXEventKeeperImpl::getCurrentBlockingNode() +{ + css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > rc; + + if (m_pCurrentBlockingBufferNode != nullptr) + { + rc = m_pCurrentBlockingBufferNode->getXMLElement(); + } + + return rc; +} + +/* XSecuritySAXEventKeeper */ +sal_Int32 SAL_CALL SAXEventKeeperImpl::addSecurityElementCollector( + css::xml::crypto::sax::ElementMarkPriority priority, + sal_Bool modifyElement ) +{ + return createElementCollector( + priority, + modifyElement, + nullptr); +} + +void SAL_CALL SAXEventKeeperImpl::setSecurityId( sal_Int32 id, sal_Int32 securityId ) +{ + ElementMark* pElementMark = findElementMarkBuffer(id); + if (pElementMark != nullptr) + { + pElementMark->setSecurityId(securityId); + } +} + + +/* XReferenceResolvedBroadcaster */ +void SAL_CALL SAXEventKeeperImpl::addReferenceResolvedListener( + sal_Int32 referenceId, + const css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener >& listener ) +{ + ElementCollector* pElementCollector = static_cast<ElementCollector*>(findElementMarkBuffer(referenceId)); + if (pElementCollector != nullptr) + { + pElementCollector->setReferenceResolvedListener(listener); + } +} + +void SAL_CALL SAXEventKeeperImpl::removeReferenceResolvedListener( + sal_Int32 /*referenceId*/, + const css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener >&) +{ +} + +/* XSAXEventKeeperStatusChangeBroadcaster */ +void SAL_CALL SAXEventKeeperImpl::addSAXEventKeeperStatusChangeListener( + const css::uno::Reference< css::xml::crypto::sax::XSAXEventKeeperStatusChangeListener >& listener ) +{ + m_xSAXEventKeeperStatusChangeListener = listener; +} + +void SAL_CALL SAXEventKeeperImpl::removeSAXEventKeeperStatusChangeListener( + const css::uno::Reference< css::xml::crypto::sax::XSAXEventKeeperStatusChangeListener >&) +{ +} + +/* XDocumentHandler */ +void SAL_CALL SAXEventKeeperImpl::startDocument( ) +{ + if ( m_xNextHandler.is()) + { + m_xNextHandler->startDocument(); + } +} + +void SAL_CALL SAXEventKeeperImpl::endDocument( ) +{ + if ( m_xNextHandler.is()) + { + m_xNextHandler->endDocument(); + } +} + +void SAL_CALL SAXEventKeeperImpl::startElement( + const OUString& aName, + const css::uno::Reference< css::xml::sax::XAttributeList >& xAttribs ) +{ + /* + * If there is a following handler and no blocking now, then + * forward this event + */ + if ((m_pCurrentBlockingBufferNode == nullptr) && + (m_xNextHandler.is()) && + (!m_bIsForwarding) && + (m_pNewBlocker == nullptr)) + { + m_xNextHandler->startElement(aName, xAttribs); + } + /* + * If not forwarding, buffer this startElement. + */ + if (!m_bIsForwarding) + { + sal_Int32 nLength = xAttribs->getLength(); + css::uno::Sequence< css::xml::csax::XMLAttribute > aAttributes (nLength); + auto aAttributesRange = asNonConstRange(aAttributes); + + for ( int i = 0; i<nLength; ++i ) + { + aAttributesRange[i].sName = xAttribs->getNameByIndex(static_cast<short>(i)); + aAttributesRange[i].sValue =xAttribs->getValueByIndex(static_cast<short>(i)); + } + + m_xCompressedDocumentHandler->compressedStartElement(aName, aAttributes); + } + + BufferNode* pBufferNode = addNewElementMarkBuffers(); + if (pBufferNode != nullptr) + { + setCurrentBufferNode(pBufferNode); + } +} + +void SAL_CALL SAXEventKeeperImpl::endElement( const OUString& aName ) +{ + const bool bIsCurrent = m_xXMLDocument->isCurrent(m_pCurrentBufferNode->getXMLElement()); + + /* + * If there is a following handler and no blocking now, then + * forward this event + */ + if ((m_pCurrentBlockingBufferNode == nullptr) && + (m_xNextHandler.is()) && + (!m_bIsForwarding)) + { + m_xNextHandler->endElement(aName); + } + + if ((m_pCurrentBlockingBufferNode != nullptr) || + (m_pCurrentBufferNode != m_pRootBufferNode.get()) || + (!m_xXMLDocument->isCurrentElementEmpty())) + { + if (!m_bIsForwarding) + { + m_xCompressedDocumentHandler->compressedEndElement(aName); + } + + /* + * If the current buffer node has not notified yet, and + * the current buffer node is waiting for the current element, + * then let it notify. + */ + if (bIsCurrent && (m_pCurrentBufferNode != m_pRootBufferNode.get())) + { + BufferNode* pOldCurrentBufferNode = m_pCurrentBufferNode; + m_pCurrentBufferNode = const_cast<BufferNode*>(m_pCurrentBufferNode->getParent()); + + pOldCurrentBufferNode->setReceivedAll(); + + if ((m_pCurrentBufferNode == m_pRootBufferNode.get()) && + m_xSAXEventKeeperStatusChangeListener.is()) + { + m_xSAXEventKeeperStatusChangeListener->collectionStatusChanged(false); + } + } + } + else + { + if (!m_bIsForwarding) + { + m_xXMLDocument->removeCurrentElement(); + } + } +} + +void SAL_CALL SAXEventKeeperImpl::characters( const OUString& aChars ) +{ + if (m_bIsForwarding) + return; + + if ((m_pCurrentBlockingBufferNode == nullptr) && m_xNextHandler.is()) + { + m_xNextHandler->characters(aChars); + } + + if ((m_pCurrentBlockingBufferNode != nullptr) || + (m_pCurrentBufferNode != m_pRootBufferNode.get())) + { + m_xCompressedDocumentHandler->compressedCharacters(aChars); + } +} + +void SAL_CALL SAXEventKeeperImpl::ignorableWhitespace( const OUString& aWhitespaces ) +{ + characters( aWhitespaces ); +} + +void SAL_CALL SAXEventKeeperImpl::processingInstruction( + const OUString& aTarget, const OUString& aData ) +{ + if (m_bIsForwarding) + return; + + if ((m_pCurrentBlockingBufferNode == nullptr) && m_xNextHandler.is()) + { + m_xNextHandler->processingInstruction(aTarget, aData); + } + + if ((m_pCurrentBlockingBufferNode != nullptr) || + (m_pCurrentBufferNode != m_pRootBufferNode.get())) + { + m_xCompressedDocumentHandler->compressedProcessingInstruction(aTarget, aData); + } +} + +void SAL_CALL SAXEventKeeperImpl::setDocumentLocator( const css::uno::Reference< css::xml::sax::XLocator >&) +{ +} + +/* XInitialization */ +void SAL_CALL SAXEventKeeperImpl::initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) +{ + OSL_ASSERT(aArguments.getLength() == 1); + + aArguments[0] >>= m_xXMLDocument; + m_xDocumentHandler.set( m_xXMLDocument, css::uno::UNO_QUERY ); + m_xCompressedDocumentHandler.set( m_xXMLDocument, css::uno::UNO_QUERY ); + + m_pRootBufferNode.reset( new BufferNode(m_xXMLDocument->getCurrentElement()) ); + m_pCurrentBufferNode = m_pRootBufferNode.get(); +} + +OUString SAXEventKeeperImpl_getImplementationName () +{ + return "com.sun.star.xml.security.framework.SAXEventKeeperImpl"; +} + +css::uno::Sequence< OUString > SAXEventKeeperImpl_getSupportedServiceNames( ) +{ + return { "com.sun.star.xml.crypto.sax.SAXEventKeeper" }; +} + +/* XServiceInfo */ +OUString SAL_CALL SAXEventKeeperImpl::getImplementationName( ) +{ + return SAXEventKeeperImpl_getImplementationName(); +} + +sal_Bool SAL_CALL SAXEventKeeperImpl::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL SAXEventKeeperImpl::getSupportedServiceNames( ) +{ + return SAXEventKeeperImpl_getSupportedServiceNames(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/framework/securityengine.cxx b/xmlsecurity/source/framework/securityengine.cxx new file mode 100644 index 0000000000..e276163d41 --- /dev/null +++ b/xmlsecurity/source/framework/securityengine.cxx @@ -0,0 +1,67 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include <framework/securityengine.hxx> + + +SecurityEngine::SecurityEngine() + :m_nIdOfTemplateEC(-1), + m_nNumOfResolvedReferences(0), + m_nIdOfKeyEC(-1), + m_bMissionDone(false), + m_nSecurityId(-1), + m_nStatus(css::xml::crypto::SecurityOperationStatus_UNKNOWN) +{ +} + +/* XReferenceResolvedListener */ +void SAL_CALL SecurityEngine::referenceResolved( sal_Int32 /*referenceId*/) +{ + m_nNumOfResolvedReferences++; + tryToPerform(); +} + +/* XKeyCollector */ +void SAL_CALL SecurityEngine::setKeyId( sal_Int32 id ) +{ + m_nIdOfKeyEC = id; + tryToPerform(); +} + +/* XMissionTaker */ +sal_Bool SAL_CALL SecurityEngine::endMission( ) +{ + bool rc = m_bMissionDone; + + if (!rc) + { + clearUp( ); + + notifyResultListener(); + m_bMissionDone = true; + } + + m_xResultListener = nullptr; + m_xSAXEventKeeper = nullptr; + + return rc; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/framework/signaturecreatorimpl.cxx b/xmlsecurity/source/framework/signaturecreatorimpl.cxx new file mode 100644 index 0000000000..4371b7ae69 --- /dev/null +++ b/xmlsecurity/source/framework/signaturecreatorimpl.cxx @@ -0,0 +1,175 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include <framework/signaturecreatorimpl.hxx> +#include <framework/xmlsignaturetemplateimpl.hxx> +#include <com/sun/star/xml/crypto/XXMLSignatureTemplate.hpp> +#include <cppuhelper/supportsservice.hxx> +#include <osl/diagnose.h> +#include <rtl/ref.hxx> + +namespace com::sun::star::xml::wrapper { class XXMLElementWrapper; } + +using namespace com::sun::star::uno; + +SignatureCreatorImpl::SignatureCreatorImpl() + : m_nIdOfBlocker(-1) +{ +} + +SignatureCreatorImpl::~SignatureCreatorImpl( ) +{ +} + +void SignatureCreatorImpl::notifyResultListener() const +/****** SignatureCreatorImpl/notifyResultListener ***************************** + * + * NAME + * notifyResultListener -- notifies the listener about the signature + * creation result. + ******************************************************************************/ +{ + css::uno::Reference< css::xml::crypto::sax::XSignatureCreationResultListener > + xSignatureCreationResultListener ( m_xResultListener , css::uno::UNO_QUERY ) ; + + xSignatureCreationResultListener->signatureCreated( m_nSecurityId, m_nStatus ); +} + +void SignatureCreatorImpl::startEngine(const rtl::Reference<XMLSignatureTemplateImpl>& xSignatureTemplate) +/****** SignatureCreatorImpl/startEngine ************************************* + * + * NAME + * startEngine -- generates the signature. + * + * FUNCTION + * generates the signature element, then if succeeds, updates the link + * of old template element to the new signature element in + * SAXEventKeeper. + * + * INPUTS + * xSignatureTemplate - the signature template (along with all referenced + * elements) to be signed. + ******************************************************************************/ +{ + css::uno::Reference< css::xml::crypto::XXMLSignatureTemplate > xResultTemplate; + try + { + xResultTemplate = m_xXMLSignature->generate(css::uno::Reference<css::xml::crypto::XXMLSignatureTemplate>(xSignatureTemplate), m_xSecurityEnvironment); + m_nStatus = xResultTemplate->getStatus(); + } + catch( css::uno::Exception& ) + { + m_nStatus = css::xml::crypto::SecurityOperationStatus_RUNTIMEERROR_FAILED; + } + + if (m_nStatus == css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED) + { + css::uno::Reference < css::xml::wrapper::XXMLElementWrapper > xResultSignature = xResultTemplate->getTemplate(); + m_xSAXEventKeeper->setElement(m_nIdOfTemplateEC, xResultSignature); + } +} + +void SignatureCreatorImpl::clearUp() const +/****** SignatureCreatorImpl/clearUp ***************************************** + * + * NAME + * clearUp -- clear up all resources used by the signature generation. + * + * SYNOPSIS + * clearUp( ); + * + * FUNCTION + * cleaning resources up includes: + * 1. SignatureEngine's clearing up; + * 2. releases the Blocker for the signature template element. + ******************************************************************************/ +{ + SignatureEngine::clearUp(); + + if (m_nIdOfBlocker != -1) + { + m_xSAXEventKeeper->removeBlocker(m_nIdOfBlocker); + } +} + +/* XBlockerMonitor */ +void SAL_CALL SignatureCreatorImpl::setBlockerId( sal_Int32 id ) +{ + m_nIdOfBlocker = id; + tryToPerform(); +} + +/* XSignatureCreationResultBroadcaster */ +void SAL_CALL SignatureCreatorImpl::addSignatureCreationResultListener( + const css::uno::Reference< css::xml::crypto::sax::XSignatureCreationResultListener >& listener ) +{ + m_xResultListener = listener; + tryToPerform(); +} + +void SAL_CALL SignatureCreatorImpl::removeSignatureCreationResultListener( + const css::uno::Reference< css::xml::crypto::sax::XSignatureCreationResultListener >&) +{ +} + +/* XInitialization */ +void SAL_CALL SignatureCreatorImpl::initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) +{ + OSL_ASSERT(aArguments.getLength() == 5); + + OUString ouTempString; + + aArguments[0] >>= ouTempString; + m_nSecurityId = ouTempString.toInt32(); + aArguments[1] >>= m_xSAXEventKeeper; + aArguments[2] >>= ouTempString; + m_nIdOfTemplateEC = ouTempString.toInt32(); + aArguments[3] >>= m_xSecurityEnvironment; + aArguments[4] >>= m_xXMLSignature; +} + + +OUString SignatureCreatorImpl_getImplementationName () +{ + return "com.sun.star.xml.security.framework.SignatureCreatorImpl"; +} + +css::uno::Sequence< OUString > SignatureCreatorImpl_getSupportedServiceNames( ) +{ + return { "com.sun.star.xml.crypto.sax.SignatureCreator" }; +} + +/* XServiceInfo */ +OUString SAL_CALL SignatureCreatorImpl::getImplementationName( ) +{ + return SignatureCreatorImpl_getImplementationName(); +} + +sal_Bool SAL_CALL SignatureCreatorImpl::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL SignatureCreatorImpl::getSupportedServiceNames( ) +{ + return SignatureCreatorImpl_getSupportedServiceNames(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/framework/signatureengine.cxx b/xmlsecurity/source/framework/signatureengine.cxx new file mode 100644 index 0000000000..0390ea7e61 --- /dev/null +++ b/xmlsecurity/source/framework/signatureengine.cxx @@ -0,0 +1,197 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include <framework/signatureengine.hxx> +#include <framework/xmlsignaturetemplateimpl.hxx> +#include <rtl/ref.hxx> + +namespace com::sun::star::xml::wrapper { class XXMLElementWrapper; } + +using namespace com::sun::star::uno; + +SignatureEngine::SignatureEngine() + : m_nTotalReferenceNumber(-1) +{ +} + +bool SignatureEngine::checkReady() const +/****** SignatureEngine/checkReady ******************************************* + * + * NAME + * checkReady -- checks the conditions for the main operation. + * + * SYNOPSIS + * bReady = checkReady( ); + * + * FUNCTION + * checks whether all following conditions are satisfied: + * 1. the main operation has't begun yet; + * 2. the key material is known; + * 3. the amount of reference is known; + * 4. all of referenced elements, the key element and the signature + * template are buffered. + * + * RESULT + * bReady - true if all conditions are satisfied, false otherwise + ******************************************************************************/ +{ + bool rc = true; + + sal_Int32 nKeyInc = 0; + if (m_nIdOfKeyEC != 0) + { + nKeyInc = 1; + } + + if (m_bMissionDone || + m_nIdOfKeyEC == -1 || + m_nTotalReferenceNumber == -1 || + m_nTotalReferenceNumber+1+nKeyInc > m_nNumOfResolvedReferences) + { + rc = false; + } + + return rc; +} + +void SignatureEngine::tryToPerform( ) +/****** SignatureEngine/tryToPerform ***************************************** + * + * NAME + * tryToPerform -- tries to perform the signature operation. + * + * FUNCTION + * if the situation is ready, perform following operations. + * 1. prepares a signature template; + * 2. calls the signature bridge component; + * 3. clears up all used resources; + * 4. notifies the result listener; + * 5. sets the "accomplishment" flag. + ******************************************************************************/ +{ + if (!checkReady()) + return; + + rtl::Reference<XMLSignatureTemplateImpl> xSignatureTemplate = new XMLSignatureTemplateImpl(); + + css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > + xXMLElement = m_xSAXEventKeeper->getElement( m_nIdOfTemplateEC ); + + xSignatureTemplate->setTemplate(xXMLElement); + + for( const auto i : m_vReferenceIds ) + { + xXMLElement = m_xSAXEventKeeper->getElement( i ); + xSignatureTemplate->setTarget(xXMLElement); + } + + /* + * set the Uri binding + */ + xSignatureTemplate->setBinding( this ); + + startEngine(xSignatureTemplate); + + /* + * done + */ + clearUp( ); + + notifyResultListener(); + + m_bMissionDone = true; +} + +void SignatureEngine::clearUp( ) const +/****** SignatureEngine/clearUp ********************************************** + * + * NAME + * clearUp -- clear up all resources used by this operation. + * + * FUNCTION + * cleaning resources up includes: + * 1. releases the ElementCollector for the signature template element; + * 2. releases ElementCollectors for referenced elements; + * 3. releases the ElementCollector for the key element, if there is one. + ******************************************************************************/ +{ + css::uno::Reference < css::xml::crypto::sax::XReferenceResolvedBroadcaster > + xReferenceResolvedBroadcaster( m_xSAXEventKeeper, css::uno::UNO_QUERY ); + xReferenceResolvedBroadcaster->removeReferenceResolvedListener( + m_nIdOfTemplateEC, + static_cast<const css::uno::Reference < css::xml::crypto::sax::XReferenceResolvedListener > >(static_cast<SecurityEngine *>(const_cast<SignatureEngine *>(this)))); + + m_xSAXEventKeeper->removeElementCollector(m_nIdOfTemplateEC); + + for( const auto& i : m_vReferenceIds ) + { + xReferenceResolvedBroadcaster->removeReferenceResolvedListener( + i, + static_cast<const css::uno::Reference < css::xml::crypto::sax::XReferenceResolvedListener > >(static_cast<SecurityEngine *>(const_cast<SignatureEngine *>(this)))); + m_xSAXEventKeeper->removeElementCollector(i); + } + + if (m_nIdOfKeyEC != 0 && m_nIdOfKeyEC != -1) + { + m_xSAXEventKeeper->removeElementCollector(m_nIdOfKeyEC); + } +} + +/* XReferenceCollector */ +void SAL_CALL SignatureEngine::setReferenceCount( sal_Int32 count ) +{ + m_nTotalReferenceNumber = count; + tryToPerform(); +} + +void SAL_CALL SignatureEngine::setReferenceId( sal_Int32 id ) +{ + m_vReferenceIds.push_back( id ); +} + +/* XUriBinding */ +void SAL_CALL SignatureEngine::setUriBinding( + const OUString& uri, + const css::uno::Reference< css::io::XInputStream >& aInputStream ) +{ + m_vUris.push_back(uri); + m_vXInputStreams.push_back(aInputStream); +} + +css::uno::Reference< css::io::XInputStream > SAL_CALL SignatureEngine::getUriBinding( const OUString& uri ) +{ + css::uno::Reference< css::io::XInputStream > xInputStream; + + int size = m_vUris.size(); + + for( int i=0; i<size; ++i) + { + if (m_vUris[i] == uri) + { + xInputStream = m_vXInputStreams[i]; + break; + } + } + + return xInputStream; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/framework/signatureverifierimpl.cxx b/xmlsecurity/source/framework/signatureverifierimpl.cxx new file mode 100644 index 0000000000..44e9e4c0a4 --- /dev/null +++ b/xmlsecurity/source/framework/signatureverifierimpl.cxx @@ -0,0 +1,130 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include <framework/signatureverifierimpl.hxx> +#include <framework/xmlsignaturetemplateimpl.hxx> +#include <com/sun/star/xml/crypto/XXMLSignatureTemplate.hpp> +#include <cppuhelper/supportsservice.hxx> +#include <osl/diagnose.h> +#include <rtl/ref.hxx> + + +SignatureVerifierImpl::SignatureVerifierImpl() +{ +} + +SignatureVerifierImpl::~SignatureVerifierImpl() +{ +} + +void SignatureVerifierImpl::notifyResultListener() const +/****** SignatureVerifierImpl/notifyResultListener *************************** + * + * NAME + * notifyResultListener -- notifies the listener about the verify result. + ******************************************************************************/ +{ + css::uno::Reference< css::xml::crypto::sax::XSignatureVerifyResultListener > + xSignatureVerifyResultListener ( m_xResultListener , css::uno::UNO_QUERY ) ; + + xSignatureVerifyResultListener->signatureVerified( m_nSecurityId, m_nStatus ); +} + +void SignatureVerifierImpl::startEngine( const rtl::Reference<XMLSignatureTemplateImpl>& xSignatureTemplate) +/****** SignatureVerifierImpl/startEngine ************************************ + * + * NAME + * startEngine -- verifies the signature. + * + * INPUTS + * xSignatureTemplate - the signature template (along with all referenced + * elements) to be verified. + ******************************************************************************/ +{ + css::uno::Reference< css::xml::crypto::XXMLSignatureTemplate > xResultTemplate; + try + { + xResultTemplate = m_xXMLSignature->validate(css::uno::Reference<css::xml::crypto::XXMLSignatureTemplate>(xSignatureTemplate), m_xXMLSecurityContext); + m_nStatus = xResultTemplate->getStatus(); + } + catch( css::uno::Exception& ) + { + m_nStatus = css::xml::crypto::SecurityOperationStatus_RUNTIMEERROR_FAILED; + } +} + +/* XSignatureVerifyResultBroadcaster */ +void SAL_CALL SignatureVerifierImpl::addSignatureVerifyResultListener( + const css::uno::Reference< css::xml::crypto::sax::XSignatureVerifyResultListener >& listener ) +{ + m_xResultListener = listener; + tryToPerform(); +} + +void SAL_CALL SignatureVerifierImpl::removeSignatureVerifyResultListener( + const css::uno::Reference< css::xml::crypto::sax::XSignatureVerifyResultListener >&) +{ +} + +/* XInitialization */ +void SAL_CALL SignatureVerifierImpl::initialize( + const css::uno::Sequence< css::uno::Any >& aArguments ) +{ + OSL_ASSERT(aArguments.getLength() == 5); + + OUString ouTempString; + + aArguments[0] >>= ouTempString; + m_nSecurityId = ouTempString.toInt32(); + aArguments[1] >>= m_xSAXEventKeeper; + aArguments[2] >>= ouTempString; + m_nIdOfTemplateEC = ouTempString.toInt32(); + aArguments[3] >>= m_xXMLSecurityContext; + aArguments[4] >>= m_xXMLSignature; +} + + +OUString SignatureVerifierImpl_getImplementationName () +{ + return "com.sun.star.xml.security.framework.SignatureVerifierImpl"; +} + +css::uno::Sequence< OUString > SignatureVerifierImpl_getSupportedServiceNames( ) +{ + return { "com.sun.star.xml.crypto.sax.SignatureVerifier" }; +} + +/* XServiceInfo */ +OUString SAL_CALL SignatureVerifierImpl::getImplementationName( ) +{ + return SignatureVerifierImpl_getImplementationName(); +} + +sal_Bool SAL_CALL SignatureVerifierImpl::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL SignatureVerifierImpl::getSupportedServiceNames( ) +{ + return SignatureVerifierImpl_getSupportedServiceNames(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/framework/xmlsignaturetemplateimpl.cxx b/xmlsecurity/source/framework/xmlsignaturetemplateimpl.cxx new file mode 100644 index 0000000000..203f0fea20 --- /dev/null +++ b/xmlsecurity/source/framework/xmlsignaturetemplateimpl.cxx @@ -0,0 +1,113 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> +#include <rtl/ustring.hxx> +#include <framework/xmlsignaturetemplateimpl.hxx> +#include <comphelper/sequence.hxx> +#include <cppuhelper/supportsservice.hxx> + +using namespace ::com::sun::star::uno ; +using ::com::sun::star::lang::XMultiServiceFactory ; + +using ::com::sun::star::xml::wrapper::XXMLElementWrapper ; +using ::com::sun::star::xml::crypto::XXMLSignatureTemplate ; + +XMLSignatureTemplateImpl::XMLSignatureTemplateImpl() + :m_nStatus ( css::xml::crypto::SecurityOperationStatus_UNKNOWN ) +{ +} + +XMLSignatureTemplateImpl::~XMLSignatureTemplateImpl() { +} + +/* XXMLSignatureTemplate */ +void SAL_CALL XMLSignatureTemplateImpl::setTemplate( const Reference< XXMLElementWrapper >& aTemplate ) +{ + m_xTemplate = aTemplate ; +} + +/* XXMLSignatureTemplate */ +Reference< XXMLElementWrapper > SAL_CALL XMLSignatureTemplateImpl::getTemplate() +{ + return m_xTemplate ; +} + +void SAL_CALL XMLSignatureTemplateImpl::setTarget( const css::uno::Reference< css::xml::wrapper::XXMLElementWrapper >& aXmlElement ) +{ + targets.push_back( aXmlElement ); +} + +css::uno::Sequence< css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > > SAL_CALL XMLSignatureTemplateImpl::getTargets() +{ + return comphelper::containerToSequence(targets); +} + +void SAL_CALL XMLSignatureTemplateImpl::setBinding( + const css::uno::Reference< css::xml::crypto::XUriBinding >& aUriBinding ) +{ + m_xUriBinding = aUriBinding; +} + +css::uno::Reference< css::xml::crypto::XUriBinding > SAL_CALL XMLSignatureTemplateImpl::getBinding() +{ + return m_xUriBinding; +} + +void SAL_CALL XMLSignatureTemplateImpl::setStatus( + css::xml::crypto::SecurityOperationStatus status ) +{ + m_nStatus = status; +} + +css::xml::crypto::SecurityOperationStatus SAL_CALL XMLSignatureTemplateImpl::getStatus( ) +{ + return m_nStatus; +} + +/* XServiceInfo */ +OUString SAL_CALL XMLSignatureTemplateImpl::getImplementationName() { + return impl_getImplementationName() ; +} + +/* XServiceInfo */ +sal_Bool SAL_CALL XMLSignatureTemplateImpl::supportsService( const OUString& serviceName) { + return cppu::supportsService(this, serviceName); +} + +/* XServiceInfo */ +Sequence< OUString > SAL_CALL XMLSignatureTemplateImpl::getSupportedServiceNames() { + return impl_getSupportedServiceNames() ; +} + +//Helper for XServiceInfo +Sequence< OUString > XMLSignatureTemplateImpl::impl_getSupportedServiceNames() { + Sequence<OUString> seqServiceNames { "com.sun.star.xml.crypto.XMLSignatureTemplate" }; + return seqServiceNames ; +} + +OUString XMLSignatureTemplateImpl::impl_getImplementationName() { + return "com.sun.star.xml.security.framework.XMLSignatureTemplateImpl" ; +} + +//Helper for registry +Reference< XInterface > XMLSignatureTemplateImpl::impl_createInstance( const Reference< XMultiServiceFactory >& ) { + return Reference< XInterface >( *new XMLSignatureTemplateImpl ) ; +} +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/gpg/CertificateImpl.cxx b/xmlsecurity/source/gpg/CertificateImpl.cxx new file mode 100644 index 0000000000..b771c1282f --- /dev/null +++ b/xmlsecurity/source/gpg/CertificateImpl.cxx @@ -0,0 +1,248 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <config_gpgme.h> + +#include "CertificateImpl.hxx" + +#include <comphelper/servicehelper.hxx> +#include <comphelper/sequence.hxx> +#include <cppuhelper/supportsservice.hxx> + +#include <com/sun/star/security/KeyUsage.hpp> +#include <officecfg/Office/Common.hxx> +#include <svl/sigstruct.hxx> + +#include <context.h> +#include <data.h> + +using namespace css; +using namespace css::uno; +using namespace css::security; +using namespace css::util; + +CertificateImpl::CertificateImpl() +{ +} + +CertificateImpl::~CertificateImpl() +{ +} + +//Methods from XCertificateImpl +sal_Int16 SAL_CALL CertificateImpl::getVersion() +{ + return 0; +} + +Sequence< sal_Int8 > SAL_CALL CertificateImpl::getSerialNumber() +{ + // TODO: perhaps map to subkey's cardSerialNumber - if you have + // one to test + return Sequence< sal_Int8 >(); +} + +OUString SAL_CALL CertificateImpl::getIssuerName() +{ + const GpgME::UserID userId = m_pKey.userID(0); + if (userId.isNull()) + return OUString(); + + return OStringToOUString(userId.id(), RTL_TEXTENCODING_UTF8); +} + +OUString SAL_CALL CertificateImpl::getSubjectName() +{ + // Same as issuer name (user ID) + return getIssuerName(); +} + +namespace { + DateTime convertUnixTimeToDateTime(time_t time) + { + DateTime dateTime; + struct tm *timeStruct = gmtime(&time); + dateTime.Year = timeStruct->tm_year + 1900; + dateTime.Month = timeStruct->tm_mon + 1; + dateTime.Day = timeStruct->tm_mday; + dateTime.Hours = timeStruct->tm_hour; + dateTime.Minutes = timeStruct->tm_min; + dateTime.Seconds = timeStruct->tm_sec; + return dateTime; + } +} + +DateTime SAL_CALL CertificateImpl::getNotValidBefore() +{ + const GpgME::Subkey subkey = m_pKey.subkey(0); + if (subkey.isNull()) + return DateTime(); + + return convertUnixTimeToDateTime(m_pKey.subkey(0).creationTime()); +} + +DateTime SAL_CALL CertificateImpl::getNotValidAfter() +{ + const GpgME::Subkey subkey = m_pKey.subkey(0); + if (subkey.isNull() || subkey.neverExpires()) + return DateTime(); + + return convertUnixTimeToDateTime(m_pKey.subkey(0).expirationTime()); +} + +Sequence< sal_Int8 > SAL_CALL CertificateImpl::getIssuerUniqueID() +{ + // Empty for gpg + return Sequence< sal_Int8 > (); +} + +Sequence< sal_Int8 > SAL_CALL CertificateImpl::getSubjectUniqueID() +{ + // Empty for gpg + return Sequence< sal_Int8 > (); +} + +Sequence< Reference< XCertificateExtension > > SAL_CALL CertificateImpl::getExtensions() +{ + // Empty for gpg + return Sequence< Reference< XCertificateExtension > > (); +} + +Reference< XCertificateExtension > SAL_CALL CertificateImpl::findCertificateExtension( const Sequence< sal_Int8 >& /*oid*/ ) +{ + // Empty for gpg + return Reference< XCertificateExtension > (); +} + +Sequence< sal_Int8 > SAL_CALL CertificateImpl::getEncoded() +{ + // Export key to base64Empty for gpg + return m_aBits; +} + +OUString SAL_CALL CertificateImpl::getSubjectPublicKeyAlgorithm() +{ + const GpgME::Subkey subkey = m_pKey.subkey(0); + if (subkey.isNull()) + return OUString(); + + return OStringToOUString(subkey.publicKeyAlgorithmAsString(), RTL_TEXTENCODING_UTF8); +} + +Sequence< sal_Int8 > SAL_CALL CertificateImpl::getSubjectPublicKeyValue() +{ + return Sequence< sal_Int8 > (); +} + +OUString SAL_CALL CertificateImpl::getSignatureAlgorithm() +{ + const GpgME::UserID userId = m_pKey.userID(0); + if (userId.isNull()) + return OUString(); + + const GpgME::UserID::Signature signature = userId.signature(0); + if (signature.isNull()) + return OUString(); + + return OStringToOUString(signature.algorithmAsString(), RTL_TEXTENCODING_UTF8); +} + +Sequence< sal_Int8 > SAL_CALL CertificateImpl::getSHA1Thumbprint() +{ + // This is mapped to the fingerprint for gpg + const char* keyId = m_pKey.primaryFingerprint(); + return comphelper::arrayToSequence<sal_Int8>( + keyId, strlen(keyId)+1); +} + +Sequence<sal_Int8> CertificateImpl::getSHA256Thumbprint() +{ + // This is mapped to the fingerprint for gpg (though that's only + // SHA1 actually) + const char* keyId = m_pKey.primaryFingerprint(); + return comphelper::arrayToSequence<sal_Int8>( + keyId, strlen(keyId)+1); +} + +svl::crypto::SignatureMethodAlgorithm CertificateImpl::getSignatureMethodAlgorithm() +{ + return svl::crypto::SignatureMethodAlgorithm::RSA; +} + +Sequence< sal_Int8 > SAL_CALL CertificateImpl::getMD5Thumbprint() +{ + // This is mapped to the shorter keyID for gpg + const char* keyId = m_pKey.keyID(); + return comphelper::arrayToSequence<sal_Int8>( + keyId, strlen(keyId)+1); +} + +CertificateKind SAL_CALL CertificateImpl::getCertificateKind() +{ + return CertificateKind_OPENPGP; +} + +sal_Int32 SAL_CALL CertificateImpl::getCertificateUsage() +{ + return KeyUsage::DIGITAL_SIGNATURE | KeyUsage::NON_REPUDIATION | KeyUsage::KEY_ENCIPHERMENT | KeyUsage::DATA_ENCIPHERMENT; +} + +void CertificateImpl::setCertificate(GpgME::Context* ctx, const GpgME::Key& key) +{ + m_pKey = key; + + // extract key data, store into m_aBits + GpgME::Data data_out; + ctx->setArmor(false); // caller will base64-encode anyway + GpgME::Error err = ctx->exportPublicKeys( + key.primaryFingerprint(), + data_out, + officecfg::Office::Common::Security::OpenPGP::MinimalKeyExport::get() + ? GpgME::Context::ExportMinimal : 0 + ); + + if (err) + throw RuntimeException("The GpgME library failed to retrieve the public key"); + + off_t result = data_out.seek(0,SEEK_SET); + (void) result; + assert(result == 0); + int len=0, curr=0; char buf; + while( (curr=data_out.read(&buf, 1)) ) + len += curr; + + // write bits to sequence of bytes + m_aBits.realloc(len); + result = data_out.seek(0,SEEK_SET); + assert(result == 0); + if( data_out.read(m_aBits.getArray(), len) != len ) + throw RuntimeException("The GpgME library failed to read the key"); +} + +const GpgME::Key* CertificateImpl::getCertificate() const +{ + return &m_pKey; +} + +/* XServiceInfo */ +OUString SAL_CALL CertificateImpl::getImplementationName() +{ + return "com.sun.star.xml.security.gpg.XCertificate_GpgImpl"; +} + +/* XServiceInfo */ +sal_Bool SAL_CALL CertificateImpl::supportsService(const OUString& serviceName) +{ + return cppu::supportsService(this, serviceName); +} + +/* XServiceInfo */ +Sequence<OUString> SAL_CALL CertificateImpl::getSupportedServiceNames() { return { OUString() }; } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/gpg/CertificateImpl.hxx b/xmlsecurity/source/gpg/CertificateImpl.hxx new file mode 100644 index 0000000000..b0856ca010 --- /dev/null +++ b/xmlsecurity/source/gpg/CertificateImpl.hxx @@ -0,0 +1,93 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include <certificate.hxx> + +#include <sal/types.h> +#include <sal/config.h> +#include <rtl/ustring.hxx> +#include <cppuhelper/implbase.hxx> + +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/security/CertificateKind.hpp> +#include <com/sun/star/security/XCertificate.hpp> + +#if defined _MSC_VER && defined __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wundef" +#endif +#include <key.h> +#if defined _MSC_VER && defined __clang__ +#pragma clang diagnostic pop +#endif + +class CertificateImpl : public cppu::WeakImplHelper< css::security::XCertificate, + css::lang::XServiceInfo >, + public xmlsecurity::Certificate +{ +private: + GpgME::Key m_pKey; + css::uno::Sequence< sal_Int8 > m_aBits; + +public: + CertificateImpl(); + virtual ~CertificateImpl() override; + + //Methods from XCertificate + virtual sal_Int16 SAL_CALL getVersion() override; + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSerialNumber() override; + + virtual OUString SAL_CALL getIssuerName() override; + virtual OUString SAL_CALL getSubjectName() override; + + virtual css::util::DateTime SAL_CALL getNotValidBefore() override; + virtual css::util::DateTime SAL_CALL getNotValidAfter() override; + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getIssuerUniqueID() override; + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSubjectUniqueID() override; + + virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificateExtension > > SAL_CALL getExtensions() override; + + virtual css::uno::Reference< css::security::XCertificateExtension > SAL_CALL findCertificateExtension(const css::uno::Sequence< sal_Int8 >& oid) override; + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getEncoded() override; + + virtual OUString SAL_CALL getSubjectPublicKeyAlgorithm() override; + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSubjectPublicKeyValue() override; + + virtual OUString SAL_CALL getSignatureAlgorithm() override; + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSHA1Thumbprint() override; + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getMD5Thumbprint() override; + + virtual sal_Int32 SAL_CALL getCertificateUsage() override; + + /// @see xmlsecurity::Certificate::getSHA256Thumbprint(). + virtual css::uno::Sequence<sal_Int8> getSHA256Thumbprint() override; + /// @see xmlsecurity::Certificate::getSignatureMethodAlgorithm(). + virtual svl::crypto::SignatureMethodAlgorithm getSignatureMethodAlgorithm() override; + virtual css::security::CertificateKind SAL_CALL getCertificateKind() override; + + // Helper methods + void setCertificate(GpgME::Context* ctx, const GpgME::Key& key); + const GpgME::Key* getCertificate() const; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override; + virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override; +} ; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/gpg/CipherContext.cxx b/xmlsecurity/source/gpg/CipherContext.cxx new file mode 100644 index 0000000000..291db0ba66 --- /dev/null +++ b/xmlsecurity/source/gpg/CipherContext.cxx @@ -0,0 +1,27 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "CipherContext.hxx" + +using namespace css; +using namespace css::uno; +using namespace css::lang; + +Sequence<sal_Int8> + SAL_CALL CipherContext::convertWithCipherContext(const Sequence<sal_Int8>& /*aData*/) +{ + return Sequence<sal_Int8>(); +} + +uno::Sequence<sal_Int8> SAL_CALL CipherContext::finalizeCipherContextAndDispose() +{ + return Sequence<sal_Int8>(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/gpg/CipherContext.hxx b/xmlsecurity/source/gpg/CipherContext.hxx new file mode 100644 index 0000000000..2c0ffcdc9b --- /dev/null +++ b/xmlsecurity/source/gpg/CipherContext.hxx @@ -0,0 +1,26 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include <com/sun/star/xml/crypto/XCipherContext.hpp> + +#include <cppuhelper/implbase.hxx> + +class CipherContext : public cppu::WeakImplHelper<css::xml::crypto::XCipherContext> +{ +private: +public: + // XCipherContext + virtual css::uno::Sequence<::sal_Int8> + SAL_CALL convertWithCipherContext(const css::uno::Sequence<::sal_Int8>& aData) override; + virtual css::uno::Sequence<::sal_Int8> SAL_CALL finalizeCipherContextAndDispose() override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/gpg/DigestContext.cxx b/xmlsecurity/source/gpg/DigestContext.cxx new file mode 100644 index 0000000000..4864191bb8 --- /dev/null +++ b/xmlsecurity/source/gpg/DigestContext.cxx @@ -0,0 +1,23 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "DigestContext.hxx" + +using namespace css; +using namespace css::uno; +using namespace css::lang; + +void SAL_CALL DigestContext::updateDigest(const Sequence<sal_Int8>& /*aData*/) {} + +uno::Sequence<sal_Int8> SAL_CALL DigestContext::finalizeDigestAndDispose() +{ + return Sequence<sal_Int8>(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/gpg/DigestContext.hxx b/xmlsecurity/source/gpg/DigestContext.hxx new file mode 100644 index 0000000000..2d48daf344 --- /dev/null +++ b/xmlsecurity/source/gpg/DigestContext.hxx @@ -0,0 +1,24 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include <com/sun/star/xml/crypto/XDigestContext.hpp> + +#include <cppuhelper/implbase.hxx> + +class DigestContext : public cppu::WeakImplHelper<css::xml::crypto::XDigestContext> +{ +public: + // XDigestContext + virtual void SAL_CALL updateDigest(const css::uno::Sequence<::sal_Int8>& aData) override; + virtual css::uno::Sequence<::sal_Int8> SAL_CALL finalizeDigestAndDispose() override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/gpg/SEInitializer.cxx b/xmlsecurity/source/gpg/SEInitializer.cxx new file mode 100644 index 0000000000..5cfe325aa8 --- /dev/null +++ b/xmlsecurity/source/gpg/SEInitializer.cxx @@ -0,0 +1,80 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <cppuhelper/supportsservice.hxx> +#include <gpg/SEInitializer.hxx> +#include "SecurityEnvironment.hxx" +#include "XMLSecurityContext.hxx" + +#include <global.h> + +namespace com::sun::star::uno +{ +class XComponentContext; +} + +using namespace css; +using namespace css::lang; +using namespace css::uno; +using namespace css::xml::crypto; + +SEInitializerGpg::SEInitializerGpg() +{ + // Also init GpgME while we're at it + GpgME::initializeLibrary(); +} + +SEInitializerGpg::~SEInitializerGpg() {} + +/* XSEInitializer */ +Reference<XXMLSecurityContext> SAL_CALL SEInitializerGpg::createSecurityContext(const OUString&) +{ + try + { + /* Build XML Security Context */ + Reference<XXMLSecurityContext> xSecCtx(new XMLSecurityContextGpg()); + + Reference<XSecurityEnvironment> xSecEnv(new SecurityEnvironmentGpg()); + sal_Int32 n = xSecCtx->addSecurityEnvironment(xSecEnv); + //originally the SecurityEnvironment with the internal slot was set as default + xSecCtx->setDefaultSecurityEnvironmentIndex(n); + return xSecCtx; + } + catch (const uno::Exception&) + { + return nullptr; + } +} + +void SAL_CALL SEInitializerGpg::freeSecurityContext(const uno::Reference<XXMLSecurityContext>&) {} + +/* XServiceInfo */ +sal_Bool SAL_CALL SEInitializerGpg::supportsService(const OUString& rServiceName) +{ + return cppu::supportsService(this, rServiceName); +} + +uno::Sequence<OUString> SAL_CALL SEInitializerGpg::getSupportedServiceNames() +{ + return { "com.sun.star.xml.crypto.GPGSEInitializer" }; +} + +OUString SAL_CALL SEInitializerGpg::getImplementationName() +{ + return "com.sun.star.xml.security.SEInitializer_Gpg"; +} + +extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface* +com_sun_star_xml_security_SEInitializer_Gpg_get_implementation( + uno::XComponentContext* /*pCtx*/, uno::Sequence<uno::Any> const& /*rSeq*/) +{ + return cppu::acquire(new SEInitializerGpg()); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/gpg/SecurityEnvironment.cxx b/xmlsecurity/source/gpg/SecurityEnvironment.cxx new file mode 100644 index 0000000000..e6813228a4 --- /dev/null +++ b/xmlsecurity/source/gpg/SecurityEnvironment.cxx @@ -0,0 +1,217 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "SecurityEnvironment.hxx" +#include "CertificateImpl.hxx" + +#include <com/sun/star/security/CertificateCharacters.hpp> +#include <com/sun/star/security/CertificateValidity.hpp> + +#include <comphelper/servicehelper.hxx> +#include <vector> +#include <rtl/ref.hxx> + +#ifdef _WIN32 +#include <config_folders.h> +#include <osl/file.hxx> +#include <osl/process.h> +#include <rtl/bootstrap.hxx> +#include <tools/urlobj.hxx> +#endif + +#include <key.h> +#include <keylistresult.h> +#include <xmlsec-wrapper.h> + +#if defined _MSC_VER && defined __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wundef" +#endif +#include <gpgme.h> +#if defined _MSC_VER && defined __clang__ +#pragma clang diagnostic pop +#endif +#include <context.h> + +using namespace css; +using namespace css::security; +using namespace css::uno; +using namespace css::lang; + +SecurityEnvironmentGpg::SecurityEnvironmentGpg() +{ +#ifdef _WIN32 + // On Windows, gpgme expects gpgme-w32spawn.exe to be in the same directory as the current + // process executable. This assumption might be wrong, e.g., for bundled python, which is + // in instdir/program/python-core-x.y.z/bin, while gpgme-w32spawn.exe is in instdir/program. + // If we can't find gpgme-w32spawn.exe in the current executable location, then try to find + // the spawn executable, and inform gpgme about actual location using gpgme_set_global_flag. + [[maybe_unused]] static bool bSpawnPathInitialized = [] { + auto accessUrl = [](const INetURLObject& url) { + osl::File file(url.GetMainURL(INetURLObject::DecodeMechanism::NONE)); + return file.open(osl_File_OpenFlag_Read) == osl::FileBase::E_None; + }; + OUString sPath; + osl_getExecutableFile(&sPath.pData); + INetURLObject aPathUrl(sPath); + aPathUrl.setName(u"gpgme-w32spawn.exe"); + if (!accessUrl(aPathUrl)) + { + sPath = "$BRAND_BASE_DIR/" LIBO_LIBEXEC_FOLDER "/gpgme-w32spawn.exe"; + rtl::Bootstrap::expandMacros(sPath); + aPathUrl.SetURL(sPath); + if (accessUrl(aPathUrl)) + { + aPathUrl.removeSegment(); + GpgME::setGlobalFlag("w32-inst-dir", + aPathUrl.getFSysPath(FSysStyle::Dos).toUtf8().getStr()); + } + } + return true; + }(); +#endif + GpgME::Error err = GpgME::checkEngine(GpgME::OpenPGP); + if (err) + throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol."); + + m_ctx.reset( GpgME::Context::createForProtocol(GpgME::OpenPGP) ); + if (m_ctx == nullptr) + throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol."); + m_ctx->setArmor(false); +} + +SecurityEnvironmentGpg::~SecurityEnvironmentGpg() +{ +} + +OUString SecurityEnvironmentGpg::getSecurityEnvironmentInformation() +{ + return OUString(); +} + +Sequence< Reference < XCertificate > > SecurityEnvironmentGpg::getCertificatesImpl( bool bPrivateOnly ) +{ + std::vector< GpgME::Key > keyList; + std::vector< rtl::Reference<CertificateImpl> > certsList; + + m_ctx->setKeyListMode(GPGME_KEYLIST_MODE_LOCAL); + GpgME::Error err = m_ctx->startKeyListing("", bPrivateOnly ); + while (!err) { + GpgME::Key k = m_ctx->nextKey(err); + if (err) + break; + if (!k.isRevoked() && !k.isExpired() && !k.isDisabled() && !k.isInvalid()) { + // We can't create CertificateImpl here as CertificateImpl::setCertificate uses GpgME API + // which interrupts our key listing here. So first get the keys from GpgME, then create the CertificateImpls + keyList.push_back(k); + } + } + m_ctx->endKeyListing(); + + for (auto const& key : keyList) { + rtl::Reference<CertificateImpl> xCert = new CertificateImpl(); + xCert->setCertificate(m_ctx.get(),key); + certsList.push_back(xCert); + } + + Sequence< Reference< XCertificate > > xCertificateSequence(certsList.size()); + auto xCertificateSequenceRange = asNonConstRange(xCertificateSequence); + int i = 0; + for (const auto& cert : certsList) { + xCertificateSequenceRange[i++] = cert; + } + + return xCertificateSequence; +} + +Sequence< Reference < XCertificate > > SecurityEnvironmentGpg::getPersonalCertificates() +{ + return getCertificatesImpl( true ); +} + +Sequence< Reference < XCertificate > > SecurityEnvironmentGpg::getAllCertificates() +{ + return getCertificatesImpl( false ); +} + +Reference< XCertificate > SecurityEnvironmentGpg::getCertificate( const OUString& keyId, const Sequence< sal_Int8 >& /*serialNumber*/ ) +{ + //xmlChar* pSignatureValue=xmlNodeGetContent(cur); + OString ostr = OUStringToOString( keyId , RTL_TEXTENCODING_UTF8 ); + const xmlChar* strKeyId = reinterpret_cast<const xmlChar*>(ostr.getStr()); + xmlSecSize nWritten; + int nRet = xmlSecBase64Decode_ex(strKeyId, const_cast<xmlSecByte*>(strKeyId), xmlStrlen(strKeyId), &nWritten); + if(nRet < 0) + throw RuntimeException("Base64 decode failed"); + + m_ctx->setKeyListMode(GPGME_KEYLIST_MODE_LOCAL); + GpgME::Error err = m_ctx->startKeyListing("", false); + while (!err) { + GpgME::Key k = m_ctx->nextKey(err); + if (err) + break; + if (!k.isInvalid() && strcmp(k.primaryFingerprint(), reinterpret_cast<const char*>(strKeyId)) == 0) { + rtl::Reference<CertificateImpl> xCert = new CertificateImpl(); + xCert->setCertificate(m_ctx.get(), k); + m_ctx->endKeyListing(); + return xCert; + } + } + m_ctx->endKeyListing(); + + return nullptr; +} + +Sequence< Reference < XCertificate > > SecurityEnvironmentGpg::buildCertificatePath( const Reference< XCertificate >& /*begin*/ ) +{ + return Sequence< Reference < XCertificate > >(); +} + +Reference< XCertificate > SecurityEnvironmentGpg::createCertificateFromRaw( const Sequence< sal_Int8 >& /*rawCertificate*/ ) +{ + return nullptr; +} + +Reference< XCertificate > SecurityEnvironmentGpg::createCertificateFromAscii( const OUString& /*asciiCertificate*/ ) +{ + return nullptr; +} + +sal_Int32 SecurityEnvironmentGpg::verifyCertificate( const Reference< XCertificate >& aCert, + const Sequence< Reference< XCertificate > >& /*intermediateCerts*/ ) +{ + const CertificateImpl* xCert = dynamic_cast<CertificateImpl*>(aCert.get()); + if (xCert == nullptr) { + // Can't find the key locally -> unknown owner + return security::CertificateValidity::ISSUER_UNKNOWN; + } + + const GpgME::Key* key = xCert->getCertificate(); + if (key->ownerTrust() == GpgME::Key::OwnerTrust::Marginal || + key->ownerTrust() == GpgME::Key::OwnerTrust::Full || + key->ownerTrust() == GpgME::Key::OwnerTrust::Ultimate) + { + return security::CertificateValidity::VALID; + } + + return security::CertificateValidity::ISSUER_UNTRUSTED; +} + +sal_Int32 SecurityEnvironmentGpg::getCertificateCharacters( + const Reference< XCertificate >& aCert) +{ + if (dynamic_cast<CertificateImpl*>(aCert.get()) == nullptr) + throw RuntimeException(); + + // we only listed private keys anyway, up in + // SecurityEnvironmentGpg::getPersonalCertificates + return CertificateCharacters::HAS_PRIVATE_KEY; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/gpg/SecurityEnvironment.hxx b/xmlsecurity/source/gpg/SecurityEnvironment.hxx new file mode 100644 index 0000000000..0c530c6715 --- /dev/null +++ b/xmlsecurity/source/gpg/SecurityEnvironment.hxx @@ -0,0 +1,65 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include <sal/config.h> + +#include <memory> + +#include <rtl/ustring.hxx> +#include <cppuhelper/implbase.hxx> + +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/xml/crypto/XSecurityEnvironment.hpp> + +namespace com::sun::star::security { class XCertificate; } +namespace GpgME { class Context; } + +class SecurityEnvironmentGpg : public cppu::WeakImplHelper< css::xml::crypto::XSecurityEnvironment > +{ + std::unique_ptr<GpgME::Context> m_ctx; + +public: + SecurityEnvironmentGpg(); + virtual ~SecurityEnvironmentGpg() override; + + //Methods from XSecurityEnvironment + virtual ::sal_Int32 SAL_CALL verifyCertificate( + const css::uno::Reference< + css::security::XCertificate >& xCert, + const css::uno::Sequence< + css::uno::Reference< css::security::XCertificate > > & + intermediateCerts) override; + + virtual ::sal_Int32 SAL_CALL getCertificateCharacters( const css::uno::Reference< css::security::XCertificate >& xCert ) override; + + virtual OUString SAL_CALL getSecurityEnvironmentInformation() override; + + virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificate > > SAL_CALL getPersonalCertificates() override; + + /** We reinterpret the first parameter (originally issuerName) as keyId. We have no other way to identify a gpg key. */ + virtual css::uno::Reference< css::security::XCertificate > SAL_CALL getCertificate( const OUString& keyId, const css::uno::Sequence< sal_Int8 >& serialNumber ) override; + + virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificate > > SAL_CALL buildCertificatePath( + const css::uno::Reference< css::security::XCertificate >& beginCert ) override; + + virtual css::uno::Reference< css::security::XCertificate > SAL_CALL createCertificateFromRaw( + const css::uno::Sequence< sal_Int8 >& rawCertificate ) override; + virtual css::uno::Reference< css::security::XCertificate > SAL_CALL createCertificateFromAscii( + const OUString& asciiCertificate ) override; + + GpgME::Context& getGpgContext() { return *m_ctx; } + virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificate > > SAL_CALL getAllCertificates() override; + +private: + css::uno::Sequence< css::uno::Reference< css::security::XCertificate > > getCertificatesImpl( bool bPrivateOnly ); +} ; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/gpg/XMLEncryption.cxx b/xmlsecurity/source/gpg/XMLEncryption.cxx new file mode 100644 index 0000000000..65083ff68b --- /dev/null +++ b/xmlsecurity/source/gpg/XMLEncryption.cxx @@ -0,0 +1,37 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "XMLEncryption.hxx" + +using namespace css::uno; +using namespace css::lang; +using namespace css::xml::wrapper; +using namespace css::xml::crypto; + +XMLEncryptionGpg::XMLEncryptionGpg() { +} + +XMLEncryptionGpg::~XMLEncryptionGpg() { +} + +/* XXMLEncryption */ +Reference< XXMLEncryptionTemplate > SAL_CALL XMLEncryptionGpg::encrypt(const Reference< XXMLEncryptionTemplate >& /*aTemplate*/, + const Reference< XSecurityEnvironment >& /*aEnvironment*/) +{ + return nullptr; +} + +/* XXMLEncryption */ +Reference< XXMLEncryptionTemplate > SAL_CALL XMLEncryptionGpg::decrypt(const Reference< XXMLEncryptionTemplate >& /*aTemplate*/, + const Reference< XXMLSecurityContext >& /*aSecurityCtx*/) +{ + return nullptr; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/gpg/XMLEncryption.hxx b/xmlsecurity/source/gpg/XMLEncryption.hxx new file mode 100644 index 0000000000..4ff47ccc49 --- /dev/null +++ b/xmlsecurity/source/gpg/XMLEncryption.hxx @@ -0,0 +1,37 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include <sal/config.h> +#include <cppuhelper/implbase.hxx> + +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/xml/crypto/XXMLEncryption.hpp> + +namespace com::sun::star::xml::crypto { class XXMLEncryptionTemplate; } +namespace com::sun::star::xml::crypto { class XXMLSecurityContext; } + +class XMLEncryptionGpg : public cppu::WeakImplHelper< css::xml::crypto::XXMLEncryption > +{ +public: + explicit XMLEncryptionGpg(); + virtual ~XMLEncryptionGpg() override; + + // XXMLEncryption + virtual css::uno::Reference< css::xml::crypto::XXMLEncryptionTemplate > SAL_CALL encrypt( + const css::uno::Reference< css::xml::crypto::XXMLEncryptionTemplate >& aTemplate, + const css::uno::Reference< css::xml::crypto::XSecurityEnvironment >& aEnvironment) override; + + virtual css::uno::Reference< css::xml::crypto::XXMLEncryptionTemplate > SAL_CALL decrypt( + const css::uno::Reference< css::xml::crypto::XXMLEncryptionTemplate >& aTemplate, + const css::uno::Reference< css::xml::crypto::XXMLSecurityContext >& aContext) override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/gpg/XMLSecurityContext.cxx b/xmlsecurity/source/gpg/XMLSecurityContext.cxx new file mode 100644 index 0000000000..1fb407113f --- /dev/null +++ b/xmlsecurity/source/gpg/XMLSecurityContext.cxx @@ -0,0 +1,87 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "XMLSecurityContext.hxx" + +#include <cppuhelper/supportsservice.hxx> +#include <o3tl/safeint.hxx> + +using namespace css::uno; +using namespace css::lang; +using namespace css::xml::crypto; + +XMLSecurityContextGpg::XMLSecurityContextGpg() + : m_nDefaultEnvIndex(-1) +{ +} + +XMLSecurityContextGpg::~XMLSecurityContextGpg() {} + +sal_Int32 SAL_CALL XMLSecurityContextGpg::addSecurityEnvironment( + const Reference<XSecurityEnvironment>& aSecurityEnvironment) +{ + if (!aSecurityEnvironment.is()) + throw RuntimeException("Invalid SecurityEnvironment given!"); + + m_vSecurityEnvironments.push_back(aSecurityEnvironment); + return m_vSecurityEnvironments.size() - 1; +} + +sal_Int32 SAL_CALL XMLSecurityContextGpg::getSecurityEnvironmentNumber() +{ + return m_vSecurityEnvironments.size(); +} + +Reference<XSecurityEnvironment> + SAL_CALL XMLSecurityContextGpg::getSecurityEnvironmentByIndex(sal_Int32 index) +{ + if (index < 0 || o3tl::make_unsigned(index) >= m_vSecurityEnvironments.size()) + throw RuntimeException("Invalid index"); + + return m_vSecurityEnvironments[index]; +} + +Reference<XSecurityEnvironment> SAL_CALL XMLSecurityContextGpg::getSecurityEnvironment() +{ + if (m_nDefaultEnvIndex < 0 + || o3tl::make_unsigned(m_nDefaultEnvIndex) >= m_vSecurityEnvironments.size()) + throw RuntimeException("Invalid index"); + + return getSecurityEnvironmentByIndex(m_nDefaultEnvIndex); +} + +sal_Int32 SAL_CALL XMLSecurityContextGpg::getDefaultSecurityEnvironmentIndex() +{ + return m_nDefaultEnvIndex; +} + +void SAL_CALL XMLSecurityContextGpg::setDefaultSecurityEnvironmentIndex(sal_Int32 nDefaultEnvIndex) +{ + m_nDefaultEnvIndex = nDefaultEnvIndex; +} + +/* XServiceInfo */ +OUString SAL_CALL XMLSecurityContextGpg::getImplementationName() +{ + return "com.sun.star.xml.security.gpg.XMLSecurityContext_GpgImpl"; +} + +/* XServiceInfo */ +sal_Bool SAL_CALL XMLSecurityContextGpg::supportsService(const OUString& serviceName) +{ + return cppu::supportsService(this, serviceName); +} + +/* XServiceInfo */ +Sequence<OUString> SAL_CALL XMLSecurityContextGpg::getSupportedServiceNames() +{ + return { OUString("com.sun.star.xml.crypto.XMLSecurityContext") }; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/gpg/XMLSecurityContext.hxx b/xmlsecurity/source/gpg/XMLSecurityContext.hxx new file mode 100644 index 0000000000..e3dea73101 --- /dev/null +++ b/xmlsecurity/source/gpg/XMLSecurityContext.hxx @@ -0,0 +1,58 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include <sal/config.h> +#include <rtl/ustring.hxx> +#include <cppuhelper/implbase.hxx> + +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/xml/crypto/XXMLSecurityContext.hpp> + +#include <vector> + +namespace com::sun::star::xml::crypto { class XSecurityEnvironment; } + +class XMLSecurityContextGpg : public cppu::WeakImplHelper< css::xml::crypto::XXMLSecurityContext, + css::lang::XServiceInfo> +{ +private: + std::vector< css::uno::Reference< css::xml::crypto::XSecurityEnvironment > > m_vSecurityEnvironments; + + sal_Int32 m_nDefaultEnvIndex; + +public: + XMLSecurityContextGpg(); + virtual ~XMLSecurityContextGpg() override; + + // XXMLSecurityContext + virtual sal_Int32 SAL_CALL addSecurityEnvironment( + const css::uno::Reference< css::xml::crypto::XSecurityEnvironment >& aSecurityEnvironment) override; + + virtual ::sal_Int32 SAL_CALL getSecurityEnvironmentNumber() override; + + virtual css::uno::Reference<css::xml::crypto::XSecurityEnvironment > SAL_CALL getSecurityEnvironmentByIndex(sal_Int32 index) override; + + virtual css::uno::Reference<css::xml::crypto::XSecurityEnvironment > SAL_CALL getSecurityEnvironment() override; + + virtual sal_Int32 SAL_CALL getDefaultSecurityEnvironmentIndex() override; + + virtual void SAL_CALL setDefaultSecurityEnvironmentIndex( sal_Int32 nDefaultEnvIndex ) override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override ; + + virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override ; + + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override ; +} ; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/gpg/xmlsignature_gpgimpl.cxx b/xmlsecurity/source/gpg/xmlsignature_gpgimpl.cxx new file mode 100644 index 0000000000..22488144f7 --- /dev/null +++ b/xmlsecurity/source/gpg/xmlsignature_gpgimpl.cxx @@ -0,0 +1,532 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> +#include <sal/log.hxx> +#include <xmlsec-wrapper.h> +#include <comphelper/servicehelper.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <gpg/xmlsignature_gpgimpl.hxx> + +#if defined _MSC_VER && defined __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wundef" +#endif +#include <gpgme.h> +#if defined _MSC_VER && defined __clang__ +#pragma clang diagnostic pop +#endif +#include <context.h> +#include <key.h> +#include <data.h> +#include <signingresult.h> +#include <importresult.h> + +#include <xmlelementwrapper_xmlsecimpl.hxx> +#include <xmlsec/xmlstreamio.hxx> +#include <xmlsec/errorcallback.hxx> + +#include "SecurityEnvironment.hxx" + +using namespace css::uno; +using namespace css::lang; +using namespace css::xml::wrapper; +using namespace css::xml::crypto; + +XMLSignature_GpgImpl::XMLSignature_GpgImpl() { +} + +XMLSignature_GpgImpl::~XMLSignature_GpgImpl() { +} + +/* XXMLSignature */ +Reference< XXMLSignatureTemplate > +SAL_CALL XMLSignature_GpgImpl::generate( + const Reference< XXMLSignatureTemplate >& aTemplate , + const Reference< XSecurityEnvironment >& aEnvironment +) +{ + xmlSecDSigCtxPtr pDsigCtx = nullptr ; + xmlNodePtr pNode = nullptr ; + + if( !aTemplate.is() ) + throw RuntimeException() ; + + if( !aEnvironment.is() ) + throw RuntimeException() ; + + //Get the xml node + Reference< XXMLElementWrapper > xElement = aTemplate->getTemplate() ; + if( !xElement.is() ) { + throw RuntimeException() ; + } + + XMLElementWrapper_XmlSecImpl* pElement = + dynamic_cast<XMLElementWrapper_XmlSecImpl*>(xElement.get()); + if( pElement == nullptr ) { + throw RuntimeException() ; + } + + pNode = pElement->getNativeElement() ; + + //Get the stream/URI binding + Reference< XUriBinding > xUriBinding = aTemplate->getBinding() ; + if( xUriBinding.is() ) { + //Register the stream input callbacks into libxml2 + if( xmlRegisterStreamInputCallbacks( xUriBinding ) < 0 ) + throw RuntimeException() ; + } + + //Get Keys Manager + SecurityEnvironmentGpg* pSecEnv = + dynamic_cast<SecurityEnvironmentGpg*>(aEnvironment.get()); + if( pSecEnv == nullptr ) + throw RuntimeException() ; + + setErrorRecorder(); + + //Create Signature context + pDsigCtx = xmlSecDSigCtxCreate( nullptr ) ; + if( pDsigCtx == nullptr ) + { + clearErrorRecorder(); + return aTemplate; + } + + // set intended operation to sign - several asserts inside libxmlsec + // wanting that for digest / transforms + pDsigCtx->operation = xmlSecTransformOperationSign; + + // we default to SHA512 for all digests - nss crypto does not have it... + //pDsigCtx->defDigestMethodId = xmlSecTransformSha512Id; + + // Calculate digest for all references + xmlNodePtr cur = xmlSecGetNextElementNode(pNode->children); + if( cur != nullptr ) + cur = xmlSecGetNextElementNode(cur->children); + while( cur != nullptr ) + { + // some of those children I suppose should be reference elements + if( xmlSecCheckNodeName(cur, xmlSecNodeReference, xmlSecDSigNs) ) + { + xmlSecDSigReferenceCtxPtr pDsigRefCtx = + xmlSecDSigReferenceCtxCreate(pDsigCtx, + xmlSecDSigReferenceOriginSignedInfo); + if(pDsigRefCtx == nullptr) + throw RuntimeException(); + + // add this one to the list + if( xmlSecPtrListAdd(&(pDsigCtx->signedInfoReferences), + pDsigRefCtx) < 0 ) + { + // TODO resource handling + xmlSecDSigReferenceCtxDestroy(pDsigRefCtx); + throw RuntimeException(); + } + + if( xmlSecDSigReferenceCtxProcessNode(pDsigRefCtx, cur) < 0 ) + throw RuntimeException(); + + // final check - all good? + if(pDsigRefCtx->status != xmlSecDSigStatusSucceeded) + { + pDsigCtx->status = xmlSecDSigStatusInvalid; + return aTemplate; // TODO - harder error? + } + } + + cur = xmlSecGetNextElementNode(cur->next); + } + + // get me a digestible buffer from the signature template! + // ------------------------------------------------------- + + // run the transformations over SignedInfo element (first child of + // pNode) + xmlSecNodeSetPtr nodeset = nullptr; + cur = xmlSecGetNextElementNode(pNode->children); + // TODO assert that... + nodeset = xmlSecNodeSetGetChildren(pNode->doc, cur, 1, 0); + if(nodeset == nullptr) + throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol."); + + if( xmlSecTransformCtxXmlExecute(&(pDsigCtx->transformCtx), nodeset) < 0 ) + throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol."); + + // now extract the keyid from PGPData + // walk xml tree to PGPData node - go to children, first is + // SignedInfo, 2nd is signaturevalue, 3rd is KeyInfo + // 1st child is PGPData, 1st grandchild is PGPKeyID + cur = xmlSecGetNextElementNode(pNode->children); + // TODO error handling + cur = xmlSecGetNextElementNode(cur->next); + cur = xmlSecGetNextElementNode(cur->next); + cur = xmlSecGetNextElementNode(cur->children); + // check that this is now PGPData + if(!xmlSecCheckNodeName(cur, xmlSecNodePGPData, xmlSecDSigNs)) + throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol."); + // check that this is now PGPKeyID + cur = xmlSecGetNextElementNode(cur->children); + static const xmlChar xmlSecNodePGPKeyID[] = "PGPKeyID"; + if(!xmlSecCheckNodeName(cur, xmlSecNodePGPKeyID, xmlSecDSigNs)) + throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol."); + + GpgME::Context& rCtx=pSecEnv->getGpgContext(); + rCtx.setKeyListMode(GPGME_KEYLIST_MODE_LOCAL); + GpgME::Error err; + xmlChar* pKey=xmlNodeGetContent(cur); + xmlSecSize nWritten; + int nRet = xmlSecBase64Decode_ex(pKey, reinterpret_cast<xmlSecByte*>(pKey), xmlStrlen(pKey), &nWritten); + if(nRet < 0) + throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol."); + if( rCtx.addSigningKey( + rCtx.key( + reinterpret_cast<char*>(pKey), err, true)) ) + throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol."); + + xmlFree(pKey); + + // good, ctx is setup now, let's sign the lot + GpgME::Data data_in( + reinterpret_cast<char*>(xmlSecBufferGetData(pDsigCtx->transformCtx.result)), + xmlSecBufferGetSize(pDsigCtx->transformCtx.result), false); + GpgME::Data data_out; + + SAL_INFO("xmlsecurity.xmlsec.gpg", "Generating signature for: " << xmlSecBufferGetData(pDsigCtx->transformCtx.result)); + + // we base64-encode anyway + rCtx.setArmor(false); + GpgME::SigningResult sign_res=rCtx.sign(data_in, data_out, + GpgME::Detached); + off_t result = data_out.seek(0,SEEK_SET); + (void) result; + assert(result == 0); + int len=0, curr=0; char buf; + while( (curr=data_out.read(&buf, 1)) ) + len += curr; + + if(sign_res.error() || !len) + throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol."); + + // write signed data to xml + xmlChar* signature = static_cast<xmlChar*>(xmlMalloc(len + 1)); + if(signature == nullptr) + throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol."); + result = data_out.seek(0,SEEK_SET); + assert(result == 0); + if( data_out.read(signature, len) != len ) + throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol."); + + // conversion to base64 + xmlChar* signatureEncoded=nullptr; + if( !(signatureEncoded=xmlSecBase64Encode(reinterpret_cast<xmlSecByte*>(signature), len, 79)) ) + throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol."); + xmlFree(signature); + + // walk xml tree to sign value node - go to children, first is + // SignedInfo, 2nd is signaturevalue + cur = xmlSecGetNextElementNode(pNode->children); + cur = xmlSecGetNextElementNode(cur->next); + + // TODO some assert would be good... + xmlNodeSetContentLen(cur, signatureEncoded, xmlStrlen(signatureEncoded)); + xmlFree(signatureEncoded); + + aTemplate->setStatus(SecurityOperationStatus_OPERATION_SUCCEEDED); + + // done + xmlSecDSigCtxDestroy( pDsigCtx ) ; + + //Unregistered the stream/URI binding + if( xUriBinding.is() ) + xmlUnregisterStreamInputCallbacks() ; + + clearErrorRecorder(); + return aTemplate ; +} + +/* XXMLSignature */ +Reference< XXMLSignatureTemplate > +SAL_CALL XMLSignature_GpgImpl::validate( + const Reference< XXMLSignatureTemplate >& aTemplate , + const Reference< XXMLSecurityContext >& aSecurityCtx +) { + xmlSecDSigCtxPtr pDsigCtx = nullptr ; + xmlNodePtr pNode = nullptr ; + + if( !aTemplate.is() ) + throw RuntimeException() ; + + if( !aSecurityCtx.is() ) + throw RuntimeException() ; + + //Get the xml node + Reference< XXMLElementWrapper > xElement = aTemplate->getTemplate() ; + if( !xElement.is() ) + throw RuntimeException() ; + + XMLElementWrapper_XmlSecImpl* pElement = + dynamic_cast<XMLElementWrapper_XmlSecImpl*>(xElement.get()); + if( pElement == nullptr ) + throw RuntimeException() ; + + pNode = pElement->getNativeElement() ; + + //Get the stream/URI binding + Reference< XUriBinding > xUriBinding = aTemplate->getBinding() ; + if( xUriBinding.is() ) { + //Register the stream input callbacks into libxml2 + if( xmlRegisterStreamInputCallbacks( xUriBinding ) < 0 ) + throw RuntimeException() ; + } + + setErrorRecorder(); + + sal_Int32 nSecurityEnvironment = aSecurityCtx->getSecurityEnvironmentNumber(); + sal_Int32 i; + + for (i=0; i<nSecurityEnvironment; ++i) + { + Reference< XSecurityEnvironment > aEnvironment = aSecurityCtx->getSecurityEnvironmentByIndex(i); + + SecurityEnvironmentGpg* pSecEnv = + dynamic_cast<SecurityEnvironmentGpg*>(aEnvironment.get()); + if( pSecEnv == nullptr ) + throw RuntimeException() ; + + // TODO figure out key from pSecEnv! + // unclear how/where that is transported in nss impl... + + //Create Signature context + pDsigCtx = xmlSecDSigCtxCreate( nullptr ) ; + if( pDsigCtx == nullptr ) + { + clearErrorRecorder(); + return aTemplate; + } + + // set intended operation to verify - several asserts inside libxmlsec + // wanting that for digest / transforms + pDsigCtx->operation = xmlSecTransformOperationVerify; + + // reset status - to be set later + pDsigCtx->status = xmlSecDSigStatusUnknown; + + // get me a digestible buffer from the SignatureInfo node! + // ------------------------------------------------------- + + // run the transformations - first child node is required to + // be SignatureInfo + xmlSecNodeSetPtr nodeset = nullptr; + xmlNodePtr cur = xmlSecGetNextElementNode(pNode->children); + // TODO assert that... + nodeset = xmlSecNodeSetGetChildren(pNode->doc, cur, 1, 0); + if(nodeset == nullptr) + throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol."); + + // TODO assert we really have the SignatureInfo here? + if( xmlSecTransformCtxXmlExecute(&(pDsigCtx->transformCtx), nodeset) < 0 ) + throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol."); + + // Validate the template via gpgme + GpgME::Context& rCtx=pSecEnv->getGpgContext(); + + GpgME::Data data_text( + reinterpret_cast<char*>(xmlSecBufferGetData(pDsigCtx->transformCtx.result)), + xmlSecBufferGetSize(pDsigCtx->transformCtx.result), false); + + SAL_INFO("xmlsecurity.xmlsec.gpg", "Validating SignatureInfo: " << xmlSecBufferGetData(pDsigCtx->transformCtx.result)); + + // walk xml tree to sign value node - go to children, first is + // SignedInfo, 2nd is signaturevalue + cur = xmlSecGetNextElementNode(pNode->children); + cur = xmlSecGetNextElementNode(cur->next); + + if(!xmlSecCheckNodeName(cur, xmlSecNodeSignatureValue, xmlSecDSigNs)) + throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol."); + xmlChar* pSignatureValue=xmlNodeGetContent(cur); + xmlSecSize nSigSize; + int nRet = xmlSecBase64Decode_ex(pSignatureValue, reinterpret_cast<xmlSecByte*>(pSignatureValue), xmlStrlen(pSignatureValue), &nSigSize); + if( nRet < 0) + throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol."); + + GpgME::Data data_signature( + reinterpret_cast<char*>(pSignatureValue), + nSigSize, false); + + GpgME::VerificationResult verify_res=rCtx.verifyDetachedSignature( + data_signature, data_text); + + // TODO: needs some more error handling, needs checking _all_ signatures + if( verify_res.isNull() || verify_res.numSignatures() == 0 + // there is at least 1 signature and it is anything else than fully valid + || ( (verify_res.numSignatures() > 0) + && verify_res.signature(0).status().encodedError() > 0 ) ) + { + // let's try again, but this time import the public key + // payload (avoiding that in a first cut for being a bit + // speedier. also prevents all too easy poisoning/sha1 + // fingerprint collision attacks) + + // walk xml tree to PGPData node - go to children, first is + // SignedInfo, 2nd is signaturevalue, 3rd is KeyInfo + // 1st child is PGPData, 1st or 2nd grandchild is PGPKeyPacket + cur = xmlSecGetNextElementNode(pNode->children); + // TODO error handling + cur = xmlSecGetNextElementNode(cur->next); + cur = xmlSecGetNextElementNode(cur->next); + cur = xmlSecGetNextElementNode(cur->children); + // check that this is now PGPData + if(!xmlSecCheckNodeName(cur, xmlSecNodePGPData, xmlSecDSigNs)) + throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol."); + // check that this is now PGPKeyPacket + cur = xmlSecGetNextElementNode(cur->children); + static const xmlChar xmlSecNodePGPKeyPacket[] = "PGPKeyPacket"; + if(!xmlSecCheckNodeName(cur, xmlSecNodePGPKeyPacket, xmlSecDSigNs)) + { + // not this one, maybe the next? + cur = xmlSecGetNextElementNode(cur->next); + if(!xmlSecCheckNodeName(cur, xmlSecNodePGPKeyPacket, xmlSecDSigNs)) + { + // ok, giving up + clearErrorRecorder(); + xmlFree(pSignatureValue); + + return aTemplate; + } + } + + // got a key packet, import & re-validate + xmlChar* pKeyPacket=xmlNodeGetContent(cur); + xmlSecSize nKeyLen; + nRet = xmlSecBase64Decode_ex(pKeyPacket, reinterpret_cast<xmlSecByte*>(pKeyPacket), xmlStrlen(pKeyPacket), &nKeyLen); + if( nRet < 0) + throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol."); + + GpgME::Data data_key( + reinterpret_cast<char*>(pKeyPacket), + nKeyLen, false); + + rCtx.importKeys(data_key); + xmlFree(pKeyPacket); + + // and re-run (rewind text and signature streams to position 0) + (void)data_text.seek(0,SEEK_SET); + (void)data_signature.seek(0,SEEK_SET); + verify_res=rCtx.verifyDetachedSignature(data_signature, data_text); + + // TODO: needs some more error handling, needs checking _all_ signatures + if( verify_res.isNull() || verify_res.numSignatures() == 0 + // there is at least 1 signature and it is anything else than valid + || ( (verify_res.numSignatures() > 0) + && verify_res.signature(0).status().encodedError() > 0 ) ) + { + clearErrorRecorder(); + xmlFree(pSignatureValue); + + return aTemplate; + } + } + + xmlFree(pSignatureValue); + + // now verify digest for all references + cur = xmlSecGetNextElementNode(pNode->children); + if( cur != nullptr ) + cur = xmlSecGetNextElementNode(cur->children); + while( cur != nullptr ) + { + // some of those children I suppose should be reference elements + if( xmlSecCheckNodeName(cur, xmlSecNodeReference, xmlSecDSigNs) ) + { + xmlSecDSigReferenceCtxPtr pDsigRefCtx = + xmlSecDSigReferenceCtxCreate(pDsigCtx, + xmlSecDSigReferenceOriginSignedInfo); + if(pDsigRefCtx == nullptr) + throw RuntimeException(); + + // add this one to the list + if( xmlSecPtrListAdd(&(pDsigCtx->signedInfoReferences), + pDsigRefCtx) < 0 ) + { + // TODO resource handling + xmlSecDSigReferenceCtxDestroy(pDsigRefCtx); + throw RuntimeException(); + } + + if( xmlSecDSigReferenceCtxProcessNode(pDsigRefCtx, cur) < 0 ) + throw RuntimeException(); + + // final check - all good? + if(pDsigRefCtx->status != xmlSecDSigStatusSucceeded) + { + pDsigCtx->status = xmlSecDSigStatusInvalid; + return aTemplate; // TODO - harder error? + } + } + + cur = xmlSecGetNextElementNode(cur->next); + } + + // TODO - also verify manifest (only relevant for ooxml)? + aTemplate->setStatus(SecurityOperationStatus_OPERATION_SUCCEEDED); + + // done + xmlSecDSigCtxDestroy( pDsigCtx ) ; + } + + //Unregistered the stream/URI binding + if( xUriBinding.is() ) + xmlUnregisterStreamInputCallbacks() ; + + clearErrorRecorder(); + return aTemplate ; +} + +/* XServiceInfo */ +OUString SAL_CALL XMLSignature_GpgImpl::getImplementationName() { + return impl_getImplementationName() ; +} + +/* XServiceInfo */ +sal_Bool SAL_CALL XMLSignature_GpgImpl::supportsService( const OUString& serviceName) { + return cppu::supportsService(this, serviceName); +} + +/* XServiceInfo */ +Sequence< OUString > SAL_CALL XMLSignature_GpgImpl::getSupportedServiceNames() { + return impl_getSupportedServiceNames() ; +} + +//Helper for XServiceInfo +Sequence< OUString > XMLSignature_GpgImpl::impl_getSupportedServiceNames() { + Sequence<OUString> seqServiceNames { "com.sun.star.xml.crypto.XMLSignature" }; + return seqServiceNames ; +} + +OUString XMLSignature_GpgImpl::impl_getImplementationName() { + return "com.sun.star.xml.security.bridge.xmlsec.XMLSignature_GpgImpl" ; +} + +//Helper for registry +Reference< XInterface > XMLSignature_GpgImpl::impl_createInstance( const Reference< XMultiServiceFactory >& ) { + return Reference< XInterface >( *new XMLSignature_GpgImpl ) ; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/helper/UriBindingHelper.cxx b/xmlsecurity/source/helper/UriBindingHelper.cxx new file mode 100644 index 0000000000..f6c36d2c8b --- /dev/null +++ b/xmlsecurity/source/helper/UriBindingHelper.cxx @@ -0,0 +1,113 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <UriBindingHelper.hxx> + +#include <tools/solar.h> +#include <unotools/streamhelper.hxx> + +#include <com/sun/star/embed/XStorage.hpp> +#include <com/sun/star/embed/ElementModes.hpp> +#include <osl/diagnose.h> +#include <rtl/uri.hxx> +#include <sal/log.hxx> + +using namespace com::sun::star; + +// XUriBinding + +UriBindingHelper::UriBindingHelper() +{ +} + +UriBindingHelper::UriBindingHelper( const css::uno::Reference < css::embed::XStorage >& rxStorage ) +{ + mxStorage = rxStorage; +} + +void SAL_CALL UriBindingHelper::setUriBinding( const OUString& /*uri*/, const uno::Reference< io::XInputStream >&) +{ +} + +uno::Reference< io::XInputStream > SAL_CALL UriBindingHelper::getUriBinding( const OUString& uri ) +{ + uno::Reference< io::XInputStream > xInputStream; + if ( mxStorage.is() ) + { + xInputStream = OpenInputStream( mxStorage, uri ); + } + else + { + SvFileStream* pStream = new SvFileStream( uri, StreamMode::READ ); + sal_uInt64 nBytes = pStream->TellEnd(); + 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 OUString& rURI ) +{ + OSL_ASSERT(!rURI.isEmpty()); + uno::Reference < io::XInputStream > xInStream; + + OUString aURI(rURI); + // Ignore leading slash, don't attempt to open a storage with name "". + if (aURI.startsWith("/")) + aURI = aURI.copy(1); + // Ignore query part of the URI. + sal_Int32 nQueryPos = aURI.indexOf('?'); + if (nQueryPos != -1) + aURI = aURI.copy(0, nQueryPos); + + + sal_Int32 nSepPos = aURI.indexOf( '/' ); + if ( nSepPos == -1 ) + { + // Cloning because of I can't keep all storage references open + // MBA with think about a better API... + const OUString sName = ::rtl::Uri::decode( + aURI, rtl_UriDecodeStrict, rtl_UriCharClassRelSegment); + if (sName.isEmpty() && !aURI.isEmpty()) + throw uno::Exception("Could not decode URI for stream element.", nullptr); + + uno::Reference< io::XStream > xStream; + if (!rxStore->hasByName(sName)) + SAL_WARN("xmlsecurity.helper", "expected stream, but not found: " << sName); + else + xStream = rxStore->cloneStreamElement( sName ); + if ( !xStream.is() ) + throw uno::RuntimeException(); + xInStream = xStream->getInputStream(); + } + else + { + const OUString aStoreName = ::rtl::Uri::decode( + aURI.copy( 0, nSepPos ), rtl_UriDecodeStrict, rtl_UriCharClassRelSegment); + if (aStoreName.isEmpty() && !aURI.isEmpty()) + throw uno::Exception("Could not decode URI for stream element.", nullptr); + + OUString aElement = aURI.copy( nSepPos+1 ); + uno::Reference < embed::XStorage > xSubStore = rxStore->openStorageElement( aStoreName, embed::ElementModes::READ ); + xInStream = OpenInputStream( xSubStore, aElement ); + } + return xInStream; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/helper/documentsignaturehelper.cxx b/xmlsecurity/source/helper/documentsignaturehelper.cxx new file mode 100644 index 0000000000..8e666b14ba --- /dev/null +++ b/xmlsecurity/source/helper/documentsignaturehelper.cxx @@ -0,0 +1,650 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include <documentsignaturehelper.hxx> + +#include <algorithm> +#include <functional> +#include <string_view> + +#include <com/sun/star/io/IOException.hpp> +#include <com/sun/star/embed/XStorage.hpp> +#include <com/sun/star/embed/StorageFormats.hpp> +#include <com/sun/star/embed/ElementModes.hpp> +#include <com/sun/star/beans/StringPair.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/xml/sax/XDocumentHandler.hpp> + +#include <comphelper/attributelist.hxx> +#include <comphelper/documentconstants.hxx> +#include <comphelper/ofopxmlhelper.hxx> +#include <comphelper/processfactory.hxx> +#include <osl/diagnose.h> +#include <rtl/ref.hxx> +#include <rtl/uri.hxx> +#include <sal/log.hxx> +#include <svx/xoutbmp.hxx> +#include <comphelper/diagnose_ex.hxx> +#include <o3tl/string_view.hxx> + +#include <xsecctl.hxx> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace css::xml::sax; + +namespace +{ +std::u16string_view getElement(std::u16string_view version, size_t * index) +{ + while (*index < version.size() && version[*index] == '0') { + ++*index; + } + return o3tl::getToken(version, u'.', *index); +} + + +// Return 1 if version1 is greater than version 2, 0 if they are equal +//and -1 if version1 is less version 2 +int compareVersions( + std::u16string_view version1, std::u16string_view version2) +{ + for (size_t i1 = 0, i2 = 0; i1 != std::u16string_view::npos || i2 != std::u16string_view::npos;) { + std::u16string_view e1(getElement(version1, &i1)); + std::u16string_view e2(getElement(version2, &i2)); + if (e1.size() < e2.size()) { + return -1; + } else if (e1.size() > e2.size()) { + return 1; + } else if (e1 < e2) { + return -1; + } else if (e1 > e2) { + return 1; + } + } + return 0; +} +} + +static void ImplFillElementList( + std::vector< OUString >& rList, const Reference < css::embed::XStorage >& rxStore, + std::u16string_view rRootStorageName, const bool bRecursive, + const DocumentSignatureAlgorithm mode) +{ + const Sequence< OUString > aElements = rxStore->getElementNames(); + + for ( const auto& rName : aElements ) + { + if (rName == "[Content_Types].xml") + // OOXML + continue; + + // If the user enabled validating according to OOo 3.0 + // then mimetype and all content of META-INF must be excluded. + if (mode != DocumentSignatureAlgorithm::OOo3_2 + && (rName == "META-INF" || rName == "mimetype")) + { + continue; + } + else + { + OUString sEncName = ::rtl::Uri::encode( + rName, rtl_UriCharClassRelSegment, + rtl_UriEncodeStrict, RTL_TEXTENCODING_UTF8); + if (sEncName.isEmpty() && !rName.isEmpty()) + throw css::uno::RuntimeException("Failed to encode element name of XStorage", nullptr); + + if ( rxStore->isStreamElement( rName ) ) + { + //Exclude documentsignatures.xml! + if (rName == + DocumentSignatureHelper::GetDocumentContentSignatureDefaultStreamName()) + continue; + OUString aFullName( rRootStorageName + sEncName ); + rList.push_back(aFullName); + } + else if ( bRecursive && rxStore->isStorageElement( rName ) ) + { + Reference < css::embed::XStorage > xSubStore = rxStore->openStorageElement( rName, css::embed::ElementModes::READ ); + OUString aFullRootName( rRootStorageName + sEncName + "/" ); + ImplFillElementList(rList, xSubStore, aFullRootName, bRecursive, mode); + } + } + } +} + + +bool DocumentSignatureHelper::isODFPre_1_2(std::u16string_view 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 + return compareVersions(sVersion, ODFVER_012_TEXT) == -1; +} + +bool DocumentSignatureHelper::isOOo3_2_Signature(const SignatureInformation & sigInfo) +{ + return std::any_of(sigInfo.vSignatureReferenceInfors.cbegin(), + sigInfo.vSignatureReferenceInfors.cend(), + [](const SignatureReferenceInformation& info) { return info.ouURI == "META-INF/manifest.xml"; }); +} + +DocumentSignatureAlgorithm +DocumentSignatureHelper::getDocumentAlgorithm( + std::u16string_view sODFVersion, const SignatureInformation & sigInfo) +{ + OSL_ASSERT(!sODFVersion.empty()); + DocumentSignatureAlgorithm mode = DocumentSignatureAlgorithm::OOo3_2; + if (!isOOo3_2_Signature(sigInfo)) + { + if (isODFPre_1_2(sODFVersion)) + mode = DocumentSignatureAlgorithm::OOo2; + else + mode = DocumentSignatureAlgorithm::OOo3_0; + } + 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< OUString > +DocumentSignatureHelper::CreateElementList( + const Reference < css::embed::XStorage >& rxStore, + DocumentSignatureMode eMode, + const DocumentSignatureAlgorithm mode) +{ + std::vector< OUString > aElements; + OUString aSep( "/" ); + + switch ( eMode ) + { + case DocumentSignatureMode::Content: + { + if (mode == DocumentSignatureAlgorithm::OOo2) //that is, ODF 1.0, 1.1 + { + // 1) Main content + ImplFillElementList(aElements, rxStore, std::u16string_view(), false, mode); + + // 2) Pictures... + OUString aSubStorageName( "Pictures" ); + try + { + Reference < css::embed::XStorage > xSubStore = rxStore->openStorageElement( aSubStorageName, css::embed::ElementModes::READ ); + ImplFillElementList( + aElements, xSubStore, Concat2View(aSubStorageName+aSep), true, mode); + } + catch(css::io::IOException& ) + { + ; // Doesn't have to exist... + } + // 3) OLE... + aSubStorageName = "ObjectReplacements"; + try + { + Reference < css::embed::XStorage > xSubStore = rxStore->openStorageElement( aSubStorageName, css::embed::ElementModes::READ ); + ImplFillElementList( + aElements, xSubStore, Concat2View(aSubStorageName+aSep), true, mode); + xSubStore.clear(); + + // Object folders... + const Sequence< OUString > aElementNames = rxStore->getElementNames(); + for ( const auto& rName : aElementNames ) + { + if ( ( rName.match( "Object " ) ) && rxStore->isStorageElement( rName ) ) + { + Reference < css::embed::XStorage > xTmpSubStore = rxStore->openStorageElement( rName, css::embed::ElementModes::READ ); + ImplFillElementList( + aElements, xTmpSubStore, Concat2View(rName+aSep), true, mode); + } + } + } + catch( css::io::IOException& ) + { + ; // Doesn't have to exist... + } + } + else + { + // Everything except META-INF + ImplFillElementList(aElements, rxStore, std::u16string_view(), true, mode); + } + } + break; + case DocumentSignatureMode::Macros: + { + // 1) Macros + OUString aSubStorageName( "Basic" ); + try + { + Reference < css::embed::XStorage > xSubStore = rxStore->openStorageElement( aSubStorageName, css::embed::ElementModes::READ ); + ImplFillElementList( + aElements, xSubStore, Concat2View(aSubStorageName+aSep), true, mode); + } + catch( css::io::IOException& ) + { + ; // Doesn't have to exist... + } + + // 2) Dialogs + aSubStorageName = "Dialogs"; + try + { + Reference < css::embed::XStorage > xSubStore = rxStore->openStorageElement( aSubStorageName, css::embed::ElementModes::READ ); + ImplFillElementList( + aElements, xSubStore, Concat2View(aSubStorageName+aSep), true, mode); + } + catch( css::io::IOException& ) + { + ; // Doesn't have to exist... + } + // 3) Scripts + aSubStorageName = "Scripts"; + try + { + Reference < css::embed::XStorage > xSubStore = rxStore->openStorageElement( aSubStorageName, css::embed::ElementModes::READ ); + ImplFillElementList( + aElements, xSubStore, Concat2View(aSubStorageName+aSep), true, mode); + } + catch( css::io::IOException& ) + { + ; // Doesn't have to exist... + } + } + break; + case DocumentSignatureMode::Package: + { + // Everything except META-INF + ImplFillElementList(aElements, rxStore, std::u16string_view(), true, mode); + } + break; + } + + return aElements; +} + +void DocumentSignatureHelper::AppendContentTypes(const uno::Reference<embed::XStorage>& xStorage, std::vector<OUString>& rElements) +{ + if (!xStorage.is() || !xStorage->hasByName("[Content_Types].xml")) + // ODF + return; + + uno::Reference<io::XInputStream> xRelStream(xStorage->openStreamElement("[Content_Types].xml", embed::ElementModes::READ), uno::UNO_QUERY); + uno::Sequence< uno::Sequence<beans::StringPair> > aContentTypeInfo = comphelper::OFOPXMLHelper::ReadContentTypeSequence(xRelStream, comphelper::getProcessComponentContext()); + if (aContentTypeInfo.getLength() < 2) + { + SAL_WARN("xmlsecurity.helper", "no defaults or overrides in aContentTypeInfo"); + return; + } + const uno::Sequence<beans::StringPair>& rDefaults = aContentTypeInfo[0]; + const uno::Sequence<beans::StringPair>& rOverrides = aContentTypeInfo[1]; + + for (OUString& rElement : rElements) + { + auto it = std::find_if(rOverrides.begin(), rOverrides.end(), [&](const beans::StringPair& rPair) + { + return rPair.First == Concat2View("/" + rElement); + }); + + if (it != rOverrides.end()) + { + rElement = "/" + rElement + "?ContentType=" + it->Second; + continue; + } + + it = std::find_if(rDefaults.begin(), rDefaults.end(), [&](const beans::StringPair& rPair) + { + return rElement.endsWith(Concat2View("." + rPair.First)); + }); + + if (it != rDefaults.end()) + { + rElement = "/" + rElement + "?ContentType=" + it->Second; + continue; + } + SAL_WARN("xmlsecurity.helper", "found no content type for " << rElement); + } + + std::sort(rElements.begin(), rElements.end()); +} + +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; + + if (!rxStore.is()) + return aHelper; + + if (rxStore->hasByName("META-INF")) + { + try + { + aHelper.xSignatureStorage = rxStore->openStorageElement( "META-INF", nSubStorageOpenMode ); + if ( aHelper.xSignatureStorage.is() ) + { + OUString aSIGStreamName; + if ( eDocSigMode == DocumentSignatureMode::Content ) + aSIGStreamName = DocumentSignatureHelper::GetDocumentContentSignatureDefaultStreamName(); + else if ( eDocSigMode == DocumentSignatureMode::Macros ) + aSIGStreamName = DocumentSignatureHelper::GetScriptingContentSignatureDefaultStreamName(); + else + aSIGStreamName = DocumentSignatureHelper::GetPackageSignatureDefaultStreamName(); + +#ifdef SAL_LOG_INFO + aHelper.xSignatureStream + = aHelper.xSignatureStorage->openStreamElement(aSIGStreamName, nOpenMode); + SAL_INFO("xmlsecurity.helper", + "DocumentSignatureHelper::OpenSignatureStream: stream name is '" + << aSIGStreamName << "'"); + if (aHelper.xSignatureStream.is()) + { + uno::Reference<io::XInputStream> xInputStream(aHelper.xSignatureStream, + uno::UNO_QUERY); + sal_Int64 nSize = 0; + uno::Reference<beans::XPropertySet> xPropertySet(xInputStream, uno::UNO_QUERY); + xPropertySet->getPropertyValue("Size") >>= nSize; + if (nSize >= 0 || nSize < SAL_MAX_INT32) + { + uno::Sequence<sal_Int8> aData; + xInputStream->readBytes(aData, nSize); + SAL_INFO("xmlsecurity.helper", + "DocumentSignatureHelper::OpenSignatureStream: stream content is '" + << OString(reinterpret_cast<const char*>(aData.getArray()), + aData.getLength()) + << "'"); + } + } + aHelper.xSignatureStream.clear(); +#endif + + aHelper.xSignatureStream = aHelper.xSignatureStorage->openStreamElement( aSIGStreamName, nOpenMode ); + } + } + catch(css::io::IOException& ) + { + // Doesn't have to exist... + SAL_WARN_IF( nOpenMode != css::embed::ElementModes::READ, "xmlsecurity.helper", "Error creating signature stream..." ); + } + } + else if(rxStore->hasByName("[Content_Types].xml")) + { + try + { + if (rxStore->hasByName("_xmlsignatures") && (nOpenMode & embed::ElementModes::TRUNCATE)) + // Truncate, then all signatures will be written -> remove previous ones. + rxStore->removeElement("_xmlsignatures"); + + aHelper.xSignatureStorage = rxStore->openStorageElement("_xmlsignatures", nSubStorageOpenMode); + aHelper.nStorageFormat = embed::StorageFormats::OFOPXML; + } + catch (const io::IOException&) + { + TOOLS_WARN_EXCEPTION_IF(nOpenMode != css::embed::ElementModes::READ, "xmlsecurity.helper", "DocumentSignatureHelper::OpenSignatureStream:"); + } + } + + return aHelper; +} + +/** Check whether the current file can be signed with GPG (only ODF >= 1.2 can currently) */ +bool DocumentSignatureHelper::CanSignWithGPG( + const Reference < css::embed::XStorage >& rxStore, + std::u16string_view sOdfVersion) +{ + if (!rxStore.is()) + return false; + + if (rxStore->hasByName("META-INF")) // ODF + { + return !isODFPre_1_2(sOdfVersion); + } + + return false; +} + + + +//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< 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; + std::function<OUString(const OUString&)> fEncode = [](const OUString& rStr) { return rStr; }; + if (alg == DocumentSignatureAlgorithm::OOo2) + //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 (...#...) + fEncode = [](const OUString& rStr) { + return rtl::Uri::encode(rStr, rtl_UriCharClassPchar, rtl_UriEncodeCheckEscapes, RTL_TEXTENCODING_UTF8); + }; + + for ( int i = sigInfo.vSignatureReferenceInfors.size(); i; ) + { + const SignatureReferenceInformation& rInf = sigInfo.vSignatureReferenceInfors[--i]; + // There is also an extra entry of type SignatureReferenceType::SAMEDOCUMENT because of signature date. + if ( ( rInf.nType == SignatureReferenceType::BINARYSTREAM ) || ( rInf.nType == SignatureReferenceType::XMLSTREAM ) ) + { + //find the file in the element list + if (std::any_of(sElementList.cbegin(), sElementList.cend(), + [&fEncode, &rInf](const OUString& rElement) { return fEncode(rElement) == fEncode(rInf.ouURI); })) + nRealCount++; + } + } + 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( + std::u16string_view rUri, std::u16string_view rPath) +{ + //split up the uri and path into segments. Both are separated by '/' + std::vector<OUString> vUriSegments; + for (sal_Int32 nIndex = 0; nIndex >= 0; ) + vUriSegments.push_back(OUString(o3tl::getToken(rUri, 0, '/', nIndex ))); + + std::vector<OUString> vPathSegments; + for (sal_Int32 nIndex = 0; nIndex >= 0; ) + vPathSegments.push_back(OUString(o3tl::getToken(rPath, 0, '/', nIndex ))); + + if (vUriSegments.size() != vPathSegments.size()) + return false; + + //Now compare each segment of the uri with its counterpart from the path + return std::equal( + vUriSegments.cbegin(), vUriSegments.cend(), vPathSegments.cbegin(), + [](const OUString& rUriSegment, const OUString& rPathSegment) { + //Decode the uri segment, so that %20 becomes ' ', etc. + OUString sDecUri = rtl::Uri::decode(rUriSegment, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8); + return sDecUri == rPathSegment; + }); +} + +OUString DocumentSignatureHelper::GetDocumentContentSignatureDefaultStreamName() +{ + return "documentsignatures.xml"; +} + +OUString DocumentSignatureHelper::GetScriptingContentSignatureDefaultStreamName() +{ + return "macrosignatures.xml"; +} + +OUString DocumentSignatureHelper::GetPackageSignatureDefaultStreamName() +{ + return "packagesignatures.xml"; +} + +void DocumentSignatureHelper::writeDigestMethod( + const uno::Reference<xml::sax::XDocumentHandler>& xDocumentHandler) +{ + rtl::Reference<comphelper::AttributeList> pAttributeList(new comphelper::AttributeList()); + pAttributeList->AddAttribute("Algorithm", ALGO_XMLDSIGSHA256); + xDocumentHandler->startElement("DigestMethod", uno::Reference<xml::sax::XAttributeList>(pAttributeList)); + xDocumentHandler->endElement("DigestMethod"); +} + +static void WriteXadesCert( + uno::Reference<xml::sax::XDocumentHandler> const& xDocumentHandler, + SignatureInformation::X509CertInfo const& rCertInfo) +{ + xDocumentHandler->startElement("xd:Cert", uno::Reference<xml::sax::XAttributeList>(new comphelper::AttributeList())); + xDocumentHandler->startElement("xd:CertDigest", uno::Reference<xml::sax::XAttributeList>(new comphelper::AttributeList())); + DocumentSignatureHelper::writeDigestMethod(xDocumentHandler); + xDocumentHandler->startElement("DigestValue", uno::Reference<xml::sax::XAttributeList>(new comphelper::AttributeList())); + assert(!rCertInfo.CertDigest.isEmpty()); + xDocumentHandler->characters(rCertInfo.CertDigest); + xDocumentHandler->endElement("DigestValue"); + xDocumentHandler->endElement("xd:CertDigest"); + xDocumentHandler->startElement("xd:IssuerSerial", uno::Reference<xml::sax::XAttributeList>(new comphelper::AttributeList())); + xDocumentHandler->startElement("X509IssuerName", uno::Reference<xml::sax::XAttributeList>(new comphelper::AttributeList())); + xDocumentHandler->characters(rCertInfo.X509IssuerName); + xDocumentHandler->endElement("X509IssuerName"); + xDocumentHandler->startElement("X509SerialNumber", uno::Reference<xml::sax::XAttributeList>(new comphelper::AttributeList())); + xDocumentHandler->characters(rCertInfo.X509SerialNumber); + xDocumentHandler->endElement("X509SerialNumber"); + xDocumentHandler->endElement("xd:IssuerSerial"); + xDocumentHandler->endElement("xd:Cert"); +} + +void DocumentSignatureHelper::writeSignedProperties( + const uno::Reference<xml::sax::XDocumentHandler>& xDocumentHandler, + const SignatureInformation& signatureInfo, + const OUString& sDate, const bool bWriteSignatureLineData) +{ + { + rtl::Reference<comphelper::AttributeList> pAttributeList(new comphelper::AttributeList()); + pAttributeList->AddAttribute("Id", "idSignedProperties_" + signatureInfo.ouSignatureId); + xDocumentHandler->startElement("xd:SignedProperties", uno::Reference<xml::sax::XAttributeList>(pAttributeList)); + } + + xDocumentHandler->startElement("xd:SignedSignatureProperties", uno::Reference<xml::sax::XAttributeList>(new comphelper::AttributeList())); + xDocumentHandler->startElement("xd:SigningTime", uno::Reference<xml::sax::XAttributeList>(new comphelper::AttributeList())); + xDocumentHandler->characters(sDate); + xDocumentHandler->endElement("xd:SigningTime"); + xDocumentHandler->startElement("xd:SigningCertificate", uno::Reference<xml::sax::XAttributeList>(new comphelper::AttributeList())); + assert(signatureInfo.GetSigningCertificate() || !signatureInfo.ouGpgKeyID.isEmpty()); + if (signatureInfo.GetSigningCertificate()) + { + // how should this deal with multiple X509Data elements? + // for now, let's write all of the certificates ... + for (auto const& rData : signatureInfo.X509Datas) + { + for (auto const& it : rData) + { + WriteXadesCert(xDocumentHandler, it); + } + } + } + else + { + // for PGP, write empty mandatory X509IssuerName, X509SerialNumber + SignatureInformation::X509CertInfo temp; + temp.CertDigest = signatureInfo.ouGpgKeyID; + WriteXadesCert(xDocumentHandler, temp); + } + xDocumentHandler->endElement("xd:SigningCertificate"); + xDocumentHandler->startElement("xd:SignaturePolicyIdentifier", uno::Reference<xml::sax::XAttributeList>(new comphelper::AttributeList())); + xDocumentHandler->startElement("xd:SignaturePolicyImplied", uno::Reference<xml::sax::XAttributeList>(new comphelper::AttributeList())); + xDocumentHandler->endElement("xd:SignaturePolicyImplied"); + xDocumentHandler->endElement("xd:SignaturePolicyIdentifier"); + + if (bWriteSignatureLineData && !signatureInfo.ouSignatureLineId.isEmpty() + && signatureInfo.aValidSignatureImage.is() && signatureInfo.aInvalidSignatureImage.is()) + { + rtl::Reference<comphelper::AttributeList> pAttributeList(new comphelper::AttributeList()); + pAttributeList->AddAttribute( + "xmlns:loext", "urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0"); + xDocumentHandler->startElement( + "loext:SignatureLine", + Reference<XAttributeList>(pAttributeList)); + + { + // Write SignatureLineId element + xDocumentHandler->startElement( + "loext:SignatureLineId", + Reference<XAttributeList>(new comphelper::AttributeList())); + xDocumentHandler->characters(signatureInfo.ouSignatureLineId); + xDocumentHandler->endElement("loext:SignatureLineId"); + } + + { + // Write SignatureLineValidImage element + xDocumentHandler->startElement( + "loext:SignatureLineValidImage", + Reference<XAttributeList>(new comphelper::AttributeList())); + + OUString aGraphicInBase64; + Graphic aGraphic(signatureInfo.aValidSignatureImage); + if (!XOutBitmap::GraphicToBase64(aGraphic, aGraphicInBase64, false)) + SAL_WARN("xmlsecurity.helper", "could not convert graphic to base64"); + + xDocumentHandler->characters(aGraphicInBase64); + xDocumentHandler->endElement("loext:SignatureLineValidImage"); + } + + { + // Write SignatureLineInvalidImage element + xDocumentHandler->startElement( + "loext:SignatureLineInvalidImage", + Reference<XAttributeList>(new comphelper::AttributeList())); + OUString aGraphicInBase64; + Graphic aGraphic(signatureInfo.aInvalidSignatureImage); + if (!XOutBitmap::GraphicToBase64(aGraphic, aGraphicInBase64, false)) + SAL_WARN("xmlsecurity.helper", "could not convert graphic to base64"); + xDocumentHandler->characters(aGraphicInBase64); + xDocumentHandler->endElement("loext:SignatureLineInvalidImage"); + } + + xDocumentHandler->endElement("loext:SignatureLine"); + } + + xDocumentHandler->endElement("xd:SignedSignatureProperties"); + + xDocumentHandler->endElement("xd:SignedProperties"); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/helper/documentsignaturemanager.cxx b/xmlsecurity/source/helper/documentsignaturemanager.cxx new file mode 100644 index 0000000000..80d74c27ba --- /dev/null +++ b/xmlsecurity/source/helper/documentsignaturemanager.cxx @@ -0,0 +1,705 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <documentsignaturemanager.hxx> +#include <config_gpgme.h> + +#include <gpg/SEInitializer.hxx> + +#include <com/sun/star/embed/StorageFormats.hpp> +#include <com/sun/star/embed/ElementModes.hpp> +#include <com/sun/star/embed/XStorage.hpp> +#include <com/sun/star/io/XTempFile.hpp> +#include <com/sun/star/io/XTruncate.hpp> +#include <com/sun/star/embed/XTransactedObject.hpp> +#include <com/sun/star/xml/crypto/SEInitializer.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/packages/manifest/ManifestReader.hpp> +#include <com/sun/star/xml/sax/XDocumentHandler.hpp> +#include <com/sun/star/xml/sax/XWriter.hpp> +#include <com/sun/star/frame/XModel.hpp> + +#include <comphelper/base64.hxx> +#include <comphelper/storagehelper.hxx> +#include <rtl/ustrbuf.hxx> +#include <sal/log.hxx> +#include <tools/datetime.hxx> +#include <o3tl/string_view.hxx> + +#include <certificate.hxx> +#include <biginteger.hxx> + +#include <xmlsec/xmlsec_init.hxx> + +#include <pdfsignaturehelper.hxx> + +#include <memory> + +using namespace css; +using namespace css::graphic; +using namespace css::uno; + +DocumentSignatureManager::DocumentSignatureManager( + const uno::Reference<uno::XComponentContext>& xContext, DocumentSignatureMode eMode) + : mxContext(xContext) + , maSignatureHelper(xContext) + , meSignatureMode(eMode) +{ +} + +DocumentSignatureManager::~DocumentSignatureManager() { deInitXmlSec(); } + +bool DocumentSignatureManager::init() +{ + SAL_WARN_IF(mxSEInitializer.is(), "xmlsecurity.helper", + "DocumentSignatureManager::Init - mxSEInitializer already set!"); + SAL_WARN_IF(mxSecurityContext.is(), "xmlsecurity.helper", + "DocumentSignatureManager::Init - mxSecurityContext already set!"); + SAL_WARN_IF(mxGpgSEInitializer.is(), "xmlsecurity.helper", + "DocumentSignatureManager::Init - mxGpgSEInitializer already set!"); + + // xmlsec is needed by both services, so init before those + initXmlSec(); + + mxSEInitializer = xml::crypto::SEInitializer::create(mxContext); +#if HAVE_FEATURE_GPGME + mxGpgSEInitializer.set(new SEInitializerGpg()); +#endif + + if (mxSEInitializer.is()) + mxSecurityContext = mxSEInitializer->createSecurityContext(OUString()); + +#if HAVE_FEATURE_GPGME + if (mxGpgSEInitializer.is()) + mxGpgSecurityContext = mxGpgSEInitializer->createSecurityContext(OUString()); + + return mxSecurityContext.is() || mxGpgSecurityContext.is(); +#else + return mxSecurityContext.is(); +#endif +} + +PDFSignatureHelper& DocumentSignatureManager::getPDFSignatureHelper() +{ + bool bInit = true; + if (!mxSecurityContext.is()) + bInit = init(); + + SAL_WARN_IF(!bInit, "xmlsecurity.comp", "Error initializing security context!"); + + if (!mpPDFSignatureHelper) + mpPDFSignatureHelper = std::make_unique<PDFSignatureHelper>(); + + return *mpPDFSignatureHelper; +} + +#if 0 // For some reason does not work +bool DocumentSignatureManager::IsXAdESRelevant() +{ + if (mxStore.is()) + { + // ZIP-based: ODF or OOXML. + maSignatureHelper.StartMission(); + + SignatureStreamHelper aStreamHelper = ImplOpenSignatureStream(embed::ElementModes::READ, /*bUseTempStream=*/true); + if (aStreamHelper.nStorageFormat == embed::StorageFormats::OFOPXML) + { + maSignatureHelper.EndMission(); + return false; + } + // FIXME: How to figure out if it is ODF 1.2? + maSignatureHelper.EndMission(); + return true; + } + return false; +} +#endif + +bool DocumentSignatureManager::readManifest() +{ + // Check if manifest was already read + if (m_manifest.hasElements()) + return true; + + if (!mxContext.is()) + return false; + + if (!mxStore.is()) + return false; + + uno::Reference<packages::manifest::XManifestReader> xReader + = packages::manifest::ManifestReader::create(mxContext); + + if (mxStore->hasByName("META-INF")) + { + //Get the manifest.xml + uno::Reference<embed::XStorage> xSubStore( + mxStore->openStorageElement("META-INF", embed::ElementModes::READ), UNO_SET_THROW); + + uno::Reference<io::XInputStream> xStream( + xSubStore->openStreamElement("manifest.xml", css::embed::ElementModes::READ), + UNO_QUERY_THROW); + + m_manifest = xReader->readManifestSequence(xStream); + } + return true; +} + +/* Using the zip storage, we cannot get the properties "MediaType" and "IsEncrypted" + We use the manifest to find out if a file is xml and if it is encrypted. + The parameter is an encoded uri. However, the manifest contains paths. Therefore + the path is encoded as uri, so they can be compared. +*/ +bool DocumentSignatureManager::isXML(std::u16string_view rURI) +{ + SAL_WARN_IF(!mxStore.is(), "xmlsecurity.helper", "empty storage reference"); + + bool bIsXML = false; + bool bPropsAvailable = false; + static constexpr OUStringLiteral sPropFullPath(u"FullPath"); + static constexpr OUStringLiteral sPropMediaType(u"MediaType"); + static constexpr OUStringLiteral sPropDigest(u"Digest"); + + if (readManifest()) + { + for (const uno::Sequence<beans::PropertyValue>& entry : std::as_const(m_manifest)) + { + OUString sPath; + OUString sMediaType; + bool bEncrypted = false; + for (const beans::PropertyValue& prop : entry) + { + if (prop.Name == sPropFullPath) + prop.Value >>= sPath; + else if (prop.Name == sPropMediaType) + prop.Value >>= sMediaType; + else if (prop.Name == sPropDigest) + bEncrypted = true; + } + if (DocumentSignatureHelper::equalsReferenceUriManifestPath(rURI, sPath)) + { + bIsXML = sMediaType == "text/xml" && !bEncrypted; + bPropsAvailable = true; + break; + } + } + } + if (!bPropsAvailable) + { + //This would be the case for at least mimetype, META-INF/manifest.xml + //META-INF/macrosignatures.xml. + //Files can only be encrypted if they are in the manifest.xml. + //That is, the current file cannot be encrypted, otherwise bPropsAvailable + //would be true. + size_t nSep = rURI.rfind('.'); + if (nSep != std::u16string_view::npos) + { + std::u16string_view aExt = rURI.substr(nSep + 1); + if (o3tl::equalsIgnoreAsciiCase(aExt, u"XML")) + bIsXML = true; + } + } + return bIsXML; +} + +//If bTempStream is true, then a temporary stream is return. If it is false then, the actual +//signature stream is used. +//Every time the user presses Add a new temporary stream is created. +//We keep the temporary stream as member because ImplGetSignatureInformations +//will later access the stream to create DocumentSignatureInformation objects +//which are stored in maCurrentSignatureInformations. +SignatureStreamHelper DocumentSignatureManager::ImplOpenSignatureStream(sal_Int32 nStreamOpenMode, + bool bTempStream) +{ + SignatureStreamHelper aHelper; + if (mxStore.is() && mxStore->hasByName("[Content_Types].xml")) + aHelper.nStorageFormat = embed::StorageFormats::OFOPXML; + + if (bTempStream) + { + if (nStreamOpenMode & embed::ElementModes::TRUNCATE) + { + //We write always into a new temporary stream. + mxTempSignatureStream = new utl::TempFileFastService; + if (aHelper.nStorageFormat != embed::StorageFormats::OFOPXML) + aHelper.xSignatureStream = mxTempSignatureStream; + else + { + mxTempSignatureStorage = comphelper::OStorageHelper::GetStorageOfFormatFromStream( + ZIP_STORAGE_FORMAT_STRING, mxTempSignatureStream); + aHelper.xSignatureStorage = mxTempSignatureStorage; + } + } + else + { + //When we read from the temp stream, then we must have previously + //created one. + SAL_WARN_IF(!mxTempSignatureStream.is(), "xmlsecurity.helper", + "empty temp. signature stream reference"); + } + aHelper.xSignatureStream = mxTempSignatureStream; + if (aHelper.nStorageFormat == embed::StorageFormats::OFOPXML) + aHelper.xSignatureStorage = mxTempSignatureStorage; + } + else + { + //No temporary stream + if (!mxSignatureStream.is()) + { + //We may not have a dedicated stream for writing the signature + //So we take one directly from the storage + //Or DocumentDigitalSignatures::showDocumentContentSignatures was called, + //in which case Add/Remove is not allowed. This is done, for example, if the + //document is readonly + aHelper = DocumentSignatureHelper::OpenSignatureStream(mxStore, nStreamOpenMode, + meSignatureMode); + } + else + { + aHelper.xSignatureStream = mxSignatureStream; + } + } + + if (nStreamOpenMode & embed::ElementModes::TRUNCATE) + { + if (aHelper.xSignatureStream.is() + && aHelper.nStorageFormat != embed::StorageFormats::OFOPXML) + { + uno::Reference<io::XTruncate> xTruncate(aHelper.xSignatureStream, uno::UNO_QUERY_THROW); + xTruncate->truncate(); + } + } + else if (bTempStream || mxSignatureStream.is()) + { + //In case we read the signature stream from the storage directly, + //which is the case when DocumentDigitalSignatures::showDocumentContentSignatures + //then XSeakable is not supported + uno::Reference<io::XSeekable> xSeek(aHelper.xSignatureStream, uno::UNO_QUERY_THROW); + xSeek->seek(0); + } + + return aHelper; +} + +bool DocumentSignatureManager::add( + const uno::Reference<security::XCertificate>& xCert, + const uno::Reference<xml::crypto::XXMLSecurityContext>& xSecurityContext, + const OUString& rDescription, sal_Int32& nSecurityId, bool bAdESCompliant, + const OUString& rSignatureLineId, const Reference<XGraphic>& xValidGraphic, + const Reference<XGraphic>& xInvalidGraphic) +{ + if (!xCert.is()) + { + SAL_WARN("xmlsecurity.helper", "no certificate selected"); + return false; + } + + // GPG or X509 key? + uno::Reference<lang::XServiceInfo> xServiceInfo(xSecurityContext, uno::UNO_QUERY); + if (xServiceInfo->getImplementationName() + == "com.sun.star.xml.security.gpg.XMLSecurityContext_GpgImpl") + { + // GPG keys only really have PGPKeyId and PGPKeyPacket + if (!mxStore.is()) + { + SAL_WARN("xmlsecurity.helper", "cannot sign pdfs with GPG keys"); + return false; + } + + maSignatureHelper.StartMission(xSecurityContext); + + nSecurityId = maSignatureHelper.GetNewSecurityId(); + + OUStringBuffer aStrBuffer; + comphelper::Base64::encode(aStrBuffer, xCert->getEncoded()); + + OUString aKeyId; + if (auto pCertificate = dynamic_cast<xmlsecurity::Certificate*>(xCert.get())) + { + OUStringBuffer aBuffer; + comphelper::Base64::encode(aBuffer, pCertificate->getSHA256Thumbprint()); + aKeyId = aBuffer.makeStringAndClear(); + } + else + SAL_WARN("xmlsecurity.helper", + "XCertificate implementation without an xmlsecurity::Certificate one"); + + maSignatureHelper.SetGpgCertificate(nSecurityId, aKeyId, aStrBuffer.makeStringAndClear(), + xCert->getIssuerName()); + } + else + { + OUString aCertSerial = xmlsecurity::bigIntegerToNumericString(xCert->getSerialNumber()); + if (aCertSerial.isEmpty()) + { + SAL_WARN("xmlsecurity.helper", "Error in Certificate, problem with serial number!"); + return false; + } + + if (!mxStore.is()) + { + // Something not ZIP based, try PDF. + nSecurityId = getPDFSignatureHelper().GetNewSecurityId(); + getPDFSignatureHelper().SetX509Certificate(xCert); + getPDFSignatureHelper().SetDescription(rDescription); + uno::Reference<io::XInputStream> xInputStream(mxSignatureStream, uno::UNO_QUERY); + if (!getPDFSignatureHelper().Sign(mxModel, xInputStream, bAdESCompliant)) + { + SAL_WARN("xmlsecurity.helper", "PDFSignatureHelper::Sign() failed"); + return false; + } + return true; + } + + maSignatureHelper.StartMission(xSecurityContext); + + nSecurityId = maSignatureHelper.GetNewSecurityId(); + + OUStringBuffer aStrBuffer; + comphelper::Base64::encode(aStrBuffer, xCert->getEncoded()); + + OUString aCertDigest; + svl::crypto::SignatureMethodAlgorithm eAlgorithmID + = svl::crypto::SignatureMethodAlgorithm::RSA; + if (auto pCertificate = dynamic_cast<xmlsecurity::Certificate*>(xCert.get())) + { + OUStringBuffer aBuffer; + comphelper::Base64::encode(aBuffer, pCertificate->getSHA256Thumbprint()); + aCertDigest = aBuffer.makeStringAndClear(); + + eAlgorithmID = pCertificate->getSignatureMethodAlgorithm(); + } + else + SAL_WARN("xmlsecurity.helper", + "XCertificate implementation without an xmlsecurity::Certificate one"); + + maSignatureHelper.SetX509Certificate(nSecurityId, xCert->getIssuerName(), aCertSerial, + aStrBuffer.makeStringAndClear(), aCertDigest, + eAlgorithmID); + } + + const uno::Sequence<uno::Reference<security::XCertificate>> aCertPath + = xSecurityContext->getSecurityEnvironment()->buildCertificatePath(xCert); + + OUStringBuffer aStrBuffer; + for (uno::Reference<security::XCertificate> const& rxCertificate : aCertPath) + { + comphelper::Base64::encode(aStrBuffer, rxCertificate->getEncoded()); + OUString aString = aStrBuffer.makeStringAndClear(); + maSignatureHelper.AddEncapsulatedX509Certificate(aString); + } + + std::vector<OUString> aElements = DocumentSignatureHelper::CreateElementList( + mxStore, meSignatureMode, DocumentSignatureAlgorithm::OOo3_2); + DocumentSignatureHelper::AppendContentTypes(mxStore, aElements); + + for (OUString const& rUri : aElements) + { + bool bBinaryMode = !isXML(rUri); + maSignatureHelper.AddForSigning(nSecurityId, rUri, bBinaryMode, bAdESCompliant); + } + + maSignatureHelper.SetDateTime(nSecurityId, DateTime(DateTime::SYSTEM)); + maSignatureHelper.SetDescription(nSecurityId, rDescription); + + if (!rSignatureLineId.isEmpty()) + maSignatureHelper.SetSignatureLineId(nSecurityId, rSignatureLineId); + + if (xValidGraphic.is()) + maSignatureHelper.SetSignatureLineValidGraphic(nSecurityId, xValidGraphic); + + if (xInvalidGraphic.is()) + maSignatureHelper.SetSignatureLineInvalidGraphic(nSecurityId, xInvalidGraphic); + + // We open a signature stream in which the existing and the new + //signature is written. ImplGetSignatureInformation (later in this function) will + //then read the stream and fill maCurrentSignatureInformations. The final signature + //is written when the user presses OK. Then only maCurrentSignatureInformation and + //a sax writer are used to write the information. + SignatureStreamHelper aStreamHelper + = ImplOpenSignatureStream(embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE, true); + + if (aStreamHelper.nStorageFormat != embed::StorageFormats::OFOPXML) + { + uno::Reference<io::XOutputStream> xOutputStream(aStreamHelper.xSignatureStream, + uno::UNO_QUERY_THROW); + uno::Reference<xml::sax::XWriter> xSaxWriter + = maSignatureHelper.CreateDocumentHandlerWithHeader(xOutputStream); + + // Export old signatures... + uno::Reference<xml::sax::XDocumentHandler> xDocumentHandler(xSaxWriter, + uno::UNO_QUERY_THROW); + std::size_t nInfos = maCurrentSignatureInformations.size(); + for (std::size_t n = 0; n < nInfos; n++) + XMLSignatureHelper::ExportSignature(xDocumentHandler, maCurrentSignatureInformations[n], + bAdESCompliant); + + // Create a new one... + maSignatureHelper.CreateAndWriteSignature(xDocumentHandler, bAdESCompliant); + + // That's it... + XMLSignatureHelper::CloseDocumentHandler(xDocumentHandler); + } + else + { + // OOXML + + // Handle relations. + maSignatureHelper.EnsureSignaturesRelation(mxStore, /*bAdd=*/true); + // Old signatures + the new one. + int nSignatureCount = maCurrentSignatureInformations.size() + 1; + maSignatureHelper.ExportSignatureRelations(aStreamHelper.xSignatureStorage, + nSignatureCount); + + // Export old signatures. + for (std::size_t i = 0; i < maCurrentSignatureInformations.size(); ++i) + maSignatureHelper.ExportOOXMLSignature(mxStore, aStreamHelper.xSignatureStorage, + maCurrentSignatureInformations[i], i + 1); + + // Create a new signature. + maSignatureHelper.CreateAndWriteOOXMLSignature(mxStore, aStreamHelper.xSignatureStorage, + nSignatureCount); + + // Flush objects. + uno::Reference<embed::XTransactedObject> xTransact(aStreamHelper.xSignatureStorage, + uno::UNO_QUERY); + xTransact->commit(); + uno::Reference<io::XOutputStream> xOutputStream(aStreamHelper.xSignatureStream, + uno::UNO_QUERY); + xOutputStream->closeOutput(); + + uno::Reference<io::XTempFile> xTempFile(aStreamHelper.xSignatureStream, uno::UNO_QUERY); + SAL_INFO("xmlsecurity.helper", + "DocumentSignatureManager::add temporary storage at " << xTempFile->getUri()); + } + + maSignatureHelper.EndMission(); + return true; +} + +void DocumentSignatureManager::remove(sal_uInt16 nPosition) +{ + if (!mxStore.is()) + { + // Something not ZIP based, try PDF. + uno::Reference<io::XInputStream> xInputStream(mxSignatureStream, uno::UNO_QUERY); + if (!PDFSignatureHelper::RemoveSignature(xInputStream, nPosition)) + { + SAL_WARN("xmlsecurity.helper", "PDFSignatureHelper::RemoveSignature() failed"); + return; + } + + // Only erase when the removal was successful, it may fail for PDF. + // Also, erase the requested and all following signatures, as PDF signatures are always chained. + maCurrentSignatureInformations.erase(maCurrentSignatureInformations.begin() + nPosition, + maCurrentSignatureInformations.end()); + return; + } + + maCurrentSignatureInformations.erase(maCurrentSignatureInformations.begin() + nPosition); + + // Export all other signatures... + SignatureStreamHelper aStreamHelper = ImplOpenSignatureStream( + embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE, /*bTempStream=*/true); + + if (aStreamHelper.nStorageFormat != embed::StorageFormats::OFOPXML) + { + uno::Reference<io::XOutputStream> xOutputStream(aStreamHelper.xSignatureStream, + uno::UNO_QUERY_THROW); + uno::Reference<xml::sax::XWriter> xSaxWriter + = maSignatureHelper.CreateDocumentHandlerWithHeader(xOutputStream); + + uno::Reference<xml::sax::XDocumentHandler> xDocumentHandler(xSaxWriter, + uno::UNO_QUERY_THROW); + std::size_t nInfos = maCurrentSignatureInformations.size(); + for (std::size_t n = 0; n < nInfos; ++n) + XMLSignatureHelper::ExportSignature(xDocumentHandler, maCurrentSignatureInformations[n], + false /* ??? */); + + XMLSignatureHelper::CloseDocumentHandler(xDocumentHandler); + } + else + { + // OOXML + + // Handle relations. + int nSignatureCount = maCurrentSignatureInformations.size(); + maSignatureHelper.ExportSignatureRelations(aStreamHelper.xSignatureStorage, + nSignatureCount); + + // Export old signatures. + for (std::size_t i = 0; i < maCurrentSignatureInformations.size(); ++i) + maSignatureHelper.ExportOOXMLSignature(mxStore, aStreamHelper.xSignatureStorage, + maCurrentSignatureInformations[i], i + 1); + + // Flush objects. + uno::Reference<embed::XTransactedObject> xTransact(aStreamHelper.xSignatureStorage, + uno::UNO_QUERY); + xTransact->commit(); + uno::Reference<io::XOutputStream> xOutputStream(aStreamHelper.xSignatureStream, + uno::UNO_QUERY); + xOutputStream->closeOutput(); + + uno::Reference<io::XTempFile> xTempFile(aStreamHelper.xSignatureStream, uno::UNO_QUERY); + SAL_INFO("xmlsecurity.helper", "DocumentSignatureManager::remove: temporary storage is at " + << xTempFile->getUri()); + } +} + +void DocumentSignatureManager::read(bool bUseTempStream, bool bCacheLastSignature) +{ + maCurrentSignatureInformations.clear(); + + if (mxStore.is()) + { + // ZIP-based: ODF or OOXML. + maSignatureHelper.StartMission(mxSecurityContext); + + SignatureStreamHelper aStreamHelper + = ImplOpenSignatureStream(embed::ElementModes::READ, bUseTempStream); + if (aStreamHelper.nStorageFormat != embed::StorageFormats::OFOPXML + && aStreamHelper.xSignatureStream.is()) + { + uno::Reference<io::XInputStream> xInputStream(aStreamHelper.xSignatureStream, + uno::UNO_QUERY); + maSignatureHelper.ReadAndVerifySignature(xInputStream); + } + else if (aStreamHelper.nStorageFormat == embed::StorageFormats::OFOPXML + && aStreamHelper.xSignatureStorage.is()) + maSignatureHelper.ReadAndVerifySignatureStorage(aStreamHelper.xSignatureStorage, + bCacheLastSignature); + maSignatureHelper.EndMission(); + + // this parses the XML independently from ImplVerifySignatures() - check + // certificates here too ... + for (auto const& it : maSignatureHelper.GetSignatureInformations()) + { + if (!it.X509Datas.empty()) + { + uno::Reference<xml::crypto::XSecurityEnvironment> const xSecEnv( + getSecurityEnvironment()); + getSignatureHelper().CheckAndUpdateSignatureInformation(xSecEnv, it); + } + } + + maCurrentSignatureInformations = maSignatureHelper.GetSignatureInformations(); + } + else + { + // Something not ZIP based, try PDF. + uno::Reference<io::XInputStream> xInputStream(mxSignatureStream, uno::UNO_QUERY); + if (getPDFSignatureHelper().ReadAndVerifySignature(xInputStream)) + maCurrentSignatureInformations = getPDFSignatureHelper().GetSignatureInformations(); + } +} + +void DocumentSignatureManager::write(bool bXAdESCompliantIfODF) +{ + if (!mxStore.is()) + { + // Something not ZIP based, assume PDF, which is written directly in add() already. + return; + } + + // Export all other signatures... + SignatureStreamHelper aStreamHelper = ImplOpenSignatureStream( + embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE, false); + + if (aStreamHelper.xSignatureStream.is() + && aStreamHelper.nStorageFormat != embed::StorageFormats::OFOPXML) + { + // ODF + uno::Reference<io::XOutputStream> xOutputStream(aStreamHelper.xSignatureStream, + uno::UNO_QUERY); + uno::Reference<xml::sax::XWriter> xSaxWriter + = maSignatureHelper.CreateDocumentHandlerWithHeader(xOutputStream); + + uno::Reference<xml::sax::XDocumentHandler> xDocumentHandler(xSaxWriter, + uno::UNO_QUERY_THROW); + std::size_t nInfos = maCurrentSignatureInformations.size(); + for (std::size_t n = 0; n < nInfos; ++n) + XMLSignatureHelper::ExportSignature(xDocumentHandler, maCurrentSignatureInformations[n], + bXAdESCompliantIfODF); + + XMLSignatureHelper::CloseDocumentHandler(xDocumentHandler); + } + else if (aStreamHelper.xSignatureStorage.is() + && aStreamHelper.nStorageFormat == embed::StorageFormats::OFOPXML) + { + // OOXML + std::size_t nSignatureCount = maCurrentSignatureInformations.size(); + maSignatureHelper.ExportSignatureContentTypes(mxStore, nSignatureCount); + if (nSignatureCount > 0) + maSignatureHelper.ExportSignatureRelations(aStreamHelper.xSignatureStorage, + nSignatureCount); + else + { + // Removing all signatures: then need to remove the signature relation as well. + maSignatureHelper.EnsureSignaturesRelation(mxStore, /*bAdd=*/false); + // Also remove the whole signature sub-storage: release our read-write reference + remove the element. + aStreamHelper = SignatureStreamHelper(); + mxStore->removeElement("_xmlsignatures"); + } + + for (std::size_t i = 0; i < nSignatureCount; ++i) + maSignatureHelper.ExportOOXMLSignature(mxStore, aStreamHelper.xSignatureStorage, + maCurrentSignatureInformations[i], i + 1); + } + + // If stream was not provided, we are responsible for committing it... + if (!mxSignatureStream.is() && aStreamHelper.xSignatureStorage.is()) + { + uno::Reference<embed::XTransactedObject> xTrans(aStreamHelper.xSignatureStorage, + uno::UNO_QUERY); + xTrans->commit(); + } +} + +uno::Reference<xml::crypto::XSecurityEnvironment> DocumentSignatureManager::getSecurityEnvironment() +{ + return mxSecurityContext.is() ? mxSecurityContext->getSecurityEnvironment() + : uno::Reference<xml::crypto::XSecurityEnvironment>(); +} + +uno::Reference<xml::crypto::XSecurityEnvironment> +DocumentSignatureManager::getGpgSecurityEnvironment() +{ + return mxGpgSecurityContext.is() ? mxGpgSecurityContext->getSecurityEnvironment() + : uno::Reference<xml::crypto::XSecurityEnvironment>(); +} + +uno::Reference<xml::crypto::XXMLSecurityContext> const& +DocumentSignatureManager::getSecurityContext() const +{ + return mxSecurityContext; +} + +uno::Reference<xml::crypto::XXMLSecurityContext> const& +DocumentSignatureManager::getGpgSecurityContext() const +{ + return mxGpgSecurityContext; +} + +void DocumentSignatureManager::setModel(const uno::Reference<frame::XModel>& xModel) +{ + mxModel = xModel; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/helper/ooxmlsecexporter.cxx b/xmlsecurity/source/helper/ooxmlsecexporter.cxx new file mode 100644 index 0000000000..804cfd2748 --- /dev/null +++ b/xmlsecurity/source/helper/ooxmlsecexporter.cxx @@ -0,0 +1,565 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "ooxmlsecexporter.hxx" + +#include <algorithm> +#include <memory> +#include <string_view> + +#include <com/sun/star/embed/ElementModes.hpp> +#include <com/sun/star/embed/XHierarchicalStorageAccess.hpp> +#include <com/sun/star/embed/XStorage.hpp> +#include <com/sun/star/beans/StringPair.hpp> +#include <com/sun/star/xml/sax/XDocumentHandler.hpp> + +#include <comphelper/attributelist.hxx> +#include <comphelper/ofopxmlhelper.hxx> +#include <o3tl/string_view.hxx> +#include <rtl/ref.hxx> +#include <sal/log.hxx> +#include <svx/xoutbmp.hxx> +#include <unotools/datetime.hxx> +#include <vcl/salctype.hxx> + +#include <documentsignaturehelper.hxx> +#include <xsecctl.hxx> + +using namespace com::sun::star; +using namespace css::xml::sax; + +struct OOXMLSecExporter::Impl +{ +private: + const uno::Reference<uno::XComponentContext>& m_xComponentContext; + const uno::Reference<embed::XStorage>& m_xRootStorage; + const uno::Reference<xml::sax::XDocumentHandler>& m_xDocumentHandler; + const SignatureInformation& m_rInformation; + OUString m_aSignatureTimeValue; + +public: + Impl(const uno::Reference<uno::XComponentContext>& xComponentContext, + const uno::Reference<embed::XStorage>& xRootStorage, + const uno::Reference<xml::sax::XDocumentHandler>& xDocumentHandler, + const SignatureInformation& rInformation) + : m_xComponentContext(xComponentContext) + , m_xRootStorage(xRootStorage) + , m_xDocumentHandler(xDocumentHandler) + , m_rInformation(rInformation) + { + } + + /// Should we intentionally not sign this stream? + static bool isOOXMLDenylist(std::u16string_view rStreamName); + /// Should we intentionally not sign this relation type? + static bool isOOXMLRelationDenylist(const OUString& rRelationName); + + const uno::Reference<xml::sax::XDocumentHandler>& getDocumentHandler() const + { + return m_xDocumentHandler; + } + + void writeSignature(); + void writeSignedInfo(); + void writeCanonicalizationMethod(); + void writeCanonicalizationTransform(); + void writeSignatureMethod(); + void writeSignedInfoReferences(); + void writeSignatureValue(); + void writeKeyInfo(); + void writePackageObject(); + void writeManifest(); + void writeRelationshipTransform(const OUString& rURI); + /// Writes <SignatureProperties> inside idPackageObject. + void writePackageObjectSignatureProperties(); + /// Writes a single <Reference> inside <Manifest>. + void writeManifestReference(const SignatureReferenceInformation& rReference); + void writeOfficeObject(); + /// Writes <SignatureInfoV1>. + void writeSignatureInfo(); + void writePackageSignature(); + void writeSignatureLineImages(); +}; + +bool OOXMLSecExporter::Impl::isOOXMLDenylist(std::u16string_view rStreamName) +{ + static const std::initializer_list<std::u16string_view> vDenylist + = { u"/%5BContent_Types%5D.xml", u"/docProps/app.xml", u"/docProps/core.xml", + // Don't attempt to sign other signatures for now. + u"/_xmlsignatures" }; + // Just check the prefix, as we don't care about the content type part of the stream name. + return std::any_of(vDenylist.begin(), vDenylist.end(), + [&](const std::u16string_view& rLiteral) { + return o3tl::starts_with(rStreamName, rLiteral); + }); +} + +bool OOXMLSecExporter::Impl::isOOXMLRelationDenylist(const OUString& rRelationName) +{ + static const std::initializer_list<std::u16string_view> vDenylist = { + u"http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties", + u"http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties", + u"http://schemas.openxmlformats.org/package/2006/relationships/digital-signature/origin" + }; + return std::find(vDenylist.begin(), vDenylist.end(), rRelationName) != vDenylist.end(); +} + +void OOXMLSecExporter::Impl::writeSignedInfo() +{ + m_xDocumentHandler->startElement( + "SignedInfo", uno::Reference<xml::sax::XAttributeList>(new comphelper::AttributeList())); + + writeCanonicalizationMethod(); + writeSignatureMethod(); + writeSignedInfoReferences(); + + m_xDocumentHandler->endElement("SignedInfo"); +} + +void OOXMLSecExporter::Impl::writeCanonicalizationMethod() +{ + rtl::Reference<comphelper::AttributeList> pAttributeList(new comphelper::AttributeList()); + pAttributeList->AddAttribute("Algorithm", ALGO_C14N); + m_xDocumentHandler->startElement("CanonicalizationMethod", + uno::Reference<xml::sax::XAttributeList>(pAttributeList)); + m_xDocumentHandler->endElement("CanonicalizationMethod"); +} + +void OOXMLSecExporter::Impl::writeCanonicalizationTransform() +{ + rtl::Reference<comphelper::AttributeList> pAttributeList(new comphelper::AttributeList()); + pAttributeList->AddAttribute("Algorithm", ALGO_C14N); + m_xDocumentHandler->startElement("Transform", + uno::Reference<xml::sax::XAttributeList>(pAttributeList)); + m_xDocumentHandler->endElement("Transform"); +} + +void OOXMLSecExporter::Impl::writeSignatureMethod() +{ + rtl::Reference<comphelper::AttributeList> pAttributeList(new comphelper::AttributeList()); + + if (m_rInformation.eAlgorithmID == svl::crypto::SignatureMethodAlgorithm::ECDSA) + pAttributeList->AddAttribute("Algorithm", ALGO_ECDSASHA256); + else + pAttributeList->AddAttribute("Algorithm", ALGO_RSASHA256); + + m_xDocumentHandler->startElement("SignatureMethod", + uno::Reference<xml::sax::XAttributeList>(pAttributeList)); + m_xDocumentHandler->endElement("SignatureMethod"); +} + +void OOXMLSecExporter::Impl::writeSignedInfoReferences() +{ + const SignatureReferenceInformations& rReferences = m_rInformation.vSignatureReferenceInfors; + for (const SignatureReferenceInformation& rReference : rReferences) + { + if (rReference.nType == SignatureReferenceType::SAMEDOCUMENT) + { + { + rtl::Reference<comphelper::AttributeList> pAttributeList( + new comphelper::AttributeList()); + if (!rReference.ouURI.startsWith("idSignedProperties")) + pAttributeList->AddAttribute("Type", + "http://www.w3.org/2000/09/xmldsig#Object"); + else + pAttributeList->AddAttribute("Type", + "http://uri.etsi.org/01903#SignedProperties"); + pAttributeList->AddAttribute("URI", "#" + rReference.ouURI); + m_xDocumentHandler->startElement( + "Reference", uno::Reference<xml::sax::XAttributeList>(pAttributeList)); + } + if (rReference.ouURI.startsWith("idSignedProperties")) + { + m_xDocumentHandler->startElement( + "Transforms", + uno::Reference<xml::sax::XAttributeList>(new comphelper::AttributeList())); + writeCanonicalizationTransform(); + m_xDocumentHandler->endElement("Transforms"); + } + + DocumentSignatureHelper::writeDigestMethod(m_xDocumentHandler); + m_xDocumentHandler->startElement( + "DigestValue", + uno::Reference<xml::sax::XAttributeList>(new comphelper::AttributeList())); + m_xDocumentHandler->characters(rReference.ouDigestValue); + m_xDocumentHandler->endElement("DigestValue"); + m_xDocumentHandler->endElement("Reference"); + } + } +} + +void OOXMLSecExporter::Impl::writeSignatureValue() +{ + m_xDocumentHandler->startElement("SignatureValue", uno::Reference<xml::sax::XAttributeList>( + new comphelper::AttributeList())); + m_xDocumentHandler->characters(m_rInformation.ouSignatureValue); + m_xDocumentHandler->endElement("SignatureValue"); +} + +void OOXMLSecExporter::Impl::writeKeyInfo() +{ + m_xDocumentHandler->startElement( + "KeyInfo", uno::Reference<xml::sax::XAttributeList>(new comphelper::AttributeList())); + assert(m_rInformation.GetSigningCertificate()); + for (auto const& rData : m_rInformation.X509Datas) + { + m_xDocumentHandler->startElement( + "X509Data", uno::Reference<xml::sax::XAttributeList>(new comphelper::AttributeList())); + for (auto const& it : rData) + { + m_xDocumentHandler->startElement( + "X509Certificate", + uno::Reference<xml::sax::XAttributeList>(new comphelper::AttributeList())); + m_xDocumentHandler->characters(it.X509Certificate); + m_xDocumentHandler->endElement("X509Certificate"); + } + m_xDocumentHandler->endElement("X509Data"); + } + m_xDocumentHandler->endElement("KeyInfo"); +} + +void OOXMLSecExporter::Impl::writePackageObject() +{ + rtl::Reference<comphelper::AttributeList> pAttributeList(new comphelper::AttributeList()); + pAttributeList->AddAttribute("Id", "idPackageObject_" + m_rInformation.ouSignatureId); + m_xDocumentHandler->startElement("Object", + uno::Reference<xml::sax::XAttributeList>(pAttributeList)); + + writeManifest(); + writePackageObjectSignatureProperties(); + + m_xDocumentHandler->endElement("Object"); +} + +void OOXMLSecExporter::Impl::writeManifest() +{ + m_xDocumentHandler->startElement( + "Manifest", uno::Reference<xml::sax::XAttributeList>(new comphelper::AttributeList())); + const SignatureReferenceInformations& rReferences = m_rInformation.vSignatureReferenceInfors; + for (const SignatureReferenceInformation& rReference : rReferences) + { + if (rReference.nType != SignatureReferenceType::SAMEDOCUMENT) + { + if (OOXMLSecExporter::Impl::isOOXMLDenylist(rReference.ouURI)) + continue; + + writeManifestReference(rReference); + } + } + m_xDocumentHandler->endElement("Manifest"); +} + +void OOXMLSecExporter::Impl::writeRelationshipTransform(const OUString& rURI) +{ + uno::Reference<embed::XHierarchicalStorageAccess> xHierarchicalStorageAccess(m_xRootStorage, + uno::UNO_QUERY); + uno::Reference<io::XInputStream> xRelStream( + xHierarchicalStorageAccess->openStreamElementByHierarchicalName(rURI, + embed::ElementModes::READ), + uno::UNO_QUERY); + { + rtl::Reference<comphelper::AttributeList> pAttributeList(new comphelper::AttributeList()); + pAttributeList->AddAttribute("Algorithm", ALGO_RELATIONSHIP); + m_xDocumentHandler->startElement("Transform", + uno::Reference<xml::sax::XAttributeList>(pAttributeList)); + } + + const uno::Sequence<uno::Sequence<beans::StringPair>> aRelationsInfo + = comphelper::OFOPXMLHelper::ReadRelationsInfoSequence(xRelStream, rURI, + m_xComponentContext); + for (const uno::Sequence<beans::StringPair>& rPairs : aRelationsInfo) + { + OUString aId; + OUString aType; + for (const beans::StringPair& rPair : rPairs) + { + if (rPair.First == "Id") + aId = rPair.Second; + else if (rPair.First == "Type") + aType = rPair.Second; + } + + if (OOXMLSecExporter::Impl::isOOXMLRelationDenylist(aType)) + continue; + + rtl::Reference<comphelper::AttributeList> pAttributeList(new comphelper::AttributeList()); + pAttributeList->AddAttribute("xmlns:mdssi", NS_MDSSI); + pAttributeList->AddAttribute("SourceId", aId); + m_xDocumentHandler->startElement("mdssi:RelationshipReference", + uno::Reference<xml::sax::XAttributeList>(pAttributeList)); + m_xDocumentHandler->endElement("mdssi:RelationshipReference"); + } + + m_xDocumentHandler->endElement("Transform"); +} + +void OOXMLSecExporter::Impl::writePackageObjectSignatureProperties() +{ + m_xDocumentHandler->startElement( + "SignatureProperties", + uno::Reference<xml::sax::XAttributeList>(new comphelper::AttributeList())); + { + rtl::Reference<comphelper::AttributeList> pAttributeList(new comphelper::AttributeList()); + pAttributeList->AddAttribute("Id", "idSignatureTime_" + m_rInformation.ouSignatureId); + pAttributeList->AddAttribute("Target", "#" + m_rInformation.ouSignatureId); + m_xDocumentHandler->startElement("SignatureProperty", + uno::Reference<xml::sax::XAttributeList>(pAttributeList)); + } + { + rtl::Reference<comphelper::AttributeList> pAttributeList(new comphelper::AttributeList()); + pAttributeList->AddAttribute("xmlns:mdssi", NS_MDSSI); + m_xDocumentHandler->startElement("mdssi:SignatureTime", + uno::Reference<xml::sax::XAttributeList>(pAttributeList)); + } + m_xDocumentHandler->startElement( + "mdssi:Format", uno::Reference<xml::sax::XAttributeList>(new comphelper::AttributeList())); + m_xDocumentHandler->characters("YYYY-MM-DDThh:mm:ssTZD"); + m_xDocumentHandler->endElement("mdssi:Format"); + + m_xDocumentHandler->startElement( + "mdssi:Value", uno::Reference<xml::sax::XAttributeList>(new comphelper::AttributeList())); + if (!m_rInformation.ouDateTime.isEmpty()) + m_aSignatureTimeValue = m_rInformation.ouDateTime; + else + { + m_aSignatureTimeValue = utl::toISO8601(m_rInformation.stDateTime); + // Ignore sub-seconds. + sal_Int32 nCommaPos = m_aSignatureTimeValue.indexOf(','); + if (nCommaPos != -1) + { + m_aSignatureTimeValue + = OUString::Concat(m_aSignatureTimeValue.subView(0, nCommaPos)) + "Z"; + } + } + m_xDocumentHandler->characters(m_aSignatureTimeValue); + m_xDocumentHandler->endElement("mdssi:Value"); + + m_xDocumentHandler->endElement("mdssi:SignatureTime"); + m_xDocumentHandler->endElement("SignatureProperty"); + m_xDocumentHandler->endElement("SignatureProperties"); +} + +void OOXMLSecExporter::Impl::writeManifestReference(const SignatureReferenceInformation& rReference) +{ + rtl::Reference<comphelper::AttributeList> pAttributeList(new comphelper::AttributeList()); + pAttributeList->AddAttribute("URI", rReference.ouURI); + m_xDocumentHandler->startElement("Reference", + uno::Reference<xml::sax::XAttributeList>(pAttributeList)); + + // Transforms + if (rReference.ouURI.endsWith( + "?ContentType=application/vnd.openxmlformats-package.relationships+xml")) + { + OUString aURI = rReference.ouURI; + // Ignore leading slash. + if (aURI.startsWith("/")) + aURI = aURI.copy(1); + // Ignore query part of the URI. + sal_Int32 nQueryPos = aURI.indexOf('?'); + if (nQueryPos != -1) + aURI = aURI.copy(0, nQueryPos); + + m_xDocumentHandler->startElement("Transforms", uno::Reference<xml::sax::XAttributeList>( + new comphelper::AttributeList())); + + writeRelationshipTransform(aURI); + writeCanonicalizationTransform(); + + m_xDocumentHandler->endElement("Transforms"); + } + + DocumentSignatureHelper::writeDigestMethod(m_xDocumentHandler); + m_xDocumentHandler->startElement( + "DigestValue", uno::Reference<xml::sax::XAttributeList>(new comphelper::AttributeList())); + m_xDocumentHandler->characters(rReference.ouDigestValue); + m_xDocumentHandler->endElement("DigestValue"); + m_xDocumentHandler->endElement("Reference"); +} + +void OOXMLSecExporter::Impl::writeOfficeObject() +{ + { + rtl::Reference<comphelper::AttributeList> pAttributeList(new comphelper::AttributeList()); + pAttributeList->AddAttribute("Id", "idOfficeObject_" + m_rInformation.ouSignatureId); + m_xDocumentHandler->startElement("Object", + uno::Reference<xml::sax::XAttributeList>(pAttributeList)); + } + m_xDocumentHandler->startElement( + "SignatureProperties", + uno::Reference<xml::sax::XAttributeList>(new comphelper::AttributeList())); + { + rtl::Reference<comphelper::AttributeList> pAttributeList(new comphelper::AttributeList()); + pAttributeList->AddAttribute("Id", "idOfficeV1Details_" + m_rInformation.ouSignatureId); + pAttributeList->AddAttribute("Target", "#" + m_rInformation.ouSignatureId); + m_xDocumentHandler->startElement("SignatureProperty", + uno::Reference<xml::sax::XAttributeList>(pAttributeList)); + } + writeSignatureInfo(); + m_xDocumentHandler->endElement("SignatureProperty"); + m_xDocumentHandler->endElement("SignatureProperties"); + m_xDocumentHandler->endElement("Object"); +} + +void OOXMLSecExporter::Impl::writeSignatureInfo() +{ + rtl::Reference<comphelper::AttributeList> pAttributeList(new comphelper::AttributeList()); + pAttributeList->AddAttribute("xmlns", "http://schemas.microsoft.com/office/2006/digsig"); + m_xDocumentHandler->startElement("SignatureInfoV1", + uno::Reference<xml::sax::XAttributeList>(pAttributeList)); + + m_xDocumentHandler->startElement( + "SetupID", uno::Reference<xml::sax::XAttributeList>(new comphelper::AttributeList())); + m_xDocumentHandler->characters(m_rInformation.ouSignatureLineId); + m_xDocumentHandler->endElement("SetupID"); + m_xDocumentHandler->startElement( + "SignatureText", uno::Reference<xml::sax::XAttributeList>(new comphelper::AttributeList())); + m_xDocumentHandler->endElement("SignatureText"); + m_xDocumentHandler->startElement("SignatureImage", uno::Reference<xml::sax::XAttributeList>( + new comphelper::AttributeList())); + m_xDocumentHandler->endElement("SignatureImage"); + m_xDocumentHandler->startElement("SignatureComments", uno::Reference<xml::sax::XAttributeList>( + new comphelper::AttributeList())); + m_xDocumentHandler->characters(m_rInformation.ouDescription); + m_xDocumentHandler->endElement("SignatureComments"); + // Just hardcode something valid according to [MS-OFFCRYPTO]. + m_xDocumentHandler->startElement("WindowsVersion", uno::Reference<xml::sax::XAttributeList>( + new comphelper::AttributeList())); + m_xDocumentHandler->characters("6.1"); + m_xDocumentHandler->endElement("WindowsVersion"); + m_xDocumentHandler->startElement( + "OfficeVersion", uno::Reference<xml::sax::XAttributeList>(new comphelper::AttributeList())); + m_xDocumentHandler->characters("16.0"); + m_xDocumentHandler->endElement("OfficeVersion"); + m_xDocumentHandler->startElement("ApplicationVersion", uno::Reference<xml::sax::XAttributeList>( + new comphelper::AttributeList())); + m_xDocumentHandler->characters("16.0"); + m_xDocumentHandler->endElement("ApplicationVersion"); + m_xDocumentHandler->startElement( + "Monitors", uno::Reference<xml::sax::XAttributeList>(new comphelper::AttributeList())); + m_xDocumentHandler->characters("1"); + m_xDocumentHandler->endElement("Monitors"); + m_xDocumentHandler->startElement( + "HorizontalResolution", + uno::Reference<xml::sax::XAttributeList>(new comphelper::AttributeList())); + m_xDocumentHandler->characters("1280"); + m_xDocumentHandler->endElement("HorizontalResolution"); + m_xDocumentHandler->startElement("VerticalResolution", uno::Reference<xml::sax::XAttributeList>( + new comphelper::AttributeList())); + m_xDocumentHandler->characters("800"); + m_xDocumentHandler->endElement("VerticalResolution"); + m_xDocumentHandler->startElement( + "ColorDepth", uno::Reference<xml::sax::XAttributeList>(new comphelper::AttributeList())); + m_xDocumentHandler->characters("32"); + m_xDocumentHandler->endElement("ColorDepth"); + m_xDocumentHandler->startElement( + "SignatureProviderId", + uno::Reference<xml::sax::XAttributeList>(new comphelper::AttributeList())); + m_xDocumentHandler->characters("{00000000-0000-0000-0000-000000000000}"); + m_xDocumentHandler->endElement("SignatureProviderId"); + m_xDocumentHandler->startElement( + "SignatureProviderUrl", + uno::Reference<xml::sax::XAttributeList>(new comphelper::AttributeList())); + m_xDocumentHandler->endElement("SignatureProviderUrl"); + m_xDocumentHandler->startElement( + "SignatureProviderDetails", + uno::Reference<xml::sax::XAttributeList>(new comphelper::AttributeList())); + m_xDocumentHandler->characters( + "9"); // This is what MSO 2016 writes, though [MS-OFFCRYPTO] doesn't document what the value means. + m_xDocumentHandler->endElement("SignatureProviderDetails"); + m_xDocumentHandler->startElement( + "SignatureType", uno::Reference<xml::sax::XAttributeList>(new comphelper::AttributeList())); + m_xDocumentHandler->characters("2"); + m_xDocumentHandler->endElement("SignatureType"); + + m_xDocumentHandler->endElement("SignatureInfoV1"); +} + +void OOXMLSecExporter::Impl::writePackageSignature() +{ + m_xDocumentHandler->startElement( + "Object", uno::Reference<xml::sax::XAttributeList>(new comphelper::AttributeList())); + { + rtl::Reference<comphelper::AttributeList> pAttributeList(new comphelper::AttributeList()); + pAttributeList->AddAttribute("xmlns:xd", NS_XD); + pAttributeList->AddAttribute("Target", "#" + m_rInformation.ouSignatureId); + m_xDocumentHandler->startElement("xd:QualifyingProperties", + uno::Reference<xml::sax::XAttributeList>(pAttributeList)); + } + + DocumentSignatureHelper::writeSignedProperties(m_xDocumentHandler, m_rInformation, + m_aSignatureTimeValue, false); + + m_xDocumentHandler->endElement("xd:QualifyingProperties"); + m_xDocumentHandler->endElement("Object"); +} + +void OOXMLSecExporter::Impl::writeSignatureLineImages() +{ + if (m_rInformation.aValidSignatureImage.is()) + { + rtl::Reference<comphelper::AttributeList> pAttributeList(new comphelper::AttributeList()); + pAttributeList->AddAttribute("Id", "idValidSigLnImg"); + m_xDocumentHandler->startElement("Object", + uno::Reference<xml::sax::XAttributeList>(pAttributeList)); + OUString aGraphicInBase64; + Graphic aGraphic(m_rInformation.aValidSignatureImage); + if (!XOutBitmap::GraphicToBase64(aGraphic, aGraphicInBase64, false, ConvertDataFormat::EMF)) + SAL_WARN("xmlsecurity.helper", "could not convert graphic to base64"); + m_xDocumentHandler->characters(aGraphicInBase64); + m_xDocumentHandler->endElement("Object"); + } + if (!m_rInformation.aInvalidSignatureImage.is()) + return; + + rtl::Reference<comphelper::AttributeList> pAttributeList(new comphelper::AttributeList()); + pAttributeList->AddAttribute("Id", "idInvalidSigLnImg"); + m_xDocumentHandler->startElement("Object", + uno::Reference<xml::sax::XAttributeList>(pAttributeList)); + OUString aGraphicInBase64; + Graphic aGraphic(m_rInformation.aInvalidSignatureImage); + if (!XOutBitmap::GraphicToBase64(aGraphic, aGraphicInBase64, false, ConvertDataFormat::EMF)) + SAL_WARN("xmlsecurity.helper", "could not convert graphic to base64"); + m_xDocumentHandler->characters(aGraphicInBase64); + m_xDocumentHandler->endElement("Object"); +} + +void OOXMLSecExporter::Impl::writeSignature() +{ + rtl::Reference<comphelper::AttributeList> pAttributeList(new comphelper::AttributeList()); + pAttributeList->AddAttribute("xmlns", NS_XMLDSIG); + pAttributeList->AddAttribute("Id", m_rInformation.ouSignatureId); + getDocumentHandler()->startElement("Signature", + uno::Reference<xml::sax::XAttributeList>(pAttributeList)); + + writeSignedInfo(); + writeSignatureValue(); + writeKeyInfo(); + writePackageObject(); + writeOfficeObject(); + writePackageSignature(); + writeSignatureLineImages(); + + getDocumentHandler()->endElement("Signature"); +} + +OOXMLSecExporter::OOXMLSecExporter( + const uno::Reference<uno::XComponentContext>& xComponentContext, + const uno::Reference<embed::XStorage>& xRootStorage, + const uno::Reference<xml::sax::XDocumentHandler>& xDocumentHandler, + const SignatureInformation& rInformation) + : m_pImpl( + std::make_unique<Impl>(xComponentContext, xRootStorage, xDocumentHandler, rInformation)) +{ +} + +OOXMLSecExporter::~OOXMLSecExporter() = default; + +void OOXMLSecExporter::writeSignature() { m_pImpl->writeSignature(); } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/helper/ooxmlsecexporter.hxx b/xmlsecurity/source/helper/ooxmlsecexporter.hxx new file mode 100644 index 0000000000..77ea7c4849 --- /dev/null +++ b/xmlsecurity/source/helper/ooxmlsecexporter.hxx @@ -0,0 +1,47 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include <memory> + +#include <svl/sigstruct.hxx> + +namespace com::sun::star +{ +namespace embed +{ +class XStorage; +} +namespace uno +{ +class XComponentContext; +} +namespace xml::sax +{ +class XDocumentHandler; +} +} + +/// Writes a single OOXML digital signature. +class OOXMLSecExporter +{ + struct Impl; + std::unique_ptr<Impl> m_pImpl; + +public: + OOXMLSecExporter(const css::uno::Reference<css::uno::XComponentContext>& xComponentContext, + const css::uno::Reference<css::embed::XStorage>& xRootStorage, + const css::uno::Reference<css::xml::sax::XDocumentHandler>& xDocumentHandler, + const SignatureInformation& rInformation); + ~OOXMLSecExporter(); + void writeSignature(); +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/helper/ooxmlsecparser.cxx b/xmlsecurity/source/helper/ooxmlsecparser.cxx new file mode 100644 index 0000000000..2692190ccb --- /dev/null +++ b/xmlsecurity/source/helper/ooxmlsecparser.cxx @@ -0,0 +1,1352 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + + +#include "ooxmlsecparser.hxx" +#include <xmlsignaturehelper.hxx> +#include <xsecctl.hxx> + +#include <xmloff/xmlnamespace.hxx> +#include <xmloff/xmltkmap.hxx> +#include <xmloff/xmlimp.hxx> + +#include <com/sun/star/xml/sax/SAXException.hpp> + +#include <sal/log.hxx> + +using namespace com::sun::star; + +class OOXMLSecParser::Context +{ + protected: + friend class OOXMLSecParser; + OOXMLSecParser & m_rParser; + private: + std::optional<SvXMLNamespaceMap> m_pOldNamespaceMap; + + public: + Context(OOXMLSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap) + : m_rParser(rParser) + , m_pOldNamespaceMap(std::move(pOldNamespaceMap)) + { + } + + virtual ~Context() = default; + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& /*xAttrs*/) + { + } + + virtual void EndElement() + { + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + sal_uInt16 const /*nNamespace*/, OUString const& /*rName*/); + + virtual void Characters(OUString const& /*rChars*/) + { + } +}; + +// it's possible that an unsupported element has an Id attribute and a +// ds:Reference digesting it - probably this means XSecController needs to know +// about it. (For known elements, the Id attribute is only processed according +// to the schema.) +class OOXMLSecParser::UnknownContext + : public OOXMLSecParser::Context +{ + public: + UnknownContext(OOXMLSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + m_rParser.HandleIdAttr(xAttrs); + } +}; + +auto OOXMLSecParser::Context::CreateChildContext( + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + sal_uInt16 const /*nNamespace*/, OUString const& /*rName*/) +-> std::unique_ptr<Context> +{ + // default: create new base context + return std::make_unique<UnknownContext>(m_rParser, std::move(pOldNamespaceMap)); +} + +/** +note: anything in ds:Object should be trusted *only* if there is a ds:Reference + to it so it is signed (exception: the xades:EncapsulatedX509Certificate). + ds:SignedInfo precedes all ds:Object. + + There may be multiple ds:Signature for purpose of counter-signatures + but the way XAdES describes these, only the ds:SignatureValue element + would be referenced, so requiring a ds:Reference for anything in + ds:Object shouldn't cause issues. + */ +class OOXMLSecParser::ReferencedContextImpl + : public OOXMLSecParser::Context +{ + protected: + bool m_isReferenced; + + public: + ReferencedContextImpl(OOXMLSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + bool const isReferenced) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_isReferenced(isReferenced) + { + } + + OUString CheckIdAttrReferenced(css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) + { + OUString const id(m_rParser.HandleIdAttr(xAttrs)); + if (!id.isEmpty() && m_rParser.m_pXSecController->haveReferenceForId(id)) + { + m_isReferenced = true; + } + return id; + } +}; + +class OOXMLSecParser::DsX509CertificateContext + : public OOXMLSecParser::Context +{ + private: + OUString & m_rValue; + + public: + DsX509CertificateContext(OOXMLSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + OUString& rValue) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rValue(rValue) + { + } + + virtual void Characters(OUString const& rChars) override + { + m_rValue += rChars; + } +}; + +class OOXMLSecParser::DsX509SerialNumberContext + : public OOXMLSecParser::Context +{ + private: + OUString & m_rValue; + + public: + DsX509SerialNumberContext(OOXMLSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + OUString& rValue) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rValue(rValue) + { + } + + virtual void Characters(OUString const& rChars) override + { + m_rValue += rChars; + } +}; + +class OOXMLSecParser::DsX509IssuerNameContext + : public OOXMLSecParser::Context +{ + private: + OUString & m_rValue; + + public: + DsX509IssuerNameContext(OOXMLSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + OUString& rValue) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rValue(rValue) + { + } + + virtual void Characters(OUString const& rChars) override + { + m_rValue += rChars; + } +}; + +class OOXMLSecParser::DsX509IssuerSerialContext + : public OOXMLSecParser::Context +{ + private: + OUString & m_rX509IssuerName; + OUString & m_rX509SerialNumber; + + public: + DsX509IssuerSerialContext(OOXMLSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + OUString& rIssuerName, OUString& rSerialNumber) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rX509IssuerName(rIssuerName) + , m_rX509SerialNumber(rSerialNumber) + { + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "X509IssuerName") + { + return std::make_unique<DsX509IssuerNameContext>(m_rParser, std::move(pOldNamespaceMap), m_rX509IssuerName); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "X509SerialNumber") + { + return std::make_unique<DsX509SerialNumberContext>(m_rParser, std::move(pOldNamespaceMap), m_rX509SerialNumber); + } + // missing: ds:X509SKI, ds:X509SubjectName, ds:X509CRL + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +/// can't be sure what is supposed to happen here because the spec is clear as mud +class OOXMLSecParser::DsX509DataContext + : public OOXMLSecParser::Context +{ + private: + // sigh... "No ordering is implied by the above constraints." + // so store the ball of mud in vectors and try to figure it out later. + std::vector<std::pair<OUString, OUString>> m_X509IssuerSerials; + std::vector<OUString> m_X509Certificates; + + public: + DsX509DataContext(OOXMLSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void EndElement() override + { + m_rParser.m_pXSecController->setX509Data(m_X509IssuerSerials, m_X509Certificates); + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "X509IssuerSerial") + { + m_X509IssuerSerials.emplace_back(); + return std::make_unique<DsX509IssuerSerialContext>(m_rParser, std::move(pOldNamespaceMap), m_X509IssuerSerials.back().first, m_X509IssuerSerials.back().second); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "X509Certificate") + { + m_X509Certificates.emplace_back(); + return std::make_unique<DsX509CertificateContext>(m_rParser, std::move(pOldNamespaceMap), m_X509Certificates.back()); + } + // missing: ds:X509SKI, ds:X509SubjectName, ds:X509CRL + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class OOXMLSecParser::DsKeyInfoContext + : public OOXMLSecParser::Context +{ + public: + DsKeyInfoContext(OOXMLSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + m_rParser.HandleIdAttr(xAttrs); + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "X509Data") + { + return std::make_unique<DsX509DataContext>(m_rParser, std::move(pOldNamespaceMap)); + } + // missing: ds:PGPData + // missing: ds:KeyName, ds:KeyValue, ds:RetrievalMethod, ds:SPKIData, ds:MgmtData + // (old code would read ds:Transform inside ds:RetrievalMethod but + // presumably that was a bug) + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } + +}; + +class OOXMLSecParser::DsSignatureValueContext + : public OOXMLSecParser::Context +{ + private: + OUString m_Value; + + public: + DsSignatureValueContext(OOXMLSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + m_rParser.HandleIdAttr(xAttrs); + } + + virtual void EndElement() override + { + m_rParser.m_pXSecController->setSignatureValue(m_Value); + } + + virtual void Characters(OUString const& rChars) override + { + m_Value += rChars; + } +}; + +class OOXMLSecParser::DsDigestValueContext + : public OOXMLSecParser::Context +{ + private: + OUString & m_rValue; + + public: + DsDigestValueContext(OOXMLSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + OUString & rValue) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rValue(rValue) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& /*xAttrs*/) override + { + m_rValue.clear(); + } + + virtual void Characters(OUString const& rChars) override + { + m_rValue += rChars; + } +}; + +class OOXMLSecParser::DsDigestMethodContext + : public OOXMLSecParser::Context +{ + private: + sal_Int32 & m_rReferenceDigestID; + + public: + DsDigestMethodContext(OOXMLSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + sal_Int32& rReferenceDigestID) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rReferenceDigestID(rReferenceDigestID) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + OUString ouAlgorithm = xAttrs->getValueByName("Algorithm"); + + SAL_WARN_IF( ouAlgorithm.isEmpty(), "xmlsecurity.helper", "no Algorithm in Reference" ); + if (ouAlgorithm.isEmpty()) + return; + + SAL_WARN_IF( ouAlgorithm != ALGO_XMLDSIGSHA1 + && ouAlgorithm != ALGO_XMLDSIGSHA256 + && ouAlgorithm != ALGO_XMLDSIGSHA512, + "xmlsecurity.helper", "Algorithm neither SHA1, SHA256 nor SHA512"); + if (ouAlgorithm == ALGO_XMLDSIGSHA1) + m_rReferenceDigestID = css::xml::crypto::DigestID::SHA1; + else if (ouAlgorithm == ALGO_XMLDSIGSHA256) + m_rReferenceDigestID = css::xml::crypto::DigestID::SHA256; + else if (ouAlgorithm == ALGO_XMLDSIGSHA512) + m_rReferenceDigestID = css::xml::crypto::DigestID::SHA512; + else + m_rReferenceDigestID = 0; + } +}; + +class OOXMLSecParser::DsTransformContext + : public OOXMLSecParser::Context +{ + private: + bool & m_rIsC14N; + + public: + DsTransformContext(OOXMLSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + bool& rIsC14N) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rIsC14N(rIsC14N) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + OUString aAlgorithm = xAttrs->getValueByName("Algorithm"); + + if (aAlgorithm == ALGO_RELATIONSHIP) + { + m_rIsC14N = true; + } + } +}; + +class OOXMLSecParser::DsTransformsContext + : public OOXMLSecParser::Context +{ + private: + bool & m_rIsC14N; + + public: + DsTransformsContext(OOXMLSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + bool& rIsC14N) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rIsC14N(rIsC14N) + { + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "Transform") + { + return std::make_unique<DsTransformContext>(m_rParser, std::move(pOldNamespaceMap), m_rIsC14N); + } + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class OOXMLSecParser::DsReferenceContext + : public OOXMLSecParser::Context +{ + private: + OUString m_URI; + OUString m_Type; + OUString m_DigestValue; + bool m_IsC14N = false; + // Relevant for ODF. The digest algorithm selected by the DigestMethod + // element's Algorithm attribute. @see css::xml::crypto::DigestID. + sal_Int32 m_nReferenceDigestID = css::xml::crypto::DigestID::SHA256; + + public: + DsReferenceContext(OOXMLSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + m_rParser.HandleIdAttr(xAttrs); + + m_URI = xAttrs->getValueByName("URI"); + SAL_WARN_IF(m_URI.isEmpty(), "xmlsecurity.helper", "URI is empty"); + // Remember the type of this reference. + m_Type = xAttrs->getValueByName("Type"); + } + + virtual void EndElement() override + { + if (m_URI.startsWith("#")) + { + /* + * remove the first character '#' from the attribute value + */ + m_rParser.m_pXSecController->addReference(m_URI.copy(1), m_nReferenceDigestID, m_Type); + } + else + { + if (m_IsC14N) // this is determined by nested ds:Transform + { + m_rParser.m_pXSecController->addStreamReference(m_URI, false, m_nReferenceDigestID); + } + else + /* + * it must be an octet stream + */ + { + m_rParser.m_pXSecController->addStreamReference(m_URI, true, m_nReferenceDigestID); + } + } + + m_rParser.m_pXSecController->setDigestValue(m_nReferenceDigestID, m_DigestValue); + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "Transforms") + { + return std::make_unique<DsTransformsContext>(m_rParser, std::move(pOldNamespaceMap), m_IsC14N); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "DigestMethod") + { + return std::make_unique<DsDigestMethodContext>(m_rParser, std::move(pOldNamespaceMap), m_nReferenceDigestID); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "DigestValue") + { + return std::make_unique<DsDigestValueContext>(m_rParser, std::move(pOldNamespaceMap), m_DigestValue); + } + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class OOXMLSecParser::DsSignatureMethodContext + : public OOXMLSecParser::Context +{ + public: + DsSignatureMethodContext(OOXMLSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + OUString ouAlgorithm = xAttrs->getValueByName("Algorithm"); + if (ouAlgorithm == ALGO_ECDSASHA1 || ouAlgorithm == ALGO_ECDSASHA256 + || ouAlgorithm == ALGO_ECDSASHA512) + { + m_rParser.m_pXSecController->setSignatureMethod(svl::crypto::SignatureMethodAlgorithm::ECDSA); + } + } +}; + +class OOXMLSecParser::DsSignedInfoContext + : public OOXMLSecParser::Context +{ + public: + DsSignedInfoContext(OOXMLSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + m_rParser.HandleIdAttr(xAttrs); + } + + virtual void EndElement() override + { + m_rParser.m_pXSecController->setReferenceCount(); + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "SignatureMethod") + { + return std::make_unique<DsSignatureMethodContext>(m_rParser, std::move(pOldNamespaceMap)); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "Reference") + { + return std::make_unique<DsReferenceContext>(m_rParser, std::move(pOldNamespaceMap)); + } + // missing: ds:CanonicalizationMethod + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class OOXMLSecParser::XadesCertDigestContext + : public OOXMLSecParser::Context +{ + private: + OUString & m_rDigestValue; + sal_Int32 & m_rReferenceDigestID; + + public: + XadesCertDigestContext(OOXMLSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + OUString& rDigestValue, sal_Int32& rReferenceDigestID) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rDigestValue(rDigestValue) + , m_rReferenceDigestID(rReferenceDigestID) + { + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "DigestMethod") + { + return std::make_unique<DsDigestMethodContext>(m_rParser, std::move(pOldNamespaceMap), m_rReferenceDigestID); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "DigestValue") + { + return std::make_unique<DsDigestValueContext>(m_rParser, std::move(pOldNamespaceMap), m_rDigestValue); + } + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class OOXMLSecParser::XadesCertContext + : public OOXMLSecParser::ReferencedContextImpl +{ + private: + sal_Int32 m_nReferenceDigestID = css::xml::crypto::DigestID::SHA1; + OUString m_CertDigest; + OUString m_X509IssuerName; + OUString m_X509SerialNumber; + + public: + XadesCertContext(OOXMLSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void EndElement() override + { + if (m_isReferenced) + { + m_rParser.m_pXSecController->setX509CertDigest(m_CertDigest, m_nReferenceDigestID, m_X509IssuerName, m_X509SerialNumber); + } + else + { + SAL_INFO("xmlsecurity.helper", "ignoring unsigned xades:Cert"); + } + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "CertDigest") + { + return std::make_unique<XadesCertDigestContext>(m_rParser, std::move(pOldNamespaceMap), m_CertDigest, m_nReferenceDigestID); + } + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "IssuerSerial") + { + return std::make_unique<DsX509IssuerSerialContext>(m_rParser, std::move(pOldNamespaceMap), m_X509IssuerName, m_X509SerialNumber); + } + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class OOXMLSecParser::XadesSigningCertificateContext + : public OOXMLSecParser::ReferencedContextImpl +{ + public: + XadesSigningCertificateContext(OOXMLSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "Cert") + { + return std::make_unique<XadesCertContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class OOXMLSecParser::XadesSigningTimeContext + : public OOXMLSecParser::ReferencedContextImpl +{ + private: + OUString m_Value; + + public: + XadesSigningTimeContext(OOXMLSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void EndElement() override + { + if (m_isReferenced) + { + m_rParser.m_pXSecController->setDate("", m_Value); + } + else + { + SAL_INFO("xmlsecurity.helper", "ignoring unsigned SigningTime"); + } + } + + virtual void Characters(OUString const& rChars) override + { + m_Value += rChars; + } +}; + +class OOXMLSecParser::XadesSignedSignaturePropertiesContext + : public OOXMLSecParser::ReferencedContextImpl +{ + public: + XadesSignedSignaturePropertiesContext(OOXMLSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + CheckIdAttrReferenced(xAttrs); + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SigningTime") + { + return std::make_unique<XadesSigningTimeContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SigningCertificate") + { + return std::make_unique<XadesSigningCertificateContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + // missing: xades:SignaturePolicyIdentifier, xades:SignatureProductionPlace, xades:SignerRole + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class OOXMLSecParser::XadesSignedPropertiesContext + : public OOXMLSecParser::ReferencedContextImpl +{ + public: + XadesSignedPropertiesContext(OOXMLSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + CheckIdAttrReferenced(xAttrs); + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SignedSignatureProperties") + { + return std::make_unique<XadesSignedSignaturePropertiesContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + // missing: xades:SignedDataObjectProperties + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class OOXMLSecParser::XadesQualifyingPropertiesContext + : public OOXMLSecParser::ReferencedContextImpl +{ + public: + XadesQualifyingPropertiesContext(OOXMLSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + CheckIdAttrReferenced(xAttrs); + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SignedProperties") + { + return std::make_unique<XadesSignedPropertiesContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + // missing: xades:UnsignedSignatureProperties + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class OOXMLSecParser::MsodigsigSetupIDContext + : public OOXMLSecParser::Context +{ + private: + OUString & m_rValue; + + public: + MsodigsigSetupIDContext(OOXMLSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + OUString& rValue) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rValue(rValue) + { + } + + virtual void Characters(OUString const& rChars) override + { + m_rValue += rChars; + } +}; + +class OOXMLSecParser::MsodigsigSignatureCommentsContext + : public OOXMLSecParser::Context +{ + private: + OUString & m_rValue; + + public: + MsodigsigSignatureCommentsContext(OOXMLSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + OUString& rValue) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rValue(rValue) + { + } + + virtual void Characters(OUString const& rChars) override + { + m_rValue += rChars; + } +}; + +class OOXMLSecParser::MsodigsigSignatureInfoV1Context + : public OOXMLSecParser::ReferencedContextImpl +{ + private: + OUString m_SetupID; + OUString m_SignatureComments; + + public: + MsodigsigSignatureInfoV1Context(OOXMLSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + CheckIdAttrReferenced(xAttrs); + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_MSODIGSIG && rName == "SetupID") + { + return std::make_unique<MsodigsigSetupIDContext>(m_rParser, std::move(pOldNamespaceMap), m_SetupID); + } + if (nNamespace == XML_NAMESPACE_MSODIGSIG && rName == "SignatureComments") + { + return std::make_unique<MsodigsigSignatureCommentsContext>(m_rParser, std::move(pOldNamespaceMap), m_SignatureComments); + } + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } + + virtual void EndElement() override + { + if (m_isReferenced) + { + if (!m_SetupID.isEmpty()) + { + m_rParser.m_pXSecController->setSignatureLineId(m_SetupID); + } + if (!m_SignatureComments.isEmpty()) + { + m_rParser.m_pXSecController->setDescription("", m_SignatureComments); + + } + } + else + { + SAL_INFO("xmlsecurity.helper", "ignoring unsigned SignatureInfoV1"); + } + } +}; + +class OOXMLSecParser::MdssiValueContext + : public OOXMLSecParser::Context +{ + private: + OUString & m_rValue; + + public: + MdssiValueContext(OOXMLSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + OUString& rValue) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rValue(rValue) + { + } + + virtual void Characters(OUString const& rChars) override + { + m_rValue += rChars; + } +}; + +class OOXMLSecParser::MdssiSignatureTimeContext + : public OOXMLSecParser::Context +{ + private: + OUString & m_rValue; + + public: + MdssiSignatureTimeContext(OOXMLSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + OUString& rValue) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rValue(rValue) + { + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_MDSSI && rName == "Value") + { + return std::make_unique<MdssiValueContext>(m_rParser, std::move(pOldNamespaceMap), m_rValue); + } + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + + +class OOXMLSecParser::DsSignaturePropertyContext + : public OOXMLSecParser::ReferencedContextImpl +{ + private: + enum class SignatureProperty { Unknown, Date, Info }; + SignatureProperty m_Property = SignatureProperty::Unknown; + OUString m_Id; + OUString m_Value; + + public: + DsSignaturePropertyContext(OOXMLSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + m_Id = CheckIdAttrReferenced(xAttrs); + } + + virtual void EndElement() override + { + if (m_isReferenced) + { + switch (m_Property) + { + case SignatureProperty::Unknown: + SAL_INFO("xmlsecurity.helper", "Unknown property in ds:Object ignored"); + break; + case SignatureProperty::Info: + break; // handled by child context + case SignatureProperty::Date: + m_rParser.m_pXSecController->setDate(m_Id, m_Value); + break; + } + } + else + { + SAL_INFO("xmlsecurity.helper", "ignoring unsigned SignatureProperty"); + } + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_MDSSI && rName == "SignatureTime") + { + m_Property = SignatureProperty::Date; + return std::make_unique<MdssiSignatureTimeContext>(m_rParser, std::move(pOldNamespaceMap), m_Value); + } + if (nNamespace == XML_NAMESPACE_MSODIGSIG && rName == "SignatureInfoV1") + { + return std::make_unique<MsodigsigSignatureInfoV1Context>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class OOXMLSecParser::DsSignaturePropertiesContext + : public OOXMLSecParser::ReferencedContextImpl +{ + public: + DsSignaturePropertiesContext(OOXMLSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + CheckIdAttrReferenced(xAttrs); + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "SignatureProperty") + { + return std::make_unique<DsSignaturePropertyContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class OOXMLSecParser::DsManifestContext + : public OOXMLSecParser::ReferencedContextImpl +{ + public: + DsManifestContext(OOXMLSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + CheckIdAttrReferenced(xAttrs); + } + +#if 0 + ??? + virtual void EndElement() override + { + m_rParser.m_pXSecController->setReferenceCount(); + } +#endif + + virtual std::unique_ptr<Context> CreateChildContext( + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "Reference") + { + return std::make_unique<DsReferenceContext>(m_rParser, std::move(pOldNamespaceMap)); + } + // missing: ds:CanonicalizationMethod + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class OOXMLSecParser::DsObjectContext + : public OOXMLSecParser::ReferencedContextImpl +{ + enum class Mode { Default, ValidSignatureLineImage, InvalidSignatureLineImage }; + Mode m_Mode = Mode::Default; + OUString m_Value; + + public: + DsObjectContext(OOXMLSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap) + // init with "false" here - the Signature element can't be referenced by its child + : OOXMLSecParser::ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), false) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + OUString const id(CheckIdAttrReferenced(xAttrs)); + if (id == "idValidSigLnImg") + { + m_Mode = Mode::ValidSignatureLineImage; + } + else if (id == "idInvalidSigLnImg") + { + m_Mode = Mode::InvalidSignatureLineImage; + } + } + + virtual void EndElement() override + { + switch (m_Mode) + { + case Mode::ValidSignatureLineImage: + if (m_isReferenced) + { + m_rParser.m_pXSecController->setValidSignatureImage(m_Value); + } + else + { + SAL_INFO("xmlsecurity.helper", "ignoring unsigned SignatureLineValidImage"); + } + break; + case Mode::InvalidSignatureLineImage: + if (m_isReferenced) + { + m_rParser.m_pXSecController->setInvalidSignatureImage(m_Value); + } + else + { + SAL_INFO("xmlsecurity.helper", "ignoring unsigned SignatureLineInvalidImage"); + } + break; + case Mode::Default: + break; + } + } + + virtual void Characters(OUString const& rChars) override + { + m_Value += rChars; + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "SignatureProperties") + { + return std::make_unique<DsSignaturePropertiesContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "QualifyingProperties") + { + return std::make_unique<XadesQualifyingPropertiesContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "Manifest") + { + return std::make_unique<DsManifestContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class OOXMLSecParser::DsSignatureContext + : public OOXMLSecParser::Context +{ + public: + DsSignatureContext(OOXMLSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + OUString const ouIdAttr(m_rParser.HandleIdAttr(xAttrs)); + m_rParser.m_rXMLSignatureHelper.StartVerifySignatureElement(); + m_rParser.m_pXSecController->addSignature(); + if (!ouIdAttr.isEmpty()) + { + m_rParser.m_pXSecController->setId( ouIdAttr ); + } + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "SignedInfo") + { + return std::make_unique<DsSignedInfoContext>(m_rParser, std::move(pOldNamespaceMap)); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "SignatureValue") + { + return std::make_unique<DsSignatureValueContext>(m_rParser, std::move(pOldNamespaceMap)); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "KeyInfo") + { + return std::make_unique<DsKeyInfoContext>(m_rParser, std::move(pOldNamespaceMap)); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "Object") + { + return std::make_unique<DsObjectContext>(m_rParser, std::move(pOldNamespaceMap)); + } + return OOXMLSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + + +OOXMLSecParser::OOXMLSecParser(XMLSignatureHelper& rXMLSignatureHelper, XSecController* pXSecController) + : m_pNamespaceMap(SvXMLNamespaceMap()) + , m_pXSecController(pXSecController) + ,m_rXMLSignatureHelper(rXMLSignatureHelper) +{ + using namespace xmloff::token; + m_pNamespaceMap->Add( GetXMLToken(XML_XML), GetXMLToken(XML_N_XML), XML_NAMESPACE_XML ); + m_pNamespaceMap->Add( "_ds", GetXMLToken(XML_N_DS), XML_NAMESPACE_DS ); + m_pNamespaceMap->Add( "_xades132", GetXMLToken(XML_N_XADES132), XML_NAMESPACE_XADES132); + m_pNamespaceMap->Add( "_xades141", GetXMLToken(XML_N_XADES141), XML_NAMESPACE_XADES141); + m_pNamespaceMap->Add( "_dc", GetXMLToken(XML_N_DC), XML_NAMESPACE_DC ); + m_pNamespaceMap->Add( "_mdssi", NS_MDSSI, XML_NAMESPACE_MDSSI ); + m_pNamespaceMap->Add( "_msodigsig", "http://schemas.microsoft.com/office/2006/digsig", XML_NAMESPACE_MSODIGSIG ); + m_pNamespaceMap->Add( "_office_libo", + GetXMLToken(XML_N_LO_EXT), XML_NAMESPACE_LO_EXT); +} + +OOXMLSecParser::~OOXMLSecParser() +{ +} + +OUString OOXMLSecParser::HandleIdAttr(css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) +{ + OUString const aId = xAttrs->getValueByName("Id"); + if (!aId.isEmpty()) + { + m_pXSecController->collectToVerify(aId); + } + return aId; +} + +void SAL_CALL OOXMLSecParser::startDocument() +{ + if (m_xNextHandler.is()) + m_xNextHandler->startDocument(); +} + +void SAL_CALL OOXMLSecParser::endDocument() +{ + if (m_xNextHandler.is()) + m_xNextHandler->endDocument(); +} + +void SAL_CALL OOXMLSecParser::startElement(const OUString& rName, const uno::Reference<xml::sax::XAttributeList>& xAttribs) +{ + assert(m_pNamespaceMap); + std::optional<SvXMLNamespaceMap> pRewindMap( + SvXMLImport::processNSAttributes(m_pNamespaceMap, nullptr, xAttribs)); + + OUString localName; + sal_uInt16 const nPrefix(m_pNamespaceMap->GetKeyByAttrName(rName, &localName)); + + std::unique_ptr<Context> pContext; + + if (m_ContextStack.empty()) + { + if (nPrefix != XML_NAMESPACE_DS || localName != "Signature") + { + throw css::xml::sax::SAXException( + "xmlsecurity: unexpected root element", nullptr, + css::uno::Any()); + } + + pContext.reset(new DsSignatureContext(*this, std::move(pRewindMap))); + + } + else + { + pContext = m_ContextStack.top()->CreateChildContext( + std::move(pRewindMap), nPrefix, localName); + } + + m_ContextStack.push(std::move(pContext)); + + m_ContextStack.top()->StartElement(xAttribs); + + if (m_xNextHandler.is()) + { + m_xNextHandler->startElement(rName, xAttribs); + } + +} + +void SAL_CALL OOXMLSecParser::endElement(const OUString& rName) +{ + assert(!m_ContextStack.empty()); // this should be checked by sax parser? + + m_ContextStack.top()->EndElement(); + + if (m_xNextHandler.is()) + { + m_xNextHandler->endElement(rName); + } + + if (m_ContextStack.top()->m_pOldNamespaceMap) + { + m_pNamespaceMap = std::move(m_ContextStack.top()->m_pOldNamespaceMap); + } + m_ContextStack.pop(); +} + +void SAL_CALL OOXMLSecParser::characters(const OUString& rChars) +{ + assert(!m_ContextStack.empty()); // this should be checked by sax parser? + m_ContextStack.top()->Characters(rChars); + + if (m_xNextHandler.is()) + m_xNextHandler->characters(rChars); +} + +void SAL_CALL OOXMLSecParser::ignorableWhitespace(const OUString& rWhitespace) +{ + if (m_xNextHandler.is()) + m_xNextHandler->ignorableWhitespace(rWhitespace); +} + +void SAL_CALL OOXMLSecParser::processingInstruction(const OUString& rTarget, const OUString& rData) +{ + if (m_xNextHandler.is()) + m_xNextHandler->processingInstruction(rTarget, rData); +} + +void SAL_CALL OOXMLSecParser::setDocumentLocator(const uno::Reference<xml::sax::XLocator>& xLocator) +{ + if (m_xNextHandler.is()) + m_xNextHandler->setDocumentLocator(xLocator); +} + +void SAL_CALL OOXMLSecParser::initialize(const uno::Sequence<uno::Any>& rArguments) +{ + rArguments[0] >>= m_xNextHandler; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/helper/ooxmlsecparser.hxx b/xmlsecurity/source/helper/ooxmlsecparser.hxx new file mode 100644 index 0000000000..1ac72a46f0 --- /dev/null +++ b/xmlsecurity/source/helper/ooxmlsecparser.hxx @@ -0,0 +1,110 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/xml/sax/XDocumentHandler.hpp> + +#include <cppuhelper/implbase.hxx> + +#include <xmloff/namespacemap.hxx> + +#include <memory> +#include <optional> +#include <stack> + +class XSecController; +class XMLSignatureHelper; + +/// Parses an OOXML digital signature. +class OOXMLSecParser: public cppu::WeakImplHelper + < + css::xml::sax::XDocumentHandler, + css::lang::XInitialization + > +{ +public: + class Context; +private: + class UnknownContext; + class ReferencedContextImpl; + class DsX509CertificateContext; + class DsX509SerialNumberContext; + class DsX509IssuerNameContext; + class DsX509IssuerSerialContext; + class DsX509DataContext; + class DsKeyInfoContext; + class DsSignatureValueContext; + class DsDigestValueContext; + class DsDigestMethodContext; + class DsTransformContext; + class DsTransformsContext; + class DsReferenceContext; + class DsSignatureMethodContext; + class DsSignedInfoContext; + class XadesEncapsulatedX509CertificateContext; + class XadesCertificateValuesContext; + class XadesUnsignedSignaturePropertiesContext; + class XadesUnsignedPropertiesContext; + class XadesCertDigestContext; + class XadesCertContext; + class XadesSigningCertificateContext; + class XadesSigningTimeContext; + class XadesSignedSignaturePropertiesContext; + class XadesSignedPropertiesContext; + class XadesQualifyingPropertiesContext; + class MdssiValueContext; + class MdssiSignatureTimeContext; + class MsodigsigSetupIDContext; + class MsodigsigSignatureCommentsContext; + class MsodigsigSignatureInfoV1Context; + class DsSignaturePropertyContext; + class DsSignaturePropertiesContext; + class DsManifestContext; + class DsObjectContext; + class DsSignatureContext; + class DsigSignaturesContext; + + std::stack<std::unique_ptr<Context>> m_ContextStack; + std::optional<SvXMLNamespaceMap> m_pNamespaceMap; + + XSecController* m_pXSecController; + css::uno::Reference<css::xml::sax::XDocumentHandler> m_xNextHandler; + + XMLSignatureHelper& m_rXMLSignatureHelper; + + OUString HandleIdAttr(css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs); + +public: + explicit OOXMLSecParser(XMLSignatureHelper& rXMLSignatureHelper, XSecController* pXSecController); + virtual ~OOXMLSecParser() override; + + // XDocumentHandler + virtual void SAL_CALL startDocument() override; + + virtual void SAL_CALL endDocument() override; + + virtual void SAL_CALL startElement(const OUString& aName, const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override; + + virtual void SAL_CALL endElement(const OUString& aName) override; + + virtual void SAL_CALL characters(const OUString& aChars) override; + + virtual void SAL_CALL ignorableWhitespace(const OUString& aWhitespaces) override; + + virtual void SAL_CALL processingInstruction(const OUString& aTarget, const OUString& aData) override; + + virtual void SAL_CALL setDocumentLocator(const css::uno::Reference<css::xml::sax::XLocator>& xLocator) override; + + // XInitialization + virtual void SAL_CALL initialize(const css::uno::Sequence<css::uno::Any>& rArguments) override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/helper/pdfsignaturehelper.cxx b/xmlsecurity/source/helper/pdfsignaturehelper.cxx new file mode 100644 index 0000000000..3c0084c8b4 --- /dev/null +++ b/xmlsecurity/source/helper/pdfsignaturehelper.cxx @@ -0,0 +1,626 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <pdfsignaturehelper.hxx> + +#include <memory> + +#include <com/sun/star/io/XTruncate.hpp> +#include <com/sun/star/io/XStream.hpp> +#include <com/sun/star/security/CertificateValidity.hpp> +#include <com/sun/star/uno/SecurityException.hpp> +#include <com/sun/star/security/DocumentSignatureInformation.hpp> +#include <com/sun/star/xml/crypto/XSecurityEnvironment.hpp> +#include <com/sun/star/drawing/XShapes.hpp> +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/frame/XStorable.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/drawing/XDrawView.hpp> + +#include <comphelper/propertysequence.hxx> +#include <sal/log.hxx> +#include <comphelper/diagnose_ex.hxx> +#include <unotools/mediadescriptor.hxx> +#include <unotools/streamwrap.hxx> +#include <unotools/ucbstreamhelper.hxx> +#include <vcl/filter/pdfdocument.hxx> +#include <vcl/checksum.hxx> +#include <svl/cryptosign.hxx> +#include <vcl/filter/PDFiumLibrary.hxx> + +using namespace ::com::sun::star; + +namespace +{ +/// Gets the current page of the current view from xModel and puts it to the 1-based rPage. +bool GetSignatureLinePage(const uno::Reference<frame::XModel>& xModel, sal_Int32& rPage) +{ + uno::Reference<drawing::XDrawView> xController(xModel->getCurrentController(), uno::UNO_QUERY); + if (!xController.is()) + { + return false; + } + + uno::Reference<beans::XPropertySet> xPage(xController->getCurrentPage(), uno::UNO_QUERY); + if (!xPage.is()) + { + return false; + } + + return xPage->getPropertyValue("Number") >>= rPage; +} + +/// If the currently selected shape is a Draw signature line, export that to PDF. +void GetSignatureLineShape(const uno::Reference<frame::XModel>& xModel, sal_Int32& rPage, + std::vector<sal_Int8>& rSignatureLineShape) +{ + if (!xModel.is()) + { + return; + } + + if (!GetSignatureLinePage(xModel, rPage)) + { + return; + } + + uno::Reference<drawing::XShapes> xShapes(xModel->getCurrentSelection(), uno::UNO_QUERY); + if (!xShapes.is() || xShapes->getCount() < 1) + { + return; + } + + uno::Reference<beans::XPropertySet> xShapeProps(xShapes->getByIndex(0), uno::UNO_QUERY); + if (!xShapeProps.is()) + { + return; + } + + comphelper::SequenceAsHashMap aMap(xShapeProps->getPropertyValue("InteropGrabBag")); + auto it = aMap.find("SignatureCertificate"); + if (it == aMap.end()) + { + return; + } + + // We know that we add a signature line shape to an existing PDF at this point. + + uno::Reference<frame::XStorable> xStorable(xModel, uno::UNO_QUERY); + if (!xStorable.is()) + { + return; + } + + // Export just the signature line. + utl::MediaDescriptor aMediaDescriptor; + aMediaDescriptor["FilterName"] <<= OUString("draw_pdf_Export"); + SvMemoryStream aStream; + uno::Reference<io::XOutputStream> xStream(new utl::OStreamWrapper(aStream)); + aMediaDescriptor["OutputStream"] <<= xStream; + uno::Sequence<beans::PropertyValue> aFilterData( + comphelper::InitPropertySequence({ { "Selection", uno::Any(xShapes) } })); + aMediaDescriptor["FilterData"] <<= aFilterData; + xStorable->storeToURL("private:stream", aMediaDescriptor.getAsConstPropertyValueList()); + xStream->flush(); + + aStream.Seek(0); + rSignatureLineShape = std::vector<sal_Int8>(aStream.GetSize()); + aStream.ReadBytes(rSignatureLineShape.data(), rSignatureLineShape.size()); +} + +/// Represents a parsed signature. +struct Signature +{ + std::unique_ptr<vcl::pdf::PDFiumSignature> m_pSignature; + /// Offset+length pairs. + std::vector<std::pair<size_t, size_t>> m_aByteRanges; +}; + +/// Turns an array of floats into offset + length pairs. +void GetByteRangesFromPDF(const std::unique_ptr<vcl::pdf::PDFiumSignature>& pSignature, + std::vector<std::pair<size_t, size_t>>& rByteRanges) +{ + std::vector<int> aByteRange = pSignature->getByteRange(); + if (aByteRange.empty()) + { + SAL_WARN("xmlsecurity.helper", "GetByteRangesFromPDF: no byte ranges"); + return; + } + + size_t nByteRangeOffset = 0; + for (size_t i = 0; i < aByteRange.size(); ++i) + { + if (i % 2 == 0) + { + nByteRangeOffset = aByteRange[i]; + continue; + } + + size_t nLength = aByteRange[i]; + rByteRanges.emplace_back(nByteRangeOffset, nLength); + } +} + +/// Determines the last position that is covered by a signature. +bool GetEOFOfSignature(const Signature& rSignature, size_t& rEOF) +{ + if (rSignature.m_aByteRanges.size() < 2) + { + return false; + } + + rEOF = rSignature.m_aByteRanges[1].first + rSignature.m_aByteRanges[1].second; + return true; +} + +/** + * Get the value of the "modification detection and prevention" permission: + * Valid values are 1, 2 and 3: only 3 allows annotations after signing. + */ +int GetMDPPerm(const std::vector<Signature>& rSignatures) +{ + int nRet = 3; + + if (rSignatures.empty()) + { + return nRet; + } + + for (const auto& rSignature : rSignatures) + { + int nPerm = rSignature.m_pSignature->getDocMDPPermission(); + if (nPerm != 0) + { + return nPerm; + } + } + + return nRet; +} + +/// Checks if there are unsigned incremental updates between the signatures or after the last one. +bool IsCompleteSignature(SvStream& rStream, const Signature& rSignature, + const std::set<unsigned int>& rSignedEOFs, + const std::vector<unsigned int>& rAllEOFs) +{ + size_t nSignatureEOF = 0; + if (!GetEOFOfSignature(rSignature, nSignatureEOF)) + { + return false; + } + + bool bFoundOwn = false; + for (const auto& rEOF : rAllEOFs) + { + if (rEOF == nSignatureEOF) + { + bFoundOwn = true; + continue; + } + + if (!bFoundOwn) + { + continue; + } + + if (rSignedEOFs.find(rEOF) == rSignedEOFs.end()) + { + // Unsigned incremental update found. + return false; + } + } + + // Make sure we find the incremental update of the signature itself. + if (!bFoundOwn) + { + return false; + } + + // No additional content after the last incremental update. + rStream.Seek(STREAM_SEEK_TO_END); + size_t nFileEnd = rStream.Tell(); + return std::find(rAllEOFs.begin(), rAllEOFs.end(), nFileEnd) != rAllEOFs.end(); +} + +/** + * Contains checksums of a PDF page, which is rendered without annotations. It also contains + * the geometry of a few dangerous annotation types. + */ +struct PageChecksum +{ + BitmapChecksum m_nPageContent; + std::vector<basegfx::B2DRectangle> m_aAnnotations; + bool operator==(const PageChecksum& rChecksum) const; +}; + +bool PageChecksum::operator==(const PageChecksum& rChecksum) const +{ + if (m_nPageContent != rChecksum.m_nPageContent) + { + return false; + } + + return m_aAnnotations == rChecksum.m_aAnnotations; +} + +/// Collects the checksum of each page of one version of the PDF. +void AnalyizeSignatureStream(SvMemoryStream& rStream, std::vector<PageChecksum>& rPageChecksums, + int nMDPPerm) +{ + auto pPdfium = vcl::pdf::PDFiumLibrary::get(); + std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument + = pPdfium->openDocument(rStream.GetData(), rStream.GetSize(), OString()); + if (!pPdfDocument) + { + return; + } + + int nPageCount = pPdfDocument->getPageCount(); + for (int nPage = 0; nPage < nPageCount; ++nPage) + { + std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(nPage); + if (!pPdfPage) + { + return; + } + + PageChecksum aPageChecksum; + aPageChecksum.m_nPageContent = pPdfPage->getChecksum(nMDPPerm); + for (int i = 0; i < pPdfPage->getAnnotationCount(); ++i) + { + std::unique_ptr<vcl::pdf::PDFiumAnnotation> pPdfAnnotation = pPdfPage->getAnnotation(i); + if (!pPdfAnnotation) + { + SAL_WARN("xmlsecurity.helper", "Cannot get PDFiumAnnotation"); + continue; + } + vcl::pdf::PDFAnnotationSubType eType = pPdfAnnotation->getSubType(); + switch (eType) + { + case vcl::pdf::PDFAnnotationSubType::Unknown: + case vcl::pdf::PDFAnnotationSubType::FreeText: + case vcl::pdf::PDFAnnotationSubType::Stamp: + case vcl::pdf::PDFAnnotationSubType::Redact: + aPageChecksum.m_aAnnotations.push_back(pPdfAnnotation->getRectangle()); + break; + default: + break; + } + } + rPageChecksums.push_back(aPageChecksum); + } +} + +/** + * Checks if incremental updates after singing performed valid modifications only. + * nMDPPerm decides if annotations/commenting is OK, other changes are always not. + */ +bool IsValidSignature(SvStream& rStream, const Signature& rSignature, int nMDPPerm) +{ + size_t nSignatureEOF = 0; + if (!GetEOFOfSignature(rSignature, nSignatureEOF)) + { + return false; + } + + SvMemoryStream aSignatureStream; + sal_uInt64 nPos = rStream.Tell(); + rStream.Seek(0); + aSignatureStream.WriteStream(rStream, nSignatureEOF); + rStream.Seek(nPos); + aSignatureStream.Seek(0); + std::vector<PageChecksum> aSignedPages; + AnalyizeSignatureStream(aSignatureStream, aSignedPages, nMDPPerm); + + SvMemoryStream aFullStream; + nPos = rStream.Tell(); + rStream.Seek(0); + aFullStream.WriteStream(rStream); + rStream.Seek(nPos); + aFullStream.Seek(0); + std::vector<PageChecksum> aAllPages; + AnalyizeSignatureStream(aFullStream, aAllPages, nMDPPerm); + + // Fail if any page looks different after signing and at the end. Annotations/commenting doesn't + // count, though. + return aSignedPages == aAllPages; +} + +/** + * @param rInformation The actual result. + * @param rDocument the parsed document to see if the signature is partial. + * @return If we can determinate a result. + */ +bool ValidateSignature(SvStream& rStream, const Signature& rSignature, + SignatureInformation& rInformation, int nMDPPerm, + const std::set<unsigned int>& rSignatureEOFs, + const std::vector<unsigned int>& rTrailerEnds) +{ + std::vector<unsigned char> aContents = rSignature.m_pSignature->getContents(); + if (aContents.empty()) + { + SAL_WARN("xmlsecurity.helper", "ValidateSignature: no contents"); + return false; + } + + OString aSubFilter = rSignature.m_pSignature->getSubFilter(); + + const bool bNonDetached = aSubFilter == "adbe.pkcs7.sha1"; + if (aSubFilter.isEmpty() + || (aSubFilter != "adbe.pkcs7.detached" && !bNonDetached + && aSubFilter != "ETSI.CAdES.detached")) + { + if (aSubFilter.isEmpty()) + SAL_WARN("xmlsecurity.helper", "ValidateSignature: missing sub-filter"); + else + SAL_WARN("xmlsecurity.helper", + "ValidateSignature: unsupported sub-filter: '" << aSubFilter << "'"); + return false; + } + + // Reason / comment / description is optional. + rInformation.ouDescription = rSignature.m_pSignature->getReason(); + + // Date: used only when the time of signing is not available in the + // signature. + rInformation.stDateTime = rSignature.m_pSignature->getTime(); + + // Detect if the byte ranges don't cover everything, but the signature itself. + if (rSignature.m_aByteRanges.size() < 2) + { + SAL_WARN("xmlsecurity.helper", "ValidateSignature: expected 2 byte ranges"); + return false; + } + if (rSignature.m_aByteRanges[0].first != 0) + { + SAL_WARN("xmlsecurity.helper", "ValidateSignature: first range start is not 0"); + return false; + } + // Binary vs hex dump and 2 is the leading "<" and the trailing ">" around the hex string. + size_t nSignatureLength = aContents.size() * 2 + 2; + if (rSignature.m_aByteRanges[1].first + != (rSignature.m_aByteRanges[0].second + nSignatureLength)) + { + SAL_WARN("xmlsecurity.helper", + "ValidateSignature: second range start is not the end of the signature"); + return false; + } + rInformation.bPartialDocumentSignature + = !IsCompleteSignature(rStream, rSignature, rSignatureEOFs, rTrailerEnds); + if (!IsValidSignature(rStream, rSignature, nMDPPerm)) + { + SAL_WARN("xmlsecurity.helper", "ValidateSignature: invalid incremental update detected"); + return false; + } + + // At this point there is no obviously missing info to validate the + // signature. + return svl::crypto::Signing::Verify(rStream, rSignature.m_aByteRanges, bNonDetached, aContents, + rInformation); +} +} + +PDFSignatureHelper::PDFSignatureHelper() = default; + +bool PDFSignatureHelper::ReadAndVerifySignature( + const uno::Reference<io::XInputStream>& xInputStream) +{ + if (!xInputStream.is()) + { + SAL_WARN("xmlsecurity.helper", "input stream missing"); + return false; + } + + std::unique_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(xInputStream, true)); + return ReadAndVerifySignatureSvStream(*pStream); +} + +bool PDFSignatureHelper::ReadAndVerifySignatureSvStream(SvStream& rStream) +{ + auto pPdfium = vcl::pdf::PDFiumLibrary::get(); + if (!pPdfium) + { + return true; + } + + SvMemoryStream aStream; + sal_uInt64 nPos = rStream.Tell(); + rStream.Seek(0); + aStream.WriteStream(rStream); + rStream.Seek(nPos); + std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument + = pPdfium->openDocument(aStream.GetData(), aStream.GetSize(), OString()); + if (!pPdfDocument) + { + SAL_WARN("xmlsecurity.helper", "failed to read the document"); + return false; + } + + int nSignatureCount = pPdfDocument->getSignatureCount(); + if (nSignatureCount <= 0) + { + return true; + } + std::vector<Signature> aSignatures(nSignatureCount); + for (int i = 0; i < nSignatureCount; ++i) + { + std::unique_ptr<vcl::pdf::PDFiumSignature> pSignature = pPdfDocument->getSignature(i); + std::vector<std::pair<size_t, size_t>> aByteRanges; + GetByteRangesFromPDF(pSignature, aByteRanges); + aSignatures[i] = Signature{ std::move(pSignature), aByteRanges }; + } + + std::set<unsigned int> aSignatureEOFs; + for (const auto& rSignature : aSignatures) + { + size_t nEOF = 0; + if (GetEOFOfSignature(rSignature, nEOF)) + { + aSignatureEOFs.insert(nEOF); + } + } + + std::vector<unsigned int> aTrailerEnds = pPdfDocument->getTrailerEnds(); + + m_aSignatureInfos.clear(); + + int nMDPPerm = GetMDPPerm(aSignatures); + + for (size_t i = 0; i < aSignatures.size(); ++i) + { + SignatureInformation aInfo(i); + + if (!ValidateSignature(rStream, aSignatures[i], aInfo, nMDPPerm, aSignatureEOFs, + aTrailerEnds)) + { + SAL_WARN("xmlsecurity.helper", "failed to determine digest match"); + } + + m_aSignatureInfos.push_back(aInfo); + } + + return true; +} + +SignatureInformations const& PDFSignatureHelper::GetSignatureInformations() const +{ + return m_aSignatureInfos; +} + +uno::Sequence<security::DocumentSignatureInformation> +PDFSignatureHelper::GetDocumentSignatureInformations( + const uno::Reference<xml::crypto::XSecurityEnvironment>& xSecEnv) const +{ + uno::Sequence<security::DocumentSignatureInformation> aRet(m_aSignatureInfos.size()); + auto aRetRange = asNonConstRange(aRet); + + for (size_t i = 0; i < m_aSignatureInfos.size(); ++i) + { + const SignatureInformation& rInternal = m_aSignatureInfos[i]; + security::DocumentSignatureInformation& rExternal = aRetRange[i]; + rExternal.SignatureIsValid + = rInternal.nStatus == xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED; + if (rInternal.GetSigningCertificate() + && !rInternal.GetSigningCertificate()->X509Certificate.isEmpty()) + { + rExternal.Signer = xSecEnv->createCertificateFromAscii( + rInternal.GetSigningCertificate()->X509Certificate); + } + rExternal.PartialDocumentSignature = rInternal.bPartialDocumentSignature; + + // Verify certificate. + if (rExternal.Signer.is()) + { + try + { + rExternal.CertificateStatus = xSecEnv->verifyCertificate(rExternal.Signer, {}); + } + catch (const uno::SecurityException&) + { + DBG_UNHANDLED_EXCEPTION("xmlsecurity.helper", "failed to verify certificate"); + rExternal.CertificateStatus = security::CertificateValidity::INVALID; + } + } + else + rExternal.CertificateStatus = security::CertificateValidity::INVALID; + } + + return aRet; +} + +sal_Int32 PDFSignatureHelper::GetNewSecurityId() const { return m_aSignatureInfos.size(); } + +void PDFSignatureHelper::SetX509Certificate( + const uno::Reference<security::XCertificate>& xCertificate) +{ + m_xCertificate = xCertificate; +} + +void PDFSignatureHelper::SetDescription(const OUString& rDescription) +{ + m_aDescription = rDescription; +} + +bool PDFSignatureHelper::Sign(const uno::Reference<frame::XModel>& xModel, + const uno::Reference<io::XInputStream>& xInputStream, bool bAdES) +{ + std::unique_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(xInputStream, true)); + vcl::filter::PDFDocument aDocument; + if (!aDocument.Read(*pStream)) + { + SAL_WARN("xmlsecurity.helper", "failed to read the document"); + return false; + } + + sal_Int32 nPage = 0; + std::vector<sal_Int8> aSignatureLineShape; + GetSignatureLineShape(xModel, nPage, aSignatureLineShape); + if (nPage > 0) + { + // UNO page number is 1-based. + aDocument.SetSignaturePage(nPage - 1); + } + if (!aSignatureLineShape.empty()) + { + aDocument.SetSignatureLine(std::move(aSignatureLineShape)); + } + + if (!aDocument.Sign(m_xCertificate, m_aDescription, bAdES)) + { + SAL_WARN("xmlsecurity.helper", "failed to sign"); + return false; + } + + uno::Reference<io::XStream> xStream(xInputStream, uno::UNO_QUERY); + std::unique_ptr<SvStream> pOutStream(utl::UcbStreamHelper::CreateStream(xStream, true)); + if (!aDocument.Write(*pOutStream)) + { + SAL_WARN("xmlsecurity.helper", "failed to write signed data"); + return false; + } + + return true; +} + +bool PDFSignatureHelper::RemoveSignature(const uno::Reference<io::XInputStream>& xInputStream, + sal_uInt16 nPosition) +{ + std::unique_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(xInputStream, true)); + vcl::filter::PDFDocument aDocument; + if (!aDocument.Read(*pStream)) + { + SAL_WARN("xmlsecurity.helper", "failed to read the document"); + return false; + } + + if (!aDocument.RemoveSignature(nPosition)) + { + SAL_WARN("xmlsecurity.helper", "failed to remove signature"); + return false; + } + + uno::Reference<io::XStream> xStream(xInputStream, uno::UNO_QUERY); + uno::Reference<io::XTruncate> xTruncate(xStream, uno::UNO_QUERY); + if (!xTruncate.is()) + { + SAL_WARN("xmlsecurity.helper", "failed to truncate"); + return false; + } + xTruncate->truncate(); + std::unique_ptr<SvStream> pOutStream(utl::UcbStreamHelper::CreateStream(xStream, true)); + if (!aDocument.Write(*pOutStream)) + { + SAL_WARN("xmlsecurity.helper", "failed to write without signature"); + return false; + } + + return true; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/helper/xmlsignaturehelper.cxx b/xmlsecurity/source/helper/xmlsignaturehelper.cxx new file mode 100644 index 0000000000..0b5825b125 --- /dev/null +++ b/xmlsecurity/source/helper/xmlsignaturehelper.cxx @@ -0,0 +1,713 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include <xmlsignaturehelper.hxx> +#include <documentsignaturehelper.hxx> +#include <xsecctl.hxx> +#include <biginteger.hxx> + +#include <UriBindingHelper.hxx> + +#include <tools/datetime.hxx> + +#include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/io/XTruncate.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/beans/StringPair.hpp> +#include <com/sun/star/xml/sax/Parser.hpp> +#include <com/sun/star/xml/sax/Writer.hpp> +#include <com/sun/star/embed/ElementModes.hpp> +#include <com/sun/star/embed/XStorage.hpp> +#include <com/sun/star/embed/StorageFormats.hpp> +#include <com/sun/star/embed/XTransactedObject.hpp> + +#include <comphelper/attributelist.hxx> +#include <comphelper/ofopxmlhelper.hxx> +#include <comphelper/sequence.hxx> +#include <comphelper/diagnose_ex.hxx> +#include <rtl/ustrbuf.hxx> +#include <sal/log.hxx> + +#include <optional> + +constexpr OUStringLiteral NS_DOCUMENTSIGNATURES = u"http://openoffice.org/2004/documentsignatures"; +constexpr OUStringLiteral NS_DOCUMENTSIGNATURES_ODF_1_2 = u"urn:oasis:names:tc:opendocument:xmlns:digitalsignature:1.0"; +constexpr OUString OOXML_SIGNATURE_ORIGIN = u"http://schemas.openxmlformats.org/package/2006/relationships/digital-signature/origin"_ustr; +constexpr OUString OOXML_SIGNATURE_SIGNATURE = u"http://schemas.openxmlformats.org/package/2006/relationships/digital-signature/signature"_ustr; + +using namespace ::com::sun::star; +using namespace ::com::sun::star::graphic; +using namespace ::com::sun::star::uno; + +XMLSignatureHelper::XMLSignatureHelper( const uno::Reference< uno::XComponentContext >& rxCtx) + : mxCtx(rxCtx), mbODFPre1_2(false) +{ + mpXSecController = new XSecController(rxCtx); + mbError = false; +} + +XMLSignatureHelper::~XMLSignatureHelper() +{ +} + +void XMLSignatureHelper::SetStorage( + const Reference < css::embed::XStorage >& rxStorage, + std::u16string_view sODFVersion) +{ + SAL_WARN_IF( mxUriBinding.is(), "xmlsecurity.helper", "SetStorage - UriBinding already set!" ); + mxUriBinding = new UriBindingHelper( rxStorage ); + SAL_WARN_IF(!rxStorage.is(), "xmlsecurity.helper", "SetStorage - empty storage!"); + mbODFPre1_2 = DocumentSignatureHelper::isODFPre_1_2(sODFVersion); +} + + +void XMLSignatureHelper::SetStartVerifySignatureHdl( const Link<LinkParamNone*,bool>& rLink ) +{ + maStartVerifySignatureHdl = rLink; +} + + +void XMLSignatureHelper::StartMission(const uno::Reference<xml::crypto::XXMLSecurityContext>& xSecurityContext) +{ + if ( !mxUriBinding.is() ) + mxUriBinding = new UriBindingHelper(); + + mpXSecController->startMission(mxUriBinding, xSecurityContext); +} + +void XMLSignatureHelper::EndMission() +{ + mpXSecController->endMission(); +} + +sal_Int32 XMLSignatureHelper::GetNewSecurityId() +{ + return mpXSecController->getNewSecurityId(); +} + +void XMLSignatureHelper::SetX509Certificate( + sal_Int32 nSecurityId, + const OUString& ouX509IssuerName, + const OUString& ouX509SerialNumber, + const OUString& ouX509Cert, + const OUString& ouX509CertDigest, + svl::crypto::SignatureMethodAlgorithm eAlgorithmID) +{ + mpXSecController->setX509Certificate( + nSecurityId, + ouX509IssuerName, + ouX509SerialNumber, + ouX509Cert, + ouX509CertDigest, + eAlgorithmID); +} + +void XMLSignatureHelper::AddEncapsulatedX509Certificate(const OUString& ouEncapsulatedX509Certificate) +{ + mpXSecController->addEncapsulatedX509Certificate(ouEncapsulatedX509Certificate); +} + +void XMLSignatureHelper::SetGpgCertificate(sal_Int32 nSecurityId, + const OUString& ouGpgCertDigest, + const OUString& ouGpgCert, + const OUString& ouGpgOwner) +{ + mpXSecController->setGpgCertificate( + nSecurityId, + ouGpgCertDigest, + ouGpgCert, + ouGpgOwner); +} + +void XMLSignatureHelper::SetDateTime( sal_Int32 nSecurityId, const ::DateTime& rDateTime ) +{ + css::util::DateTime stDateTime = rDateTime.GetUNODateTime(); + mpXSecController->setDate( nSecurityId, stDateTime ); +} + +void XMLSignatureHelper::SetDescription(sal_Int32 nSecurityId, const OUString& rDescription) +{ + mpXSecController->setDescription(nSecurityId, rDescription); +} + +void XMLSignatureHelper::SetSignatureLineId(sal_Int32 nSecurityId, const OUString& rSignatureLineId) +{ + mpXSecController->setSignatureLineId(nSecurityId, rSignatureLineId); +} + +void XMLSignatureHelper::SetSignatureLineValidGraphic( + sal_Int32 nSecurityId, const css::uno::Reference<XGraphic>& xValidGraphic) +{ + mpXSecController->setSignatureLineValidGraphic(nSecurityId, xValidGraphic); +} + +void XMLSignatureHelper::SetSignatureLineInvalidGraphic( + sal_Int32 nSecurityId, const css::uno::Reference<XGraphic>& xInvalidGraphic) +{ + mpXSecController->setSignatureLineInvalidGraphic(nSecurityId, xInvalidGraphic); +} + +void XMLSignatureHelper::AddForSigning( sal_Int32 nSecurityId, const OUString& uri, bool bBinary, bool bXAdESCompliantIfODF ) +{ + mpXSecController->signAStream( nSecurityId, uri, bBinary, bXAdESCompliantIfODF ); +} + + +uno::Reference<xml::sax::XWriter> XMLSignatureHelper::CreateDocumentHandlerWithHeader( + const css::uno::Reference< css::io::XOutputStream >& xOutputStream ) +{ + /* + * get SAX writer component + */ + uno::Reference< xml::sax::XWriter > xSaxWriter = xml::sax::Writer::create(mxCtx); + + /* + * connect XML writer to output stream + */ + xSaxWriter->setOutputStream( xOutputStream ); + + /* + * write the xml context for signatures + */ + rtl::Reference<comphelper::AttributeList> pAttributeList = new comphelper::AttributeList(); + OUString sNamespace; + if (mbODFPre1_2) + sNamespace = NS_DOCUMENTSIGNATURES; + else + sNamespace = NS_DOCUMENTSIGNATURES_ODF_1_2; + + pAttributeList->AddAttribute( + "xmlns", + sNamespace); + + xSaxWriter->startDocument(); + xSaxWriter->startElement( + "document-signatures", + pAttributeList); + + return xSaxWriter; +} + +void XMLSignatureHelper::CloseDocumentHandler( const uno::Reference<xml::sax::XDocumentHandler>& xDocumentHandler ) +{ + xDocumentHandler->endElement( "document-signatures" ); + xDocumentHandler->endDocument(); +} + +void XMLSignatureHelper::ExportSignature( + const uno::Reference< xml::sax::XDocumentHandler >& xDocumentHandler, + const SignatureInformation& signatureInfo, + bool bXAdESCompliantIfODF ) +{ + XSecController::exportSignature(xDocumentHandler, signatureInfo, bXAdESCompliantIfODF); +} + +void XMLSignatureHelper::ExportOOXMLSignature(const uno::Reference<embed::XStorage>& xRootStorage, const uno::Reference<embed::XStorage>& xSignatureStorage, const SignatureInformation& rInformation, int nSignatureIndex) +{ + uno::Reference<io::XOutputStream> xOutputStream(xSignatureStorage->openStreamElement("sig" + OUString::number(nSignatureIndex) + ".xml", embed::ElementModes::READWRITE), uno::UNO_QUERY); + + if (rInformation.aSignatureBytes.hasElements()) + // This is a signature roundtrip, just write back the signature as-is. + xOutputStream->writeBytes(rInformation.aSignatureBytes); + else + { + uno::Reference<xml::sax::XWriter> xSaxWriter = xml::sax::Writer::create(mxCtx); + xSaxWriter->setOutputStream(xOutputStream); + xSaxWriter->startDocument(); + + mpXSecController->exportOOXMLSignature(xRootStorage, xSaxWriter, rInformation); + + xSaxWriter->endDocument(); + } +} + +void XMLSignatureHelper::CreateAndWriteSignature( const uno::Reference< xml::sax::XDocumentHandler >& xDocumentHandler, bool bXAdESCompliantIfODF ) +{ + mbError = false; + + if ( !mpXSecController->WriteSignature( xDocumentHandler, bXAdESCompliantIfODF ) ) + { + mbError = true; + } +} + +bool XMLSignatureHelper::ReadAndVerifySignature( const css::uno::Reference< css::io::XInputStream >& xInputStream ) +{ + mbError = false; + + SAL_WARN_IF(!xInputStream.is(), "xmlsecurity.helper", "input stream missing"); + + // prepare ParserInputSource + xml::sax::InputSource aParserInput; + aParserInput.aInputStream = xInputStream; + + // get SAX parser component + uno::Reference< xml::sax::XParser > xParser = xml::sax::Parser::create(mxCtx); + + // create a signature reader + uno::Reference< xml::sax::XDocumentHandler > xHandler + = mpXSecController->createSignatureReader(*this); + + // setup the connection: + // Parser -> SignatureReader + xParser->setDocumentHandler( xHandler ); + + // Parse the stream. + try + { + xParser->parseStream( aParserInput ); + } + catch( uno::Exception& ) + { + DBG_UNHANDLED_EXCEPTION("xmlsecurity.helper"); + mbError = true; + } + + // 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(); +} + +void XMLSignatureHelper::StartVerifySignatureElement() +{ + if ( !maStartVerifySignatureHdl.IsSet() || maStartVerifySignatureHdl.Call(nullptr) ) + { + sal_Int32 nSignatureId = mpXSecController->getNewSecurityId(); + mpXSecController->addSignature( nSignatureId ); + } +} + +namespace +{ +bool lcl_isSignatureType(const beans::StringPair& rPair) +{ + return rPair.First == "Type" && rPair.Second == OOXML_SIGNATURE_SIGNATURE; +} +bool lcl_isSignatureOriginType(const beans::StringPair& rPair) +{ + return rPair.First == "Type" && rPair.Second == OOXML_SIGNATURE_ORIGIN; +} +} + +bool XMLSignatureHelper::ReadAndVerifySignatureStorage(const uno::Reference<embed::XStorage>& xStorage, bool bCacheLastSignature) +{ + sal_Int32 nOpenMode = embed::ElementModes::READ; + if (xStorage.is() && !xStorage->hasByName("_rels")) + { + SAL_WARN("xmlsecurity.helper", "expected stream, in signature storage but not found: _rels"); + return false; + } + + uno::Reference<embed::XStorage> xSubStorage = xStorage->openStorageElement("_rels", nOpenMode); + uno::Reference<io::XInputStream> xRelStream(xSubStorage->openStreamElement("origin.sigs.rels", nOpenMode), uno::UNO_QUERY); + uno::Sequence< uno::Sequence<beans::StringPair> > aRelationsInfo = comphelper::OFOPXMLHelper::ReadRelationsInfoSequence(xRelStream, u"origin.sigs.rels", mxCtx); + + for (sal_Int32 i = 0; i < aRelationsInfo.getLength(); ++i) + { + const uno::Sequence<beans::StringPair>& rRelation = aRelationsInfo[i]; + if (std::any_of(rRelation.begin(), rRelation.end(), lcl_isSignatureType)) + { + auto it = std::find_if(rRelation.begin(), rRelation.end(), [](const beans::StringPair& rPair) { return rPair.First == "Target"; }); + if (it != rRelation.end()) + { + if (xStorage.is() && !xStorage->hasByName(it->Second)) + { + SAL_WARN("xmlsecurity.helper", "expected stream, but not found: " << it->Second); + continue; + } + + uno::Reference<io::XInputStream> xInputStream(xStorage->openStreamElement(it->Second, nOpenMode), uno::UNO_QUERY); + if (!ReadAndVerifySignatureStorageStream(xInputStream)) + return false; + + // By default, we cache. If it's requested, then we don't cache the last signature. + bool bCache = true; + if (!bCacheLastSignature && i == aRelationsInfo.getLength() - 1) + bCache = false; + + if (!bCache) + continue; + // Store the contents of the stream as is, in case we need to write it back later. + xInputStream.clear(); + xInputStream.set(xStorage->openStreamElement(it->Second, nOpenMode), uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xPropertySet(xInputStream, uno::UNO_QUERY); + if (!xPropertySet.is()) + continue; + + sal_Int64 nSize = 0; + xPropertySet->getPropertyValue("Size") >>= nSize; + if (nSize < 0 || nSize > SAL_MAX_INT32) + { + SAL_WARN("xmlsecurity.helper", "bogus signature size: " << nSize); + continue; + } + uno::Sequence<sal_Int8> aData; + xInputStream->readBytes(aData, nSize); + mpXSecController->setSignatureBytes(aData); + } + } + } + + return true; +} + +bool XMLSignatureHelper::ReadAndVerifySignatureStorageStream(const css::uno::Reference<css::io::XInputStream>& xInputStream) +{ + mbError = false; + + // Create the input source. + xml::sax::InputSource aParserInput; + aParserInput.aInputStream = xInputStream; + + // Create the sax parser. + uno::Reference<xml::sax::XParser> xParser = xml::sax::Parser::create(mxCtx); + + // Create the signature reader. + uno::Reference<xml::sax::XDocumentHandler> xHandler = mpXSecController->createSignatureReader(*this, embed::StorageFormats::OFOPXML); + + // Parser -> signature reader. + xParser->setDocumentHandler(xHandler); + + // Parse the stream. + try + { + xParser->parseStream(aParserInput); + } + catch(const uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("xmlsecurity.helper"); + mbError = true; + } + + // release the signature reader + mpXSecController->releaseSignatureReader(); + + return !mbError; +} + +void XMLSignatureHelper::EnsureSignaturesRelation(const css::uno::Reference<css::embed::XStorage>& xStorage, bool bAdd) +{ + sal_Int32 nOpenMode = embed::ElementModes::READWRITE; + uno::Reference<embed::XStorage> xSubStorage = xStorage->openStorageElement("_rels", nOpenMode); + uno::Reference<io::XInputStream> xRelStream(xSubStorage->openStreamElement(".rels", nOpenMode), uno::UNO_QUERY); + std::vector< uno::Sequence<beans::StringPair> > aRelationsInfo = comphelper::sequenceToContainer< std::vector< uno::Sequence<beans::StringPair> > >(comphelper::OFOPXMLHelper::ReadRelationsInfoSequence(xRelStream, u".rels", mxCtx)); + + // Do we have a relation already? + bool bHaveRelation = false; + int nCount = 0; + for (const uno::Sequence<beans::StringPair>& rRelation : aRelationsInfo) + { + auto aRelation = comphelper::sequenceToContainer< std::vector<beans::StringPair> >(rRelation); + if (std::any_of(aRelation.begin(), aRelation.end(), lcl_isSignatureOriginType)) + { + bHaveRelation = true; + break; + } + ++nCount; + } + + if (!bHaveRelation && bAdd) + { + // No, and have to add one. + std::vector<beans::StringPair> aRelation; + aRelation.emplace_back("Id", "rId" + OUString::number(++nCount)); + aRelation.emplace_back("Type", OOXML_SIGNATURE_ORIGIN); + aRelation.emplace_back("Target", "_xmlsignatures/origin.sigs"); + aRelationsInfo.push_back(comphelper::containerToSequence(aRelation)); + } + else if (bHaveRelation && !bAdd) + { + // Yes, and need to remove it. + for (std::vector< uno::Sequence<beans::StringPair> >::iterator it = aRelationsInfo.begin(); it != aRelationsInfo.end();) + { + auto aRelation = comphelper::sequenceToContainer< std::vector<beans::StringPair> >(*it); + if (std::any_of(aRelation.begin(), aRelation.end(), lcl_isSignatureOriginType)) + it = aRelationsInfo.erase(it); + else + ++it; + } + } + + // Write it back. + uno::Reference<io::XTruncate> xTruncate(xRelStream, uno::UNO_QUERY); + xTruncate->truncate(); + uno::Reference<io::XOutputStream> xOutputStream(xRelStream, uno::UNO_QUERY); + comphelper::OFOPXMLHelper::WriteRelationsInfoSequence(xOutputStream, comphelper::containerToSequence(aRelationsInfo), mxCtx); + + // Commit it. + uno::Reference<embed::XTransactedObject> xTransact(xSubStorage, uno::UNO_QUERY); + xTransact->commit(); + xTransact.set(xStorage, uno::UNO_QUERY); + xTransact->commit(); +} + +void XMLSignatureHelper::ExportSignatureRelations(const css::uno::Reference<css::embed::XStorage>& xStorage, int nSignatureCount) +{ + // Write the empty file, its relations will be the signatures. + sal_Int32 nOpenMode = embed::ElementModes::READWRITE; + uno::Reference<io::XOutputStream> xOriginStream(xStorage->openStreamElement("origin.sigs", nOpenMode), uno::UNO_QUERY); + uno::Reference<io::XTruncate> xTruncate(xOriginStream, uno::UNO_QUERY); + xTruncate->truncate(); + xOriginStream->closeOutput(); + + // Write the relations. + uno::Reference<embed::XStorage> xSubStorage = xStorage->openStorageElement("_rels", nOpenMode); + uno::Reference<io::XOutputStream> xRelStream(xSubStorage->openStreamElement("origin.sigs.rels", nOpenMode), uno::UNO_QUERY); + std::vector< uno::Sequence<beans::StringPair> > aRelations; + for (int i = 0; i < nSignatureCount; ++i) + { + std::vector<beans::StringPair> aRelation; + aRelation.emplace_back("Id", "rId" + OUString::number(i + 1)); + aRelation.emplace_back("Type", OOXML_SIGNATURE_SIGNATURE); + aRelation.emplace_back("Target", "sig" + OUString::number(i + 1) + ".xml"); + aRelations.push_back(comphelper::containerToSequence(aRelation)); + } + comphelper::OFOPXMLHelper::WriteRelationsInfoSequence(xRelStream, comphelper::containerToSequence(aRelations), mxCtx); + uno::Reference<embed::XTransactedObject> xTransact(xSubStorage, uno::UNO_QUERY); + xTransact->commit(); +} + +void XMLSignatureHelper::ExportSignatureContentTypes(const css::uno::Reference<css::embed::XStorage>& xStorage, int nSignatureCount) +{ + uno::Reference<io::XStream> xStream = xStorage->openStreamElement("[Content_Types].xml", embed::ElementModes::READWRITE); + uno::Reference<io::XInputStream> xInputStream = xStream->getInputStream(); + uno::Sequence< uno::Sequence<beans::StringPair> > aContentTypeInfo = comphelper::OFOPXMLHelper::ReadContentTypeSequence(xInputStream, mxCtx); + if (aContentTypeInfo.getLength() < 2) + { + SAL_WARN("xmlsecurity.helper", "no defaults or overrides in aContentTypeInfo"); + return; + } + auto pContentTypeInfo = aContentTypeInfo.getArray(); + + // Append rels and sigs to defaults, if it's not there already. + uno::Sequence<beans::StringPair>& rDefaults = pContentTypeInfo[0]; + auto aDefaults = comphelper::sequenceToContainer< std::vector<beans::StringPair> >(rDefaults); + if (std::none_of(std::cbegin(rDefaults), std::cend(rDefaults), [](const beans::StringPair& rPair) { return rPair.First == "rels"; })) + aDefaults.emplace_back("rels", "application/vnd.openxmlformats-package.relationships+xml"); + + if (std::none_of(std::cbegin(rDefaults), std::cend(rDefaults), [](const beans::StringPair& rPair) { return rPair.First == "sigs"; })) + aDefaults.emplace_back("sigs", "application/vnd.openxmlformats-package.digital-signature-origin"); + rDefaults = comphelper::containerToSequence(aDefaults); + + // Remove existing signature overrides. + uno::Sequence<beans::StringPair>& rOverrides = pContentTypeInfo[1]; + auto aOverrides = comphelper::sequenceToContainer< std::vector<beans::StringPair> >(rOverrides); + std::erase_if(aOverrides, [](const beans::StringPair& rPair) + { + return rPair.First.startsWith("/_xmlsignatures/sig"); + }); + + // Add our signature overrides. + for (int i = 1; i <= nSignatureCount; ++i) + aOverrides.emplace_back("/_xmlsignatures/sig" + OUString::number(i) + ".xml", "application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml"); + + rOverrides = comphelper::containerToSequence(aOverrides); + uno::Reference<io::XOutputStream> xOutputStream = xStream->getOutputStream(); + uno::Reference <io::XTruncate> xTruncate(xOutputStream, uno::UNO_QUERY); + xTruncate->truncate(); + comphelper::OFOPXMLHelper::WriteContentSequence(xOutputStream, rDefaults, rOverrides, mxCtx); + uno::Reference<embed::XTransactedObject> xTransact(xStorage, uno::UNO_QUERY); + xTransact->commit(); +} +void XMLSignatureHelper::CreateAndWriteOOXMLSignature(const uno::Reference<embed::XStorage>& xRootStorage, const uno::Reference<embed::XStorage>& xSignatureStorage, int nSignatureIndex) +{ + uno::Reference<io::XOutputStream> xOutputStream(xSignatureStorage->openStreamElement("sig" + OUString::number(nSignatureIndex) + ".xml", embed::ElementModes::READWRITE), uno::UNO_QUERY); + uno::Reference<xml::sax::XWriter> xSaxWriter = xml::sax::Writer::create(mxCtx); + xSaxWriter->setOutputStream(xOutputStream); + xSaxWriter->startDocument(); + + mbError = false; + if (!mpXSecController->WriteOOXMLSignature(xRootStorage, xSaxWriter)) + mbError = true; + + xSaxWriter->endDocument(); +} + +/** check this constraint from xmldsig-core 4.5.4: + + All certificates appearing in an X509Data element MUST relate to the + validation key by either containing it or being part of a certification + chain that terminates in a certificate containing the validation key. + */ +static auto CheckX509Data( + uno::Reference<xml::crypto::XSecurityEnvironment> const& xSecEnv, + std::vector<SignatureInformation::X509CertInfo> const& rX509CertInfos, + std::vector<uno::Reference<security::XCertificate>> & rCerts, + std::vector<SignatureInformation::X509CertInfo> & rSorted) -> bool +{ + assert(rCerts.empty()); + assert(rSorted.empty()); + if (rX509CertInfos.empty()) + { + SAL_WARN("xmlsecurity.comp", "no X509Data"); + return false; + } + std::vector<uno::Reference<security::XCertificate>> certs; + for (SignatureInformation::X509CertInfo const& it : rX509CertInfos) + { + if (!it.X509Certificate.isEmpty()) + { + certs.emplace_back(xSecEnv->createCertificateFromAscii(it.X509Certificate)); + } + else + { + certs.emplace_back(xSecEnv->getCertificate( + it.X509IssuerName, + xmlsecurity::numericStringToBigInteger(it.X509SerialNumber))); + } + if (!certs.back().is()) + { + SAL_WARN("xmlsecurity.comp", "X509Data cannot be parsed"); + return false; + } + } + + // first, search one whose issuer isn't in the list, or a self-signed one + std::optional<size_t> start; + for (size_t i = 0; i < certs.size(); ++i) + { + for (size_t j = 0; ; ++j) + { + if (j == certs.size()) + { + if (start) + { + SAL_WARN("xmlsecurity.comp", "X509Data do not form a chain: certificate has no issuer but already have start of chain: " << certs[i]->getSubjectName()); + return false; + } + start = i; // issuer isn't in the list + break; + } + if (xmlsecurity::EqualDistinguishedNames(certs[i]->getIssuerName(), certs[j]->getSubjectName(), xmlsecurity::NOCOMPAT)) + { + if (i == j) // self signed + { + if (start) + { + SAL_WARN("xmlsecurity.comp", "X509Data do not form a chain: certificate is self-signed but already have start of chain: " << certs[i]->getSubjectName()); + return false; + } + start = i; + } + break; + } + } + } + std::vector<size_t> chain; + if (!start) + { + // this can only be a cycle? + SAL_WARN("xmlsecurity.comp", "X509Data do not form a chain: cycle detected"); + return false; + } + chain.emplace_back(*start); + + // second, check that there is a chain, no tree or cycle... + for (size_t i = 0; i < certs.size(); ++i) + { + assert(chain.size() == i + 1); + for (size_t j = 0; j < certs.size(); ++j) + { + if (chain[i] != j) + { + if (xmlsecurity::EqualDistinguishedNames( + certs[chain[i]]->getSubjectName(), certs[j]->getIssuerName(), xmlsecurity::NOCOMPAT)) + { + if (chain.size() != i + 1) // already found issue? + { + SAL_WARN("xmlsecurity.comp", "X509Data do not form a chain: certificate issued 2 others: " << certs[chain[i]]->getSubjectName()); + return false; + } + chain.emplace_back(j); + } + } + } + if (i == certs.size() - 1) + { // last one: must be a leaf + if (chain.size() != i + 1) + { + SAL_WARN("xmlsecurity.comp", "X509Data do not form a chain: certificate in cycle: " << certs[chain[i]]->getSubjectName()); + return false; + } + } + else if (chain.size() != i + 2) + { // not issuer of another? + SAL_WARN("xmlsecurity.comp", "X509Data do not form a chain: certificate issued 0 others: " << certs[chain[i]]->getSubjectName()); + return false; + } + } + + // success + assert(chain.size() == rX509CertInfos.size()); + for (auto const& it : chain) + { + rSorted.emplace_back(rX509CertInfos[it]); + rCerts.emplace_back(certs[it]); + } + return true; +} + +std::vector<uno::Reference<security::XCertificate>> +XMLSignatureHelper::CheckAndUpdateSignatureInformation( + uno::Reference<xml::crypto::XSecurityEnvironment> const& xSecEnv, + SignatureInformation const& rInfo) +{ + // if the check fails, it's not possible to determine which X509Data + // contained the signing certificate - the UI cannot display something + // useful in this case, so prevent anything misleading by clearing the + // X509Datas. + + std::vector<uno::Reference<security::XCertificate>> certs; + std::vector<SignatureInformation::X509Data> datas; + // TODO: for now, just merge all X509Datas together for checking... + // (this will probably break round-trip of signature with multiple X509Data, + // no idea if that is a problem) + SignatureInformation::X509Data temp; + SignatureInformation::X509Data tempResult; + for (auto const& rData : rInfo.X509Datas) + { + for (auto const& it : rData) + { + temp.emplace_back(it); + } + } + if (CheckX509Data(xSecEnv, temp, certs, tempResult)) + { + datas.emplace_back(tempResult); + } + + // rInfo is a copy, update the original + mpXSecController->UpdateSignatureInformation(rInfo.nSecurityId, std::move(datas)); + return certs; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/helper/xsecctl.cxx b/xmlsecurity/source/helper/xsecctl.cxx new file mode 100644 index 0000000000..08b822f157 --- /dev/null +++ b/xmlsecurity/source/helper/xsecctl.cxx @@ -0,0 +1,1005 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <config_gpgme.h> + +#include <utility> +#include <xsecctl.hxx> +#include <documentsignaturehelper.hxx> +#include <framework/saxeventkeeperimpl.hxx> +#include <xmlsec/xmldocumentwrapper_xmlsecimpl.hxx> +#if HAVE_FEATURE_GPGME +# include <gpg/xmlsignature_gpgimpl.hxx> +#endif + +#include <com/sun/star/xml/crypto/sax/XMissionTaker.hpp> +#include <com/sun/star/xml/crypto/SecurityOperationStatus.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/xml/sax/XParser.hpp> +#include <com/sun/star/xml/crypto/XXMLSignature.hpp> + +#include <comphelper/attributelist.hxx> +#include <rtl/ustrbuf.hxx> +#include <rtl/ref.hxx> +#include <sal/log.hxx> +#include <unotools/datetime.hxx> +#include "ooxmlsecexporter.hxx" +#include <UriBindingHelper.hxx> + +using namespace com::sun::star; + +namespace +{ +OUString getDigestURI(sal_Int32 nID) +{ + switch( nID ) + { + case css::xml::crypto::DigestID::SHA1: + return ALGO_XMLDSIGSHA1; + case css::xml::crypto::DigestID::SHA256: + return ALGO_XMLDSIGSHA256; + case css::xml::crypto::DigestID::SHA512: + return ALGO_XMLDSIGSHA512; + default: + return ALGO_XMLDSIGSHA1; + } +} +OUString getSignatureURI(svl::crypto::SignatureMethodAlgorithm eAlgorithm, sal_Int32 nDigestID) +{ + OUString aRet; + + if (eAlgorithm == svl::crypto::SignatureMethodAlgorithm::ECDSA) + { + switch (nDigestID) + { + case css::xml::crypto::DigestID::SHA1: + aRet = ALGO_ECDSASHA1; + break; + case css::xml::crypto::DigestID::SHA256: + aRet = ALGO_ECDSASHA256; + break; + case css::xml::crypto::DigestID::SHA512: + aRet = ALGO_ECDSASHA512; + break; + default: + aRet = ALGO_ECDSASHA1; + break; + } + } + if (!aRet.isEmpty()) + return aRet; + + switch (nDigestID) + { + case css::xml::crypto::DigestID::SHA1: + return ALGO_RSASHA1; + case css::xml::crypto::DigestID::SHA256: + return ALGO_RSASHA256; + case css::xml::crypto::DigestID::SHA512: + return ALGO_RSASHA512; + default: + return ALGO_RSASHA1; + } +} +} + +XSecController::XSecController( css::uno::Reference<css::uno::XComponentContext> xCtx ) + : mxCtx(std::move(xCtx)) + , m_nNextSecurityId(1) + , m_bIsPreviousNodeInitializable(false) + , m_bIsSAXEventKeeperConnected(false) + , m_bIsCollectingElement(false) + , m_bIsBlocking(false) + , m_eStatusOfSecurityComponents(InitializationState::UNINITIALIZED) + , m_bIsSAXEventKeeperSticky(false) + , m_nReservedSignatureId(0) + , m_bVerifyCurrentSignature(false) +{ +} + +XSecController::~XSecController() +{ +} + + +/* + * private methods + */ +int XSecController::findSignatureInfor( sal_Int32 nSecurityId) const +/****** XSecController/findSignatureInfor ************************************* + * + * NAME + * findSignatureInfor -- find SignatureInformation struct for a particular + * signature + * + * SYNOPSIS + * index = findSignatureInfor( nSecurityId ); + * + * INPUTS + * nSecurityId - the signature's id + * + * RESULT + * index - the index of the signature, or -1 when no such signature + * existing + ******************************************************************************/ +{ + 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 + * + * FUNCTION + * Creates xml security components, including: + * 1. an xml signature bridge component + * 2. an XMLDocumentWrapper component + * 3. a SAXEventKeeper component + ******************************************************************************/ +{ + /* + * marks all security components are not available. + */ + m_eStatusOfSecurityComponents = InitializationState::FAILTOINITIALIZED; + m_xXMLSignature = nullptr; + m_xXMLDocumentWrapper = nullptr; + m_xSAXEventKeeper = nullptr; + + css::uno::Reference< css::lang::XMultiComponentFactory > xMCF( mxCtx->getServiceManager() ); + +#if HAVE_FEATURE_GPGME + uno::Reference< lang::XServiceInfo > xServiceInfo( m_xSecurityContext, css::uno::UNO_QUERY ); + if (xServiceInfo->getImplementationName() == "com.sun.star.xml.security.gpg.XMLSecurityContext_GpgImpl") + m_xXMLSignature.set(new XMLSignature_GpgImpl()); + else // xmlsec or mscrypt +#endif + m_xXMLSignature.set(xMCF->createInstanceWithContext("com.sun.star.xml.crypto.XMLSignature", mxCtx), css::uno::UNO_QUERY); + + bool bSuccess = m_xXMLSignature.is(); + if ( bSuccess ) + /* + * XMLSignature created successfully. + */ + m_xXMLDocumentWrapper = new XMLDocumentWrapper_XmlSecImpl(); + + bSuccess &= m_xXMLDocumentWrapper.is(); + if ( bSuccess ) + m_xSAXEventKeeper = new SAXEventKeeperImpl(); + + bSuccess &= m_xSAXEventKeeper.is(); + + if (!bSuccess) + /* + * SAXEventKeeper created successfully. + */ + return; + + css::uno::Sequence <css::uno::Any> arg{ css::uno::Any( + uno::Reference<xml::wrapper::XXMLDocumentWrapper>(m_xXMLDocumentWrapper)) }; + m_xSAXEventKeeper->initialize(arg); + + css::uno::Reference< css::xml::crypto::sax::XSAXEventKeeperStatusChangeListener > + xStatusChangeListener = this; + + m_xSAXEventKeeper->addSAXEventKeeperStatusChangeListener( xStatusChangeListener ); + + m_eStatusOfSecurityComponents = InitializationState::INITIALIZED; +} + +bool XSecController::chainOn() +/****** XSecController/chainOn ************************************************ + * + * NAME + * chainOn -- tries to connect the SAXEventKeeper with the SAX chain. + * + * SYNOPSIS + * bJustChainingOn = chainOn(); + * + * 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 buffered by the + * SAXEventKeeper has the same structure with the original document. + * + * 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 a 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. + ******************************************************************************/ +{ + bool rc = false; + + if (!m_bIsSAXEventKeeperSticky && !m_bIsSAXEventKeeperConnected) + { + if ( m_eStatusOfSecurityComponents == InitializationState::UNINITIALIZED ) + { + createXSecComponent(); + } + + if ( m_eStatusOfSecurityComponents == InitializationState::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( nullptr ); + + css::uno::Reference< css::xml::sax::XDocumentHandler > xSEKHandler(m_xSAXEventKeeper); + + /* + * connects the previous document handler on the SAX chain + */ + if ( m_xPreviousNodeOnSAXChain.is() ) + { + if ( m_bIsPreviousNodeInitializable ) + { + css::uno::Reference< css::lang::XInitialization > xInitialization + (m_xPreviousNodeOnSAXChain, css::uno::UNO_QUERY); + + xInitialization->initialize({ css::uno::Any(xSEKHandler) }); + } + else + { + css::uno::Reference< css::xml::sax::XParser > xParser + (m_xPreviousNodeOnSAXChain, css::uno::UNO_QUERY); + xParser->setDocumentHandler( xSEKHandler ); + } + } + + /* + * connects the next document handler on the SAX chain + */ + m_xSAXEventKeeper->setNextHandler(uno::Reference<xml::sax::XDocumentHandler>()); + + m_bIsSAXEventKeeperConnected = true; + + rc = true; + } + } + + return rc; +} + +void XSecController::chainOff() +/****** XSecController/chainOff *********************************************** + * + * NAME + * chainOff -- disconnects the SAXEventKeeper from the SAX chain. + ******************************************************************************/ +{ + if (m_bIsSAXEventKeeperSticky ) + return; + + if (!m_bIsSAXEventKeeperConnected) + return; + + m_xSAXEventKeeper->setNextHandler( nullptr ); + + if ( m_xPreviousNodeOnSAXChain.is() ) + { + if ( m_bIsPreviousNodeInitializable ) + { + css::uno::Reference< css::lang::XInitialization > xInitialization + (m_xPreviousNodeOnSAXChain, css::uno::UNO_QUERY); + + css::uno::Sequence<css::uno::Any> aArgs{ css::uno::Any( + uno::Reference<xml::sax::XDocumentHandler>()) }; + xInitialization->initialize(aArgs); + } + else + { + css::uno::Reference< css::xml::sax::XParser > xParser(m_xPreviousNodeOnSAXChain, css::uno::UNO_QUERY); + xParser->setDocumentHandler(uno::Reference<xml::sax::XDocumentHandler>()); + } + } + + 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. + ******************************************************************************/ +{ + if ( m_bIsCollectingElement || m_bIsBlocking ) + { + chainOn(); + } + else + { + chainOff(); + } +} + +void XSecController::initializeSAXChain() +/****** XSecController/initializeSAXChain ************************************* + * + * NAME + * initializeSAXChain -- initializes the SAX chain according to the + * current setting. + * + * 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. + ******************************************************************************/ +{ + m_bIsSAXEventKeeperConnected = false; + m_bIsCollectingElement = false; + m_bIsBlocking = false; + + chainOff(); +} + +css::uno::Reference< css::io::XInputStream > + XSecController::getObjectInputStream( const OUString& objectURL ) +/****** XSecController/getObjectInputStream ************************************ + * + * NAME + * getObjectInputStream -- get a XInputStream interface from a SotStorage + * + * SYNOPSIS + * xInputStream = getObjectInputStream( objectURL ); + * + * INPUTS + * objectURL - the object uri + * + * RESULT + * xInputStream - the XInputStream interface + ******************************************************************************/ +{ + css::uno::Reference< css::io::XInputStream > xObjectInputStream; + + SAL_WARN_IF( !m_xUriBinding.is(), "xmlsecurity.helper", "Need XUriBinding!" ); + + xObjectInputStream = m_xUriBinding->getUriBinding(objectURL); + + return xObjectInputStream; +} + +/* + * public methods + */ + +sal_Int32 XSecController::getNewSecurityId( ) +{ + sal_Int32 nId = m_nNextSecurityId; + m_nNextSecurityId++; + return nId; +} + +void XSecController::startMission(const rtl::Reference<UriBindingHelper>& xUriBinding, const css::uno::Reference< css::xml::crypto::XXMLSecurityContext >& xSecurityContext ) +/****** XSecController/startMission ******************************************* + * + * NAME + * startMission -- starts a new security mission. + * + * 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 + ******************************************************************************/ +{ + m_xUriBinding = xUriBinding; + + m_eStatusOfSecurityComponents = InitializationState::UNINITIALIZED; + m_xSecurityContext = xSecurityContext; + + m_vInternalSignatureInformations.clear(); + + m_bVerifyCurrentSignature = false; +} + +void XSecController::setSAXChainConnector(const css::uno::Reference< css::lang::XInitialization >& xInitialization) +/****** XSecController/setSAXChainConnector *********************************** + * + * NAME + * setSAXChainConnector -- configures the components which will + * collaborate with the SAXEventKeeper on the SAX chain. + * + * SYNOPSIS + * setSAXChainConnector(xInitialization); + * + * INPUTS + * xInitialization - the previous node on the SAX chain + ******************************************************************************/ +{ + m_bIsPreviousNodeInitializable = true; + m_xPreviousNodeOnSAXChain = xInitialization; + + initializeSAXChain( ); +} + +void XSecController::clearSAXChainConnector() +/****** XSecController/clearSAXChainConnector ********************************* + * + * NAME + * clearSAXChainConnector -- resets the collaborating components. + ******************************************************************************/ +{ + chainOff(); + + m_xPreviousNodeOnSAXChain = nullptr; +} + +void XSecController::endMission() +/****** XSecController/endMission ********************************************* + * + * NAME + * endMission -- forces to end all missions + * + * FUNCTION + * Deletes all signature information and forces all missions to an end. + ******************************************************************************/ +{ + sal_Int32 size = m_vInternalSignatureInformations.size(); + + for (int i=0; i<size; ++i) + { + if ( m_eStatusOfSecurityComponents == InitializationState::INITIALIZED ) + /* + * ResolvedListener only exist when the security components are created. + */ + { + css::uno::Reference< css::xml::crypto::sax::XMissionTaker > xMissionTaker + ( m_vInternalSignatureInformations[i].xReferenceResolvedListener, css::uno::UNO_QUERY ); + + /* + * asks the SignatureCreator/SignatureVerifier to release + * all resources it uses. + */ + xMissionTaker->endMission(); + } + } + + m_xUriBinding = nullptr; + m_xSecurityContext = nullptr; + + /* + * free the status change listener reference to this object + */ + if (m_xSAXEventKeeper.is()) + m_xSAXEventKeeper->addSAXEventKeeperStatusChangeListener( nullptr ); +} + +namespace +{ +void writeUnsignedProperties( + const css::uno::Reference<css::xml::sax::XDocumentHandler>& xDocumentHandler, + const SignatureInformation& signatureInfo) +{ + { + rtl::Reference<comphelper::AttributeList> pAttributeList(new comphelper::AttributeList()); + pAttributeList->AddAttribute("Id", "idUnsignedProperties_" + signatureInfo.ouSignatureId); + xDocumentHandler->startElement("xd:UnsignedProperties", uno::Reference<xml::sax::XAttributeList>(pAttributeList)); + } + + { + xDocumentHandler->startElement("xd:UnsignedSignatureProperties", uno::Reference<xml::sax::XAttributeList>(new comphelper::AttributeList())); + + { + xDocumentHandler->startElement("xd:CertificateValues", uno::Reference<xml::sax::XAttributeList>(new comphelper::AttributeList())); + + { + for (const auto& i: signatureInfo.maEncapsulatedX509Certificates) + { + xDocumentHandler->startElement("xd:EncapsulatedX509Certificate", uno::Reference<xml::sax::XAttributeList>(new comphelper::AttributeList())); + xDocumentHandler->characters(i); + xDocumentHandler->endElement("xd:EncapsulatedX509Certificate"); + } + } + + xDocumentHandler->endElement("xd:CertificateValues"); + } + + xDocumentHandler->endElement("xd:UnsignedSignatureProperties"); + } + + xDocumentHandler->endElement("xd:UnsignedProperties"); +} + +} + +void XSecController::exportSignature( + const css::uno::Reference<css::xml::sax::XDocumentHandler>& xDocumentHandler, + const SignatureInformation& signatureInfo, + bool bXAdESCompliantIfODF ) +/****** XSecController/exportSignature **************************************** + * + * NAME + * exportSignature -- export a signature structure to an XDocumentHandler + * + * SYNOPSIS + * exportSignature( xDocumentHandler, signatureInfo); + * + * INPUTS + * xDocumentHandler - the document handler to receive the signature + * signatureInfo - signature to be exported + ******************************************************************************/ +{ + const SignatureReferenceInformations& vReferenceInfors = signatureInfo.vSignatureReferenceInfors; + rtl::Reference<comphelper::AttributeList> pAttributeList; + + /* + * Write Signature element + */ + pAttributeList = new comphelper::AttributeList(); + pAttributeList->AddAttribute( + "xmlns", + NS_XMLDSIG); + + if (!signatureInfo.ouSignatureId.isEmpty()) + { + pAttributeList->AddAttribute( + "Id", + signatureInfo.ouSignatureId); + } + + xDocumentHandler->startElement( "Signature", pAttributeList); + { + /* Write SignedInfo element */ + xDocumentHandler->startElement( + "SignedInfo", + css::uno::Reference< css::xml::sax::XAttributeList > (new comphelper::AttributeList())); + { + /* Write CanonicalizationMethod element */ + pAttributeList = new comphelper::AttributeList(); + pAttributeList->AddAttribute( + "Algorithm", + ALGO_C14N); + xDocumentHandler->startElement( "CanonicalizationMethod", pAttributeList ); + xDocumentHandler->endElement( "CanonicalizationMethod" ); + + /* Write SignatureMethod element */ + pAttributeList = new comphelper::AttributeList(); + + // TODO: actually roundtrip this value from parsing documentsignatures.xml - entirely + // broken to assume this would in any way relate to the 1st reference's digest algo + + // Assume that all Reference elements use the same DigestMethod:Algorithm, and that the + // SignatureMethod:Algorithm should be the corresponding one. + pAttributeList->AddAttribute( + "Algorithm", + getSignatureURI(signatureInfo.eAlgorithmID, vReferenceInfors[0].nDigestID)); + xDocumentHandler->startElement( "SignatureMethod", pAttributeList ); + xDocumentHandler->endElement( "SignatureMethod" ); + + /* Write Reference element */ + int j; + int refNum = vReferenceInfors.size(); + + for(j=0; j<refNum; ++j) + { + const SignatureReferenceInformation& refInfor = vReferenceInfors[j]; + + pAttributeList = new comphelper::AttributeList(); + if ( refInfor.nType != SignatureReferenceType::SAMEDOCUMENT ) + /* + * stream reference + */ + { + pAttributeList->AddAttribute( + "URI", + refInfor.ouURI); + } + else + /* + * same-document reference + */ + { + if (refInfor.ouURI.startsWith("idSignedProperties")) + { + pAttributeList->AddAttribute("URI", "#idSignedProperties_" + signatureInfo.ouSignatureId); + if (bXAdESCompliantIfODF && !refInfor.ouType.isEmpty()) + { + // The reference which points to the SignedProperties + // shall have this specific type. + pAttributeList->AddAttribute("Type", refInfor.ouType); + } + } + else + { + pAttributeList->AddAttribute( + "URI", + "#" + refInfor.ouURI); + } + } + + xDocumentHandler->startElement( "Reference", pAttributeList ); + { + /* Write Transforms element */ + if (refInfor.nType == SignatureReferenceType::XMLSTREAM) + /* + * xml stream, so c14n transform is needed + */ + { + xDocumentHandler->startElement( + "Transforms", + css::uno::Reference< css::xml::sax::XAttributeList > (new comphelper::AttributeList())); + { + pAttributeList = new comphelper::AttributeList(); + pAttributeList->AddAttribute( + "Algorithm", + ALGO_C14N); + xDocumentHandler->startElement( + "Transform", + pAttributeList ); + xDocumentHandler->endElement( "Transform" ); + } + xDocumentHandler->endElement( "Transforms" ); + } + + /* Write DigestMethod element */ + pAttributeList = new comphelper::AttributeList(); + pAttributeList->AddAttribute( + "Algorithm", + getDigestURI(refInfor.nDigestID)); + xDocumentHandler->startElement( + "DigestMethod", + pAttributeList ); + xDocumentHandler->endElement( "DigestMethod" ); + + /* Write DigestValue element */ + xDocumentHandler->startElement( + "DigestValue", + css::uno::Reference< css::xml::sax::XAttributeList > (new comphelper::AttributeList())); + xDocumentHandler->characters( refInfor.ouDigestValue ); + xDocumentHandler->endElement( "DigestValue" ); + } + xDocumentHandler->endElement( "Reference" ); + } + } + xDocumentHandler->endElement( "SignedInfo" ); + + /* Write SignatureValue element */ + xDocumentHandler->startElement( + "SignatureValue", + css::uno::Reference< css::xml::sax::XAttributeList > (new comphelper::AttributeList())); + xDocumentHandler->characters( signatureInfo.ouSignatureValue ); + xDocumentHandler->endElement( "SignatureValue" ); + + /* Write KeyInfo element */ + xDocumentHandler->startElement( + "KeyInfo", + css::uno::Reference< css::xml::sax::XAttributeList > (new comphelper::AttributeList())); + { + // GPG or X509 key? + if (!signatureInfo.ouGpgCertificate.isEmpty()) + { + pAttributeList = new comphelper::AttributeList(); + pAttributeList->AddAttribute("xmlns:loext", NS_LOEXT); + /* Write PGPData element */ + xDocumentHandler->startElement( + "PGPData", + pAttributeList); + { + /* Write keyid element */ + xDocumentHandler->startElement( + "PGPKeyID", + css::uno::Reference< css::xml::sax::XAttributeList > (new comphelper::AttributeList())); + xDocumentHandler->characters(signatureInfo.ouGpgKeyID); + xDocumentHandler->endElement( "PGPKeyID" ); + + /* Write PGPKeyPacket element */ + if (!signatureInfo.ouGpgCertificate.isEmpty()) + { + xDocumentHandler->startElement( + "PGPKeyPacket", + css::uno::Reference< css::xml::sax::XAttributeList > (new comphelper::AttributeList())); + xDocumentHandler->characters( signatureInfo.ouGpgCertificate ); + xDocumentHandler->endElement( "PGPKeyPacket" ); + } + + /* Write PGPOwner element */ + xDocumentHandler->startElement( + "loext:PGPOwner", + css::uno::Reference< css::xml::sax::XAttributeList >(new comphelper::AttributeList())); + xDocumentHandler->characters( signatureInfo.ouGpgOwner ); + xDocumentHandler->endElement( "loext:PGPOwner" ); + } + xDocumentHandler->endElement( "PGPData" ); + } + else + { + assert(signatureInfo.GetSigningCertificate()); + for (auto const& rData : signatureInfo.X509Datas) + { + /* Write X509Data element */ + xDocumentHandler->startElement( + "X509Data", + css::uno::Reference< css::xml::sax::XAttributeList > (new comphelper::AttributeList())); + { + for (auto const& it : rData) + { + /* Write X509IssuerSerial element */ + xDocumentHandler->startElement( + "X509IssuerSerial", + css::uno::Reference< css::xml::sax::XAttributeList > (new comphelper::AttributeList())); + { + /* Write X509IssuerName element */ + xDocumentHandler->startElement( + "X509IssuerName", + css::uno::Reference< css::xml::sax::XAttributeList > (new comphelper::AttributeList())); + xDocumentHandler->characters(it.X509IssuerName); + xDocumentHandler->endElement( "X509IssuerName" ); + + /* Write X509SerialNumber element */ + xDocumentHandler->startElement( + "X509SerialNumber", + css::uno::Reference< css::xml::sax::XAttributeList > (new comphelper::AttributeList())); + xDocumentHandler->characters(it.X509SerialNumber); + xDocumentHandler->endElement( "X509SerialNumber" ); + } + xDocumentHandler->endElement( "X509IssuerSerial" ); + + /* Write X509Certificate element */ + if (!it.X509Certificate.isEmpty()) + { + xDocumentHandler->startElement( + "X509Certificate", + css::uno::Reference< css::xml::sax::XAttributeList > (new comphelper::AttributeList())); + xDocumentHandler->characters(it.X509Certificate); + xDocumentHandler->endElement( "X509Certificate" ); + } + } + } + xDocumentHandler->endElement( "X509Data" ); + } + } + } + xDocumentHandler->endElement( "KeyInfo" ); + + OUString sDate; + + /* Write Object element */ + xDocumentHandler->startElement( + "Object", + css::uno::Reference< css::xml::sax::XAttributeList > (new comphelper::AttributeList())); + { + /* Write SignatureProperties element */ + xDocumentHandler->startElement( + "SignatureProperties", + css::uno::Reference< css::xml::sax::XAttributeList > (new comphelper::AttributeList())); + { + /* Write SignatureProperty element */ + pAttributeList = new comphelper::AttributeList(); + pAttributeList->AddAttribute( + "Id", + signatureInfo.ouDateTimePropertyId); + pAttributeList->AddAttribute( + "Target", + "#" + signatureInfo.ouSignatureId); + xDocumentHandler->startElement( + "SignatureProperty", + pAttributeList); + { + /* Write timestamp element */ + + pAttributeList = new comphelper::AttributeList(); + pAttributeList->AddAttribute( + "xmlns:dc", + NS_DC); + + xDocumentHandler->startElement( + "dc:date", + pAttributeList); + + OUStringBuffer buffer; + //If the xml signature was already contained in the document, + //then we use the original date and time string, rather than the + //converted one. This avoids writing a different string due to + //e.g. rounding issues and thus breaking the signature. + if (!signatureInfo.ouDateTime.isEmpty()) + buffer = signatureInfo.ouDateTime; + else + { + buffer = utl::toISO8601(signatureInfo.stDateTime); + // xsd:dateTime must use period as separator for fractional seconds, while + // utl::toISO8601 uses comma (as allowed, and even recommended, by ISO8601). + buffer.replace(',', '.'); + } + sDate = buffer.makeStringAndClear(); + xDocumentHandler->characters( sDate ); + + xDocumentHandler->endElement( + "dc:date"); + } + xDocumentHandler->endElement( "SignatureProperty" ); + } + + // Write signature description. + if (!signatureInfo.ouDescription.isEmpty()) + { + // SignatureProperty element. + pAttributeList = new comphelper::AttributeList(); + pAttributeList->AddAttribute("Id", signatureInfo.ouDescriptionPropertyId); + pAttributeList->AddAttribute("Target", "#" + signatureInfo.ouSignatureId); + xDocumentHandler->startElement("SignatureProperty", pAttributeList); + + { + // Description element. + pAttributeList = new comphelper::AttributeList(); + pAttributeList->AddAttribute("xmlns:dc", NS_DC); + + xDocumentHandler->startElement("dc:description", pAttributeList); + xDocumentHandler->characters(signatureInfo.ouDescription); + xDocumentHandler->endElement("dc:description"); + } + + xDocumentHandler->endElement("SignatureProperty"); + } + + xDocumentHandler->endElement( "SignatureProperties" ); + } + xDocumentHandler->endElement( "Object" ); + + // In XAdES, write another Object element for the QualifyingProperties + if (bXAdESCompliantIfODF) + { + pAttributeList = new comphelper::AttributeList(); + pAttributeList->AddAttribute("xmlns:xd", NS_XD); + xDocumentHandler->startElement( + "Object", + pAttributeList); + { + pAttributeList = new comphelper::AttributeList(); + pAttributeList->AddAttribute("Target", "#" + signatureInfo.ouSignatureId); + xDocumentHandler->startElement( + "xd:QualifyingProperties", + pAttributeList); + DocumentSignatureHelper::writeSignedProperties(xDocumentHandler, signatureInfo, sDate, true); + writeUnsignedProperties(xDocumentHandler, signatureInfo); + xDocumentHandler->endElement( "xd:QualifyingProperties" ); + } + xDocumentHandler->endElement( "Object" ); + } + } + xDocumentHandler->endElement( "Signature" ); +} + +void XSecController::exportOOXMLSignature(const uno::Reference<embed::XStorage>& xRootStorage, const uno::Reference<xml::sax::XDocumentHandler>& xDocumentHandler, const SignatureInformation& rInformation) +{ + OOXMLSecExporter aExporter(mxCtx, xRootStorage, xDocumentHandler, rInformation); + aExporter.writeSignature(); +} + +void XSecController::UpdateSignatureInformation(sal_Int32 const nSecurityId, + std::vector<SignatureInformation::X509Data> && rDatas) +{ + int const nIndex = findSignatureInfor(nSecurityId); + assert(nIndex != -1); // nothing should touch this between parsing and verify + m_vInternalSignatureInformations[nIndex].signatureInfor.X509Datas = std::move(rDatas); +} + +SignatureInformation XSecController::getSignatureInformation( sal_Int32 nSecurityId ) const +{ + SignatureInformation aInf( 0 ); + int nIndex = findSignatureInfor(nSecurityId); + SAL_WARN_IF( nIndex == -1, "xmlsecurity.helper", "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; +} + +/* + * XSAXEventKeeperStatusChangeListener + */ + +void SAL_CALL XSecController::blockingStatusChanged( sal_Bool isBlocking ) +{ + m_bIsBlocking = isBlocking; + checkChainingStatus(); +} + +void SAL_CALL XSecController::collectionStatusChanged( + sal_Bool isInsideCollectedElement ) +{ + m_bIsCollectingElement = isInsideCollectedElement; + checkChainingStatus(); +} + +void SAL_CALL XSecController::bufferStatusChanged( sal_Bool /*isBufferEmpty*/) +{ + +} + +/* + * XSignatureCreationResultListener + */ +void SAL_CALL XSecController::signatureCreated( sal_Int32 securityId, css::xml::crypto::SecurityOperationStatus nResult ) +{ + int index = findSignatureInfor(securityId); + assert(index != -1 && "Signature Not Found!"); + SignatureInformation& signatureInfor = m_vInternalSignatureInformations.at(index).signatureInfor; + signatureInfor.nStatus = nResult; +} + +/* + * XSignatureVerifyResultListener + */ +void SAL_CALL XSecController::signatureVerified( sal_Int32 securityId, css::xml::crypto::SecurityOperationStatus nResult ) +{ + int index = findSignatureInfor(securityId); + assert(index != -1 && "Signature Not Found!"); + SignatureInformation& signatureInfor = m_vInternalSignatureInformations.at(index).signatureInfor; + signatureInfor.nStatus = nResult; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/helper/xsecparser.cxx b/xmlsecurity/source/helper/xsecparser.cxx new file mode 100644 index 0000000000..af3562f46c --- /dev/null +++ b/xmlsecurity/source/helper/xsecparser.cxx @@ -0,0 +1,1632 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "xsecparser.hxx" +#include <xsecctl.hxx> +#include <xmlsignaturehelper.hxx> + +#include <xmloff/xmlnamespace.hxx> +#include <xmloff/xmltkmap.hxx> +#include <xmloff/xmlimp.hxx> + +#include <com/sun/star/xml/sax/SAXException.hpp> +#include <cppuhelper/exc_hlp.hxx> +#include <sal/log.hxx> + +class XSecParser::Context +{ + protected: + friend class XSecParser; + XSecParser & m_rParser; + private: + std::optional<SvXMLNamespaceMap> m_pOldNamespaceMap; + + public: + Context(XSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap) + : m_rParser(rParser) + , m_pOldNamespaceMap(std::move(pOldNamespaceMap)) + { + } + + virtual ~Context() = default; + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& /*xAttrs*/) + { + } + + virtual void EndElement() + { + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + sal_uInt16 const /*nNamespace*/, OUString const& /*rName*/); + + virtual void Characters(OUString const& /*rChars*/) + { + } +}; + +// it's possible that an unsupported element has an Id attribute and a +// ds:Reference digesting it - probably this means XSecController needs to know +// about it. (For known elements, the Id attribute is only processed according +// to the schema.) +class XSecParser::UnknownContext + : public XSecParser::Context +{ + public: + UnknownContext(XSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + m_rParser.HandleIdAttr(xAttrs); + } +}; + +auto XSecParser::Context::CreateChildContext( + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + sal_uInt16 const /*nNamespace*/, OUString const& /*rName*/) +-> std::unique_ptr<Context> +{ + // default: create new base context + return std::make_unique<UnknownContext>(m_rParser, std::move(pOldNamespaceMap)); +} + +/** +note: anything in ds:Object should be trusted *only* if there is a ds:Reference + to it so it is signed (exception: the xades:EncapsulatedX509Certificate). + ds:SignedInfo precedes all ds:Object. + + There may be multiple ds:Signature for purpose of counter-signatures + but the way XAdES describes these, only the ds:SignatureValue element + would be referenced, so requiring a ds:Reference for anything in + ds:Object shouldn't cause issues. + */ +class XSecParser::ReferencedContextImpl + : public XSecParser::Context +{ + protected: + bool m_isReferenced; + + public: + ReferencedContextImpl(XSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + bool const isReferenced) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_isReferenced(isReferenced) + { + } + + OUString CheckIdAttrReferenced(css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) + { + OUString const id(m_rParser.HandleIdAttr(xAttrs)); + if (!id.isEmpty() && m_rParser.m_pXSecController->haveReferenceForId(id)) + { + m_isReferenced = true; + } + return id; + } +}; + +class XSecParser::LoPGPOwnerContext + : public XSecParser::Context +{ + private: + OUString m_Value; + + public: + LoPGPOwnerContext(XSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void EndElement() override + { + m_rParser.m_pXSecController->setGpgOwner(m_Value); + } + + virtual void Characters(OUString const& rChars) override + { + m_Value += rChars; + } +}; + +class XSecParser::DsPGPKeyPacketContext + : public XSecParser::Context +{ + private: + OUString m_Value; + + public: + DsPGPKeyPacketContext(XSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void EndElement() override + { + m_rParser.m_pXSecController->setGpgCertificate(m_Value); + } + + virtual void Characters(OUString const& rChars) override + { + m_Value += rChars; + } +}; + +class XSecParser::DsPGPKeyIDContext + : public XSecParser::Context +{ + private: + OUString m_Value; + + public: + DsPGPKeyIDContext(XSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void EndElement() override + { + m_rParser.m_pXSecController->setGpgKeyID(m_Value); + } + + virtual void Characters(OUString const& rChars) override + { + m_Value += rChars; + } +}; + +class XSecParser::DsPGPDataContext + : public XSecParser::Context +{ + public: + DsPGPDataContext(XSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& /*xAttrs*/) override + { + m_rParser.m_pXSecController->switchGpgSignature(); + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "PGPKeyID") + { + return std::make_unique<DsPGPKeyIDContext>(m_rParser, std::move(pOldNamespaceMap)); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "PGPKeyPacket") + { + return std::make_unique<DsPGPKeyPacketContext>(m_rParser, std::move(pOldNamespaceMap)); + } + if (nNamespace == XML_NAMESPACE_LO_EXT && rName == "PGPOwner") + { + return std::make_unique<LoPGPOwnerContext>(m_rParser, std::move(pOldNamespaceMap)); + } + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class XSecParser::DsX509CertificateContext + : public XSecParser::Context +{ + private: + OUString & m_rValue; + + public: + DsX509CertificateContext(XSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + OUString& rValue) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rValue(rValue) + { + } + + virtual void Characters(OUString const& rChars) override + { + m_rValue += rChars; + } +}; + +class XSecParser::DsX509SerialNumberContext + : public XSecParser::Context +{ + private: + OUString & m_rValue; + + public: + DsX509SerialNumberContext(XSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + OUString& rValue) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rValue(rValue) + { + } + + virtual void Characters(OUString const& rChars) override + { + m_rValue += rChars; + } +}; + +class XSecParser::DsX509IssuerNameContext + : public XSecParser::Context +{ + private: + OUString & m_rValue; + + public: + DsX509IssuerNameContext(XSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + OUString& rValue) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rValue(rValue) + { + } + + virtual void Characters(OUString const& rChars) override + { + m_rValue += rChars; + } +}; + +class XSecParser::DsX509IssuerSerialContext + : public XSecParser::Context +{ + private: + OUString & m_rX509IssuerName; + OUString & m_rX509SerialNumber; + + public: + DsX509IssuerSerialContext(XSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + OUString& rIssuerName, OUString& rSerialNumber) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rX509IssuerName(rIssuerName) + , m_rX509SerialNumber(rSerialNumber) + { + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "X509IssuerName") + { + return std::make_unique<DsX509IssuerNameContext>(m_rParser, std::move(pOldNamespaceMap), m_rX509IssuerName); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "X509SerialNumber") + { + return std::make_unique<DsX509SerialNumberContext>(m_rParser, std::move(pOldNamespaceMap), m_rX509SerialNumber); + } + // missing: ds:X509SKI, ds:X509SubjectName, ds:X509CRL + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +/// can't be sure what is supposed to happen here because the spec is clear as mud +class XSecParser::DsX509DataContext + : public XSecParser::Context +{ + private: + // sigh... "No ordering is implied by the above constraints." + // so store the ball of mud in vectors and try to figure it out later. + std::vector<std::pair<OUString, OUString>> m_X509IssuerSerials; + std::vector<OUString> m_X509Certificates; + + public: + DsX509DataContext(XSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void EndElement() override + { + m_rParser.m_pXSecController->setX509Data(m_X509IssuerSerials, m_X509Certificates); + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "X509IssuerSerial") + { + m_X509IssuerSerials.emplace_back(); + return std::make_unique<DsX509IssuerSerialContext>(m_rParser, std::move(pOldNamespaceMap), m_X509IssuerSerials.back().first, m_X509IssuerSerials.back().second); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "X509Certificate") + { + m_X509Certificates.emplace_back(); + return std::make_unique<DsX509CertificateContext>(m_rParser, std::move(pOldNamespaceMap), m_X509Certificates.back()); + } + // missing: ds:X509SKI, ds:X509SubjectName, ds:X509CRL + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class XSecParser::DsKeyInfoContext + : public XSecParser::Context +{ + public: + DsKeyInfoContext(XSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + m_rParser.HandleIdAttr(xAttrs); + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "X509Data") + { + return std::make_unique<DsX509DataContext>(m_rParser, std::move(pOldNamespaceMap)); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "PGPData") + { + return std::make_unique<DsPGPDataContext>(m_rParser, std::move(pOldNamespaceMap)); + } + // missing: ds:KeyName, ds:KeyValue, ds:RetrievalMethod, ds:SPKIData, ds:MgmtData + // (old code would read ds:Transform inside ds:RetrievalMethod but + // presumably that was a bug) + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } + +}; + +class XSecParser::DsSignatureValueContext + : public XSecParser::Context +{ + private: + OUString m_Value; + + public: + DsSignatureValueContext(XSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + m_rParser.HandleIdAttr(xAttrs); + } + + virtual void EndElement() override + { + m_rParser.m_pXSecController->setSignatureValue(m_Value); + } + + virtual void Characters(OUString const& rChars) override + { + m_Value += rChars; + } +}; + +class XSecParser::DsDigestValueContext + : public XSecParser::Context +{ + private: + OUString & m_rValue; + + public: + DsDigestValueContext(XSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + OUString& rValue) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rValue(rValue) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& /*xAttrs*/) override + { + m_rValue.clear(); + } + + virtual void Characters(OUString const& rChars) override + { + m_rValue += rChars; + } +}; + +class XSecParser::DsDigestMethodContext + : public XSecParser::Context +{ + private: + sal_Int32 & m_rReferenceDigestID; + + public: + DsDigestMethodContext(XSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + sal_Int32& rReferenceDigestID) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rReferenceDigestID(rReferenceDigestID) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + OUString ouAlgorithm = xAttrs->getValueByName("Algorithm"); + + SAL_WARN_IF( ouAlgorithm.isEmpty(), "xmlsecurity.helper", "no Algorithm in Reference" ); + if (ouAlgorithm.isEmpty()) + return; + + SAL_WARN_IF( ouAlgorithm != ALGO_XMLDSIGSHA1 + && ouAlgorithm != ALGO_XMLDSIGSHA256 + && ouAlgorithm != ALGO_XMLDSIGSHA512, + "xmlsecurity.helper", "Algorithm neither SHA1, SHA256 nor SHA512"); + if (ouAlgorithm == ALGO_XMLDSIGSHA1) + m_rReferenceDigestID = css::xml::crypto::DigestID::SHA1; + else if (ouAlgorithm == ALGO_XMLDSIGSHA256) + m_rReferenceDigestID = css::xml::crypto::DigestID::SHA256; + else if (ouAlgorithm == ALGO_XMLDSIGSHA512) + m_rReferenceDigestID = css::xml::crypto::DigestID::SHA512; + else + m_rReferenceDigestID = 0; + } +}; + +class XSecParser::DsTransformContext + : public XSecParser::Context +{ + private: + bool & m_rIsC14N; + + public: + DsTransformContext(XSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + bool& rIsC14N) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rIsC14N(rIsC14N) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + OUString ouAlgorithm = xAttrs->getValueByName("Algorithm"); + + if (ouAlgorithm == ALGO_C14N) + /* + * a xml stream + */ + { + m_rIsC14N = true; + } + } +}; + +class XSecParser::DsTransformsContext + : public XSecParser::Context +{ + private: + bool & m_rIsC14N; + + public: + DsTransformsContext(XSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + bool& rIsC14N) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rIsC14N(rIsC14N) + { + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "Transform") + { + return std::make_unique<DsTransformContext>(m_rParser, std::move(pOldNamespaceMap), m_rIsC14N); + } + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class XSecParser::DsReferenceContext + : public XSecParser::Context +{ + private: + OUString m_URI; + OUString m_Type; + OUString m_DigestValue; + bool m_IsC14N = false; + // Relevant for ODF. The digest algorithm selected by the DigestMethod + // element's Algorithm attribute. @see css::xml::crypto::DigestID. + sal_Int32 m_nReferenceDigestID = css::xml::crypto::DigestID::SHA1; + + public: + DsReferenceContext(XSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + m_rParser.HandleIdAttr(xAttrs); + + m_URI = xAttrs->getValueByName("URI"); + SAL_WARN_IF(m_URI.isEmpty(), "xmlsecurity.helper", "URI is empty"); + // Remember the type of this reference. + m_Type = xAttrs->getValueByName("Type"); + } + + virtual void EndElement() override + { + if (m_URI.startsWith("#")) + { + /* + * remove the first character '#' from the attribute value + */ + m_rParser.m_pXSecController->addReference(m_URI.copy(1), m_nReferenceDigestID, m_Type); + } + else + { + if (m_IsC14N) // this is determined by nested ds:Transform + { + m_rParser.m_pXSecController->addStreamReference(m_URI, false, m_nReferenceDigestID); + } + else + /* + * it must be an octet stream + */ + { + m_rParser.m_pXSecController->addStreamReference(m_URI, true, m_nReferenceDigestID); + } + } + + m_rParser.m_pXSecController->setDigestValue(m_nReferenceDigestID, m_DigestValue); + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "Transforms") + { + return std::make_unique<DsTransformsContext>(m_rParser, std::move(pOldNamespaceMap), m_IsC14N); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "DigestMethod") + { + return std::make_unique<DsDigestMethodContext>(m_rParser, std::move(pOldNamespaceMap), m_nReferenceDigestID); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "DigestValue") + { + return std::make_unique<DsDigestValueContext>(m_rParser, std::move(pOldNamespaceMap), m_DigestValue); + } + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class XSecParser::DsSignatureMethodContext + : public XSecParser::Context +{ + public: + DsSignatureMethodContext(XSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + OUString ouAlgorithm = xAttrs->getValueByName("Algorithm"); + if (ouAlgorithm == ALGO_ECDSASHA1 || ouAlgorithm == ALGO_ECDSASHA256 + || ouAlgorithm == ALGO_ECDSASHA512) + { + m_rParser.m_pXSecController->setSignatureMethod(svl::crypto::SignatureMethodAlgorithm::ECDSA); + } + } +}; + +class XSecParser::DsSignedInfoContext + : public XSecParser::Context +{ + public: + DsSignedInfoContext(XSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + m_rParser.HandleIdAttr(xAttrs); + } + + virtual void EndElement() override + { + m_rParser.m_pXSecController->setReferenceCount(); + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "SignatureMethod") + { + return std::make_unique<DsSignatureMethodContext>(m_rParser, std::move(pOldNamespaceMap)); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "Reference") + { + return std::make_unique<DsReferenceContext>(m_rParser, std::move(pOldNamespaceMap)); + } + // missing: ds:CanonicalizationMethod + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class XSecParser::XadesEncapsulatedX509CertificateContext + : public XSecParser::Context +{ + private: + OUString m_Value; + + public: + XadesEncapsulatedX509CertificateContext(XSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + m_rParser.HandleIdAttr(xAttrs); + } + + virtual void EndElement() override + { + m_rParser.m_pXSecController->addEncapsulatedX509Certificate(m_Value); + } + + virtual void Characters(OUString const& rChars) override + { + m_Value += rChars; + } +}; + +class XSecParser::XadesCertificateValuesContext + : public XSecParser::Context +{ + public: + XadesCertificateValuesContext(XSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + m_rParser.HandleIdAttr(xAttrs); + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "EncapsulatedX509Certificate") + { + return std::make_unique<XadesEncapsulatedX509CertificateContext>(m_rParser, std::move(pOldNamespaceMap)); + } + // missing: xades:OtherCertificate + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class XSecParser::XadesUnsignedSignaturePropertiesContext + : public XSecParser::Context +{ + public: + XadesUnsignedSignaturePropertiesContext(XSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + m_rParser.HandleIdAttr(xAttrs); + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "CertificateValues") + { + return std::make_unique<XadesCertificateValuesContext>(m_rParser, std::move(pOldNamespaceMap)); + } + // missing: + // xades:CounterSignature + // ^ old code would read a ds:Signature inside it? + // xades:SignatureTimeStamp + // xades:CompleteCertificateRefs + // xades:CompleteRevocationRefs + // xades:AttributeCertificateRefs + // xades:AttributeRevocationRefs + // xades:SigAndRefsTimeStamp + // xades:RefsOnlyTimeStamp + // xades:RevocationValues + // xades:AttrAuthoritiesCertValues + // ^ old code: was equivalent to CertificateValues ??? + // xades:AttributeRevocationValues + // xades:ArchiveTimeStamp + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class XSecParser::XadesUnsignedPropertiesContext + : public XSecParser::Context +{ + public: + XadesUnsignedPropertiesContext(XSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + m_rParser.HandleIdAttr(xAttrs); + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "UnsignedSignatureProperties") + { + return std::make_unique<XadesUnsignedSignaturePropertiesContext>(m_rParser, std::move(pOldNamespaceMap)); + } + // missing: xades:UnsignedDataObjectProperties + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class XSecParser::LoSignatureLineIdContext + : public XSecParser::ReferencedContextImpl +{ + private: + OUString m_Value; + + public: + LoSignatureLineIdContext(XSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void EndElement() override + { + if (m_isReferenced) + { + m_rParser.m_pXSecController->setSignatureLineId(m_Value); + } + else + { + SAL_INFO("xmlsecurity.helper", "ignoring unsigned SignatureLineId"); + } + } + + virtual void Characters(OUString const& rChars) override + { + m_Value += rChars; + } +}; + +class XSecParser::LoSignatureLineValidImageContext + : public XSecParser::ReferencedContextImpl +{ + private: + OUString m_Value; + + public: + LoSignatureLineValidImageContext(XSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void EndElement() override + { + if (m_isReferenced) + { + m_rParser.m_pXSecController->setValidSignatureImage(m_Value); + } + else + { + SAL_INFO("xmlsecurity.helper", "ignoring unsigned SignatureLineValidImage"); + } + } + + virtual void Characters(OUString const& rChars) override + { + m_Value += rChars; + } +}; + +class XSecParser::LoSignatureLineInvalidImageContext + : public XSecParser::ReferencedContextImpl +{ + private: + OUString m_Value; + + public: + LoSignatureLineInvalidImageContext(XSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void EndElement() override + { + if (m_isReferenced) + { + m_rParser.m_pXSecController->setInvalidSignatureImage(m_Value); + } + else + { + SAL_INFO("xmlsecurity.helper", "ignoring unsigned SignatureLineInvalidImage"); + } + } + + virtual void Characters(OUString const& rChars) override + { + m_Value += rChars; + } +}; + +class XSecParser::LoSignatureLineContext + : public XSecParser::ReferencedContextImpl +{ + public: + LoSignatureLineContext(XSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_LO_EXT && rName == "SignatureLineId") + { + return std::make_unique<LoSignatureLineIdContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + if (nNamespace == XML_NAMESPACE_LO_EXT && rName == "SignatureLineValidImage") + { + return std::make_unique<LoSignatureLineValidImageContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + if (nNamespace == XML_NAMESPACE_LO_EXT && rName == "SignatureLineInvalidImage") + { + return std::make_unique<LoSignatureLineInvalidImageContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class XSecParser::XadesCertDigestContext + : public XSecParser::Context +{ + private: + OUString & m_rDigestValue; + sal_Int32 & m_rReferenceDigestID; + + public: + XadesCertDigestContext(XSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + OUString& rDigestValue, sal_Int32& rReferenceDigestID) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rDigestValue(rDigestValue) + , m_rReferenceDigestID(rReferenceDigestID) + { + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "DigestMethod") + { + return std::make_unique<DsDigestMethodContext>(m_rParser, std::move(pOldNamespaceMap), m_rReferenceDigestID); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "DigestValue") + { + return std::make_unique<DsDigestValueContext>(m_rParser, std::move(pOldNamespaceMap), m_rDigestValue); + } + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class XSecParser::XadesCertContext + : public XSecParser::ReferencedContextImpl +{ + private: + sal_Int32 m_nReferenceDigestID = css::xml::crypto::DigestID::SHA1; + OUString m_CertDigest; + OUString m_X509IssuerName; + OUString m_X509SerialNumber; + + public: + XadesCertContext(XSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void EndElement() override + { + if (m_isReferenced) + { + m_rParser.m_pXSecController->setX509CertDigest(m_CertDigest, m_nReferenceDigestID, m_X509IssuerName, m_X509SerialNumber); + } + else + { + SAL_INFO("xmlsecurity.helper", "ignoring unsigned xades:Cert"); + } + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "CertDigest") + { + return std::make_unique<XadesCertDigestContext>(m_rParser, std::move(pOldNamespaceMap), m_CertDigest, m_nReferenceDigestID); + } + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "IssuerSerial") + { + return std::make_unique<DsX509IssuerSerialContext>(m_rParser, std::move(pOldNamespaceMap), m_X509IssuerName, m_X509SerialNumber); + } + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class XSecParser::XadesSigningCertificateContext + : public XSecParser::ReferencedContextImpl +{ + public: + XadesSigningCertificateContext(XSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "Cert") + { + return std::make_unique<XadesCertContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class XSecParser::XadesSigningTimeContext + : public XSecParser::ReferencedContextImpl +{ + private: + OUString m_Value; + + public: + XadesSigningTimeContext(XSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void EndElement() override + { + if (m_isReferenced) + { + m_rParser.m_pXSecController->setDate("", m_Value); + } + else + { + SAL_INFO("xmlsecurity.helper", "ignoring unsigned SigningTime"); + } + } + + virtual void Characters(OUString const& rChars) override + { + m_Value += rChars; + } +}; + +class XSecParser::XadesSignedSignaturePropertiesContext + : public XSecParser::ReferencedContextImpl +{ + public: + XadesSignedSignaturePropertiesContext(XSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + CheckIdAttrReferenced(xAttrs); + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SigningTime") + { + return std::make_unique<XadesSigningTimeContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SigningCertificate") + { + return std::make_unique<XadesSigningCertificateContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + if (nNamespace == XML_NAMESPACE_LO_EXT && rName == "SignatureLine") + { + return std::make_unique<LoSignatureLineContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + // missing: xades:SignaturePolicyIdentifier, xades:SignatureProductionPlace, xades:SignerRole + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class XSecParser::XadesSignedPropertiesContext + : public XSecParser::ReferencedContextImpl +{ + public: + XadesSignedPropertiesContext(XSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + CheckIdAttrReferenced(xAttrs); + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SignedSignatureProperties") + { + return std::make_unique<XadesSignedSignaturePropertiesContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + // missing: xades:SignedDataObjectProperties + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class XSecParser::XadesQualifyingPropertiesContext + : public XSecParser::ReferencedContextImpl +{ + public: + XadesQualifyingPropertiesContext(XSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + CheckIdAttrReferenced(xAttrs); + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SignedProperties") + { + return std::make_unique<XadesSignedPropertiesContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "UnsignedProperties") + { + return std::make_unique<XadesUnsignedPropertiesContext>(m_rParser, std::move(pOldNamespaceMap)); + } + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class XSecParser::DcDateContext + : public XSecParser::Context +{ + private: + OUString & m_rValue; + + public: + DcDateContext(XSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + OUString& rValue) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rValue(rValue) + { + } + + virtual void Characters(OUString const& rChars) override + { + m_rValue += rChars; + } +}; + +class XSecParser::DcDescriptionContext + : public XSecParser::Context +{ + private: + OUString & m_rValue; + + public: + DcDescriptionContext(XSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + OUString& rValue) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rValue(rValue) + { + } + + virtual void Characters(OUString const& rChars) override + { + m_rValue += rChars; + } +}; + +class XSecParser::DsSignaturePropertyContext + : public XSecParser::ReferencedContextImpl +{ + private: + enum class SignatureProperty { Unknown, Date, Description }; + SignatureProperty m_Property = SignatureProperty::Unknown; + OUString m_Id; + OUString m_Value; + + public: + DsSignaturePropertyContext(XSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + m_Id = CheckIdAttrReferenced(xAttrs); + } + + virtual void EndElement() override + { + if (m_isReferenced) + { + switch (m_Property) + { + case SignatureProperty::Unknown: + SAL_INFO("xmlsecurity.helper", "Unknown property in ds:Object ignored"); + break; + case SignatureProperty::Date: + m_rParser.m_pXSecController->setDate(m_Id, m_Value); + break; + case SignatureProperty::Description: + m_rParser.m_pXSecController->setDescription(m_Id, m_Value); + break; + } + } + else + { + SAL_INFO("xmlsecurity.helper", "ignoring unsigned SignatureProperty"); + } + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DC && rName == "date") + { + m_Property = SignatureProperty::Date; + return std::make_unique<DcDateContext>(m_rParser, std::move(pOldNamespaceMap), m_Value); + } + if (nNamespace == XML_NAMESPACE_DC && rName == "description") + { + m_Property = SignatureProperty::Description; + return std::make_unique<DcDescriptionContext>(m_rParser, std::move(pOldNamespaceMap), m_Value); + } + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class XSecParser::DsSignaturePropertiesContext + : public XSecParser::ReferencedContextImpl +{ + public: + DsSignaturePropertiesContext(XSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + CheckIdAttrReferenced(xAttrs); + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "SignatureProperty") + { + return std::make_unique<DsSignaturePropertyContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class XSecParser::DsObjectContext + : public XSecParser::ReferencedContextImpl +{ + public: + DsObjectContext(XSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap) + // init with "false" here - the Signature element can't be referenced by its child + : XSecParser::ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), false) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + CheckIdAttrReferenced(xAttrs); + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "SignatureProperties") + { + return std::make_unique<DsSignaturePropertiesContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "QualifyingProperties") + { + return std::make_unique<XadesQualifyingPropertiesContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + // missing: ds:Manifest + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class XSecParser::DsSignatureContext + : public XSecParser::Context +{ + public: + DsSignatureContext(XSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override + { + OUString const ouIdAttr(m_rParser.HandleIdAttr(xAttrs)); + m_rParser.m_rXMLSignatureHelper.StartVerifySignatureElement(); + m_rParser.m_pXSecController->addSignature(); + if (!ouIdAttr.isEmpty()) + { + m_rParser.m_pXSecController->setId( ouIdAttr ); + } + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "SignedInfo") + { + return std::make_unique<DsSignedInfoContext>(m_rParser, std::move(pOldNamespaceMap)); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "SignatureValue") + { + return std::make_unique<DsSignatureValueContext>(m_rParser, std::move(pOldNamespaceMap)); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "KeyInfo") + { + return std::make_unique<DsKeyInfoContext>(m_rParser, std::move(pOldNamespaceMap)); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "Object") + { + return std::make_unique<DsObjectContext>(m_rParser, std::move(pOldNamespaceMap)); + } + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + +class XSecParser::DsigSignaturesContext + : public XSecParser::Context +{ + public: + DsigSignaturesContext(XSecParser& rParser, + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual std::unique_ptr<Context> CreateChildContext( + std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "Signature") + { + return std::make_unique<DsSignatureContext>(m_rParser, std::move(pOldNamespaceMap)); + } + return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName); + } +}; + + +XSecParser::XSecParser(XMLSignatureHelper& rXMLSignatureHelper, + XSecController* pXSecController) + : m_pNamespaceMap(SvXMLNamespaceMap()) + , m_pXSecController(pXSecController) + , m_rXMLSignatureHelper(rXMLSignatureHelper) +{ + using namespace xmloff::token; + m_pNamespaceMap->Add( GetXMLToken(XML_XML), GetXMLToken(XML_N_XML), XML_NAMESPACE_XML ); + m_pNamespaceMap->Add( "_dsig_ooo", GetXMLToken(XML_N_DSIG_OOO), XML_NAMESPACE_DSIG_OOO ); + m_pNamespaceMap->Add( "_dsig", GetXMLToken(XML_N_DSIG), XML_NAMESPACE_DSIG ); + m_pNamespaceMap->Add( "_ds", GetXMLToken(XML_N_DS), XML_NAMESPACE_DS ); + m_pNamespaceMap->Add( "_xades132", GetXMLToken(XML_N_XADES132), XML_NAMESPACE_XADES132); + m_pNamespaceMap->Add( "_xades141", GetXMLToken(XML_N_XADES141), XML_NAMESPACE_XADES141); + m_pNamespaceMap->Add( "_dc", GetXMLToken(XML_N_DC), XML_NAMESPACE_DC ); + m_pNamespaceMap->Add( "_office_libo", + GetXMLToken(XML_N_LO_EXT), XML_NAMESPACE_LO_EXT); +} + +OUString XSecParser::HandleIdAttr(css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) +{ + OUString ouIdAttr = getIdAttr(xAttrs); + if (!ouIdAttr.isEmpty()) + { + m_pXSecController->collectToVerify( ouIdAttr ); + } + return ouIdAttr; +} + +OUString XSecParser::getIdAttr(const css::uno::Reference< css::xml::sax::XAttributeList >& xAttribs ) +{ + OUString ouIdAttr = xAttribs->getValueByName("id"); + + if (ouIdAttr.isEmpty()) + { + ouIdAttr = xAttribs->getValueByName("Id"); + } + + return ouIdAttr; +} + +/* + * XDocumentHandler + */ +void SAL_CALL XSecParser::startDocument( ) +{ + if (m_xNextHandler.is()) + { + m_xNextHandler->startDocument(); + } +} + +void SAL_CALL XSecParser::endDocument( ) +{ + if (m_xNextHandler.is()) + { + m_xNextHandler->endDocument(); + } +} + +void SAL_CALL XSecParser::startElement( + const OUString& rName, + const css::uno::Reference< css::xml::sax::XAttributeList >& xAttribs ) +{ + assert(m_pNamespaceMap); + std::optional<SvXMLNamespaceMap> pRewindMap( + SvXMLImport::processNSAttributes(m_pNamespaceMap, nullptr, xAttribs)); + + OUString localName; + sal_uInt16 const nPrefix(m_pNamespaceMap->GetKeyByAttrName(rName, &localName)); + + std::unique_ptr<Context> pContext; + + if (m_ContextStack.empty()) + { + if ((nPrefix != XML_NAMESPACE_DSIG && nPrefix != XML_NAMESPACE_DSIG_OOO) + || localName != "document-signatures") + { + throw css::xml::sax::SAXException( + "xmlsecurity: unexpected root element", nullptr, + css::uno::Any()); + } + + pContext.reset(new DsigSignaturesContext(*this, std::move(pRewindMap))); + + } + else + { + pContext = m_ContextStack.top()->CreateChildContext( + std::move(pRewindMap), nPrefix, localName); + } + + m_ContextStack.push(std::move(pContext)); + + try + { + m_ContextStack.top()->StartElement(xAttribs); + + if (m_xNextHandler.is()) + { + m_xNextHandler->startElement(rName, xAttribs); + } + } + catch (css::uno::Exception& ) + {//getCaughtException MUST be the first line in the catch block + css::uno::Any exc = cppu::getCaughtException(); + throw css::xml::sax::SAXException( + "xmlsecurity: Exception in XSecParser::startElement", + nullptr, exc); + } + catch (...) + { + throw css::xml::sax::SAXException( + "xmlsecurity: unexpected exception in XSecParser::startElement", nullptr, + css::uno::Any()); + } +} + +void SAL_CALL XSecParser::endElement(const OUString& rName) +{ + assert(!m_ContextStack.empty()); // this should be checked by sax parser? + + try + { + m_ContextStack.top()->EndElement(); + + if (m_xNextHandler.is()) + { + m_xNextHandler->endElement(rName); + } + } + catch (css::uno::Exception& ) + {//getCaughtException MUST be the first line in the catch block + css::uno::Any exc = cppu::getCaughtException(); + throw css::xml::sax::SAXException( + "xmlsecurity: Exception in XSecParser::endElement", + nullptr, exc); + } + catch (...) + { + throw css::xml::sax::SAXException( + "xmlsecurity: unexpected exception in XSecParser::endElement", nullptr, + css::uno::Any()); + } + + if (m_ContextStack.top()->m_pOldNamespaceMap) + { + m_pNamespaceMap = std::move(m_ContextStack.top()->m_pOldNamespaceMap); + } + m_ContextStack.pop(); +} + +void SAL_CALL XSecParser::characters(const OUString& rChars) +{ + assert(!m_ContextStack.empty()); // this should be checked by sax parser? + m_ContextStack.top()->Characters(rChars); + + if (m_xNextHandler.is()) + { + m_xNextHandler->characters(rChars); + } +} + +void SAL_CALL XSecParser::ignorableWhitespace( const OUString& aWhitespaces ) +{ + if (m_xNextHandler.is()) + { + m_xNextHandler->ignorableWhitespace( aWhitespaces ); + } +} + +void SAL_CALL XSecParser::processingInstruction( const OUString& aTarget, const OUString& aData ) +{ + if (m_xNextHandler.is()) + { + m_xNextHandler->processingInstruction(aTarget, aData); + } +} + +void SAL_CALL XSecParser::setDocumentLocator( const css::uno::Reference< css::xml::sax::XLocator >& xLocator ) +{ + if (m_xNextHandler.is()) + { + m_xNextHandler->setDocumentLocator( xLocator ); + } +} + +/* + * XInitialization + */ +void SAL_CALL XSecParser::initialize( + const css::uno::Sequence< css::uno::Any >& aArguments ) +{ + aArguments[0] >>= m_xNextHandler; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/helper/xsecparser.hxx b/xmlsecurity/source/helper/xsecparser.hxx new file mode 100644 index 0000000000..6279d65439 --- /dev/null +++ b/xmlsecurity/source/helper/xsecparser.hxx @@ -0,0 +1,159 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/xml/sax/XDocumentHandler.hpp> + +#include <cppuhelper/implbase.hxx> + +#include <xmloff/namespacemap.hxx> + +#include <memory> +#include <optional> +#include <stack> + +class XMLSignatureHelper; +class XSecController; + +class XSecParser: public cppu::WeakImplHelper +< + css::xml::sax::XDocumentHandler, + css::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. + * + * NOTES + * This class is used when importing a document. + ******************************************************************************/ +{ + friend class XSecController; +public: + class Context; +private: + class UnknownContext; + class ReferencedContextImpl; + class LoPGPOwnerContext; + class DsPGPKeyPacketContext; + class DsPGPKeyIDContext; + class DsPGPDataContext; + class DsX509CertificateContext; + class DsX509SerialNumberContext; + class DsX509IssuerNameContext; + class DsX509IssuerSerialContext; + class DsX509DataContext; + class DsKeyInfoContext; + class DsSignatureValueContext; + class DsDigestValueContext; + class DsDigestMethodContext; + class DsTransformContext; + class DsTransformsContext; + class DsReferenceContext; + class DsSignatureMethodContext; + class DsSignedInfoContext; + class XadesEncapsulatedX509CertificateContext; + class XadesCertificateValuesContext; + class XadesUnsignedSignaturePropertiesContext; + class XadesUnsignedPropertiesContext; + class LoSignatureLineIdContext; + class LoSignatureLineValidImageContext; + class LoSignatureLineInvalidImageContext; + class LoSignatureLineContext; + class XadesCertDigestContext; + class XadesCertContext; + class XadesSigningCertificateContext; + class XadesSigningTimeContext; + class XadesSignedSignaturePropertiesContext; + class XadesSignedPropertiesContext; + class XadesQualifyingPropertiesContext; + class DcDateContext; + class DcDescriptionContext; + class DsSignaturePropertyContext; + class DsSignaturePropertiesContext; + class DsObjectContext; + class DsSignatureContext; + class DsigSignaturesContext; + + std::stack<std::unique_ptr<Context>> m_ContextStack; + std::optional<SvXMLNamespaceMap> m_pNamespaceMap; + + /* + * the XSecController collaborating with XSecParser + */ + XSecController* m_pXSecController; + + /* + * the next XDocumentHandler on the SAX chain + */ + css::uno::Reference< + css::xml::sax::XDocumentHandler > m_xNextHandler; + + XMLSignatureHelper& m_rXMLSignatureHelper; + + OUString HandleIdAttr(css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs); + static OUString getIdAttr(const css::uno::Reference< + css::xml::sax::XAttributeList >& xAttribs ); + +public: + XSecParser(XMLSignatureHelper& rXMLSignatureHelper, XSecController* pXSecController); + + /* + * XDocumentHandler + */ + virtual void SAL_CALL startDocument( ) override; + + virtual void SAL_CALL endDocument( ) override; + + virtual void SAL_CALL startElement( + const OUString& aName, + const css::uno::Reference< + css::xml::sax::XAttributeList >& xAttribs ) override; + + virtual void SAL_CALL endElement( const OUString& aName ) override; + + virtual void SAL_CALL characters( const OUString& aChars ) override; + + virtual void SAL_CALL ignorableWhitespace( const OUString& aWhitespaces ) override; + + virtual void SAL_CALL processingInstruction( + const OUString& aTarget, + const OUString& aData ) override; + + virtual void SAL_CALL setDocumentLocator( + const css::uno::Reference< + css::xml::sax::XLocator >& xLocator ) override; + + /* + * XInitialization + */ + virtual void SAL_CALL initialize( + const css::uno::Sequence< css::uno::Any >& aArguments ) override; +}; + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/helper/xsecsign.cxx b/xmlsecurity/source/helper/xsecsign.cxx new file mode 100644 index 0000000000..6788f694ec --- /dev/null +++ b/xmlsecurity/source/helper/xsecsign.cxx @@ -0,0 +1,462 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include <xsecctl.hxx> + +#include <com/sun/star/xml/crypto/sax/ElementMarkPriority.hpp> +#include <com/sun/star/embed/StorageFormats.hpp> +#include <rtl/uuid.h> +#include <sal/log.hxx> + +#include <framework/signaturecreatorimpl.hxx> +#include <framework/saxeventkeeperimpl.hxx> + +namespace com::sun::star::graphic { class XGraphic; } + +using namespace css; +using namespace css::uno; +using namespace css::graphic; + +/* protected: for signature generation */ +OUString XSecController::createId() +{ + sal_uInt8 aSeq[16]; + rtl_createUuid( aSeq, nullptr, true ); + + char str[68]="ID_"; + int length = 3; + for (sal_uInt8 i : aSeq) + { + SAL_WNODEPRECATED_DECLARATIONS_PUSH // sprintf (macOS 13 SDK) + length += sprintf(str+length, "%04x", i); + SAL_WNODEPRECATED_DECLARATIONS_POP + } + + return OUString::createFromAscii(str); +} + +css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > XSecController::prepareSignatureToWrite( + InternalSignatureInformation& internalSignatureInfor, + sal_Int32 nStorageFormat, + bool bXAdESCompliantIfODF) +{ + sal_Int32 nSecurityId = internalSignatureInfor.signatureInfor.nSecurityId; + SignatureReferenceInformations& vReferenceInfors = internalSignatureInfor.signatureInfor.vSignatureReferenceInfors; + + sal_Int32 nIdOfSignatureElementCollector; + + nIdOfSignatureElementCollector = + m_xSAXEventKeeper->addSecurityElementCollector( css::xml::crypto::sax::ElementMarkPriority_AFTERMODIFY, true ); + + m_xSAXEventKeeper->setSecurityId(nIdOfSignatureElementCollector, nSecurityId); + + rtl::Reference<SignatureCreatorImpl> xSignatureCreator(new SignatureCreatorImpl); + + css::uno::Sequence<css::uno::Any> args + { + Any(OUString::number(nSecurityId)), + Any(uno::Reference<xml::crypto::sax::XSecuritySAXEventKeeper>(m_xSAXEventKeeper)), + Any(OUString::number(nIdOfSignatureElementCollector)), + + //for nss, the internal module is used for signing, which needs to be improved later + Any(m_xSecurityContext->getSecurityEnvironment()), + Any(m_xXMLSignature) + }; + xSignatureCreator->initialize(args); + + sal_Int32 nBlockerId = m_xSAXEventKeeper->addBlocker(); + m_xSAXEventKeeper->setSecurityId(nBlockerId, nSecurityId); + + xSignatureCreator->setBlockerId(nBlockerId); + + xSignatureCreator->addSignatureCreationResultListener(this); + + m_xSAXEventKeeper->addReferenceResolvedListener(nIdOfSignatureElementCollector, xSignatureCreator); + + int size = vReferenceInfors.size(); + sal_Int32 nReferenceCount = 0; + + for(int i=0; i<size; ++i) + { + sal_Int32 keeperId = internalSignatureInfor.vKeeperIds[i]; + + if ( keeperId != -1) + { + m_xSAXEventKeeper->setSecurityId(keeperId, nSecurityId); + m_xSAXEventKeeper->addReferenceResolvedListener( keeperId, xSignatureCreator); + xSignatureCreator->setReferenceId( keeperId ); + nReferenceCount++; + } + } + + xSignatureCreator->setReferenceCount( nReferenceCount ); + + /* + * adds all URI binding + */ + for(int i=0; i<size; ++i) + { + const SignatureReferenceInformation& refInfor = vReferenceInfors[i]; + + css::uno::Reference< css::io::XInputStream > xInputStream + = getObjectInputStream( refInfor.ouURI ); + + if (xInputStream.is()) + xSignatureCreator->setUriBinding(refInfor.ouURI,xInputStream); + } + + xSignatureCreator->setKeyId(0); + + // use sha512 for gpg signing unconditionally + const sal_Int32 digestID = !internalSignatureInfor.signatureInfor.ouGpgCertificate.isEmpty()? + css::xml::crypto::DigestID::SHA512 : (bXAdESCompliantIfODF ? css::xml::crypto::DigestID::SHA256 : css::xml::crypto::DigestID::SHA1); + + if (nStorageFormat != embed::StorageFormats::OFOPXML) + { + internalSignatureInfor.signatureInfor.ouSignatureId = createId(); + internalSignatureInfor.signatureInfor.ouDateTimePropertyId = createId(); + internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, digestID, internalSignatureInfor.signatureInfor.ouDateTimePropertyId, -1, OUString() ); + size++; + + if (bXAdESCompliantIfODF) + { + OUString aId = "idSignedProperties_" + internalSignatureInfor.signatureInfor.ouSignatureId; + // We write a new reference, so it's possible to use the correct type URI. + internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, digestID, aId, -1, "http://uri.etsi.org/01903#SignedProperties"); + size++; + } + + if (!internalSignatureInfor.signatureInfor.ouDescription.isEmpty()) + { + // Only mention the hash of the description in the signature if it's non-empty. + internalSignatureInfor.signatureInfor.ouDescriptionPropertyId = createId(); + internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, digestID, internalSignatureInfor.signatureInfor.ouDescriptionPropertyId, -1, OUString()); + size++; + } + } + else // OOXML + { + OUString aID = createId(); + internalSignatureInfor.signatureInfor.ouSignatureId = aID; + + internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, digestID, "idPackageObject_" + aID, -1, OUString()); + size++; + internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, digestID, "idOfficeObject_" + aID, -1, OUString()); + size++; + internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, digestID, "idSignedProperties_" + aID, -1, OUString()); + size++; + } + + /* + * replace both digestValues and signatureValue to " " + */ + for(int i=0; i<size; ++i) + { + SignatureReferenceInformation& refInfor = vReferenceInfors[i]; + refInfor.ouDigestValue = " "; + } + + internalSignatureInfor.signatureInfor.ouSignatureValue = " "; + + return xSignatureCreator; +} + +void XSecController::signAStream( sal_Int32 securityId, const OUString& uri, bool isBinary, bool bXAdESCompliantIfODF) +{ + const SignatureReferenceType type = isBinary ? SignatureReferenceType::BINARYSTREAM : SignatureReferenceType::XMLSTREAM; + sal_Int32 digestID = bXAdESCompliantIfODF ? css::xml::crypto::DigestID::SHA256 : css::xml::crypto::DigestID::SHA1; + + int index = findSignatureInfor( securityId ); + + if (index == -1) + { + InternalSignatureInformation isi(securityId, nullptr); + isi.addReference(type, digestID, uri, -1, OUString()); + m_vInternalSignatureInformations.push_back( isi ); + } + else + { + // use sha512 for gpg signing unconditionally + if (!m_vInternalSignatureInformations[index].signatureInfor.ouGpgCertificate.isEmpty()) + digestID = css::xml::crypto::DigestID::SHA512; + m_vInternalSignatureInformations[index].addReference(type, digestID, uri, -1, OUString()); + } +} + +// note: this is called when creating a new signature from scratch +void XSecController::setX509Certificate( + sal_Int32 nSecurityId, + const OUString& ouX509IssuerName, + const OUString& ouX509SerialNumber, + const OUString& ouX509Cert, + const OUString& ouX509CertDigest, + svl::crypto::SignatureMethodAlgorithm eAlgorithmID) +{ + int index = findSignatureInfor( nSecurityId ); + + if ( index == -1 ) + { + InternalSignatureInformation isi(nSecurityId, nullptr); + isi.signatureInfor.X509Datas.clear(); + isi.signatureInfor.X509Datas.emplace_back(); + isi.signatureInfor.X509Datas.back().emplace_back(); + isi.signatureInfor.X509Datas.back().back().X509IssuerName = ouX509IssuerName; + isi.signatureInfor.X509Datas.back().back().X509SerialNumber = ouX509SerialNumber; + isi.signatureInfor.X509Datas.back().back().X509Certificate = ouX509Cert; + isi.signatureInfor.X509Datas.back().back().CertDigest = ouX509CertDigest; + isi.signatureInfor.eAlgorithmID = eAlgorithmID; + m_vInternalSignatureInformations.push_back( isi ); + } + else + { + SignatureInformation &si + = m_vInternalSignatureInformations[index].signatureInfor; + si.X509Datas.clear(); + si.X509Datas.emplace_back(); + si.X509Datas.back().emplace_back(); + si.X509Datas.back().back().X509IssuerName = ouX509IssuerName; + si.X509Datas.back().back().X509SerialNumber = ouX509SerialNumber; + si.X509Datas.back().back().X509Certificate = ouX509Cert; + si.X509Datas.back().back().CertDigest = ouX509CertDigest; + } +} + +void XSecController::setGpgCertificate( + sal_Int32 nSecurityId, + const OUString& ouKeyDigest, + const OUString& ouCert, + const OUString& ouOwner) +{ + int index = findSignatureInfor( nSecurityId ); + + if ( index == -1 ) + { + InternalSignatureInformation isi(nSecurityId, nullptr); + isi.signatureInfor.ouGpgCertificate = ouCert; + isi.signatureInfor.ouGpgOwner = ouOwner; + isi.signatureInfor.ouGpgKeyID = ouKeyDigest; + m_vInternalSignatureInformations.push_back( isi ); + } + else + { + SignatureInformation &si + = m_vInternalSignatureInformations[index].signatureInfor; + si.X509Datas.clear(); // it is a PGP signature now + si.ouGpgCertificate = ouCert; + si.ouGpgOwner = ouOwner; + si.ouGpgKeyID = ouKeyDigest; + } +} + +void XSecController::setDate( + sal_Int32 nSecurityId, + const css::util::DateTime& rDateTime ) +{ + int index = findSignatureInfor( nSecurityId ); + + if ( index == -1 ) + { + InternalSignatureInformation isi(nSecurityId, nullptr); + isi.signatureInfor.stDateTime = rDateTime; + m_vInternalSignatureInformations.push_back( isi ); + } + else + { + SignatureInformation &si + = m_vInternalSignatureInformations[index].signatureInfor; + si.stDateTime = rDateTime; + } +} + +void XSecController::setDescription(sal_Int32 nSecurityId, const OUString& rDescription) +{ + int nIndex = findSignatureInfor(nSecurityId); + + if (nIndex == -1) + { + InternalSignatureInformation aInformation(nSecurityId, nullptr); + aInformation.signatureInfor.ouDescription = rDescription; + m_vInternalSignatureInformations.push_back(aInformation); + } + else + { + SignatureInformation& rInformation = m_vInternalSignatureInformations[nIndex].signatureInfor; + rInformation.ouDescription = rDescription; + } +} + +void XSecController::setSignatureLineId(sal_Int32 nSecurityId, const OUString& rSignatureLineId) +{ + int nIndex = findSignatureInfor(nSecurityId); + + if (nIndex == -1) + { + InternalSignatureInformation aInformation(nSecurityId, nullptr); + aInformation.signatureInfor.ouSignatureLineId = rSignatureLineId; + m_vInternalSignatureInformations.push_back(aInformation); + } + else + { + SignatureInformation& rInformation = m_vInternalSignatureInformations[nIndex].signatureInfor; + rInformation.ouSignatureLineId = rSignatureLineId; + } +} + +void XSecController::setSignatureLineValidGraphic(sal_Int32 nSecurityId, + const Reference<XGraphic>& xValidGraphic) +{ + int nIndex = findSignatureInfor(nSecurityId); + + if (nIndex == -1) + { + InternalSignatureInformation aInformation(nSecurityId, nullptr); + aInformation.signatureInfor.aValidSignatureImage = xValidGraphic; + m_vInternalSignatureInformations.push_back(aInformation); + } + else + { + SignatureInformation& rInformation + = m_vInternalSignatureInformations[nIndex].signatureInfor; + rInformation.aValidSignatureImage = xValidGraphic; + } +} + +void XSecController::setSignatureLineInvalidGraphic( + sal_Int32 nSecurityId, const Reference<XGraphic>& xInvalidGraphic) +{ + int nIndex = findSignatureInfor(nSecurityId); + + if (nIndex == -1) + { + InternalSignatureInformation aInformation(nSecurityId, nullptr); + aInformation.signatureInfor.aInvalidSignatureImage = xInvalidGraphic; + m_vInternalSignatureInformations.push_back(aInformation); + } + else + { + SignatureInformation& rInformation + = m_vInternalSignatureInformations[nIndex].signatureInfor; + rInformation.aInvalidSignatureImage = xInvalidGraphic; + } +} + +bool XSecController::WriteSignature( + const css::uno::Reference<css::xml::sax::XDocumentHandler>& xDocumentHandler, + bool bXAdESCompliantIfODF ) +{ + bool rc = false; + + SAL_WARN_IF( !xDocumentHandler.is(), "xmlsecurity.helper", "I really need a document handler!" ); + + /* + * chain the SAXEventKeeper to the SAX chain + */ + chainOn(); + + if ( m_eStatusOfSecurityComponents == InitializationState::INITIALIZED ) + /* + * if all security components are ready, add the signature + * stream. + */ + { + m_bIsSAXEventKeeperSticky = true; + m_xSAXEventKeeper->setNextHandler(xDocumentHandler); + + try + { + /* + * export the signature template + */ + css::uno::Reference<css::xml::sax::XDocumentHandler> xSEKHandler(m_xSAXEventKeeper); + + int i; + int sigNum = m_vInternalSignatureInformations.size(); + + for (i=0; i<sigNum; ++i) + { + InternalSignatureInformation &isi = m_vInternalSignatureInformations[i]; + + // Prepare the signature creator. + // 0 is not a documented value of embed::StorageFormats, ugh + isi.xReferenceResolvedListener = prepareSignatureToWrite( isi, 0, bXAdESCompliantIfODF ); + + exportSignature( xSEKHandler, isi.signatureInfor, bXAdESCompliantIfODF ); + } + + m_bIsSAXEventKeeperSticky = false; + chainOff(); + + rc = true; + } + catch( css::uno::Exception& ) + { + } + + m_xSAXEventKeeper->setNextHandler( nullptr ); + m_bIsSAXEventKeeperSticky = false; + } + + return rc; +} + +bool XSecController::WriteOOXMLSignature(const uno::Reference<embed::XStorage>& xRootStorage, const uno::Reference<xml::sax::XDocumentHandler>& xDocumentHandler) +{ + bool bRet = false; + + SAL_WARN_IF(!xDocumentHandler.is(), "xmlsecurity.helper", "empty xDocumentHandler reference"); + + // Chain the SAXEventKeeper to the SAX chain. + chainOn(); + + if (m_eStatusOfSecurityComponents == InitializationState::INITIALIZED) + { + m_bIsSAXEventKeeperSticky = true; + m_xSAXEventKeeper->setNextHandler(xDocumentHandler); + + try + { + // Export the signature template. + css::uno::Reference<xml::sax::XDocumentHandler> xSEKHandler(m_xSAXEventKeeper); + + for (InternalSignatureInformation & rInformation : m_vInternalSignatureInformations) + { + // Prepare the signature creator. + rInformation.xReferenceResolvedListener = prepareSignatureToWrite(rInformation, embed::StorageFormats::OFOPXML, false); + + exportOOXMLSignature(xRootStorage, xSEKHandler, rInformation.signatureInfor); + } + + m_bIsSAXEventKeeperSticky = false; + chainOff(); + + bRet = true; + } + catch(const uno::Exception&) + { + } + + m_xSAXEventKeeper->setNextHandler(nullptr); + m_bIsSAXEventKeeperSticky = false; + } + + return bRet; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/helper/xsecverify.cxx b/xmlsecurity/source/helper/xsecverify.cxx new file mode 100644 index 0000000000..c45bece5fe --- /dev/null +++ b/xmlsecurity/source/helper/xsecverify.cxx @@ -0,0 +1,630 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <config_gpgme.h> + +#include <xsecctl.hxx> +#include "xsecparser.hxx" +#include "ooxmlsecparser.hxx" +#include <biginteger.hxx> +#include <framework/signatureverifierimpl.hxx> +#include <framework/saxeventkeeperimpl.hxx> +#include <gpg/xmlsignature_gpgimpl.hxx> +#include <gpg/SEInitializer.hxx> + +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/xml/crypto/sax/XKeyCollector.hpp> +#include <com/sun/star/xml/crypto/sax/ElementMarkPriority.hpp> +#include <com/sun/star/xml/crypto/sax/XReferenceCollector.hpp> +#include <com/sun/star/xml/crypto/sax/XSignatureVerifyResultBroadcaster.hpp> +#include <com/sun/star/xml/crypto/XSEInitializer.hpp> +#include <com/sun/star/graphic/GraphicProvider.hpp> +#include <com/sun/star/embed/StorageFormats.hpp> +#include <sal/log.hxx> +#include <unotools/datetime.hxx> +#include <comphelper/base64.hxx> +#include <comphelper/processfactory.hxx> +#include <comphelper/propertyvalue.hxx> +#include <comphelper/seqstream.hxx> + +namespace com::sun::star::graphic { class XGraphic; } + +using namespace css; +using namespace css::uno; +using namespace css::beans; + +/* protected: for signature verify */ +css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > XSecController::prepareSignatureToRead( + sal_Int32 nSecurityId) +{ + if ( m_eStatusOfSecurityComponents != InitializationState::INITIALIZED ) + { + return nullptr; + } + + sal_Int32 nIdOfSignatureElementCollector; + css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > xReferenceResolvedListener; + + nIdOfSignatureElementCollector = + m_xSAXEventKeeper->addSecurityElementCollector( css::xml::crypto::sax::ElementMarkPriority_BEFOREMODIFY, false); + + m_xSAXEventKeeper->setSecurityId(nIdOfSignatureElementCollector, nSecurityId); + + /* + * create a SignatureVerifier + */ + xReferenceResolvedListener = new SignatureVerifierImpl; + + css::uno::Reference<css::lang::XInitialization> xInitialization(xReferenceResolvedListener, css::uno::UNO_QUERY); + + css::uno::Sequence<css::uno::Any> args + { + Any(OUString::number(nSecurityId)), + Any(uno::Reference<xml::crypto::sax::XSecuritySAXEventKeeper>(m_xSAXEventKeeper)), + Any(OUString::number(nIdOfSignatureElementCollector)), + Any(m_xSecurityContext), + Any(m_xXMLSignature) + }; + xInitialization->initialize(args); + + css::uno::Reference< css::xml::crypto::sax::XSignatureVerifyResultBroadcaster > + signatureVerifyResultBroadcaster(xReferenceResolvedListener, css::uno::UNO_QUERY); + + signatureVerifyResultBroadcaster->addSignatureVerifyResultListener( this ); + + m_xSAXEventKeeper->addReferenceResolvedListener( + nIdOfSignatureElementCollector, + xReferenceResolvedListener); + + css::uno::Reference<css::xml::crypto::sax::XKeyCollector> keyCollector (xReferenceResolvedListener, css::uno::UNO_QUERY); + keyCollector->setKeyId(0); + + return xReferenceResolvedListener; +} + +void XSecController::addSignature() +{ + css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > xReferenceResolvedListener; + sal_Int32 nSignatureId = 0; + + + if (m_bVerifyCurrentSignature) + { + chainOn(); + xReferenceResolvedListener = prepareSignatureToRead( m_nReservedSignatureId ); + m_bVerifyCurrentSignature = false; + nSignatureId = m_nReservedSignatureId; + } + + InternalSignatureInformation isi( nSignatureId, xReferenceResolvedListener ); + m_vInternalSignatureInformations.push_back( isi ); +} + +void XSecController::setSignatureMethod(svl::crypto::SignatureMethodAlgorithm eAlgorithmID) +{ + if (m_vInternalSignatureInformations.empty()) + return; + + m_vInternalSignatureInformations.back().signatureInfor.eAlgorithmID = eAlgorithmID; +} + +void XSecController::switchGpgSignature() +{ +#if HAVE_FEATURE_GPGME + // swap signature verifier for the Gpg one + m_xXMLSignature.set(new XMLSignature_GpgImpl()); + if (m_vInternalSignatureInformations.empty()) + return; + + SignatureVerifierImpl* pImpl= + dynamic_cast<SignatureVerifierImpl*>( + m_vInternalSignatureInformations.back().xReferenceResolvedListener.get()); + if (pImpl) + { + css::uno::Reference<css::xml::crypto::XSEInitializer> xGpgSEInitializer( + new SEInitializerGpg()); + pImpl->updateSignature(new XMLSignature_GpgImpl(), + xGpgSEInitializer->createSecurityContext(OUString())); + } +#else + (void) this; +#endif +} + +bool XSecController::haveReferenceForId(std::u16string_view rId) const +{ + if (m_vInternalSignatureInformations.empty()) + { + SAL_INFO("xmlsecurity.helper","XSecController::haveReferenceForId: no signature"); + return false; + } + InternalSignatureInformation const& rIsi(m_vInternalSignatureInformations.back()); + for (SignatureReferenceInformation const& rSri : rIsi.signatureInfor.vSignatureReferenceInfors) + { + if (rSri.nType == SignatureReferenceType::SAMEDOCUMENT + && rSri.ouURI == rId) // ouUri has # stripped + { + return true; + } + } + return false; +} + +void XSecController::addReference( const OUString& ouUri, sal_Int32 nDigestID, const OUString& ouType ) +{ + if (m_vInternalSignatureInformations.empty()) + { + SAL_INFO("xmlsecurity.helper","XSecController::addReference: no signature"); + return; + } + InternalSignatureInformation &isi = m_vInternalSignatureInformations.back(); + isi.addReference(SignatureReferenceType::SAMEDOCUMENT, nDigestID, ouUri, -1, ouType ); +} + +void XSecController::addStreamReference( + const OUString& ouUri, + bool isBinary, + sal_Int32 nDigestID ) +{ + SignatureReferenceType type = (isBinary?SignatureReferenceType::BINARYSTREAM:SignatureReferenceType::XMLSTREAM); + + if (m_vInternalSignatureInformations.empty()) + { + SAL_INFO("xmlsecurity.helper","XSecController::addStreamReference: no signature"); + return; + } + InternalSignatureInformation &isi = m_vInternalSignatureInformations.back(); + + if ( isi.xReferenceResolvedListener.is() ) + { + /* + * get the input stream + */ + css::uno::Reference< css::io::XInputStream > xObjectInputStream + = getObjectInputStream( ouUri ); + + if ( xObjectInputStream.is() ) + { + css::uno::Reference<css::xml::crypto::XUriBinding> xUriBinding + (isi.xReferenceResolvedListener, css::uno::UNO_QUERY); + xUriBinding->setUriBinding(ouUri, xObjectInputStream); + } + } + + isi.addReference(type, nDigestID, ouUri, -1, OUString()); +} + +void XSecController::setReferenceCount() const +{ + if (m_vInternalSignatureInformations.empty()) + { + SAL_INFO("xmlsecurity.helper","XSecController::setReferenceCount: no signature"); + return; + } + const InternalSignatureInformation &isi = + m_vInternalSignatureInformations.back(); + + if ( !isi.xReferenceResolvedListener.is() ) + return; + + const SignatureReferenceInformations &refInfors = isi.signatureInfor.vSignatureReferenceInfors; + + int refNum = refInfors.size(); + sal_Int32 referenceCount = 0; + + for(int i=0 ; i<refNum; ++i) + { + if (refInfors[i].nType == SignatureReferenceType::SAMEDOCUMENT ) + /* + * same-document reference + */ + { + referenceCount++; + } + } + + css::uno::Reference<css::xml::crypto::sax::XReferenceCollector> xReferenceCollector + (isi.xReferenceResolvedListener, css::uno::UNO_QUERY); + xReferenceCollector->setReferenceCount( referenceCount ); +} + +void XSecController::setX509Data( + std::vector<std::pair<OUString, OUString>> & rX509IssuerSerials, + std::vector<OUString> const& rX509Certificates) +{ + if (m_vInternalSignatureInformations.empty()) + { + SAL_INFO("xmlsecurity.helper","XSecController::setX509IssuerName: no signature"); + return; + } + InternalSignatureInformation &isi = m_vInternalSignatureInformations.back(); + SignatureInformation::X509Data data; + // due to the excessive flexibility of the spec it's possible that there + // is both a reference to a cert and the cert itself in one X509Data + for (OUString const& it : rX509Certificates) + { + try + { + data.emplace_back(); + data.back().X509Certificate = it; + uno::Reference<xml::crypto::XSecurityEnvironment> const xSecEnv(m_xSecurityContext->getSecurityEnvironment()); + uno::Reference<security::XCertificate> const xCert(xSecEnv->createCertificateFromAscii(it)); + if (!xCert.is()) + { + SAL_INFO("xmlsecurity.helper", "cannot parse X509Certificate"); + continue; // will be handled in CheckX509Data + } + OUString const issuerName(xCert->getIssuerName()); + OUString const serialNumber(xmlsecurity::bigIntegerToNumericString(xCert->getSerialNumber())); + auto const iter = std::find_if(rX509IssuerSerials.begin(), rX509IssuerSerials.end(), + [&](auto const& rX509IssuerSerial) { + return xmlsecurity::EqualDistinguishedNames(issuerName, rX509IssuerSerial.first, xmlsecurity::COMPAT_2ND) + && serialNumber == rX509IssuerSerial.second; + }); + if (iter != rX509IssuerSerials.end()) + { + data.back().X509IssuerName = iter->first; + data.back().X509SerialNumber = iter->second; + rX509IssuerSerials.erase(iter); + } + } + catch (uno::Exception const&) + { + SAL_INFO("xmlsecurity.helper", "cannot parse X509Certificate"); + } + } + // now handle any that are left... + for (auto const& it : rX509IssuerSerials) + { + data.emplace_back(); + data.back().X509IssuerName = it.first; + data.back().X509SerialNumber = it.second; + } + if (!data.empty()) + { + isi.signatureInfor.X509Datas.push_back(data); + } +} + +void XSecController::setSignatureValue( OUString const & ouSignatureValue ) +{ + if (m_vInternalSignatureInformations.empty()) + { + SAL_INFO("xmlsecurity.helper","XSecController::setSignatureValue: no signature"); + return; + } + InternalSignatureInformation &isi = m_vInternalSignatureInformations.back(); + isi.signatureInfor.ouSignatureValue = ouSignatureValue; +} + +void XSecController::setDigestValue( sal_Int32 nDigestID, OUString const & ouDigestValue ) +{ + if (m_vInternalSignatureInformations.empty()) + { + SAL_INFO("xmlsecurity.helper","XSecController::setDigestValue: no signature"); + return; + } + InternalSignatureInformation &isi = m_vInternalSignatureInformations.back(); + if (isi.signatureInfor.vSignatureReferenceInfors.empty()) + { + SAL_INFO("xmlsecurity.helper","XSecController::setDigestValue: no signature reference"); + return; + } + SignatureReferenceInformation &reference = + isi.signatureInfor.vSignatureReferenceInfors.back(); + reference.nDigestID = nDigestID; + reference.ouDigestValue = ouDigestValue; +} + +void XSecController::setGpgKeyID( OUString const & ouKeyID ) +{ + if (m_vInternalSignatureInformations.empty()) + { + SAL_INFO("xmlsecurity.helper","XSecController::setGpgKeyID: no signature"); + return; + } + InternalSignatureInformation &isi = m_vInternalSignatureInformations.back(); + isi.signatureInfor.ouGpgKeyID = ouKeyID; +} + +void XSecController::setGpgCertificate( OUString const & ouGpgCert ) +{ + if (m_vInternalSignatureInformations.empty()) + { + SAL_INFO("xmlsecurity.helper","XSecController::setGpgCertificate: no signature"); + return; + } + InternalSignatureInformation &isi = m_vInternalSignatureInformations.back(); + isi.signatureInfor.ouGpgCertificate = ouGpgCert; +} + +void XSecController::setGpgOwner( OUString const & ouGpgOwner ) +{ + if (m_vInternalSignatureInformations.empty()) + { + SAL_INFO("xmlsecurity.helper","XSecController::setGpgOwner: no signature"); + return; + } + InternalSignatureInformation &isi = m_vInternalSignatureInformations.back(); + isi.signatureInfor.ouGpgOwner = ouGpgOwner; +} + +void XSecController::setDate(OUString const& rId, OUString const& ouDate) +{ + if (m_vInternalSignatureInformations.empty()) + { + SAL_INFO("xmlsecurity.helper","XSecController::setDate: no signature"); + return; + } + InternalSignatureInformation &isi = m_vInternalSignatureInformations.back(); + // there may be multiple timestamps in a signature - check them for consistency + if (!isi.signatureInfor.ouDateTime.isEmpty() + && isi.signatureInfor.ouDateTime != ouDate) + { + isi.signatureInfor.hasInconsistentSigningTime = true; + } + (void)utl::ISO8601parseDateTime( ouDate, isi.signatureInfor.stDateTime); + isi.signatureInfor.ouDateTime = ouDate; + if (!rId.isEmpty()) + { + isi.signatureInfor.ouDateTimePropertyId = rId; + } +} + +void XSecController::setDescription(OUString const& rId, OUString const& rDescription) +{ + if (m_vInternalSignatureInformations.empty()) + return; + + InternalSignatureInformation& rInformation = m_vInternalSignatureInformations.back(); + rInformation.signatureInfor.ouDescription = rDescription; + if (!rId.isEmpty()) + { + rInformation.signatureInfor.ouDescriptionPropertyId = rId; + } +} + +void XSecController::setSignatureBytes(const uno::Sequence<sal_Int8>& rBytes) +{ + if (m_vInternalSignatureInformations.empty()) + return; + + InternalSignatureInformation& rInformation = m_vInternalSignatureInformations.back(); + rInformation.signatureInfor.aSignatureBytes = rBytes; +} + +void XSecController::setX509CertDigest( + OUString const& rCertDigest, sal_Int32 const /*TODO nReferenceDigestID*/, + std::u16string_view const& rX509IssuerName, std::u16string_view const& rX509SerialNumber) +{ + if (m_vInternalSignatureInformations.empty()) + return; + + InternalSignatureInformation& rInformation = m_vInternalSignatureInformations.back(); + for (auto & rData : rInformation.signatureInfor.X509Datas) + { + for (auto & it : rData) + { + if (xmlsecurity::EqualDistinguishedNames(it.X509IssuerName, rX509IssuerName, xmlsecurity::COMPAT_BOTH) + && it.X509SerialNumber == rX509SerialNumber) + { + it.CertDigest = rCertDigest; + return; + } + } + } + // fall-back: read the actual certificates + for (auto & rData : rInformation.signatureInfor.X509Datas) + { + for (auto & it : rData) + { + if (!it.X509Certificate.isEmpty()) + { + try + { + uno::Reference<xml::crypto::XSecurityEnvironment> const xSecEnv(m_xSecurityContext->getSecurityEnvironment()); + uno::Reference<security::XCertificate> const xCert(xSecEnv->createCertificateFromAscii(it.X509Certificate)); + if (!xCert.is()) + { + SAL_INFO("xmlsecurity.helper", "cannot parse X509Certificate"); + } + else if (xmlsecurity::EqualDistinguishedNames(xCert->getIssuerName(), rX509IssuerName, xmlsecurity::COMPAT_2ND) + && xmlsecurity::bigIntegerToNumericString(xCert->getSerialNumber()) == rX509SerialNumber) + { + it.CertDigest = rCertDigest; + // note: testInsertCertificate_PEM_DOCX requires these! + it.X509SerialNumber = rX509SerialNumber; + it.X509IssuerName = rX509IssuerName; + return; + } + } + catch (uno::Exception const&) + { + SAL_INFO("xmlsecurity.helper", "cannot parse X509Certificate"); + } + } + } + } + if (!rInformation.signatureInfor.ouGpgCertificate.isEmpty()) + { + SAL_INFO_IF(rCertDigest != rInformation.signatureInfor.ouGpgKeyID, + "xmlsecurity.helper", "PGPKeyID vs CertDigest mismatch"); + } + else + { + SAL_INFO("xmlsecurity.helper", "cannot find X509Data for CertDigest"); + } +} + +namespace { +Reference<css::graphic::XGraphic> lcl_getGraphicFromString(std::u16string_view rImage) +{ + Sequence<sal_Int8> seq; + comphelper::Base64::decode(seq, rImage); + + Reference< graphic::XGraphic > xGraphic; + if( !seq.hasElements() ) + return Reference<css::graphic::XGraphic>(); + + Reference< graphic::XGraphicProvider > xGraphicProvider( + graphic::GraphicProvider::create(comphelper::getProcessComponentContext()) ); + Reference< io::XInputStream > xInputStream( new ::comphelper::SequenceInputStream( seq ) ); + + Sequence< PropertyValue > aArgs{ comphelper::makePropertyValue("InputStream", xInputStream) }; + xGraphic = xGraphicProvider->queryGraphic(aArgs); + + return xGraphic; +} +} + +void XSecController::setValidSignatureImage(std::u16string_view rValidSigImg) +{ + if (m_vInternalSignatureInformations.empty() || rValidSigImg.empty()) + return; + + InternalSignatureInformation& rInformation = m_vInternalSignatureInformations.back(); + rInformation.signatureInfor.aValidSignatureImage = lcl_getGraphicFromString(rValidSigImg); +} + +void XSecController::setInvalidSignatureImage(std::u16string_view rInvalidSigImg) +{ + if (m_vInternalSignatureInformations.empty() || rInvalidSigImg.empty()) + return; + + InternalSignatureInformation& rInformation = m_vInternalSignatureInformations.back(); + rInformation.signatureInfor.aInvalidSignatureImage = lcl_getGraphicFromString(rInvalidSigImg); +} + +void XSecController::setSignatureLineId(const OUString& rSignatureLineId) +{ + if (m_vInternalSignatureInformations.empty()) + return; + + InternalSignatureInformation& rInformation = m_vInternalSignatureInformations.back(); + rInformation.signatureInfor.ouSignatureLineId = rSignatureLineId; +} + +void XSecController::addEncapsulatedX509Certificate(const OUString& rEncapsulatedX509Certificate) +{ + if (m_vInternalSignatureInformations.empty()) + return; + + if (rEncapsulatedX509Certificate.isEmpty()) + return; + + InternalSignatureInformation& rInformation = m_vInternalSignatureInformations.back(); + rInformation.signatureInfor.maEncapsulatedX509Certificates.insert(rEncapsulatedX509Certificate); +} + +void XSecController::setId( OUString const & ouId ) +{ + if (m_vInternalSignatureInformations.empty()) + { + SAL_INFO("xmlsecurity.helper","XSecController::setId: no signature"); + return; + } + InternalSignatureInformation &isi = m_vInternalSignatureInformations.back(); + isi.signatureInfor.ouSignatureId = ouId; +} + +/* public: for signature verify */ +void XSecController::collectToVerify( std::u16string_view referenceId ) +{ + /* SAL_WARN_IF( !m_xSAXEventKeeper.is(), "xmlsecurity", "the SAXEventKeeper is NULL" ); */ + + if ( m_eStatusOfSecurityComponents != InitializationState::INITIALIZED ) + /* + * if all security components are ready, verify the signature. + */ + return; + + bool bJustChainingOn = false; + css::uno::Reference< css::xml::sax::XDocumentHandler > xHandler; + + int i,j; + int sigNum = m_vInternalSignatureInformations.size(); + + for (i=0; i<sigNum; ++i) + { + InternalSignatureInformation& isi = m_vInternalSignatureInformations[i]; + SignatureReferenceInformations& vReferenceInfors = isi.signatureInfor.vSignatureReferenceInfors; + int refNum = vReferenceInfors.size(); + + for (j=0; j<refNum; ++j) + { + SignatureReferenceInformation &refInfor = vReferenceInfors[j]; + + if (refInfor.ouURI == referenceId) + { + if (chainOn()) + { + bJustChainingOn = true; + xHandler = m_xSAXEventKeeper->setNextHandler(nullptr); + } + + sal_Int32 nKeeperId = m_xSAXEventKeeper->addSecurityElementCollector( + css::xml::crypto::sax::ElementMarkPriority_BEFOREMODIFY, false ); + + css::uno::Reference<css::xml::crypto::sax::XReferenceCollector> xReferenceCollector + ( isi.xReferenceResolvedListener, css::uno::UNO_QUERY ); + + m_xSAXEventKeeper->setSecurityId(nKeeperId, isi.signatureInfor.nSecurityId); + m_xSAXEventKeeper->addReferenceResolvedListener( nKeeperId, isi.xReferenceResolvedListener); + xReferenceCollector->setReferenceId( nKeeperId ); + + isi.vKeeperIds[j] = nKeeperId; + break; + } + } + } + + if ( bJustChainingOn ) + { + m_xSAXEventKeeper->setNextHandler(xHandler); + } +} + +void XSecController::addSignature( sal_Int32 nSignatureId ) +{ + SAL_WARN_IF( !m_xSecParser.is(), "xmlsecurity.helper", "No XSecParser initialized" ); + + m_nReservedSignatureId = nSignatureId; + m_bVerifyCurrentSignature = true; +} + +css::uno::Reference< css::xml::sax::XDocumentHandler > const & XSecController::createSignatureReader(XMLSignatureHelper& rXMLSignatureHelper, sal_Int32 nType) +{ + if (nType == embed::StorageFormats::OFOPXML) + m_xSecParser = new OOXMLSecParser(rXMLSignatureHelper, this); + else + m_xSecParser = new XSecParser(rXMLSignatureHelper, this); + css::uno::Reference< css::lang::XInitialization > xInitialization(m_xSecParser, uno::UNO_QUERY); + + setSAXChainConnector(xInitialization); + + return m_xSecParser; +} + +void XSecController::releaseSignatureReader() +{ + clearSAXChainConnector( ); + m_xSecParser.clear(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/biginteger.cxx b/xmlsecurity/source/xmlsec/biginteger.cxx new file mode 100644 index 0000000000..1a4ab6fd9d --- /dev/null +++ b/xmlsecurity/source/xmlsec/biginteger.cxx @@ -0,0 +1,106 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include <biginteger.hxx> + +#include <xmlsec-wrapper.h> +#include <com/sun/star/uno/Sequence.hxx> + +#include <comphelper/sequence.hxx> + +using namespace ::com::sun::star::uno ; + +namespace xmlsecurity +{ +Sequence< sal_Int8 > numericStringToBigInteger ( std::u16string_view numeral ) +{ + xmlChar* chNumeral ; + const xmlSecByte* bnInteger ; + xmlSecSize length ; + xmlSecBn bn ; + + OString onumeral = OUStringToOString( numeral , RTL_TEXTENCODING_ASCII_US ) ; + + chNumeral = xmlStrndup( reinterpret_cast<const xmlChar*>(onumeral.getStr()), static_cast<int>(onumeral.getLength()) ) ; + + if( xmlSecBnInitialize( &bn, 0 ) < 0 ) { + xmlFree( chNumeral ) ; + return Sequence< sal_Int8 >(); + } + + if( xmlSecBnFromDecString( &bn, chNumeral ) < 0 ) { + xmlFree( chNumeral ) ; + xmlSecBnFinalize( &bn ) ; + return Sequence< sal_Int8 >(); + } + + xmlFree( chNumeral ) ; + + length = xmlSecBnGetSize( &bn ) ; + if( length <= 0 ) { + xmlSecBnFinalize( &bn ) ; + return Sequence< sal_Int8 >(); + } + + bnInteger = xmlSecBnGetData( &bn ) ; + if( bnInteger == nullptr ) { + xmlSecBnFinalize( &bn ) ; + return Sequence< sal_Int8 >(); + } + + Sequence< sal_Int8 > integer = comphelper::arrayToSequence<sal_Int8>(bnInteger, length); + + xmlSecBnFinalize( &bn ) ; + return integer ; +} + +OUString bigIntegerToNumericString ( const Sequence< sal_Int8 >& integer ) +{ + OUString aRet ; + + if( integer.hasElements() ) { + xmlSecBn bn ; + xmlChar* chNumeral ; + + if( xmlSecBnInitialize( &bn, 0 ) < 0 ) + return aRet ; + + if( xmlSecBnSetData( &bn, reinterpret_cast<const unsigned char*>(integer.getConstArray()), integer.getLength() ) < 0 ) { + xmlSecBnFinalize( &bn ) ; + return aRet ; + } + + chNumeral = xmlSecBnToDecString( &bn ) ; + if( chNumeral == nullptr ) { + xmlSecBnFinalize( &bn ) ; + return aRet ; + } + + aRet = OUString::createFromAscii( reinterpret_cast<char*>(chNumeral) ) ; + + xmlSecBnFinalize( &bn ) ; + xmlFree( chNumeral ) ; + } + + return aRet ; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/certificateextension_certextn.cxx b/xmlsecurity/source/xmlsec/certificateextension_certextn.cxx new file mode 100644 index 0000000000..d7325759de --- /dev/null +++ b/xmlsecurity/source/xmlsec/certificateextension_certextn.cxx @@ -0,0 +1,47 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "certificateextension_certextn.hxx" + +#include <comphelper/sequence.hxx> + +CertificateExtension_CertExtn::CertificateExtension_CertExtn() + : m_critical(false) +{ +} + +void CertificateExtension_CertExtn::setCertExtn(const unsigned char* value, unsigned int vlen, + const unsigned char* id, unsigned int idlen, bool critical) +{ + if( value != nullptr && vlen != 0 ) { + m_xExtnValue = comphelper::arrayToSequence<sal_Int8>(value, vlen); + } else { + m_xExtnValue = css::uno::Sequence<sal_Int8>(); + } + + if( id != nullptr && idlen != 0 ) { + m_xExtnId = comphelper::arrayToSequence<sal_Int8>(id, idlen); + } else { + m_xExtnId = css::uno::Sequence<sal_Int8>(); + } + + m_critical = critical ; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/certificateextension_certextn.hxx b/xmlsecurity/source/xmlsec/certificateextension_certextn.hxx new file mode 100644 index 0000000000..ac84596c83 --- /dev/null +++ b/xmlsecurity/source/xmlsec/certificateextension_certextn.hxx @@ -0,0 +1,36 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <sal/config.h> +#include <com/sun/star/uno/Sequence.hxx> + +struct CertificateExtension_CertExtn +{ + bool m_critical; + css::uno::Sequence<sal_Int8> m_xExtnId; + css::uno::Sequence<sal_Int8> m_xExtnValue; + + CertificateExtension_CertExtn(); + void setCertExtn(unsigned char const* value, unsigned int vlen, unsigned char const* id, + unsigned int idlen, bool critical); +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/certificateextension_xmlsecimpl.hxx b/xmlsecurity/source/xmlsec/certificateextension_xmlsecimpl.hxx new file mode 100644 index 0000000000..9db5867fc7 --- /dev/null +++ b/xmlsecurity/source/xmlsec/certificateextension_xmlsecimpl.hxx @@ -0,0 +1,56 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <sal/config.h> +#include <cppuhelper/implbase.hxx> +#include <com/sun/star/security/XCertificateExtension.hpp> +#include "certificateextension_certextn.hxx" + +class CertificateExtension_XmlSecImpl : public ::cppu::WeakImplHelper< + css::security::XCertificateExtension > +{ + private: + CertificateExtension_CertExtn m_Extn; + + public: + //Methods from XCertificateExtension + virtual sal_Bool SAL_CALL isCritical() override + { + return m_Extn.m_critical; + } + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getExtensionId() override + { + return m_Extn.m_xExtnId; + } + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getExtensionValue() override + { + return m_Extn.m_xExtnValue; + } + + void setCertExtn(unsigned char const * value, unsigned int vlen, unsigned char const * id, unsigned int idlen, bool critical) + { + m_Extn.setCertExtn(value, vlen, id, idlen, critical); + } +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/errorcallback.cxx b/xmlsecurity/source/xmlsec/errorcallback.cxx new file mode 100644 index 0000000000..a535ffa770 --- /dev/null +++ b/xmlsecurity/source/xmlsec/errorcallback.cxx @@ -0,0 +1,68 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> +#include <xmlsec-wrapper.h> + +#include <xmlsec/errorcallback.hxx> + +#include <rtl/ustring.hxx> +#include <sal/log.hxx> + +#ifdef _WIN32 +#include <prewin.h> +#include <postwin.h> +#include <comphelper/windowserrorstring.hxx> +#endif + +extern "C" { + +static void errorCallback(const char* file, + int line, + const char* func, + const char* errorObject, + const char* errorSubject, + int reason, + const char* msg) +{ + const char* pErrorObject = errorObject ? errorObject : ""; + const char* pErrorSubject = errorSubject ? errorSubject : ""; + const char* pMsg = msg ? msg : ""; + OUString systemErrorString; + +#ifdef _WIN32 + systemErrorString = " " + WindowsErrorString(GetLastError()); +#endif + + SAL_WARN("xmlsecurity.xmlsec", file << ":" << line << ": " << func << "() '" << pErrorObject << "' '" << pErrorSubject << "' " << reason << " '" << pMsg << "'" << systemErrorString); +} + +} + +void setErrorRecorder() +{ + xmlSecErrorsSetCallback(errorCallback); +} + +void clearErrorRecorder() +{ + xmlSecErrorsSetCallback(nullptr); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/mscrypt/akmngr.cxx b/xmlsecurity/source/xmlsec/mscrypt/akmngr.cxx new file mode 100644 index 0000000000..ec3cecd4a7 --- /dev/null +++ b/xmlsecurity/source/xmlsec/mscrypt/akmngr.cxx @@ -0,0 +1,229 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> +#include <xmlsec-wrapper.h> + +#include "akmngr.hxx" + +#include <xmlsec/xmlsec.h> +#include <xmlsec/keys.h> +#include <xmlsec/keysmngr.h> +#include <xmlsec/transforms.h> +#include <xmlsec/errors.h> + +#include <xmlsec/mscng/crypto.h> +#include <xmlsec/mscng/keysstore.h> +#include <xmlsec/mscng/x509.h> +#include <svl/cryptosign.hxx> + +namespace xmlsecurity +{ + +/** + * MSCryptoAppliedKeysMngrCreate: + * + * Create and load key store and certificate database into keys manager + * + * Returns keys manager pointer on success or NULL otherwise. + */ +xmlSecKeysMngrPtr MSCryptoAppliedKeysMngrCreate() +{ + xmlSecKeysMngrPtr keyMngr = nullptr ; + xmlSecKeyStorePtr keyStore = nullptr ; + + keyStore = xmlSecKeyStoreCreate(xmlSecMSCngKeysStoreId); + if (keyStore == nullptr) + { + xmlSecError(XMLSEC_ERRORS_HERE, + nullptr, + "xmlSecKeyStoreCreate", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE) ; + return nullptr ; + } + + keyMngr = xmlSecKeysMngrCreate() ; + if (keyMngr == nullptr) + { + xmlSecError(XMLSEC_ERRORS_HERE, + nullptr, + "xmlSecKeysMngrCreate", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE) ; + + xmlSecKeyStoreDestroy(keyStore) ; + return nullptr ; + } + + /*- + * Add key store to manager, from now on keys manager destroys the store if + * needed + */ + if (xmlSecKeysMngrAdoptKeysStore(keyMngr, keyStore) < 0) + { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyStoreGetName(keyStore)), + "xmlSecKeysMngrAdoptKeyStore", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE) ; + + xmlSecKeyStoreDestroy(keyStore) ; + xmlSecKeysMngrDestroy(keyMngr) ; + return nullptr ; + } + + /*- + * Initialize crypto library specific data in keys manager + */ + if (xmlSecMSCngKeysMngrInit(keyMngr) < 0) + { + xmlSecError(XMLSEC_ERRORS_HERE, + nullptr, + "xmlSecMSCngKeysMngrInit", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + + xmlSecKeysMngrDestroy(keyMngr); + return nullptr; + } + + /*- + * Set certificate database to X509 key data store + */ + /*- + * At present, MS Crypto engine do not provide a way to setup a cert store. + */ + + /*- + * Set the getKey callback + */ + keyMngr->getKey = xmlSecKeysMngrGetKey ; + + return keyMngr ; +} + +int +MSCryptoAppliedKeysMngrAdoptKeyStore( + xmlSecKeysMngrPtr mngr, + HCERTSTORE keyStore +) +{ + xmlSecKeyDataStorePtr x509Store ; + + xmlSecAssert2(mngr != nullptr, -1) ; + xmlSecAssert2(keyStore != nullptr, -1) ; + + x509Store = xmlSecKeysMngrGetDataStore(mngr, xmlSecMSCngX509StoreId); + if (x509Store == nullptr) + { + xmlSecError(XMLSEC_ERRORS_HERE, + nullptr, + "xmlSecKeysMngrGetDataStore", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE) ; + return -1 ; + } + + if (xmlSecMSCngX509StoreAdoptKeyStore(x509Store, keyStore) < 0) + { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(x509Store)), + "xmlSecMSCngX509StoreAdoptKeyStore", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return -1; + } + + return 0 ; +} + +int +MSCryptoAppliedKeysMngrAdoptTrustedStore( + xmlSecKeysMngrPtr mngr, + HCERTSTORE trustedStore +) +{ + xmlSecKeyDataStorePtr x509Store ; + + xmlSecAssert2(mngr != nullptr, -1) ; + xmlSecAssert2(trustedStore != nullptr, -1) ; + + x509Store = xmlSecKeysMngrGetDataStore(mngr, xmlSecMSCngX509StoreId); + if (x509Store == nullptr) + { + xmlSecError(XMLSEC_ERRORS_HERE, + nullptr, + "xmlSecKeysMngrGetDataStore", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE) ; + return -1 ; + } + + if (xmlSecMSCngX509StoreAdoptTrustedStore(x509Store, trustedStore) < 0) + { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(x509Store)), + "xmlSecMSCngX509StoreAdoptKeyStore", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return -1; + } + + return 0 ; +} + +int +MSCryptoAppliedKeysMngrAdoptUntrustedStore( + xmlSecKeysMngrPtr mngr, + HCERTSTORE untrustedStore +) +{ + xmlSecKeyDataStorePtr x509Store ; + + xmlSecAssert2(mngr != nullptr, -1) ; + xmlSecAssert2(untrustedStore != nullptr, -1) ; + + x509Store = xmlSecKeysMngrGetDataStore(mngr, xmlSecMSCngX509StoreId); + if (x509Store == nullptr) + { + xmlSecError(XMLSEC_ERRORS_HERE, + nullptr, + "xmlSecKeysMngrGetDataStore", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE) ; + return -1 ; + } + + if (xmlSecMSCngX509StoreAdoptUntrustedStore(x509Store, untrustedStore) < 0) + { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(x509Store)), + "xmlSecMSCngX509StoreAdoptKeyStore", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return -1; + } + + return 0 ; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/xmlsecurity/source/xmlsec/mscrypt/akmngr.hxx b/xmlsecurity/source/xmlsec/mscrypt/akmngr.hxx new file mode 100644 index 0000000000..e5942ba2af --- /dev/null +++ b/xmlsecurity/source/xmlsec/mscrypt/akmngr.hxx @@ -0,0 +1,56 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#if !defined WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +#endif +#include <windows.h> +#include <wincrypt.h> + +#include <xmlsec/xmlsec.h> +#include <xmlsec/keys.h> +#include <xmlsec/transforms.h> + +namespace xmlsecurity +{ + +xmlSecKeysMngrPtr MSCryptoAppliedKeysMngrCreate(); + +int +MSCryptoAppliedKeysMngrAdoptKeyStore( + xmlSecKeysMngrPtr mngr, + HCERTSTORE keyStore +) ; + +int +MSCryptoAppliedKeysMngrAdoptTrustedStore( + xmlSecKeysMngrPtr mngr, + HCERTSTORE trustedStore +) ; + +int +MSCryptoAppliedKeysMngrAdoptUntrustedStore( + xmlSecKeysMngrPtr mngr, + HCERTSTORE untrustedStore +) ; + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/xmlsecurity/source/xmlsec/mscrypt/oid.hxx b/xmlsecurity/source/xmlsec/mscrypt/oid.hxx new file mode 100644 index 0000000000..ce573d8827 --- /dev/null +++ b/xmlsecurity/source/xmlsec/mscrypt/oid.hxx @@ -0,0 +1,153 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <sal/macros.h> + +typedef struct { + char const *oid; + char const *desc; +} OIDItem; + +OIDItem OIDs[] = { + {"1.2.840.113549", "RSA Data Security Inc."}, + {"1.2.840.113549.1", "PKCS"}, + {"1.2.840.113549.2", "RSA digest algorithm"}, + {"1.2.840.113549.3", "RSA cipher algorithm"}, + {"1.2.840.113549.1.1", "PKCS #1"}, + {"1.2.840.113549.1.2", "Unknown"}, + {"1.2.840.113549.1.3", "Unknown"}, + {"1.2.840.113549.1.4", "Unknown"}, + {"1.2.840.113549.1.5", "PKCS #5"}, + {"1.2.840.113549.1.6", "Unknown"}, + {"1.2.840.113549.1.7", "PKCS #7"}, + {"1.2.840.113549.1.8", "Unknown"}, + {"1.2.840.113549.1.9", "PKCS #9"}, + {"1.2.840.113549.1.10", "Unknown"}, + {"1.2.840.113549.1.12", "PKCS #12"}, + {"1.2.840.113549.1.1.2", "PKCS #1 MD2 With RSA Encryption"}, + {"1.2.840.113549.1.1.3", "PKCS #1 MD4 With RSA Encryption"}, + {"1.2.840.113549.1.1.4", "PKCS #1 MD5 With RSA Encryption"}, + {"1.2.840.113549.1.1.1", "PKCS #1 RSA Encryption"}, + {"1.2.840.113549.1.1.2", "PKCS #1 MD2 With RSA Encryption"}, + {"1.2.840.113549.1.1.3", "PKCS #1 MD4 With RSA Encryption"}, + {"1.2.840.113549.1.1.4", "PKCS #1 MD5 With RSA Encryption"}, + {"1.2.840.113549.1.1.5", "PKCS #1 SHA-1 With RSA Encryption"}, + {"1.2.840.113549.1.1.5", "PKCS #1 SHA-1 With RSA Encryption"}, + {"1.2.840.113549.1.3.1", "Unknown"}, + {"1.2.840.113549.1.7.1", "PKCS #7 Data"}, + {"1.2.840.113549.1.7.2", "PKCS #7 Signed Data"}, + {"1.2.840.113549.1.7.3", "PKCS #7 Enveloped Data"}, + {"1.2.840.113549.1.7.4", "PKCS #7 Signed and Enveloped Data"}, + {"1.2.840.113549.1.7.5", "PKCS #7 Digested Data"}, + {"1.2.840.113549.1.7.6", "PKCS #7 Encrypted Data"}, + {"1.2.840.113549.1.9.1", "PKCS #9 Email Address"}, + {"1.2.840.113549.1.9.2", "PKCS #9 Unstructured Name"}, + {"1.2.840.113549.1.9.3", "PKCS #9 Content Type"}, + {"1.2.840.113549.1.9.4", "PKCS #9 Message Digest"}, + {"1.2.840.113549.1.9.5", "PKCS #9 Signing Time"}, + {"1.2.840.113549.1.9.6", "PKCS #9 Counter Signature"}, + {"1.2.840.113549.1.9.7", "PKCS #9 Challenge Password"}, + {"1.2.840.113549.1.9.8", "PKCS #9 Unstructured Address"}, + {"1.2.840.113549.1.9.9", "PKCS #9 Extended Certificate Attributes"}, + {"1.2.840.113549.1.9.15", "PKCS #9 S/MIME Capabilities"}, + {"1.2.840.113549.1.9.15.1", "Unknown"}, + {"1.2.840.113549.3.2", "RC2-CBC"}, + {"1.2.840.113549.3.4", "RC4"}, + {"1.2.840.113549.3.7", "DES-EDE3-CBC"}, + {"1.2.840.113549.3.9", "RC5-CBCPad"}, + {"1.2.840.10046", "ANSI X9.42"}, + {"1.2.840.10046.2.1", "Diffie-Hellman Public Key Algorithm"}, + {"1.2.840.10040", "ANSI X9.57"}, + {"1.2.840.10040.4.1", "ANSI X9.57 DSA Signature"}, + {"1.2.840.10040.4.3", "ANSI X9.57 Algorithm DSA Signature with SHA-1 Digest"}, + {"2.5", "Directory"}, + {"2.5.8", "X.500-defined algorithms"}, + {"2.5.8.1", "X.500-defined encryption algorithms"}, + {"2.5.8.2", "Unknown"}, + {"2.5.8.3", "Unknown"}, + {"2.5.8.1.1", "RSA Encryption Algorithm"}, + {"1.3.14", "Open Systems Implementors Workshop"}, + {"1.3.14.3.2", "OIW SECSIG Algorithm"}, + {"1.3.14.3.2.2", "Unknown"}, + {"1.3.14.3.2.3", "Unknown"}, + {"1.3.14.3.2.4", "Unknown"}, + {"1.3.14.3.2.6", "DES-ECB"}, + {"1.3.14.3.2.7", "DES-CBC"}, + {"1.3.14.3.2.8", "DES-OFB"}, + {"1.3.14.3.2.9", "DES-CFB"}, + {"1.3.14.3.2.10", "DES-MAC"}, + {"1.3.14.3.2.11", "Unknown"}, + {"1.3.14.3.2.12", "Unknown"}, + {"1.3.14.3.2.13", "Unknown"}, + {"1.3.14.3.2.14", "Unknown"}, + {"1.3.14.3.2.15", "ISO SHA with RSA Signature"}, + {"1.3.14.3.2.16", "Unknown"}, + {"1.3.14.3.2.17", "DES-EDE"}, + {"1.3.14.3.2.18", "Unknown"}, + {"1.3.14.3.2.19", "Unknown"}, + {"1.3.14.3.2.20", "Unknown"}, + {"1.3.14.3.2.21", "Unknown"}, + {"1.3.14.3.2.22", "Unknown"}, + {"1.3.14.3.2.23", "Unknown"}, + {"1.3.14.3.2.24", "Unknown"}, + {"1.3.14.3.2.25", "Unknown"}, + {"1.3.14.3.2.26", "SHA-1"}, + {"1.3.14.3.2.27", "Forgezza DSA Signature with SHA-1 Digest"}, + {"1.3.14.3.2.28", "Unknown"}, + {"1.3.14.3.2.29", "Unknown"}, + {"1.3.14.7.2", "Unknown"}, + {"1.3.14.7.2.1", "Unknown"}, + {"1.3.14.7.2.2", "Unknown"}, + {"1.3.14.7.2.3", "Unknown"}, + {"1.3.14.7.2.2.1", "Unknown"}, + {"1.3.14.7.2.3.1", "Unknown"}, + {"2.16.840.1.101.2.1", "US DOD Infosec"}, + {"2.16.840.1.101.2.1.1.1", "Unknown"}, + {"2.16.840.1.101.2.1.1.2", "MISSI DSS Algorithm (Old)"}, + {"2.16.840.1.101.2.1.1.3", "Unknown"}, + {"2.16.840.1.101.2.1.1.4", "Skipjack CBC64"}, + {"2.16.840.1.101.2.1.1.5", "Unknown"}, + {"2.16.840.1.101.2.1.1.6", "Unknown"}, + {"2.16.840.1.101.2.1.1.7", "Unknown"}, + {"2.16.840.1.101.2.1.1.8", "Unknown"}, + {"2.16.840.1.101.2.1.1.9", "Unknown"}, + {"2.16.840.1.101.2.1.1.10", "MISSI KEA Algorithm"}, + {"2.16.840.1.101.2.1.1.11", "Unknown"}, + {"2.16.840.1.101.2.1.1.12", "MISSI KEA and DSS Algorithm (Old)"}, + {"2.16.840.1.101.2.1.1.13", "Unknown"}, + {"2.16.840.1.101.2.1.1.14", "Unknown"}, + {"2.16.840.1.101.2.1.1.15", "Unknown"}, + {"2.16.840.1.101.2.1.1.16", "Unknown"}, + {"2.16.840.1.101.2.1.1.17", "Unknown"}, + {"2.16.840.1.101.2.1.1.18", "Unknown"}, + {"2.16.840.1.101.2.1.1.19", "MISSI DSS Algorithm"}, + {"2.16.840.1.101.2.1.1.20", "MISSI KEA and DSS Algorithm"}, + {"2.16.840.1.101.2.1.1.21", "Unknown"}, + {"1.2.643.2.2.35.0", "GOST_R_34.10-2001_Test"}, + {"1.2.643.2.2.35.1", "GOST_R_34.10-2001_Sign_DH_PRO"}, + {"1.2.643.2.2.35.2", "GOST_R_34.10-2001_Sign_DH_CARD"}, + {"1.2.643.2.2.35.3", "GOST_R_34.10-2001_Sign_DH"}, + {"1.2.643.2.2.36.0", "GOST_R_34.10-2001_Sign_DH_PRO"} +}; + +const int nOID = SAL_N_ELEMENTS(OIDs); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/mscrypt/sanextension_mscryptimpl.cxx b/xmlsecurity/source/xmlsec/mscrypt/sanextension_mscryptimpl.cxx new file mode 100644 index 0000000000..6ded5fa0cb --- /dev/null +++ b/xmlsecurity/source/xmlsec/mscrypt/sanextension_mscryptimpl.cxx @@ -0,0 +1,131 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include <memory> + +#include <rtl/uuid.h> +#include <rtl/ustring.hxx> +#include <com/sun/star/security/ExtAltNameType.hpp> +#include <com/sun/star/security/CertAltNameEntry.hpp> +#include <com/sun/star/beans/NamedValue.hpp> +#include <comphelper/sequence.hxx> +#include <o3tl/char16_t2wchar_t.hxx> + +#include "sanextension_mscryptimpl.hxx" + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno ; +using namespace ::com::sun::star::security ; + +using ::com::sun::star::security::XCertificateExtension ; + + +SanExtensionImpl::SanExtensionImpl() : + m_critical( false ) +{ +} + +SanExtensionImpl::~SanExtensionImpl() { +} + + +//Methods from XCertificateExtension +sal_Bool SAL_CALL SanExtensionImpl::isCritical() { + return m_critical ; +} + +css::uno::Sequence< sal_Int8 > SAL_CALL SanExtensionImpl::getExtensionId() { + return m_xExtnId ; +} + +css::uno::Sequence< sal_Int8 > SAL_CALL SanExtensionImpl::getExtensionValue() { + return m_xExtnValue ; +} + +//Methods from XSanExtension +css::uno::Sequence< css::security::CertAltNameEntry > SAL_CALL SanExtensionImpl::getAlternativeNames(){ + + if (!m_Entries.hasElements()) + { + CERT_ALT_NAME_INFO *subjectName; + DWORD size; + CryptDecodeObjectEx(X509_ASN_ENCODING, X509_ALTERNATE_NAME, reinterpret_cast<unsigned char*>(m_xExtnValue.getArray()), m_xExtnValue.getLength(), CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG, nullptr,&subjectName, &size); + + auto arrCertAltNameEntry = std::make_unique<CertAltNameEntry[]>(subjectName->cAltEntry); + + for (unsigned int i = 0; i < static_cast<unsigned int>(subjectName->cAltEntry); i++){ + PCERT_ALT_NAME_ENTRY pEntry = &subjectName->rgAltEntry[i]; + + switch(pEntry->dwAltNameChoice) { + case CERT_ALT_NAME_OTHER_NAME : + { + arrCertAltNameEntry[i].Type = ExtAltNameType_OTHER_NAME; + PCERT_OTHER_NAME pOtherName = pEntry->pOtherName; + + css::beans::NamedValue otherNameProp; + otherNameProp.Name = OUString::createFromAscii(pOtherName->pszObjId); + + Sequence< sal_Int8 > otherName( comphelper::arrayToSequence<sal_Int8>( + pOtherName->Value.pbData, pOtherName->Value.cbData) ); + otherNameProp.Value <<= otherName; + + arrCertAltNameEntry[i].Value <<= otherNameProp; + break; + } + case CERT_ALT_NAME_RFC822_NAME : + arrCertAltNameEntry[i].Type = ExtAltNameType_RFC822_NAME; + arrCertAltNameEntry[i].Value <<= OUString(o3tl::toU(pEntry->pwszRfc822Name)); + break; + case CERT_ALT_NAME_DNS_NAME : + arrCertAltNameEntry[i].Type = ExtAltNameType_DNS_NAME; + arrCertAltNameEntry[i].Value <<= OUString(o3tl::toU(pEntry->pwszDNSName)); + break; + case CERT_ALT_NAME_DIRECTORY_NAME : + { + arrCertAltNameEntry[i].Type = ExtAltNameType_DIRECTORY_NAME; + break; + } + case CERT_ALT_NAME_URL : + arrCertAltNameEntry[i].Type = ExtAltNameType_URL; + arrCertAltNameEntry[i].Value <<= OUString(o3tl::toU(pEntry->pwszURL)); + break; + case CERT_ALT_NAME_IP_ADDRESS : + { + arrCertAltNameEntry[i].Type = ExtAltNameType_IP_ADDRESS; + + Sequence< sal_Int8 > ipAddress( comphelper::arrayToSequence<sal_Int8>( + pEntry->IPAddress.pbData, pEntry->IPAddress.cbData) ); + arrCertAltNameEntry[i].Value <<= ipAddress; + break; + } + case CERT_ALT_NAME_REGISTERED_ID : + arrCertAltNameEntry[i].Type = ExtAltNameType_REGISTERED_ID; + arrCertAltNameEntry[i].Value <<= OUString::createFromAscii(pEntry->pszRegisteredID); + break; + } + } + m_Entries = ::comphelper::arrayToSequence< css::security::CertAltNameEntry >(arrCertAltNameEntry.get(), subjectName->cAltEntry); + } + + return m_Entries; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/mscrypt/sanextension_mscryptimpl.hxx b/xmlsecurity/source/xmlsec/mscrypt/sanextension_mscryptimpl.hxx new file mode 100644 index 0000000000..6c65c84f86 --- /dev/null +++ b/xmlsecurity/source/xmlsec/mscrypt/sanextension_mscryptimpl.hxx @@ -0,0 +1,66 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#if !defined WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +#endif +#include <Windows.h> +#include <WinCrypt.h> +#include <sal/config.h> +#include <rtl/ustring.hxx> +#include <cppuhelper/factory.hxx> +#include <cppuhelper/implbase.hxx> +#include <com/sun/star/uno/Exception.hpp> +#include <com/sun/star/uno/SecurityException.hpp> +#include <com/sun/star/security/XCertificateExtension.hpp> +#include <com/sun/star/security/XSanExtension.hpp> +#include <com/sun/star/security/CertAltNameEntry.hpp> + +class SanExtensionImpl : public ::cppu::WeakImplHelper< + css::security::XSanExtension > +{ + private: + bool m_critical ; + css::uno::Sequence< sal_Int8 > m_xExtnId ; + css::uno::Sequence< sal_Int8 > m_xExtnValue ; + + css::uno::Sequence< css::security::CertAltNameEntry > m_Entries; + + public: + SanExtensionImpl() ; + virtual ~SanExtensionImpl() override; + + //Methods from XCertificateExtension + virtual sal_Bool SAL_CALL isCritical() override; + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getExtensionId() override; + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getExtensionValue() override; + + //Methods from XSanExtension + + virtual css::uno::Sequence< css::security::CertAltNameEntry > SAL_CALL getAlternativeNames() override; + + //Helper method + void setCertExtn( unsigned char* value, unsigned int vlen, unsigned char* id, unsigned int idlen, bool critical ) ; +} ; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.cxx b/xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.cxx new file mode 100644 index 0000000000..cd3d40eb14 --- /dev/null +++ b/xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.cxx @@ -0,0 +1,1110 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include <cstddef> +#include <string.h> + +#if !defined WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +#endif +#include <Windows.h> +#include <WinCrypt.h> +#include <sal/macros.h> +#include <osl/thread.h> +#include "securityenvironment_mscryptimpl.hxx" + +#include "x509certificate_mscryptimpl.hxx" +#include <comphelper/servicehelper.hxx> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <cppuhelper/supportsservice.hxx> +#include <xmlsec-wrapper.h> +#include "akmngr.hxx" + +#include <biginteger.hxx> + +#include <comphelper/sequence.hxx> +#include <comphelper/windowserrorstring.hxx> +#include <sal/log.hxx> +#include <rtl/locale.h> +#include <rtl/ref.hxx> +#include <osl/nlsupport.h> +#include <osl/process.h> +#include <o3tl/char16_t2wchar_t.hxx> +#include <svl/cryptosign.hxx> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::lang ; + +using ::com::sun::star::xml::crypto::XSecurityEnvironment ; +using ::com::sun::star::security::XCertificate ; + +static rtl::Reference<X509Certificate_MSCryptImpl> MswcryCertContextToXCert( PCCERT_CONTEXT cert ) ; + +namespace { + +struct CertErrorToString{ + DWORD error; + char const * name; +}; + +} + +CertErrorToString const arErrStrings[] = +{ + { 0x00000000, "CERT_TRUST_NO_ERROR"}, + { 0x00000001, "CERT_TRUST_IS_NOT_TIME_VALID"}, + { 0x00000002, "CERT_TRUST_IS_NOT_TIME_NESTED"}, + { 0x00000004, "CERT_TRUST_IS_REVOKED" }, + { 0x00000008, "CERT_TRUST_IS_NOT_SIGNATURE_VALID" }, + { 0x00000010, "CERT_TRUST_IS_NOT_SIGNATURE_VALID"}, + { 0x00000020, "CERT_TRUST_IS_UNTRUSTED_ROOT"}, + { 0x00000040, "CERT_TRUST_REVOCATION_STATUS_UNKNOWN"}, + { 0x00000080, "CERT_TRUST_IS_CYCLIC"}, + { 0x00000100, "CERT_TRUST_INVALID_EXTENSION"}, + { 0x00000200, "CERT_TRUST_INVALID_POLICY_CONSTRAINTS"}, + { 0x00000400, "CERT_TRUST_INVALID_BASIC_CONSTRAINTS"}, + { 0x00000800, "CERT_TRUST_INVALID_NAME_CONSTRAINTS"}, + { 0x00001000, "CERT_TRUST_HAS_NOT_SUPPORTED_NAME_CONSTRAINT"}, + { 0x00002000, "CERT_TRUST_HAS_NOT_DEFINED_NAME_CONSTRAINT"}, + { 0x00004000, "CERT_TRUST_HAS_NOT_PERMITTED_NAME_CONSTRAINT"}, + { 0x00008000, "CERT_TRUST_HAS_EXCLUDED_NAME_CONSTRAINT"}, + { 0x01000000, "CERT_TRUST_IS_OFFLINE_REVOCATION"}, + { 0x02000000, "CERT_TRUST_NO_ISSUANCE_CHAIN_POLICY"}, + { 0x04000000, "CERT_TRUST_IS_EXPLICIT_DISTRUST"}, + { 0x08000000, "CERT_TRUST_HAS_NOT_SUPPORTED_CRITICAL_EXT"}, + //Chain errors + { 0x00010000, "CERT_TRUST_IS_PARTIAL_CHAIN"}, + { 0x00020000, "CERT_TRUST_CTL_IS_NOT_TIME_VALID"}, + { 0x00040000, "CERT_TRUST_CTL_IS_NOT_SIGNATURE_VALID"}, + { 0x00080000, "CERT_TRUST_CTL_IS_NOT_VALID_FOR_USAGE"} +}; + +static void traceTrustStatus(DWORD err) +{ + if (err == 0) + SAL_INFO("xmlsecurity.xmlsec", " " << arErrStrings[0].name); + for (auto const & arErrStringIter : arErrStrings) + { + if (arErrStringIter.error & err) + SAL_INFO("xmlsecurity.xmlsec", " " << arErrStringIter.name); + } +} + +SecurityEnvironment_MSCryptImpl::SecurityEnvironment_MSCryptImpl( const uno::Reference< uno::XComponentContext >& xContext ) : m_hProv( 0 ) , m_pszContainer( nullptr ) , m_hKeyStore( nullptr ), m_hCertStore( nullptr ), m_hMySystemStore(nullptr), m_hRootSystemStore(nullptr), m_hTrustSystemStore(nullptr), m_hCaSystemStore(nullptr), m_bEnableDefault( false ){ + + m_xServiceManager.set(xContext, uno::UNO_QUERY); +} + +SecurityEnvironment_MSCryptImpl::~SecurityEnvironment_MSCryptImpl() { + + if( m_hProv != 0 ) { + CryptReleaseContext( m_hProv, 0 ) ; + m_hProv = 0 ; + } + + if( m_pszContainer != nullptr ) { + //TODO: Don't know whether or not it should be released now. + m_pszContainer = nullptr ; + } + + if( m_hCertStore != nullptr ) { + CertCloseStore( m_hCertStore, CERT_CLOSE_STORE_FORCE_FLAG ) ; + m_hCertStore = nullptr ; + } + + if( m_hKeyStore != nullptr ) { + CertCloseStore( m_hKeyStore, CERT_CLOSE_STORE_FORCE_FLAG ) ; + m_hKeyStore = nullptr ; + } + + //i120675, close the store handles + if( m_hMySystemStore != nullptr ) { + CertCloseStore( m_hMySystemStore, CERT_CLOSE_STORE_CHECK_FLAG ) ; + m_hMySystemStore = nullptr ; + } + + if( m_hRootSystemStore != nullptr ) { + CertCloseStore( m_hRootSystemStore, CERT_CLOSE_STORE_CHECK_FLAG ) ; + m_hRootSystemStore = nullptr ; + } + + if( m_hTrustSystemStore != nullptr ) { + CertCloseStore( m_hTrustSystemStore, CERT_CLOSE_STORE_CHECK_FLAG ) ; + m_hTrustSystemStore = nullptr ; + } + + if( m_hCaSystemStore != nullptr ) { + CertCloseStore( m_hCaSystemStore, CERT_CLOSE_STORE_CHECK_FLAG ) ; + m_hCaSystemStore = nullptr ; + } +} + +/* XServiceInfo */ +OUString SAL_CALL SecurityEnvironment_MSCryptImpl::getImplementationName() { + return "com.sun.star.xml.crypto.SecurityEnvironment"; +} + +/* XServiceInfo */ +sal_Bool SAL_CALL SecurityEnvironment_MSCryptImpl::supportsService( const OUString& serviceName) { + return cppu::supportsService(this, serviceName); +} +/* XServiceInfo */ +uno::Sequence< OUString > SAL_CALL SecurityEnvironment_MSCryptImpl::getSupportedServiceNames() { + return { "com.sun.star.xml.crypto.SecurityEnvironment" }; +} + +HCRYPTPROV SecurityEnvironment_MSCryptImpl::getCryptoProvider() { + return m_hProv ; +} + +void SecurityEnvironment_MSCryptImpl::setCryptoProvider( HCRYPTPROV aProv ) { + if( m_hProv != 0 ) { + CryptReleaseContext( m_hProv, 0 ) ; + m_hProv = 0 ; + } + + if( aProv != 0 ) { + m_hProv = aProv ; + } +} + +LPCTSTR SecurityEnvironment_MSCryptImpl::getKeyContainer() { + return m_pszContainer ; +} + +void SecurityEnvironment_MSCryptImpl::setKeyContainer( LPCTSTR aKeyContainer ) { + //TODO: Don't know whether or not it should be copied. + m_pszContainer = aKeyContainer ; +} + + +HCERTSTORE SecurityEnvironment_MSCryptImpl::getCryptoSlot() { + return m_hKeyStore ; +} + +void SecurityEnvironment_MSCryptImpl::setCryptoSlot( HCERTSTORE aSlot) { + if( m_hKeyStore != nullptr ) { + CertCloseStore( m_hKeyStore, CERT_CLOSE_STORE_FORCE_FLAG ) ; + m_hKeyStore = nullptr ; + } + + if( aSlot != nullptr ) { + m_hKeyStore = CertDuplicateStore( aSlot ) ; + } +} + +HCERTSTORE SecurityEnvironment_MSCryptImpl::getCertDb() { + return m_hCertStore ; +} + +void SecurityEnvironment_MSCryptImpl::setCertDb( HCERTSTORE aCertDb ) { + if( m_hCertStore != nullptr ) { + CertCloseStore( m_hCertStore, CERT_CLOSE_STORE_FORCE_FLAG ) ; + m_hCertStore = nullptr ; + } + + if( aCertDb != nullptr ) { + m_hCertStore = CertDuplicateStore( aCertDb ) ; + } +} + +#ifdef SAL_LOG_INFO + +// Based on sample code from MSDN + +static OUString get_system_name(const void *pvSystemStore, + DWORD dwFlags) +{ + LPCWSTR ppwszSystemName; + if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG) + { + _CERT_SYSTEM_STORE_RELOCATE_PARA const * pRelocatePara; + pRelocatePara = static_cast<_CERT_SYSTEM_STORE_RELOCATE_PARA const *>(pvSystemStore); + ppwszSystemName = pRelocatePara->pwszSystemStore; + } + else + { + ppwszSystemName = static_cast<LPCWSTR>(pvSystemStore); + } + return OUString(o3tl::toU(ppwszSystemName)); +} + +extern "C" { + +static BOOL WINAPI cert_enum_physical_store_callback(const void *, + DWORD dwFlags, + LPCWSTR pwszStoreName, + PCERT_PHYSICAL_STORE_INFO, + void *, + void *) +{ + OUString name(o3tl::toU(pwszStoreName)); + if (dwFlags & CERT_PHYSICAL_STORE_PREDEFINED_ENUM_FLAG) + name += " (implicitly created)"; + SAL_INFO("xmlsecurity.xmlsec", " Physical store: " << name); + + return TRUE; +} + +static BOOL WINAPI cert_enum_system_store_callback(const void *pvSystemStore, + DWORD dwFlags, + PCERT_SYSTEM_STORE_INFO, + void *, + void *) +{ + SAL_INFO("xmlsecurity.xmlsec", "System store: " << get_system_name(pvSystemStore, dwFlags)); + + if (!CertEnumPhysicalStore(pvSystemStore, + dwFlags, + nullptr, + cert_enum_physical_store_callback)) + { + DWORD dwErr = GetLastError(); + if (!(ERROR_FILE_NOT_FOUND == dwErr || + ERROR_NOT_SUPPORTED == dwErr)) + { + SAL_WARN("xmlsecurity.xmlsec", "CertEnumPhysicalStore failed:" << WindowsErrorString(GetLastError())); + } + } + return TRUE; +} + +} + +#endif + +//Methods from XSecurityEnvironment +uno::Sequence< uno::Reference < XCertificate > > SecurityEnvironment_MSCryptImpl::getPersonalCertificates() +{ + sal_Int32 length ; + rtl::Reference<X509Certificate_MSCryptImpl> xcert ; + std::vector< rtl::Reference<X509Certificate_MSCryptImpl> > certsList ; + PCCERT_CONTEXT pCertContext = nullptr; + + //firstly, we try to find private keys in given key store. + if( m_hKeyStore != nullptr ) { + pCertContext = CertEnumCertificatesInStore( m_hKeyStore, pCertContext ); + while (pCertContext) + { + xcert = MswcryCertContextToXCert( pCertContext ) ; + if( xcert.is() ) + certsList.push_back( xcert ) ; + pCertContext = CertEnumCertificatesInStore( m_hKeyStore, pCertContext ); + } + } + + //Thirdly, we try to find certificate from system default key store. + if( m_bEnableDefault ) { + HCERTSTORE hSystemKeyStore ; + DWORD dwKeySpec; + NCRYPT_KEY_HANDLE hCryptKey; + +#ifdef SAL_LOG_INFO + CertEnumSystemStore(CERT_SYSTEM_STORE_CURRENT_USER, nullptr, nullptr, cert_enum_system_store_callback); +#endif + + hSystemKeyStore = CertOpenSystemStoreW( 0, L"MY" ) ; + if( hSystemKeyStore != nullptr ) { + pCertContext = CertEnumCertificatesInStore( hSystemKeyStore, pCertContext ); + while (pCertContext) + { + // for checking whether the certificate is a personal certificate or not. + DWORD dwFlags = CRYPT_ACQUIRE_COMPARE_KEY_FLAG | CRYPT_ACQUIRE_ONLY_NCRYPT_KEY_FLAG; + HCRYPTPROV_OR_NCRYPT_KEY_HANDLE* phCryptProvOrNCryptKey = &hCryptKey; + if(!(CryptAcquireCertificatePrivateKey(pCertContext, + dwFlags, + nullptr, + phCryptProvOrNCryptKey, + &dwKeySpec, + nullptr))) + { + // Not Privatekey found. SKIP this one. + pCertContext = CertEnumCertificatesInStore( hSystemKeyStore, pCertContext ); + continue; + } + // then TODO : Check the personal cert is valid or not. + + xcert = MswcryCertContextToXCert( pCertContext ) ; + if( xcert.is() ) + certsList.push_back( xcert ) ; + pCertContext = CertEnumCertificatesInStore( hSystemKeyStore, pCertContext ); + } + } + + CertCloseStore( hSystemKeyStore, CERT_CLOSE_STORE_CHECK_FLAG ) ; + } + + length = certsList.size() ; + if( length != 0 ) { + int i = 0; + uno::Sequence< uno::Reference< XCertificate > > certSeq( length ) ; + auto pcertSeq = certSeq.getArray(); + + for( const auto& rXCert : certsList ) { + pcertSeq[i] = rXCert ; + ++i; + } + + return certSeq ; + } + + return uno::Sequence< uno::Reference< XCertificate > >() ; +} + + +uno::Reference< XCertificate > SecurityEnvironment_MSCryptImpl::getCertificate( const OUString& issuerName, const uno::Sequence< sal_Int8 >& serialNumber ) { + unsigned int i ; + rtl::Reference<X509Certificate_MSCryptImpl> xcert ; + PCCERT_CONTEXT pCertContext = nullptr ; + HCERTSTORE hCertStore = nullptr ; + CRYPT_INTEGER_BLOB cryptSerialNumber ; + CERT_INFO certInfo ; + + // for correct encoding + rtl_Locale *pLocale = nullptr ; + osl_getProcessLocale( &pLocale ) ; + + //Create cert info from issue and serial + LPCWSTR pszName = o3tl::toW( issuerName.getStr() ); + + if( ! ( CertStrToNameW( + X509_ASN_ENCODING | PKCS_7_ASN_ENCODING , + pszName , + CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG | CERT_NAME_STR_ENABLE_UTF8_UNICODE_FLAG, + nullptr , + nullptr , + &certInfo.Issuer.cbData, nullptr ) ) + ) { + return nullptr ; + } + + certInfo.Issuer.pbData = static_cast<BYTE*>(malloc( certInfo.Issuer.cbData )); + if(!certInfo.Issuer.pbData) + throw uno::RuntimeException() ; + + if( ! ( CertStrToNameW( + X509_ASN_ENCODING | PKCS_7_ASN_ENCODING , + pszName , + CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG | CERT_NAME_STR_ENABLE_UTF8_UNICODE_FLAG, + nullptr , + certInfo.Issuer.pbData , + &certInfo.Issuer.cbData, nullptr ) ) + ) { + free( certInfo.Issuer.pbData ) ; + return nullptr ; + } + + //Get the SerialNumber + cryptSerialNumber.cbData = serialNumber.getLength() ; + cryptSerialNumber.pbData = static_cast<BYTE*>(malloc( cryptSerialNumber.cbData)); + if (!cryptSerialNumber.pbData) + { + free( certInfo.Issuer.pbData ) ; + throw uno::RuntimeException() ; + } + for( i = 0; i < cryptSerialNumber.cbData; i ++ ) + cryptSerialNumber.pbData[i] = serialNumber[ cryptSerialNumber.cbData - i - 1 ] ; + + certInfo.SerialNumber.cbData = cryptSerialNumber.cbData ; + certInfo.SerialNumber.pbData = cryptSerialNumber.pbData ; + + // Get the Cert from all store. + for( i = 0 ; i < 6 ; i ++ ) + { + switch(i) + { + case 0: + if(m_hKeyStore == nullptr) continue ; + hCertStore = m_hKeyStore ; + break; + case 1: + if(m_hCertStore == nullptr) continue ; + hCertStore = m_hCertStore ; + break; + case 2: + hCertStore = CertOpenSystemStoreW( 0, L"MY" ) ; + if(hCertStore == nullptr || !m_bEnableDefault) continue ; + break; + case 3: + hCertStore = CertOpenSystemStoreW( 0, L"Root" ) ; + if(hCertStore == nullptr || !m_bEnableDefault) continue ; + break; + case 4: + hCertStore = CertOpenSystemStoreW( 0, L"Trust" ) ; + if(hCertStore == nullptr || !m_bEnableDefault) continue ; + break; + case 5: + hCertStore = CertOpenSystemStoreW( 0, L"CA" ) ; + if(hCertStore == nullptr || !m_bEnableDefault) continue ; + break; + default: + i=6; + continue; + } + +/******************************************************************************* + * This code reserved for remind us there are another way to find one cert by + * IssuerName&serialnumber. You can use the code to replaced the function + * CertFindCertificateInStore IF and ONLY IF you must find one special cert in + * certStore but can not be found by CertFindCertificateInStore , then , you + * should also change the same part in libxmlsec/.../src/mscrypto/x509vfy.c#875. + * By Chandler Peng(chandler.peng@sun.com) + *****/ +/******************************************************************************* + pCertContext = NULL ; + found = 0; + do{ + // 1. enum the certs has same string in the issuer string. + pCertContext = CertEnumCertificatesInStore( hCertStore , pCertContext ) ; + if( pCertContext != NULL ) + { + // 2. check the cert's issuer name . + char* issuer = NULL ; + DWORD cbIssuer = 0 ; + + cbIssuer = CertNameToStr( + X509_ASN_ENCODING | PKCS_7_ASN_ENCODING , + &( pCertContext->pCertInfo->Issuer ), + CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG , + NULL, 0 + ) ; + + if( cbIssuer == 0 ) continue ; // discard this cert; + + issuer = (char *)malloc( cbIssuer ) ; + if( issuer == NULL ) // discard this cert; + { + free( cryptSerialNumber.pbData) ; + free( certInfo.Issuer.pbData ) ; + CertFreeCertificateContext( pCertContext ) ; + if(i != 0 && i != 1) CertCloseStore( hCertStore, CERT_CLOSE_STORE_CHECK_FLAG ) ; + throw RuntimeException() ; + } + + cbIssuer = CertNameToStr( + X509_ASN_ENCODING | PKCS_7_ASN_ENCODING , + &( pCertContext->pCertInfo->Issuer ), + CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG , + issuer, cbIssuer + ) ; + + if( cbIssuer <= 0 ) + { + free( issuer ) ; + continue ;// discard this cert; + } + + if(strncmp(pszName , issuer , cbIssuer) != 0) + { + free( issuer ) ; + continue ;// discard this cert; + } + free( issuer ) ; + + // 3. check the serial number. + if( memcmp( cryptSerialNumber.pbData , pCertContext->pCertInfo->SerialNumber.pbData , cryptSerialNumber.cbData ) != 0 ) + { + continue ;// discard this cert; + } + + // 4. confirm and break; + found = 1; + break ; + } + + }while(pCertContext); + + if(i != 0 && i != 1) CertCloseStore( hCertStore, CERT_CLOSE_STORE_CHECK_FLAG ) ; + if( found != 0 ) break; // Found the certificate. +********************************************************************************/ + + pCertContext = CertFindCertificateInStore( + hCertStore, + X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, + 0, + CERT_FIND_SUBJECT_CERT, + &certInfo, + nullptr + ) ; + + if(i != 0 && i != 1) CertCloseStore( hCertStore, CERT_CLOSE_STORE_CHECK_FLAG ) ; + if( pCertContext != nullptr ) break ; // Found the certificate. + + } + + free(cryptSerialNumber.pbData); + free(certInfo.Issuer.pbData); + + if( pCertContext != nullptr ) { + xcert = MswcryCertContextToXCert(pCertContext); + CertFreeCertificateContext(pCertContext); + } + + return xcert ; +} + +uno::Reference< XCertificate > SecurityEnvironment_MSCryptImpl::getCertificate( const OUString& issuerName, const OUString& serialNumber ) { + uno::Sequence< sal_Int8 > serial = xmlsecurity::numericStringToBigInteger( serialNumber ) ; + return getCertificate( issuerName, serial ) ; +} + +uno::Sequence< uno::Reference < XCertificate > > SecurityEnvironment_MSCryptImpl::buildCertificatePath( const uno::Reference< XCertificate >& begin ) { + PCCERT_CHAIN_CONTEXT pChainContext ; + PCCERT_CONTEXT pCertContext ; + + CERT_ENHKEY_USAGE enhKeyUsage ; + CERT_USAGE_MATCH certUsage ; + CERT_CHAIN_PARA chainPara ; + + enhKeyUsage.cUsageIdentifier = 0 ; + enhKeyUsage.rgpszUsageIdentifier = nullptr ; + certUsage.dwType = USAGE_MATCH_TYPE_AND ; + certUsage.Usage = enhKeyUsage ; + chainPara.cbSize = sizeof( CERT_CHAIN_PARA ) ; + chainPara.RequestedUsage = certUsage ; + + const auto* xcert = dynamic_cast<X509Certificate_MSCryptImpl*>(begin.get()); + if( xcert == nullptr ) { + throw uno::RuntimeException() ; + } + + pCertContext = xcert->getMswcryCert() ; + + pChainContext = nullptr ; + + bool bChain = false; + if( pCertContext != nullptr ) + { + HCERTSTORE hAdditionalStore = nullptr; + HCERTSTORE hCollectionStore = nullptr; + if (m_hCertStore && m_hKeyStore) + { + //Merge m_hCertStore and m_hKeyStore into one store. + hCollectionStore = CertOpenStore( + CERT_STORE_PROV_COLLECTION , + 0 , + 0 , + 0 , + nullptr + ) ; + if (hCollectionStore != nullptr) + { + CertAddStoreToCollection ( + hCollectionStore , + m_hCertStore , + CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG , + 0) ; + CertAddStoreToCollection ( + hCollectionStore , + m_hKeyStore, + CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG , + 0) ; + hAdditionalStore = hCollectionStore; + } + + } + + //if the merge of both stores failed then we add only m_hCertStore + if (hAdditionalStore == nullptr && m_hCertStore) + hAdditionalStore = m_hCertStore; + else if (hAdditionalStore == nullptr && m_hKeyStore) + hAdditionalStore = m_hKeyStore; + else + hAdditionalStore = nullptr; + + //CertGetCertificateChain searches by default in MY, CA, ROOT and TRUST + bChain = CertGetCertificateChain( + nullptr , + pCertContext , + nullptr , //use current system time + hAdditionalStore, + &chainPara , + CERT_CHAIN_REVOCATION_CHECK_CHAIN | CERT_CHAIN_TIMESTAMP_TIME , + nullptr , + &pChainContext); + if (!bChain) + pChainContext = nullptr; + + //Close the additional store + CertCloseStore(hCollectionStore, CERT_CLOSE_STORE_CHECK_FLAG); + } + + if(bChain && pChainContext != nullptr && pChainContext->cChain > 0 ) + { + PCCERT_CONTEXT pCertInChain ; + PCERT_SIMPLE_CHAIN pCertChain ; + rtl::Reference<X509Certificate_MSCryptImpl> pCert ; + + pCertChain = pChainContext->rgpChain[0] ; + if( pCertChain->cElement ) { + uno::Sequence< uno::Reference< XCertificate > > xCertChain( pCertChain->cElement ) ; + auto pxCertChain = xCertChain.getArray(); + + for( unsigned int i = 0 ; i < pCertChain->cElement ; i ++ ) { + if( pCertChain->rgpElement[i] ) + pCertInChain = pCertChain->rgpElement[i]->pCertContext ; + else + pCertInChain = nullptr ; + + if( pCertInChain != nullptr ) { + pCert = MswcryCertContextToXCert( pCertInChain ) ; + if( pCert.is() ) + pxCertChain[i] = pCert ; + } + } + + CertFreeCertificateChain( pChainContext ) ; + pChainContext = nullptr ; + + return xCertChain ; + } + } + if (pChainContext) + CertFreeCertificateChain(pChainContext); + + return uno::Sequence< uno::Reference < XCertificate > >(); +} + +uno::Reference< XCertificate > SecurityEnvironment_MSCryptImpl::createCertificateFromRaw( const uno::Sequence< sal_Int8 >& rawCertificate ) { + rtl::Reference<X509Certificate_MSCryptImpl> xcert ; + + if( rawCertificate.getLength() > 0 ) { + xcert = new X509Certificate_MSCryptImpl() ; + xcert->setRawCert( rawCertificate ) ; + } + + return xcert ; +} + +uno::Reference< XCertificate > SecurityEnvironment_MSCryptImpl::createCertificateFromAscii( const OUString& asciiCertificate ) +{ + OString oscert = OUStringToOString( asciiCertificate , RTL_TEXTENCODING_ASCII_US ) ; + xmlChar* chCert = xmlStrndup( reinterpret_cast<const xmlChar*>(oscert.getStr()), static_cast<int>(oscert.getLength()) ) ; + xmlSecSize certSize; + int nRet = xmlSecBase64Decode_ex( chCert, reinterpret_cast<xmlSecByte*>(chCert), xmlStrlen( chCert ), &certSize ) ; + if (nRet < 0 || certSize == 0) + { + xmlFree(chCert); + return nullptr; + } + + uno::Sequence<sal_Int8> rawCert(comphelper::arrayToSequence<sal_Int8>(chCert, certSize)); + + xmlFree( chCert ) ; + + return createCertificateFromRaw( rawCert ) ; +} + +static HCERTSTORE getCertStoreForIntermediatCerts( + const uno::Sequence< uno::Reference< css::security::XCertificate > >& seqCerts) +{ + HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, 0, nullptr); + if (store == nullptr) + return nullptr; + + for (int i = 0; i < seqCerts.getLength(); i++) + { + SAL_INFO("xmlsecurity.xmlsec", "Added temporary certificate: " << seqCerts[i]->getSubjectName()); + + uno::Sequence<sal_Int8> data = seqCerts[i]->getEncoded(); + PCCERT_CONTEXT cert = CertCreateCertificateContext( + X509_ASN_ENCODING, reinterpret_cast<const BYTE*>(&data[0]), data.getLength()); + //Adding the certificate creates a copy and not just increases the ref count + //Therefore we free later the certificate that we now add + CertAddCertificateContextToStore(store, cert, CERT_STORE_ADD_ALWAYS, nullptr); + CertFreeCertificateContext(cert); + } + return store; +} + +static bool CheckUnitTestStore(PCCERT_CHAIN_CONTEXT const pChainContext, DWORD ignoreFlags) +{ + bool ret = false; + static char const*const pVar = getenv("LIBO_TEST_CRYPTOAPI_PKCS7"); + if (!pVar) + { + return ret; + } + if (pChainContext->cChain == 0) + { + return ret; + } + PCERT_SIMPLE_CHAIN pSimpleChain = pChainContext->rgpChain[0]; + // check if untrusted root is the only problem + if (pSimpleChain->TrustStatus.dwErrorStatus & ~(CERT_TRUST_IS_UNTRUSTED_ROOT | ignoreFlags)) + { + return ret; + } + + // leak this store, re-opening is a waste of time in tests + static HCERTSTORE const hExtra = CertOpenStore( + CERT_STORE_PROV_FILENAME_A, + PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, + 0, + CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG, + OString(OString::Concat(pVar) + "/test.p7b").getStr()); + assert(hExtra != nullptr); + if (pSimpleChain->cElement < 1) + { + SAL_WARN("xmlsecurity.xmlsec", "unexpected empty chain"); + return ret; + } + PCCERT_CONTEXT const pRoot(pSimpleChain->rgpElement[pSimpleChain->cElement-1]->pCertContext); + PCCERT_CONTEXT const pIssuerCert = CertFindCertificateInStore( + hExtra, + PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, + 0, + CERT_FIND_SUBJECT_NAME, + &pRoot->pCertInfo->Subject, + nullptr); + if (pIssuerCert) + { + // check that it signed itself + DWORD flags = CERT_STORE_SIGNATURE_FLAG; + bool result = CertVerifySubjectCertificateContext(pRoot, pIssuerCert, &flags); + if (result && flags == 0) + { + ret = true; + } + } + CertFreeCertificateContext(pIssuerCert); + return ret; +} + +//We return only valid or invalid, as long as the API documentation expresses +//explicitly that all validation steps are carried out even if one or several +//errors occur. See also +//http://wiki.openoffice.org/wiki/Certificate_Path_Validation#Validation_status +sal_Int32 SecurityEnvironment_MSCryptImpl::verifyCertificate( + const uno::Reference< css::security::XCertificate >& aCert, + const uno::Sequence< uno::Reference< css::security::XCertificate > >& seqCerts) +{ + sal_Int32 validity = css::security::CertificateValidity::INVALID; + PCCERT_CHAIN_CONTEXT pChainContext = nullptr; + PCCERT_CONTEXT pCertContext = nullptr; + + SAL_INFO("xmlsecurity.xmlsec", "Start verification of certificate: " << aCert->getSubjectName()); + + const auto* xcert = dynamic_cast<X509Certificate_MSCryptImpl*>(aCert.get()); + if( xcert == nullptr ) { + throw uno::RuntimeException() ; + } + + pCertContext = xcert->getMswcryCert() ; + + CERT_ENHKEY_USAGE enhKeyUsage ; + CERT_USAGE_MATCH certUsage ; + CERT_CHAIN_PARA chainPara = {}; + + //Prepare parameter for CertGetCertificateChain + enhKeyUsage.cUsageIdentifier = 0 ; + enhKeyUsage.rgpszUsageIdentifier = nullptr ; + certUsage.dwType = USAGE_MATCH_TYPE_AND ; + certUsage.Usage = enhKeyUsage ; + chainPara.cbSize = sizeof( CERT_CHAIN_PARA ) ; + chainPara.RequestedUsage = certUsage ; + + + HCERTSTORE hCollectionStore = nullptr; + HCERTSTORE hIntermediateCertsStore = nullptr; + bool bChain = false; + if( pCertContext != nullptr ) + { + hIntermediateCertsStore = + getCertStoreForIntermediatCerts(seqCerts); + + //Merge m_hCertStore and m_hKeyStore and the store of the intermediate + //certificates into one store. + hCollectionStore = CertOpenStore( + CERT_STORE_PROV_COLLECTION , + 0 , + 0 , + 0 , + nullptr + ) ; + if (hCollectionStore != nullptr) + { + CertAddStoreToCollection ( + hCollectionStore , + m_hCertStore , + CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG , + 0) ; + CertAddStoreToCollection ( + hCollectionStore , + m_hKeyStore, + CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG , + 0) ; + CertAddStoreToCollection ( + hCollectionStore, + hIntermediateCertsStore, + CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, + 0); + + } + + //CertGetCertificateChain searches by default in MY, CA, ROOT and TRUST + //We do not check revocation of the root. In most cases there are none. + //Then we would get CERT_TRUST_REVOCATION_STATUS_UNKNOWN + SAL_INFO("xmlsecurity.xmlsec", "Verifying cert using revocation information."); + bChain = CertGetCertificateChain( + nullptr , + pCertContext , + nullptr , //use current system time + hCollectionStore, + &chainPara , + CERT_CHAIN_REVOCATION_CHECK_CHAIN | CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT, + nullptr , + &pChainContext); + + if (bChain && pChainContext->cChain > 0) + { + SAL_INFO("xmlsecurity.xmlsec", "Overall error status (all chains):"); + traceTrustStatus(pChainContext->TrustStatus.dwErrorStatus); + //highest quality chains come first + PCERT_SIMPLE_CHAIN pSimpleChain = pChainContext->rgpChain[0]; + SAL_INFO("xmlsecurity.xmlsec", "Error status of first chain:"); + traceTrustStatus(pSimpleChain->TrustStatus.dwErrorStatus); + + //CERT_TRUST_REVOCATION_STATUS_UNKNOWN is also set if a certificate + //has no AIA(OCSP) or CRLDP extension and there is no CRL locally installed. + DWORD revocationFlags = CERT_TRUST_REVOCATION_STATUS_UNKNOWN | + CERT_TRUST_IS_OFFLINE_REVOCATION; + DWORD otherErrorsMask = ~revocationFlags; + if (!(pSimpleChain->TrustStatus.dwErrorStatus & otherErrorsMask) + || CheckUnitTestStore(pChainContext, revocationFlags)) + + { + //No errors except maybe those caused by missing revocation information + //Check if there are errors + if ( pSimpleChain->TrustStatus.dwErrorStatus & revocationFlags) + { + //No revocation information. Because MSDN documentation is not + //clear about if all other tests are performed if an error occurs, + //we test again, without requiring revocation checking. + CertFreeCertificateChain(pChainContext); + pChainContext = nullptr; + SAL_INFO("xmlsecurity.xmlsec", "Checking again but without requiring revocation information."); + bChain = CertGetCertificateChain( + nullptr , + pCertContext , + nullptr , //use current system time + hCollectionStore, + &chainPara , + 0, + nullptr , + &pChainContext); + if (bChain + && pChainContext->cChain > 0 + && pChainContext->rgpChain[0]->TrustStatus.dwErrorStatus == CERT_TRUST_NO_ERROR) + { + SAL_INFO("xmlsecurity.xmlsec", "Certificate is valid."); + validity = css::security::CertificateValidity::VALID; + } + else if (CheckUnitTestStore(pChainContext, 0)) + { + SAL_INFO("xmlsecurity.xmlsec", "root certificate found in extra test store"); + validity = css::security::CertificateValidity::VALID; + } + else + { + SAL_INFO("xmlsecurity.xmlsec", "Certificate is invalid."); + } + } + else + { + //valid and revocation information available + SAL_INFO("xmlsecurity.xmlsec", "Certificate is valid."); + validity = css::security::CertificateValidity::VALID; + } + } + else + { + //invalid + SAL_INFO("xmlsecurity.xmlsec", "Certificate is invalid."); + validity = css::security::CertificateValidity::INVALID ; + } + } + else + { + SAL_INFO("xmlsecurity.xmlsec", "CertGetCertificateChain failed."); + } + } + + if (pChainContext) + { + CertFreeCertificateChain(pChainContext); + pChainContext = nullptr; + } + + //Close the additional store, do not destroy the contained certs + CertCloseStore(hCollectionStore, CERT_CLOSE_STORE_CHECK_FLAG); + //Close the temporary store containing the intermediate certificates and make + //sure all certificates are deleted. + CertCloseStore(hIntermediateCertsStore, CERT_CLOSE_STORE_CHECK_FLAG); + + return validity ; +} + +sal_Int32 SecurityEnvironment_MSCryptImpl::getCertificateCharacters( const css::uno::Reference< css::security::XCertificate >& aCert ) { + sal_Int32 characters ; + PCCERT_CONTEXT pCertContext ; + + const auto* xcert = dynamic_cast<X509Certificate_MSCryptImpl*>(aCert.get()); + if( xcert == nullptr ) { + throw uno::RuntimeException() ; + } + + pCertContext = xcert->getMswcryCert() ; + + characters = 0x00000000 ; + + //Firstly, make sentence whether or not the cert is self-signed. + if( CertCompareCertificateName( X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &(pCertContext->pCertInfo->Subject), &(pCertContext->pCertInfo->Issuer) ) ) { + characters |= css::security::CertificateCharacters::SELF_SIGNED ; + } else { + characters &= ~ css::security::CertificateCharacters::SELF_SIGNED ; + } + + //Secondly, make sentence whether or not the cert has a private key. + { + BOOL fCallerFreeProv ; + DWORD dwKeySpec ; + NCRYPT_KEY_HANDLE hKey = 0; + DWORD dwFlags = CRYPT_ACQUIRE_ONLY_NCRYPT_KEY_FLAG; + HCRYPTPROV_OR_NCRYPT_KEY_HANDLE* phCryptProvOrNCryptKey = &hKey; + if( CryptAcquireCertificatePrivateKey( pCertContext , + dwFlags, + nullptr , + phCryptProvOrNCryptKey, + &dwKeySpec, + &fCallerFreeProv ) + ) { + characters |= css::security::CertificateCharacters::HAS_PRIVATE_KEY ; + + if (hKey && fCallerFreeProv) + NCryptFreeObject(hKey); + } else { + characters &= ~ css::security::CertificateCharacters::HAS_PRIVATE_KEY ; + } + } + return characters ; +} + +void SecurityEnvironment_MSCryptImpl::enableDefaultCrypt( bool enable ) { + m_bEnableDefault = enable ; +} + +bool SecurityEnvironment_MSCryptImpl::defaultEnabled() { + return m_bEnableDefault ; +} + +static rtl::Reference<X509Certificate_MSCryptImpl> MswcryCertContextToXCert( PCCERT_CONTEXT cert ) +{ + rtl::Reference<X509Certificate_MSCryptImpl> xcert ; + + if( cert != nullptr ) { + xcert = new X509Certificate_MSCryptImpl() ; + xcert->setMswcryCert( cert ) ; + } + + return xcert ; +} + +OUString SecurityEnvironment_MSCryptImpl::getSecurityEnvironmentInformation() +{ + return "Microsoft Crypto API"; +} + +xmlSecKeysMngrPtr SecurityEnvironment_MSCryptImpl::createKeysManager() { + + /*- + * The following lines is based on the of xmlsec-mscrypto crypto engine + */ + xmlSecKeysMngrPtr pKeysMngr = xmlsecurity::MSCryptoAppliedKeysMngrCreate() ; + if( pKeysMngr == nullptr ) + throw uno::RuntimeException() ; + + /*- + * Adopt system default certificate store. + */ + if( defaultEnabled() ) { + //Add system key store into the keys manager. + m_hMySystemStore = CertOpenSystemStoreW( 0, L"MY" ) ; + if( m_hMySystemStore != nullptr ) { + if( xmlsecurity::MSCryptoAppliedKeysMngrAdoptKeyStore( pKeysMngr, m_hMySystemStore ) < 0 ) { + CertCloseStore( m_hMySystemStore, CERT_CLOSE_STORE_CHECK_FLAG ) ; + m_hMySystemStore = nullptr; + throw uno::RuntimeException() ; + } + m_hMySystemStore = nullptr; + } + + //Add system root store into the keys manager. + m_hRootSystemStore = CertOpenSystemStoreW( 0, L"Root" ) ; + if( m_hRootSystemStore != nullptr ) { + if( xmlsecurity::MSCryptoAppliedKeysMngrAdoptTrustedStore( pKeysMngr, m_hRootSystemStore ) < 0 ) { + CertCloseStore( m_hRootSystemStore, CERT_CLOSE_STORE_CHECK_FLAG ) ; + m_hRootSystemStore = nullptr; + throw uno::RuntimeException() ; + } + m_hRootSystemStore = nullptr; + } + + //Add system trusted store into the keys manager. + m_hTrustSystemStore = CertOpenSystemStoreW( 0, L"Trust" ) ; + if( m_hTrustSystemStore != nullptr ) { + if( xmlsecurity::MSCryptoAppliedKeysMngrAdoptUntrustedStore( pKeysMngr, m_hTrustSystemStore ) < 0 ) { + CertCloseStore( m_hTrustSystemStore, CERT_CLOSE_STORE_CHECK_FLAG ) ; + m_hTrustSystemStore = nullptr; + throw uno::RuntimeException() ; + } + m_hTrustSystemStore = nullptr; + } + + //Add system CA store into the keys manager. + m_hCaSystemStore = CertOpenSystemStoreW( 0, L"CA" ) ; + if( m_hCaSystemStore != nullptr ) { + if( xmlsecurity::MSCryptoAppliedKeysMngrAdoptUntrustedStore( pKeysMngr, m_hCaSystemStore ) < 0 ) { + CertCloseStore( m_hCaSystemStore, CERT_CLOSE_STORE_CHECK_FLAG ) ; + m_hCaSystemStore = nullptr; + throw uno::RuntimeException() ; + } + m_hCaSystemStore = nullptr; + } + } + + return pKeysMngr ; +} +void SecurityEnvironment_MSCryptImpl::destroyKeysManager(xmlSecKeysMngrPtr pKeysMngr) { + if( pKeysMngr != nullptr ) { + xmlSecKeysMngrDestroy( pKeysMngr ) ; + } +} + +extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface* +com_sun_star_xml_crypto_SecurityEnvironment_get_implementation( + uno::XComponentContext* pCtx, uno::Sequence<uno::Any> const& /*rSeq*/) +{ + return cppu::acquire(new SecurityEnvironment_MSCryptImpl(pCtx)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.hxx b/xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.hxx new file mode 100644 index 0000000000..5867b2b462 --- /dev/null +++ b/xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.hxx @@ -0,0 +1,168 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#if !defined WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +#endif +#include <windows.h> +#include <wincrypt.h> +#include <sal/config.h> +#include <rtl/ustring.hxx> +#include <comphelper/servicehelper.hxx> +#include <cppuhelper/factory.hxx> +#include <cppuhelper/implbase.hxx> +#include <com/sun/star/uno/Exception.hpp> + +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> + +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/xml/crypto/XSecurityEnvironment.hpp> +#include <com/sun/star/security/XCertificate.hpp> +#include <com/sun/star/security/CertificateCharacters.hpp> +#include <com/sun/star/security/CertificateValidity.hpp> + +#include <vector> +#include <xmlsec-wrapper.h> + +#include <sal/types.h> + + +class SecurityEnvironment_MSCryptImpl : public ::cppu::WeakImplHelper< + css::xml::crypto::XSecurityEnvironment , + css::lang::XServiceInfo > +{ + private: + //crypto provider and key container + HCRYPTPROV m_hProv ; + LPCTSTR m_pszContainer ; + + //Key store + HCERTSTORE m_hKeyStore ; + + //Certificate store + HCERTSTORE m_hCertStore ; + + // i120675, save the store handles + HCERTSTORE m_hMySystemStore; + HCERTSTORE m_hRootSystemStore; + HCERTSTORE m_hTrustSystemStore; + HCERTSTORE m_hCaSystemStore; + + //Enable default system cryptography setting + bool m_bEnableDefault ; + + //Service manager + css::uno::Reference< css::lang::XMultiServiceFactory > m_xServiceManager ; + + public: + explicit SecurityEnvironment_MSCryptImpl( const css::uno::Reference< css::uno::XComponentContext >& xContext ) ; + virtual ~SecurityEnvironment_MSCryptImpl() override; + + //Methods from XSecurityEnvironment + virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificate > > SAL_CALL getPersonalCertificates() override; + virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificate > > SAL_CALL getAllCertificates() override + { return css::uno::Sequence< css::uno::Reference< css::security::XCertificate > >(); } + + virtual css::uno::Reference< css::security::XCertificate > SAL_CALL getCertificate( + const OUString& issuerName, + const css::uno::Sequence< sal_Int8 >& serialNumber ) override; + + /// @throws css::uno::SecurityException + /// @throws css::uno::RuntimeException + virtual css::uno::Reference< css::security::XCertificate > getCertificate( + const OUString& issuerName, + const OUString& serialNumber ) ; + + virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificate > > SAL_CALL buildCertificatePath( + const css::uno::Reference< css::security::XCertificate >& beginCert ) override; + + virtual css::uno::Reference< css::security::XCertificate > SAL_CALL createCertificateFromRaw( + const css::uno::Sequence< sal_Int8 >& rawCertificate ) override; + + virtual css::uno::Reference< css::security::XCertificate > SAL_CALL createCertificateFromAscii( + const OUString& asciiCertificate ) override; + + virtual ::sal_Int32 SAL_CALL verifyCertificate( + const css::uno::Reference< css::security::XCertificate >& xCert, + const css::uno::Sequence< css::uno::Reference< + css::security::XCertificate > >& intermediateCertificates) override; + + virtual ::sal_Int32 SAL_CALL getCertificateCharacters( + const css::uno::Reference< css::security::XCertificate >& xCert ) override; + + virtual OUString SAL_CALL getSecurityEnvironmentInformation( ) override; + + + //Methods from XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + + virtual sal_Bool SAL_CALL supportsService( + const OUString& ServiceName + ) override; + + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; + + /// @throws css::uno::Exception + /// @throws css::uno::RuntimeException + HCRYPTPROV getCryptoProvider() ; + /// @throws css::uno::Exception + /// @throws css::uno::RuntimeException + void setCryptoProvider( HCRYPTPROV aProv ) ; + + /// @throws css::uno::Exception + /// @throws css::uno::RuntimeException + LPCTSTR getKeyContainer() ; + /// @throws css::uno::Exception + /// @throws css::uno::RuntimeException + void setKeyContainer( LPCTSTR aKeyContainer ) ; + + /// @throws css::uno::Exception + /// @throws css::uno::RuntimeException + HCERTSTORE getCryptoSlot() ; + /// @throws css::uno::Exception + /// @throws css::uno::RuntimeException + void setCryptoSlot( HCERTSTORE aKeyStore ) ; + + /// @throws css::uno::Exception + /// @throws css::uno::RuntimeException + HCERTSTORE getCertDb() ; + /// @throws css::uno::Exception + /// @throws css::uno::RuntimeException + void setCertDb( HCERTSTORE aCertDb ) ; + + /// @throws css::uno::Exception + /// @throws css::uno::RuntimeException + void enableDefaultCrypt( bool enable ) ; + /// @throws css::uno::Exception + /// @throws css::uno::RuntimeException + bool defaultEnabled() ; + + /// @throws css::uno::Exception + /// @throws css::uno::RuntimeException + xmlSecKeysMngrPtr createKeysManager() ; + + /// @throws css::uno::Exception + /// @throws css::uno::RuntimeException + static void destroyKeysManager(xmlSecKeysMngrPtr pKeysMngr) ; +} ; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/mscrypt/seinitializer_mscryptimpl.cxx b/xmlsecurity/source/xmlsec/mscrypt/seinitializer_mscryptimpl.cxx new file mode 100644 index 0000000000..99381e5e25 --- /dev/null +++ b/xmlsecurity/source/xmlsec/mscrypt/seinitializer_mscryptimpl.cxx @@ -0,0 +1,172 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> +#include <xmlsec-wrapper.h> + +#include "seinitializer_mscryptimpl.hxx" + +#include "securityenvironment_mscryptimpl.hxx" + +#include <xmlsec/mscng/app.h> +#include <com/sun/star/xml/crypto/SecurityEnvironment.hpp> +#include <com/sun/star/xml/crypto/XMLSecurityContext.hpp> +#include <cppuhelper/supportsservice.hxx> +#include <o3tl/char16_t2wchar_t.hxx> +#include <svl/cryptosign.hxx> + +using namespace com::sun::star; +namespace cssl = com::sun::star::lang; +namespace cssxc = com::sun::star::xml::crypto; + +SEInitializer_MSCryptImpl::SEInitializer_MSCryptImpl( + const uno::Reference< uno::XComponentContext > &rxContext) + :mxContext( rxContext ) +{ +} + +SEInitializer_MSCryptImpl::~SEInitializer_MSCryptImpl() +{ +} + +/* XSEInitializer */ +uno::Reference< cssxc::XXMLSecurityContext > SAL_CALL + SEInitializer_MSCryptImpl::createSecurityContext( + const OUString& sCertDB ) +{ + const char* n_pCertStore ; + HCERTSTORE n_hStoreHandle ; + OString sCertDir; + + //Initialize the crypto engine + if( sCertDB.getLength() > 0 ) + { + sCertDir = OUStringToOString(sCertDB, RTL_TEXTENCODING_ASCII_US); + n_pCertStore = sCertDir.getStr(); + n_hStoreHandle = CertOpenSystemStoreW( 0, o3tl::toW(sCertDB.getStr())) ; + if( n_hStoreHandle == nullptr ) + { + return nullptr; + } + } + else + { + n_pCertStore = nullptr ; + n_hStoreHandle = nullptr ; + } + + xmlSecMSCngAppInit(n_pCertStore); + + try { + /* Build Security Environment */ + uno::Reference< cssxc::XSecurityEnvironment > xSecEnv = cssxc::SecurityEnvironment::create( mxContext ); + + /* Setup key slot and certDb */ + SecurityEnvironment_MSCryptImpl* pSecEnv = dynamic_cast<SecurityEnvironment_MSCryptImpl*>(xSecEnv.get()); + if( pSecEnv == nullptr ) + { + if( n_hStoreHandle != nullptr ) + { + CertCloseStore( n_hStoreHandle, CERT_CLOSE_STORE_FORCE_FLAG ) ; + } + + xmlSecMSCngAppShutdown(); + return nullptr; + } + + if( n_hStoreHandle != nullptr ) + { + pSecEnv->setCryptoSlot( n_hStoreHandle ) ; + pSecEnv->setCertDb( n_hStoreHandle ) ; + } + else + { + pSecEnv->enableDefaultCrypt( true ) ; + } + + /* Build XML Security Context */ + uno::Reference< cssxc::XXMLSecurityContext > xSecCtx = cssxc::XMLSecurityContext::create( mxContext ); + + xSecCtx->setDefaultSecurityEnvironmentIndex(xSecCtx->addSecurityEnvironment( xSecEnv )) ; + return xSecCtx; + } + catch( uno::Exception& ) + { + if( n_hStoreHandle != nullptr ) + { + CertCloseStore( n_hStoreHandle, CERT_CLOSE_STORE_FORCE_FLAG ) ; + } + + xmlSecMSCngAppShutdown(); + return nullptr; + } +} + +void SAL_CALL SEInitializer_MSCryptImpl::freeSecurityContext( const uno::Reference< cssxc::XXMLSecurityContext >&) +{ + /* + uno::Reference< cssxc::XSecurityEnvironment > xSecEnv + = securityContext->getSecurityEnvironment(); + + if( xSecEnv.is() ) + { + uno::Reference< cssl::XUnoTunnel > xEnvTunnel( xSecEnv , uno::UNO_QUERY ) ; + if (auto pSecEnv = comphelper::getFromUnoTunnel<SecurityEnvironment_MSCryptImpl>(xEnvTunnel)) + { + HCERTSTORE n_hStoreHandle = pSecEnv->getCryptoSlot(); + + if( n_hStoreHandle != NULL ) + { + CertCloseStore( n_hStoreHandle, CERT_CLOSE_STORE_FORCE_FLAG ) ; + pSecEnv->setCryptoSlot( NULL ) ; + pSecEnv->setCertDb( NULL ) ; + } + + xmlSecMSCryptoAppShutdown() ; + } + } + */ + + xmlSecMSCngAppShutdown(); +} + +/* XServiceInfo */ +OUString SAL_CALL SEInitializer_MSCryptImpl::getImplementationName() +{ + return "com.sun.star.xml.crypto.SEInitializer"; +} + +sal_Bool SAL_CALL SEInitializer_MSCryptImpl::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService( this, rServiceName ); +} + +uno::Sequence< OUString > SAL_CALL SEInitializer_MSCryptImpl::getSupportedServiceNames() +{ + return { "com.sun.star.xml.crypto.SEInitializer" }; +} + +extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface* +com_sun_star_xml_crypto_SEInitializer_get_implementation( + uno::XComponentContext* pCtx, uno::Sequence<uno::Any> const& /*rSeq*/) +{ + return cppu::acquire(new SEInitializer_MSCryptImpl(pCtx)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/mscrypt/seinitializer_mscryptimpl.hxx b/xmlsecurity/source/xmlsec/mscrypt/seinitializer_mscryptimpl.hxx new file mode 100644 index 0000000000..182ba5e5af --- /dev/null +++ b/xmlsecurity/source/xmlsec/mscrypt/seinitializer_mscryptimpl.hxx @@ -0,0 +1,71 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <com/sun/star/xml/crypto/XXMLSecurityContext.hpp> +#include <com/sun/star/xml/crypto/XSEInitializer.hpp> +#include <com/sun/star/lang/XUnoTunnel.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <cppuhelper/implbase.hxx> + +#include <libxml/tree.h> + +class SEInitializer_MSCryptImpl : public cppu::WeakImplHelper +< + css::xml::crypto::XSEInitializer, + css::lang::XServiceInfo +> +/****** SEInitializer_MSCryptImpl.hxx/CLASS SEInitializer_MSCryptImpl *********** + * + * NAME + * SEInitializer_MSCryptImpl -- Class to initialize a Security Context + * instance + * + * FUNCTION + * Use this class to initialize a XmlSec based Security Context + * instance. After this instance is used up, use this class to free this + * instance. + ******************************************************************************/ +{ +private: + css::uno::Reference< css::uno::XComponentContext > mxContext; + +public: + explicit SEInitializer_MSCryptImpl(const css::uno::Reference< css::uno::XComponentContext > &rxContext); + virtual ~SEInitializer_MSCryptImpl() override; + + /* XSEInitializer */ + virtual css::uno::Reference< css::xml::crypto::XXMLSecurityContext > + SAL_CALL createSecurityContext( const OUString& certDB ) override; + + virtual void SAL_CALL freeSecurityContext( const css::uno::Reference< + css::xml::crypto::XXMLSecurityContext >& securityContext ) override; + + /* XServiceInfo */ + virtual OUString SAL_CALL getImplementationName( ) override; + + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx b/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx new file mode 100644 index 0000000000..bd4ef701e6 --- /dev/null +++ b/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx @@ -0,0 +1,783 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <string.h> + +#include <sal/config.h> +#include <sal/log.hxx> +#include <comphelper/servicehelper.hxx> +#include <comphelper/windowserrorstring.hxx> +#include <cppuhelper/supportsservice.hxx> +#include "x509certificate_mscryptimpl.hxx" +#include <certificateextension_xmlsecimpl.hxx> +#include <biginteger.hxx> +#include "sanextension_mscryptimpl.hxx" + +#include "oid.hxx" + +#include <rtl/locale.h> +#include <rtl/ref.hxx> +#include <rtl/ustrbuf.hxx> +#include <osl/nlsupport.h> +#include <osl/process.h> +#include <o3tl/char16_t2wchar_t.hxx> +#include <o3tl/string_view.hxx> + +#include <memory> +#include <string_view> +#include <utility> +#include <vector> +#include <tools/time.hxx> +#include <svl/sigstruct.hxx> + +using namespace com::sun::star; +using namespace ::com::sun::star::uno ; +using namespace ::com::sun::star::security ; + +using ::com::sun::star::security::XCertificate ; +using ::com::sun::star::util::DateTime ; + +/*Returns the index within rRawString where sTypeName starts and where it ends. + The starting index is pair.first. The ending index in pair.second points + one char after the last character of the type. + sTypeName can be + "S" or "CN" (without ""). Do not use spaces at the beginning of the type name. + If the type name is not found then pair.first and pair.second are -1. +*/ +static std::pair< sal_Int32, sal_Int32 > +findTypeInDN(const OUString& rRawString, std::u16string_view sTypeName) +{ + std::pair< sal_Int32, sal_Int32 > retVal; + bool bInEscape = false; + bool bInValue = false; + bool bFound = false; + sal_Int32 nTypeNameStart = 0; + sal_Int32 length = rRawString.getLength(); + + for (sal_Int32 i = 0; i < length; i++) + { + sal_Unicode c = rRawString[i]; + + if (c == '=') + { + if (! bInValue) + { + std::u16string_view sType = rRawString.subView(nTypeNameStart, i - nTypeNameStart); + sType = o3tl::trim(sType); + if (o3tl::equalsIgnoreAsciiCase(sType, sTypeName)) + { + bFound = true; + break; + } + } + } + else if (c == '"') + { + if (!bInEscape) + { + //If this is the quote is the first of the couple which enclose the + //whole value, because the value contains special characters + //then we just drop it. That is, this character must be followed by + //a character which is not '"'. + if ( i + 1 < length && rRawString[i+1] == '"') + bInEscape = true; + else + bInValue = !bInValue; //value is enclosed in " " + } + else + { + //This quote is escaped by a preceding quote and therefore is + //part of the value + bInEscape = false; + } + } + else if (c == ',' || c == '+') + { + //The comma separate the attribute value pairs. + //If the comma is not part of a value (the value would then be enclosed in '"'), + //then we have reached the end of the value + if (!bInValue) + { + //The next char is the start of the new type + nTypeNameStart = i + 1; + } + } + } + + //Found the Type Name, but there can still be spaces after the last comma + //and the beginning of the type. + if (bFound) + { + while (true) + { + sal_Unicode c = rRawString[nTypeNameStart]; + if (c != ' ' && c != '\t') + //found + break; + nTypeNameStart ++; + } + // search end (one after last letter) + sal_Int32 nTypeNameEnd = nTypeNameStart; + nTypeNameEnd++; + while (true) + { + sal_Unicode c = rRawString[nTypeNameEnd]; + if (c == ' ' || c == '\t' || c == '=') + break; + nTypeNameEnd++; + } + retVal = std::make_pair(nTypeNameStart, nTypeNameEnd); + } + else + { + retVal = std::make_pair(-1, -1); + } + return retVal; +} + + +/* + MS Crypto uses the 'S' tag (equal to the 'ST' tag in NSS), but the NSS can't recognise + it, so the 'S' tag should be changed to 'ST' tag. However I am not sure if this is necessary + anymore, because we provide always the signers certificate when signing. So libmlsec can find + the private key based on the provided certificate (X509Certificate element) and does not need + the issuer name (X509IssuerName element). The issuer name in the xml signature has also no + effect for the signature nor the certificate validation. + In many RFCs, for example 4519, on speaks of 'ST'. However, the certificate does not contain + strings for type names. Instead it uses OIDs. + */ + +static OUString replaceTagSWithTagST(OUString const & oldDN) +{ + std::pair<sal_Int32, sal_Int32 > pairIndex = findTypeInDN(oldDN, u"S"); + + if (pairIndex.first != -1) + { + return OUString::Concat(oldDN.subView(0, pairIndex.first))+"ST" + +oldDN.subView(pairIndex.second); + } + return oldDN; +} +/* end */ + +X509Certificate_MSCryptImpl::X509Certificate_MSCryptImpl() : + m_pCertContext( nullptr ) +{ +} + +X509Certificate_MSCryptImpl::~X509Certificate_MSCryptImpl() { + if( m_pCertContext != nullptr ) { + CertFreeCertificateContext( m_pCertContext ) ; + } +} + +//Methods from XCertificate +sal_Int16 SAL_CALL X509Certificate_MSCryptImpl::getVersion() { + if( m_pCertContext != nullptr && m_pCertContext->pCertInfo != nullptr ) { + return static_cast<char>(m_pCertContext->pCertInfo->dwVersion) ; + } else { + return -1 ; + } +} + +css::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_MSCryptImpl::getSerialNumber() { + if( m_pCertContext != nullptr && m_pCertContext->pCertInfo != nullptr ) { + Sequence< sal_Int8 > serial( m_pCertContext->pCertInfo->SerialNumber.cbData ) ; + auto serialRange = asNonConstRange(serial); + for( unsigned int i = 0 ; i < m_pCertContext->pCertInfo->SerialNumber.cbData ; i ++ ) + serialRange[i] = *( m_pCertContext->pCertInfo->SerialNumber.pbData + m_pCertContext->pCertInfo->SerialNumber.cbData - i - 1 ) ; + + return serial ; + } else { + return Sequence< sal_Int8 >(); + } +} + +OUString SAL_CALL X509Certificate_MSCryptImpl::getIssuerName() { + if( m_pCertContext != nullptr && m_pCertContext->pCertInfo != nullptr ) { + DWORD cchIssuer = CertNameToStrW( + X509_ASN_ENCODING | PKCS_7_ASN_ENCODING , + &( m_pCertContext->pCertInfo->Issuer ), + CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG , + nullptr, 0 + ) ; + + // Here the cbIssuer count the last 0x00 , take care. + if( cchIssuer != 0 ) { + auto issuer = std::make_unique<wchar_t[]>(cchIssuer); + + cchIssuer = CertNameToStrW( + X509_ASN_ENCODING | PKCS_7_ASN_ENCODING , + &( m_pCertContext->pCertInfo->Issuer ), + CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG , + issuer.get(), cchIssuer + ) ; + + if( cchIssuer <= 0 ) { + throw RuntimeException() ; + } + + if(issuer.get()[cchIssuer -1] == 0) cchIssuer--; //delimit the last 0x00; + OUString xIssuer(o3tl::toU(issuer.get()), cchIssuer) ; + + return replaceTagSWithTagST(xIssuer); + } else { + return OUString() ; + } + } else { + return OUString() ; + } +} + +OUString SAL_CALL X509Certificate_MSCryptImpl::getSubjectName() +{ + if( m_pCertContext != nullptr && m_pCertContext->pCertInfo != nullptr ) + { + DWORD cchSubject = CertNameToStrW( + X509_ASN_ENCODING | PKCS_7_ASN_ENCODING , + &( m_pCertContext->pCertInfo->Subject ), + CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG , + nullptr, 0 + ) ; + + if( cchSubject != 0 ) + { + auto subject = std::make_unique<wchar_t[]>(cchSubject); + + cchSubject = CertNameToStrW( + X509_ASN_ENCODING | PKCS_7_ASN_ENCODING , + &( m_pCertContext->pCertInfo->Subject ), + CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG , + subject.get(), cchSubject + ) ; + + if( cchSubject <= 0 ) { + throw RuntimeException() ; + } + + OUString xSubject(o3tl::toU(subject.get())); + + return replaceTagSWithTagST(xSubject); + } else + { + return OUString() ; + } + } + else + { + return OUString() ; + } +} + +css::util::DateTime SAL_CALL X509Certificate_MSCryptImpl::getNotValidBefore() { + if( m_pCertContext != nullptr && m_pCertContext->pCertInfo != nullptr ) { + SYSTEMTIME explTime ; + DateTime dateTime ; + FILETIME localFileTime; + + if (FileTimeToLocalFileTime(&( m_pCertContext->pCertInfo->NotBefore ), &localFileTime)) + { + if( FileTimeToSystemTime( &localFileTime, &explTime ) ) { + //Convert the time to readable local time + dateTime.NanoSeconds = explTime.wMilliseconds * ::tools::Time::nanoPerMilli ; + dateTime.Seconds = explTime.wSecond ; + dateTime.Minutes = explTime.wMinute ; + dateTime.Hours = explTime.wHour ; + dateTime.Day = explTime.wDay ; + dateTime.Month = explTime.wMonth ; + dateTime.Year = explTime.wYear ; + } + } + + return dateTime ; + } else { + return DateTime() ; + } +} + +css::util::DateTime SAL_CALL X509Certificate_MSCryptImpl::getNotValidAfter() { + if( m_pCertContext != nullptr && m_pCertContext->pCertInfo != nullptr ) { + SYSTEMTIME explTime ; + DateTime dateTime ; + FILETIME localFileTime; + + if (FileTimeToLocalFileTime(&( m_pCertContext->pCertInfo->NotAfter ), &localFileTime)) + { + if( FileTimeToSystemTime( &localFileTime, &explTime ) ) { + //Convert the time to readable local time + dateTime.NanoSeconds = explTime.wMilliseconds * ::tools::Time::nanoPerMilli ; + dateTime.Seconds = explTime.wSecond ; + dateTime.Minutes = explTime.wMinute ; + dateTime.Hours = explTime.wHour ; + dateTime.Day = explTime.wDay ; + dateTime.Month = explTime.wMonth ; + dateTime.Year = explTime.wYear ; + } + } + + return dateTime ; + } else { + return DateTime() ; + } +} + +css::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_MSCryptImpl::getIssuerUniqueID() { + if( m_pCertContext != nullptr && m_pCertContext->pCertInfo != nullptr ) { + Sequence< sal_Int8 > issuerUid( m_pCertContext->pCertInfo->IssuerUniqueId.cbData ) ; + auto issuerUidRange = asNonConstRange(issuerUid); + for( unsigned int i = 0 ; i < m_pCertContext->pCertInfo->IssuerUniqueId.cbData; i ++ ) + issuerUidRange[i] = *( m_pCertContext->pCertInfo->IssuerUniqueId.pbData + i ) ; + + return issuerUid ; + } else { + return Sequence< sal_Int8 >(); + } +} + +css::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_MSCryptImpl::getSubjectUniqueID() { + if( m_pCertContext != nullptr && m_pCertContext->pCertInfo != nullptr ) { + Sequence< sal_Int8 > subjectUid( m_pCertContext->pCertInfo->SubjectUniqueId.cbData ) ; + auto subjectUidRange = asNonConstRange(subjectUid); + for( unsigned int i = 0 ; i < m_pCertContext->pCertInfo->SubjectUniqueId.cbData; i ++ ) + subjectUidRange[i] = *( m_pCertContext->pCertInfo->SubjectUniqueId.pbData + i ) ; + + return subjectUid ; + } else { + return Sequence< sal_Int8 >(); + } +} + +css::uno::Sequence< css::uno::Reference< css::security::XCertificateExtension > > SAL_CALL X509Certificate_MSCryptImpl::getExtensions() { + if( m_pCertContext != nullptr && m_pCertContext->pCertInfo != nullptr && m_pCertContext->pCertInfo->cExtension != 0 ) { + rtl::Reference<CertificateExtension_XmlSecImpl> xExtn ; + Sequence< Reference< XCertificateExtension > > xExtns( m_pCertContext->pCertInfo->cExtension ) ; + auto pExtns = xExtns.getArray(); + + for( unsigned int i = 0; i < m_pCertContext->pCertInfo->cExtension; i++ ) { + CERT_EXTENSION* pExtn = &(m_pCertContext->pCertInfo->rgExtension[i]) ; + + + OUString objId = OUString::createFromAscii( pExtn->pszObjId ); + + if ( objId == "2.5.29.17" ) + xExtn = reinterpret_cast<CertificateExtension_XmlSecImpl*>(new SanExtensionImpl()); + else + xExtn = new CertificateExtension_XmlSecImpl; + + xExtn->setCertExtn( pExtn->Value.pbData, pExtn->Value.cbData, reinterpret_cast<unsigned char*>(pExtn->pszObjId), strlen( pExtn->pszObjId ), pExtn->fCritical ) ; + + pExtns[i] = xExtn ; + } + + return xExtns ; + } else { + return Sequence< Reference< XCertificateExtension > >(); + } +} + +css::uno::Reference< css::security::XCertificateExtension > SAL_CALL X509Certificate_MSCryptImpl::findCertificateExtension( const css::uno::Sequence< sal_Int8 >& /*oid*/ ) { + if( m_pCertContext != nullptr && m_pCertContext->pCertInfo != nullptr && m_pCertContext->pCertInfo->cExtension != 0 ) { + rtl::Reference<CertificateExtension_XmlSecImpl> xExtn ; + + for( unsigned int i = 0; i < m_pCertContext->pCertInfo->cExtension; i++ ) { + CERT_EXTENSION* pExtn = &( m_pCertContext->pCertInfo->rgExtension[i] ) ; + + //TODO: Compare the oid + if( false ) { + xExtn = new CertificateExtension_XmlSecImpl; + xExtn->setCertExtn( pExtn->Value.pbData, pExtn->Value.cbData, reinterpret_cast<unsigned char*>(pExtn->pszObjId), strlen( pExtn->pszObjId ), pExtn->fCritical ) ; + } + } + + return xExtn ; + } else { + return nullptr ; + } +} + + +css::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_MSCryptImpl::getEncoded() { + if( m_pCertContext != nullptr && m_pCertContext->cbCertEncoded > 0 ) { + Sequence< sal_Int8 > rawCert( m_pCertContext->cbCertEncoded ) ; + auto prawCert = rawCert.getArray(); + + for( unsigned int i = 0 ; i < m_pCertContext->cbCertEncoded ; i ++ ) + prawCert[i] = *( m_pCertContext->pbCertEncoded + i ) ; + + return rawCert ; + } else { + return Sequence< sal_Int8 >(); + } +} + +//Helper methods +void X509Certificate_MSCryptImpl::setMswcryCert( const CERT_CONTEXT* cert ) { + if( m_pCertContext != nullptr ) { + CertFreeCertificateContext( m_pCertContext ) ; + m_pCertContext = nullptr ; + } + + if( cert != nullptr ) { + m_pCertContext = CertDuplicateCertificateContext( cert ) ; + } +} + +const CERT_CONTEXT* X509Certificate_MSCryptImpl::getMswcryCert() const { + if( m_pCertContext != nullptr ) { + return m_pCertContext ; + } else { + return nullptr ; + } +} + +void X509Certificate_MSCryptImpl::setRawCert( Sequence< sal_Int8 > const & rawCert ) { + if( m_pCertContext != nullptr ) { + CertFreeCertificateContext( m_pCertContext ) ; + m_pCertContext = nullptr ; + } + + if( rawCert.getLength() != 0 ) { + m_pCertContext = CertCreateCertificateContext( X509_ASN_ENCODING, reinterpret_cast<const sal_uInt8*>(&rawCert[0]), rawCert.getLength() ) ; + } +} + +static OUString findOIDDescription(char const *oid) +{ + OUString ouOID = OUString::createFromAscii( oid ); + for (int i=0; i<nOID; i++) + { + OUString item = OUString::createFromAscii( OIDs[i].oid ); + if (ouOID == item) + { + return OUString::createFromAscii( OIDs[i].desc ); + } + } + + return OUString() ; +} + +static css::uno::Sequence< sal_Int8 > getThumbprint(const CERT_CONTEXT* pCertContext, DWORD dwPropId) +{ + if( pCertContext != nullptr ) + { + DWORD cbData = dwPropId == CERT_SHA256_HASH_PROP_ID ? 32 : 20; + unsigned char fingerprint[32]; + if (CertGetCertificateContextProperty(pCertContext, dwPropId, fingerprint, &cbData)) + { + Sequence< sal_Int8 > thumbprint( cbData ) ; + auto pthumbprint = thumbprint.getArray(); + for( unsigned int i = 0 ; i < cbData ; i ++ ) + { + pthumbprint[i] = fingerprint[i]; + } + + return thumbprint; + } + else + { + DWORD e = GetLastError(); + cbData = e; + } + } + + return Sequence< sal_Int8 >(); +} + +OUString SAL_CALL X509Certificate_MSCryptImpl::getSubjectPublicKeyAlgorithm() +{ + if( m_pCertContext != nullptr && m_pCertContext->pCertInfo != nullptr ) + { + CRYPT_ALGORITHM_IDENTIFIER algorithm = m_pCertContext->pCertInfo->SubjectPublicKeyInfo.Algorithm; + return findOIDDescription( algorithm.pszObjId ) ; + } + else + { + return OUString() ; + } +} + +css::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_MSCryptImpl::getSubjectPublicKeyValue() +{ + if( m_pCertContext != nullptr && m_pCertContext->pCertInfo != nullptr ) + { + CRYPT_BIT_BLOB publicKey = m_pCertContext->pCertInfo->SubjectPublicKeyInfo.PublicKey; + + Sequence< sal_Int8 > key( publicKey.cbData ) ; + auto keyRange = asNonConstRange(key); + for( unsigned int i = 0 ; i < publicKey.cbData ; i++ ) + { + keyRange[i] = *(publicKey.pbData + i) ; + } + + return key; + } + else + { + return Sequence< sal_Int8 >(); + } +} + +OUString SAL_CALL X509Certificate_MSCryptImpl::getSignatureAlgorithm() +{ + if( m_pCertContext != nullptr && m_pCertContext->pCertInfo != nullptr ) + { + CRYPT_ALGORITHM_IDENTIFIER algorithm = m_pCertContext->pCertInfo->SignatureAlgorithm; + return findOIDDescription( algorithm.pszObjId ) ; + } + else + { + return OUString() ; + } +} + +uno::Sequence<sal_Int8> X509Certificate_MSCryptImpl::getSHA256Thumbprint() +{ + return getThumbprint(m_pCertContext, CERT_SHA256_HASH_PROP_ID); +} + +svl::crypto::SignatureMethodAlgorithm X509Certificate_MSCryptImpl::getSignatureMethodAlgorithm() +{ + svl::crypto::SignatureMethodAlgorithm nRet = svl::crypto::SignatureMethodAlgorithm::RSA; + + if (!m_pCertContext || !m_pCertContext->pCertInfo) + return nRet; + + CRYPT_ALGORITHM_IDENTIFIER algorithm = m_pCertContext->pCertInfo->SubjectPublicKeyInfo.Algorithm; + OString aObjId(algorithm.pszObjId); + if (aObjId == szOID_ECC_PUBLIC_KEY) + nRet = svl::crypto::SignatureMethodAlgorithm::ECDSA; + + return nRet; +} + +css::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_MSCryptImpl::getSHA1Thumbprint() +{ + return getThumbprint(m_pCertContext, CERT_SHA1_HASH_PROP_ID); +} + +css::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_MSCryptImpl::getMD5Thumbprint() +{ + return getThumbprint(m_pCertContext, CERT_MD5_HASH_PROP_ID); +} + +CertificateKind SAL_CALL X509Certificate_MSCryptImpl::getCertificateKind() +{ + return CertificateKind_X509; +} + +sal_Int32 SAL_CALL X509Certificate_MSCryptImpl::getCertificateUsage( ) +{ + sal_Int32 usage = + CERT_DATA_ENCIPHERMENT_KEY_USAGE | + CERT_DIGITAL_SIGNATURE_KEY_USAGE | + CERT_KEY_AGREEMENT_KEY_USAGE | + CERT_KEY_CERT_SIGN_KEY_USAGE | + CERT_KEY_ENCIPHERMENT_KEY_USAGE | + CERT_NON_REPUDIATION_KEY_USAGE | + CERT_OFFLINE_CRL_SIGN_KEY_USAGE; + + if( m_pCertContext != nullptr && m_pCertContext->pCertInfo != nullptr && m_pCertContext->pCertInfo->cExtension != 0 ) + { + CERT_EXTENSION* pExtn = CertFindExtension( + szOID_KEY_USAGE, + m_pCertContext->pCertInfo->cExtension, + m_pCertContext->pCertInfo->rgExtension); + + if (pExtn != nullptr) + { + DWORD length = 0; + bool rc = CryptDecodeObject( + X509_ASN_ENCODING, + X509_KEY_USAGE, + pExtn->Value.pbData, + pExtn->Value.cbData, + 0, + nullptr, + &length); + + if (!rc) + SAL_WARN("xmlsecurity.xmlsec", "CryptDecodeObject failed: " << WindowsErrorString(GetLastError())); + else + { + std::vector<char>buffer(length); + + rc = CryptDecodeObject( + X509_ASN_ENCODING, + X509_KEY_USAGE, + pExtn->Value.pbData, + pExtn->Value.cbData, + 0, + buffer.data(), + &length); + + CRYPT_BIT_BLOB *blob = reinterpret_cast<CRYPT_BIT_BLOB*>(buffer.data()); + if (!rc) + SAL_WARN("xmlsecurity.xmlsec", "CryptDecodeObject failed: " << WindowsErrorString(GetLastError())); + else if (blob->cbData == 1) + usage = blob->pbData[0]; + else + SAL_WARN("xmlsecurity.xmlsec", "CryptDecodeObject(X509_KEY_USAGE) returned unexpected amount of data: " << blob->cbData); + } + } + } + + return usage; +} + +/* XServiceInfo */ +OUString SAL_CALL X509Certificate_MSCryptImpl::getImplementationName() +{ + return "com.sun.star.xml.security.gpg.XCertificate_MsCryptImpl"; +} + +/* XServiceInfo */ +sal_Bool SAL_CALL X509Certificate_MSCryptImpl::supportsService(const OUString& serviceName) +{ + return cppu::supportsService(this, serviceName); +} + +/* XServiceInfo */ +Sequence<OUString> SAL_CALL X509Certificate_MSCryptImpl::getSupportedServiceNames() +{ + return { OUString() }; +} + +namespace xmlsecurity { + +// based on some guesswork and: +// https://datatracker.ietf.org/doc/html/rfc1485 +// https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-certnametostra#CERT_X500_NAME_STR +// the main problem appears to be that in values NSS uses \ escapes but CryptoAPI requires " quotes around value +static OUString CompatDNNSS(OUString const& rDN) +{ + OUStringBuffer buf(rDN.getLength()); + enum { DEFAULT, INVALUE, INQUOTE } state(DEFAULT); + for (sal_Int32 i = 0; i < rDN.getLength(); ++i) + { + if (state == DEFAULT) + { + buf.append(rDN[i]); + if (rDN[i] == '=') + { + if (rDN.getLength() == i+1) + { + break; // invalid? + } + else + { + buf.append('"'); + state = INVALUE; + } + } + } + else if (state == INVALUE) + { + if (rDN[i] == '+' || rDN[i] == ',' || rDN[i] == ';') + { + buf.append("\"" + OUStringChar(rDN[i])); + state = DEFAULT; + } + else if (rDN[i] == '\\') + { + if (rDN.getLength() == i+1) + { + break; // invalid? + } + if (rDN[i+1] == '"') + { + buf.append('"'); + } + buf.append(rDN[i+1]); + ++i; + } + else + { + buf.append(rDN[i]); + } + if (i+1 == rDN.getLength()) + { + buf.append('"'); + state = DEFAULT; + } + } + } + return buf.makeStringAndClear(); +} + +static bool EncodeDistinguishedName(std::u16string_view const rName, CERT_NAME_BLOB & rBlob) +{ + LPCWSTR pszError; + if (!CertStrToNameW(X509_ASN_ENCODING, + reinterpret_cast<LPCWSTR>(rName.data()), CERT_X500_NAME_STR, + nullptr, nullptr, &rBlob.cbData, &pszError)) + { + SAL_INFO("xmlsecurity.xmlsec", "CertStrToNameW failed: " << WindowsErrorString(GetLastError()) << "; " << OUString(o3tl::toU(pszError))); + return false; + } + rBlob.pbData = new BYTE[rBlob.cbData]; + if (!CertStrToNameW(X509_ASN_ENCODING, + reinterpret_cast<LPCWSTR>(rName.data()), CERT_X500_NAME_STR, + nullptr, rBlob.pbData, &rBlob.cbData, &pszError)) + { + SAL_INFO("xmlsecurity.xmlsec", "CertStrToNameW failed: " << WindowsErrorString(GetLastError()) << "; " << OUString(o3tl::toU(pszError))); + return false; + } + return true; +} + +bool EqualDistinguishedNames( + std::u16string_view const rName1, std::u16string_view const rName2, + EqualMode const eMode) +{ + if (eMode == COMPAT_BOTH && !rName1.empty() && rName1 == rName2) + { // handle case where both need to be converted + return true; + } + CERT_NAME_BLOB blob1; + if (!EncodeDistinguishedName(rName1, blob1)) + { + return false; + } + CERT_NAME_BLOB blob2; + bool ret(false); + if (EncodeDistinguishedName(rName2, blob2)) + { + ret = CertCompareCertificateName(X509_ASN_ENCODING, + &blob1, &blob2) == TRUE; + delete[] blob2.pbData; + } + if (!ret && eMode == COMPAT_2ND) + { + CERT_NAME_BLOB blob2compat; + if (!EncodeDistinguishedName(CompatDNNSS(OUString(rName2)), blob2compat)) + { + delete[] blob1.pbData; + return false; + } + ret = CertCompareCertificateName(X509_ASN_ENCODING, + &blob1, &blob2compat) == TRUE; + delete[] blob2compat.pbData; + } + delete[] blob1.pbData; + return ret; +} + +} // namespace xmlsecurity + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.hxx b/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.hxx new file mode 100644 index 0000000000..ba02281794 --- /dev/null +++ b/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.hxx @@ -0,0 +1,91 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#if !defined WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +#endif +#include <Windows.h> +#include <WinCrypt.h> +#include <sal/config.h> +#include <rtl/ustring.hxx> +#include <cppuhelper/factory.hxx> +#include <cppuhelper/implbase.hxx> +#include <comphelper/servicehelper.hxx> +#include <com/sun/star/uno/Exception.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/uno/SecurityException.hpp> +#include <com/sun/star/security/CertificateKind.hpp> +#include <com/sun/star/security/XCertificate.hpp> +#include <certificate.hxx> + +class X509Certificate_MSCryptImpl : public ::cppu::WeakImplHelper< + css::security::XCertificate , + css::lang::XServiceInfo > , public xmlsecurity::Certificate +{ + private: + const CERT_CONTEXT* m_pCertContext ; + + public: + X509Certificate_MSCryptImpl() ; + virtual ~X509Certificate_MSCryptImpl() override; + + //Methods from XCertificate + virtual sal_Int16 SAL_CALL getVersion() override; + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSerialNumber() override; + virtual OUString SAL_CALL getIssuerName() override; + virtual OUString SAL_CALL getSubjectName() override; + virtual css::util::DateTime SAL_CALL getNotValidBefore() override; + virtual css::util::DateTime SAL_CALL getNotValidAfter() override; + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getIssuerUniqueID() override; + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSubjectUniqueID() override; + virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificateExtension > > SAL_CALL getExtensions() override; + virtual css::uno::Reference< css::security::XCertificateExtension > SAL_CALL findCertificateExtension( const css::uno::Sequence< sal_Int8 >& oid ) override; + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getEncoded() override; + virtual OUString SAL_CALL getSubjectPublicKeyAlgorithm() override; + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSubjectPublicKeyValue() override; + virtual OUString SAL_CALL getSignatureAlgorithm() override; + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSHA1Thumbprint() override; + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getMD5Thumbprint() override; + virtual css::security::CertificateKind SAL_CALL getCertificateKind() override; + + + virtual sal_Int32 SAL_CALL getCertificateUsage( ) override; + + /// @see xmlsecurity::Certificate::getSHA256Thumbprint(). + virtual css::uno::Sequence<sal_Int8> getSHA256Thumbprint() override; + + /// @see xmlsecurity::Certificate::getSignatureMethodAlgorithm(). + virtual svl::crypto::SignatureMethodAlgorithm getSignatureMethodAlgorithm() override; + + //Helper methods + void setMswcryCert( const CERT_CONTEXT* cert ) ; + const CERT_CONTEXT* getMswcryCert() const ; + /// @throws css::uno::RuntimeException + void setRawCert( css::uno::Sequence< sal_Int8 > const & rawCert ) ; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override; + virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override; +} ; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/mscrypt/xmlsecuritycontext_mscryptimpl.cxx b/xmlsecurity/source/xmlsec/mscrypt/xmlsecuritycontext_mscryptimpl.cxx new file mode 100644 index 0000000000..f024a39b47 --- /dev/null +++ b/xmlsecurity/source/xmlsec/mscrypt/xmlsecuritycontext_mscryptimpl.cxx @@ -0,0 +1,153 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> +#include <xmlsec-wrapper.h> + +#include <com/sun/star/xml/crypto/XXMLSecurityContext.hpp> +#include "securityenvironment_mscryptimpl.hxx" + +#include <xmlsec/xmlstreamio.hxx> +#include "akmngr.hxx" + +#include <cppuhelper/supportsservice.hxx> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::lang ; + +using ::com::sun::star::xml::crypto::XSecurityEnvironment ; +using ::com::sun::star::xml::crypto::XXMLSecurityContext ; + +namespace { + +class XMLSecurityContext_MSCryptImpl : public ::cppu::WeakImplHelper< + css::xml::crypto::XXMLSecurityContext , + css::lang::XServiceInfo > +{ + private: + //xmlSecKeysMngrPtr m_pKeysMngr ; + css::uno::Reference< css::xml::crypto::XSecurityEnvironment > m_xSecurityEnvironment ; + + public: + XMLSecurityContext_MSCryptImpl(); + + //Methods from XXMLSecurityContext + virtual sal_Int32 SAL_CALL addSecurityEnvironment( + const css::uno::Reference< css::xml::crypto::XSecurityEnvironment >& aSecurityEnvironment + ) override; + + virtual ::sal_Int32 SAL_CALL getSecurityEnvironmentNumber( ) override; + + virtual css::uno::Reference< + css::xml::crypto::XSecurityEnvironment > SAL_CALL + getSecurityEnvironmentByIndex( ::sal_Int32 index ) override; + + virtual css::uno::Reference< + css::xml::crypto::XSecurityEnvironment > SAL_CALL + getSecurityEnvironment( ) override; + + virtual ::sal_Int32 SAL_CALL getDefaultSecurityEnvironmentIndex( ) override; + + virtual void SAL_CALL setDefaultSecurityEnvironmentIndex( sal_Int32 nDefaultEnvIndex ) override; + + + //Methods from XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + + virtual sal_Bool SAL_CALL supportsService( + const OUString& ServiceName + ) override; + + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; +}; + +} + +XMLSecurityContext_MSCryptImpl::XMLSecurityContext_MSCryptImpl() +{ +} + +sal_Int32 SAL_CALL XMLSecurityContext_MSCryptImpl::addSecurityEnvironment( + const css::uno::Reference< css::xml::crypto::XSecurityEnvironment >& aSecurityEnvironment) +{ + if( !aSecurityEnvironment.is() ) + { + throw uno::RuntimeException() ; + } + + m_xSecurityEnvironment = aSecurityEnvironment; + + return 0; +} + + +sal_Int32 SAL_CALL XMLSecurityContext_MSCryptImpl::getSecurityEnvironmentNumber( ) +{ + return 1; +} + +css::uno::Reference< css::xml::crypto::XSecurityEnvironment > SAL_CALL + XMLSecurityContext_MSCryptImpl::getSecurityEnvironmentByIndex( sal_Int32 index ) +{ + if (index != 0) + { + throw uno::RuntimeException() ; + } + return m_xSecurityEnvironment; +} + +css::uno::Reference< css::xml::crypto::XSecurityEnvironment > SAL_CALL + XMLSecurityContext_MSCryptImpl::getSecurityEnvironment( ) +{ + return m_xSecurityEnvironment; +} + +sal_Int32 SAL_CALL XMLSecurityContext_MSCryptImpl::getDefaultSecurityEnvironmentIndex( ) +{ + return 0; +} + +void SAL_CALL XMLSecurityContext_MSCryptImpl::setDefaultSecurityEnvironmentIndex( sal_Int32 /*nDefaultEnvIndex*/ ) +{ + //dummy +} + +/* XServiceInfo */ +OUString SAL_CALL XMLSecurityContext_MSCryptImpl::getImplementationName() { + return "com.sun.star.xml.crypto.XMLSecurityContext" ; +} + +/* XServiceInfo */ +sal_Bool SAL_CALL XMLSecurityContext_MSCryptImpl::supportsService( const OUString& serviceName) { + return cppu::supportsService(this, serviceName); +} + +/* XServiceInfo */ +uno::Sequence< OUString > SAL_CALL XMLSecurityContext_MSCryptImpl::getSupportedServiceNames() { + return { "com.sun.star.xml.crypto.XMLSecurityContext" }; +} + +extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface* +com_sun_star_xml_crypto_XMLSecurityContext_get_implementation( + uno::XComponentContext* /*pCtx*/, uno::Sequence<uno::Any> const& /*rSeq*/) +{ + return cppu::acquire(new XMLSecurityContext_MSCryptImpl); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/mscrypt/xmlsignature_mscryptimpl.cxx b/xmlsecurity/source/xmlsec/mscrypt/xmlsignature_mscryptimpl.cxx new file mode 100644 index 0000000000..2a3709938a --- /dev/null +++ b/xmlsecurity/source/xmlsec/mscrypt/xmlsignature_mscryptimpl.cxx @@ -0,0 +1,305 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> +#include <sal/log.hxx> +#include <rtl/uuid.h> +#include <xmlsec-wrapper.h> + +#include <xmlsec/mscng/x509.h> + +#include <com/sun/star/xml/crypto/SecurityOperationStatus.hpp> +#include <com/sun/star/xml/crypto/XXMLSignature.hpp> + +#include "securityenvironment_mscryptimpl.hxx" + +#include <xmlsec/xmldocumentwrapper_xmlsecimpl.hxx> +#include <xmlelementwrapper_xmlsecimpl.hxx> +#include <xmlsec/xmlstreamio.hxx> +#include <xmlsec/errorcallback.hxx> +#include <cppuhelper/supportsservice.hxx> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno ; +using namespace ::com::sun::star::lang ; + +using ::com::sun::star::xml::wrapper::XXMLElementWrapper ; +using ::com::sun::star::xml::crypto::XSecurityEnvironment ; +using ::com::sun::star::xml::crypto::XXMLSignature ; +using ::com::sun::star::xml::crypto::XXMLSignatureTemplate ; +using ::com::sun::star::xml::crypto::XXMLSecurityContext ; +using ::com::sun::star::xml::crypto::XUriBinding ; + +namespace { + +class XMLSignature_MSCryptImpl : public ::cppu::WeakImplHelper< + css::xml::crypto::XXMLSignature , + css::lang::XServiceInfo > +{ + public: + explicit XMLSignature_MSCryptImpl(); + + //Methods from XXMLSignature + virtual css::uno::Reference< css::xml::crypto::XXMLSignatureTemplate > SAL_CALL generate( + const css::uno::Reference< css::xml::crypto::XXMLSignatureTemplate >& aTemplate , + const css::uno::Reference< css::xml::crypto::XSecurityEnvironment >& aEnvironment + ) override; + + virtual css::uno::Reference< css::xml::crypto::XXMLSignatureTemplate > SAL_CALL validate( + const css::uno::Reference< css::xml::crypto::XXMLSignatureTemplate >& aTemplate , + const css::uno::Reference< css::xml::crypto::XXMLSecurityContext >& aContext + ) override; + + //Methods from XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + + virtual sal_Bool SAL_CALL supportsService( + const OUString& ServiceName + ) override; + + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; +} ; + +} + +XMLSignature_MSCryptImpl::XMLSignature_MSCryptImpl() { +} + +/* XXMLSignature */ +Reference< XXMLSignatureTemplate > +SAL_CALL XMLSignature_MSCryptImpl::generate( + const Reference< XXMLSignatureTemplate >& aTemplate , + const Reference< XSecurityEnvironment >& aEnvironment +) +{ + xmlSecKeysMngrPtr pMngr = nullptr ; + xmlSecDSigCtxPtr pDsigCtx = nullptr ; + xmlNodePtr pNode = nullptr ; + + if( !aTemplate.is() ) + throw RuntimeException() ; + + if( !aEnvironment.is() ) + throw RuntimeException() ; + + //Get Keys Manager + SecurityEnvironment_MSCryptImpl* pSecEnv = dynamic_cast<SecurityEnvironment_MSCryptImpl*>(aEnvironment.get()); + if( pSecEnv == nullptr ) + throw RuntimeException() ; + + //Get the xml node + Reference< XXMLElementWrapper > xElement = aTemplate->getTemplate() ; + if( !xElement.is() ) { + throw RuntimeException() ; + } + + XMLElementWrapper_XmlSecImpl* pElement = dynamic_cast<XMLElementWrapper_XmlSecImpl*>(xElement.get()); + if( pElement == nullptr ) { + throw RuntimeException() ; + } + + pNode = pElement->getNativeElement() ; + + //Get the stream/URI binding + Reference< XUriBinding > xUriBinding = aTemplate->getBinding() ; + if( xUriBinding.is() ) { + //Register the stream input callbacks into libxml2 + if( xmlRegisterStreamInputCallbacks( xUriBinding ) < 0 ) + throw RuntimeException() ; + } + + setErrorRecorder( ); + + pMngr = pSecEnv->createKeysManager(); + if( !pMngr ) { + throw RuntimeException() ; + } + + //Create Signature context + pDsigCtx = xmlSecDSigCtxCreate( pMngr ) ; + if( pDsigCtx == nullptr ) + { + //throw XMLSignatureException() ; + SecurityEnvironment_MSCryptImpl::destroyKeysManager( pMngr ); + clearErrorRecorder(); + return aTemplate; + } + + //Sign the template + if( xmlSecDSigCtxSign( pDsigCtx , pNode ) == 0 ) + { + if (pDsigCtx->status == xmlSecDSigStatusSucceeded) + aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED); + else + aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_UNKNOWN); + } + else + { + aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_UNKNOWN); + } + + + xmlSecDSigCtxDestroy( pDsigCtx ) ; + SecurityEnvironment_MSCryptImpl::destroyKeysManager( pMngr ); + + //Unregistered the stream/URI binding + if( xUriBinding.is() ) + xmlUnregisterStreamInputCallbacks() ; + + clearErrorRecorder(); + return aTemplate ; +} + +/* XXMLSignature */ +Reference< XXMLSignatureTemplate > +SAL_CALL XMLSignature_MSCryptImpl::validate( + const Reference< XXMLSignatureTemplate >& aTemplate , + const Reference< XXMLSecurityContext >& aSecurityCtx +) { + xmlSecKeysMngrPtr pMngr = nullptr ; + xmlSecDSigCtxPtr pDsigCtx = nullptr ; + xmlNodePtr pNode = nullptr ; + + if( !aTemplate.is() ) + throw RuntimeException() ; + + if( !aSecurityCtx.is() ) + throw RuntimeException() ; + + //Get Keys Manager + Reference< XSecurityEnvironment > xSecEnv + = aSecurityCtx->getSecurityEnvironmentByIndex( + aSecurityCtx->getDefaultSecurityEnvironmentIndex()); + SecurityEnvironment_MSCryptImpl* pSecEnv = dynamic_cast<SecurityEnvironment_MSCryptImpl*>(xSecEnv.get()); + if( pSecEnv == nullptr ) + throw RuntimeException() ; + + //Get the xml node + Reference< XXMLElementWrapper > xElement = aTemplate->getTemplate() ; + if( !xElement.is() ) + throw RuntimeException() ; + + XMLElementWrapper_XmlSecImpl* pElement = dynamic_cast<XMLElementWrapper_XmlSecImpl*>(xElement.get()); + if( pElement == nullptr ) + throw RuntimeException() ; + + pNode = pElement->getNativeElement() ; + + //Get the stream/URI binding + Reference< XUriBinding > xUriBinding = aTemplate->getBinding() ; + if( xUriBinding.is() ) { + //Register the stream input callbacks into libxml2 + if( xmlRegisterStreamInputCallbacks( xUriBinding ) < 0 ) + throw RuntimeException() ; + } + + setErrorRecorder( ); + + pMngr = pSecEnv->createKeysManager(); + if( !pMngr ) { + throw RuntimeException() ; + } + + //Create Signature context + pDsigCtx = xmlSecDSigCtxCreate( pMngr ) ; + if( pDsigCtx == nullptr ) + { + SecurityEnvironment_MSCryptImpl::destroyKeysManager( pMngr ); + clearErrorRecorder(); + return aTemplate; + } + + // We do certificate verification ourselves. + pDsigCtx->keyInfoReadCtx.flags |= XMLSEC_KEYINFO_FLAGS_X509DATA_DONT_VERIFY_CERTS; + + // limit possible key data to valid X509 certificates only, no KeyValues + if (xmlSecPtrListAdd(&(pDsigCtx->keyInfoReadCtx.enabledKeyData), BAD_CAST xmlSecMSCngKeyDataX509GetKlass()) < 0) + throw RuntimeException("failed to limit allowed key data"); + + //Verify signature + //The documentation says that the signature is only valid if the return value is 0 (that is, not < 0) + //AND pDsigCtx->status == xmlSecDSigStatusSucceeded. That is, we must not make any assumptions, if + //the return value is < 0. Then we must regard the signature as INVALID. We cannot use the + //error recorder feature to get the ONE error that made the verification fail, because there is no + //documentation/specification as to how to interpret the number of recorded errors and what is the initial + //error. + int rs = xmlSecDSigCtxVerify(pDsigCtx , pNode); + + // Also verify manifest: this is empty for ODF, but contains everything (except signature metadata) for OOXML. + xmlSecSize nReferenceCount = xmlSecPtrListGetSize(&pDsigCtx->manifestReferences); + // Require that all manifest references are also good. + xmlSecSize nReferenceGood = 0; + for (xmlSecSize nReference = 0; nReference < nReferenceCount; ++nReference) + { + xmlSecDSigReferenceCtxPtr pReference = static_cast<xmlSecDSigReferenceCtxPtr>(xmlSecPtrListGetItem(&pDsigCtx->manifestReferences, nReference)); + if (pReference) + { + if (pReference->status == xmlSecDSigStatusSucceeded) + ++nReferenceGood; + } + } + SAL_INFO("xmlsecurity.xmlsec", "xmlSecDSigCtxVerify status " << pDsigCtx->status << ", references good " << nReferenceGood << " of " << nReferenceCount); + + if (rs == 0 && nReferenceCount == nReferenceGood) + { + if (pDsigCtx->status == xmlSecDSigStatusSucceeded) + aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED); + else + aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_UNKNOWN); + } + else + { + aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_UNKNOWN); + } + + xmlSecDSigCtxDestroy( pDsigCtx ) ; + SecurityEnvironment_MSCryptImpl::destroyKeysManager( pMngr ); + + //Unregistered the stream/URI binding + if( xUriBinding.is() ) + xmlUnregisterStreamInputCallbacks() ; + + + clearErrorRecorder(); + return aTemplate; +} + +/* XServiceInfo */ +OUString SAL_CALL XMLSignature_MSCryptImpl::getImplementationName() { + return "com.sun.star.xml.crypto.XMLSignature"; +} + +/* XServiceInfo */ +sal_Bool SAL_CALL XMLSignature_MSCryptImpl::supportsService( const OUString& serviceName) { +return cppu::supportsService(this, serviceName); +} + +/* XServiceInfo */ +Sequence< OUString > SAL_CALL XMLSignature_MSCryptImpl::getSupportedServiceNames() { + return { "com.sun.star.xml.crypto.XMLSignature" }; +} + +extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface* +com_sun_star_xml_crypto_XMLSignature_get_implementation(uno::XComponentContext* /*pCtx*/, + uno::Sequence<uno::Any> const& /*rSeq*/) +{ + return cppu::acquire(new XMLSignature_MSCryptImpl); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/certerrors.h b/xmlsecurity/source/xmlsec/nss/certerrors.h new file mode 100644 index 0000000000..e8b7b38737 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/certerrors.h @@ -0,0 +1,385 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +{SEC_ERROR_IO, "An I/O error occurred during security authorization."}, + +{SEC_ERROR_LIBRARY_FAILURE, "security library failure."}, + +{SEC_ERROR_BAD_DATA, "security library: received bad data."}, + +{SEC_ERROR_OUTPUT_LEN, "security library: output length error."}, + +{SEC_ERROR_INPUT_LEN, "security library has experienced an input length error."}, + +{SEC_ERROR_INVALID_ARGS, "security library: invalid arguments."}, + +{SEC_ERROR_INVALID_ALGORITHM, "security library: invalid algorithm."}, + +{SEC_ERROR_INVALID_AVA, "security library: invalid AVA."}, + +{SEC_ERROR_INVALID_TIME, "Improperly formatted time string."}, + +{SEC_ERROR_BAD_DER, "security library: improperly formatted DER-encoded message."}, + +{SEC_ERROR_BAD_SIGNATURE, "Peer's certificate has an invalid signature."}, + +{SEC_ERROR_EXPIRED_CERTIFICATE, "Peer's Certificate has expired."}, + +{SEC_ERROR_REVOKED_CERTIFICATE, "Peer's Certificate has been revoked."}, + +{SEC_ERROR_UNKNOWN_ISSUER, "Peer's Certificate issuer is not recognized."}, + +{SEC_ERROR_BAD_KEY, "Peer's public key is invalid."}, + +{SEC_ERROR_BAD_PASSWORD, "The security password entered is incorrect."}, + +{SEC_ERROR_RETRY_PASSWORD, "New password entered incorrectly. Please try again."}, + +{SEC_ERROR_NO_NODELOCK, "security library: no nodelock."}, + +{SEC_ERROR_BAD_DATABASE, "security library: bad database."}, + +{SEC_ERROR_NO_MEMORY, "security library: memory allocation failure."}, + +{SEC_ERROR_UNTRUSTED_ISSUER, "Peer's certificate issuer has been marked as not trusted by the user."}, + +{SEC_ERROR_UNTRUSTED_CERT, "Peer's certificate has been marked as not trusted by the user."}, + +{SEC_ERROR_DUPLICATE_CERT, "Certificate already exists in your database."}, + +{SEC_ERROR_DUPLICATE_CERT_NAME, "Downloaded certificate's name duplicates one already in your database."}, + +{SEC_ERROR_ADDING_CERT, "Error adding certificate to database."}, + +{SEC_ERROR_FILING_KEY, "Error refiling the key for this certificate."}, + +{SEC_ERROR_NO_KEY, "The private key for this certificate cannot be found in key database"}, + +{SEC_ERROR_CERT_VALID, "This certificate is valid."}, + +{SEC_ERROR_CERT_NOT_VALID, "This certificate is not valid."}, + +{SEC_ERROR_CERT_NO_RESPONSE, "Cert Library: No Response"}, + +{SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE, "The certificate issuer's certificate has expired. Check your system date and time."}, + +{SEC_ERROR_CRL_EXPIRED, "The CRL for the certificate's issuer has expired. Update it or check your system date and time."}, + +{SEC_ERROR_CRL_BAD_SIGNATURE, "The CRL for the certificate's issuer has an invalid signature."}, + +{SEC_ERROR_CRL_INVALID, "New CRL has an invalid format."}, + +{SEC_ERROR_EXTENSION_VALUE_INVALID, "Certificate extension value is invalid."}, + +{SEC_ERROR_EXTENSION_NOT_FOUND, "Certificate extension not found."}, + +{SEC_ERROR_CA_CERT_INVALID, "Issuer certificate is invalid."}, + +{SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID, "Certificate path length constraint is invalid."}, + +{SEC_ERROR_CERT_USAGES_INVALID, "Certificate usages field is invalid."}, + +{SEC_INTERNAL_ONLY, "**Internal ONLY module**"}, + +{SEC_ERROR_INVALID_KEY, "The key does not support the requested operation."}, + +{SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION, "Certificate contains unknown critical extension."}, + +{SEC_ERROR_OLD_CRL, "New CRL is not later than the current one."}, + +{SEC_ERROR_NO_EMAIL_CERT, "Not encrypted or signed: you do not yet have an email certificate."}, + +{SEC_ERROR_NO_RECIPIENT_CERTS_QUERY, "Not encrypted: you do not have certificates for each of the recipients."}, + +{SEC_ERROR_NOT_A_RECIPIENT, "Cannot decrypt: you are not a recipient, or matching certificate and \ +private key not found."}, + +{SEC_ERROR_PKCS7_KEYALG_MISMATCH, "Cannot decrypt: key encryption algorithm does not match your certificate."}, + +{SEC_ERROR_PKCS7_BAD_SIGNATURE, "Signature verification failed: no signer found, too many signers found, \ +or improper or corrupted data."}, + +{SEC_ERROR_UNSUPPORTED_KEYALG, "Unsupported or unknown key algorithm."}, + +{SEC_ERROR_DECRYPTION_DISALLOWED, "Cannot decrypt: encrypted using a disallowed algorithm or key size."}, + + +/* Fortezza Alerts */ +{XP_SEC_FORTEZZA_BAD_CARD, "Fortezza card has not been properly initialized. \ +Please remove it and return it to your issuer."}, + +{XP_SEC_FORTEZZA_NO_CARD, "No Fortezza cards Found"}, + +{XP_SEC_FORTEZZA_NONE_SELECTED, "No Fortezza card selected"}, + +{XP_SEC_FORTEZZA_MORE_INFO, "Please select a personality to get more info on"}, + +{XP_SEC_FORTEZZA_PERSON_NOT_FOUND, "Personality not found"}, + +{XP_SEC_FORTEZZA_NO_MORE_INFO, "No more information on that Personality"}, + +{XP_SEC_FORTEZZA_BAD_PIN, "Invalid Pin"}, + +{XP_SEC_FORTEZZA_PERSON_ERROR, "Couldn't initialize Fortezza personalities."}, +/* end fortezza alerts. */ + +{SEC_ERROR_NO_KRL, "No KRL for this site's certificate has been found."}, + +{SEC_ERROR_KRL_EXPIRED, "The KRL for this site's certificate has expired."}, + +{SEC_ERROR_KRL_BAD_SIGNATURE, "The KRL for this site's certificate has an invalid signature."}, + +{SEC_ERROR_REVOKED_KEY, "The key for this site's certificate has been revoked."}, + +{SEC_ERROR_KRL_INVALID, "New KRL has an invalid format."}, + +{SEC_ERROR_NEED_RANDOM, "security library: need random data."}, + +{SEC_ERROR_NO_MODULE, "security library: no security module can perform the requested operation."}, + +{SEC_ERROR_NO_TOKEN, "The security card or token does not exist, needs to be initialized, or has been removed."}, + +{SEC_ERROR_READ_ONLY, "security library: read-only database."}, + +{SEC_ERROR_NO_SLOT_SELECTED, "No slot or token was selected."}, + +{SEC_ERROR_CERT_NICKNAME_COLLISION, "A certificate with the same nickname already exists."}, + +{SEC_ERROR_KEY_NICKNAME_COLLISION, "A key with the same nickname already exists."}, + +{SEC_ERROR_SAFE_NOT_CREATED, "error while creating safe object"}, + +{SEC_ERROR_BAGGAGE_NOT_CREATED, "error while creating baggage object"}, + +{XP_JAVA_REMOVE_PRINCIPAL_ERROR, "Couldn't remove the principal"}, + +{XP_JAVA_DELETE_PRIVILEGE_ERROR, "Couldn't delete the privilege"}, + +{XP_JAVA_CERT_NOT_EXISTS_ERROR, "This principal doesn't have a certificate"}, + +{SEC_ERROR_BAD_EXPORT_ALGORITHM, "Required algorithm is not allowed."}, + +{SEC_ERROR_EXPORTING_CERTIFICATES, "Error attempting to export certificates."}, + +{SEC_ERROR_IMPORTING_CERTIFICATES, "Error attempting to import certificates."}, + +{SEC_ERROR_PKCS12_DECODING_PFX, "Unable to import. Decoding error. File not valid."}, + +{SEC_ERROR_PKCS12_INVALID_MAC, "Unable to import. Invalid MAC. Incorrect password or corrupt file."}, + +{SEC_ERROR_PKCS12_UNSUPPORTED_MAC_ALGORITHM, "Unable to import. MAC algorithm not supported."}, + +{SEC_ERROR_PKCS12_UNSUPPORTED_TRANSPORT_MODE, "Unable to import. Only password integrity and privacy modes supported."}, + +{SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE, "Unable to import. File structure is corrupt."}, + +{SEC_ERROR_PKCS12_UNSUPPORTED_PBE_ALGORITHM, "Unable to import. Encryption algorithm not supported."}, + +{SEC_ERROR_PKCS12_UNSUPPORTED_VERSION, "Unable to import. File version not supported."}, + +{SEC_ERROR_PKCS12_PRIVACY_PASSWORD_INCORRECT, "Unable to import. Incorrect privacy password."}, + +{SEC_ERROR_PKCS12_CERT_COLLISION, "Unable to import. Same nickname already exists in database."}, + +{SEC_ERROR_USER_CANCELLED, "The user pressed cancel."}, + +{SEC_ERROR_PKCS12_DUPLICATE_DATA, "Not imported, already in database."}, + +{SEC_ERROR_MESSAGE_SEND_ABORTED, "Message not sent."}, + +{SEC_ERROR_INADEQUATE_KEY_USAGE, "Certificate key usage inadequate for attempted operation."}, + +{SEC_ERROR_INADEQUATE_CERT_TYPE, "Certificate type not approved for application."}, + +{SEC_ERROR_CERT_ADDR_MISMATCH, "Address in signing certificate does not match address in message headers."}, + +{SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY, "Unable to import. Error attempting to import private key."}, + +{SEC_ERROR_PKCS12_IMPORTING_CERT_CHAIN, "Unable to import. Error attempting to import certificate chain."}, + +{SEC_ERROR_PKCS12_UNABLE_TO_LOCATE_OBJECT_BY_NAME, "Unable to export. Unable to locate certificate or key by nickname."}, + +{SEC_ERROR_PKCS12_UNABLE_TO_EXPORT_KEY, "Unable to export. Private Key could not be located and exported."}, + +{SEC_ERROR_PKCS12_UNABLE_TO_WRITE, "Unable to export. Unable to write the export file."}, + +{SEC_ERROR_PKCS12_UNABLE_TO_READ, "Unable to import. Unable to read the import file."}, + +{SEC_ERROR_PKCS12_KEY_DATABASE_NOT_INITIALIZED, "Unable to export. Key database corrupt or deleted."}, + +{SEC_ERROR_KEYGEN_FAIL, "Unable to generate public/private key pair."}, + +{SEC_ERROR_INVALID_PASSWORD, "Password entered is invalid. Please pick a different one."}, + +{SEC_ERROR_RETRY_OLD_PASSWORD, "Old password entered incorrectly. Please try again."}, + +{SEC_ERROR_BAD_NICKNAME, "Certificate nickname already in use."}, + +{SEC_ERROR_NOT_FORTEZZA_ISSUER, "Peer FORTEZZA chain has a non-FORTEZZA Certificate."}, + +{SEC_ERROR_CANNOT_MOVE_SENSITIVE_KEY, "A sensitive key cannot be moved to the slot where it is needed."}, + +{SEC_ERROR_JS_INVALID_MODULE_NAME, "Invalid module name."}, + +{SEC_ERROR_JS_INVALID_DLL, "Invalid module path/filename"}, + +{SEC_ERROR_JS_ADD_MOD_FAILURE, "Unable to add module"}, + +{SEC_ERROR_JS_DEL_MOD_FAILURE, "Unable to delete module"}, + +{SEC_ERROR_OLD_KRL, "New KRL is not later than the current one."}, + +{SEC_ERROR_CKL_CONFLICT, "New CKL has different issuer than current CKL. Delete current CKL."}, + +{SEC_ERROR_CERT_NOT_IN_NAME_SPACE, "The Certifying Authority for this certificate is not permitted to issue a \ +certificate with this name."}, + +{SEC_ERROR_KRL_NOT_YET_VALID, "The key revocation list for this certificate is not yet valid."}, + +{SEC_ERROR_CRL_NOT_YET_VALID, "The certificate revocation list for this certificate is not yet valid."}, + +{SEC_ERROR_UNKNOWN_CERT, "The requested certificate could not be found."}, + +{SEC_ERROR_UNKNOWN_SIGNER, "The signer's certificate could not be found."}, + +{SEC_ERROR_CERT_BAD_ACCESS_LOCATION, "The location for the certificate status server has invalid format."}, + +{SEC_ERROR_OCSP_UNKNOWN_RESPONSE_TYPE, "The OCSP response cannot be fully decoded; it is of an unknown type."}, + +{SEC_ERROR_OCSP_BAD_HTTP_RESPONSE, "The OCSP server returned unexpected/invalid HTTP data."}, + +{SEC_ERROR_OCSP_MALFORMED_REQUEST, "The OCSP server found the request to be corrupted or improperly formed."}, + +{SEC_ERROR_OCSP_SERVER_ERROR, "The OCSP server experienced an internal error."}, + +{SEC_ERROR_OCSP_TRY_SERVER_LATER, "The OCSP server suggests trying again later."}, + +{SEC_ERROR_OCSP_REQUEST_NEEDS_SIG, "The OCSP server requires a signature on this request."}, + +{SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST, "The OCSP server has refused this request as unauthorized."}, + +{SEC_ERROR_OCSP_UNKNOWN_RESPONSE_STATUS, "The OCSP server returned an unrecognizable status."}, + +{SEC_ERROR_OCSP_UNKNOWN_CERT, "The OCSP server has no status for the certificate."}, + +{SEC_ERROR_OCSP_NOT_ENABLED, "You must enable OCSP before performing this operation."}, + +{SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER, "You must set the OCSP default responder before performing this operation."}, + +{SEC_ERROR_OCSP_MALFORMED_RESPONSE, "The response from the OCSP server was corrupted or improperly formed."}, + +{SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE, "The signer of the OCSP response is not authorized to give status for \ +this certificate."}, + +{SEC_ERROR_OCSP_FUTURE_RESPONSE, "The OCSP response is not yet valid (contains a date in the future},."}, + +{SEC_ERROR_OCSP_OLD_RESPONSE, "The OCSP response contains out-of-date information."}, + +{SEC_ERROR_DIGEST_NOT_FOUND, "The CMS or PKCS #7 Digest was not found in signed message."}, + +{SEC_ERROR_UNSUPPORTED_MESSAGE_TYPE, "The CMS or PKCS #7 Message type is unsupported."}, + +{SEC_ERROR_MODULE_STUCK, "PKCS #11 module could not be removed because it is still in use."}, + +{SEC_ERROR_BAD_TEMPLATE, "Could not decode ASN.1 data. Specified template was invalid."}, + +{SEC_ERROR_CRL_NOT_FOUND, "No matching CRL was found."}, + +{SEC_ERROR_REUSED_ISSUER_AND_SERIAL, "You are attempting to import a cert with the same issuer/serial as \ +an existing cert, but that is not the same cert."}, + +{SEC_ERROR_BUSY, "NSS could not shutdown. Objects are still in use."}, + +{SEC_ERROR_EXTRA_INPUT, "DER-encoded message contained extra unused data."}, + +{SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE, "Unsupported elliptic curve."}, + +{SEC_ERROR_UNSUPPORTED_EC_POINT_FORM, "Unsupported elliptic curve point form."}, + +{SEC_ERROR_UNRECOGNIZED_OID, "Unrecognized Object Identifier."}, + +{SEC_ERROR_OCSP_INVALID_SIGNING_CERT, "Invalid OCSP signing certificate in OCSP response."}, + +{SEC_ERROR_REVOKED_CERTIFICATE_CRL, "Certificate is revoked in issuer's certificate revocation list."}, + +{SEC_ERROR_REVOKED_CERTIFICATE_OCSP, "Issuer's OCSP responder reports certificate is revoked."}, + +{SEC_ERROR_CRL_INVALID_VERSION, "Issuer's Certificate Revocation List has an unknown version number."}, + +{SEC_ERROR_CRL_V1_CRITICAL_EXTENSION, "Issuer's V1 Certificate Revocation List has a critical extension."}, + +{SEC_ERROR_CRL_UNKNOWN_CRITICAL_EXTENSION, "Issuer's V2 Certificate Revocation List has an unknown critical extension."}, + +{SEC_ERROR_UNKNOWN_OBJECT_TYPE, "Unknown object type specified."}, + +{SEC_ERROR_INCOMPATIBLE_PKCS11, "PKCS #11 driver violates the spec in an incompatible way."}, + +{SEC_ERROR_NO_EVENT, "No new slot event is available at this time."}, + +{SEC_ERROR_CRL_ALREADY_EXISTS, "CRL already exists."}, + +{SEC_ERROR_NOT_INITIALIZED, "NSS is not initialized."}, + +{SEC_ERROR_TOKEN_NOT_LOGGED_IN, "The operation failed because the PKCS#11 token is not logged in."}, + +{SEC_ERROR_OCSP_RESPONDER_CERT_INVALID, "Configured OCSP responder's certificate is invalid."}, + +{SEC_ERROR_OCSP_BAD_SIGNATURE, "OCSP response has an invalid signature."}, + +{SEC_ERROR_OUT_OF_SEARCH_LIMITS, "Cert validation search is out of search limits"}, + +{SEC_ERROR_INVALID_POLICY_MAPPING, "Policy mapping contains anypolicy"}, + +{SEC_ERROR_POLICY_VALIDATION_FAILED, "Cert chain fails policy validation"}, + +{SEC_ERROR_UNKNOWN_AIA_LOCATION_TYPE, "Unknown location type in cert AIA extension"}, + +{SEC_ERROR_BAD_HTTP_RESPONSE, "Server returned bad HTTP response"}, + +{SEC_ERROR_BAD_LDAP_RESPONSE, "Server returned bad LDAP response"}, + +{SEC_ERROR_FAILED_TO_ENCODE_DATA, "Failed to encode data with ASN1 encoder"}, + +{SEC_ERROR_BAD_INFO_ACCESS_LOCATION, "Bad information access location in cert extension"}, + +{SEC_ERROR_LIBPKIX_INTERNAL, "Libpkix internal error occurred during cert validation."}, + +#if ( NSS_VMAJOR > 3 ) || ( NSS_VMAJOR == 3 && NSS_VMINOR > 12 ) || ( NSS_VMAJOR == 3 && NSS_VMINOR == 12 && NSS_VPATCH > 2 ) +// following 3 errors got first used in NSS 3.12.3 +// they were in the header even in 3.12.2 but there was missing the mapping in pk11err.c +// see also https://bugzilla.mozilla.org/show_bug.cgi?id=453364 + +{SEC_ERROR_PKCS11_GENERAL_ERROR, "A PKCS #11 module returned CKR_GENERAL_ERROR, indicating that an unrecoverable error has occurred."}, + +{SEC_ERROR_PKCS11_FUNCTION_FAILED, "A PKCS #11 module returned CKR_FUNCTION_FAILED, indicating that the requested function could not be performed. Trying the same operation again might succeed."}, + +{SEC_ERROR_PKCS11_DEVICE_ERROR, "A PKCS #11 module returned CKR_DEVICE_ERROR, indicating that a problem has occurred with the token or slot."}, + +#endif + +#if ( NSS_VMAJOR > 3 ) || ( NSS_VMAJOR == 3 && NSS_VMINOR > 12 ) || ( NSS_VMAJOR == 3 && NSS_VMINOR == 12 && NSS_VPATCH > 3 ) +// following 2 errors got added in NSS 3.12.4 + +{SEC_ERROR_BAD_INFO_ACCESS_METHOD, "Unknown information access method in certificate extension."}, + +{SEC_ERROR_CRL_IMPORT_FAILED, "Error attempting to import a CRL."}, + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/ciphercontext.cxx b/xmlsecurity/source/xmlsec/nss/ciphercontext.cxx new file mode 100644 index 0000000000..c3bbfdb0f2 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/ciphercontext.cxx @@ -0,0 +1,389 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include <com/sun/star/lang/DisposedException.hpp> +#include <rtl/random.h> +#include <rtl/ref.hxx> +#include <sal/log.hxx> + +#include "ciphercontext.hxx" +#include <nss.h> // for NSS_VMINOR +#include <pk11pub.h> + +constexpr size_t nAESGCMIVSize = 12; +constexpr size_t nAESGCMTagSize = 16; + +using namespace ::com::sun::star; + +uno::Reference< xml::crypto::XCipherContext > OCipherContext::Create( CK_MECHANISM_TYPE nNSSCipherID, const uno::Sequence< ::sal_Int8 >& aKey, const uno::Sequence< ::sal_Int8 >& aInitializationVector, bool bEncryption, bool bW3CPadding ) +{ + ::rtl::Reference< OCipherContext > xResult = new OCipherContext; + + xResult->m_pSlot = PK11_GetBestSlot( nNSSCipherID, nullptr ); + if (!xResult->m_pSlot) + { + SAL_WARN("xmlsecurity.nss", "PK11_GetBestSlot failed"); + throw uno::RuntimeException("PK11_GetBestSlot failed"); + } + + SECItem aKeyItem = { siBuffer, + const_cast<unsigned char*>(reinterpret_cast<const unsigned char*>(aKey.getConstArray())), + sal::static_int_cast<unsigned>(aKey.getLength()) }; + xResult->m_pSymKey = PK11_ImportSymKey(xResult->m_pSlot, nNSSCipherID, + PK11_OriginDerive, bEncryption ? CKA_ENCRYPT : CKA_DECRYPT, &aKeyItem, nullptr); + if (!xResult->m_pSymKey) + { + SAL_WARN("xmlsecurity.nss", "PK11_ImportSymKey failed"); + throw uno::RuntimeException("PK11_ImportSymKey failed"); + } + + if (nNSSCipherID == CKM_AES_GCM) + { + // TODO: when runtime requirements are raised to NSS 3.52, + // cleanup according to + // https://fedoraproject.org/wiki/Changes/NssGCMParams +#if NSS_VMINOR >= 52 + xResult->m_pSecParam = SECITEM_AllocItem(nullptr, nullptr, sizeof(CK_NSS_GCM_PARAMS)); +#else + xResult->m_pSecParam = SECITEM_AllocItem(nullptr, nullptr, sizeof(CK_GCM_PARAMS)); +#endif + if (!xResult->m_pSecParam) + { + SAL_WARN("xmlsecurity.nss", "SECITEM_AllocItem failed"); + throw uno::RuntimeException("SECITEM_AllocItem failed"); + } + assert(aInitializationVector.getLength() == nAESGCMIVSize); + xResult->m_AESGCMIV = aInitializationVector; +#if NSS_VMINOR >= 52 + auto *const pParams = reinterpret_cast<CK_NSS_GCM_PARAMS*>(xResult->m_pSecParam->data); +#else + auto *const pParams = reinterpret_cast<CK_GCM_PARAMS*>(xResult->m_pSecParam->data); +#endif + pParams->pIv = const_cast<unsigned char*>(reinterpret_cast<const unsigned char*>(xResult->m_AESGCMIV.getConstArray())); + pParams->ulIvLen = sal::static_int_cast<unsigned>(xResult->m_AESGCMIV.getLength()); + pParams->pAAD = nullptr; + pParams->ulAADLen = 0; + pParams->ulTagBits = nAESGCMTagSize * 8; + } + else + { + SECItem aIVItem = { siBuffer, + const_cast<unsigned char*>(reinterpret_cast<const unsigned char*>(aInitializationVector.getConstArray())), + sal::static_int_cast<unsigned>(aInitializationVector.getLength()) }; + xResult->m_pSecParam = PK11_ParamFromIV(nNSSCipherID, &aIVItem); + if (!xResult->m_pSecParam) + { + SAL_WARN("xmlsecurity.nss", "PK11_ParamFromIV failed"); + throw uno::RuntimeException("PK11_ParamFromIV failed"); + } + + xResult->m_pContext = PK11_CreateContextBySymKey( nNSSCipherID, bEncryption ? CKA_ENCRYPT : CKA_DECRYPT, xResult->m_pSymKey, xResult->m_pSecParam); + if (!xResult->m_pContext) + { + SAL_WARN("xmlsecurity.nss", "PK11_CreateContextBySymKey failed"); + throw uno::RuntimeException("PK11_CreateContextBySymKey failed"); + } + } + + xResult->m_bEncryption = bEncryption; + xResult->m_bW3CPadding = bW3CPadding; + xResult->m_bPadding = bW3CPadding || ( PK11_GetPadMechanism( nNSSCipherID ) == nNSSCipherID ); + // in NSS 3.94, a global default value of 8 is returned for CKM_AES_GCM + xResult->m_nBlockSize = nNSSCipherID == CKM_AES_GCM ? 16 : PK11_GetBlockSize(nNSSCipherID, xResult->m_pSecParam); + if (SAL_MAX_INT8 < xResult->m_nBlockSize) + { + SAL_WARN("xmlsecurity.nss", "PK11_GetBlockSize unexpected result"); + throw uno::RuntimeException("PK11_GetBlockSize unexpected result"); + } + return xResult; +} + +void OCipherContext::Dispose() +{ + if ( m_pContext ) + { + PK11_DestroyContext( m_pContext, PR_TRUE ); + m_pContext = nullptr; + } + + if ( m_pSecParam ) + { + SECITEM_FreeItem( m_pSecParam, PR_TRUE ); + m_pSecParam = nullptr; + } + + if ( m_pSymKey ) + { + PK11_FreeSymKey( m_pSymKey ); + m_pSymKey = nullptr; + } + + if ( m_pSlot ) + { + PK11_FreeSlot( m_pSlot ); + m_pSlot = nullptr; + } + + m_bDisposed = true; +} + +uno::Sequence< ::sal_Int8 > SAL_CALL OCipherContext::convertWithCipherContext( const uno::Sequence< ::sal_Int8 >& aData ) +{ + std::unique_lock aGuard( m_aMutex ); + + if ( m_bBroken ) + throw uno::RuntimeException(); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + if (m_AESGCMIV.getLength()) + { + if (SAL_MAX_INT32 - nAESGCMIVSize - nAESGCMTagSize <= static_cast<size_t>(m_aLastBlock.getLength()) + static_cast<size_t>(aData.getLength())) + { + m_bBroken = true; + throw uno::RuntimeException("overflow"); + } + m_aLastBlock.realloc(m_aLastBlock.getLength() + aData.getLength()); + memcpy(m_aLastBlock.getArray() + m_aLastBlock.getLength() - aData.getLength(), aData.getConstArray(), aData.getLength()); + return {}; + } + + uno::Sequence< sal_Int8 > aToConvert; + if ( aData.hasElements() ) + { + sal_Int32 nOldLastBlockLen = m_aLastBlock.getLength(); + + sal_Int32 nAvailableData = nOldLastBlockLen + aData.getLength(); + sal_Int32 nToConvertLen; + if ( m_bEncryption || !m_bW3CPadding ) + { + assert(nOldLastBlockLen < m_nBlockSize); + if ( nAvailableData % m_nBlockSize == 0 ) + nToConvertLen = nAvailableData; + else if ( nAvailableData < m_nBlockSize ) + nToConvertLen = 0; + else + nToConvertLen = nAvailableData - nAvailableData % m_nBlockSize; + } + else + { + assert(nOldLastBlockLen < m_nBlockSize * 2); + // decryption with W3C padding needs at least one block for finalizing + if ( nAvailableData < m_nBlockSize * 2 ) + nToConvertLen = 0; + else + nToConvertLen = nAvailableData - nAvailableData % m_nBlockSize - m_nBlockSize; + } + + aToConvert.realloc( nToConvertLen ); + if ( nToConvertLen == 0 ) + { + m_aLastBlock.realloc( nOldLastBlockLen + aData.getLength() ); + memcpy( m_aLastBlock.getArray() + nOldLastBlockLen, aData.getConstArray(), aData.getLength() ); + // aToConvert stays empty + } + else if ( nToConvertLen < nOldLastBlockLen ) + { + memcpy( aToConvert.getArray(), m_aLastBlock.getConstArray(), nToConvertLen ); + memcpy( m_aLastBlock.getArray(), m_aLastBlock.getConstArray() + nToConvertLen, nOldLastBlockLen - nToConvertLen ); + m_aLastBlock.realloc( nOldLastBlockLen - nToConvertLen + aData.getLength() ); + memcpy( m_aLastBlock.getArray() + nOldLastBlockLen - nToConvertLen, aData.getConstArray(), aData.getLength() ); + } + else + { + memcpy( aToConvert.getArray(), m_aLastBlock.getConstArray(), nOldLastBlockLen ); + if ( nToConvertLen > nOldLastBlockLen ) + memcpy( aToConvert.getArray() + nOldLastBlockLen, aData.getConstArray(), nToConvertLen - nOldLastBlockLen ); + m_aLastBlock.realloc( nAvailableData - nToConvertLen ); + memcpy( m_aLastBlock.getArray(), aData.getConstArray() + nToConvertLen - nOldLastBlockLen, nAvailableData - nToConvertLen ); + } + } + + uno::Sequence< sal_Int8 > aResult; + assert(aToConvert.getLength() % m_nBlockSize == 0); + if ( aToConvert.hasElements() ) + { + int nResultLen = 0; + aResult.realloc( aToConvert.getLength() + m_nBlockSize ); + if ( PK11_CipherOp( m_pContext, reinterpret_cast< unsigned char* >( aResult.getArray() ), &nResultLen, aResult.getLength(), reinterpret_cast< const unsigned char* >( aToConvert.getConstArray() ), aToConvert.getLength() ) != SECSuccess ) + { + m_bBroken = true; + Dispose(); + throw uno::RuntimeException("PK11_CipherOp failed"); + } + + m_nConverted += aToConvert.getLength(); + aResult.realloc( nResultLen ); + } + + return aResult; +} + +uno::Sequence< ::sal_Int8 > SAL_CALL OCipherContext::finalizeCipherContextAndDispose() +{ + std::unique_lock aGuard( m_aMutex ); + + if ( m_bBroken ) + throw uno::RuntimeException(); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + if (m_AESGCMIV.getLength()) + { + uno::Sequence<sal_Int8> aResult; + unsigned outLen; + if (m_bEncryption) + { + assert(sal::static_int_cast<size_t>(m_aLastBlock.getLength()) <= SAL_MAX_INT32 - nAESGCMIVSize - nAESGCMTagSize); + // add space for IV and tag + aResult.realloc(m_aLastBlock.getLength() + nAESGCMIVSize + nAESGCMTagSize); + // W3C xmlenc-core1 requires the IV preceding the ciphertext, + // but NSS doesn't do it, so copy it manually + memcpy(aResult.getArray(), m_AESGCMIV.getConstArray(), nAESGCMIVSize); + if (PK11_Encrypt(m_pSymKey, CKM_AES_GCM, m_pSecParam, + reinterpret_cast<unsigned char*>(aResult.getArray() + nAESGCMIVSize), + &outLen, aResult.getLength() - nAESGCMIVSize, + reinterpret_cast<unsigned char const*>(m_aLastBlock.getConstArray()), + m_aLastBlock.getLength()) != SECSuccess) + { + m_bBroken = true; + Dispose(); + throw uno::RuntimeException("PK11_Encrypt failed"); + } + assert(outLen == sal::static_int_cast<unsigned>(aResult.getLength() - nAESGCMIVSize)); + } + else if (nAESGCMIVSize + nAESGCMTagSize < sal::static_int_cast<size_t>(m_aLastBlock.getLength())) + { + if (0 != memcmp(m_AESGCMIV.getConstArray(), m_aLastBlock.getConstArray(), nAESGCMIVSize)) + { + m_bBroken = true; + Dispose(); + throw uno::RuntimeException("inconsistent IV"); + } + aResult.realloc(m_aLastBlock.getLength() - nAESGCMIVSize - nAESGCMTagSize); + if (PK11_Decrypt(m_pSymKey, CKM_AES_GCM, m_pSecParam, + reinterpret_cast<unsigned char*>(aResult.getArray()), + &outLen, aResult.getLength(), + reinterpret_cast<unsigned char const*>(m_aLastBlock.getConstArray() + nAESGCMIVSize), + m_aLastBlock.getLength() - nAESGCMIVSize) != SECSuccess) + { + m_bBroken = true; + Dispose(); + throw uno::RuntimeException("PK11_Decrypt failed"); + } + assert(outLen == sal::static_int_cast<unsigned>(aResult.getLength())); + } + else + { + m_bBroken = true; + Dispose(); + throw uno::RuntimeException("incorrect size of input"); + } + Dispose(); + return aResult; + } + + assert(m_nBlockSize <= SAL_MAX_INT8); + assert(m_nConverted % m_nBlockSize == 0); // whole blocks are converted + sal_Int32 nSizeForPadding = ( m_nConverted + m_aLastBlock.getLength() ) % m_nBlockSize; + + // if it is decryption, the amount of data should be rounded to the block size even in case of padding + if ( ( !m_bPadding || !m_bEncryption ) && nSizeForPadding ) + throw uno::RuntimeException("The data should contain complete blocks only." ); + + if ( m_bW3CPadding && m_bEncryption ) + { + // in this case the last block should be smaller than standard block + // it will be increased with the padding + assert(m_aLastBlock.getLength() < m_nBlockSize); + + // W3CPadding handling for encryption + sal_Int32 nPaddingSize = m_nBlockSize - nSizeForPadding; + sal_Int32 nOldLastBlockLen = m_aLastBlock.getLength(); + m_aLastBlock.realloc( nOldLastBlockLen + nPaddingSize ); + auto pLastBlock = m_aLastBlock.getArray(); + + if ( nPaddingSize > 1 ) + { + rtlRandomPool aRandomPool = rtl_random_createPool(); + rtl_random_getBytes( aRandomPool, pLastBlock + nOldLastBlockLen, nPaddingSize - 1 ); + rtl_random_destroyPool ( aRandomPool ); + } + pLastBlock[m_aLastBlock.getLength() - 1] = static_cast< sal_Int8 >( nPaddingSize ); + } + + // finally should the last block be smaller than two standard blocks + assert(m_aLastBlock.getLength() < m_nBlockSize * 2); + + uno::Sequence< sal_Int8 > aResult; + if ( m_aLastBlock.hasElements() ) + { + int nPrefResLen = 0; + aResult.realloc( m_aLastBlock.getLength() + m_nBlockSize ); + if ( PK11_CipherOp( m_pContext, reinterpret_cast< unsigned char* >( aResult.getArray() ), &nPrefResLen, aResult.getLength(), reinterpret_cast< const unsigned char* >( m_aLastBlock.getConstArray() ), m_aLastBlock.getLength() ) != SECSuccess ) + { + m_bBroken = true; + Dispose(); + throw uno::RuntimeException("PK11_CipherOp failed"); + } + + aResult.realloc( nPrefResLen ); + m_aLastBlock.realloc( 0 ); + } + + sal_Int32 nPrefixLen = aResult.getLength(); + aResult.realloc( nPrefixLen + m_nBlockSize * 2 ); + unsigned nFinalLen = 0; + if ( PK11_DigestFinal( m_pContext, reinterpret_cast< unsigned char* >( aResult.getArray() + nPrefixLen ), &nFinalLen, aResult.getLength() - nPrefixLen ) != SECSuccess ) + { + m_bBroken = true; + Dispose(); + throw uno::RuntimeException("PK11_DigestFinal failed"); + } + + aResult.realloc( nPrefixLen + nFinalLen ); + + if ( m_bW3CPadding && !m_bEncryption ) + { + // W3CPadding handling for decryption + // aResult should have enough data, except if the input was completely empty + + // see https://www.w3.org/TR/xmlenc-core1/#sec-Alg-Block + if (aResult.getLength() < m_nBlockSize + || aResult[aResult.getLength()-1] <= 0 + || m_nBlockSize < aResult[aResult.getLength()-1]) + { + m_bBroken = true; + Dispose(); + throw uno::RuntimeException("incorrect size of padding"); + } + + aResult.realloc(aResult.getLength() - aResult[aResult.getLength()-1]); + } + + Dispose(); + + return aResult; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/ciphercontext.hxx b/xmlsecurity/source/xmlsec/nss/ciphercontext.hxx new file mode 100644 index 0000000000..d2c002ec46 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/ciphercontext.hxx @@ -0,0 +1,81 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <com/sun/star/xml/crypto/XCipherContext.hpp> + +#include <cppuhelper/implbase.hxx> +#include <mutex> +#include <seccomon.h> +#include <secmodt.h> + +class OCipherContext : public cppu::WeakImplHelper< css::xml::crypto::XCipherContext > +{ +private: + std::mutex m_aMutex; + + PK11SlotInfo* m_pSlot; + PK11SymKey* m_pSymKey; + SECItem* m_pSecParam; + PK11Context* m_pContext; + + sal_Int32 m_nBlockSize; + css::uno::Sequence< sal_Int8 > m_aLastBlock; + css::uno::Sequence<sal_Int8> m_AESGCMIV; + + bool m_bEncryption; + bool m_bPadding; + bool m_bW3CPadding; + sal_Int64 m_nConverted; + + bool m_bDisposed; + bool m_bBroken; + + void Dispose(); + + OCipherContext() + : m_pSlot( nullptr ) + , m_pSymKey( nullptr ) + , m_pSecParam( nullptr ) + , m_pContext( nullptr ) + , m_nBlockSize( 0 ) + , m_bEncryption( false ) + , m_bPadding( false ) + , m_bW3CPadding( false ) + , m_nConverted( 0 ) + , m_bDisposed( false ) + , m_bBroken( false ) + {} + +public: + + virtual ~OCipherContext() override + { + Dispose(); + } + + static css::uno::Reference< css::xml::crypto::XCipherContext > Create( CK_MECHANISM_TYPE nNSSCipherID, const css::uno::Sequence< ::sal_Int8 >& aKey, const css::uno::Sequence< ::sal_Int8 >& aInitializationVector, bool bEncryption, bool bW3CPadding ); + + // XCipherContext + virtual css::uno::Sequence< ::sal_Int8 > SAL_CALL convertWithCipherContext( const css::uno::Sequence< ::sal_Int8 >& aData ) override; + virtual css::uno::Sequence< ::sal_Int8 > SAL_CALL finalizeCipherContextAndDispose( ) override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/digestcontext.cxx b/xmlsecurity/source/xmlsec/nss/digestcontext.cxx new file mode 100644 index 0000000000..63c128e702 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/digestcontext.cxx @@ -0,0 +1,94 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include <com/sun/star/lang/DisposedException.hpp> + +#include <pk11pub.h> +#include "digestcontext.hxx" + +using namespace ::com::sun::star; + +ODigestContext::~ODigestContext() +{ + if ( m_pContext ) + { + PK11_DestroyContext( m_pContext, PR_TRUE ); + m_pContext = nullptr; + } +} + +void SAL_CALL ODigestContext::updateDigest( const uno::Sequence< ::sal_Int8 >& aData ) +{ + std::scoped_lock aGuard( m_aMutex ); + + if ( m_bBroken ) + throw uno::RuntimeException(); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + if (m_b1KData && m_nDigested >= 1024) + return; + + uno::Sequence< sal_Int8 > aToDigest = aData; + if ( m_b1KData && m_nDigested + aData.getLength() > 1024 ) + aToDigest.realloc( 1024 - m_nDigested ); + + if ( PK11_DigestOp( m_pContext, reinterpret_cast< const unsigned char* >( aToDigest.getConstArray() ), aToDigest.getLength() ) != SECSuccess ) + { + PK11_DestroyContext( m_pContext, PR_TRUE ); + m_pContext = nullptr; + m_bBroken = true; + throw uno::RuntimeException(); + } + + m_nDigested += aToDigest.getLength(); +} + +uno::Sequence< ::sal_Int8 > SAL_CALL ODigestContext::finalizeDigestAndDispose() +{ + std::scoped_lock aGuard( m_aMutex ); + + if ( m_bBroken ) + throw uno::RuntimeException(); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + uno::Sequence< sal_Int8 > aResult( m_nDigestLength ); + unsigned int nResultLen = 0; + if ( PK11_DigestFinal( m_pContext, reinterpret_cast< unsigned char* >( aResult.getArray() ), &nResultLen, aResult.getLength() ) != SECSuccess ) + { + PK11_DestroyContext( m_pContext, PR_TRUE ); + m_pContext = nullptr; + m_bBroken = true; + throw uno::RuntimeException(); + } + + PK11_DestroyContext( m_pContext, PR_TRUE ); + m_pContext = nullptr; + m_bDisposed = true; + + aResult.realloc( nResultLen ); + return aResult; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/digestcontext.hxx b/xmlsecurity/source/xmlsec/nss/digestcontext.hxx new file mode 100644 index 0000000000..72e1864851 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/digestcontext.hxx @@ -0,0 +1,59 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <com/sun/star/xml/crypto/XDigestContext.hpp> + +#include <cppuhelper/implbase.hxx> +#include <mutex> +#include <secmodt.h> + +class ODigestContext : public cppu::WeakImplHelper< css::xml::crypto::XDigestContext > +{ +private: + std::mutex m_aMutex; + + PK11Context* m_pContext; + sal_Int32 const m_nDigestLength; + bool const m_b1KData; + sal_Int32 m_nDigested; + + bool m_bDisposed; + bool m_bBroken; + +public: + ODigestContext( PK11Context* pContext, sal_Int32 nDigestLength, bool b1KData ) + : m_pContext( pContext ) + , m_nDigestLength( nDigestLength ) + , m_b1KData( b1KData ) + , m_nDigested( 0 ) + , m_bDisposed( false ) + , m_bBroken( false ) + {} + + virtual ~ODigestContext() override; + + + // XDigestContext + virtual void SAL_CALL updateDigest( const css::uno::Sequence< ::sal_Int8 >& aData ) override; + virtual css::uno::Sequence< ::sal_Int8 > SAL_CALL finalizeDigestAndDispose() override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/nssinitializer.cxx b/xmlsecurity/source/xmlsec/nss/nssinitializer.cxx new file mode 100644 index 0000000000..bf74fa04ce --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/nssinitializer.cxx @@ -0,0 +1,647 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <com/sun/star/mozilla/XMozillaBootstrap.hpp> +#include <com/sun/star/xml/crypto/DigestID.hpp> +#include <com/sun/star/xml/crypto/CipherID.hpp> +#include <com/sun/star/xml/crypto/NSSInitializer.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <cppuhelper/supportsservice.hxx> +#include <officecfg/Office/Common.hxx> +#include <sal/types.h> +#include <rtl/bootstrap.hxx> +#include <rtl/string.hxx> +#include <osl/file.hxx> +#include <osl/thread.h> +#include <sal/log.hxx> +#include <comphelper/diagnose_ex.hxx> +#include <unotools/tempfile.hxx> +#include <comphelper/singletonref.hxx> +#include <comphelper/sequence.hxx> + +#include <nss/nssinitializer.hxx> + +#include "digestcontext.hxx" +#include "ciphercontext.hxx" + +#include <cstddef> +#include <memory> +#include <utility> +#include <vector> + +#include <nss.h> +#include <pk11pub.h> +#include <secmod.h> +#include <prerror.h> +#include <prinit.h> + +namespace cssu = css::uno; +namespace cssl = css::lang; + +using namespace com::sun::star; + +#define ROOT_CERTS "Root Certs for OpenOffice.org" + +extern "C" { + +static void nsscrypto_finalize(); + +} + +namespace +{ + +class InitNSSPrivate +{ +private: + std::optional<utl::TempFileNamed> m_oTempFileDatabaseDirectory; + +public: + OUString getTempDatabasePath() + { + if (!m_oTempFileDatabaseDirectory) + { + m_oTempFileDatabaseDirectory.emplace(nullptr, true); + m_oTempFileDatabaseDirectory->EnableKillingFile(); + } + return m_oTempFileDatabaseDirectory->GetFileName(); + } + + void reset() + { + if (m_oTempFileDatabaseDirectory) + { + m_oTempFileDatabaseDirectory.reset(); + } + } +}; + +comphelper::SingletonRef<InitNSSPrivate>* getInitNSSPrivate() +{ + static comphelper::SingletonRef<InitNSSPrivate> aInitNSSPrivate; + return &aInitNSSPrivate; +} + +bool nsscrypto_initialize( const css::uno::Reference< css::uno::XComponentContext > &rxContext, bool & out_nss_init ); + +#ifdef XMLSEC_CRYPTO_NSS + +void deleteRootsModule() +{ + SECMODModule *RootsModule = nullptr; + SECMODModuleList *list = SECMOD_GetDefaultModuleList(); + SECMODListLock *lock = SECMOD_GetDefaultModuleListLock(); + SECMOD_GetReadLock(lock); + + while (!RootsModule && list) + { + SECMODModule *module = list->module; + + for (int i=0; i < module->slotCount; i++) + { + PK11SlotInfo *slot = module->slots[i]; + if (PK11_IsPresent(slot)) + { + if (PK11_HasRootCerts(slot)) + { + SAL_INFO("xmlsecurity.xmlsec", "The root certificates module \"" << module->commonName << "\" is already loaded: " << module->dllName); + + RootsModule = SECMOD_ReferenceModule(module); + break; + } + } + } + list = list->next; + } + SECMOD_ReleaseReadLock(lock); + + if (!RootsModule) + return; + + PRInt32 modType; + if (SECSuccess == SECMOD_DeleteModule(RootsModule->commonName, &modType)) + { + SAL_INFO("xmlsecurity.xmlsec", "Deleted module \"" << RootsModule->commonName << "\"."); + } + else + { + SAL_INFO("xmlsecurity.xmlsec", "Failed to delete \"" << RootsModule->commonName << "\": " << RootsModule->dllName); + } + SECMOD_DestroyModule(RootsModule); + RootsModule = nullptr; +} + +#endif + +bool lcl_pathExists(const OUString& sPath) +{ + if (sPath.isEmpty()) + return false; + + ::osl::DirectoryItem aPathItem; + OUString sURL; + osl::FileBase::getFileURLFromSystemPath(sPath, sURL); + if (::osl::FileBase::E_None == ::osl::DirectoryItem::get(sURL, aPathItem)) + { + ::osl::FileStatus aStatus = osl_FileStatus_Mask_Validate; + if (::osl::FileBase::E_None == aPathItem.getFileStatus(aStatus)) + return true; + } + + return false; +} + +} // namespace + +const OUString & ONSSInitializer::getMozillaCurrentProfile(const css::uno::Reference< css::uno::XComponentContext > &rxContext, bool bSetActive) +{ + if (m_bIsNSSinitialized) + return m_sNSSPath; + if (bSetActive) + m_bIsNSSinitialized = true; + + // first, try to get the profile from "MOZILLA_CERTIFICATE_FOLDER" + const char* pEnv = getenv("MOZILLA_CERTIFICATE_FOLDER"); + if (pEnv) + { + SAL_INFO( + "xmlsecurity.xmlsec", + "Using Mozilla profile from MOZILLA_CERTIFICATE_FOLDER=" << pEnv); + m_sNSSPath = OStringToOUString(pEnv, osl_getThreadTextEncoding()); + } + + // second, try to get saved user-preference + if (m_sNSSPath.isEmpty()) + { + try + { + OUString sUserSetCertPath = + officecfg::Office::Common::Security::Scripting::CertDir::get().value_or(OUString()); + + if (lcl_pathExists(sUserSetCertPath)) + { + SAL_INFO( + "xmlsecurity.xmlsec", + "Using Mozilla profile from /org.openoffice.Office.Common/" + "Security/Scripting/CertDir: " << sUserSetCertPath); + m_sNSSPath = sUserSetCertPath; + } + } + catch (const uno::Exception &) + { + TOOLS_WARN_EXCEPTION("xmlsecurity.xmlsec", "getMozillaCurrentProfile:"); + } + } + + // third, dig around to see if there's one default available + mozilla::MozillaProductType productTypes[3] = { + mozilla::MozillaProductType_Thunderbird, + mozilla::MozillaProductType_Firefox, + mozilla::MozillaProductType_Mozilla }; + + uno::Reference<uno::XInterface> xInstance = rxContext->getServiceManager()->createInstanceWithContext("com.sun.star.mozilla.MozillaBootstrap", rxContext); + OSL_ENSURE( xInstance.is(), "failed to create instance" ); + + uno::Reference<mozilla::XMozillaBootstrap> xMozillaBootstrap(xInstance,uno::UNO_QUERY); + OSL_ENSURE( xMozillaBootstrap.is(), "failed to create instance" ); + + if (xMozillaBootstrap.is()) + { + for (auto const productTypeIter : productTypes) + { + OUString profile = xMozillaBootstrap->getDefaultProfile(productTypeIter); + + if (!profile.isEmpty()) + { + OUString sProfilePath = xMozillaBootstrap->getProfilePath(productTypeIter, profile); + if (m_sNSSPath.isEmpty()) + { + SAL_INFO("xmlsecurity.xmlsec", "Using Mozilla profile " << sProfilePath); + m_sNSSPath = sProfilePath; + } + break; + } + } + } + + SAL_INFO_IF(m_sNSSPath.isEmpty(), "xmlsecurity.xmlsec", "No Mozilla profile found"); + return m_sNSSPath; +} + +css::uno::Sequence<css::xml::crypto::NSSProfile> SAL_CALL ONSSInitializer::getNSSProfiles() +{ + ONSSInitializer::getMozillaCurrentProfile(m_xContext); + + std::vector<xml::crypto::NSSProfile> aProfileList; + aProfileList.reserve(10); + + mozilla::MozillaProductType productTypes[3] = { + mozilla::MozillaProductType_Thunderbird, + mozilla::MozillaProductType_Firefox, + mozilla::MozillaProductType_Mozilla }; + + uno::Reference<uno::XInterface> xInstance = m_xContext->getServiceManager()->createInstanceWithContext("com.sun.star.mozilla.MozillaBootstrap", m_xContext); + OSL_ENSURE(xInstance.is(), "failed to create instance" ); + + uno::Reference<mozilla::XMozillaBootstrap> xMozillaBootstrap(xInstance,uno::UNO_QUERY); + + if (xMozillaBootstrap.is()) + { + for (auto const productTypeIter : productTypes) + { + uno::Sequence<OUString> aProductProfileList; + xMozillaBootstrap->getProfileList(productTypeIter, aProductProfileList); + for (const auto& sProfile : std::as_const(aProductProfileList)) + aProfileList.push_back({sProfile, xMozillaBootstrap->getProfilePath(productTypeIter, sProfile), productTypeIter}); + } + } + + OUString sUserSelect; + try + { + sUserSelect = officecfg::Office::Common::Security::Scripting::CertDir::get().value_or(OUString());; + if (!lcl_pathExists(sUserSelect)) + sUserSelect = OUString(); + } + catch (const uno::Exception &) + { + TOOLS_WARN_EXCEPTION("xmlsecurity.xmlsec", "getMozillaCurrentProfile:"); + } + aProfileList.push_back({"MANUAL", sUserSelect, mozilla::MozillaProductType_Default}); + + const char* pEnv = getenv("MOZILLA_CERTIFICATE_FOLDER"); + aProfileList.push_back({"MOZILLA_CERTIFICATE_FOLDER", + pEnv ? OStringToOUString(pEnv, osl_getThreadTextEncoding()) : OUString(), + mozilla::MozillaProductType_Default}); + + return comphelper::containerToSequence(aProfileList); +} + +bool ONSSInitializer::m_bIsNSSinitialized = false; +OUString ONSSInitializer::m_sNSSPath; + +OUString SAL_CALL ONSSInitializer::getNSSPath() +{ + ONSSInitializer::getMozillaCurrentProfile(m_xContext); + return m_sNSSPath; +}; + +sal_Bool SAL_CALL ONSSInitializer::getIsNSSinitialized() +{ + return m_bIsNSSinitialized; +} + +ONSSInitializer::ONSSInitializer(css::uno::Reference< css::uno::XComponentContext > xContext) + : m_xContext(std::move(xContext)) +{ +} + +ONSSInitializer::ONSSInitializer() +{ +} + +namespace +{ + +//Older versions of Firefox (FF), for example FF2, and Thunderbird (TB) 2 write +//the roots certificate module (libnssckbi.so), which they use, into the +//profile. This module will then already be loaded during NSS_Init (and the +//other init functions). This fails in two cases. First, FF3 was used to create +//the profile, or possibly used that profile before, and second the profile was +//used on a different platform. +// +//Then one needs to add the roots module oneself. This should be done with +//SECMOD_LoadUserModule rather than SECMOD_AddNewModule. The latter would write +//the location of the roots module to the profile, which makes FF2 and TB2 use +//it instead of their own module. +// +//When using SYSTEM_NSS then the libnss3.so lib is typically found in /usr/lib. +//This folder may, however, NOT contain the roots certificate module. That is, +//just providing the library name in SECMOD_LoadUserModule or +//SECMOD_AddNewModule will FAIL to load the mozilla unless the LD_LIBRARY_PATH +//contains an FF or TB installation. +//ATTENTION: DO NOT call this function directly instead use initNSS +//return true - whole initialization was successful +//param out_nss_init = true: at least the NSS initialization (NSS_InitReadWrite +//was successful and therefore NSS_Shutdown should be called when terminating. +bool nsscrypto_initialize(css::uno::Reference<css::uno::XComponentContext> const & rxContext, bool & out_nss_init) +{ + // this method must be called only once, no need for additional lock + OString sCertDir; + +#ifdef XMLSEC_CRYPTO_NSS + sCertDir = OUStringToOString(ONSSInitializer::getMozillaCurrentProfile(rxContext, true), osl_getThreadTextEncoding()); +#else + (void) rxContext; +#endif + SAL_INFO("xmlsecurity.xmlsec", "Using profile: " << sCertDir ); + + PR_Init( PR_USER_THREAD, PR_PRIORITY_NORMAL, 1 ) ; + + bool bSuccess = false; + // there might be no profile + if (!sCertDir.isEmpty()) + { + if (sCertDir.indexOf(':') == -1) //might be env var with explicit prefix + { + OUString sCertDirURL; + osl::FileBase::getFileURLFromSystemPath( + OStringToOUString(sCertDir, osl_getThreadTextEncoding()), + sCertDirURL); + osl::DirectoryItem item; + if (osl::FileBase::E_NOENT != osl::DirectoryItem::get(sCertDirURL + "/cert8.db", item) && + osl::FileBase::E_NOENT == osl::DirectoryItem::get(sCertDirURL + "/cert9.db", item)) + { + SAL_INFO("xmlsecurity.xmlsec", "nsscrypto_initialize: trying to avoid profile migration"); + sCertDir = "dbm:" + sCertDir; + } + } + if (NSS_InitReadWrite(sCertDir.getStr()) != SECSuccess) + { + SAL_INFO("xmlsecurity.xmlsec", "Initializing NSS with profile failed."); + int errlen = PR_GetErrorTextLength(); + if (errlen > 0) + { + std::unique_ptr<char[]> const error(new char[errlen + 1]); + PR_GetErrorText(error.get()); + SAL_INFO("xmlsecurity.xmlsec", error.get()); + } + } + else + { + bSuccess = true; + } + } + + if (!bSuccess) // Try to create a database in temp dir + { + SAL_INFO("xmlsecurity.xmlsec", "Initializing NSS with a temporary profile."); + OUString rString = (*getInitNSSPrivate())->getTempDatabasePath(); + + if (NSS_InitReadWrite(rString.toUtf8().getStr()) != SECSuccess) + { + SAL_INFO("xmlsecurity.xmlsec", "Initializing NSS with a temporary profile."); + int errlen = PR_GetErrorTextLength(); + if(errlen > 0) + { + std::unique_ptr<char[]> const error(new char[errlen + 1]); + PR_GetErrorText(error.get()); + SAL_INFO("xmlsecurity.xmlsec", error.get()); + } + return false; + } + } + + // Initialize and set empty password if needed + // note: it's possible that the first NSS_InitReadWrite() succeeds by + // creating a new DB; in this case it may also be necessary to call + // PK11_InitPin() + PK11SlotInfo* pSlot = PK11_GetInternalKeySlot(); + if (pSlot) + { + if (PK11_NeedUserInit(pSlot)) + PK11_InitPin(pSlot, nullptr, nullptr); + PK11_FreeSlot(pSlot); + } + + out_nss_init = true; + +#ifdef XMLSEC_CRYPTO_NSS + bool return_value = true; + +#if defined SYSTEM_NSS || defined IOS // The statically linked nss on iOS acts as a "system" nss in this regards + if (!SECMOD_HasRootCerts()) +#endif + { + deleteRootsModule(); + +#ifdef IOS // Use statically linked NSS + OUString rootModulePath("NSSCKBI"); + + if (true) +#else +#if defined SYSTEM_NSS || defined ANDROID + OUString rootModule("libnssckbi" SAL_DLLEXTENSION); +#else + OUString rootModule("${LO_LIB_DIR}/libnssckbi" SAL_DLLEXTENSION); +#endif + ::rtl::Bootstrap::expandMacros(rootModule); + + OUString rootModulePath; + if (::osl::File::E_None == ::osl::File::getSystemPathFromFileURL(rootModule, rootModulePath)) +#endif + { + OString ospath = OUStringToOString(rootModulePath, osl_getThreadTextEncoding()); + OString aStr = "name=\"" ROOT_CERTS "\" library=\"" + ospath + "\""; + + SECMODModule * RootsModule = + SECMOD_LoadUserModule( + const_cast<char*>(aStr.getStr()), + nullptr, // no parent + PR_FALSE); // do not recurse + + if (RootsModule) + { + + bool found = RootsModule->loaded; + + SECMOD_DestroyModule(RootsModule); + RootsModule = nullptr; + if (found) + SAL_INFO("xmlsecurity.xmlsec", "Added new root certificate module " ROOT_CERTS " contained in " << ospath); + else + { + SAL_INFO("xmlsecurity.xmlsec", "FAILED to load the new root certificate module " ROOT_CERTS "contained in " << ospath); + return_value = false; + } + } + else + { + SAL_INFO("xmlsecurity.xmlsec", "FAILED to add new root certificate module " ROOT_CERTS " contained in " << ospath); + return_value = false; + + } + } + else + { + SAL_INFO("xmlsecurity.xmlsec", "Adding new root certificate module failed."); + return_value = false; + } + } + + return return_value; +#else + return true; +#endif +} + +} // namespace + +// must be extern "C" because we pass the function pointer to atexit +extern "C" void nsscrypto_finalize() +{ + SECMODModule *RootsModule = SECMOD_FindModule(ROOT_CERTS); + + if (RootsModule) + { + + if (SECSuccess == SECMOD_UnloadUserModule(RootsModule)) + { + SAL_INFO("xmlsecurity.xmlsec", "Unloaded module \"" ROOT_CERTS "\"."); + } + else + { + SAL_INFO("xmlsecurity.xmlsec", "Failed unloading module \"" ROOT_CERTS "\"."); + } + SECMOD_DestroyModule(RootsModule); + } + else + { + SAL_INFO("xmlsecurity.xmlsec", "Unloading module \"" ROOT_CERTS "\" failed because it was not found."); + } + PK11_LogoutAll(); + (void)NSS_Shutdown(); + + (*getInitNSSPrivate())->reset(); +} + + +ONSSInitializer::~ONSSInitializer() +{ +} + +bool ONSSInitializer::initNSS( const css::uno::Reference< css::uno::XComponentContext > &rxContext ) +{ + static bool gbInitialized = [&rxContext]() + { + bool bNSSInit = false; + bool bInitialized = nsscrypto_initialize( rxContext, bNSSInit ); + if (bNSSInit) + atexit(nsscrypto_finalize); + return bInitialized; + }(); + return gbInitialized; +} + +css::uno::Reference< css::xml::crypto::XDigestContext > SAL_CALL ONSSInitializer::getDigestContext( ::sal_Int32 nDigestID, const css::uno::Sequence< css::beans::NamedValue >& aParams ) +{ + SECOidTag nNSSDigestID = SEC_OID_UNKNOWN; + sal_Int32 nDigestLength = 0; + bool b1KData = false; + if ( nDigestID == css::xml::crypto::DigestID::SHA256 + || nDigestID == css::xml::crypto::DigestID::SHA256_1K ) + { + nNSSDigestID = SEC_OID_SHA256; + nDigestLength = 32; + b1KData = ( nDigestID == css::xml::crypto::DigestID::SHA256_1K ); + } + else if ( nDigestID == css::xml::crypto::DigestID::SHA1 + || nDigestID == css::xml::crypto::DigestID::SHA1_1K ) + { + nNSSDigestID = SEC_OID_SHA1; + nDigestLength = 20; + b1KData = ( nDigestID == css::xml::crypto::DigestID::SHA1_1K ); + } + else if ( nDigestID == css::xml::crypto::DigestID::SHA512 + || nDigestID == css::xml::crypto::DigestID::SHA512_1K ) + { + nNSSDigestID = SEC_OID_SHA512; + nDigestLength = 64; + b1KData = ( nDigestID == css::xml::crypto::DigestID::SHA512_1K ); + } + else + throw css::lang::IllegalArgumentException("Unexpected digest requested.", css::uno::Reference< css::uno::XInterface >(), 1 ); + + if ( aParams.hasElements() ) + throw css::lang::IllegalArgumentException("Unexpected arguments provided for digest creation.", css::uno::Reference< css::uno::XInterface >(), 2 ); + + css::uno::Reference< css::xml::crypto::XDigestContext > xResult; + if( initNSS( m_xContext ) ) + { + PK11Context* pContext = PK11_CreateDigestContext( nNSSDigestID ); + if ( pContext && PK11_DigestBegin( pContext ) == SECSuccess ) + xResult = new ODigestContext( pContext, nDigestLength, b1KData ); + } + + return xResult; +} + +css::uno::Reference< css::xml::crypto::XCipherContext > SAL_CALL ONSSInitializer::getCipherContext( ::sal_Int32 nCipherID, const css::uno::Sequence< ::sal_Int8 >& aKey, const css::uno::Sequence< ::sal_Int8 >& aInitializationVector, sal_Bool bEncryption, const css::uno::Sequence< css::beans::NamedValue >& aParams ) +{ + CK_MECHANISM_TYPE nNSSCipherID = 0; + bool bW3CPadding = false; + switch (nCipherID) + { + case css::xml::crypto::CipherID::AES_CBC_W3C_PADDING: + nNSSCipherID = CKM_AES_CBC; + bW3CPadding = true; + break; + case css::xml::crypto::CipherID::AES_GCM_W3C: + nNSSCipherID = CKM_AES_GCM; + break; + default: + throw css::lang::IllegalArgumentException("Unexpected cipher requested.", css::uno::Reference< css::uno::XInterface >(), 1); + } + + if ( aKey.getLength() != 16 && aKey.getLength() != 24 && aKey.getLength() != 32 ) + throw css::lang::IllegalArgumentException("Unexpected key length.", css::uno::Reference< css::uno::XInterface >(), 2 ); + + if ( aParams.hasElements() ) + throw css::lang::IllegalArgumentException("Unexpected arguments provided for cipher creation.", css::uno::Reference< css::uno::XInterface >(), 5 ); + + css::uno::Reference< css::xml::crypto::XCipherContext > xResult; + if( initNSS( m_xContext ) ) + { + if ( aInitializationVector.getLength() != PK11_GetIVLength( nNSSCipherID ) ) + throw css::lang::IllegalArgumentException("Unexpected length of initialization vector.", css::uno::Reference< css::uno::XInterface >(), 3 ); + + xResult = OCipherContext::Create( nNSSCipherID, aKey, aInitializationVector, bEncryption, bW3CPadding ); + assert(xResult.is()); + } + + return xResult; +} + +/* XServiceInfo */ +OUString SAL_CALL ONSSInitializer::getImplementationName() +{ + return "com.sun.star.xml.crypto.NSSInitializer"; +} + +sal_Bool SAL_CALL ONSSInitializer::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +cssu::Sequence< OUString > SAL_CALL ONSSInitializer::getSupportedServiceNames( ) +{ + return { NSS_SERVICE_NAME }; +} + +#ifndef XMLSEC_CRYPTO_NSS +extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface* +com_sun_star_xml_crypto_NSSInitializer_get_implementation( + uno::XComponentContext* pCtx, uno::Sequence<uno::Any> const& /*rSeq*/) +{ + return cppu::acquire(new ONSSInitializer(pCtx)); +} +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/nssinitializer.hxx b/xmlsecurity/source/xmlsec/nss/nssinitializer.hxx new file mode 100644 index 0000000000..c461dd5c97 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/nssinitializer.hxx @@ -0,0 +1,68 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <com/sun/star/xml/crypto/XNSSInitializer.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> + +#include <cppuhelper/implbase.hxx> + +namespace com::sun::star::uno { class XComponentContext; } + +inline constexpr OUString NSS_SERVICE_NAME = u"com.sun.star.xml.crypto.NSSInitializer"_ustr; + +class ONSSInitializer : public cppu::WeakImplHelper +< + css::xml::crypto::XNSSInitializer, + css::lang::XServiceInfo +> +{ +protected: + css::uno::Reference< css::uno::XComponentContext > m_xContext; + static OUString m_sNSSPath; + static bool m_bIsNSSinitialized; + + ONSSInitializer(); + +public: + explicit ONSSInitializer(css::uno::Reference<css::uno::XComponentContext> xContext); + virtual ~ONSSInitializer() override; + + static bool initNSS( const css::uno::Reference< css::uno::XComponentContext > &rxContext ); + static const OUString & getMozillaCurrentProfile(const css::uno::Reference< css::uno::XComponentContext > &rxContext, bool bSetActive = false); + + /* XNSSInitializer */ + virtual OUString SAL_CALL getNSSPath() override; + virtual sal_Bool SAL_CALL getIsNSSinitialized() override; + virtual css::uno::Sequence<css::xml::crypto::NSSProfile> SAL_CALL getNSSProfiles() override; + + /* XDigestContextSupplier */ + virtual css::uno::Reference< css::xml::crypto::XDigestContext > SAL_CALL getDigestContext( ::sal_Int32 nDigestID, const css::uno::Sequence< css::beans::NamedValue >& aParams ) override; + + /* XCipherContextSupplier */ + virtual css::uno::Reference< css::xml::crypto::XCipherContext > SAL_CALL getCipherContext( ::sal_Int32 nCipherID, const css::uno::Sequence< ::sal_Int8 >& aKey, const css::uno::Sequence< ::sal_Int8 >& aInitializationVector, sal_Bool bEncryption, const css::uno::Sequence< css::beans::NamedValue >& aParams ) override; + + /* XServiceInfo */ + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/nssrenam.h b/xmlsecurity/source/xmlsec/nss/nssrenam.h new file mode 100644 index 0000000000..47280408b7 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/nssrenam.h @@ -0,0 +1,41 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 2001 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +#pragma once + +#define CERT_NewTempCertificate __CERT_NewTempCertificate +#define PK11_GetKeyData __PK11_GetKeyData +#define CERT_DecodeDERCertificate __CERT_DecodeDERCertificate + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/sanextension_nssimpl.cxx b/xmlsecurity/source/xmlsec/nss/sanextension_nssimpl.cxx new file mode 100644 index 0000000000..1395cb2e8a --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/sanextension_nssimpl.cxx @@ -0,0 +1,164 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> +#include <rtl/ustring.hxx> +#include <com/sun/star/security/ExtAltNameType.hpp> +#include <com/sun/star/security/CertAltNameEntry.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <comphelper/sequence.hxx> +#include <seccomon.h> +#include <cert.h> +#include <certt.h> + +#include "sanextension_nssimpl.hxx" + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno ; +using namespace ::com::sun::star::security ; + +namespace { + // Helper functions from nss/lib/certdb/genname.c + int GetNamesLength(CERTGeneralName *names) + { + int length = 0; + CERTGeneralName *first; + + first = names; + if (names != nullptr) { + do { + length++; + names = CERT_GetNextGeneralName(names); + } while (names != first); + } + return length; + } + +} + +//Methods from XSanExtension +css::uno::Sequence< css::security::CertAltNameEntry > SAL_CALL SanExtensionImpl::getAlternativeNames() +{ + if (m_Entries.empty()) + { + SECItem item; + + item.type = siDERCertBuffer; + item.data = reinterpret_cast<unsigned char*>(m_Extn.m_xExtnValue.getArray()); + item.len = m_Extn.m_xExtnValue.getLength(); + + PRArenaPool *arena; + CERTGeneralName *nameList; + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + + if (!arena) + return css::uno::Sequence<css::security::CertAltNameEntry>(); + + nameList = CERT_DecodeAltNameExtension(arena, &item); + + CERTGeneralName* current = nameList; + + int size = GetNamesLength(nameList); + m_Entries.resize(size); + for(int i = 0; i < size; ++i){ + switch (current->type) { + case certOtherName: { + m_Entries[i].Type = ExtAltNameType_OTHER_NAME; + css::beans::PropertyValue otherNameProp; + otherNameProp.Name = OUString::createFromAscii(CERT_GetOidString(¤t->name.OthName.oid)); + + Sequence< sal_Int8 > otherName( current->name.OthName.name.len ) ; + auto otherNameRange = asNonConstRange(otherName); + for( unsigned int r = 0; r < current->name.OthName.name.len ; r ++ ) + otherNameRange[r] = *( current->name.OthName.name.data + r ) ; + + otherNameProp.Value <<= otherName; + + m_Entries[i].Value <<= otherNameProp; + break; + } + case certRFC822Name: + m_Entries[i].Type = ExtAltNameType_RFC822_NAME; + m_Entries[i].Value <<= OUString(reinterpret_cast<char*>(current->name.other.data), current->name.other.len, RTL_TEXTENCODING_ASCII_US); + break; + case certDNSName: + m_Entries[i].Type = ExtAltNameType_DNS_NAME; + m_Entries[i].Value <<= OUString(reinterpret_cast<char*>(current->name.other.data), current->name.other.len, RTL_TEXTENCODING_ASCII_US); + break; + case certX400Address: { + // unsupported + m_Entries[i].Type = ExtAltNameType_X400_ADDRESS; + break; + } + case certDirectoryName: { + // unsupported + m_Entries[i].Type = ExtAltNameType_DIRECTORY_NAME; + break; + } + case certEDIPartyName: { + // unsupported + m_Entries[i].Type = ExtAltNameType_EDI_PARTY_NAME; + break; + } + case certURI: + m_Entries[i].Type = ExtAltNameType_URL; + m_Entries[i].Value <<= OUString(reinterpret_cast<char*>(current->name.other.data), current->name.other.len, RTL_TEXTENCODING_ASCII_US); + break; + case certIPAddress: { + m_Entries[i].Type = ExtAltNameType_IP_ADDRESS; + + Sequence< sal_Int8 > ipAddress( current->name.other.len ) ; + auto ipAddressRange = asNonConstRange(ipAddress); + for( unsigned int r = 0; r < current->name.other.len ; r ++ ) + ipAddressRange[r] = *( current->name.other.data + r ) ; + + m_Entries[i].Value <<= ipAddress; + break; + } + case certRegisterID: + m_Entries[i].Type = ExtAltNameType_REGISTERED_ID; + + + OString nssOid(CERT_GetOidString(¤t->name.other)); + OString unoOid = removeOIDFromString(nssOid); + m_Entries[i].Value <<= OStringToOUString( unoOid, RTL_TEXTENCODING_ASCII_US ); + break; + } + current = CERT_GetNextGeneralName(current); + } + + PORT_FreeArena(arena, PR_FALSE); + } + + return comphelper::containerToSequence<css::security::CertAltNameEntry>(m_Entries); +} + +OString SanExtensionImpl::removeOIDFromString( const OString &oidString) +{ + OString objID; + constexpr std::string_view oid("OID."); + if (oidString.match(oid)) + objID = oidString.copy(oid.size()); + else + objID = oidString; + return objID; + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/sanextension_nssimpl.hxx b/xmlsecurity/source/xmlsec/nss/sanextension_nssimpl.hxx new file mode 100644 index 0000000000..3716d414e5 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/sanextension_nssimpl.hxx @@ -0,0 +1,65 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <sal/config.h> +#include <cppuhelper/implbase.hxx> +#include <com/sun/star/security/XSanExtension.hpp> +#include <com/sun/star/security/CertAltNameEntry.hpp> +#include <certificateextension_certextn.hxx> +#include <vector> + +class SanExtensionImpl : public ::cppu::WeakImplHelper< + css::security::XSanExtension > +{ + private: + CertificateExtension_CertExtn m_Extn; + std::vector<css::security::CertAltNameEntry> m_Entries; + + static OString removeOIDFromString( const OString &oid); + + public: + //Methods from XCertificateExtension + virtual sal_Bool SAL_CALL isCritical() override + { + return m_Extn.m_critical; + } + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getExtensionId() override + { + return m_Extn.m_xExtnId; + } + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getExtensionValue() override + { + return m_Extn.m_xExtnValue; + } + + void setCertExtn(unsigned char const * value, unsigned int vlen, unsigned char const * id, unsigned int idlen, bool critical) + { + m_Extn.setCertExtn(value, vlen, id, idlen, critical); + } + + //Methods from XSanExtension + + virtual css::uno::Sequence< css::security::CertAltNameEntry > SAL_CALL getAlternativeNames() override ; +} ; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/secerror.cxx b/xmlsecurity/source/xmlsec/nss/secerror.cxx new file mode 100644 index 0000000000..b7e623ce00 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/secerror.cxx @@ -0,0 +1,152 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include <secerr.h> +#include "secerror.hxx" +#include <nss.h> +#include <certt.h> +#include <sal/log.hxx> + +namespace { + +struct ErrDesc { + PRErrorCode const errNum; + const char * errString; +}; + +} + +const ErrDesc allDesc[] = { + +#include "certerrors.h" + +}; + + +/* Returns a UTF-8 encoded constant error string for "errNum". + * Returns NULL of errNum is unknown. + */ +const char * +getCertError(PRErrorCode errNum) +{ + for (const ErrDesc& i : allDesc) + { + if (i.errNum == errNum) + return i.errString; + } + + return ""; +} + +void +printChainFailure(CERTVerifyLog *log) +{ + unsigned int depth = static_cast<unsigned int>(-1); + CERTVerifyLogNode *node = nullptr; + + if (log->count > 0) + { + SAL_INFO("xmlsecurity.xmlsec", "Bad certification path:"); + unsigned long errorFlags = 0; + for (node = log->head; node; node = node->next) + { + if (depth != node->depth) + { + depth = node->depth; + SAL_INFO("xmlsecurity.xmlsec", "Certificate: " << depth << + node->cert->subjectName << ": " << + (depth ? "[Certificate Authority]": "")); + } + SAL_INFO("xmlsecurity.xmlsec", " ERROR " << node->error << ": " << + getCertError(node->error)); + const char * specificError = nullptr; + const char * issuer = nullptr; + switch (node->error) + { + case SEC_ERROR_INADEQUATE_KEY_USAGE: + errorFlags = reinterpret_cast<unsigned long>(node->arg); + switch (errorFlags) + { + case KU_DIGITAL_SIGNATURE: + specificError = "Certificate cannot sign."; + break; + case KU_KEY_ENCIPHERMENT: + specificError = "Certificate cannot encrypt."; + break; + case KU_KEY_CERT_SIGN: + specificError = "Certificate cannot sign other certs."; + break; + default: + specificError = "[unknown usage]."; + break; + } + break; + case SEC_ERROR_INADEQUATE_CERT_TYPE: + errorFlags = reinterpret_cast<unsigned long>(node->arg); + switch (errorFlags) + { + case NS_CERT_TYPE_SSL_CLIENT: + case NS_CERT_TYPE_SSL_SERVER: + specificError = "Certificate cannot be used for SSL."; + break; + case NS_CERT_TYPE_SSL_CA: + specificError = "Certificate cannot be used as an SSL CA."; + break; + case NS_CERT_TYPE_EMAIL: + specificError = "Certificate cannot be used for SMIME."; + break; + case NS_CERT_TYPE_EMAIL_CA: + specificError = "Certificate cannot be used as an SMIME CA."; + break; + case NS_CERT_TYPE_OBJECT_SIGNING: + specificError = "Certificate cannot be used for object signing."; + break; + case NS_CERT_TYPE_OBJECT_SIGNING_CA: + specificError = "Certificate cannot be used as an object signing CA."; + break; + default: + specificError = "[unknown usage]."; + break; + } + break; + case SEC_ERROR_UNKNOWN_ISSUER: + specificError = "Unknown issuer:"; + issuer = node->cert->issuerName; + break; + case SEC_ERROR_UNTRUSTED_ISSUER: + specificError = "Untrusted issuer:"; + issuer = node->cert->issuerName; + break; + case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE: + specificError = "Expired issuer certificate:"; + issuer = node->cert->issuerName; + break; + default: + break; + } + if (specificError) + SAL_INFO("xmlsecurity.xmlsec", specificError); + if (issuer) + SAL_INFO("xmlsecurity.xmlsec", issuer); + } + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/secerror.hxx b/xmlsecurity/source/xmlsec/nss/secerror.hxx new file mode 100644 index 0000000000..bd59078262 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/secerror.hxx @@ -0,0 +1,31 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <sal/config.h> + +#include <certt.h> +#include <prerror.h> + +const char* getCertError(PRErrorCode errNum); + +void printChainFailure(CERTVerifyLog* log); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.cxx b/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.cxx new file mode 100644 index 0000000000..2ab5b011e2 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.cxx @@ -0,0 +1,878 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "nssrenam.h" +#include <cert.h> +#include <secerr.h> +#include <ocsp.h> + +#include <sal/config.h> +#include <sal/macros.h> +#include <osl/diagnose.h> +#include "securityenvironment_nssimpl.hxx" +#include <cppuhelper/supportsservice.hxx> +#include <comphelper/servicehelper.hxx> + +#include <xmlsec-wrapper.h> + +#include <rtl/ustrbuf.hxx> +#include <comphelper/processfactory.hxx> +#include <comphelper/docpasswordrequest.hxx> +#include <sal/log.hxx> +#include <com/sun/star/task/InteractionHandler.hpp> +#include <vector> +#include <memory> +#include <osl/thread.h> +#include <comphelper/sequence.hxx> + +#include "x509certificate_nssimpl.hxx" +#include "secerror.hxx" +#include <prerror.h> +#include <keyhi.h> + +// added for password exception +#include <com/sun/star/security/NoPasswordException.hpp> +#include <com/sun/star/security/CertificateCharacters.hpp> +#include <com/sun/star/security/CertificateValidity.hpp> + +namespace csss = ::com::sun::star::security; +using namespace ::com::sun::star::security; +using namespace com::sun::star; +using namespace ::com::sun::star::uno ; +using namespace ::com::sun::star::lang ; + +using ::com::sun::star::security::XCertificate ; + +namespace std +{ +template <> struct default_delete<PRArenaPool> +{ + void operator()(PRArenaPool* ptr) { PORT_FreeArena(ptr, PR_FALSE); } +}; +} + +static rtl::Reference<X509Certificate_NssImpl> NssCertToXCert( CERTCertificate* cert ) ; +static rtl::Reference<X509Certificate_NssImpl> NssPrivKeyToXCert( SECKEYPrivateKey* ) ; + +namespace { + +struct UsageDescription +{ + SECCertificateUsage usage; + char const* description; + + UsageDescription() + : usage( certificateUsageCheckAllUsages ) + , description( nullptr ) + {} + + UsageDescription( SECCertificateUsage i_usage, char const* i_description ) + : usage( i_usage ) + , description( i_description ) + {} +}; + +} + +static char* GetPasswordFunction( PK11SlotInfo* pSlot, PRBool bRetry, void* /*arg*/ ) +{ + uno::Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() ); + uno::Reference < task::XInteractionHandler2 > xInteractionHandler( + task::InteractionHandler::createWithParent(xContext, nullptr) ); + + task::PasswordRequestMode eMode = bRetry ? task::PasswordRequestMode_PASSWORD_REENTER : task::PasswordRequestMode_PASSWORD_ENTER; + rtl::Reference<::comphelper::DocPasswordRequest> pPasswordRequest = new ::comphelper::DocPasswordRequest( + ::comphelper::DocPasswordRequestType::Standard, eMode, OUString::createFromAscii(PK11_GetTokenName(pSlot)) ); + + xInteractionHandler->handle( pPasswordRequest ); + + if ( pPasswordRequest->isPassword() ) + { + OString aPassword(OUStringToOString( + pPasswordRequest->getPassword(), + osl_getThreadTextEncoding())); + sal_Int32 nLen = aPassword.getLength(); + char* pPassword = static_cast<char*>(PORT_Alloc( nLen+1 ) ); + pPassword[nLen] = 0; + memcpy( pPassword, aPassword.getStr(), nLen ); + return pPassword; + } + return nullptr; +} + +SecurityEnvironment_NssImpl::SecurityEnvironment_NssImpl() : +m_pHandler( nullptr ) { + PK11_SetPasswordFunc( GetPasswordFunction ) ; +} + +SecurityEnvironment_NssImpl::~SecurityEnvironment_NssImpl() { + + PK11_SetPasswordFunc( nullptr ) ; + + for (auto& slot : m_Slots) + { + PK11_FreeSlot(slot); + } + + for( auto& symKey : m_tSymKeyList ) + PK11_FreeSymKey( symKey ) ; +} + +/* XServiceInfo */ +OUString SAL_CALL SecurityEnvironment_NssImpl::getImplementationName() { + return "com.sun.star.xml.crypto.SecurityEnvironment"; +} + +/* XServiceInfo */ +sal_Bool SAL_CALL SecurityEnvironment_NssImpl::supportsService( const OUString& serviceName) { + return cppu::supportsService(this, serviceName); +} + +/* XServiceInfo */ +Sequence< OUString > SAL_CALL SecurityEnvironment_NssImpl::getSupportedServiceNames() { + Sequence<OUString> seqServiceNames{ "com.sun.star.xml.crypto.SecurityEnvironment" }; + return seqServiceNames; +} + +OUString SecurityEnvironment_NssImpl::getSecurityEnvironmentInformation() +{ + OUStringBuffer buff; + for (auto& slot : m_Slots) + { + buff.appendAscii(PK11_GetTokenName(slot)); + buff.append("\n"); + } + return buff.makeStringAndClear(); +} + +void SecurityEnvironment_NssImpl::addCryptoSlot( PK11SlotInfo* aSlot) +{ + PK11_ReferenceSlot(aSlot); + m_Slots.push_back(aSlot); +} + +//Could we have multiple cert dbs? +void SecurityEnvironment_NssImpl::setCertDb( CERTCertDBHandle* aCertDb ) { + m_pHandler = aCertDb ; +} + +void SecurityEnvironment_NssImpl::adoptSymKey( PK11SymKey* aSymKey ) { + if( aSymKey == nullptr ) return; + + //First try to find the key in the list + if (std::find(m_tSymKeyList.begin(), m_tSymKeyList.end(), aSymKey) != m_tSymKeyList.end()) + return; + + //If we do not find the key in the list, add a new node + PK11SymKey* symkey = PK11_ReferenceSymKey( aSymKey ) ; + if( symkey == nullptr ) + throw RuntimeException() ; + + try { + m_tSymKeyList.push_back( symkey ) ; + } catch ( Exception& ) { + PK11_FreeSymKey( symkey ) ; + } +} + +void SecurityEnvironment_NssImpl::updateSlots() +{ + //In case new tokens are present then we can obtain the corresponding slot + std::scoped_lock guard(m_mutex); + + m_Slots.clear(); + m_tSymKeyList.clear(); + + PK11SlotList * slotList = PK11_GetAllTokens( CKM_INVALID_MECHANISM, PR_FALSE, PR_FALSE, nullptr ) ; + if( slotList == nullptr ) + return; + + for (PK11SlotListElement* slotEle = slotList->head ; slotEle != nullptr; slotEle = slotEle->next) + { + PK11SlotInfo * pSlot = slotEle->slot ; + + if(pSlot != nullptr) + { + SAL_INFO( + "xmlsecurity.xmlsec", + "Found a slot: SlotName=" << PK11_GetSlotName(pSlot) + << ", TokenName=" << PK11_GetTokenName(pSlot)); + +//The following code which is commented out checks if a slot, that is a smart card for example, is +// able to generate a symmetric key of type CKM_DES3_CBC. If this fails then this token +// will not be used. This key is possibly used for the encryption service. However, all +// interfaces and services used for public key signature and encryption are not published +// and the encryption is not used in OOo. Therefore it does not do any harm to remove +// this code, hence allowing smart cards which cannot generate this type of key. +// +// By doing this, the encryption may fail if a smart card is being used which does not +// support this key generation. +// + PK11SymKey * pSymKey = PK11_KeyGen( pSlot , CKM_DES3_CBC, nullptr, 128, nullptr ) ; +// if( pSymKey == NULL ) +// { +// PK11_FreeSlot( pSlot ) ; +// SAL_INFO( "xmlsecurity", "XMLSEC: Error - pSymKey is NULL" ); +// continue; +// } + addCryptoSlot(pSlot); + + if (pSymKey != nullptr) + { + adoptSymKey( pSymKey ) ; + PK11_FreeSymKey( pSymKey ) ; + pSymKey = nullptr; + } + + }// end of if(pSlot != NULL) + }// end of for + + PK11_FreeSlotList(slotList); +} + +Sequence< Reference < XCertificate > > +SecurityEnvironment_NssImpl::getPersonalCertificates() +{ + std::vector< rtl::Reference<X509Certificate_NssImpl> > certsList ; + + updateSlots(); + //firstly, we try to find private keys in slot + for (auto& slot : m_Slots) + { + SECKEYPrivateKeyList* priKeyList ; + + if( PK11_NeedLogin(slot ) ) { + SECStatus nRet = PK11_Authenticate(slot, PR_TRUE, nullptr); + //PK11_Authenticate may fail in case the a slot has not been initialized. + //this is the case if the user has a new profile, so that they have never + //added a personal certificate. + if( nRet != SECSuccess && PORT_GetError() != SEC_ERROR_IO) { + throw NoPasswordException(); + } + } + + priKeyList = PK11_ListPrivateKeysInSlot(slot) ; + if( priKeyList != nullptr ) + { + for (SECKEYPrivateKeyListNode* curPri = PRIVKEY_LIST_HEAD(priKeyList); + !PRIVKEY_LIST_END( curPri, priKeyList ) && curPri != nullptr; + curPri = PRIVKEY_LIST_NEXT(curPri)) + { + rtl::Reference<X509Certificate_NssImpl> xcert = NssPrivKeyToXCert( curPri->key ) ; + if( xcert != nullptr ) + certsList.push_back( xcert ) ; + } + SECKEY_DestroyPrivateKeyList( priKeyList ) ; + } + + + } + + if( certsList.size() != 0 ) { + return comphelper::containerToSequence<Reference< XCertificate >>(certsList) ; + } + + return Sequence< Reference < XCertificate > > (); +} + +Reference< XCertificate > SecurityEnvironment_NssImpl::getCertificate( const OUString& issuerName, const Sequence< sal_Int8 >& serialNumber ) +{ + if( !m_pHandler ) + return nullptr; + + rtl::Reference<X509Certificate_NssImpl> xcert; + CERTIssuerAndSN issuerAndSN ; + CERTCertificate* cert ; + CERTName* nmIssuer ; + char* chIssuer ; + SECItem* derIssuer ; + std::unique_ptr<PRArenaPool> arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE)); + if( arena == nullptr ) + throw RuntimeException() ; + + // Create cert info from issue and serial + OString ostr = OUStringToOString( issuerName , RTL_TEXTENCODING_UTF8 ) ; + chIssuer = PL_strndup( ostr.getStr(), static_cast<int>(ostr.getLength()) ) ; + nmIssuer = CERT_AsciiToName( chIssuer ) ; + if( nmIssuer == nullptr ) { + PL_strfree( chIssuer ) ; + return nullptr; // no need for exception cf. i40394 + } + + derIssuer = SEC_ASN1EncodeItem( arena.get(), nullptr, static_cast<void*>(nmIssuer), SEC_ASN1_GET( CERT_NameTemplate ) ) ; + if( derIssuer == nullptr ) { + PL_strfree( chIssuer ) ; + CERT_DestroyName( nmIssuer ) ; + throw RuntimeException() ; + } + + memset( &issuerAndSN, 0, sizeof( issuerAndSN ) ) ; + + issuerAndSN.derIssuer.data = derIssuer->data ; + issuerAndSN.derIssuer.len = derIssuer->len ; + + issuerAndSN.serialNumber.data = reinterpret_cast<unsigned char *>(const_cast<sal_Int8 *>(serialNumber.getConstArray())); + issuerAndSN.serialNumber.len = serialNumber.getLength() ; + + cert = CERT_FindCertByIssuerAndSN( m_pHandler, &issuerAndSN ) ; + if( cert != nullptr ) { + xcert = NssCertToXCert( cert ) ; + } + + PL_strfree( chIssuer ) ; + CERT_DestroyName( nmIssuer ) ; + //SECITEM_FreeItem( derIssuer, PR_FALSE ) ; + CERT_DestroyCertificate( cert ) ; + + return xcert ; +} + +Sequence< Reference < XCertificate > > SecurityEnvironment_NssImpl::buildCertificatePath( const Reference< XCertificate >& begin ) { + + X509Certificate_NssImpl* xcert = dynamic_cast<X509Certificate_NssImpl*>(begin.get()); + if( xcert == nullptr ) { + throw RuntimeException() ; + } + + // Remember the signing certificate. + m_xSigningCertificate = xcert; + + const CERTCertificate* cert = xcert->getNssCert() ; + if (!cert) + return {}; + + //Get the system clock time + int64 timeboundary = PR_Now() ; + CERTCertList* certChain = CERT_GetCertChainFromCert( const_cast<CERTCertificate*>(cert), timeboundary, certUsageAnyCA ) ; + + if( !certChain ) + return {}; + + std::vector<uno::Reference<security::XCertificate>> aCertChain; + + for (CERTCertListNode* node = CERT_LIST_HEAD(certChain); !CERT_LIST_END(node, certChain); node = CERT_LIST_NEXT(node)) { + rtl::Reference<X509Certificate_NssImpl> pCert = new X509Certificate_NssImpl(); + if( pCert == nullptr ) { + CERT_DestroyCertList( certChain ) ; + throw RuntimeException() ; + } + + pCert->setCert( node->cert ) ; + + aCertChain.push_back(pCert); + } + + CERT_DestroyCertList( certChain ) ; + + return comphelper::containerToSequence(aCertChain); +} + +rtl::Reference<X509Certificate_NssImpl> SecurityEnvironment_NssImpl::createAndAddCertificateFromPackage( + const css::uno::Sequence<sal_Int8>& raDERCertificate, + std::u16string_view raString) +{ + auto pCertificateBytes = reinterpret_cast<char *>(const_cast<sal_Int8 *>(raDERCertificate.getConstArray())); + CERTCertificate* pCERTCertificate = CERT_DecodeCertFromPackage(pCertificateBytes, raDERCertificate.getLength()); + + if (!pCERTCertificate) + return nullptr; + + SECStatus aStatus; + + OString aTrustString = OUStringToOString(raString, RTL_TEXTENCODING_ASCII_US); + CERTCertTrust aTrust; + + aStatus = CERT_DecodeTrustString(&aTrust, aTrustString.getStr()); + + if (aStatus != SECSuccess) + { + PRIntn err = PR_GetError(); + SAL_WARN("xmlsecurity.xmlsec", "Error: " << err << ": " << getCertError(err)); + return nullptr; + } + + PK11SlotInfo* pSlot = PK11_GetInternalKeySlot(); + + if (!pSlot) + return nullptr; + + aStatus = PK11_ImportCert(pSlot, pCERTCertificate, CK_INVALID_HANDLE, nullptr, PR_FALSE); + + if (aStatus != SECSuccess) + { + PRIntn err = PR_GetError(); + SAL_WARN("xmlsecurity.xmlsec", "Error: " << err << ": " << getCertError(err)); + return nullptr; + } + + aStatus = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), pCERTCertificate, &aTrust); + + if (aStatus != SECSuccess) + { + PRIntn err = PR_GetError(); + SAL_WARN("xmlsecurity.xmlsec", "Error: " << err << ": " << getCertError(err)); + return nullptr; + } + + PK11_FreeSlot(pSlot); + + rtl::Reference<X509Certificate_NssImpl> pX509Certificate = new X509Certificate_NssImpl(); + pX509Certificate->setCert(pCERTCertificate); + return pX509Certificate; +} + +rtl::Reference<X509Certificate_NssImpl> SecurityEnvironment_NssImpl::createX509CertificateFromDER(const css::uno::Sequence<sal_Int8>& aDerCertificate) +{ + rtl::Reference<X509Certificate_NssImpl> pX509Certificate; + + if (aDerCertificate.hasElements()) + { + pX509Certificate = new X509Certificate_NssImpl(); + if (pX509Certificate == nullptr) + throw RuntimeException(); + pX509Certificate->setRawCert(aDerCertificate); + } + return pX509Certificate; +} + +Reference<XCertificate> SecurityEnvironment_NssImpl::createCertificateFromRaw(const Sequence< sal_Int8 >& rawCertificate) +{ + return createX509CertificateFromDER(rawCertificate); +} + +Reference< XCertificate > SecurityEnvironment_NssImpl::createCertificateFromAscii( const OUString& asciiCertificate ) +{ + OString oscert = OUStringToOString( asciiCertificate , RTL_TEXTENCODING_ASCII_US ) ; + xmlChar* chCert = xmlStrndup( reinterpret_cast<const xmlChar*>(oscert.getStr()), static_cast<int>(oscert.getLength()) ) ; + xmlSecSize certSize; + int nRet = xmlSecBase64Decode_ex( chCert, reinterpret_cast<xmlSecByte*>(chCert), xmlStrlen( chCert ), &certSize ) ; + if (nRet < 0 || certSize == 0) + { + xmlFree(chCert); + return nullptr; + } + + Sequence< sal_Int8 > rawCert(comphelper::arrayToSequence<sal_Int8>(chCert, certSize)) ; + + xmlFree( chCert ) ; + + return createCertificateFromRaw( rawCert ) ; +} + +sal_Int32 SecurityEnvironment_NssImpl :: +verifyCertificate( const Reference< csss::XCertificate >& aCert, + const Sequence< Reference< csss::XCertificate > >& intermediateCerts ) +{ + sal_Int32 validity = csss::CertificateValidity::INVALID; + const CERTCertificate* cert ; + + SAL_INFO("xmlsecurity.xmlsec", "Start verification of certificate: " << aCert->getSubjectName()); + + const X509Certificate_NssImpl* xcert = dynamic_cast<X509Certificate_NssImpl*>(aCert.get()); + if( xcert == nullptr ) { + throw RuntimeException() ; + } + + //CERT_PKIXVerifyCert does not take a db as argument. It will therefore + //internally use CERT_GetDefaultCertDB + //Make sure m_pHandler is the default DB + OSL_ASSERT(m_pHandler == CERT_GetDefaultCertDB()); + CERTCertDBHandle * certDb = m_pHandler != nullptr ? m_pHandler : CERT_GetDefaultCertDB(); + cert = xcert->getNssCert() ; + if( !cert ) + return css::security::CertificateValidity::INVALID; + + + ::std::vector<CERTCertificate*> vecTmpNSSCertificates; + + //prepare the intermediate certificates + for (const auto& rIntermediateCert : intermediateCerts) + { + Sequence<sal_Int8> der = rIntermediateCert->getEncoded(); + SECItem item; + item.type = siBuffer; + item.data = reinterpret_cast<unsigned char*>(der.getArray()); + item.len = der.getLength(); + + CERTCertificate* certTmp = CERT_NewTempCertificate(certDb, &item, + nullptr /* nickname */, + PR_FALSE /* isPerm */, + PR_TRUE /* copyDER */); + if (!certTmp) + { + SAL_INFO("xmlsecurity.xmlsec", "Failed to add a temporary certificate: " << rIntermediateCert->getIssuerName()); + + } + else + { + SAL_INFO("xmlsecurity.xmlsec", "Added temporary certificate: " << + (certTmp->subjectName ? certTmp->subjectName : "")); + vecTmpNSSCertificates.push_back(certTmp); + } + } + + + SECStatus status ; + + CERTVerifyLog log; + log.arena = PORT_NewArena(512); + log.head = log.tail = nullptr; + log.count = 0; + + CERT_EnableOCSPChecking(certDb); + CERT_DisableOCSPDefaultResponder(certDb); + CERTValOutParam cvout[5]; + CERTValInParam cvin[3]; + int ncvinCount=0; + +#if ( NSS_VMAJOR > 3 ) || ( NSS_VMAJOR == 3 && NSS_VMINOR > 12 ) || ( NSS_VMAJOR == 3 && NSS_VMINOR == 12 && NSS_VPATCH > 0 ) + cvin[ncvinCount].type = cert_pi_useAIACertFetch; + cvin[ncvinCount].value.scalar.b = PR_TRUE; + ncvinCount++; +#endif + + PRUint64 revFlagsLeaf[2]; + PRUint64 revFlagsChain[2]; + CERTRevocationFlags rev; + rev.leafTests.number_of_defined_methods = 2; + rev.leafTests.cert_rev_flags_per_method = revFlagsLeaf; + //the flags are defined in cert.h + //We check both leaf and chain. + //It is enough if one revocation method has fresh info, + //but at least one must have some. Otherwise validation fails. + //!!! using leaf test and CERT_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE + // when validating a root certificate will result in "revoked". Usually + //there is no revocation information available for the root cert because + //it must be trusted anyway and it does itself issue revocation information. + //When we use the flag here and OOo shows the certification path then the root + //cert is invalid while all other can be valid. It would probably best if + //this interface method returned the whole chain. + //Otherwise we need to check if the certificate is self-signed and if it is + //then not use the flag when doing the leaf-test. + rev.leafTests.cert_rev_flags_per_method[cert_revocation_method_crl] = + CERT_REV_M_TEST_USING_THIS_METHOD + | CERT_REV_M_IGNORE_IMPLICIT_DEFAULT_SOURCE; + rev.leafTests.cert_rev_flags_per_method[cert_revocation_method_ocsp] = + CERT_REV_M_TEST_USING_THIS_METHOD + | CERT_REV_M_IGNORE_IMPLICIT_DEFAULT_SOURCE; + rev.leafTests.number_of_preferred_methods = 0; + rev.leafTests.preferred_methods = nullptr; + rev.leafTests.cert_rev_method_independent_flags = + CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST; + + rev.chainTests.number_of_defined_methods = 2; + rev.chainTests.cert_rev_flags_per_method = revFlagsChain; + rev.chainTests.cert_rev_flags_per_method[cert_revocation_method_crl] = + CERT_REV_M_TEST_USING_THIS_METHOD + | CERT_REV_M_IGNORE_IMPLICIT_DEFAULT_SOURCE; + rev.chainTests.cert_rev_flags_per_method[cert_revocation_method_ocsp] = + CERT_REV_M_TEST_USING_THIS_METHOD + | CERT_REV_M_IGNORE_IMPLICIT_DEFAULT_SOURCE; + rev.chainTests.number_of_preferred_methods = 0; + rev.chainTests.preferred_methods = nullptr; + rev.chainTests.cert_rev_method_independent_flags = + CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST; + + + cvin[ncvinCount].type = cert_pi_revocationFlags; + cvin[ncvinCount].value.pointer.revocation = &rev; + ncvinCount++; + // does not work, not implemented yet in 3.12.4 +// cvin[ncvinCount].type = cert_pi_keyusage; +// cvin[ncvinCount].value.scalar.ui = KU_DIGITAL_SIGNATURE; +// ncvinCount++; + cvin[ncvinCount].type = cert_pi_end; + + cvout[0].type = cert_po_trustAnchor; + cvout[0].value.pointer.cert = nullptr; + cvout[1].type = cert_po_errorLog; + cvout[1].value.pointer.log = &log; + cvout[2].type = cert_po_end; + + // We check SSL server certificates, CA certificates and signing certificates. + // + // ToDo check keyusage, looking at CERT_KeyUsageAndTypeForCertUsage ( + // mozilla/security/nss/lib/certdb/certdb.c indicates that + // certificateUsageSSLClient, certificateUsageSSLServer and certificateUsageSSLCA + // are sufficient. They cover the key usages for digital signature, key agreement + // and encipherment and certificate signature + + //never use the following usages because they are not checked properly + // certificateUsageUserCertImport + // certificateUsageVerifyCA + // certificateUsageAnyCA + // certificateUsageProtectedObjectSigner + + UsageDescription arUsages[5]; + arUsages[0] = UsageDescription( certificateUsageSSLClient, "certificateUsageSSLClient" ); + arUsages[1] = UsageDescription( certificateUsageSSLServer, "certificateUsageSSLServer" ); + arUsages[2] = UsageDescription( certificateUsageSSLCA, "certificateUsageSSLCA" ); + arUsages[3] = UsageDescription( certificateUsageEmailSigner, "certificateUsageEmailSigner" ); + arUsages[4] = UsageDescription( certificateUsageEmailRecipient, "certificateUsageEmailRecipient" ); + + int numUsages = std::size(arUsages); + for (int i = 0; i < numUsages; i++) + { + SAL_INFO("xmlsecurity.xmlsec", "Testing usage " << i+1 << + " of " << numUsages << ": " << + arUsages[i].description << + " (0x" << std::hex << static_cast<int>(arUsages[i].usage) << ")" << std::dec); + + status = CERT_PKIXVerifyCert(const_cast<CERTCertificate *>(cert), arUsages[i].usage, + cvin, cvout, nullptr); + if( status == SECSuccess ) + { + SAL_INFO("xmlsecurity.xmlsec", "CERT_PKIXVerifyCert returned SECSuccess."); + //When an intermediate or root certificate is checked then we expect the usage + //certificateUsageSSLCA. This, however, will be only set when in the trust settings dialog + //the button "This certificate can identify websites" is checked. If for example only + //"This certificate can identify mail users" is set then the end certificate can + //be validated and the returned usage will contain certificateUsageEmailRecipient. + //But checking directly the root or intermediate certificate will fail. In the + //certificate path view the end certificate will be shown as valid but the others + //will be displayed as invalid. + + validity = csss::CertificateValidity::VALID; + SAL_INFO("xmlsecurity.xmlsec", "Certificate is valid."); + CERTCertificate * issuerCert = cvout[0].value.pointer.cert; + if (issuerCert) + { + SAL_INFO("xmlsecurity.xmlsec", "Root certificate: " << issuerCert->subjectName); + CERT_DestroyCertificate(issuerCert); + }; + + break; + } + else + { + PRIntn err = PR_GetError(); + SAL_INFO("xmlsecurity.xmlsec", "Error: " << err << ": " << getCertError(err)); + + /* Display validation results */ + if ( log.count > 0) + { + CERTVerifyLogNode *node = nullptr; + printChainFailure(&log); + + for (node = log.head; node; node = node->next) { + if (node->cert) + CERT_DestroyCertificate(node->cert); + } + log.head = log.tail = nullptr; + log.count = 0; + } + SAL_INFO("xmlsecurity.xmlsec", "Certificate is invalid."); + } + } + + //Destroying the temporary certificates + for (auto& tmpCert : vecTmpNSSCertificates) + { + SAL_INFO("xmlsecurity.xmlsec", "Destroying temporary certificate"); + CERT_DestroyCertificate(tmpCert); + } + PORT_FreeArena(log.arena, true); + return validity ; +} + +sal_Int32 SecurityEnvironment_NssImpl::getCertificateCharacters( + const css::uno::Reference< css::security::XCertificate >& aCert ) { + sal_Int32 characters ; + const CERTCertificate* cert ; + + const X509Certificate_NssImpl* xcert = dynamic_cast<X509Certificate_NssImpl*>(aCert.get()); + if( xcert == nullptr ) { + throw RuntimeException() ; + } + + cert = xcert->getNssCert() ; + + characters = 0x00000000 ; + + //Firstly, find out whether or not the cert is self-signed. + if( SECITEM_CompareItem( &(cert->derIssuer), &(cert->derSubject) ) == SECEqual ) { + characters |= css::security::CertificateCharacters::SELF_SIGNED ; + } else { + characters &= ~ css::security::CertificateCharacters::SELF_SIGNED ; + } + + //Secondly, find out whether or not the cert has a private key. + + /* + * i40394 + * + * mmi : need to check whether the cert's slot is valid first + */ + SECKEYPrivateKey* priKey = nullptr; + + if (cert->slot != nullptr) + { + priKey = PK11_FindPrivateKeyFromCert( cert->slot, const_cast<CERTCertificate*>(cert), nullptr ) ; + } + if(priKey == nullptr) + { + for (auto& slot : m_Slots) + { + priKey = PK11_FindPrivateKeyFromCert(slot, const_cast<CERTCertificate*>(cert), nullptr); + if (priKey) + break; + } + } + if( priKey != nullptr ) { + characters |= css::security::CertificateCharacters::HAS_PRIVATE_KEY ; + + SECKEY_DestroyPrivateKey( priKey ) ; + } else { + characters &= ~ css::security::CertificateCharacters::HAS_PRIVATE_KEY ; + } + + return characters ; +} + +rtl::Reference<X509Certificate_NssImpl> NssCertToXCert( CERTCertificate* cert ) +{ + if( cert != nullptr ) { + rtl::Reference<X509Certificate_NssImpl> xcert = new X509Certificate_NssImpl() ; + xcert->setCert( cert ) ; + return xcert; + } + + return nullptr; +} + +rtl::Reference<X509Certificate_NssImpl> NssPrivKeyToXCert( SECKEYPrivateKey* priKey ) +{ + if( priKey != nullptr ) { + rtl::Reference<X509Certificate_NssImpl> xcert; + CERTCertificate* cert = PK11_GetCertFromPrivateKey( priKey ) ; + + if( cert != nullptr ) { + xcert = NssCertToXCert( cert ) ; + } + + CERT_DestroyCertificate( cert ) ; + return xcert; + } + + return nullptr; +} + +xmlSecKeysMngrPtr SecurityEnvironment_NssImpl::createKeysManager() { + + /*- + * The following lines is based on the private version of xmlSec-NSS + * crypto engine + */ + int cSlots = m_Slots.size(); + std::unique_ptr<PK11SlotInfo*[]> sarSlots(new PK11SlotInfo*[cSlots]); + PK11SlotInfo** slots = sarSlots.get(); + int count = 0; + for (const auto& slot : m_Slots) + { + slots[count] = slot; + ++count; + } + + xmlSecKeysMngrPtr pKeysMngr = xmlSecKeysMngrCreate(); + if (!pKeysMngr) + throw RuntimeException(); + + if (xmlSecNssAppDefaultKeysMngrInit(pKeysMngr) < 0) + throw RuntimeException(); + + // Adopt the private key of the signing certificate, if it has any. + if (m_xSigningCertificate) + { + SECKEYPrivateKey* pPrivateKey = SECKEY_CopyPrivateKey(m_xSigningCertificate->getPrivateKey()); + if (pPrivateKey) + { + xmlSecKeyDataPtr pKeyData = xmlSecNssPKIAdoptKey(pPrivateKey, nullptr); + xmlSecKeyPtr pKey = xmlSecKeyCreate(); + xmlSecKeySetValue(pKey, pKeyData); + xmlSecNssAppDefaultKeysMngrAdoptKey(pKeysMngr, pKey); + } + else + { + SAL_WARN("xmlsecurity.xmlsec", "Can't get the private key from the certificate."); + } + } + + return pKeysMngr; +} + +void SecurityEnvironment_NssImpl::destroyKeysManager(xmlSecKeysMngrPtr pKeysMngr) { + if( pKeysMngr != nullptr ) { + xmlSecKeysMngrDestroy( pKeysMngr ) ; + } +} + +SECKEYPrivateKey* SecurityEnvironment_NssImpl::insertPrivateKey(css::uno::Sequence<sal_Int8> const & raPrivateKey) +{ + PK11SlotInfo* pSlot = PK11_GetInternalKeySlot(); + + if (!pSlot) + return nullptr; + + SECItem aDerPrivateKeyInfo; + aDerPrivateKeyInfo.data = reinterpret_cast<unsigned char *>(const_cast<sal_Int8 *>(raPrivateKey.getConstArray())); + aDerPrivateKeyInfo.len = raPrivateKey.getLength(); + + const unsigned int aKeyUsage = KU_ALL; + SECKEYPrivateKey* pPrivateKey = nullptr; + + bool bPermanent = PR_FALSE; + bool bPrivate = PR_TRUE; + + SECStatus nStatus = PK11_ImportDERPrivateKeyInfoAndReturnKey( + pSlot, &aDerPrivateKeyInfo, nullptr, nullptr, bPermanent, bPrivate, + aKeyUsage, &pPrivateKey, nullptr); + + if (nStatus != SECSuccess) + return nullptr; + + PK11_FreeSlot(pSlot); + + return pPrivateKey; +} + +uno::Reference<security::XCertificate> SecurityEnvironment_NssImpl::createDERCertificateWithPrivateKey( + Sequence<sal_Int8> const & raDERCertificate, Sequence<sal_Int8> const & raPrivateKey) +{ + SECKEYPrivateKey* pPrivateKey = insertPrivateKey(raPrivateKey); + + if (!pPrivateKey) + return uno::Reference<security::XCertificate>(); + + return createAndAddCertificateFromPackage(raDERCertificate, u"TCu,TCu,TCu"); +} + +uno::Reference<security::XCertificate> SecurityEnvironment_NssImpl::addDERCertificateToTheDatabase( + uno::Sequence<sal_Int8> const & raDERCertificate, OUString const & raTrustString) +{ + return createAndAddCertificateFromPackage(raDERCertificate, raTrustString); +} + +extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface* +com_sun_star_xml_crypto_SecurityEnvironment_get_implementation( + uno::XComponentContext* /*pCtx*/, uno::Sequence<uno::Any> const& /*rSeq*/) +{ + return cppu::acquire(new SecurityEnvironment_NssImpl); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.hxx b/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.hxx new file mode 100644 index 0000000000..c0e4698998 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.hxx @@ -0,0 +1,139 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <sal/config.h> +#include <rtl/ustring.hxx> +#include <rtl/ref.hxx> +#include <cppuhelper/implbase.hxx> + +#include <com/sun/star/uno/Reference.hxx> + +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/xml/crypto/XSecurityEnvironment.hpp> +#include <com/sun/star/xml/crypto/XCertificateCreator.hpp> + +#include <mutex> + +#include <keythi.h> +#include <certt.h> + +#include <string_view> +#include <vector> + +#include <xmlsec-wrapper.h> + +namespace com::sun::star::security { class XCertificate; } +class X509Certificate_NssImpl; + +class SecurityEnvironment_NssImpl : public ::cppu::WeakImplHelper< + css::xml::crypto::XSecurityEnvironment, + css::xml::crypto::XCertificateCreator, + css::lang::XServiceInfo > +{ +private: + + std::vector< PK11SlotInfo* > m_Slots; + /// The last used certificate which has the private key for signing. + rtl::Reference<X509Certificate_NssImpl> m_xSigningCertificate; + + std::mutex m_mutex; + + CERTCertDBHandle* m_pHandler ; + std::vector< PK11SymKey* > m_tSymKeyList ; + + public: + SecurityEnvironment_NssImpl(); + virtual ~SecurityEnvironment_NssImpl() override; + + //Methods from XSecurityEnvironment + + //Methods from XServiceInfo + virtual OUString SAL_CALL getImplementationName() override ; + + virtual sal_Bool SAL_CALL supportsService( + const OUString& ServiceName + ) override ; + + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override ; + + virtual ::sal_Int32 SAL_CALL verifyCertificate( + const css::uno::Reference< + css::security::XCertificate >& xCert, + const css::uno::Sequence< + css::uno::Reference< css::security::XCertificate > > & + intermediateCerts) override ; + + virtual ::sal_Int32 SAL_CALL getCertificateCharacters( const css::uno::Reference< css::security::XCertificate >& xCert ) override ; + + virtual OUString SAL_CALL getSecurityEnvironmentInformation( ) override; + + /// @throws css::uno::Exception + /// @throws css::uno::RuntimeException + void setCertDb( CERTCertDBHandle* aCertDb ) ; + + /// @throws css::uno::Exception + /// @throws css::uno::RuntimeException + void adoptSymKey( PK11SymKey* aSymKey ) ; + + virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificate > > SAL_CALL getPersonalCertificates() override ; + virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificate > > SAL_CALL getAllCertificates() override + { return css::uno::Sequence< css::uno::Reference< css::security::XCertificate > >(); } + + virtual css::uno::Reference< css::security::XCertificate > SAL_CALL getCertificate( const OUString& issuerName, const css::uno::Sequence< sal_Int8 >& serialNumber ) override ; + + virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificate > > SAL_CALL buildCertificatePath( const css::uno::Reference< css::security::XCertificate >& beginCert ) override ; + + virtual css::uno::Reference< css::security::XCertificate > SAL_CALL createCertificateFromRaw( const css::uno::Sequence< sal_Int8 >& rawCertificate ) override ; + virtual css::uno::Reference< css::security::XCertificate > SAL_CALL createCertificateFromAscii( const OUString& asciiCertificate ) override ; + + // Methods of XCertificateCreator + css::uno::Reference<css::security::XCertificate> SAL_CALL addDERCertificateToTheDatabase( + css::uno::Sequence<sal_Int8> const & raDERCertificate, + OUString const & raTrustString) override; + + css::uno::Reference<css::security::XCertificate> SAL_CALL createDERCertificateWithPrivateKey( + css::uno::Sequence<sal_Int8> const & raDERCertificate, + css::uno::Sequence<sal_Int8> const & raPrivateKey) override; + + //Native methods + /// @throws css::uno::RuntimeException + xmlSecKeysMngrPtr createKeysManager() ; + /// @throws css::uno::Exception + /// @throws css::uno::RuntimeException + static void destroyKeysManager(xmlSecKeysMngrPtr pKeysMngr) ; + +private: + + void updateSlots(); + + static rtl::Reference<X509Certificate_NssImpl> createAndAddCertificateFromPackage( + const css::uno::Sequence<sal_Int8>& raDerCertificate, + std::u16string_view raString); + static SECKEYPrivateKey* insertPrivateKey(css::uno::Sequence<sal_Int8> const & raPrivateKey); + + static rtl::Reference<X509Certificate_NssImpl> createX509CertificateFromDER(const css::uno::Sequence<sal_Int8>& raDerCertificate); + + /// @throws css::uno::Exception + /// @throws css::uno::RuntimeException + void addCryptoSlot( PK11SlotInfo* aSlot ) ; +} ; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/seinitializer_nssimpl.cxx b/xmlsecurity/source/xmlsec/nss/seinitializer_nssimpl.cxx new file mode 100644 index 0000000000..6b5c3d6c5b --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/seinitializer_nssimpl.cxx @@ -0,0 +1,144 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/types.h> +#include <com/sun/star/xml/crypto/SecurityEnvironment.hpp> +#include <com/sun/star/xml/crypto/XMLSecurityContext.hpp> +#include <comphelper/servicehelper.hxx> +#include <cppuhelper/supportsservice.hxx> + +#include "seinitializer_nssimpl.hxx" +#include "securityenvironment_nssimpl.hxx" + +#include <cert.h> + + +using namespace com::sun::star; + + +SEInitializer_NssImpl::SEInitializer_NssImpl( const css::uno::Reference< css::uno::XComponentContext > &rxContext ) +{ + m_xContext = rxContext; +} + +SEInitializer_NssImpl::~SEInitializer_NssImpl() +{ +} + +/* XSEInitializer */ +uno::Reference< css::xml::crypto::XXMLSecurityContext > SAL_CALL + SEInitializer_NssImpl::createSecurityContext( const OUString& ) +{ + CERTCertDBHandle *pCertHandle = nullptr ; + + if( !initNSS( m_xContext ) ) + return nullptr; + + pCertHandle = CERT_GetDefaultCertDB() ; + + try + { + /* Build XML Security Context */ + uno::Reference< css::xml::crypto::XXMLSecurityContext > xSecCtx = css::xml::crypto::XMLSecurityContext::create( m_xContext ); + + uno::Reference< css::xml::crypto::XSecurityEnvironment > xSecEnv = css::xml::crypto::SecurityEnvironment::create( m_xContext ); + SecurityEnvironment_NssImpl* pSecEnv = dynamic_cast<SecurityEnvironment_NssImpl*>(xSecEnv.get()); + assert(pSecEnv && "can only succeed"); + pSecEnv->setCertDb(pCertHandle); + + sal_Int32 n = xSecCtx->addSecurityEnvironment(xSecEnv); + //originally the SecurityEnvironment with the internal slot was set as default + xSecCtx->setDefaultSecurityEnvironmentIndex( n ); + return xSecCtx; + } + catch( const uno::Exception& ) + { + //PK11_LogoutAll(); + //NSS_Shutdown(); + return nullptr; + } +} + +void SAL_CALL SEInitializer_NssImpl::freeSecurityContext( const uno::Reference< css::xml::crypto::XXMLSecurityContext >& ) +{ + /* + * because the security context will free all its content when it + * is destructed, so here no free process for the security context + * is needed. + */ + //PK11_LogoutAll(); + //NSS_Shutdown(); +} + +/* XServiceInfo */ +OUString SAL_CALL SEInitializer_NssImpl::getImplementationName( ) +{ + return "com.sun.star.xml.crypto.SEInitializer"; +} +sal_Bool SAL_CALL SEInitializer_NssImpl::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService( this, rServiceName ); +} +uno::Sequence< OUString > SAL_CALL SEInitializer_NssImpl::getSupportedServiceNames( ) +{ + return { "com.sun.star.xml.crypto.SEInitializer" }; +} + +namespace { + +class NSSInitializer_NssImpl : public SEInitializer_NssImpl +{ +public: + explicit NSSInitializer_NssImpl(const uno::Reference<uno::XComponentContext>& xContext); + OUString SAL_CALL getImplementationName() override; + uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override; +}; + +} + +NSSInitializer_NssImpl::NSSInitializer_NssImpl(const uno::Reference<uno::XComponentContext>& xContext) + : SEInitializer_NssImpl(xContext) +{ +} + +OUString NSSInitializer_NssImpl::getImplementationName() +{ + return "com.sun.star.xml.crypto.NSSInitializer"; +} + +uno::Sequence<OUString> SAL_CALL NSSInitializer_NssImpl::getSupportedServiceNames() +{ + return { "com.sun.star.xml.crypto.NSSInitializer" }; +} + +extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface* +com_sun_star_xml_crypto_NSSInitializer_get_implementation( + uno::XComponentContext* pCtx, uno::Sequence<uno::Any> const& /*rSeq*/) +{ + return cppu::acquire(new NSSInitializer_NssImpl(pCtx)); +} + +extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface* +com_sun_star_xml_crypto_SEInitializer_get_implementation( + uno::XComponentContext* pCtx, uno::Sequence<uno::Any> const& /*rSeq*/) +{ + return cppu::acquire(new SEInitializer_NssImpl(pCtx)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/seinitializer_nssimpl.hxx b/xmlsecurity/source/xmlsec/nss/seinitializer_nssimpl.hxx new file mode 100644 index 0000000000..f078f387af --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/seinitializer_nssimpl.hxx @@ -0,0 +1,55 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <com/sun/star/xml/crypto/XSEInitializer.hpp> + +#include <cppuhelper/implbase.hxx> + +#include "nssinitializer.hxx" + +namespace com::sun::star::xml::crypto { class XXMLSecurityContext; } + +class SEInitializer_NssImpl : public cppu::ImplInheritanceHelper +< + ONSSInitializer, + css::xml::crypto::XSEInitializer +> +{ +public: + explicit SEInitializer_NssImpl(const css::uno::Reference<css::uno::XComponentContext > &rxContext); + virtual ~SEInitializer_NssImpl() override; + + /* XSEInitializer */ + virtual css::uno::Reference< css::xml::crypto::XXMLSecurityContext > + SAL_CALL createSecurityContext( const OUString& ) override; + + virtual void SAL_CALL freeSecurityContext( const css::uno::Reference< + css::xml::crypto::XXMLSecurityContext >& securityContext ) override; + + /* XServiceInfo */ + virtual OUString SAL_CALL getImplementationName( ) override; + + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx b/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx new file mode 100644 index 0000000000..e1526ea90d --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx @@ -0,0 +1,602 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "nssrenam.h" +#include <secder.h> + +#include <cert.h> +#include <pk11pub.h> +#include <hasht.h> + +#include <comphelper/sequence.hxx> +#include <comphelper/servicehelper.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <rtl/ref.hxx> +#include <rtl/ustrbuf.hxx> +#include <sal/log.hxx> +#include "x509certificate_nssimpl.hxx" + +#include <biginteger.hxx> +#include <certificateextension_xmlsecimpl.hxx> + +#include "sanextension_nssimpl.hxx" +#include <o3tl/string_view.hxx> +#include <tools/time.hxx> +#include <svl/sigstruct.hxx> + +using ::css::util::DateTime; + +X509Certificate_NssImpl::X509Certificate_NssImpl() : + m_pCert(nullptr) +{ +} + +X509Certificate_NssImpl::~X509Certificate_NssImpl() { + if( m_pCert != nullptr ) { + CERT_DestroyCertificate( m_pCert ) ; + } +} + +//Methods from XCertificate +sal_Int16 SAL_CALL X509Certificate_NssImpl::getVersion() { + if( m_pCert != nullptr ) { + if( m_pCert->version.len > 0 ) { + return static_cast<char>(*( m_pCert->version.data )) ; + } else + return 0 ; + } else { + return -1 ; + } +} + +css::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_NssImpl::getSerialNumber() { + if( m_pCert != nullptr && m_pCert->serialNumber.len > 0 ) { + return comphelper::arrayToSequence<sal_Int8>(m_pCert->serialNumber.data, + m_pCert->serialNumber.len) ; + } else { + return css::uno::Sequence< sal_Int8 >(); + } +} + +OUString SAL_CALL X509Certificate_NssImpl::getIssuerName() { + if( m_pCert != nullptr ) { + return OUString(m_pCert->issuerName , PL_strlen(m_pCert->issuerName) , RTL_TEXTENCODING_UTF8) ; + } else { + return OUString() ; + } +} + +OUString SAL_CALL X509Certificate_NssImpl::getSubjectName() { + if( m_pCert != nullptr ) { + return OUString(m_pCert->subjectName , PL_strlen(m_pCert->subjectName) , RTL_TEXTENCODING_UTF8); + } else { + return OUString() ; + } +} + +css::util::DateTime SAL_CALL X509Certificate_NssImpl::getNotValidBefore() { + if( m_pCert != nullptr ) { + SECStatus rv ; + PRTime notBefore ; + PRExplodedTime explTime ; + DateTime dateTime ; + + rv = DER_DecodeTimeChoice( ¬Before, &m_pCert->validity.notBefore ) ; + if( rv != SECStatus::SECSuccess ) { + return DateTime() ; + } + + //Convert the time to readable local time + PR_ExplodeTime( notBefore, PR_LocalTimeParameters, &explTime ) ; + + dateTime.NanoSeconds = static_cast< sal_Int32 >( explTime.tm_usec * ::tools::Time::nanoPerMicro ); + dateTime.Seconds = static_cast< sal_Int16 >( explTime.tm_sec ); + dateTime.Minutes = static_cast< sal_Int16 >( explTime.tm_min ); + dateTime.Hours = static_cast< sal_Int16 >( explTime.tm_hour ); + dateTime.Day = static_cast< sal_Int16 >( explTime.tm_mday ); + dateTime.Month = static_cast< sal_Int16 >( explTime.tm_month+1 ); + dateTime.Year = static_cast< sal_Int16 >( explTime.tm_year ); + + return dateTime ; + } else { + return DateTime() ; + } +} + +css::util::DateTime SAL_CALL X509Certificate_NssImpl::getNotValidAfter() { + if( m_pCert != nullptr ) { + SECStatus rv ; + PRTime notAfter ; + PRExplodedTime explTime ; + DateTime dateTime ; + + rv = DER_DecodeTimeChoice( ¬After, &m_pCert->validity.notAfter ) ; + if( rv != SECStatus::SECSuccess ) { + return DateTime() ; + } + + //Convert the time to readable local time + PR_ExplodeTime( notAfter, PR_LocalTimeParameters, &explTime ) ; + + dateTime.NanoSeconds = static_cast< sal_Int16 >( explTime.tm_usec * ::tools::Time::nanoPerMicro ); + dateTime.Seconds = static_cast< sal_Int16 >( explTime.tm_sec ); + dateTime.Minutes = static_cast< sal_Int16 >( explTime.tm_min ); + dateTime.Hours = static_cast< sal_Int16 >( explTime.tm_hour ); + dateTime.Day = static_cast< sal_Int16 >( explTime.tm_mday ); + dateTime.Month = static_cast< sal_Int16 >( explTime.tm_month+1 ); + dateTime.Year = static_cast< sal_Int16 >( explTime.tm_year ); + + return dateTime ; + } else { + return DateTime() ; + } +} + +css::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_NssImpl::getIssuerUniqueID() { + if( m_pCert != nullptr && m_pCert->issuerID.len > 0 ) { + return comphelper::arrayToSequence<sal_Int8>(m_pCert->issuerID.data, m_pCert->issuerID.len) ; + } else { + return css::uno::Sequence< sal_Int8 >(); + } +} + +css::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_NssImpl::getSubjectUniqueID() { + if( m_pCert != nullptr && m_pCert->subjectID.len > 0 ) { + return comphelper::arrayToSequence<sal_Int8>(m_pCert->subjectID.data, + m_pCert->subjectID.len) ; + } else { + return css::uno::Sequence< sal_Int8 >(); + } +} + +css::uno::Sequence< css::uno::Reference< css::security::XCertificateExtension > > SAL_CALL X509Certificate_NssImpl::getExtensions() { + if( m_pCert != nullptr && m_pCert->extensions != nullptr ) { + CERTCertExtension** extns ; + int len ; + + for( len = 0, extns = m_pCert->extensions; *extns != nullptr; len ++, extns ++ ) ; + css::uno::Sequence< css::uno::Reference< css::security::XCertificateExtension > > xExtns( len ) ; + auto xExtnsRange = asNonConstRange(xExtns); + + for( extns = m_pCert->extensions, len = 0; *extns != nullptr; extns ++, len ++ ) { + const SECItem id = (*extns)->id; + OString oidString(CERT_GetOidString(&id)); + + bool crit; + if( (*extns)->critical.data == nullptr ) + crit = false ; + else + crit = (*extns)->critical.data[0] == 0xFF; + + // remove "OID." prefix if existing + OString objID; + constexpr std::string_view oid("OID."); + if (oidString.match(oid)) + objID = oidString.copy(oid.size()); + else + objID = oidString; + + unsigned char* value = (*extns)->value.data; + unsigned int vlen = (*extns)->value.len; + unsigned char* objid = reinterpret_cast<unsigned char *>(const_cast<char *>(objID.getStr())); + unsigned int objidlen = objID.getLength(); + + if (objID == "2.5.29.17") + { + rtl::Reference<SanExtensionImpl> pExtn = new SanExtensionImpl; + pExtn->setCertExtn(value, vlen, objid, objidlen, crit); + xExtnsRange[len] = pExtn ; + } + else + { + rtl::Reference<CertificateExtension_XmlSecImpl> pExtn = new CertificateExtension_XmlSecImpl; + pExtn->setCertExtn(value, vlen, objid, objidlen, crit); + xExtnsRange[len] = pExtn; + } + } + + return xExtns ; + } else { + return css::uno::Sequence< css::uno::Reference< css::security::XCertificateExtension > > (); + } +} + +css::uno::Reference< css::security::XCertificateExtension > SAL_CALL X509Certificate_NssImpl::findCertificateExtension( const css::uno::Sequence< sal_Int8 >& oid ) { + if( m_pCert != nullptr && m_pCert->extensions != nullptr ) { + CERTCertExtension** extns ; + SECItem idItem ; + + idItem.data = reinterpret_cast<unsigned char *>(const_cast<sal_Int8 *>(oid.getConstArray())); + idItem.len = oid.getLength() ; + + css::uno::Reference<css::security::XCertificateExtension> xExtn; + for( extns = m_pCert->extensions; *extns != nullptr; extns ++ ) { + if( SECITEM_CompareItem( &idItem, &(*extns)->id ) == SECEqual ) { + const SECItem id = (*extns)->id; + OString objId(CERT_GetOidString(&id)); + + bool crit; + if( (*extns)->critical.data == nullptr ) + crit = false ; + else + crit = (*extns)->critical.data[0] == 0xFF; + + unsigned char* value = (*extns)->value.data; + unsigned int vlen = (*extns)->value.len; + unsigned char* objid = (*extns)->id.data; + unsigned int objidlen = (*extns)->id.len; + + if ( objId == "OID.2.5.29.17" ) + { + rtl::Reference<SanExtensionImpl> xSanImpl( + new SanExtensionImpl); + xSanImpl->setCertExtn(value, vlen, objid, objidlen, crit); + xExtn = xSanImpl.get(); + } + else + { + rtl::Reference<CertificateExtension_XmlSecImpl> xSecImpl( + new CertificateExtension_XmlSecImpl); + xSecImpl->setCertExtn(value, vlen, objid, objidlen, crit); + xExtn = xSecImpl.get(); + } + break; + } + } + + return xExtn; + } else { + return nullptr ; + } +} + + +css::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_NssImpl::getEncoded() { + if( m_pCert != nullptr && m_pCert->derCert.len > 0 ) { + return comphelper::arrayToSequence<sal_Int8>(m_pCert->derCert.data, m_pCert->derCert.len) ; + } else { + return css::uno::Sequence< sal_Int8 >(); + } +} + +//Helper methods +void X509Certificate_NssImpl::setCert( CERTCertificate* cert ) { + if( m_pCert != nullptr ) { + CERT_DestroyCertificate( m_pCert ) ; + m_pCert = nullptr ; + } + + if( cert != nullptr ) { + m_pCert = CERT_DupCertificate( cert ) ; + } +} + +const CERTCertificate* X509Certificate_NssImpl::getNssCert() const { + if( m_pCert != nullptr ) { + return m_pCert ; + } else { + return nullptr ; + } +} + +void X509Certificate_NssImpl::setRawCert( const css::uno::Sequence< sal_Int8 >& rawCert ) { + CERTCertificate* cert ; + SECItem certItem ; + + certItem.data = reinterpret_cast<unsigned char *>(const_cast<sal_Int8 *>(rawCert.getConstArray())); + certItem.len = rawCert.getLength() ; + + cert = CERT_DecodeDERCertificate( &certItem, PR_TRUE, nullptr ) ; + if( cert == nullptr ) + throw css::uno::RuntimeException() ; + + if( m_pCert != nullptr ) { + CERT_DestroyCertificate( m_pCert ) ; + m_pCert = nullptr ; + } + + m_pCert = cert ; +} + +SECKEYPrivateKey* X509Certificate_NssImpl::getPrivateKey() +{ + if (m_pCert && m_pCert->slot) + { + SECKEYPrivateKey* pPrivateKey = PK11_FindPrivateKeyFromCert(m_pCert->slot, m_pCert, nullptr); + if (pPrivateKey) + return pPrivateKey; + pPrivateKey = PK11_FindKeyByDERCert(m_pCert->slot, m_pCert, nullptr); + if (pPrivateKey) + { + SAL_INFO("xmlsecurity.xmlsec", "fallback from PK11_FindPrivateKeyFromCert to PK11_FindKeyByDERCert needed"); + return pPrivateKey; + } + SAL_WARN("xmlsecurity.xmlsec", "X509Certificate_NssImpl::getPrivateKey() cannot find private key"); + } + return nullptr; +} + +static OUString getAlgorithmDescription(SECAlgorithmID const *aid) +{ + SECOidTag tag; + tag = SECOID_GetAlgorithmTag(aid); + + const char *pDesc = SECOID_FindOIDTagDescription(tag); + + return OUString::createFromAscii( pDesc ) ; +} + +static css::uno::Sequence< sal_Int8 > getThumbprint(CERTCertificate const *pCert, SECOidTag id) +{ + if( pCert != nullptr ) + { + SECStatus rv; + unsigned char fingerprint[32]; + int length = 0; + switch (id) + { + case SEC_OID_MD5: + length = MD5_LENGTH; + break; + case SEC_OID_SHA1: + length = SHA1_LENGTH; + break; + case SEC_OID_SHA256: + length = SHA256_LENGTH; + break; + default: + break; + } + + memset(fingerprint, 0, sizeof fingerprint); + rv = PK11_HashBuf(id, fingerprint, pCert->derCert.data, pCert->derCert.len); + if(rv == SECStatus::SECSuccess) + { + return comphelper::arrayToSequence<sal_Int8>(fingerprint, length); + } + } + return css::uno::Sequence< sal_Int8 >(); +} + +OUString SAL_CALL X509Certificate_NssImpl::getSubjectPublicKeyAlgorithm() +{ + if( m_pCert != nullptr ) + { + return getAlgorithmDescription(&(m_pCert->subjectPublicKeyInfo.algorithm)); + } + else + { + return OUString() ; + } +} + +css::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_NssImpl::getSubjectPublicKeyValue() +{ + if( m_pCert != nullptr ) + { + SECItem spk = m_pCert->subjectPublicKeyInfo.subjectPublicKey; + DER_ConvertBitString(&spk); + + if ( spk.len>0) + { + return comphelper::arrayToSequence<sal_Int8>(spk.data, spk.len) ; + } + } + + return css::uno::Sequence< sal_Int8 >(); +} + +OUString SAL_CALL X509Certificate_NssImpl::getSignatureAlgorithm() +{ + if( m_pCert != nullptr ) + { + return getAlgorithmDescription(&(m_pCert->signature)); + } + else + { + return OUString() ; + } +} + +svl::crypto::SignatureMethodAlgorithm X509Certificate_NssImpl::getSignatureMethodAlgorithm() +{ + svl::crypto::SignatureMethodAlgorithm nRet = svl::crypto::SignatureMethodAlgorithm::RSA; + + if (!m_pCert) + return nRet; + + SECOidTag eTag = SECOID_GetAlgorithmTag(&m_pCert->subjectPublicKeyInfo.algorithm); + if (eTag == SEC_OID_ANSIX962_EC_PUBLIC_KEY) + nRet = svl::crypto::SignatureMethodAlgorithm::ECDSA; + + return nRet; +} + +css::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_NssImpl::getSHA1Thumbprint() +{ + return getThumbprint(m_pCert, SEC_OID_SHA1); +} + +css::uno::Sequence<sal_Int8> X509Certificate_NssImpl::getSHA256Thumbprint() +{ + return getThumbprint(m_pCert, SEC_OID_SHA256); +} + +css::uno::Sequence< sal_Int8 > SAL_CALL X509Certificate_NssImpl::getMD5Thumbprint() +{ + return getThumbprint(m_pCert, SEC_OID_MD5); +} + +css::security::CertificateKind SAL_CALL X509Certificate_NssImpl::getCertificateKind() +{ + return css::security::CertificateKind_X509; +} + +sal_Int32 SAL_CALL X509Certificate_NssImpl::getCertificateUsage( ) +{ + SECStatus rv; + SECItem tmpitem; + sal_Int32 usage; + + rv = CERT_FindKeyUsageExtension(m_pCert, &tmpitem); + if ( rv == SECStatus::SECSuccess ) + { + usage = tmpitem.data[0]; + PORT_Free(tmpitem.data); + tmpitem.data = nullptr; + } + else + { + usage = KU_ALL; + } + + /* + * to make the nss implementation compatible with MSCrypto, + * the following usage is ignored + * + * + if ( CERT_GovtApprovedBitSet(m_pCert) ) + { + usage |= KU_NS_GOVT_APPROVED; + } + */ + + return usage; +} + +/* XServiceInfo */ +OUString SAL_CALL X509Certificate_NssImpl::getImplementationName() +{ + return "com.sun.star.xml.security.gpg.XCertificate_NssImpl"; +} + +/* XServiceInfo */ +sal_Bool SAL_CALL X509Certificate_NssImpl::supportsService(const OUString& serviceName) +{ + return cppu::supportsService(this, serviceName); +} + +/* XServiceInfo */ +css::uno::Sequence<OUString> SAL_CALL X509Certificate_NssImpl::getSupportedServiceNames() { return { OUString() }; } + +namespace xmlsecurity { + +// based on some guesswork and: +// https://datatracker.ietf.org/doc/html/rfc1485 +// https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-certnametostra#CERT_X500_NAME_STR +// the main problem appears to be that in values " is escaped as "" vs. \" +static OUString CompatDNCryptoAPI(std::u16string_view rDN) +{ + OUStringBuffer buf(rDN.size()); + enum { DEFAULT, INVALUE, INQUOTE } state(DEFAULT); + for (size_t i = 0; i < rDN.size(); ++i) + { + if (state == DEFAULT) + { + buf.append(rDN[i]); + if (rDN[i] == '=') + { + if (rDN.size() == i+1) + { + break; // invalid? + } + else if (rDN[i+1] == '"') + { + buf.append(rDN[i+1]); + ++i; + state = INQUOTE; + } + else + { + state = INVALUE; + } + } + } + else if (state == INVALUE) + { + if (rDN[i] == '+' || rDN[i] == ',' || rDN[i] == ';') + { + state = DEFAULT; + } + buf.append(rDN[i]); + } + else + { + assert(state == INQUOTE); + if (rDN[i] == '"') + { + if (rDN.size() != i+1 && rDN[i+1] == '"') + { + buf.append(OUString::Concat("\\") + OUStringChar(rDN[i+1])); + ++i; + } + else + { + buf.append(rDN[i]); + state = DEFAULT; + } + } + else + { + buf.append(rDN[i]); + } + } + } + return buf.makeStringAndClear(); +} + +bool EqualDistinguishedNames( + std::u16string_view const rName1, std::u16string_view const rName2, + EqualMode const eMode) +{ + if (eMode == COMPAT_BOTH && !rName1.empty() && rName1 == rName2) + { // handle case where both need to be converted + return true; + } + CERTName *const pName1(CERT_AsciiToName(OUStringToOString(rName1, RTL_TEXTENCODING_UTF8).getStr())); + if (pName1 == nullptr) + { + return false; + } + CERTName *const pName2(CERT_AsciiToName(OUStringToOString(rName2, RTL_TEXTENCODING_UTF8).getStr())); + bool ret(false); + if (pName2) + { + ret = (CERT_CompareName(pName1, pName2) == SECEqual); + CERT_DestroyName(pName2); + } + if (!ret && eMode == COMPAT_2ND) + { + CERTName *const pName2Compat(CERT_AsciiToName(OUStringToOString( + CompatDNCryptoAPI(rName2), RTL_TEXTENCODING_UTF8).getStr())); + if (pName2Compat == nullptr) + { + CERT_DestroyName(pName1); + return false; + } + ret = CERT_CompareName(pName1, pName2Compat) == SECEqual; + CERT_DestroyName(pName2Compat); + } + CERT_DestroyName(pName1); + return ret; +} + +} // namespace xmlsecurity + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.hxx b/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.hxx new file mode 100644 index 0000000000..9ad50f12ba --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.hxx @@ -0,0 +1,97 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <sal/config.h> +#include <rtl/ustring.hxx> +#include <cppuhelper/implbase.hxx> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/security/CertificateKind.hpp> +#include <com/sun/star/security/XCertificate.hpp> + +#include <certificate.hxx> +#include <certt.h> +#include <keythi.h> + +class X509Certificate_NssImpl : public ::cppu::WeakImplHelper< + css::security::XCertificate , + css::lang::XServiceInfo > , public xmlsecurity::Certificate +{ + private: + CERTCertificate* m_pCert; + + public: + X509Certificate_NssImpl() ; + virtual ~X509Certificate_NssImpl() override ; + + //Methods from XCertificate + virtual sal_Int16 SAL_CALL getVersion( ) override ; + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSerialNumber( ) override ; + + virtual OUString SAL_CALL getIssuerName( ) override ; + virtual OUString SAL_CALL getSubjectName( ) override ; + + virtual css::util::DateTime SAL_CALL getNotValidBefore( ) override ; + virtual css::util::DateTime SAL_CALL getNotValidAfter( ) override ; + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getIssuerUniqueID( ) override ; + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSubjectUniqueID( ) override ; + + virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificateExtension > > SAL_CALL getExtensions( ) override ; + + virtual css::uno::Reference< css::security::XCertificateExtension > SAL_CALL findCertificateExtension( const css::uno::Sequence< sal_Int8 >& oid ) override ; + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getEncoded( ) override ; + + virtual OUString SAL_CALL getSubjectPublicKeyAlgorithm() override ; + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSubjectPublicKeyValue() override ; + + virtual OUString SAL_CALL getSignatureAlgorithm() override ; + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSHA1Thumbprint() override ; + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getMD5Thumbprint() override ; + virtual css::security::CertificateKind SAL_CALL getCertificateKind() override; + + virtual sal_Int32 SAL_CALL getCertificateUsage( ) override ; + + /// @see xmlsecurity::Certificate::getSHA256Thumbprint(). + virtual css::uno::Sequence<sal_Int8> getSHA256Thumbprint() override; + + /// @see xmlsecurity::Certificate::getSignatureMethodAlgorithm(). + virtual svl::crypto::SignatureMethodAlgorithm getSignatureMethodAlgorithm() override; + + //Helper methods + void setCert( CERTCertificate* cert ) ; + const CERTCertificate* getNssCert() const ; + + /// @throws css::uno::RuntimeException + void setRawCert( const css::uno::Sequence< sal_Int8 >& rawCert ) ; + SECKEYPrivateKey* getPrivateKey(); + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override; + virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override; +} ; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/xmlsecuritycontext_nssimpl.cxx b/xmlsecurity/source/xmlsec/nss/xmlsecuritycontext_nssimpl.cxx new file mode 100644 index 0000000000..9ccf0ab982 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/xmlsecuritycontext_nssimpl.cxx @@ -0,0 +1,150 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> +#include <vector> +#include <cppuhelper/implbase.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/xml/crypto/XXMLSecurityContext.hpp> +#include <o3tl/safeint.hxx> + +namespace com::sun::star::uno { class XComponentContext; } + +using namespace ::com::sun::star; +using namespace ::com::sun::star::lang ; + +using ::com::sun::star::xml::crypto::XSecurityEnvironment ; +using ::com::sun::star::xml::crypto::XXMLSecurityContext ; + +namespace { + +class XMLSecurityContext_NssImpl + : public ::cppu::WeakImplHelper<xml::crypto::XXMLSecurityContext, lang::XServiceInfo> +{ +private: + std::vector<uno::Reference<xml::crypto::XSecurityEnvironment>> m_vSecurityEnvironments; + + sal_Int32 m_nDefaultEnvIndex; + +public: + XMLSecurityContext_NssImpl(); + + //XXMLSecurityContext + virtual sal_Int32 SAL_CALL addSecurityEnvironment( + const uno::Reference<xml::crypto::XSecurityEnvironment>& aSecurityEnvironment) override; + + virtual ::sal_Int32 SAL_CALL getSecurityEnvironmentNumber() override; + + virtual uno::Reference<xml::crypto::XSecurityEnvironment> + SAL_CALL getSecurityEnvironmentByIndex(::sal_Int32 index) override; + + virtual uno::Reference<xml::crypto::XSecurityEnvironment> + SAL_CALL getSecurityEnvironment() override; + + virtual ::sal_Int32 SAL_CALL getDefaultSecurityEnvironmentIndex() override; + + virtual void SAL_CALL setDefaultSecurityEnvironmentIndex(sal_Int32 nDefaultEnvIndex) override; + + //XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + + virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override; + + virtual uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override; +}; + +} + +XMLSecurityContext_NssImpl::XMLSecurityContext_NssImpl() + : m_nDefaultEnvIndex(-1) +{ +} + +sal_Int32 SAL_CALL XMLSecurityContext_NssImpl::addSecurityEnvironment( + const uno::Reference< xml::crypto::XSecurityEnvironment >& aSecurityEnvironment) +{ + if( !aSecurityEnvironment.is() ) + { + throw uno::RuntimeException() ; + } + + m_vSecurityEnvironments.push_back( aSecurityEnvironment ); + + return m_vSecurityEnvironments.size() - 1 ; +} + + +sal_Int32 SAL_CALL XMLSecurityContext_NssImpl::getSecurityEnvironmentNumber( ) +{ + return m_vSecurityEnvironments.size(); +} + +uno::Reference< xml::crypto::XSecurityEnvironment > SAL_CALL + XMLSecurityContext_NssImpl::getSecurityEnvironmentByIndex( sal_Int32 index ) +{ + if (index < 0 || o3tl::make_unsigned(index) >= m_vSecurityEnvironments.size()) + throw uno::RuntimeException(); + + uno::Reference< xml::crypto::XSecurityEnvironment > xSecurityEnvironment = m_vSecurityEnvironments[index]; + return xSecurityEnvironment; +} + +uno::Reference< xml::crypto::XSecurityEnvironment > SAL_CALL + XMLSecurityContext_NssImpl::getSecurityEnvironment( ) +{ + if (m_nDefaultEnvIndex < 0 || o3tl::make_unsigned(m_nDefaultEnvIndex) >= m_vSecurityEnvironments.size()) + throw uno::RuntimeException(); + + return getSecurityEnvironmentByIndex(m_nDefaultEnvIndex); +} + +sal_Int32 SAL_CALL XMLSecurityContext_NssImpl::getDefaultSecurityEnvironmentIndex( ) +{ + return m_nDefaultEnvIndex ; +} + +void SAL_CALL XMLSecurityContext_NssImpl::setDefaultSecurityEnvironmentIndex( sal_Int32 nDefaultEnvIndex ) +{ + m_nDefaultEnvIndex = nDefaultEnvIndex; +} + +/* XServiceInfo */ +OUString SAL_CALL XMLSecurityContext_NssImpl::getImplementationName() { + return "com.sun.star.xml.crypto.XMLSecurityContext"; +} + +/* XServiceInfo */ +sal_Bool SAL_CALL XMLSecurityContext_NssImpl::supportsService( const OUString& serviceName) { + return cppu::supportsService(this, serviceName); +} + +/* XServiceInfo */ +uno::Sequence< OUString > SAL_CALL XMLSecurityContext_NssImpl::getSupportedServiceNames() { + return { "com.sun.star.xml.crypto.XMLSecurityContext" }; +} + +extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface* +com_sun_star_xml_crypto_XMLSecurityContext_get_implementation( + uno::XComponentContext* /*pCtx*/, uno::Sequence<uno::Any> const& /*rSeq*/) +{ + return cppu::acquire(new XMLSecurityContext_NssImpl); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/xmlsignature_nssimpl.cxx b/xmlsecurity/source/xmlsec/nss/xmlsignature_nssimpl.cxx new file mode 100644 index 0000000000..4c5cc4b418 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/xmlsignature_nssimpl.cxx @@ -0,0 +1,321 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> +#include <xmlsec-wrapper.h> + +#include <xmlsec/nss/x509.h> + +#include <xmlelementwrapper_xmlsecimpl.hxx> +#include <xmlsec/xmlstreamio.hxx> +#include <xmlsec/errorcallback.hxx> + +#include "securityenvironment_nssimpl.hxx" + +#include <comphelper/servicehelper.hxx> +#include <sal/log.hxx> + +#include <com/sun/star/xml/crypto/XXMLSignature.hpp> +#include <memory> + +namespace com::sun::star::uno { class XComponentContext; } + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno ; +using namespace ::com::sun::star::lang ; + +using ::com::sun::star::xml::wrapper::XXMLElementWrapper ; +using ::com::sun::star::xml::crypto::XSecurityEnvironment ; +using ::com::sun::star::xml::crypto::XXMLSignature ; +using ::com::sun::star::xml::crypto::XXMLSignatureTemplate ; +using ::com::sun::star::xml::crypto::XXMLSecurityContext ; +using ::com::sun::star::xml::crypto::XUriBinding ; + +namespace std +{ +template <> struct default_delete<xmlSecKeysMngr> +{ + void operator()(xmlSecKeysMngrPtr ptr) { SecurityEnvironment_NssImpl::destroyKeysManager(ptr); } +}; +template <> struct default_delete<xmlSecDSigCtx> +{ + void operator()(xmlSecDSigCtxPtr ptr) { xmlSecDSigCtxDestroy(ptr); } +}; +} + +namespace { + +class XMLSignature_NssImpl + : public ::cppu::WeakImplHelper<xml::crypto::XXMLSignature, lang::XServiceInfo> +{ +public: + explicit XMLSignature_NssImpl(); + + //Methods from XXMLSignature + virtual uno::Reference<xml::crypto::XXMLSignatureTemplate> SAL_CALL + generate(const uno::Reference<xml::crypto::XXMLSignatureTemplate>& aTemplate, + const uno::Reference<xml::crypto::XSecurityEnvironment>& aEnvironment) override; + + virtual uno::Reference<xml::crypto::XXMLSignatureTemplate> SAL_CALL + validate(const uno::Reference<xml::crypto::XXMLSignatureTemplate>& aTemplate, + const uno::Reference<xml::crypto::XXMLSecurityContext>& aContext) override; + + //Methods from XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + + virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override; + + virtual uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override; +}; + +} + +XMLSignature_NssImpl::XMLSignature_NssImpl() { +} + +/* XXMLSignature */ +Reference< XXMLSignatureTemplate > +SAL_CALL XMLSignature_NssImpl::generate( + const Reference< XXMLSignatureTemplate >& aTemplate , + const Reference< XSecurityEnvironment >& aEnvironment +) +{ + xmlNodePtr pNode = nullptr ; + + if( !aTemplate.is() ) + throw RuntimeException() ; + + if( !aEnvironment.is() ) + throw RuntimeException() ; + + //Get the xml node + Reference< XXMLElementWrapper > xElement = aTemplate->getTemplate() ; + if( !xElement.is() ) { + throw RuntimeException() ; + } + + XMLElementWrapper_XmlSecImpl* pElement + = dynamic_cast<XMLElementWrapper_XmlSecImpl*>(xElement.get()); + if( pElement == nullptr ) { + throw RuntimeException() ; + } + + pNode = pElement->getNativeElement() ; + + //Get the stream/URI binding + Reference< XUriBinding > xUriBinding = aTemplate->getBinding() ; + if( xUriBinding.is() ) { + //Register the stream input callbacks into libxml2 + if( xmlRegisterStreamInputCallbacks( xUriBinding ) < 0 ) + throw RuntimeException() ; + } + + //Get Keys Manager + + // the key manager should be retrieved from SecurityEnvironment, instead of SecurityContext + SecurityEnvironment_NssImpl* pSecEnv + = dynamic_cast<SecurityEnvironment_NssImpl*>(aEnvironment.get()); + if( pSecEnv == nullptr ) + throw RuntimeException() ; + + setErrorRecorder(); + + std::unique_ptr<xmlSecKeysMngr> pMngr(pSecEnv->createKeysManager()); + if( !pMngr ) { + throw RuntimeException() ; + } + + //Create Signature context + std::unique_ptr<xmlSecDSigCtx> pDsigCtx(xmlSecDSigCtxCreate(pMngr.get())); + if( pDsigCtx == nullptr ) + { + //throw XMLSignatureException() ; + clearErrorRecorder(); + return aTemplate; + } + + //Sign the template + if( xmlSecDSigCtxSign( pDsigCtx.get() , pNode ) == 0 ) + { + if (pDsigCtx->status == xmlSecDSigStatusSucceeded) + aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED); + else + aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_UNKNOWN); + } + else + { + aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_UNKNOWN); + } + + //Unregistered the stream/URI binding + if( xUriBinding.is() ) + xmlUnregisterStreamInputCallbacks() ; + + clearErrorRecorder(); + return aTemplate ; +} + +/* XXMLSignature */ +Reference< XXMLSignatureTemplate > +SAL_CALL XMLSignature_NssImpl::validate( + const Reference< XXMLSignatureTemplate >& aTemplate , + const Reference< XXMLSecurityContext >& aSecurityCtx +) { + xmlNodePtr pNode = nullptr ; + //sal_Bool valid ; + + if( !aTemplate.is() ) + throw RuntimeException() ; + + if( !aSecurityCtx.is() ) + throw RuntimeException() ; + + //Get the xml node + Reference< XXMLElementWrapper > xElement = aTemplate->getTemplate() ; + if( !xElement.is() ) + throw RuntimeException() ; + + XMLElementWrapper_XmlSecImpl* pElement + = dynamic_cast<XMLElementWrapper_XmlSecImpl*>(xElement.get()); + if( pElement == nullptr ) + throw RuntimeException() ; + + pNode = pElement->getNativeElement() ; + + //Get the stream/URI binding + Reference< XUriBinding > xUriBinding = aTemplate->getBinding() ; + if( xUriBinding.is() ) { + //Register the stream input callbacks into libxml2 + if( xmlRegisterStreamInputCallbacks( xUriBinding ) < 0 ) + throw RuntimeException() ; + } + + setErrorRecorder(); + + sal_Int32 nSecurityEnvironment = aSecurityCtx->getSecurityEnvironmentNumber(); + sal_Int32 i; + + for (i=0; i<nSecurityEnvironment; ++i) + { + Reference< XSecurityEnvironment > aEnvironment = aSecurityCtx->getSecurityEnvironmentByIndex(i); + + //Get Keys Manager + SecurityEnvironment_NssImpl* pSecEnv + = dynamic_cast<SecurityEnvironment_NssImpl*>(aEnvironment.get()); + if( pSecEnv == nullptr ) + throw RuntimeException() ; + + std::unique_ptr<xmlSecKeysMngr> pMngr(pSecEnv->createKeysManager()); + if( !pMngr ) { + throw RuntimeException() ; + } + + //Create Signature context + std::unique_ptr<xmlSecDSigCtx> pDsigCtx(xmlSecDSigCtxCreate(pMngr.get())); + if( pDsigCtx == nullptr ) + { + clearErrorRecorder(); + return aTemplate; + } + + // We do certificate verification ourselves. + pDsigCtx->keyInfoReadCtx.flags |= XMLSEC_KEYINFO_FLAGS_X509DATA_DONT_VERIFY_CERTS; + + // limit possible key data to valid X509 certificates only, no KeyValues + if (xmlSecPtrListAdd(&(pDsigCtx->keyInfoReadCtx.enabledKeyData), BAD_CAST xmlSecNssKeyDataX509GetKlass()) < 0) + throw RuntimeException("failed to limit allowed key data"); + + xmlBufferPtr pBuf = xmlBufferCreate(); + xmlNodeDump(pBuf, nullptr, pNode, 0, 0); + SAL_INFO("xmlsecurity.xmlsec", "xmlSecDSigCtxVerify input XML node is '" + << reinterpret_cast<const char*>(xmlBufferContent(pBuf)) + << "'"); + xmlBufferFree(pBuf); + + //Verify signature + int rs = xmlSecDSigCtxVerify( pDsigCtx.get() , pNode ); + + // Also verify manifest: this is empty for ODF, but contains everything (except signature metadata) for OOXML. + xmlSecSize nReferenceCount = xmlSecPtrListGetSize(&pDsigCtx->manifestReferences); + // Require that all manifest references are also good. + xmlSecSize nReferenceGood = 0; + for (xmlSecSize nReference = 0; nReference < nReferenceCount; ++nReference) + { + xmlSecDSigReferenceCtxPtr pReference = static_cast<xmlSecDSigReferenceCtxPtr>(xmlSecPtrListGetItem(&pDsigCtx->manifestReferences, nReference)); + if (pReference) + { + if (pReference->status == xmlSecDSigStatusSucceeded) + ++nReferenceGood; + } + } + SAL_INFO("xmlsecurity.xmlsec", "xmlSecDSigCtxVerify status " << pDsigCtx->status << ", references good " << nReferenceGood << " of " << nReferenceCount); + + if (rs == 0 && pDsigCtx->status == xmlSecDSigStatusSucceeded && nReferenceCount == nReferenceGood) + { + aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED); + break; + } + else + { + aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_UNKNOWN); + } + } + + + //Unregistered the stream/URI binding + if( xUriBinding.is() ) + xmlUnregisterStreamInputCallbacks() ; + + //return valid ; + clearErrorRecorder(); + return aTemplate; +} + +/* XServiceInfo */ +OUString SAL_CALL XMLSignature_NssImpl::getImplementationName() +{ + return "com.sun.star.xml.crypto.XMLSignature"; +} + +/* XServiceInfo */ +sal_Bool SAL_CALL XMLSignature_NssImpl::supportsService(const OUString& rServiceName) +{ + const css::uno::Sequence<OUString> aServiceNames = getSupportedServiceNames(); + for (OUString const & rCurrentServiceName : aServiceNames) + { + if (rCurrentServiceName == rServiceName) + return true; + } + return false; +} + +/* XServiceInfo */ +Sequence<OUString> SAL_CALL XMLSignature_NssImpl::getSupportedServiceNames() +{ + return { "com.sun.star.xml.crypto.XMLSignature" }; +} + +extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface* +com_sun_star_xml_crypto_XMLSignature_get_implementation(uno::XComponentContext* /*pCtx*/, + uno::Sequence<uno::Any> const& /*rSeq*/) +{ + return cppu::acquire(new XMLSignature_NssImpl); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/saxhelper.cxx b/xmlsecurity/source/xmlsec/saxhelper.cxx new file mode 100644 index 0000000000..ff576db496 --- /dev/null +++ b/xmlsecurity/source/xmlsec/saxhelper.cxx @@ -0,0 +1,364 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include <string_view> + +#include <rtl/ustring.hxx> + +#include <xmlsec/saxhelper.hxx> +#include <libxml/parserInternals.h> + +#include <com/sun/star/xml/csax/XMLAttribute.hpp> +#include <com/sun/star/uno/Sequence.hxx> + +#ifndef XMLSEC_NO_XSLT +#include "libxslt/xslt.h" +#endif + +/** + * The return value is NULL terminated. The application has the responsibility to + * deallocate the return value. + */ +static xmlChar* ous_to_xmlstr( std::u16string_view oustr ) +{ + OString ostr = OUStringToOString( oustr , RTL_TEXTENCODING_UTF8 ) ; + return xmlStrndup( reinterpret_cast<xmlChar const *>(ostr.getStr()), static_cast<int>(ostr.getLength()) ) ; +} + +/** + * The return value is NULL terminated. The application has the responsibility to + * deallocate the return value. + */ +static xmlChar* ous_to_nxmlstr( std::u16string_view oustr, int& length ) +{ + OString ostr = OUStringToOString( oustr , RTL_TEXTENCODING_UTF8 ) ; + length = ostr.getLength(); + + return xmlStrndup( reinterpret_cast<xmlChar const *>(ostr.getStr()), length ) ; +} + +/** + * The return value and the referenced value must be NULL terminated. + * The application has the responsibility to deallocate the return value. + */ +static const xmlChar** attrlist_to_nxmlstr( const css::uno::Sequence< css::xml::csax::XMLAttribute >& aAttributes ) +{ + xmlChar* attname = nullptr ; + xmlChar* attvalue = nullptr ; + const xmlChar** attrs = nullptr ; + + sal_Int32 nLength = aAttributes.getLength(); + + if( nLength != 0 ) + { + attrs = static_cast<const xmlChar**>(xmlMalloc( ( nLength * 2 + 2 ) * sizeof( xmlChar* ) )); + } + else + { + return nullptr ; + } + + int i = 0; + for( const auto& rAttr : aAttributes ) + { + attname = ous_to_xmlstr( rAttr.sName ) ; + attvalue = ous_to_xmlstr( rAttr.sValue ) ; + + if( attname != nullptr && attvalue != nullptr ) + { + attrs[i++] = attname ; + attrs[i++] = attvalue ; + attrs[i] = nullptr ; + attrs[i+1] = nullptr ; + } + else + { + if( attname != nullptr ) + xmlFree( attname ) ; + if( attvalue != nullptr ) + xmlFree( attvalue ) ; + } + } + + return attrs ; +} + +/** + * Constructor + * + * In this constructor, a libxml sax parser context is initialized. a libxml + * default sax handler is initialized with the context. + */ +SAXHelper::SAXHelper( ) + : m_pParserCtxt( nullptr ), + m_pSaxHandler( nullptr ) +{ + xmlInitParser() ; + LIBXML_TEST_VERSION ; + + /* + * compile error: + * xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS ; + */ + xmlSubstituteEntitiesDefault(0) ; + +#ifndef XMLSEC_NO_XSLT + xmlIndentTreeOutput = 1 ; +#endif /* XMLSEC_NO_XSLT */ + + m_pParserCtxt = xmlNewParserCtxt() ; + + if( m_pParserCtxt == nullptr ) + { +// see issue i74334, we cannot call xmlCleanupParser when libxml is still used +// in other parts of the office. +// xmlCleanupParser() ; +// and neither can we call xsltCleanupGlobals() + throw css::uno::RuntimeException() ; + } + + xmlSAXVersion(m_pParserCtxt->sax, 1); + + if (m_pParserCtxt->inputTab != nullptr) + { + m_pParserCtxt->inputTab[0] = nullptr ; + } + + if( m_pParserCtxt->sax == nullptr ) + { + xmlFreeParserCtxt( m_pParserCtxt ) ; + +// see issue i74334, we cannot call xmlCleanupParser when libxml is still used +// in other parts of the office. +// xmlCleanupParser() ; +// and neither can we call xsltCleanupGlobals() + m_pParserCtxt = nullptr ; + throw css::uno::RuntimeException() ; + } + else + { + m_pSaxHandler = m_pParserCtxt->sax ; + + //Adjust the context + m_pParserCtxt->recovery = 1 ; + } +} + +/** + * Destructor + * + * In this destructor, a libxml sax parser context is destructed. The XML tree + * in the context is not deallocated because the tree is bind with a document + * model by the setTargetDocument method, which delegate the target document to + * destruct the xml tree. + */ +SAXHelper::~SAXHelper() { + if( m_pParserCtxt != nullptr ) + { + /* + * In the situation that no object refer the Document, this destructor + * must deallocate the Document memory + */ + if( m_pSaxHandler == m_pParserCtxt->sax ) + { + m_pSaxHandler = nullptr ; + } + + xmlFreeParserCtxt( m_pParserCtxt ) ; + m_pParserCtxt = nullptr ; + } + + if( m_pSaxHandler != nullptr ) + { + xmlFree( m_pSaxHandler ) ; + m_pSaxHandler = nullptr ; + } +// see issue i74334, we cannot call xmlCleanupParser when libxml is still used +// in other parts of the office. +// xmlCleanupParser() ; +} + + +void SAXHelper::setCurrentNode(const xmlNodePtr pNode) +{ + /* + * This is really a black trick. + * When the current node is replaced, the nodeTab + * stack's top has to been replaced with the same + * node, in order to make compatibility. + */ + m_pParserCtxt->nodeTab[m_pParserCtxt->nodeNr - 1] + = m_pParserCtxt->node + = pNode; +} + + +/** + * XDocumentHandler -- start an xml document + */ +void SAXHelper::startDocument() +{ + if( m_pParserCtxt == nullptr) + { + throw css::uno::RuntimeException() ; + } + /* + * Adjust inputTab + */ + xmlParserInputPtr pInput = xmlNewInputStream( m_pParserCtxt ) ; + + if( m_pParserCtxt->inputTab != nullptr && m_pParserCtxt->inputMax != 0 ) + { + m_pParserCtxt->inputTab[0] = pInput ; + m_pParserCtxt->input = pInput ; + } + + m_pSaxHandler->startDocument( m_pParserCtxt ) ; + + if( m_pParserCtxt->myDoc == nullptr ) + { + throw css::uno::RuntimeException() ; + } +} + +/** + * XDocumentHandler -- end an xml document + */ +void SAXHelper::endDocument() +{ + m_pSaxHandler->endDocument( m_pParserCtxt ) ; +} + +/** + * XDocumentHandler -- start an xml element + */ +void SAXHelper::startElement( + std::u16string_view aName, + const css::uno::Sequence< css::xml::csax::XMLAttribute >& aAttributes ) +{ + const xmlChar* fullName = nullptr ; + const xmlChar** attrs = nullptr ; + + fullName = ous_to_xmlstr( aName ) ; + attrs = attrlist_to_nxmlstr( aAttributes ) ; + + if( fullName != nullptr || attrs != nullptr ) + { + m_pSaxHandler->startElement( m_pParserCtxt , fullName , attrs ) ; + } + + if( fullName != nullptr ) + { + xmlFree( const_cast<xmlChar*>(fullName) ) ; + fullName = nullptr ; + } + + if( attrs != nullptr ) + { + for( int i = 0 ; attrs[i] != nullptr ; ++i ) + { + xmlFree( const_cast<xmlChar*>(attrs[i]) ) ; + attrs[i] = nullptr ; + } + + xmlFree( static_cast<void*>(attrs) ) ; + attrs = nullptr ; + } +} + +/** + * XDocumentHandler -- end an xml element + */ +void SAXHelper::endElement( std::u16string_view aName ) +{ + xmlChar* fullname = ous_to_xmlstr( aName ) ; + m_pSaxHandler->endElement( m_pParserCtxt , fullname ) ; + + if( fullname != nullptr ) + { + xmlFree( fullname ) ; + fullname = nullptr ; + } +} + +/** + * XDocumentHandler -- an xml element or cdata characters + */ +void SAXHelper::characters( std::u16string_view aChars ) +{ + const xmlChar* chars = nullptr ; + int length = 0 ; + + chars = ous_to_nxmlstr( aChars, length ) ; + m_pSaxHandler->characters( m_pParserCtxt , chars , length ) ; + + if( chars != nullptr ) + { + xmlFree( const_cast<xmlChar*>(chars) ) ; + } +} + +/** + * XDocumentHandler -- ignorable xml white space + */ +void SAXHelper::ignorableWhitespace( std::u16string_view aWhitespaces ) +{ + const xmlChar* chars = nullptr ; + int length = 0 ; + + chars = ous_to_nxmlstr( aWhitespaces, length ) ; + m_pSaxHandler->ignorableWhitespace( m_pParserCtxt , chars , length ) ; + + if( chars != nullptr ) + { + xmlFree( const_cast<xmlChar*>(chars) ) ; + } +} + +/** + * XDocumentHandler -- preprocessing instruction + */ +void SAXHelper::processingInstruction( + std::u16string_view aTarget, + std::u16string_view aData ) +{ + xmlChar* target = nullptr ; + xmlChar* data = nullptr ; + + target = ous_to_xmlstr( aTarget ) ; + data = ous_to_xmlstr( aData ) ; + + m_pSaxHandler->processingInstruction( m_pParserCtxt , target , data ) ; + + if( target != nullptr ) + { + xmlFree( target ) ; + target = nullptr ; + } + + if( data != nullptr ) + { + xmlFree( data ) ; + data = nullptr ; + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/xmldocumentwrapper_xmlsecimpl.cxx b/xmlsecurity/source/xmlsec/xmldocumentwrapper_xmlsecimpl.cxx new file mode 100644 index 0000000000..918735d380 --- /dev/null +++ b/xmlsecurity/source/xmlsec/xmldocumentwrapper_xmlsecimpl.cxx @@ -0,0 +1,900 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include <osl/diagnose.h> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/xml/crypto/sax/XSAXEventKeeper.hpp> +#include <cppuhelper/supportsservice.hxx> +#include <xmlsec/xmldocumentwrapper_xmlsecimpl.hxx> +#include "xmlelementwrapper_xmlsecimpl.hxx" +#include <comphelper/attributelist.hxx> +#include <rtl/ref.hxx> + +#ifdef UNX +#define stricmp strcasecmp +#endif + +using namespace com::sun::star; + +#define STRXMLNS "xmlns" + +/* used by the recursiveDelete method */ +#define NODE_REMOVED 0 +#define NODE_NOTREMOVED 1 +#define NODE_STOPPED 2 + +XMLDocumentWrapper_XmlSecImpl::XMLDocumentWrapper_XmlSecImpl() + : m_nCurrentPosition(0) + , m_pStopAtNode(nullptr) + , m_pCurrentReservedNode(nullptr) + , m_nReservedNodeIndex(0) +{ + saxHelper.startDocument(); + m_pDocument = saxHelper.getDocument(); + + /* + * creates the virtual root element + */ + saxHelper.startElement(u"root", uno::Sequence<css::xml::csax::XMLAttribute>()); + + m_pRootElement = saxHelper.getCurrentNode(); + m_pCurrentElement = m_pRootElement; +} + +XMLDocumentWrapper_XmlSecImpl::~XMLDocumentWrapper_XmlSecImpl() +{ + saxHelper.endDocument(); + xmlFreeDoc(m_pDocument); +} + +void XMLDocumentWrapper_XmlSecImpl::getNextSAXEvent() +/****** XMLDocumentWrapper_XmlSecImpl/getNextSAXEvent ************************* + * + * NAME + * getNextSAXEvent -- Prepares the next SAX event to be manipulate + * + * FUNCTION + * When converting the document into SAX events, this method is used to + * decide the next SAX event to be generated. + * Two member variables are checked to make the decision, the + * m_pCurrentElement and the m_nCurrentPosition. + * The m_pCurrentElement represents the node which have been covered, and + * the m_nCurrentPosition represents the event which have been sent. + * For example, suppose that the m_pCurrentElement + * points to element A, and the m_nCurrentPosition equals to + * NODEPOSITION_STARTELEMENT, then the next SAX event should be the + * endElement for element A if A has no child, or startElement for the + * first child element of element A otherwise. + * The m_nCurrentPosition can be one of following values: + * NODEPOSITION_STARTELEMENT for startElement; + * NODEPOSITION_ENDELEMENT for endElement; + * NODEPOSITION_NORMAL for other SAX events; + ******************************************************************************/ +{ + OSL_ASSERT( m_pCurrentElement != nullptr ); + + /* + * Get the next event through tree order. + * + * if the current event is a startElement, then the next + * event depends on whether or not the current node has + * children. + */ + if (m_nCurrentPosition == NODEPOSITION_STARTELEMENT) + { + /* + * If the current node has children, then its first child + * should be next current node, and the next event will be + * startElement or characters(PI) based on that child's node + * type. Otherwise, the endElement of current node is the + * next event. + */ + if (m_pCurrentElement->children != nullptr) + { + m_pCurrentElement = m_pCurrentElement->children; + m_nCurrentPosition + = (m_pCurrentElement->type == XML_ELEMENT_NODE)? + NODEPOSITION_STARTELEMENT:NODEPOSITION_NORMAL; + } + else + { + m_nCurrentPosition = NODEPOSITION_ENDELEMENT; + } + } + /* + * if the current event is a not startElement, then the next + * event depends on whether or not the current node has + * following sibling. + */ + else if (m_nCurrentPosition == NODEPOSITION_ENDELEMENT || m_nCurrentPosition == NODEPOSITION_NORMAL) + { + xmlNodePtr pNextSibling = m_pCurrentElement->next; + + /* + * If the current node has following sibling, that sibling + * should be next current node, and the next event will be + * startElement or characters(PI) based on that sibling's node + * type. Otherwise, the endElement of current node's parent + * becomes the next event. + */ + if (pNextSibling != nullptr) + { + m_pCurrentElement = pNextSibling; + m_nCurrentPosition + = (m_pCurrentElement->type == XML_ELEMENT_NODE)? + NODEPOSITION_STARTELEMENT:NODEPOSITION_NORMAL; + } + else + { + m_pCurrentElement = m_pCurrentElement->parent; + m_nCurrentPosition = NODEPOSITION_ENDELEMENT; + } + } +} + +void XMLDocumentWrapper_XmlSecImpl::sendStartElement( + const uno::Reference< css::xml::sax::XDocumentHandler >& xHandler, + const uno::Reference< css::xml::sax::XDocumentHandler >& xHandler2, + const xmlNodePtr pNode) +/****** XMLDocumentWrapper_XmlSecImpl/sendStartElement ************************ + * + * NAME + * sendStartElement -- Constructs a startElement SAX event + * + * FUNCTION + * Used when converting the document into SAX event stream. + * This method constructs a startElement SAX event for a particular + * element, then calls the startElement methods of the XDocumentHandlers. + * + * INPUTS + * xHandler - the first XDocumentHandler interface to receive the + * startElement SAX event. It can be NULL. + * xHandler2 - the second XDocumentHandler interface to receive the + * startElement SAX event. It can't be NULL. + * pNode - the node on which the startElement should be generated. + * This node must be an element type. + ******************************************************************************/ +{ + rtl::Reference<comphelper::AttributeList> pAttributeList = new comphelper::AttributeList(); + + xmlNsPtr pNsDef = pNode->nsDef; + + while (pNsDef != nullptr) + { + const xmlChar* pNsPrefix = pNsDef->prefix; + const xmlChar* pNsHref = pNsDef->href; + + if (pNsDef->prefix == nullptr) + { + pAttributeList->AddAttribute( + STRXMLNS, + OUString::fromUtf8(reinterpret_cast<char const *>(pNsHref))); + } + else + { + pAttributeList->AddAttribute( + STRXMLNS ":" + +OUString::fromUtf8(reinterpret_cast<char const *>(pNsPrefix)), + OUString::fromUtf8(reinterpret_cast<char const *>(pNsHref))); + } + + pNsDef = pNsDef->next; + } + + xmlAttrPtr pAttr = pNode->properties; + + while (pAttr != nullptr) + { + const xmlChar* pAttrName = pAttr->name; + xmlNsPtr pAttrNs = pAttr->ns; + + OUString ouAttrName; + if (pAttrNs == nullptr) + { + ouAttrName = OUString::fromUtf8(reinterpret_cast<char const *>(pAttrName)); + } + else + { + ouAttrName = OUString::fromUtf8(reinterpret_cast<char const *>(pAttrNs->prefix)) + + ":" + OUString::fromUtf8(reinterpret_cast<char const *>(pAttrName)); + } + + pAttributeList->AddAttribute( + ouAttrName, + OUString::fromUtf8(reinterpret_cast<char*>(pAttr->children->content))); + pAttr = pAttr->next; + } + + OString sNodeName = getNodeQName(pNode); + + if (xHandler.is()) + { + xHandler->startElement( + OUString::fromUtf8(sNodeName), + pAttributeList); + } + + xHandler2->startElement( + OUString::fromUtf8(sNodeName), + pAttributeList); +} + +void XMLDocumentWrapper_XmlSecImpl::sendEndElement( + const uno::Reference< css::xml::sax::XDocumentHandler >& xHandler, + const uno::Reference< css::xml::sax::XDocumentHandler >& xHandler2, + const xmlNodePtr pNode) +/****** XMLDocumentWrapper_XmlSecImpl/sendEndElement ************************** + * + * NAME + * sendEndElement -- Constructs an endElement SAX event + * + * FUNCTION + * Used when converting the document into SAX event stream. + * This method constructs an endElement SAX event for a particular + * element, then calls the endElement methods of the XDocumentHandlers. + * + * INPUTS + * xHandler - the first XDocumentHandler interface to receive the + * endElement SAX event. It can be NULL. + * xHandler2 - the second XDocumentHandler interface to receive the + * endElement SAX event. It can't be NULL. + * pNode - the node on which the endElement should be generated. + * This node must be an element type. + ******************************************************************************/ +{ + OString sNodeName = getNodeQName(pNode); + + if (xHandler.is()) + { + xHandler->endElement(OUString::fromUtf8(sNodeName)); + } + + xHandler2->endElement(OUString::fromUtf8(sNodeName)); +} + +void XMLDocumentWrapper_XmlSecImpl::sendNode( + const uno::Reference< css::xml::sax::XDocumentHandler >& xHandler, + const uno::Reference< css::xml::sax::XDocumentHandler >& xHandler2, + const xmlNodePtr pNode) +/****** XMLDocumentWrapper_XmlSecImpl/sendNode ******************************** + * + * NAME + * sendNode -- Constructs a characters SAX event or a + * processingInstruction SAX event + * + * FUNCTION + * Used when converting the document into SAX event stream. + * This method constructs a characters SAX event or a + * processingInstructionfor SAX event based on the type of a particular + * element, then calls the corresponding methods of the XDocumentHandlers. + * + * INPUTS + * xHandler - the first XDocumentHandler interface to receive the + * SAX event. It can be NULL. + * xHandler2 - the second XDocumentHandler interface to receive the + * SAX event. It can't be NULL. + * pNode - the node on which the endElement should be generated. + * If it is a text node, then a characters SAX event is + * generated; if it is a PI node, then a + * processingInstructionfor SAX event is generated. + ******************************************************************************/ +{ + xmlElementType type = pNode->type; + + if (type == XML_TEXT_NODE) + { + if (xHandler.is()) + { + xHandler->characters(OUString::fromUtf8(reinterpret_cast<char*>(pNode->content))); + } + + xHandler2->characters(OUString::fromUtf8(reinterpret_cast<char*>(pNode->content))); + } + else if (type == XML_PI_NODE) + { + if (xHandler.is()) + { + xHandler->processingInstruction( + OUString::fromUtf8(reinterpret_cast<char const *>(pNode->name)), + OUString::fromUtf8(reinterpret_cast<char const *>(pNode->content))); + } + + xHandler2->processingInstruction( + OUString::fromUtf8(reinterpret_cast<char const *>(pNode->name)), + OUString::fromUtf8(reinterpret_cast<char*>(pNode->content))); + } +} + +OString XMLDocumentWrapper_XmlSecImpl::getNodeQName(const xmlNodePtr pNode) +/****** XMLDocumentWrapper_XmlSecImpl/getNodeQName **************************** + * + * NAME + * getNodeQName -- Retrieves the qualified name of a node + * + * INPUTS + * pNode - the node whose name will be retrieved + * + * RESULT + * name - the node's qualified name + ******************************************************************************/ +{ + OString sNodeName(reinterpret_cast<const char*>(pNode->name)); + if (pNode->ns != nullptr) + { + xmlNsPtr pNs = pNode->ns; + + if (pNs->prefix != nullptr) + { + OString sPrefix(reinterpret_cast<const char*>(pNs->prefix)); + sNodeName = sPrefix + ":" + sNodeName; + } + } + + return sNodeName; +} + +xmlNodePtr XMLDocumentWrapper_XmlSecImpl::checkElement( const uno::Reference< css::xml::wrapper::XXMLElementWrapper >& xXMLElement) +/****** XMLDocumentWrapper_XmlSecImpl/checkElement **************************** + * + * NAME + * checkElement -- Retrieves the node wrapped by an XXMLElementWrapper + * interface + * + * INPUTS + * xXMLElement - the XXMLElementWrapper interface wrapping a node + * + * RESULT + * node - the node wrapped in the XXMLElementWrapper interface + ******************************************************************************/ +{ + xmlNodePtr rc = nullptr; + + if (xXMLElement.is()) + { + XMLElementWrapper_XmlSecImpl* pElement + = dynamic_cast<XMLElementWrapper_XmlSecImpl*>(xXMLElement.get()); + + if( pElement == nullptr ) { + throw uno::RuntimeException() ; + } + + rc = pElement->getNativeElement(); + } + + return rc; +} + +sal_Int32 XMLDocumentWrapper_XmlSecImpl::recursiveDelete( + const xmlNodePtr pNode) +/****** XMLDocumentWrapper_XmlSecImpl/recursiveDelete ************************* + * + * NAME + * recursiveDelete -- Deletes a particular node with its branch. + * + * FUNCTION + * Deletes a particular node with its branch, while reserving the nodes + * (and their branches) listed in the m_aReservedNodes. + * The deletion process is performed in the tree order, that is, a node + * is deleted after its previous sibling node is deleted, a parent node + * is deleted after its branch is deleted. + * During the deletion process when the m_pStopAtNode is reached, the + * progress is interrupted at once. + * + * INPUTS + * pNode - the node to be deleted + * + * RESULT + * result - the result of the deletion process, can be one of following + * values: + * NODE_STOPPED - the process is interrupted by meeting the + * m_pStopAtNode + * NODE_NOTREMOVED - the pNode is not completely removed + * because there is its descendant in the + * m_aReservedNodes list + * NODE_REMOVED - the pNode and its branch are completely + * removed + * + * NOTES + * The node in the m_aReservedNodes list must be in the tree order, otherwise + * the result is unpredictable. + ******************************************************************************/ +{ + if (pNode == m_pStopAtNode) + { + return NODE_STOPPED; + } + + if (pNode != m_pCurrentReservedNode) + { + xmlNodePtr pChild = pNode->children; + + xmlNodePtr pNextSibling; + bool bIsRemoved = true; + sal_Int32 nResult; + + while( pChild != nullptr ) + { + pNextSibling = pChild->next; + nResult = recursiveDelete(pChild); + + switch (nResult) + { + case NODE_STOPPED: + return NODE_STOPPED; + case NODE_NOTREMOVED: + bIsRemoved = false; + break; + case NODE_REMOVED: + removeNode(pChild); + break; + default: + throw uno::RuntimeException(); + } + + pChild = pNextSibling; + } + + if (pNode == m_pCurrentElement) + { + bIsRemoved = false; + } + + return bIsRemoved?NODE_REMOVED:NODE_NOTREMOVED; + } + else + { + getNextReservedNode(); + return NODE_NOTREMOVED; + } +} + +void XMLDocumentWrapper_XmlSecImpl::getNextReservedNode() +/****** XMLDocumentWrapper_XmlSecImpl/getNextReservedNode ********************* + * + * NAME + * getNextReservedNode -- Highlights the next reserved node in the + * reserved node list + * + * FUNCTION + * The m_aReservedNodes array holds a node list, while the + * m_pCurrentReservedNode points to the one currently highlighted. + * This method is used to highlight the next node in the node list. + * This method is called at the time when the current highlighted node + * has been already processed, and the next node should be ready. + ******************************************************************************/ +{ + if (m_nReservedNodeIndex < m_aReservedNodes.getLength()) + { + m_pCurrentReservedNode = checkElement( m_aReservedNodes[m_nReservedNodeIndex] ); + m_nReservedNodeIndex ++; + } + else + { + m_pCurrentReservedNode = nullptr; + } +} + +void XMLDocumentWrapper_XmlSecImpl::removeNode(const xmlNodePtr pNode) const +/****** XMLDocumentWrapper_XmlSecImpl/removeNode ****************************** + * + * NAME + * removeNode -- Deletes a node with its branch unconditionally + * + * FUNCTION + * Delete the node along with its branch from the document. + * + * INPUTS + * pNode - the node to be deleted + ******************************************************************************/ +{ + /* you can't remove the current node */ + OSL_ASSERT( m_pCurrentElement != pNode ); + + xmlAttrPtr pAttr = pNode->properties; + + while (pAttr != nullptr) + { + if (!stricmp(reinterpret_cast<char const *>(pAttr->name), "id")) + { + xmlRemoveID(m_pDocument, pAttr); + } + + pAttr = pAttr->next; + } + + xmlUnlinkNode(pNode); + xmlFreeNode(pNode); +} + +void XMLDocumentWrapper_XmlSecImpl::buildIDAttr(xmlNodePtr pNode) const +/****** XMLDocumentWrapper_XmlSecImpl/buildIDAttr ***************************** + * + * NAME + * buildIDAttr -- build the ID attribute of a node + * + * INPUTS + * pNode - the node whose id attribute will be built + ******************************************************************************/ +{ + xmlAttrPtr idAttr = xmlHasProp( pNode, reinterpret_cast<const unsigned char *>("id") ); + if (idAttr == nullptr) + { + idAttr = xmlHasProp( pNode, reinterpret_cast<const unsigned char *>("Id") ); + } + + if (idAttr != nullptr) + { + xmlChar* idValue = xmlNodeListGetString( m_pDocument, idAttr->children, 1 ) ; + xmlAddID( nullptr, m_pDocument, idValue, idAttr ); + } +} + +void XMLDocumentWrapper_XmlSecImpl::rebuildIDLink(xmlNodePtr pNode) const +/****** XMLDocumentWrapper_XmlSecImpl/rebuildIDLink *************************** + * + * NAME + * rebuildIDLink -- rebuild the ID link for the branch + * + * INPUTS + * pNode - the node, from which the branch will be rebuilt + ******************************************************************************/ +{ + if (pNode != nullptr && pNode->type == XML_ELEMENT_NODE) + { + buildIDAttr( pNode ); + + xmlNodePtr child = pNode->children; + while (child != nullptr) + { + rebuildIDLink(child); + child = child->next; + } + } +} + +/* XXMLDocumentWrapper */ +uno::Reference< css::xml::wrapper::XXMLElementWrapper > SAL_CALL XMLDocumentWrapper_XmlSecImpl::getCurrentElement( ) +{ + return new XMLElementWrapper_XmlSecImpl(m_pCurrentElement); +} + +void SAL_CALL XMLDocumentWrapper_XmlSecImpl::setCurrentElement( const uno::Reference< css::xml::wrapper::XXMLElementWrapper >& element ) +{ + m_pCurrentElement = checkElement( element ); + saxHelper.setCurrentNode( m_pCurrentElement ); +} + +void SAL_CALL XMLDocumentWrapper_XmlSecImpl::removeCurrentElement( ) +{ + OSL_ASSERT( m_pCurrentElement != nullptr ); + + xmlNodePtr pOldCurrentElement = m_pCurrentElement; + + /* + * pop the top node in the parser context's + * nodeTab stack, then the parent of that node will + * automatically become the new stack top, and + * the current node as well. + */ + saxHelper.endElement(OUString::fromUtf8(reinterpret_cast<char const *>(pOldCurrentElement->name))); + m_pCurrentElement = saxHelper.getCurrentNode(); + + /* + * remove the node + */ + removeNode(pOldCurrentElement); +} + +sal_Bool SAL_CALL XMLDocumentWrapper_XmlSecImpl::isCurrent( const uno::Reference< css::xml::wrapper::XXMLElementWrapper >& node ) +{ + xmlNodePtr pNode = checkElement(node); + return (pNode == m_pCurrentElement); +} + +sal_Bool SAL_CALL XMLDocumentWrapper_XmlSecImpl::isCurrentElementEmpty( ) +{ + bool rc = false; + + if (m_pCurrentElement->children == nullptr) + { + rc = true; + } + + return rc; +} + +OUString SAL_CALL XMLDocumentWrapper_XmlSecImpl::getNodeName( const uno::Reference< css::xml::wrapper::XXMLElementWrapper >& node ) +{ + xmlNodePtr pNode = checkElement(node); + return OUString::fromUtf8(reinterpret_cast<char const *>(pNode->name)); +} + +void SAL_CALL XMLDocumentWrapper_XmlSecImpl::clearUselessData( + const uno::Reference< css::xml::wrapper::XXMLElementWrapper >& node, + const uno::Sequence< uno::Reference< css::xml::wrapper::XXMLElementWrapper > >& reservedDescendants, + const uno::Reference< css::xml::wrapper::XXMLElementWrapper >& stopAtNode ) +{ + xmlNodePtr pTargetNode = checkElement(node); + + m_pStopAtNode = checkElement(stopAtNode); + m_aReservedNodes = reservedDescendants; + m_nReservedNodeIndex = 0; + + getNextReservedNode(); + + recursiveDelete(pTargetNode); +} + +void SAL_CALL XMLDocumentWrapper_XmlSecImpl::collapse( const uno::Reference< css::xml::wrapper::XXMLElementWrapper >& node ) +{ + xmlNodePtr pTargetNode = checkElement(node); + xmlNodePtr pParent; + + while (pTargetNode != nullptr) + { + if (pTargetNode->children != nullptr || pTargetNode == m_pCurrentElement) + { + break; + } + + pParent = pTargetNode->parent; + removeNode(pTargetNode); + pTargetNode = pParent; + } +} + +void SAL_CALL XMLDocumentWrapper_XmlSecImpl::getTree( const uno::Reference< css::xml::sax::XDocumentHandler >& handler ) +{ + if (m_pRootElement == nullptr) + return; + + xmlNodePtr pTempCurrentElement = m_pCurrentElement; + sal_Int32 nTempCurrentPosition = m_nCurrentPosition; + + m_pCurrentElement = m_pRootElement; + + m_nCurrentPosition = NODEPOSITION_STARTELEMENT; + + while(true) + { + switch (m_nCurrentPosition) + { + case NODEPOSITION_STARTELEMENT: + sendStartElement(nullptr, handler, m_pCurrentElement); + break; + case NODEPOSITION_ENDELEMENT: + sendEndElement(nullptr, handler, m_pCurrentElement); + break; + case NODEPOSITION_NORMAL: + sendNode(nullptr, handler, m_pCurrentElement); + break; + } + + if ( (m_pCurrentElement == m_pRootElement) && (m_nCurrentPosition == NODEPOSITION_ENDELEMENT )) + { + break; + } + + getNextSAXEvent(); + } + + m_pCurrentElement = pTempCurrentElement; + m_nCurrentPosition = nTempCurrentPosition; +} + +void SAL_CALL XMLDocumentWrapper_XmlSecImpl::generateSAXEvents( + const uno::Reference< css::xml::sax::XDocumentHandler >& handler, + const uno::Reference< css::xml::sax::XDocumentHandler >& xEventKeeperHandler, + const uno::Reference< css::xml::wrapper::XXMLElementWrapper >& startNode, + const uno::Reference< css::xml::wrapper::XXMLElementWrapper >& endNode ) +{ + /* + * The first SAX event is the startElement of the startNode + * element. + */ + bool bHasCurrentElementChild = (m_pCurrentElement->children != nullptr); + + xmlNodePtr pTempCurrentElement = m_pCurrentElement; + + m_pCurrentElement = checkElement(startNode); + + if (m_pCurrentElement->type == XML_ELEMENT_NODE) + { + m_nCurrentPosition = NODEPOSITION_STARTELEMENT; + } + else + { + m_nCurrentPosition = NODEPOSITION_NORMAL; + } + + xmlNodePtr pEndNode = checkElement(endNode); + + uno::Reference < css::xml::crypto::sax::XSAXEventKeeper > xSAXEventKeeper( xEventKeeperHandler, uno::UNO_QUERY ); + + uno::Reference< css::xml::sax::XDocumentHandler > xHandler = handler; + + while(true) + { + switch (m_nCurrentPosition) + { + case NODEPOSITION_STARTELEMENT: + sendStartElement(xHandler, xEventKeeperHandler, m_pCurrentElement); + break; + case NODEPOSITION_ENDELEMENT: + sendEndElement(xHandler, xEventKeeperHandler, m_pCurrentElement); + break; + case NODEPOSITION_NORMAL: + sendNode(xHandler, xEventKeeperHandler, m_pCurrentElement); + break; + default: + throw uno::RuntimeException(); + } + + if (xSAXEventKeeper->isBlocking()) + { + xHandler = nullptr; + } + + if (pEndNode == nullptr && + ((bHasCurrentElementChild && m_pCurrentElement == xmlGetLastChild(pTempCurrentElement) && m_nCurrentPosition != NODEPOSITION_STARTELEMENT) || + (!bHasCurrentElementChild && m_pCurrentElement == pTempCurrentElement && m_nCurrentPosition == NODEPOSITION_STARTELEMENT))) + { + break; + } + + getNextSAXEvent(); + + /* + * If there is an end point specified, then check whether + * the current node equals to the end point. If so, stop + * generating. + */ + if (pEndNode != nullptr && m_pCurrentElement == pEndNode) + { + break; + } + } + + m_pCurrentElement = pTempCurrentElement; +} + +void SAL_CALL XMLDocumentWrapper_XmlSecImpl::rebuildIDLink( + const css::uno::Reference< css::xml::wrapper::XXMLElementWrapper >& node ) +{ + xmlNodePtr pNode = checkElement( node ); + rebuildIDLink(pNode); +} + + +/* css::xml::sax::XDocumentHandler */ +void SAL_CALL XMLDocumentWrapper_XmlSecImpl::startDocument( ) +{ +} + +void SAL_CALL XMLDocumentWrapper_XmlSecImpl::endDocument( ) +{ +} + +void SAL_CALL XMLDocumentWrapper_XmlSecImpl::startElement( const OUString& aName, const uno::Reference< css::xml::sax::XAttributeList >& xAttribs ) +{ + sal_Int32 nLength = xAttribs->getLength(); + uno::Sequence< css::xml::csax::XMLAttribute > aAttributes (nLength); + auto aAttributesRange = asNonConstRange(aAttributes); + + for (int i = 0; i < nLength; ++i) + { + aAttributesRange[i].sName = xAttribs->getNameByIndex(static_cast<short>(i)); + aAttributesRange[i].sValue =xAttribs->getValueByIndex(static_cast<short>(i)); + } + + compressedStartElement(aName, aAttributes); +} + +void SAL_CALL XMLDocumentWrapper_XmlSecImpl::endElement( const OUString& aName ) +{ + saxHelper.endElement(aName); + m_pCurrentElement = saxHelper.getCurrentNode(); +} + +void SAL_CALL XMLDocumentWrapper_XmlSecImpl::characters( const OUString& aChars ) +{ + saxHelper.characters(aChars); +} + +void SAL_CALL XMLDocumentWrapper_XmlSecImpl::ignorableWhitespace( const OUString& aWhitespaces ) +{ + saxHelper.ignorableWhitespace(aWhitespaces); +} + +void SAL_CALL XMLDocumentWrapper_XmlSecImpl::processingInstruction( const OUString& aTarget, const OUString& aData ) +{ + saxHelper.processingInstruction(aTarget, aData); +} + +void SAL_CALL XMLDocumentWrapper_XmlSecImpl::setDocumentLocator( const uno::Reference< css::xml::sax::XLocator >& ) +{ +} + +/* XCompressedDocumentHandler */ +void SAL_CALL XMLDocumentWrapper_XmlSecImpl::compressedStartDocument( ) +{ +} + +void SAL_CALL XMLDocumentWrapper_XmlSecImpl::compressedEndDocument( ) +{ +} + +void SAL_CALL XMLDocumentWrapper_XmlSecImpl::compressedStartElement( const OUString& aName, const uno::Sequence< css::xml::csax::XMLAttribute >& aAttributes ) +{ + saxHelper.startElement(aName, aAttributes); + m_pCurrentElement = saxHelper.getCurrentNode(); + + buildIDAttr( m_pCurrentElement ); +} + +void SAL_CALL XMLDocumentWrapper_XmlSecImpl::compressedEndElement( const OUString& aName ) +{ + endElement( aName ); +} + +void SAL_CALL XMLDocumentWrapper_XmlSecImpl::compressedCharacters( const OUString& aChars ) +{ + characters( aChars ); +} + +void SAL_CALL XMLDocumentWrapper_XmlSecImpl::compressedIgnorableWhitespace( const OUString& aWhitespaces ) +{ + ignorableWhitespace( aWhitespaces ); +} + +void SAL_CALL XMLDocumentWrapper_XmlSecImpl::compressedProcessingInstruction( const OUString& aTarget, const OUString& aData ) +{ + processingInstruction( aTarget, aData ); +} + +void SAL_CALL XMLDocumentWrapper_XmlSecImpl::compressedSetDocumentLocator( sal_Int32 /*columnNumber*/, sal_Int32 /*lineNumber*/, const OUString& /*publicId*/, const OUString& /*systemId*/ ) +{ +} + +/* XServiceInfo */ +OUString SAL_CALL XMLDocumentWrapper_XmlSecImpl::getImplementationName( ) +{ + return "com.sun.star.xml.wrapper.XMLDocumentWrapper"; +} + +sal_Bool SAL_CALL XMLDocumentWrapper_XmlSecImpl::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService( this, rServiceName ); +} + +uno::Sequence< OUString > SAL_CALL XMLDocumentWrapper_XmlSecImpl::getSupportedServiceNames( ) +{ + return { "com.sun.star.xml.wrapper.XMLDocumentWrapper" }; +} + +extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface* +com_sun_star_xml_wrapper_XMLDocumentWrapper_get_implementation( + uno::XComponentContext* /*pCtx*/, uno::Sequence<uno::Any> const& /*rSeq*/) +{ + return cppu::acquire(new XMLDocumentWrapper_XmlSecImpl()); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/xmlelementwrapper_xmlsecimpl.cxx b/xmlsecurity/source/xmlsec/xmlelementwrapper_xmlsecimpl.cxx new file mode 100644 index 0000000000..ccc4f03dd9 --- /dev/null +++ b/xmlsecurity/source/xmlsec/xmlelementwrapper_xmlsecimpl.cxx @@ -0,0 +1,58 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <string.h> + +#include "xmlelementwrapper_xmlsecimpl.hxx" +#include <comphelper/servicehelper.hxx> +#include <cppuhelper/supportsservice.hxx> + +namespace com::sun::star::uno { class XComponentContext; } + +using namespace com::sun::star; + +XMLElementWrapper_XmlSecImpl::XMLElementWrapper_XmlSecImpl(const xmlNodePtr pNode) + : m_pElement( pNode ) +{ +} + +/* XServiceInfo */ +OUString SAL_CALL XMLElementWrapper_XmlSecImpl::getImplementationName( ) +{ + return "com.sun.star.xml.wrapper.XMLElementWrapper"; +} + +sal_Bool SAL_CALL XMLElementWrapper_XmlSecImpl::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService( this, rServiceName ); +} + +uno::Sequence< OUString > SAL_CALL XMLElementWrapper_XmlSecImpl::getSupportedServiceNames( ) +{ + return { "com.sun.star.xml.wrapper.XMLElementWrapper" }; +} + +extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface* +com_sun_star_xml_wrapper_XMLElementWrapper_get_implementation( + uno::XComponentContext* /*pCtx*/, uno::Sequence<uno::Any> const& /*rSeq*/) +{ + return cppu::acquire(new XMLElementWrapper_XmlSecImpl(nullptr)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/xmlelementwrapper_xmlsecimpl.hxx b/xmlsecurity/source/xmlsec/xmlelementwrapper_xmlsecimpl.hxx new file mode 100644 index 0000000000..93ce721f0b --- /dev/null +++ b/xmlsecurity/source/xmlsec/xmlelementwrapper_xmlsecimpl.hxx @@ -0,0 +1,72 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <com/sun/star/xml/wrapper/XXMLElementWrapper.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <cppuhelper/implbase.hxx> + +#include <libxml/tree.h> +#include <xsecxmlsecdllapi.h> + +class XMLElementWrapper_XmlSecImpl : public cppu::WeakImplHelper +< + css::xml::wrapper::XXMLElementWrapper, + css::lang::XServiceInfo +> +/****** XMLElementWrapper_XmlSecImpl.hxx/CLASS XMLElementWrapper_XmlSecImpl *** + * + * NAME + * XMLElementWrapper_XmlSecImpl -- Class to wrap a libxml2 node + * + * FUNCTION + * Used as a wrapper class to transfer a libxml2 node structure + * between different UNO components. + ******************************************************************************/ +{ +private: + /* the libxml2 node wrapped by this object */ + xmlNodePtr const m_pElement; + +public: + explicit XMLElementWrapper_XmlSecImpl(const xmlNodePtr pNode); + + /* XXMLElementWrapper */ + + /* css::lang::XServiceInfo */ + virtual OUString SAL_CALL getImplementationName( ) override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; + +public: + /* + * NAME + * getNativeElement -- Retrieves the libxml2 node wrapped by this object + * + * SYNOPSIS + * pNode = getNativeElement(); + * + * RESULT + * pNode - the libxml2 node wrapped by this object + */ + xmlNodePtr getNativeElement( ) const { return m_pElement;} +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/xmlsec_init.cxx b/xmlsecurity/source/xmlsec/xmlsec_init.cxx new file mode 100644 index 0000000000..410408ed2e --- /dev/null +++ b/xmlsecurity/source/xmlsec/xmlsec_init.cxx @@ -0,0 +1,73 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <sal/config.h> +#include <xmlsec-wrapper.h> + +#include <xmlsec/xmlsec_init.hxx> + +#include <com/sun/star/uno/RuntimeException.hpp> + +#include <xmlsec/xmlstreamio.hxx> +#ifdef XMLSEC_CRYPTO_MSCRYPTO +#include <xmlsec/mscng/crypto.h> +#endif +#ifdef XMLSEC_CRYPTO_NSS +#include <xmlsec/nss/crypto.h> +#endif + +using namespace css::uno; + +XSECXMLSEC_DLLPUBLIC void initXmlSec() +{ + //Init xmlsec library + if( xmlSecInit() < 0 ) { + throw RuntimeException() ; + } + + //Init xmlsec crypto engine library +#ifdef XMLSEC_CRYPTO_MSCRYPTO + if( xmlSecMSCngInit() < 0 ) { + xmlSecShutdown(); + throw RuntimeException(); + } +#endif +#ifdef XMLSEC_CRYPTO_NSS + if( xmlSecNssInit() < 0 ) { + xmlSecShutdown(); + throw RuntimeException(); + } +#endif + + //Enable external stream handlers + if( xmlEnableStreamInputCallbacks() < 0 ) { +#ifdef XMLSEC_CRYPTO_MSCRYPTO + xmlSecMSCngShutdown(); +#endif +#ifdef XMLSEC_CRYPTO_NSS + xmlSecNssShutdown(); +#endif + xmlSecShutdown() ; + throw RuntimeException() ; + } +} + +XSECXMLSEC_DLLPUBLIC void deInitXmlSec() +{ + xmlDisableStreamInputCallbacks(); +#ifdef XMLSEC_CRYPTO_MSCRYPTO + xmlSecMSCngShutdown(); +#endif +#ifdef XMLSEC_CRYPTO_NSS + xmlSecNssShutdown(); +#endif + xmlSecShutdown(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/xmlstreamio.cxx b/xmlsecurity/source/xmlsec/xmlstreamio.cxx new file mode 100644 index 0000000000..b3ee767120 --- /dev/null +++ b/xmlsecurity/source/xmlsec/xmlstreamio.cxx @@ -0,0 +1,251 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> +#include <xmlsec-wrapper.h> + +/* + * Implementation of the I/O interfaces based on stream and URI binding + */ +#include <xmlsec/xmlstreamio.hxx> +#include <xmlsec/errorcallback.hxx> +#include <rtl/ustring.hxx> +#include <rtl/uri.hxx> +#include <comphelper/scopeguard.hxx> +#include <sal/log.hxx> + +#include <com/sun/star/xml/crypto/XUriBinding.hpp> + +static bool g_bInputCallbacksEnabled = false; +static bool g_bInputCallbacksRegistered = false; + +static css::uno::Reference< css::xml::crypto::XUriBinding > m_xUriBinding ; + +extern "C" { + +static int xmlStreamMatch( const char* uri ) +{ + css::uno::Reference< css::io::XInputStream > xInputStream ; + + if (g_bInputCallbacksEnabled && g_bInputCallbacksRegistered) + { + if( uri == nullptr || !m_xUriBinding.is() ) + return 0 ; + //XMLSec first unescapes the uri and calls this function. For example, we pass the Uri + //ObjectReplacements/Object%201 then XMLSec passes ObjectReplacements/Object 1 + //first. If this failed it would try this + //again with the original escaped string. However, it does not get this far, because there + //is another callback registered by libxml which claims to be able to handle this uri. + OUString sUri = + ::rtl::Uri::encode( OUString::createFromAscii( uri ), + rtl_UriCharClassUric, rtl_UriEncodeKeepEscapes, RTL_TEXTENCODING_UTF8); + xInputStream = m_xUriBinding->getUriBinding( sUri ) ; + if (!xInputStream.is()) + { + //Try the passed in uri directly. + //For old documents prior OOo 3.0. We did not use URIs then. + xInputStream = m_xUriBinding->getUriBinding( + OUString::createFromAscii(uri)); + } + } + SAL_INFO("xmlsecurity.xmlsec", + "xmlStreamMath: uri is '" << uri << "', returning " << xInputStream.is()); + if (xInputStream.is()) + return 1; + else + return 0 ; +} + +static void* xmlStreamOpen( const char* uri ) +{ + css::uno::Reference< css::io::XInputStream > xInputStream ; + + if (g_bInputCallbacksEnabled && g_bInputCallbacksRegistered) + { + if( uri == nullptr || !m_xUriBinding.is() ) + return nullptr ; + + //see xmlStreamMatch + OUString sUri = + ::rtl::Uri::encode( OUString::createFromAscii( uri ), + rtl_UriCharClassUric, rtl_UriEncodeKeepEscapes, RTL_TEXTENCODING_UTF8); + xInputStream = m_xUriBinding->getUriBinding( sUri ) ; + if (!xInputStream.is()) + { + //For old documents. + //try the passed in uri directly. + xInputStream = m_xUriBinding->getUriBinding( + OUString::createFromAscii(uri)); + } + + if( xInputStream.is() ) { + css::io::XInputStream* pInputStream ; + pInputStream = xInputStream.get() ; + pInputStream->acquire() ; + SAL_INFO("xmlsecurity.xmlsec", + "xmlStreamOpen: uri is '" << uri << "', returning context " << pInputStream); + return static_cast<void*>(pInputStream) ; + } + } + + return nullptr ; +} + +static int xmlStreamRead( void* context, char* buffer, int len ) +{ + int numbers ; + css::uno::Reference< css::io::XInputStream > xInputStream ; + css::uno::Sequence< sal_Int8 > outSeqs( len ) ; + + numbers = 0 ; + if (g_bInputCallbacksEnabled && g_bInputCallbacksRegistered) + { + if( context != nullptr ) { + xInputStream = static_cast<css::io::XInputStream*>(context); + if( !xInputStream.is() ) + return 0 ; + + numbers = xInputStream->readBytes( outSeqs, len ) ; + const sal_Int8* readBytes = outSeqs.getArray() ; + for( int i = 0 ; i < numbers ; i ++ ) + *( buffer + i ) = *( readBytes + i ) ; + } + } + + SAL_INFO("xmlsecurity.xmlsec", "xmlStreamRead: context is " << context << ", buffer is now '" + << OString(buffer, numbers) << "'"); + return numbers ; +} + +static int xmlStreamClose( void * context ) +{ + if (g_bInputCallbacksEnabled && g_bInputCallbacksRegistered) + { + if( context != nullptr ) { + css::io::XInputStream* pInputStream ; + pInputStream = static_cast<css::io::XInputStream*>(context); + pInputStream->release() ; + SAL_INFO("xmlsecurity.xmlsec", "xmlStreamRead: closed context " << context); + } + } + + return 0 ; +} + +} + +int xmlEnableStreamInputCallbacks() +{ + if (!g_bInputCallbacksEnabled) + { + //Register the callbacks into xmlSec + //In order to make the xmlsec io finding the callbacks firstly, + //I put the callbacks at the very beginning. + + //Cleanup the older callbacks. + //Notes: all none default callbacks will lose. + xmlSecIOCleanupCallbacks() ; + + // Make sure that errors are reported via SAL_WARN(). + setErrorRecorder(); + comphelper::ScopeGuard g([] { clearErrorRecorder(); }); + + // Newer xmlsec wants the callback order in the opposite direction. + if (xmlSecCheckVersionExt(1, 2, 26, xmlSecCheckVersionABICompatible)) + { + //Register the default callbacks. + //Notes: the error will cause xmlsec working problems. + int cbs = xmlSecIORegisterDefaultCallbacks() ; + if( cbs < 0 ) { + return -1 ; + } + + //Register my classbacks. + cbs = xmlSecIORegisterCallbacks( + xmlStreamMatch, + xmlStreamOpen, + xmlStreamRead, + xmlStreamClose ) ; + if( cbs < 0 ) { + return -1 ; + } + } + else + { + //Register my classbacks. + int cbs = xmlSecIORegisterCallbacks( + xmlStreamMatch, + xmlStreamOpen, + xmlStreamRead, + xmlStreamClose ) ; + if( cbs < 0 ) { + return -1 ; + } + + //Register the default callbacks. + //Notes: the error will cause xmlsec working problems. + cbs = xmlSecIORegisterDefaultCallbacks() ; + if( cbs < 0 ) { + return -1 ; + } + } + + g_bInputCallbacksEnabled = true; + } + + return 0 ; +} + +int xmlRegisterStreamInputCallbacks( + css::uno::Reference< css::xml::crypto::XUriBinding > const & aUriBinding +) { + if (!g_bInputCallbacksEnabled) + { + if( xmlEnableStreamInputCallbacks() < 0 ) + return -1 ; + } + + if (!g_bInputCallbacksRegistered) + g_bInputCallbacksRegistered = true; + + m_xUriBinding = aUriBinding ; + + return 0 ; +} + +int xmlUnregisterStreamInputCallbacks() +{ + if (g_bInputCallbacksRegistered) + { + //Clear the uri-stream binding + m_xUriBinding.clear() ; + + //disable the registered flag + g_bInputCallbacksRegistered = false; + } + + return 0 ; +} + +void xmlDisableStreamInputCallbacks() { + xmlUnregisterStreamInputCallbacks() ; + g_bInputCallbacksEnabled = false; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/test_docs/CAs/README.txt b/xmlsecurity/test_docs/CAs/README.txt new file mode 100644 index 0000000000..b454f1fafd --- /dev/null +++ b/xmlsecurity/test_docs/CAs/README.txt @@ -0,0 +1,383 @@ +This folder contains the directory structures needed by openssl to create +and manager certificates. + + + +################################################################################ + +Root 1 +====== +Valid root CA certificate. +Provides CRL = NO +Provides CRL via HTTP = NO +Provides OCSP = NO + +Sub CA 1 Root 1 +=============== +Valid intermediate CA certificate. +Provides CRL = NO +Provides CRL via HTTP = NO +Provides OCSP = NO +CRLDP = NO +AIA = NO + +User 1 Sub CA 1 Root 1 +====================== +Valid end certificate. +CRLDP = NO +AIA = NO + +################################################################################ + +Root 2 +====== +Valid root CA certificate. +Provides CRL = NO +Provides CRL via HTTP = NO +Provides OCSP = NO + +Sub CA 1 Root 2 +=============== +Valid intermediate CA certificate. +Provides CRL = YES +Provides CRL via HTTP = NO +Provides OCSP = NO +CRLDP = NO +AIA = NO + +User 1 Sub CA 1 Root 2 +====================== +Valid end certificate. +CRLDP = NO +AIA = NO + +################################################################################ + +Root 3 +====== +Valid root CA certificate. +Provides CRL = YES +Provides CRL via HTTP = NO +Provides OCSP = NO + +Sub CA 1 Root 3 +=============== +Valid intermediate CA certificate. +Provides CRL = NO +Provides CRL via HTTP = NO +Provides OCSP = NO +CRLDP = NO +AIA = NO + +User 1 Sub CA 1 Root 3 +====================== +Valid end certificate. +CRLDP = NO +AIA = NO + +################################################################################ + +Root 4 +====== +Valid root CA certificate. +Provides CRL = YES +Provides CRL via HTTP = NO +Provides OCSP = NO + +Revoked certificates: + +- Sub CA 2 Root 4 + + +Sub CA 1 Root 4 +=============== +Valid intermediate CA certificate. +Provides CRL = YES +Provides CRL via HTTP = NO +Provides OCSP = NO +CRLDP = NO +AIA = NO + +Revoked certificates: + +- User 2 Sub CA 1 Root 4 + + +User 1 Sub CA 1 Root 4 +====================== +Valid end certificate. +CRLDP = NO +AIA = NO + +User 2 Sub CA 1 Root 4 +====================== +Revoked end certificate. +CRLDP = NO +AIA = NO + +Sub CA 2 Root 4 +=============== +Revoked intermediate CA certificate. Reason = keyCompromise +Provides CRL = YES +Provides CRL via HTTP = NO +Provides OCSP = NO +CRLDP = NO +AIA = NO + +Revoked certificates: + +- User 2 Sub CA 2 Root 4 + +User 1 Sub CA 2 Root 4 +====================== +Valid end certificate. Issuer is revoked. +CRLDP = NO +AIA = NO + +User 2 Sub CA 2 Root 4 +====================== +Revoked end certificate. Reason = keyCompromise. Issuer is revoked. +CRLDP = NO +AIA = NO + +################################################################################ + +Root 5 +====== +Valid root CA certificate. +Provides CRL = NO +Provides CRL via HTTP = NO +Provides OCSP = NO + +Sub CA 1 Root 5 +=============== +Valid intermediate CA certificate. +Provides CRL = NO +Provides CRL via HTTP = YES +Provides OCSP = NO +CRLDP = URL=http://localhost:8901/demoCA/crl/Root_5.crl +AIA = NO + +User 1 Sub CA 1 Root 5 +====================== +Valid end certificate. +CRLDP = URL=http://localhost:8902/demoCA/crl/Sub_CA_1_Root_5.crl +AIA = NO + + +################################################################################ + +Root 6 +====== +Valid root CA certificate. +Provides CRL = NO +Provides CRL via HTTP = YES +Provides OCSP = NO + +Sub CA 1 Root 6 +=============== +Valid intermediate CA certificate. +Provides CRL = NO +Provides CRL via HTTP = NO +Provides OCSP = NO +CRLDP = URL=http://localhost:8901/demoCA/crl/Root_6.crl +AIA = NO + +User 1 Sub CA 1 Root 6 +====================== +Valid end certificate. +CRLDP = URL=http://localhost:8902/demoCA/crl/Sub_CA_1_Root_6.crl +AIA = NO + +################################################################################ + +Root 7 +====== +Valid root CA certificate. +Provides CRL = NO +Provides CRL via HTTP = YES +Provides OCSP = NO + +Revoked certificates: + +- Sub CA 2 Root 7 + + +Sub CA 1 Root 7 +=============== +Valid intermediate CA certificate. +Provides CRL = NO +Provides CRL via HTTP = YES +Provides OCSP = NO +CRLDP = URL=http://localhost:8901/demoCA/crl/Root_7.crl +AIA = NO + +Revoked certificates: + +- User 2 Sub CA 1 Root 7 + + +User 1 Sub CA 1 Root 7 +====================== +Valid end certificate. +CRLDP = URL=http://localhost:8902/demoCA/crl/Sub_CA_1_Root_7.crl +AIA = NO + +User 2 Sub CA 1 Root 7 +====================== +Revoked end certificate. Reason = CACompromise. +CRLDP = URL=http://localhost:8902/demoCA/crl/Sub_CA_1_Root_7.crl +AIA = NO + +Sub CA 2 Root 7 +=============== +Revoked intermediate CA certificate. Reason = keyCompromise +Provides CRL = NO +Provides CRL via HTTP = YES +Provides OCSP = NO +CRLDP = URL=http://localhost:8901/demoCA/crl/Root_7.crl +AIA = NO + +Revoked certificates: + +- User 2 Sub CA 2 Root 7 + +User 1 Sub CA 2 Root 7 +====================== +Valid end certificate. Issuer is revoked. +CRLDP = URL=http://localhost:8902/demoCA/crl/Sub_CA_2_Root_7.crl +AIA = NO + +User 2 Sub CA 2 Root 7 +====================== +Revoked end certificate. Reason = CACompromise. Issuer is revoked. +CRLDP = URL=http://localhost:8902/demoCA/crl/Sub_CA_2_Root_7.crl +AIA = NO + +################################################################################ + +Root 8 +====== +Valid root CA certificate. +Provides CRL = NO +Provides CRL via HTTP = NO +Provides OCSP = YES + +Revoked certificates: + +- Sub CA 2 Root 8 + + +Sub CA 1 Root 8 +=============== +Valid intermediate CA certificate. +Provides CRL = NO +Provides CRL via HTTP = NO +Provides OCSP = YES +CRLDP = +AIA = OCSP;URI:http://localhost:8888 + +Revoked certificates: + +- User 2 Sub CA 1 Root 8 + + +User 1 Sub CA 1 Root 8 +====================== +Valid end certificate. +CRLDP = NO +AIA = OCSP;URI:http://localhost:8889 + +User 2 Sub CA 1 Root 8 +====================== +Revoked end certificate. Reason = superseded. +CRLDP = NO +AIA = OCSP;URI:http://localhost:8889 + +Sub CA 2 Root 8 +=============== +Revoked intermediate CA certificate. Reason = superseded. +Provides CRL = NO +Provides CRL via HTTP = NO +Provides OCSP = YES +CRLDP = NO +AIA = OCSP;URI:http://localhost:8888 + +Revoked certificates: + +- User 2 Sub CA 2 Root 8 + +User 1 Sub CA 2 Root 8 +====================== +Valid end certificate. Issuer is revoked. +CRLDP = NO +AIA = OCSP;URI:http://localhost:8889 + +User 2 Sub CA 2 Root 8 +====================== +Revoked end certificate. Reason = superseded. Issuer is revoked. +CRLDP = NO +AIA = OCSP;URI:http://localhost:8889 + +################################################################################ + +Root 9 +====== +Valid root CA certificate. (Not installed.) +Provides CRL = YES +Provides CRL via HTTP = NO +Provides OCSP = NO + +Sub CA 1 Root 9 +=============== +Valid intermediate CA certificate. +Provides CRL = YES +Provides CRL via HTTP = NO +Provides OCSP = NO +CRLDP = NO +AIA = NO + +User 1 Sub CA 1 Root 9 +====================== +Valid end certificate. +CRLDP = NO +AIA = NO + +################################################################################ + +Root 10 +====== +Valid root CA certificate. +Provides CRL = YES +Provides CRL via HTTP = NO +Provides OCSP = NO + +Sub CA 1 Root 10 +=============== +Valid intermediate CA certificate. (Not installed.) +Provides CRL = NO +Provides CRL via HTTP = YES +Provides OCSP = NO +CRLDP = NO +AIA = NO + +User 1 Sub CA 1 Root 10 +====================== +Valid end certificate. +CRLDP = URI:http://localhost:8902/demoCA/crl/Sub_CA_1_Root_10.crl +AIA = caIssuers;URI:http://localhost:8910/demoCA/Sub_CA_1_Root_10.crt + +################################################################################ + +Root 11 +====== +Valid root CA certificate. +Provides CRL = YES +Provides CRL via HTTP = NO +Provides OCSP = NO + +User x Root 11 +====================== +All certificate issues by Root 11 are valid end certificate. Currently there are +31 certificates. + diff --git a/xmlsecurity/test_docs/CAs/Root_1/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Root_1/demoCA/cacert.pem new file mode 100644 index 0000000000..091052e3ab --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_1/demoCA/cacert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDBDCCAm2gAwIBAgIJAJWwBSvtwjktMA0GCSqGSIb3DQEBBQUAMF8xCzAJBgNV +BAYTAkRFMRAwDgYDVQQIEwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9y +ZzEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgMTAeFw0wOTEx +MTgxNDU1NDFaFw0zNDExMTIxNDU1NDFaMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw +gYkCgYEAvrD6NFWcOQQVxIuXw5Pzpy667PZbBP80ow2Bbnj+RFCI/LbgfQTsC8Bw +eSlQGX7IqMHkCTuWNJw7CoNeOLFhRMtm0DEKnEkZlM0t6kpFshbs12jZu9okcnII +F5uIoKxx/thbD5AbC1Q74vZr6XOXY5Sc+k9Ic6Jwhe9ZyEt6SUsCAwEAAaOBxzCB +xDAdBgNVHQ4EFgQUD/rG69/OuLuzqT5Cprrs0pPKR6QwgZEGA1UdIwSBiTCBhoAU +D/rG69/OuLuzqT5Cprrs0pPKR6ShY6RhMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgMYIJAJWwBSvtwjktMA8GA1UdEwEB/wQF +MAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAqORur4HQGdQOQCaiyZR5u0+9mM/0w79y +r8Cmt+H8WB5BBeDgCyOcmaZjF0eEoRBF/ZhtlO54i4CH/yb/Pl6gGlxfGZL9iLu0 +tv4HRIIibnoi0N7Z0r/dhJcrTHo4Ha8EARhAqxoNUSlGVBsaKUfjW9RyCjv4Akyi +WUSwsmtd/sY= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_1/demoCA/crl/DO_NOT_CREATE_A_CRL b/xmlsecurity/test_docs/CAs/Root_1/demoCA/crl/DO_NOT_CREATE_A_CRL new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_1/demoCA/crl/DO_NOT_CREATE_A_CRL diff --git a/xmlsecurity/test_docs/CAs/Root_1/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Root_1/demoCA/crlnumber new file mode 100644 index 0000000000..83b33d238d --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_1/demoCA/crlnumber @@ -0,0 +1 @@ +1000 diff --git a/xmlsecurity/test_docs/CAs/Root_1/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Root_1/demoCA/index.txt new file mode 100644 index 0000000000..9a6e64301b --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_1/demoCA/index.txt @@ -0,0 +1 @@ +V 341112150713Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 1 Root 1 diff --git a/xmlsecurity/test_docs/CAs/Root_1/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Root_1/demoCA/index.txt.attr new file mode 100644 index 0000000000..8f7e63a347 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_1/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Root_1/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Root_1/demoCA/newcerts/1000.pem new file mode 100644 index 0000000000..be26aa5d8f --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_1/demoCA/newcerts/1000.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 1 + Validity + Not Before: Nov 18 15:07:13 2009 GMT + Not After : Nov 12 15:07:13 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 1 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:d9:3a:8d:64:95:87:76:76:e8:61:c3:e9:65:f4: + a6:b7:0c:77:0e:4b:10:e8:14:a3:e1:84:69:7c:8e: + 97:d2:7d:01:ad:b2:dc:5c:cd:c6:91:a1:f3:93:7c: + 54:36:64:e3:ca:22:ca:00:cb:c6:91:ab:6b:26:88: + 69:60:9a:61:d7:59:17:db:93:7d:09:36:da:28:cb: + ec:2d:a4:26:bb:1a:42:20:b8:08:b2:0f:b9:77:a6: + 80:71:cf:13:f5:37:a2:90:4d:ab:e8:97:49:d2:80: + 94:8f:b1:9d:5a:b4:9f:de:ff:fa:b6:d6:e0:45:5f: + cc:d4:10:1e:32:46:7b:ba:55 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 37:71:74:81:44:DD:1E:B1:60:96:41:B7:4B:38:C4:B7:79:1B:CF:8A + X509v3 Authority Key Identifier: + keyid:0F:FA:C6:EB:DF:CE:B8:BB:B3:A9:3E:42:A6:BA:EC:D2:93:CA:47:A4 + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 1 + serial:95:B0:05:2B:ED:C2:39:2D + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 18:f6:02:5e:75:04:5f:eb:3b:07:41:85:c0:9e:08:29:58:3d: + b5:6f:c2:aa:24:0d:93:1d:17:fc:be:d6:43:ac:43:d7:4d:a0: + 2c:40:fd:3d:d5:7e:91:46:25:49:62:ba:e9:7f:67:c2:fc:8a: + c3:a0:37:bf:ec:f9:54:bf:61:10:35:dd:5b:bb:da:7c:70:54: + 32:13:b9:ae:7d:ea:a5:7d:aa:55:3e:ef:0a:ef:12:fd:c3:f6: + e5:25:98:97:34:02:64:fd:88:79:b3:e2:f4:fc:ff:e7:d3:98: + f1:d9:d5:18:d9:b4:62:ae:99:88:61:2e:ff:02:6a:13:35:fe: + 37:c7 +-----BEGIN CERTIFICATE----- +MIIDBjCCAm+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCAxMB4XDTA5MTExODE1MDcx +M1oXDTM0MTExMjE1MDcxM1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCAxMIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDZOo1klYd2duhhw+ll9Ka3DHcOSxDoFKPhhGl8jpfSfQGtstxczcaR +ofOTfFQ2ZOPKIsoAy8aRq2smiGlgmmHXWRfbk30JNtooy+wtpCa7GkIguAiyD7l3 +poBxzxP1N6KQTavol0nSgJSPsZ1atJ/e//q21uBFX8zUEB4yRnu6VQIDAQABo4HH +MIHEMB0GA1UdDgQWBBQ3cXSBRN0esWCWQbdLOMS3eRvPijCBkQYDVR0jBIGJMIGG +gBQP+sbr3864u7OpPkKmuuzSk8pHpKFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCAxggkAlbAFK+3COS0wDwYDVR0TAQH/ +BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQAY9gJedQRf6zsHQYXAnggpWD21b8Kq +JA2THRf8vtZDrEPXTaAsQP091X6RRiVJYrrpf2fC/IrDoDe/7PlUv2EQNd1bu9p8 +cFQyE7mufeqlfapVPu8K7xL9w/blJZiXNAJk/Yh5s+L0/P/n05jx2dUY2bRirpmI +YS7/AmoTNf43xw== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_1/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Root_1/demoCA/private/cakey.pem new file mode 100644 index 0000000000..6d38b24e6f --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_1/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,2D2CC3782F59A842 + +901JcMMdeCfHjfY05bkyLIsgMxwu4SFJPXZH75ebFtJQpkQQf5WNhSlo3sgKJ5MF +GZeqQw4w9CmN+CNqQENZOOGrVKxT+sFtWIgSLVk4hrLzPtsT7domHc1yUKfpBH/w +xo/bsL5wZPqcsxSdlmd4FA0PKzW/rhyYvRxF0oKQx2PVnJKT29WbhwlYurI3+2gG +pS+N6f7awWjmgyqYvFuFo7DWhERDDL/Bi/sJ7qFinijtfp1CkVG1XWFZ8Tu9ij+t +KPT3fpWbh4sV0V1ZGng7EPb4c+p/+GHvKsGM9N5kuyxufllNzAeIy6hfTR3mxn0i +Ep4CoufMi0JwNEfgwBB+o47k1hVoBTn0ofXc2iP6iQWsoC5ZoPPGLLklWK3Tur7P +kpng8UECTxV2s6J3nYkAoHfy+TzK+nssFPpE8zDmaprpeTj9oh3KrPTn0IdoPHcx +oI3yqWqDK9uErJBBCAjLF0SPJWAsmp0HsJaGnj5ErVe0yy3jBxVWogVDSWkoWU0W ++umK1pSQrS1A/oKErsnbhPi8XAD/gd4etEaKdcY538QKgE2tdPvhLoAeXxslyOfG +UiPohtmcm2Mva7vT0Iu1MGKplw76DxmmM1Rpf3+u7Kwf/+K6bMOSBGZQJhjE2AuZ +aPyHX8gCNlZfqB6eeuWdbqIHhTN5dS2Bba3QquvS84Vgb3O2ck+vdjmdPEeetvA7 +7S4WZYHBRmz1ZHwdfSvwyBkdTRP5YrUhrIthbqy2NjcP9TkpQmJaDIlWXsGY738q +zTsjCkcnS06x0/JvHe1I8IAib+MFsmGI7Dw25fzgY3ReS4wZRZdU0A== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Root_1/demoCA/serial b/xmlsecurity/test_docs/CAs/Root_1/demoCA/serial new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_1/demoCA/serial @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Root_1/openssl.cfg b/xmlsecurity/test_docs/CAs/Root_1/openssl.cfg new file mode 100644 index 0000000000..0dd15bd9ec --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_1/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Root_10/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Root_10/demoCA/cacert.pem new file mode 100644 index 0000000000..72e6c66e2e --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_10/demoCA/cacert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDBzCCAnCgAwIBAgIJAL/ID7vZoDprMA0GCSqGSIb3DQEBBQUAMGAxCzAJBgNV +BAYTAkRFMRAwDgYDVQQIEwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9y +ZzEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxEDAOBgNVBAMTB1Jvb3QgMTAwHhcNMDkx +MTIzMTUwNzA0WhcNMzQxMTE3MTUwNzA0WjBgMQswCQYDVQQGEwJERTEQMA4GA1UE +CBMHSGFtYnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0Rl +dmVsb3BtZW50MRAwDgYDVQQDEwdSb290IDEwMIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQC5qE1pk/tI2i60IrVhlwS77j7jAyktxRuwKJqBECd2ZD2/goO8wcwD +R/wfrh+zuLWRwFb57PF1O7ig+WNhQk3GDhXhMbuB82Bwjb/n5phKDWHsAIqDRbH4 +vpl/7sWYXvE46zf41PpQPgudOtqpeL1ENFoHKZOJthkBc4Yx6HTUSQIDAQABo4HI +MIHFMB0GA1UdDgQWBBTIp6OAIHRsb+wReva+JhA3MYewejCBkgYDVR0jBIGKMIGH +gBTIp6OAIHRsb+wReva+JhA3MYeweqFkpGIwYDELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMIIJAL/ID7vZoDprMA8GA1UdEwEB +/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAroDDzqZQL+7NeQuePohejcGfFR/0 +vtbQ3AYViQ2JS42gQpaNaMNcVCvO0nUwLHldLNVdQsn9P0ultu6KcUKkBbY4/2Xp +er6RMQWsrKVLnszgIi2gk1NiNwZ+N9RISJvElaQuIciZs+8sM6LOPybVTArMjxEo +U3VqHTViFfOvWC0= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_10/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Root_10/demoCA/crlnumber new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_10/demoCA/crlnumber @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Root_10/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Root_10/demoCA/index.txt new file mode 100644 index 0000000000..2db3924cea --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_10/demoCA/index.txt @@ -0,0 +1 @@ +V 341117151448Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 1 Root 10 diff --git a/xmlsecurity/test_docs/CAs/Root_10/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Root_10/demoCA/index.txt.attr new file mode 100644 index 0000000000..8f7e63a347 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_10/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Root_10/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Root_10/demoCA/newcerts/1000.pem new file mode 100644 index 0000000000..1f27b97b3d --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_10/demoCA/newcerts/1000.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 10 + Validity + Not Before: Nov 23 15:14:48 2009 GMT + Not After : Nov 17 15:14:48 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 10 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:e4:d5:66:14:88:9f:79:41:50:b0:d1:a0:1b:98: + bf:b0:21:34:30:36:70:58:6f:8b:58:f1:b9:58:3a: + ce:29:6b:65:b6:11:f7:0d:c8:a6:c3:be:db:0f:2a: + 4e:c7:42:df:c9:0e:13:c0:00:0f:af:b5:71:c4:bc: + dd:82:fc:4a:27:c0:ee:af:ba:e1:7b:67:de:6b:bb: + ac:4c:fe:88:01:1a:73:4e:f5:32:15:3a:d0:cb:6b: + 97:84:1b:6c:d0:d6:91:a8:a4:5a:87:2a:69:61:36: + 1d:42:cc:16:d0:03:9c:c6:90:5c:61:20:8b:b1:be: + b6:54:24:5b:6f:1f:a9:5a:6f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 11:63:A1:BE:8B:E3:56:07:E6:A3:9F:23:39:72:7D:E3:22:B6:53:39 + X509v3 Authority Key Identifier: + keyid:C8:A7:A3:80:20:74:6C:6F:EC:11:7A:F6:BE:26:10:37:31:87:B0:7A + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 10 + serial:BF:C8:0F:BB:D9:A0:3A:6B + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 6b:0f:75:6d:56:b0:4e:45:19:65:ad:50:ef:4e:87:6c:95:5d: + 05:39:5a:43:5c:b4:51:25:9a:ec:f4:93:d1:f0:f6:91:dd:a3: + 77:95:0c:74:3c:a9:7c:c2:f6:62:ce:bf:58:5f:66:1f:d0:55: + ca:d8:2d:c4:1e:29:3a:ad:55:2c:9d:2c:8f:8e:9e:ce:ac:17: + 7e:1b:d1:16:d9:12:76:5c:2d:3f:9d:70:66:aa:39:34:f0:ec: + 31:4b:4b:5a:14:0c:c5:5b:3c:c8:47:02:90:cb:77:d7:4f:88: + 10:a7:80:3d:ca:19:5c:b5:04:c9:f0:e1:1b:5a:5f:fb:61:b2: + 14:b5 +-----BEGIN CERTIFICATE----- +MIIDCTCCAnKgAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMDAeFw0wOTExMjMxNTE0 +NDhaFw0zNDExMTcxNTE0NDhaMGkxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxGTAXBgNVBAMTEFN1YiBDQSAxIFJvb3QgMTAwgZ8wDQYJKoZIhvcNAQEBBQAD +gY0AMIGJAoGBAOTVZhSIn3lBULDRoBuYv7AhNDA2cFhvi1jxuVg6zilrZbYR9w3I +psO+2w8qTsdC38kOE8AAD6+1ccS83YL8SifA7q+64Xtn3mu7rEz+iAEac071MhU6 +0Mtrl4QbbNDWkaikWocqaWE2HULMFtADnMaQXGEgi7G+tlQkW28fqVpvAgMBAAGj +gcgwgcUwHQYDVR0OBBYEFBFjob6L41YH5qOfIzlyfeMitlM5MIGSBgNVHSMEgYow +gYeAFMino4AgdGxv7BF69r4mEDcxh7B6oWSkYjBgMQswCQYDVQQGEwJERTEQMA4G +A1UECBMHSGFtYnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsT +C0RldmVsb3BtZW50MRAwDgYDVQQDEwdSb290IDEwggkAv8gPu9mgOmswDwYDVR0T +AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBrD3VtVrBORRllrVDvTodslV0F +OVpDXLRRJZrs9JPR8PaR3aN3lQx0PKl8wvZizr9YX2Yf0FXK2C3EHik6rVUsnSyP +jp7OrBd+G9EW2RJ2XC0/nXBmqjk08OwxS0taFAzFWzzIRwKQy3fXT4gQp4A9yhlc +tQTJ8OEbWl/7YbIUtQ== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_10/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Root_10/demoCA/private/cakey.pem new file mode 100644 index 0000000000..f75ccc08ef --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_10/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,78CCF9A24E7B5044 + +ppKSX6K7DHnU4EvbmBAIzWDJ35yGppjzNdWRKpB7rkGW60dW0Cw0Jmbxf1dfbUC+ +UTWtxE+i0x159jF7jGobPvLFQnAg1ZPUUIgeXJt+fqf/OghY4i8x82BdSlaKJ293 +GgwR9m1N1I2/6ydob+9KwzJhOPhmylyUyRJVAx/OF86E9G4nxtuJA1c1nzSBgwR5 +7uHU0LiY5A42iTDiMmu7Jw4vj6Cy81P88hmyoVzo4JQG8YFuJyLz2ei+DJ3/572z +BCefqDKmlmI2vvayZW1jgpLDlTwmqiIGUDBBipN4vDmqZAdEbv/9BjLkS4Svy3PU +xaFs1tFQzv8ivGpyPWU5naoTKhmMhOEAKpEi6YqWbcD/qKn1pRrYSyVyD9zNXHEK +QrXjTP+D/DMSHNJTo5WI4kxvwSZtPI97vaCTmxkrjnIXDPD5L4v9dJUdejnngsqn +cHB/C/05dR0RLEp5CHrl0hwGiIY1IgQXmGHY2HEUyQYttyJ5jdY0pdnn9n0eQxHr +9Mg3WneWC42XHw0pyqEsgiMmr8SjaF42MSrMB6y4WEVtBstn03LTdFnRIFTgZ5Mj +l/O2mSk+YUBR4CYTUTRaWpzCAZmFVy98I8KQgrhi8t96wrRe0+9tB1uC5PoDNR5P +CcgsmiEPeqolPZwOmnDdij+DcIiT43Sx2vDYGfDtqc+kur/O6noYyX8Kf7wzcpan +V4gHTCEOrlcRiEcVIxAQFDpB8CERG9fJvnBdZE9Gjepz6OatRpE/2kDZMelwRcEx +V5zeE1qNS51gdq2dE0qYkdyU1yfbNUouqtFy/z1sXU6Q5nR1r21jFQ== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Root_10/demoCA/serial b/xmlsecurity/test_docs/CAs/Root_10/demoCA/serial new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_10/demoCA/serial @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Root_10/openssl.cfg b/xmlsecurity/test_docs/CAs/Root_10/openssl.cfg new file mode 100644 index 0000000000..f48e3d5a34 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_10/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Root_7.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/cacert.pem new file mode 100644 index 0000000000..8cfffd9a6c --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/cacert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDBzCCAnCgAwIBAgIJAI3gSU2IIGPLMA0GCSqGSIb3DQEBBQUAMGAxCzAJBgNV +BAYTAkRFMRAwDgYDVQQIEwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9y +ZzEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxEDAOBgNVBAMTB1Jvb3QgMTEwHhcNMTAw +MTE0MTEzNzA1WhcNMzUwMTA4MTEzNzA2WjBgMQswCQYDVQQGEwJERTEQMA4GA1UE +CBMHSGFtYnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0Rl +dmVsb3BtZW50MRAwDgYDVQQDEwdSb290IDExMIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDKGrq6yC3tyctcBo+iz31MF2yvDiQ7YFgez8TswNvb3USOPOUPsCaB +ufVN6ULSqmGi5BzFIW7CVAj5L+iCrrwMtPyG86fKbvgdWmLepz5a4S1y+vydnQ0B +rJCNdxmLdQK+l/P7jzrH5xhcR62DPQ2lLabvmixvylHv4H6cFjJ98wIDAQABo4HI +MIHFMB0GA1UdDgQWBBToarvCkOpscCI+9vZIGwPmvremVTCBkgYDVR0jBIGKMIGH +gBToarvCkOpscCI+9vZIGwPmvremVaFkpGIwYDELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMYIJAI3gSU2IIGPLMA8GA1UdEwEB +/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAZRXdBfSqhY+xELs28/gjsZ4/mUvu +LKL3PruRCNqUgIOznEdxsQXsmLIQhEPZ4a4jd31srFD2j5gJmZ8KdeFXII9NRvIX +RpRcrl2uclHXWbIC7s6xiATDWumrL2nXB5bU4qYMZ0ybytXprIwkzqRFXUrEHcYm +OXJCSKayIviQ6G0= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Root_11/demoCA/crlnumber new file mode 100644 index 0000000000..83b33d238d --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/crlnumber @@ -0,0 +1 @@ +1000 diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Root_11/demoCA/index.txt new file mode 100644 index 0000000000..f6c52e5ac2 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/index.txt @@ -0,0 +1,35 @@ +V 350108161110Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\xC5\xB9\xC5\xBA\xC5\xBB\xC5\xBC\xC5\xBD\xC5\xBE \xEF\xAC\xB3 j\xCE\xAC\xCE\xAD\xCE\xAE +V 350108161614Z 1001 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\xC5\xB9\xC5\xBA\xC5\xBB\xC5\xBC\xC5\xBD\xC5\xBE \xEF\xAD\x86 j\xCE\xAC\xCE\xAD\xCE\xAE +V 350112144417Z 1002 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x04\x0F\x04\x10\x04\x11\x04\x12\x04\x13\x04\x14 +V 350112153942Z 1003 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x01y\x01z\x01{\x00 \x03\xA6\x03\xA7\x03\xA8\x03\xA9 +V 350112160038Z 1004 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00"\x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00s\x00" +V 350112160547Z 1005 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00"\x00"\x00d\x00o\x00u\x00b\x00l\x00e\x00 \x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00s\x00"\x00" +V 350112160921Z 1006 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00"\x00"\x00t\x00w\x00o\x00 \x00s\x00t\x00a\x00r\x00t\x00i\x00n\x00g\x00 \x00o\x00n\x00e\x00 \x00e\x00n\x00d\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00" +V 350112161153Z 1007 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00"\x00s\x00t\x00a\x00r\x00t\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e +V 350112161405Z 1008 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00e\x00n\x00d\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00" +V 350112161631Z 1009 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00"\x00q\x00u\x00o\x00t\x00e +V 350112161857Z 100A unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00d\x00o\x00u\x00b\x00l\x00e\x00 \x00"\x00"\x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00q\x00u\x00o\x00t\x00e +V 350113090237Z 100B unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00p\x00a\x00r\x00t\x00i\x00a\x00l\x00l\x00y\x00 \x00"\x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00" +V 350113094852Z 100C unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00"\x00U\x00s\x00e\x00r\x00 \x001\x001\x00,\x00 \x00s\x00t\x00a\x00r\x00t\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e +V 350113095110Z 100D unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00U\x00s\x00e\x00r\x00 \x001\x002\x00,\x00 \x00e\x00n\x00d\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00" +V 350113095308Z 100E unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00"\x00U\x00s\x00e\x00r\x00 \x001\x003\x00,\x00 \x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00s\x00" +V 350113095502Z 100F unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00U\x00s\x00e\x00r\x00 \x001\x004\x00 \x00"\x00,\x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00q\x00u\x00o\x00t\x00e\x00" +V 350113095752Z 1010 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00\\x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00s\x00\ +V 350113095922Z 1011 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00\\x00\\x00d\x00o\x00u\x00b\x00l\x00e\x00 \x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00s\x00\\x00\ +V 350113100207Z 1012 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00\\x00\\x00t\x00w\x00o\x00 \x00s\x00t\x00a\x00r\x00t\x00i\x00n\x00g\x00 \x00o\x00n\x00e\x00 \x00e\x00n\x00d\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00\ +V 350113100436Z 1013 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00\\x00s\x00t\x00a\x00r\x00t\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e +V 350113100550Z 1014 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00e\x00n\x00d\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00\ +V 350113100707Z 1015 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00\\x00q\x00u\x00o\x00t\x00e +V 350113100950Z 1016 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00d\x00o\x00u\x00b\x00l\x00e\x00 \x00\\x00\\x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00q\x00u\x00o\x00t\x00e +V 350113101153Z 1017 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00p\x00a\x00r\x00t\x00i\x00a\x00l\x00l\x00y\x00 \x00\\x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00\ +V 350113101338Z 1018 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00\\x00U\x00s\x00e\x00r\x00 \x002\x003\x00,\x00 \x00s\x00t\x00a\x00r\x00t\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e +V 350113101450Z 1019 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00U\x00s\x00e\x00r\x00 \x002\x004\x00,\x00 \x00e\x00n\x00d\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00\ +V 350113101610Z 101A unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00\\x00U\x00s\x00e\x00r\x00 \x002\x005\x00,\x00 \x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00\ +V 350113101745Z 101B unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00U\x00s\x00e\x00r\x00 \x002\x006\x00\\x00,\x00 \x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00q\x00u\x00o\x00t\x00e +V 350113101913Z 101C unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=comma, comma, comma , +V 350113102047Z 101D unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=equal CN=User 28 +V 350113102213Z 101E unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 29+OU=ooo +V 350113102601Z 101F unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00U\x00s\x00e\x00r\x00 \x003\x000\x00<\x00 \x00>\x00#\x00;\x00 \x00"\x00+\x00" +V 350113102847Z 1020 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00U\x00s\x00e\x00r\x00 \x003\x001\x00 \x00\\x00"\x00a\x00,\x00b\x00"\x00+\x00C\x00N\x00=\x00U\x00S\x00,\x00 \x00>\x00 \x00\\x00\\x00d\x00e\x00 \x00< +V 350113104059Z 1021 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00U\x00s\x00e\x00r\x00 \x001\x004\x00 \x00"\x00,\x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00q\x00u\x00o\x00t\x00e +V 111108105139Z 1022 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 35 diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Root_11/demoCA/index.txt.attr new file mode 100644 index 0000000000..8f7e63a347 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1000.pem new file mode 100644 index 0000000000..6efde26f7e --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1000.pem @@ -0,0 +1,57 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 14 16:11:10 2010 GMT + Not After : Jan 8 16:11:10 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\xC5\xB9\xC5\xBA\xC5\xBB\xC5\xBC\xC5\xBD\xC5\xBE \xEF\xAC\xB3 j\xCE\xAC\xCE\xAD\xCE\xAE + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:c5:8e:23:dc:00:60:ab:13:ac:00:15:c8:2f:13: + 04:4a:05:15:38:1e:ea:43:cb:68:8e:e3:08:cc:a4: + bb:ef:78:3e:4a:d3:3c:89:50:95:c4:16:6f:a4:89: + 97:4a:07:ad:17:b4:96:1e:54:87:82:ed:22:a4:15: + f7:cf:09:83:b7:4d:ee:75:70:8c:71:5a:b8:e7:4d: + 27:b4:f8:eb:19:67:8f:58:3f:4c:5f:b3:ca:aa:bd: + 5b:95:d7:b4:ba:d4:bc:0e:69:01:52:b9:8a:2d:55: + 83:9e:4d:3f:01:0c:f1:d7:bd:c9:82:54:d2:71:d6: + 51:9c:55:4c:a3:82:43:35:2f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + CA:DF:DA:1A:F7:9C:D8:41:19:34:69:EA:67:74:68:CA:A3:24:0F:9F + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + Signature Algorithm: sha1WithRSAEncryption + 28:3a:db:4b:fd:15:4c:bb:ea:74:b4:53:4f:75:2a:92:3c:78: + b6:86:aa:39:bc:b0:67:3a:5a:00:f1:1e:74:5c:c7:2b:19:4f: + f4:c0:4d:ff:01:4c:b2:0f:b5:49:14:c3:9a:96:ce:61:b6:c7: + 37:82:44:75:76:fc:bd:5d:74:f9:22:ae:f2:36:cb:20:b7:e3: + c8:c8:01:ae:d5:01:f6:5e:b4:cb:ca:76:fe:72:98:f3:0a:c3: + ac:76:fa:41:67:b4:5c:92:67:fa:ca:17:02:80:00:d8:b6:d5: + 01:03:89:25:97:96:60:86:0c:0b:d8:64:94:c9:77:43:28:06: + f9:4e +-----BEGIN CERTIFICATE----- +MIIClzCCAgCgAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTQxNjEx +MTBaFw0zNTAxMDgxNjExMTBaMHExCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxITAfBgNVBAMUGMW5xbrFu8W8xb3FviDvrLMgas6szq3OrjCBnzANBgkqhkiG +9w0BAQEFAAOBjQAwgYkCgYEAxY4j3ABgqxOsABXILxMESgUVOB7qQ8tojuMIzKS7 +73g+StM8iVCVxBZvpImXSgetF7SWHlSHgu0ipBX3zwmDt03udXCMcVq4500ntPjr +GWePWD9MX7PKqr1blde0utS8DmkBUrmKLVWDnk0/AQzx173JglTScdZRnFVMo4JD +NS8CAwEAAaNPME0wCwYDVR0PBAQDAgXgMB0GA1UdDgQWBBTK39oa95zYQRk0aepn +dGjKoyQPnzAfBgNVHSMEGDAWgBToarvCkOpscCI+9vZIGwPmvremVTANBgkqhkiG +9w0BAQUFAAOBgQAoOttL/RVMu+p0tFNPdSqSPHi2hqo5vLBnOloA8R50XMcrGU/0 +wE3/AUyyD7VJFMOals5htsc3gkR1dvy9XXT5Iq7yNssgt+PIyAGu1QH2XrTLynb+ +cpjzCsOsdvpBZ7Rckmf6yhcCgADYttUBA4kll5ZghgwL2GSUyXdDKAb5Tg== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1002.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1002.pem new file mode 100644 index 0000000000..037410ad79 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1002.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4098 (0x1002) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 18 14:44:17 2010 GMT + Not After : Jan 12 14:44:17 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x04\x0F\x04\x10\x04\x11\x04\x12\x04\x13\x04\x14 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:b4:d3:fd:a0:56:2b:d9:72:66:e3:fc:4b:5b:70: + fb:9c:23:10:0b:b9:8a:c4:d1:dd:1d:37:cd:20:f4: + 9d:52:c3:8f:80:14:26:c4:3e:dc:3d:af:38:86:70: + 2f:e1:54:1c:a6:5e:b6:6a:2d:73:b4:2d:88:7c:ed: + eb:63:34:bf:ef:d0:a8:e0:00:ea:f0:24:50:68:3b: + ff:03:4a:22:e0:eb:5c:a4:e8:65:e4:c7:e7:38:e9: + ce:0c:44:3e:36:08:fe:82:d8:50:b9:13:43:3b:17: + 77:09:ef:7b:cc:9f:b4:7d:5d:f7:ab:8e:ab:c0:11: + bc:7a:07:ea:98:51:c0:27:1f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 49:1F:9A:43:D9:43:B9:89:0C:00:D9:90:C8:BC:9C:67:CD:8D:3E:C6 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 2 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 03:bc:24:ba:71:8b:4f:cc:3a:60:5a:04:13:15:4e:b0:79:e7: + 94:6c:9b:3b:4c:5d:d8:26:75:f5:94:04:71:5a:3e:b9:8c:5f: + b5:3d:e0:bb:8b:64:71:8f:0d:9a:99:b8:ff:ec:14:c0:c0:ca: + 63:5a:4e:1d:75:77:7a:2f:fb:12:90:25:44:ba:d8:2f:03:39: + 86:ef:88:4a:cc:69:79:0b:ff:a6:66:83:45:08:17:0b:0c:05: + f9:25:7c:6a:30:05:b3:61:df:1a:fe:2c:ca:49:e9:73:bd:b3: + 11:6b:bf:04:b0:a6:46:76:21:40:95:5c:78:b3:aa:4b:fd:03: + ee:51 +-----BEGIN CERTIFICATE----- +MIICszCCAhygAwIBAgICEAIwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTgxNDQ0 +MTdaFw0zNTAxMTIxNDQ0MTdaMGUxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxFTATBgNVBAMeDAQPBBAEEQQSBBMEFDCBnzANBgkqhkiG9w0BAQEFAAOBjQAw +gYkCgYEAtNP9oFYr2XJm4/xLW3D7nCMQC7mKxNHdHTfNIPSdUsOPgBQmxD7cPa84 +hnAv4VQcpl62ai1ztC2IfO3rYzS/79Co4ADq8CRQaDv/A0oi4OtcpOhl5MfnOOnO +DEQ+Ngj+gthQuRNDOxd3Ce97zJ+0fV33q46rwBG8egfqmFHAJx8CAwEAAaN3MHUw +CwYDVR0PBAQDAgXgMB0GA1UdDgQWBBRJH5pD2UO5iQwA2ZDIvJxnzY0+xjAfBgNV +HSMEGDAWgBToarvCkOpscCI+9vZIGwPmvremVTAmBgNVHREEHzAdpBswGTEXMBUG +A1UEAxMOVXNlciAyIFJvb3QgMTEwDQYJKoZIhvcNAQEFBQADgYEAA7wkunGLT8w6 +YFoEExVOsHnnlGybO0xd2CZ19ZQEcVo+uYxftT3gu4tkcY8Nmpm4/+wUwMDKY1pO +HXV3ei/7EpAlRLrYLwM5hu+ISsxpeQv/pmaDRQgXCwwF+SV8ajAFs2HfGv4syknp +c72zEWu/BLCmRnYhQJVceLOqS/0D7lE= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1003.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1003.pem new file mode 100644 index 0000000000..95589b2271 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1003.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4099 (0x1003) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 18 15:39:42 2010 GMT + Not After : Jan 12 15:39:42 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x01y\x01z\x01{\x00 \x03\xA6\x03\xA7\x03\xA8\x03\xA9 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:d6:d8:62:3c:69:c9:dd:93:b3:e9:65:63:89:03: + 4e:f8:8a:e1:8b:9d:92:c6:43:ca:8e:af:fd:6e:9c: + c7:66:31:48:f4:ce:5e:be:38:c5:6c:1b:48:c9:61: + f5:78:8a:e9:74:ac:a8:98:9c:83:f9:b0:74:e3:25: + 7c:5a:bb:df:5f:73:ef:fc:a0:dc:6a:ac:07:a2:b8: + 52:ea:7a:42:ba:9f:74:3c:00:cc:26:46:ba:90:5d: + 45:78:02:57:e7:47:9f:8e:94:9c:5a:31:ab:f3:ff: + bc:9f:7f:d9:b0:a6:f6:86:70:a6:9d:52:ff:c8:19: + 47:88:75:78:6a:73:d5:97:e9 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + E3:01:F6:1E:51:6D:FC:DB:BF:82:A9:12:21:4B:E2:46:FF:E8:EE:FF + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 1 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 68:f0:88:18:d5:98:63:da:42:39:47:bf:51:22:f6:0b:8e:46: + b0:8c:83:b0:4d:07:a4:e3:a9:66:76:4d:41:23:1a:6b:dc:d8: + d1:85:b1:bf:4f:f9:e6:01:4a:36:a9:a3:26:2d:0b:33:cc:36: + 97:c6:40:b6:77:26:1c:06:f2:1b:fa:0a:ef:5c:61:8d:0d:9c: + 3c:d3:0f:db:dd:60:69:8c:24:c6:70:bc:f8:3b:38:19:90:7a: + f3:4f:7e:7c:b7:69:b6:0f:55:e1:4b:da:77:cd:b1:fe:5f:f1: + c1:8a:f8:3d:26:10:3d:40:6f:83:17:0a:d8:dd:da:a1:27:10: + a1:73 +-----BEGIN CERTIFICATE----- +MIICtzCCAiCgAwIBAgICEAMwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTgxNTM5 +NDJaFw0zNTAxMTIxNTM5NDJaMGkxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxGTAXBgNVBAMeEAF5AXoBewAgA6YDpwOoA6kwgZ8wDQYJKoZIhvcNAQEBBQAD +gY0AMIGJAoGBANbYYjxpyd2Ts+llY4kDTviK4YudksZDyo6v/W6cx2YxSPTOXr44 +xWwbSMlh9XiK6XSsqJicg/mwdOMlfFq7319z7/yg3GqsB6K4Uup6QrqfdDwAzCZG +upBdRXgCV+dHn46UnFoxq/P/vJ9/2bCm9oZwpp1S/8gZR4h1eGpz1ZfpAgMBAAGj +dzB1MAsGA1UdDwQEAwIF4DAdBgNVHQ4EFgQU4wH2HlFt/Nu/gqkSIUviRv/o7v8w +HwYDVR0jBBgwFoAU6Gq7wpDqbHAiPvb2SBsD5r63plUwJgYDVR0RBB8wHaQbMBkx +FzAVBgNVBAMTDlVzZXIgMSBSb290IDExMA0GCSqGSIb3DQEBBQUAA4GBAGjwiBjV +mGPaQjlHv1Ei9guORrCMg7BNB6TjqWZ2TUEjGmvc2NGFsb9P+eYBSjapoyYtCzPM +NpfGQLZ3JhwG8hv6Cu9cYY0NnDzTD9vdYGmMJMZwvPg7OBmQevNPfny3abYPVeFL +2nfNsf5f8cGK+D0mED1Ab4MXCtjd2qEnEKFz +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1004.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1004.pem new file mode 100644 index 0000000000..6f57ca6845 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1004.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4100 (0x1004) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 18 16:00:38 2010 GMT + Not After : Jan 12 16:00:38 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00"\x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00s\x00" + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:c9:ff:37:16:4d:7a:ad:59:bd:f2:c4:dc:4f:79: + 6a:f6:21:c7:ef:cd:af:f1:39:34:24:92:f4:46:d3: + 8b:43:31:55:11:3e:22:2b:85:19:38:ed:0b:35:3c: + 73:fc:b9:17:e8:73:99:21:a2:20:30:b4:e9:11:c6: + 7a:61:fa:fa:fe:eb:c8:30:c4:73:5f:77:f2:fc:42: + b7:10:29:ac:9e:8a:c2:df:25:9b:44:17:05:a3:39: + d9:1b:58:62:fb:2c:86:07:f7:f0:28:7b:5a:38:1b: + 6a:de:88:fb:ad:32:f4:53:e2:a1:c5:0f:68:db:64: + ae:39:2a:5e:02:d0:b5:38:07 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 86:2F:46:D0:A9:F9:3F:22:BD:57:83:51:35:F9:67:11:A2:00:AB:33 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 3 Root 11 + Signature Algorithm: sha1WithRSAEncryption + bb:f6:61:ae:30:94:3a:4a:d6:d5:cb:b5:50:bb:ca:0e:ab:9f: + 09:e9:78:d4:2f:20:fe:18:4e:d8:61:db:97:28:a9:d9:dc:e5: + 06:f8:6c:41:c2:5a:95:53:47:7e:a7:73:c9:45:4f:6b:30:fc: + fd:17:9a:7b:a9:d8:27:57:a9:fd:8d:e7:7e:4b:3e:98:11:42: + 00:39:1a:55:4b:3d:a5:de:75:3c:43:5a:33:10:d3:cf:4e:04: + 0a:71:d4:93:2b:0b:2b:15:82:7b:04:46:9b:50:da:18:84:66: + 31:75:36:5b:09:eb:82:5d:7d:e1:35:a3:a4:6c:b2:ac:c8:fa: + bd:5f +-----BEGIN CERTIFICATE----- +MIICyzCCAjSgAwIBAgICEAQwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTgxNjAw +MzhaFw0zNTAxMTIxNjAwMzhaMH0xCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxLTArBgNVBAMeJAAiAGUAbgBjAGwAbwBzAGkAbgBnACAAcQB1AG8AdABlAHMA +IjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAyf83Fk16rVm98sTcT3lq9iHH +782v8Tk0JJL0RtOLQzFVET4iK4UZOO0LNTxz/LkX6HOZIaIgMLTpEcZ6Yfr6/uvI +MMRzX3fy/EK3ECmsnorC3yWbRBcFoznZG1hi+yyGB/fwKHtaOBtq3oj7rTL0U+Kh +xQ9o22SuOSpeAtC1OAcCAwEAAaN3MHUwCwYDVR0PBAQDAgXgMB0GA1UdDgQWBBSG +L0bQqfk/Ir1Xg1E1+WcRogCrMzAfBgNVHSMEGDAWgBToarvCkOpscCI+9vZIGwPm +vremVTAmBgNVHREEHzAdpBswGTEXMBUGA1UEAxMOVXNlciAzIFJvb3QgMTEwDQYJ +KoZIhvcNAQEFBQADgYEAu/ZhrjCUOkrW1cu1ULvKDqufCel41C8g/hhO2GHblyip +2dzlBvhsQcJalVNHfqdzyUVPazD8/Reae6nYJ1ep/Y3nfks+mBFCADkaVUs9pd51 +PENaMxDTz04ECnHUkysLKxWCewRGm1DaGIRmMXU2Wwnrgl194TWjpGyyrMj6vV8= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1005.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1005.pem new file mode 100644 index 0000000000..3a2f7522d1 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1005.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4101 (0x1005) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 18 16:05:47 2010 GMT + Not After : Jan 12 16:05:47 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00"\x00"\x00d\x00o\x00u\x00b\x00l\x00e\x00 \x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00s\x00"\x00" + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:de:4d:31:93:c5:1b:7c:2b:85:86:da:89:3d:06: + 6f:6d:44:a5:de:6c:6a:06:28:b0:96:7b:40:34:01: + af:e4:b1:f4:93:f1:25:78:b0:43:ea:92:2a:87:60: + e8:be:7e:c9:b6:02:f8:14:93:1b:b8:5f:cb:2c:24: + e2:80:24:f0:5c:6d:77:f2:dc:ef:90:d6:d1:78:22: + 53:f0:7f:45:ad:f2:1a:9d:25:08:13:c8:62:6b:9e: + 88:79:3d:9e:b4:0a:05:11:79:7d:a1:b2:46:89:f3: + 45:ce:f3:22:2e:17:ab:e1:a9:b1:04:93:3b:f3:ca: + e6:60:c0:fd:91:7f:34:80:65 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + C1:6E:6A:FB:5A:B1:0C:67:07:C8:7E:F1:8D:86:F6:D0:27:56:6D:73 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 4 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 61:72:4b:33:1d:60:91:08:19:4f:ff:ec:8e:9e:83:71:d7:00: + 96:0a:b5:82:b7:8c:a6:3f:70:64:36:ac:25:a7:f1:a9:83:f1: + 63:f8:29:06:fa:58:86:8a:fd:25:9e:77:38:dd:c7:3b:cd:68: + 91:8e:f4:57:42:c9:6b:88:87:ec:24:57:38:84:fb:c0:d9:bc: + 6c:1c:6e:9d:9d:b9:da:cc:7e:fe:f9:bd:29:be:14:26:6f:63: + 1f:6f:6a:f1:dd:fd:d2:03:69:f2:36:e1:35:e0:57:72:d5:e3: + 09:ee:6a:08:45:b4:73:e9:d1:18:c2:38:1d:86:53:53:6d:bf: + f0:1e +-----BEGIN CERTIFICATE----- +MIIC3jCCAkegAwIBAgICEAUwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTgxNjA1 +NDdaFw0zNTAxMTIxNjA1NDdaMIGPMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MT8wPQYDVQQDHjYAIgAiAGQAbwB1AGIAbABlACAAZQBuAGMAbABvAHMAaQBu +AGcAIABxAHUAbwB0AGUAcwAiACIwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB +AN5NMZPFG3wrhYbaiT0Gb21Epd5sagYosJZ7QDQBr+Sx9JPxJXiwQ+qSKodg6L5+ +ybYC+BSTG7hfyywk4oAk8Fxtd/Lc75DW0XgiU/B/Ra3yGp0lCBPIYmueiHk9nrQK +BRF5faGyRonzRc7zIi4Xq+GpsQSTO/PK5mDA/ZF/NIBlAgMBAAGjdzB1MAsGA1Ud +DwQEAwIF4DAdBgNVHQ4EFgQUwW5q+1qxDGcHyH7xjYb20CdWbXMwHwYDVR0jBBgw +FoAU6Gq7wpDqbHAiPvb2SBsD5r63plUwJgYDVR0RBB8wHaQbMBkxFzAVBgNVBAMT +DlVzZXIgNCBSb290IDExMA0GCSqGSIb3DQEBBQUAA4GBAGFySzMdYJEIGU//7I6e +g3HXAJYKtYK3jKY/cGQ2rCWn8amD8WP4KQb6WIaK/SWedzjdxzvNaJGO9FdCyWuI +h+wkVziE+8DZvGwcbp2dudrMfv75vSm+FCZvYx9vavHd/dIDafI24TXgV3LV4wnu +aghFtHPp0RjCOB2GU1Ntv/Ae +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1006.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1006.pem new file mode 100644 index 0000000000..cb72b8d161 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1006.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4102 (0x1006) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 18 16:09:21 2010 GMT + Not After : Jan 12 16:09:21 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00"\x00"\x00t\x00w\x00o\x00 \x00s\x00t\x00a\x00r\x00t\x00i\x00n\x00g\x00 \x00o\x00n\x00e\x00 \x00e\x00n\x00d\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00" + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:d1:a4:91:c7:28:84:f8:54:63:09:1f:bc:2e:4e: + a3:be:54:01:42:2e:f7:ef:4f:b8:46:a9:35:b1:b3: + 29:0e:8b:f7:b5:fa:b7:71:5b:33:03:ac:e6:b5:f6: + ba:f5:ba:21:72:ed:7d:ea:f0:f1:2c:55:2a:a9:c6: + d8:54:ef:12:f0:f5:37:ca:57:b2:3c:ce:7c:5a:57: + 86:68:a2:51:82:80:bd:58:a5:04:1c:e8:cf:f6:5b: + 4e:d2:6a:79:63:eb:ac:52:7c:61:8c:fe:0a:6b:b2: + f6:16:9c:94:ae:a6:f6:69:b9:d5:0b:26:0d:01:7f: + 62:d2:58:c2:02:53:25:63:0d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 45:DF:D7:35:D1:13:E4:8F:E3:0D:E3:7E:A9:9A:5D:56:00:64:4E:43 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 5 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 9d:bd:dc:dc:8e:a8:e8:e4:15:cb:14:c1:6a:ab:d8:ab:e6:e5: + 4f:f5:a8:8b:2c:ab:80:e2:31:f9:89:d8:12:ba:9c:4f:b3:f5: + bb:7e:ee:8b:df:58:d3:b2:ee:f8:c5:46:c3:5d:2e:a9:35:d0: + 7a:1e:80:18:14:4d:78:6e:f1:c8:9a:51:db:86:3e:2c:04:4a: + 0a:2f:f1:7a:01:e3:1b:31:d7:1d:f1:32:c4:04:db:b9:7e:c4: + fd:b0:c1:41:3f:8a:b3:88:4f:4a:9c:a6:38:11:2a:4a:0f:8b: + d0:9a:8a:2c:33:fe:7f:42:b5:93:8d:54:df:de:2b:b1:08:5c: + d9:0d +-----BEGIN CERTIFICATE----- +MIIC6DCCAlGgAwIBAgICEAYwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTgxNjA5 +MjFaFw0zNTAxMTIxNjA5MjFaMIGZMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MUkwRwYDVQQDHkAAIgAiAHQAdwBvACAAcwB0AGEAcgB0AGkAbgBnACAAbwBu +AGUAIABlAG4AZABpAG4AZwAgAHEAdQBvAHQAZQAiMIGfMA0GCSqGSIb3DQEBAQUA +A4GNADCBiQKBgQDRpJHHKIT4VGMJH7wuTqO+VAFCLvfvT7hGqTWxsykOi/e1+rdx +WzMDrOa19rr1uiFy7X3q8PEsVSqpxthU7xLw9TfKV7I8znxaV4ZoolGCgL1YpQQc +6M/2W07Sanlj66xSfGGM/gprsvYWnJSupvZpudULJg0Bf2LSWMICUyVjDQIDAQAB +o3cwdTALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFEXf1zXRE+SP4w3jfqmaXVYAZE5D +MB8GA1UdIwQYMBaAFOhqu8KQ6mxwIj729kgbA+a+t6ZVMCYGA1UdEQQfMB2kGzAZ +MRcwFQYDVQQDEw5Vc2VyIDUgUm9vdCAxMTANBgkqhkiG9w0BAQUFAAOBgQCdvdzc +jqjo5BXLFMFqq9ir5uVP9aiLLKuA4jH5idgSupxPs/W7fu6L31jTsu74xUbDXS6p +NdB6HoAYFE14bvHImlHbhj4sBEoKL/F6AeMbMdcd8TLEBNu5fsT9sMFBP4qziE9K +nKY4ESpKD4vQmoosM/5/QrWTjVTf3iuxCFzZDQ== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1007.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1007.pem new file mode 100644 index 0000000000..ce9b36d12d --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1007.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4103 (0x1007) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 18 16:11:53 2010 GMT + Not After : Jan 12 16:11:53 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00"\x00s\x00t\x00a\x00r\x00t\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:d1:99:9c:20:2e:65:ee:0f:ce:cb:8a:d8:70:c8: + 04:3c:ac:2f:14:7c:6c:8f:5e:95:36:f8:53:74:5b: + 88:bf:a1:43:73:04:ab:3a:42:b4:7c:2c:3c:3b:63: + 7e:ef:82:c5:bb:b1:28:9b:8b:b7:29:72:3d:30:08: + e9:a2:d7:4b:08:e2:2e:e6:d4:9f:75:29:31:23:be: + b4:30:5d:94:30:41:38:a1:d5:34:bc:69:f5:d8:8d: + c6:08:cc:28:4a:92:22:2b:19:89:f5:ad:7c:49:89: + b3:63:c6:e5:6c:86:d7:62:05:1b:97:db:2d:fb:c2: + 47:e5:51:a6:f0:50:6f:e3:53 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 5F:DA:34:F6:6F:BA:9E:12:99:DC:02:2A:4C:3E:8C:0D:14:A1:9B:2B + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 6 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 24:af:11:b6:1a:5c:d1:bf:70:93:85:c0:2e:10:96:4d:b7:ad: + 4e:d7:c4:7e:87:a1:3b:20:d7:bf:04:07:cc:91:13:0c:ad:66: + 08:d6:2e:b6:d0:aa:d0:45:0e:c0:92:3d:7c:a6:82:19:04:3c: + 9a:b3:5e:e8:fe:9e:5c:d6:17:75:73:e3:3c:64:0c:ae:5d:92: + 2a:eb:0e:ef:04:f5:ce:a5:7f:1f:2f:1d:05:a0:70:f4:24:80: + c3:38:35:2d:e5:ac:a7:11:4a:3e:a2:b2:d1:14:91:ba:b0:d8: + 5f:be:80:8a:34:2c:72:fb:00:47:88:47:9e:34:65:12:ad:9f: + ff:99 +-----BEGIN CERTIFICATE----- +MIICxTCCAi6gAwIBAgICEAcwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTgxNjEx +NTNaFw0zNTAxMTIxNjExNTNaMHcxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxJzAlBgNVBAMeHgAiAHMAdABhAHIAdABpAG4AZwAgAHEAdQBvAHQAZTCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0ZmcIC5l7g/Oy4rYcMgEPKwvFHxsj16V +NvhTdFuIv6FDcwSrOkK0fCw8O2N+74LFu7Eom4u3KXI9MAjpotdLCOIu5tSfdSkx +I760MF2UMEE4odU0vGn12I3GCMwoSpIiKxmJ9a18SYmzY8blbIbXYgUbl9st+8JH +5VGm8FBv41MCAwEAAaN3MHUwCwYDVR0PBAQDAgXgMB0GA1UdDgQWBBRf2jT2b7qe +EpncAipMPowNFKGbKzAfBgNVHSMEGDAWgBToarvCkOpscCI+9vZIGwPmvremVTAm +BgNVHREEHzAdpBswGTEXMBUGA1UEAxMOVXNlciA2IFJvb3QgMTEwDQYJKoZIhvcN +AQEFBQADgYEAJK8Rthpc0b9wk4XALhCWTbetTtfEfoehOyDXvwQHzJETDK1mCNYu +ttCq0EUOwJI9fKaCGQQ8mrNe6P6eXNYXdXPjPGQMrl2SKusO7wT1zqV/Hy8dBaBw +9CSAwzg1LeWspxFKPqKy0RSRurDYX76AijQscvsAR4hHnjRlEq2f/5k= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1008.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1008.pem new file mode 100644 index 0000000000..8d6f2bd25c --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1008.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4104 (0x1008) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 18 16:14:05 2010 GMT + Not After : Jan 12 16:14:05 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00e\x00n\x00d\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00" + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:a6:a8:3f:60:a7:9a:3b:20:c9:2c:8c:4f:cd:11: + 1f:0d:a9:2a:2c:eb:12:80:0c:55:8a:4d:06:ef:b2: + 5f:2e:47:be:0d:10:22:8a:15:57:29:4a:90:63:f9: + 1c:13:85:47:c7:c9:b9:76:09:10:a9:b1:94:5c:8d: + c9:f4:01:26:43:e4:d4:98:d6:00:1a:d4:cd:2a:d1: + cd:7e:4c:4e:ab:18:78:5a:fb:b2:ec:a3:87:a1:0e: + 84:3f:70:cf:ca:02:24:c8:d7:1b:83:a3:ac:a5:f0: + 10:c5:de:b7:a2:6c:0b:0c:9d:ab:32:a3:1a:c9:ae: + 9b:48:a8:65:cd:50:db:0b:cf + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 91:32:56:26:62:63:A1:32:B0:BC:D0:91:F1:D8:F2:94:CB:10:F1:91 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 7 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 4c:d5:2f:ab:fb:83:f8:11:c9:d2:df:aa:dc:e9:b8:38:2e:53: + e1:3a:5b:bb:0a:bf:72:f7:47:b5:57:de:82:8a:e6:bb:7d:62: + af:1b:9c:8e:4a:f5:cf:0b:ac:e9:06:16:ca:59:f1:7f:d7:45: + c0:88:84:ee:f4:c7:8b:e0:39:aa:c7:b7:95:b9:fe:a2:4a:3a: + 41:df:d0:02:bf:6f:54:30:9a:9a:0a:a6:04:5f:f4:17:52:d6: + c2:39:43:5e:b9:a3:86:0f:3d:ad:eb:a3:81:f4:cc:90:29:17: + dc:46:5e:6b:9c:f6:70:0f:b2:0f:dc:0f:9c:9f:09:6c:fa:31: + 6c:01 +-----BEGIN CERTIFICATE----- +MIICwTCCAiqgAwIBAgICEAgwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTgxNjE0 +MDVaFw0zNTAxMTIxNjE0MDVaMHMxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxIzAhBgNVBAMeGgBlAG4AZABpAG4AZwAgAHEAdQBvAHQAZQAiMIGfMA0GCSqG +SIb3DQEBAQUAA4GNADCBiQKBgQCmqD9gp5o7IMksjE/NER8NqSos6xKADFWKTQbv +sl8uR74NECKKFVcpSpBj+RwThUfHybl2CRCpsZRcjcn0ASZD5NSY1gAa1M0q0c1+ +TE6rGHha+7Lso4ehDoQ/cM/KAiTI1xuDo6yl8BDF3reibAsMnasyoxrJrptIqGXN +UNsLzwIDAQABo3cwdTALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFJEyViZiY6EysLzQ +kfHY8pTLEPGRMB8GA1UdIwQYMBaAFOhqu8KQ6mxwIj729kgbA+a+t6ZVMCYGA1Ud +EQQfMB2kGzAZMRcwFQYDVQQDEw5Vc2VyIDcgUm9vdCAxMTANBgkqhkiG9w0BAQUF +AAOBgQBM1S+r+4P4EcnS36rc6bg4LlPhOlu7Cr9y90e1V96Ciua7fWKvG5yOSvXP +C6zpBhbKWfF/10XAiITu9MeL4Dmqx7eVuf6iSjpB39ACv29UMJqaCqYEX/QXUtbC +OUNeuaOGDz2t66OB9MyQKRfcRl5rnPZwD7IP3A+cnwls+jFsAQ== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1009.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1009.pem new file mode 100644 index 0000000000..c1a94dae5d --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1009.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4105 (0x1009) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 18 16:16:31 2010 GMT + Not After : Jan 12 16:16:31 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00"\x00q\x00u\x00o\x00t\x00e + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:b4:3b:c7:b0:6c:b5:f2:b3:a5:79:89:54:de:af: + 03:3c:0e:c9:57:15:8e:73:2a:48:83:18:59:ce:b4: + 12:fb:5c:92:28:69:75:18:f9:0f:24:15:95:38:b2: + 4c:81:07:90:97:3b:d7:3a:ab:a6:92:5a:9f:5a:1f: + fe:14:ac:4d:b5:5e:6a:a6:0f:98:55:08:07:09:07: + a5:fb:79:9e:a0:2d:73:99:92:ad:6e:bc:75:36:d0: + b5:f1:1c:91:3a:d4:49:8a:60:1e:a7:01:2f:bc:d9: + cd:b4:f4:70:b4:38:d1:3c:d3:ee:00:df:b3:83:45: + 63:5c:5d:28:47:bc:b1:b9:57 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + D6:18:38:7B:14:4B:D6:72:42:A9:53:E2:1D:BE:81:88:26:DB:0A:06 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 8 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 98:f3:ac:db:7b:a0:00:d2:58:be:74:21:ff:09:29:4c:0c:1a: + 7a:1f:dd:e2:f3:f4:9a:52:5d:da:ac:10:30:f9:b8:93:10:60: + 46:bf:48:47:bd:af:87:a1:d9:c6:46:81:b3:0d:a4:f8:ba:ca: + 17:7c:f2:f9:46:03:62:7f:32:6b:f0:7c:75:a4:05:44:cb:10: + 42:36:ce:12:c0:b9:e5:5f:e0:7b:c6:c8:39:5c:0c:50:30:a0: + f6:fe:e1:a2:e6:00:b3:fc:86:56:11:66:d8:41:81:e3:4e:15: + e5:68:9d:1c:b0:c4:4f:ab:86:75:55:fa:39:58:3f:7c:68:03: + e0:76 +-----BEGIN CERTIFICATE----- +MIICwTCCAiqgAwIBAgICEAkwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTgxNjE2 +MzFaFw0zNTAxMTIxNjE2MzFaMHMxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxIzAhBgNVBAMeGgBtAGkAZABkAGwAZQAgACIAcQB1AG8AdABlMIGfMA0GCSqG +SIb3DQEBAQUAA4GNADCBiQKBgQC0O8ewbLXys6V5iVTerwM8DslXFY5zKkiDGFnO +tBL7XJIoaXUY+Q8kFZU4skyBB5CXO9c6q6aSWp9aH/4UrE21XmqmD5hVCAcJB6X7 +eZ6gLXOZkq1uvHU20LXxHJE61EmKYB6nAS+82c209HC0ONE80+4A37ODRWNcXShH +vLG5VwIDAQABo3cwdTALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFNYYOHsUS9ZyQqlT +4h2+gYgm2woGMB8GA1UdIwQYMBaAFOhqu8KQ6mxwIj729kgbA+a+t6ZVMCYGA1Ud +EQQfMB2kGzAZMRcwFQYDVQQDEw5Vc2VyIDggUm9vdCAxMTANBgkqhkiG9w0BAQUF +AAOBgQCY86zbe6AA0li+dCH/CSlMDBp6H93i8/SaUl3arBAw+biTEGBGv0hHva+H +odnGRoGzDaT4usoXfPL5RgNifzJr8Hx1pAVEyxBCNs4SwLnlX+B7xsg5XAxQMKD2 +/uGi5gCz/IZWEWbYQYHjThXlaJ0csMRPq4Z1Vfo5WD98aAPgdg== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100A.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100A.pem new file mode 100644 index 0000000000..a3a79bf831 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100A.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4106 (0x100a) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 18 16:18:57 2010 GMT + Not After : Jan 12 16:18:57 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00d\x00o\x00u\x00b\x00l\x00e\x00 \x00"\x00"\x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00q\x00u\x00o\x00t\x00e + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:e5:3f:d4:e1:d6:26:2a:c9:40:1d:34:3c:1e:e8: + f4:54:67:6b:6c:a5:b7:fe:04:bb:cb:0e:c0:2d:26: + 61:c1:81:80:9d:da:1b:fd:d3:7a:7a:57:78:c5:f6: + e6:4b:ad:2d:a2:8d:49:b3:ac:18:ca:1c:25:67:44: + 7c:8e:b5:ab:ec:f7:a8:da:b7:37:ed:77:76:b2:8f: + bb:15:b2:e3:45:5f:b2:2a:aa:27:b7:f1:bc:37:8f: + b7:b4:c5:ff:45:fd:67:04:25:47:2c:1a:a7:63:1e: + 97:f6:ac:d7:39:cf:ef:24:63:a1:87:9b:36:97:92: + fa:d9:4d:a9:fa:dd:c9:fb:75 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 62:F1:43:E3:B1:7B:98:0D:69:A4:8F:CF:32:F7:6D:E6:88:D6:23:90 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 9 Root 11 + Signature Algorithm: sha1WithRSAEncryption + ab:46:88:13:e8:02:63:4e:f2:a0:5a:48:7e:35:a4:c2:f8:55: + 33:cb:ef:45:55:30:81:a1:9e:c2:c7:43:cd:19:23:1f:df:3f: + 8b:b8:7e:69:5e:98:06:b1:47:dd:e5:05:e2:3a:19:cf:af:e3: + dd:7b:75:e5:53:b0:bc:4e:58:40:bf:3b:d2:9c:7f:9e:b1:66: + f8:3f:58:c4:5f:ab:be:1f:03:fb:89:47:a4:25:8a:1e:10:e0: + 20:33:70:07:13:92:32:e1:bf:92:6a:d5:89:03:2c:ad:e1:85: + 8c:b3:1d:ee:0c:35:70:2f:aa:e5:e0:77:97:b0:9b:a3:0d:22: + 6f:dc +-----BEGIN CERTIFICATE----- +MIIC0jCCAjugAwIBAgICEAowDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTgxNjE4 +NTdaFw0zNTAxMTIxNjE4NTdaMIGDMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MTMwMQYDVQQDHioAZABvAHUAYgBsAGUAIAAiACIAbQBpAGQAZABsAGUAIABx +AHUAbwB0AGUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOU/1OHWJirJQB00 +PB7o9FRna2ylt/4Eu8sOwC0mYcGBgJ3aG/3TenpXeMX25kutLaKNSbOsGMocJWdE +fI61q+z3qNq3N+13drKPuxWy40VfsiqqJ7fxvDePt7TF/0X9ZwQlRywap2Mel/as +1znP7yRjoYebNpeS+tlNqfrdyft1AgMBAAGjdzB1MAsGA1UdDwQEAwIF4DAdBgNV +HQ4EFgQUYvFD47F7mA1ppI/PMvdt5ojWI5AwHwYDVR0jBBgwFoAU6Gq7wpDqbHAi +Pvb2SBsD5r63plUwJgYDVR0RBB8wHaQbMBkxFzAVBgNVBAMTDlVzZXIgOSBSb290 +IDExMA0GCSqGSIb3DQEBBQUAA4GBAKtGiBPoAmNO8qBaSH41pML4VTPL70VVMIGh +nsLHQ80ZIx/fP4u4fmlemAaxR93lBeI6Gc+v4917deVTsLxOWEC/O9Kcf56xZvg/ +WMRfq74fA/uJR6Qlih4Q4CAzcAcTkjLhv5Jq1YkDLK3hhYyzHe4MNXAvquXgd5ew +m6MNIm/c +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100B.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100B.pem new file mode 100644 index 0000000000..75684732d7 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100B.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4107 (0x100b) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 09:02:37 2010 GMT + Not After : Jan 13 09:02:37 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00p\x00a\x00r\x00t\x00i\x00a\x00l\x00l\x00y\x00 \x00"\x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00" + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:ae:9f:8e:b8:88:8e:ed:53:aa:2a:2c:ed:f1:6c: + 99:47:9f:ab:8b:4e:8e:d8:2e:c2:78:2c:54:f9:29: + 14:27:b9:6a:3c:33:3f:06:51:ba:76:15:0a:16:60: + db:f2:f0:db:af:5b:38:be:18:42:b4:31:02:ba:6f: + 19:00:57:be:d0:f3:7c:6b:34:36:e8:7c:45:77:0d: + f5:d0:7c:0e:23:64:7c:59:02:5c:54:15:71:82:be: + 98:3f:c9:2d:f0:9e:d5:f0:32:02:44:61:5b:2f:71: + 16:13:9a:b3:2b:28:ff:d5:d8:3d:00:9c:eb:ec:b7: + 04:e2:b6:15:42:45:e5:ef:3f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 8C:2C:B6:8B:82:43:DC:41:EC:AC:D4:75:E8:DA:D8:3F:A9:A0:F5:31 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 10 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 48:a6:51:46:5b:44:a5:be:18:ed:8f:d4:c6:d2:3c:86:8f:e7: + e5:f4:a2:5d:51:aa:00:9b:bc:d8:b1:d3:f4:24:a0:a1:0d:80: + 2e:7e:62:26:ee:8c:4b:bd:79:0c:39:bd:6e:af:db:92:b6:03: + b1:b0:49:95:a7:59:28:54:30:33:fc:7e:2f:0f:a2:ce:90:27: + 29:b9:d8:3f:99:36:e9:81:9f:f5:fa:cb:f9:f2:05:b5:48:60: + 4d:50:4d:1e:ba:45:fd:f1:99:84:a6:79:0b:6b:76:eb:73:9d: + 5c:47:27:be:0d:23:0b:97:cc:9d:5a:80:fa:9b:ff:66:e7:37: + 60:a4 +-----BEGIN CERTIFICATE----- +MIIC3zCCAkigAwIBAgICEAswDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkwOTAy +MzdaFw0zNTAxMTMwOTAyMzdaMIGPMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MT8wPQYDVQQDHjYAcABhAHIAdABpAGEAbABsAHkAIAAiAGUAbgBjAGwAbwBz +AGkAbgBnACAAcQB1AG8AdABlACIwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB +AK6fjriIju1Tqios7fFsmUefq4tOjtguwngsVPkpFCe5ajwzPwZRunYVChZg2/Lw +269bOL4YQrQxArpvGQBXvtDzfGs0Nuh8RXcN9dB8DiNkfFkCXFQVcYK+mD/JLfCe +1fAyAkRhWy9xFhOasyso/9XYPQCc6+y3BOK2FUJF5e8/AgMBAAGjeDB2MAsGA1Ud +DwQEAwIF4DAdBgNVHQ4EFgQUjCy2i4JD3EHsrNR16NrYP6mg9TEwHwYDVR0jBBgw +FoAU6Gq7wpDqbHAiPvb2SBsD5r63plUwJwYDVR0RBCAwHqQcMBoxGDAWBgNVBAMT +D1VzZXIgMTAgUm9vdCAxMTANBgkqhkiG9w0BAQUFAAOBgQBIplFGW0Slvhjtj9TG +0jyGj+fl9KJdUaoAm7zYsdP0JKChDYAufmIm7oxLvXkMOb1ur9uStgOxsEmVp1ko +VDAz/H4vD6LOkCcpudg/mTbpgZ/1+sv58gW1SGBNUE0eukX98ZmEpnkLa3brc51c +Rye+DSMLl8ydWoD6m/9m5zdgpA== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100C.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100C.pem new file mode 100644 index 0000000000..115190ca67 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100C.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4108 (0x100c) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 09:48:52 2010 GMT + Not After : Jan 13 09:48:52 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00"\x00U\x00s\x00e\x00r\x00 \x001\x001\x00,\x00 \x00s\x00t\x00a\x00r\x00t\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:e2:8b:a9:94:06:b0:cb:e7:1b:a3:fd:7c:70:d1: + 66:e6:2d:aa:c7:ec:2e:e3:08:c3:39:3f:48:47:fd: + 09:67:2d:16:17:87:c0:e3:4d:c1:cc:6b:3f:c4:7b: + 74:d5:71:70:d6:74:8a:a2:17:fd:39:78:f8:c7:b3: + 42:54:ac:f7:07:d7:6f:55:da:03:15:11:e0:c2:d8: + 95:d2:87:c3:9c:3d:94:96:9d:01:81:5d:61:43:aa: + 4c:92:d5:68:aa:6c:73:88:52:7b:ee:9b:76:65:0d: + 2a:ae:3d:83:71:41:44:8b:23:7d:a6:f9:3c:81:56: + 6c:9b:52:96:87:c8:97:18:8d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 48:89:BE:3C:AA:C9:5A:38:6B:CA:FA:C8:B2:BB:F7:E1:44:4B:7B:08 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 11 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 23:c9:5b:f5:9f:59:ff:97:0b:79:35:2d:32:db:b7:4b:b1:c9: + 2b:1e:cf:88:7b:b4:4e:f0:ed:13:a3:64:85:8f:d6:70:b5:ed: + 2a:57:92:a0:b4:14:96:48:7a:aa:a4:19:59:df:d9:a9:0f:86: + a3:e5:ec:b5:67:ef:c3:ee:23:dd:c3:3e:24:86:6c:09:03:59: + ab:93:d6:c7:0a:4c:ef:c5:4a:be:d6:ff:0f:2e:81:8e:18:d5: + 44:21:3a:0e:86:04:aa:86:8a:38:1e:d6:07:75:d0:08:be:ef: + 29:7d:d2:fc:85:8d:0c:d3:bd:ea:47:be:40:bb:fa:2f:29:fc: + c6:d8 +-----BEGIN CERTIFICATE----- +MIIC2TCCAkKgAwIBAgICEAwwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkwOTQ4 +NTJaFw0zNTAxMTMwOTQ4NTJaMIGJMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MTkwNwYDVQQDHjAAIgBVAHMAZQByACAAMQAxACwAIABzAHQAYQByAHQAaQBu +AGcAIABxAHUAbwB0AGUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOKLqZQG +sMvnG6P9fHDRZuYtqsfsLuMIwzk/SEf9CWctFheHwONNwcxrP8R7dNVxcNZ0iqIX +/Tl4+MezQlSs9wfXb1XaAxUR4MLYldKHw5w9lJadAYFdYUOqTJLVaKpsc4hSe+6b +dmUNKq49g3FBRIsjfab5PIFWbJtSlofIlxiNAgMBAAGjeDB2MAsGA1UdDwQEAwIF +4DAdBgNVHQ4EFgQUSIm+PKrJWjhryvrIsrv34URLewgwHwYDVR0jBBgwFoAU6Gq7 +wpDqbHAiPvb2SBsD5r63plUwJwYDVR0RBCAwHqQcMBoxGDAWBgNVBAMTD1VzZXIg +MTEgUm9vdCAxMTANBgkqhkiG9w0BAQUFAAOBgQAjyVv1n1n/lwt5NS0y27dLsckr +Hs+Ie7RO8O0To2SFj9Zwte0qV5KgtBSWSHqqpBlZ39mpD4aj5ey1Z+/D7iPdwz4k +hmwJA1mrk9bHCkzvxUq+1v8PLoGOGNVEIToOhgSqhoo4HtYHddAIvu8pfdL8hY0M +073qR75Au/ovKfzG2A== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100D.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100D.pem new file mode 100644 index 0000000000..95e419a174 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100D.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4109 (0x100d) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 09:51:10 2010 GMT + Not After : Jan 13 09:51:10 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00U\x00s\x00e\x00r\x00 \x001\x002\x00,\x00 \x00e\x00n\x00d\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00" + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:bf:4f:93:6b:6b:86:76:30:31:3b:0e:eb:b7:a6: + b9:a3:3e:84:ea:d5:31:50:5a:df:f4:3f:67:11:5a: + a5:28:23:58:37:67:a5:5c:72:6d:f2:fc:80:81:55: + 78:86:28:e9:60:c2:0a:d0:17:3c:3a:e9:a8:01:71: + 64:b8:27:f4:42:e0:d7:69:f5:4e:ef:14:07:69:fd: + de:7b:af:c8:a4:0c:9c:56:00:8b:76:67:d1:ba:a9: + e7:40:63:77:da:44:d3:89:5c:a7:5a:ea:d5:f3:9b: + 15:43:f3:08:2d:bc:8a:bf:4a:5b:57:01:f0:c7:97: + fe:b0:93:b2:1b:79:a0:4e:ad + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 0A:A2:A6:09:88:23:56:82:9E:60:8B:79:23:61:CA:BF:D4:F7:ED:A9 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 12 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 64:3e:b6:a6:5e:0d:6f:b3:e7:f6:c7:1f:4a:48:96:4c:fe:13: + 3c:4a:7b:e7:46:51:56:45:66:02:e4:79:1a:7f:15:a4:e9:5b: + f7:4c:68:cf:cf:b0:7b:e2:ba:57:37:23:c6:cd:ba:75:85:e8: + eb:d5:ca:a2:6d:9a:75:84:4b:7b:47:38:58:bc:0a:4b:cc:2c: + 2a:0d:eb:7e:ac:36:6f:0b:a5:26:b7:d3:0b:0f:e7:cc:26:db: + bb:01:48:5b:38:49:f5:3e:2d:75:c0:d6:11:ad:3e:a0:b6:8a: + 8e:7f:4d:10:2c:7b:d7:03:0d:de:da:6b:e0:07:06:90:73:1f: + dd:f1 +-----BEGIN CERTIFICATE----- +MIIC1TCCAj6gAwIBAgICEA0wDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkwOTUx +MTBaFw0zNTAxMTMwOTUxMTBaMIGFMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MTUwMwYDVQQDHiwAVQBzAGUAcgAgADEAMgAsACAAZQBuAGQAaQBuAGcAIABx +AHUAbwB0AGUAIjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAv0+Ta2uGdjAx +Ow7rt6a5oz6E6tUxUFrf9D9nEVqlKCNYN2elXHJt8vyAgVV4hijpYMIK0Bc8Oumo +AXFkuCf0QuDXafVO7xQHaf3ee6/IpAycVgCLdmfRuqnnQGN32kTTiVynWurV85sV +Q/MILbyKv0pbVwHwx5f+sJOyG3mgTq0CAwEAAaN4MHYwCwYDVR0PBAQDAgXgMB0G +A1UdDgQWBBQKoqYJiCNWgp5gi3kjYcq/1PftqTAfBgNVHSMEGDAWgBToarvCkOps +cCI+9vZIGwPmvremVTAnBgNVHREEIDAepBwwGjEYMBYGA1UEAxMPVXNlciAxMiBS +b290IDExMA0GCSqGSIb3DQEBBQUAA4GBAGQ+tqZeDW+z5/bHH0pIlkz+EzxKe+dG +UVZFZgLkeRp/FaTpW/dMaM/PsHviulc3I8bNunWF6OvVyqJtmnWES3tHOFi8CkvM +LCoN636sNm8LpSa30wsP58wm27sBSFs4SfU+LXXA1hGtPqC2io5/TRAse9cDDd7a +a+AHBpBzH93x +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100E.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100E.pem new file mode 100644 index 0000000000..f91766a0a8 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100E.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4110 (0x100e) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 09:53:08 2010 GMT + Not After : Jan 13 09:53:08 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00"\x00U\x00s\x00e\x00r\x00 \x001\x003\x00,\x00 \x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00s\x00" + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:e0:b2:b3:77:34:32:23:3c:45:ce:1f:5f:9a:60: + c5:59:af:2f:bf:73:8e:be:3d:88:8d:97:4f:fe:8a: + 00:b9:71:7f:07:3a:1e:6a:5b:37:8a:ff:58:8f:f1: + b3:e5:0b:9d:35:58:57:6d:da:d1:15:cd:52:7f:e2: + 15:25:16:d4:d6:1e:71:a6:f3:f7:c5:6d:01:64:fc: + 20:d4:4e:6a:f2:f9:b9:2a:36:f8:ae:e6:17:a8:f9: + 8e:7c:bb:75:e5:24:39:ad:4c:18:c8:bb:07:22:cd: + d1:a6:52:93:7f:24:5f:90:dd:0f:64:07:70:42:67: + 39:9b:1f:ea:5e:bb:cd:df:ab + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 75:49:D0:1F:A0:B3:A2:C6:F2:7F:CF:16:A3:4C:4B:DF:D6:4C:07:9D + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 13 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 5d:60:60:06:aa:8a:2d:ee:20:2a:ee:fb:b5:99:8c:ed:d8:67: + 28:30:d8:26:a7:e0:1c:6e:5d:e1:4c:5e:c8:f9:02:e2:2e:c4: + 1e:58:e9:84:bc:d7:79:4e:d5:c5:ea:ba:74:aa:4e:30:9d:2b: + 98:c8:0b:fe:7f:eb:fb:e9:24:5f:f8:17:27:a9:ce:7c:ff:4b: + 88:15:3e:25:18:71:73:bf:b6:bf:c5:51:6b:1d:db:32:1d:ae: + 00:bf:ed:a5:65:99:16:43:8d:d2:6d:27:53:fc:65:9a:91:94: + 7b:44:c8:58:a1:f1:2b:95:86:0b:2d:2d:94:10:6f:5e:be:f8: + 7b:8e +-----BEGIN CERTIFICATE----- +MIIC3zCCAkigAwIBAgICEA4wDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkwOTUz +MDhaFw0zNTAxMTMwOTUzMDhaMIGPMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MT8wPQYDVQQDHjYAIgBVAHMAZQByACAAMQAzACwAIABlAG4AYwBsAG8AcwBp +AG4AZwAgAHEAdQBvAHQAZQBzACIwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB +AOCys3c0MiM8Rc4fX5pgxVmvL79zjr49iI2XT/6KALlxfwc6HmpbN4r/WI/xs+UL +nTVYV23a0RXNUn/iFSUW1NYecabz98VtAWT8INROavL5uSo2+K7mF6j5jny7deUk +Oa1MGMi7ByLN0aZSk38kX5DdD2QHcEJnOZsf6l67zd+rAgMBAAGjeDB2MAsGA1Ud +DwQEAwIF4DAdBgNVHQ4EFgQUdUnQH6Czosbyf88Wo0xL39ZMB50wHwYDVR0jBBgw +FoAU6Gq7wpDqbHAiPvb2SBsD5r63plUwJwYDVR0RBCAwHqQcMBoxGDAWBgNVBAMT +D1VzZXIgMTMgUm9vdCAxMTANBgkqhkiG9w0BAQUFAAOBgQBdYGAGqoot7iAq7vu1 +mYzt2GcoMNgmp+Acbl3hTF7I+QLiLsQeWOmEvNd5TtXF6rp0qk4wnSuYyAv+f+v7 +6SRf+Bcnqc58/0uIFT4lGHFzv7a/xVFrHdsyHa4Av+2lZZkWQ43SbSdT/GWakZR7 +RMhYofErlYYLLS2UEG9evvh7jg== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100F.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100F.pem new file mode 100644 index 0000000000..34a9b97c5f --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100F.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4111 (0x100f) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 09:55:02 2010 GMT + Not After : Jan 13 09:55:02 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00U\x00s\x00e\x00r\x00 \x001\x004\x00 \x00"\x00,\x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00q\x00u\x00o\x00t\x00e\x00" + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:d7:b7:68:39:6e:80:18:83:2e:d7:0a:e5:f1:3f: + 27:80:68:59:a8:05:ac:7f:d9:6e:5d:7f:1c:58:86: + b7:74:b5:51:3d:64:09:4a:a0:ff:e7:10:0e:bc:8a: + f0:d1:54:18:0a:ed:68:0a:a2:33:e5:9f:f0:3d:7f: + 24:9c:46:34:ba:45:8f:05:59:51:2d:fb:32:1d:79: + 51:37:1a:4b:f8:6e:c5:49:c0:49:9e:ef:2b:ae:aa: + 03:fa:ff:55:08:69:85:0d:b4:06:53:ee:20:4e:74: + 6c:ca:b8:98:8d:64:8f:b5:99:a9:06:37:32:ca:ca: + eb:31:16:ce:97:e8:17:0d:9d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + A7:D8:65:FB:E9:A1:F6:A4:16:76:1C:2E:5B:F3:1B:8E:08:B1:1D:7F + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 14 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 35:54:0f:d2:d3:ec:9e:a6:ea:e6:51:69:27:a3:f1:ae:ea:ef: + f9:da:ca:2a:50:f1:9e:2a:7c:74:43:d6:7f:91:ad:5a:5c:e2: + da:f3:cb:27:a2:78:99:75:0b:9e:e9:3a:bd:3e:31:14:6a:06: + b7:3f:59:d1:0a:67:03:a4:32:63:cd:b1:b6:5c:68:bb:bb:e2: + 23:a6:ff:8e:55:e5:92:a6:a8:b3:87:3d:25:21:9c:2a:6f:ab: + 09:ad:f5:e6:e6:d8:37:62:f2:30:ac:51:da:f4:9c:1d:06:f6: + f3:73:2f:6a:3b:7f:53:0d:c0:2e:ad:cc:6e:81:fe:ce:e3:53: + 0e:23 +-----BEGIN CERTIFICATE----- +MIIC1zCCAkCgAwIBAgICEA8wDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkwOTU1 +MDJaFw0zNTAxMTMwOTU1MDJaMIGHMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MTcwNQYDVQQDHi4AVQBzAGUAcgAgADEANAAgACIALABtAGkAZABkAGwAZQAg +AHEAdQBvAHQAZQAiMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDXt2g5boAY +gy7XCuXxPyeAaFmoBax/2W5dfxxYhrd0tVE9ZAlKoP/nEA68ivDRVBgK7WgKojPl +n/A9fyScRjS6RY8FWVEt+zIdeVE3Gkv4bsVJwEme7yuuqgP6/1UIaYUNtAZT7iBO +dGzKuJiNZI+1makGNzLKyusxFs6X6BcNnQIDAQABo3gwdjALBgNVHQ8EBAMCBeAw +HQYDVR0OBBYEFKfYZfvpofakFnYcLlvzG44IsR1/MB8GA1UdIwQYMBaAFOhqu8KQ +6mxwIj729kgbA+a+t6ZVMCcGA1UdEQQgMB6kHDAaMRgwFgYDVQQDEw9Vc2VyIDE0 +IFJvb3QgMTEwDQYJKoZIhvcNAQEFBQADgYEANVQP0tPsnqbq5lFpJ6Pxrurv+drK +KlDxnip8dEPWf5GtWlzi2vPLJ6J4mXULnuk6vT4xFGoGtz9Z0QpnA6QyY82xtlxo +u7viI6b/jlXlkqaos4c9JSGcKm+rCa315ubYN2LyMKxR2vScHQb283Mvajt/Uw3A +Lq3MboH+zuNTDiM= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1010.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1010.pem new file mode 100644 index 0000000000..ae0a417473 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1010.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4112 (0x1010) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 09:57:52 2010 GMT + Not After : Jan 13 09:57:52 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00\\x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00s\x00\ + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:a1:cc:00:2b:07:2b:e7:ac:80:29:cb:40:37:e3: + 1f:a3:c5:13:86:16:63:6b:cc:b8:c1:aa:54:fd:57: + 0f:de:4c:69:2f:e5:5f:f0:a9:bb:25:74:48:ee:36: + 77:6b:08:b5:95:a9:00:aa:15:31:9e:d8:f6:25:53: + 78:9d:bc:2b:8f:7a:19:32:12:8c:13:60:7d:76:1e: + 4e:b1:e4:51:c7:43:c0:e6:ee:d9:61:df:85:90:a0: + 95:3c:a2:81:83:3d:22:f6:8d:42:ee:69:fa:5c:ae: + 1c:b5:52:02:fb:ec:a6:12:2f:bb:fb:6c:a8:61:95: + 08:6c:d2:e5:1e:90:61:a6:27 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 2F:C9:F6:94:E6:1E:91:13:CE:75:A1:17:FD:1D:93:7E:45:CE:4D:67 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 15 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 19:d0:dc:4c:c8:59:f0:7a:14:f2:51:54:e5:9e:5a:b3:27:0b: + d7:36:0f:74:38:07:26:65:1a:b5:94:1a:1f:b2:b7:3d:ee:b1: + 90:05:83:41:6a:98:5f:25:b4:cb:5c:49:12:24:35:d6:97:cf: + 50:2e:0a:17:41:0b:75:e9:6a:a4:fb:bb:c2:cc:c1:94:64:03: + 81:c4:25:d2:3f:3e:8f:d1:29:44:db:a9:3c:7f:0c:2c:6d:48: + 38:cb:8f:56:82:9c:d3:f3:f3:20:1f:45:19:8e:ea:91:9c:c1: + 25:cf:20:1d:bb:70:7e:b9:a0:c5:34:78:93:5f:2b:d9:fd:d5: + de:ad +-----BEGIN CERTIFICATE----- +MIICzDCCAjWgAwIBAgICEBAwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkwOTU3 +NTJaFw0zNTAxMTMwOTU3NTJaMH0xCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxLTArBgNVBAMeJABcAGUAbgBjAGwAbwBzAGkAbgBnACAAcQB1AG8AdABlAHMA +XDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAocwAKwcr56yAKctAN+Mfo8UT +hhZja8y4wapU/VcP3kxpL+Vf8Km7JXRI7jZ3awi1lakAqhUxntj2JVN4nbwrj3oZ +MhKME2B9dh5OseRRx0PA5u7ZYd+FkKCVPKKBgz0i9o1C7mn6XK4ctVIC++ymEi+7 ++2yoYZUIbNLlHpBhpicCAwEAAaN4MHYwCwYDVR0PBAQDAgXgMB0GA1UdDgQWBBQv +yfaU5h6RE851oRf9HZN+Rc5NZzAfBgNVHSMEGDAWgBToarvCkOpscCI+9vZIGwPm +vremVTAnBgNVHREEIDAepBwwGjEYMBYGA1UEAxMPVXNlciAxNSBSb290IDExMA0G +CSqGSIb3DQEBBQUAA4GBABnQ3EzIWfB6FPJRVOWeWrMnC9c2D3Q4ByZlGrWUGh+y +tz3usZAFg0FqmF8ltMtcSRIkNdaXz1AuChdBC3XpaqT7u8LMwZRkA4HEJdI/Po/R +KUTbqTx/DCxtSDjLj1aCnNPz8yAfRRmO6pGcwSXPIB27cH65oMU0eJNfK9n91d6t +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1011.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1011.pem new file mode 100644 index 0000000000..21222706f4 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1011.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4113 (0x1011) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 09:59:22 2010 GMT + Not After : Jan 13 09:59:22 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00\\x00\\x00d\x00o\x00u\x00b\x00l\x00e\x00 \x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00s\x00\\x00\ + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:a4:e3:64:10:9f:0a:e4:35:bb:e3:e1:f0:28:86: + 8a:f2:6e:d3:f8:44:ac:58:7b:f5:dd:1c:71:17:bf: + 3e:14:29:55:f0:5c:c9:ed:36:c0:7f:e7:cc:7c:a3: + c4:9a:13:4f:7d:6c:b3:1e:ab:24:ba:1a:ff:48:96: + 67:a5:ca:e5:75:30:24:70:3a:94:d2:92:db:29:2b: + 69:1f:1d:a4:da:37:91:57:03:79:d7:0a:c7:a9:09: + 14:a8:70:60:b5:a3:62:4f:b8:bf:0a:22:0a:9c:83: + 3a:4d:1a:47:06:97:f1:4a:38:78:95:45:10:9e:44: + 90:fb:6e:13:ba:3a:1b:b7:4b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + A5:32:FD:E7:0D:90:82:17:34:E1:AD:2A:48:5D:78:27:2B:C9:2A:B8 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 16 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 96:ee:46:fc:41:4f:55:0d:bc:46:27:5a:3c:09:7c:17:6c:e3: + 9e:3a:85:eb:3b:e2:f7:a5:ab:b5:ae:aa:44:81:d7:b7:29:39: + b8:20:40:1e:36:da:a8:03:8b:3a:96:c3:2e:ba:cd:81:b9:af: + a0:a5:95:b0:3b:55:c1:85:9d:3d:c2:d0:7b:a4:d0:0e:16:7c: + 26:ba:85:e5:96:f0:f9:cc:28:c4:ed:83:e8:6f:30:a8:22:7a: + 7e:3b:99:d6:b2:3d:a2:90:1e:c9:9b:70:0a:af:04:d9:7c:46: + 52:e2:5a:d3:57:d6:18:a9:e9:55:ee:00:e8:10:a1:84:ed:ca: + 2b:bf +-----BEGIN CERTIFICATE----- +MIIC3zCCAkigAwIBAgICEBEwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkwOTU5 +MjJaFw0zNTAxMTMwOTU5MjJaMIGPMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MT8wPQYDVQQDHjYAXABcAGQAbwB1AGIAbABlACAAZQBuAGMAbABvAHMAaQBu +AGcAIABxAHUAbwB0AGUAcwBcAFwwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB +AKTjZBCfCuQ1u+Ph8CiGivJu0/hErFh79d0ccRe/PhQpVfBcye02wH/nzHyjxJoT +T31ssx6rJLoa/0iWZ6XK5XUwJHA6lNKS2ykraR8dpNo3kVcDedcKx6kJFKhwYLWj +Yk+4vwoiCpyDOk0aRwaX8Uo4eJVFEJ5EkPtuE7o6G7dLAgMBAAGjeDB2MAsGA1Ud +DwQEAwIF4DAdBgNVHQ4EFgQUpTL95w2Qghc04a0qSF14JyvJKrgwHwYDVR0jBBgw +FoAU6Gq7wpDqbHAiPvb2SBsD5r63plUwJwYDVR0RBCAwHqQcMBoxGDAWBgNVBAMT +D1VzZXIgMTYgUm9vdCAxMTANBgkqhkiG9w0BAQUFAAOBgQCW7kb8QU9VDbxGJ1o8 +CXwXbOOeOoXrO+L3pau1rqpEgde3KTm4IEAeNtqoA4s6lsMuus2Bua+gpZWwO1XB +hZ09wtB7pNAOFnwmuoXllvD5zCjE7YPobzCoInp+O5nWsj2ikB7Jm3AKrwTZfEZS +4lrTV9YYqelV7gDoEKGE7corvw== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1012.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1012.pem new file mode 100644 index 0000000000..b75551711c --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1012.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4114 (0x1012) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 10:02:07 2010 GMT + Not After : Jan 13 10:02:07 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00\\x00\\x00t\x00w\x00o\x00 \x00s\x00t\x00a\x00r\x00t\x00i\x00n\x00g\x00 \x00o\x00n\x00e\x00 \x00e\x00n\x00d\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00\ + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:e9:8c:31:90:52:8d:ef:c6:6a:10:17:7d:37:a3: + ef:00:34:19:dd:a4:1a:f6:cc:37:b0:19:c8:9d:f6: + 9f:f8:3d:15:c9:cf:73:ab:0a:42:f2:54:5b:cc:12: + fb:64:35:54:c9:50:36:18:6c:b6:b0:cf:d6:1e:30: + 0b:0d:fa:f3:25:99:d7:49:20:dd:cc:04:d7:bb:07: + 00:b9:b9:87:8c:75:e5:28:a6:74:a9:b4:96:36:b8: + 15:62:84:0c:7a:a2:f3:07:9c:5c:8f:7a:22:3d:ba: + a4:06:69:f6:ce:d2:36:a0:62:e1:ae:67:aa:23:24: + ac:1d:53:ac:bf:b6:30:74:f7 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + C0:28:3E:BA:44:88:99:A0:80:67:AA:3E:B6:D4:12:A7:35:DA:A6:BB + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 17 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 06:5b:fb:65:55:34:ca:2c:1a:c2:2d:2a:97:1b:a1:68:f6:0c: + 13:18:03:44:f9:0d:37:a1:8c:b1:f7:bc:b7:74:a8:aa:c1:e7: + 36:e7:b9:e0:64:79:76:63:98:7b:1d:d8:80:8c:d9:26:61:a8: + e7:07:96:60:e9:8a:24:78:cb:9c:f3:35:15:c9:d9:0c:2e:68: + 68:48:9c:df:6b:56:3f:aa:47:34:36:b0:ef:0e:d2:e0:ee:a9: + a9:6a:27:93:60:27:5f:42:76:9c:e0:aa:74:6c:b9:aa:de:fe: + 86:98:5a:3d:73:c5:15:38:c8:ff:09:8e:ed:da:06:74:fb:67: + 92:51 +-----BEGIN CERTIFICATE----- +MIIC6TCCAlKgAwIBAgICEBIwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDAy +MDdaFw0zNTAxMTMxMDAyMDdaMIGZMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MUkwRwYDVQQDHkAAXABcAHQAdwBvACAAcwB0AGEAcgB0AGkAbgBnACAAbwBu +AGUAIABlAG4AZABpAG4AZwAgAHEAdQBvAHQAZQBcMIGfMA0GCSqGSIb3DQEBAQUA +A4GNADCBiQKBgQDpjDGQUo3vxmoQF303o+8ANBndpBr2zDewGcid9p/4PRXJz3Or +CkLyVFvMEvtkNVTJUDYYbLawz9YeMAsN+vMlmddJIN3MBNe7BwC5uYeMdeUopnSp +tJY2uBVihAx6ovMHnFyPeiI9uqQGafbO0jagYuGuZ6ojJKwdU6y/tjB09wIDAQAB +o3gwdjALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFMAoPrpEiJmggGeqPrbUEqc12qa7 +MB8GA1UdIwQYMBaAFOhqu8KQ6mxwIj729kgbA+a+t6ZVMCcGA1UdEQQgMB6kHDAa +MRgwFgYDVQQDEw9Vc2VyIDE3IFJvb3QgMTEwDQYJKoZIhvcNAQEFBQADgYEABlv7 +ZVU0yiwawi0qlxuhaPYMExgDRPkNN6GMsfe8t3SoqsHnNue54GR5dmOYex3YgIzZ +JmGo5weWYOmKJHjLnPM1FcnZDC5oaEic32tWP6pHNDaw7w7S4O6pqWonk2AnX0J2 +nOCqdGy5qt7+hphaPXPFFTjI/wmO7doGdPtnklE= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1013.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1013.pem new file mode 100644 index 0000000000..2b48a29b0e --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1013.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4115 (0x1013) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 10:04:36 2010 GMT + Not After : Jan 13 10:04:36 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00\\x00s\x00t\x00a\x00r\x00t\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:bb:73:a4:4e:45:8e:80:b1:65:b6:d8:3b:96:c8: + 3b:c4:2e:40:98:2a:a9:0d:2e:75:29:df:dd:28:8f: + dc:65:4e:2f:8b:24:55:f4:5b:95:5e:d8:29:c8:31: + aa:53:41:a6:1b:2a:cc:8d:67:b6:d8:5f:56:7d:bd: + 0e:17:88:9b:28:b8:fc:54:ff:0e:1f:d9:59:f7:6f: + 99:46:76:86:69:87:f7:07:51:f6:1a:76:91:37:40: + 96:de:5a:0e:c1:20:7f:b5:1b:79:c2:63:13:50:dc: + f0:35:11:2c:4a:30:e0:68:8f:dc:51:4c:2b:61:ba: + a5:e6:ad:72:8b:c4:e1:2d:73 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 31:AE:51:BD:37:3E:EB:D6:98:7D:BD:DF:45:0C:92:4E:73:58:35:AA + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 18 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 51:34:24:4b:78:89:95:5d:43:15:3e:62:fc:40:a0:34:a5:6e: + 83:b5:ee:f0:93:ae:8a:27:97:9c:66:54:c9:aa:f5:9b:96:88: + 43:25:76:b6:0d:06:36:6c:0e:08:5f:15:45:c6:cc:d1:62:18: + 6b:fa:cd:af:53:7c:7c:97:30:13:a7:03:ac:db:04:25:bb:22: + 7d:49:70:30:69:9f:c8:22:94:32:40:83:d3:d1:9d:1c:2a:64: + cf:a9:42:0c:ce:0c:b8:3d:63:33:bb:e1:85:45:a7:79:89:ac: + 0c:1b:b5:a4:e0:1d:4d:99:d6:68:9b:c2:67:97:9c:9d:2c:57: + 12:fe +-----BEGIN CERTIFICATE----- +MIICxjCCAi+gAwIBAgICEBMwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDA0 +MzZaFw0zNTAxMTMxMDA0MzZaMHcxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxJzAlBgNVBAMeHgBcAHMAdABhAHIAdABpAG4AZwAgAHEAdQBvAHQAZTCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAu3OkTkWOgLFlttg7lsg7xC5AmCqpDS51 +Kd/dKI/cZU4viyRV9FuVXtgpyDGqU0GmGyrMjWe22F9Wfb0OF4ibKLj8VP8OH9lZ +92+ZRnaGaYf3B1H2GnaRN0CW3loOwSB/tRt5wmMTUNzwNREsSjDgaI/cUUwrYbql +5q1yi8ThLXMCAwEAAaN4MHYwCwYDVR0PBAQDAgXgMB0GA1UdDgQWBBQxrlG9Nz7r +1ph9vd9FDJJOc1g1qjAfBgNVHSMEGDAWgBToarvCkOpscCI+9vZIGwPmvremVTAn +BgNVHREEIDAepBwwGjEYMBYGA1UEAxMPVXNlciAxOCBSb290IDExMA0GCSqGSIb3 +DQEBBQUAA4GBAFE0JEt4iZVdQxU+YvxAoDSlboO17vCTroonl5xmVMmq9ZuWiEMl +drYNBjZsDghfFUXGzNFiGGv6za9TfHyXMBOnA6zbBCW7In1JcDBpn8gilDJAg9PR +nRwqZM+pQgzODLg9YzO74YVFp3mJrAwbtaTgHU2Z1mibwmeXnJ0sVxL+ +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1014.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1014.pem new file mode 100644 index 0000000000..a2027e9d8a --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1014.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4116 (0x1014) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 10:05:50 2010 GMT + Not After : Jan 13 10:05:50 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00e\x00n\x00d\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00\ + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:ca:cc:98:77:0c:10:dd:0e:87:a2:da:b6:e6:97: + 91:36:71:54:de:2b:f8:de:18:b7:23:eb:e5:e3:57: + ae:cf:0b:6d:86:0f:63:f0:c4:4e:2a:66:48:33:c4: + e3:0b:2c:f5:e6:e5:e5:0f:f8:e0:a1:bc:11:06:a1: + 19:16:ec:44:77:a6:db:7d:d6:78:29:1f:57:f1:9d: + 3c:b4:3a:2b:3b:94:64:6d:e3:ce:b3:fa:d8:28:e2: + ed:76:9a:97:41:64:7c:0d:48:b8:1d:6a:56:e3:f9: + 4c:88:e9:1a:3c:b8:af:7a:13:67:19:59:36:46:79: + 52:72:ea:51:80:65:be:e2:0f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + D2:D8:8D:EE:39:D7:EA:15:23:00:7C:9D:48:1C:51:17:F8:80:86:CE + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 19 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 6e:05:c4:48:32:4a:62:6f:a3:8c:23:af:47:dd:d4:c7:c1:91: + 17:7e:cd:36:73:39:a3:7b:c9:ae:da:f6:e1:bd:82:d6:72:17: + 78:20:a2:27:ad:f5:d2:3f:10:66:e0:d8:ba:10:00:c3:76:5b: + de:36:cb:2a:91:25:89:08:0e:2a:6a:81:d0:a7:49:70:42:f3: + 94:a3:bf:6c:6b:b9:fa:fd:f9:d4:1f:6f:75:27:b9:0d:d3:d2: + fd:5d:0d:dc:f5:34:29:a2:3a:2f:04:ab:48:41:6d:d7:2b:fd: + 42:02:99:3c:cf:aa:6b:98:66:17:83:39:4a:6f:47:36:ad:db: + 22:6e +-----BEGIN CERTIFICATE----- +MIICwjCCAiugAwIBAgICEBQwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDA1 +NTBaFw0zNTAxMTMxMDA1NTBaMHMxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxIzAhBgNVBAMeGgBlAG4AZABpAG4AZwAgAHEAdQBvAHQAZQBcMIGfMA0GCSqG +SIb3DQEBAQUAA4GNADCBiQKBgQDKzJh3DBDdDoei2rbml5E2cVTeK/jeGLcj6+Xj +V67PC22GD2PwxE4qZkgzxOMLLPXm5eUP+OChvBEGoRkW7ER3ptt91ngpH1fxnTy0 +Ois7lGRt486z+tgo4u12mpdBZHwNSLgdalbj+UyI6Ro8uK96E2cZWTZGeVJy6lGA +Zb7iDwIDAQABo3gwdjALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFNLYje451+oVIwB8 +nUgcURf4gIbOMB8GA1UdIwQYMBaAFOhqu8KQ6mxwIj729kgbA+a+t6ZVMCcGA1Ud +EQQgMB6kHDAaMRgwFgYDVQQDEw9Vc2VyIDE5IFJvb3QgMTEwDQYJKoZIhvcNAQEF +BQADgYEAbgXESDJKYm+jjCOvR93Ux8GRF37NNnM5o3vJrtr24b2C1nIXeCCiJ631 +0j8QZuDYuhAAw3Zb3jbLKpEliQgOKmqB0KdJcELzlKO/bGu5+v351B9vdSe5DdPS +/V0N3PU0KaI6LwSrSEFt1yv9QgKZPM+qa5hmF4M5Sm9HNq3bIm4= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1015.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1015.pem new file mode 100644 index 0000000000..d9d3f941e6 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1015.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4117 (0x1015) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 10:07:07 2010 GMT + Not After : Jan 13 10:07:07 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00\\x00q\x00u\x00o\x00t\x00e + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:f0:7c:07:f6:13:52:ce:13:cf:8a:5f:7f:5f:3c: + d4:93:c8:a0:43:1f:e2:fc:3f:62:63:be:b5:17:e0: + 32:b0:d0:c2:9a:35:9e:3b:29:30:b4:13:78:18:ae: + 80:ba:fb:f3:fc:81:ad:aa:47:18:eb:fc:d1:76:de: + b6:cf:55:65:5e:3e:15:93:8e:9c:39:4e:a3:ae:1d: + c0:49:22:dc:25:09:33:95:0d:b5:62:7c:96:0b:05: + b6:10:ae:ee:f8:18:24:9f:d4:ed:b3:4c:a9:4d:f2: + be:6c:66:37:b9:17:cb:14:df:52:b4:a8:de:63:0d: + 4f:78:58:16:ab:f2:3f:f6:a9 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 41:CC:3D:88:34:10:21:13:A2:34:24:B6:4E:F9:33:3C:B3:FA:56:BC + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 20 Root 11 + Signature Algorithm: sha1WithRSAEncryption + a7:17:c3:92:37:10:ee:9a:12:65:32:82:56:93:82:fa:0e:40: + 9f:ae:30:6a:b1:6f:85:18:7f:ff:9c:30:49:b7:56:bf:a3:86: + d7:dd:5d:79:d1:7f:9a:95:b6:bd:1d:43:cc:2c:aa:7a:40:c4: + de:17:02:22:74:ec:a9:cd:8d:93:f6:6c:98:7e:bb:6a:68:70: + 66:d4:a0:8f:1a:7a:8e:9e:38:35:aa:87:6a:e5:db:80:69:51: + 51:68:46:4f:3d:da:17:df:6f:22:60:77:95:55:d3:12:1b:11: + c1:6f:c1:96:78:00:47:61:af:53:c0:37:44:6b:92:67:7f:14: + 79:80 +-----BEGIN CERTIFICATE----- +MIICwjCCAiugAwIBAgICEBUwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDA3 +MDdaFw0zNTAxMTMxMDA3MDdaMHMxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxIzAhBgNVBAMeGgBtAGkAZABkAGwAZQAgAFwAcQB1AG8AdABlMIGfMA0GCSqG +SIb3DQEBAQUAA4GNADCBiQKBgQDwfAf2E1LOE8+KX39fPNSTyKBDH+L8P2JjvrUX +4DKw0MKaNZ47KTC0E3gYroC6+/P8ga2qRxjr/NF23rbPVWVePhWTjpw5TqOuHcBJ +ItwlCTOVDbVifJYLBbYQru74GCSf1O2zTKlN8r5sZje5F8sU31K0qN5jDU94WBar +8j/2qQIDAQABo3gwdjALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFEHMPYg0ECETojQk +tk75Mzyz+la8MB8GA1UdIwQYMBaAFOhqu8KQ6mxwIj729kgbA+a+t6ZVMCcGA1Ud +EQQgMB6kHDAaMRgwFgYDVQQDEw9Vc2VyIDIwIFJvb3QgMTEwDQYJKoZIhvcNAQEF +BQADgYEApxfDkjcQ7poSZTKCVpOC+g5An64warFvhRh//5wwSbdWv6OG191dedF/ +mpW2vR1DzCyqekDE3hcCInTsqc2Nk/ZsmH67amhwZtSgjxp6jp44NaqHauXbgGlR +UWhGTz3aF99vImB3lVXTEhsRwW/BlngAR2GvU8A3RGuSZ38UeYA= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1016.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1016.pem new file mode 100644 index 0000000000..9f4e006f02 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1016.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4118 (0x1016) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 10:09:50 2010 GMT + Not After : Jan 13 10:09:50 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00d\x00o\x00u\x00b\x00l\x00e\x00 \x00\\x00\\x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00q\x00u\x00o\x00t\x00e + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:cd:22:93:9a:93:18:34:2f:50:e0:cc:23:f4:60: + bc:96:60:d5:a5:f9:da:45:9a:5b:a3:0a:fb:71:25: + 4c:bd:60:84:19:f5:93:28:c1:5d:b9:8d:05:05:4d: + 01:85:aa:9e:5b:08:9c:01:f8:32:90:fe:ef:7f:eb: + cb:b3:8b:b2:c8:d1:79:d6:47:a3:d8:df:f1:d0:56: + 04:04:bd:41:72:fc:98:75:10:d2:9b:b5:bc:55:a1: + fa:19:01:67:93:09:48:0a:67:ec:4d:12:47:37:6f: + c2:53:0e:c9:7a:30:ec:1d:9d:a5:e2:64:d8:92:4d: + ed:ec:b2:bb:10:96:76:28:47 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + DC:FF:9A:2B:49:51:1E:FB:A7:3A:90:94:1B:E0:3E:34:89:13:48:EE + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 21 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 16:aa:a6:b7:0e:e3:d2:ba:7e:9b:59:f6:cc:ce:5d:4d:2a:f2: + 95:60:46:24:dd:ea:e8:08:e6:60:9c:33:82:8c:34:a2:d8:38: + fb:75:fe:31:79:10:78:7d:93:44:3b:00:90:83:a4:15:52:8d: + 3a:b4:9c:c0:6f:95:2c:4f:d8:b3:3b:cf:69:ab:3c:41:3a:43: + 1b:0a:8b:b0:b4:aa:8b:bf:6f:96:e2:65:4a:00:3a:49:bc:9a: + a1:cd:13:b1:24:93:f6:44:cd:d3:71:91:da:4f:dd:75:3d:68: + 5c:6b:49:14:8a:23:b5:b6:4f:b6:41:d0:a7:16:7c:67:4c:b3: + 0a:88 +-----BEGIN CERTIFICATE----- +MIIC0zCCAjygAwIBAgICEBYwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDA5 +NTBaFw0zNTAxMTMxMDA5NTBaMIGDMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MTMwMQYDVQQDHioAZABvAHUAYgBsAGUAIABcAFwAbQBpAGQAZABsAGUAIABx +AHUAbwB0AGUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM0ik5qTGDQvUODM +I/RgvJZg1aX52kWaW6MK+3ElTL1ghBn1kyjBXbmNBQVNAYWqnlsInAH4MpD+73/r +y7OLssjRedZHo9jf8dBWBAS9QXL8mHUQ0pu1vFWh+hkBZ5MJSApn7E0SRzdvwlMO +yXow7B2dpeJk2JJN7eyyuxCWdihHAgMBAAGjeDB2MAsGA1UdDwQEAwIF4DAdBgNV +HQ4EFgQU3P+aK0lRHvunOpCUG+A+NIkTSO4wHwYDVR0jBBgwFoAU6Gq7wpDqbHAi +Pvb2SBsD5r63plUwJwYDVR0RBCAwHqQcMBoxGDAWBgNVBAMTD1VzZXIgMjEgUm9v +dCAxMTANBgkqhkiG9w0BAQUFAAOBgQAWqqa3DuPSun6bWfbMzl1NKvKVYEYk3ero +COZgnDOCjDSi2Dj7df4xeRB4fZNEOwCQg6QVUo06tJzAb5UsT9izO89pqzxBOkMb +CouwtKqLv2+W4mVKADpJvJqhzROxJJP2RM3TcZHaT911PWhca0kUiiO1tk+2QdCn +FnxnTLMKiA== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1017.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1017.pem new file mode 100644 index 0000000000..7bb12fa789 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1017.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4119 (0x1017) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 10:11:53 2010 GMT + Not After : Jan 13 10:11:53 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00p\x00a\x00r\x00t\x00i\x00a\x00l\x00l\x00y\x00 \x00\\x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00\ + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:e7:c9:bb:89:11:2f:2c:39:bc:d3:f5:d9:86:d4: + 8e:d7:20:11:81:75:30:25:7e:2b:29:70:61:83:38: + 24:d1:0f:cc:0b:88:71:29:06:05:a5:53:d2:00:2f: + 12:0c:7d:42:e6:47:33:de:cc:f8:7b:2a:5d:d9:cb: + 69:24:91:38:bf:0c:1a:12:cf:1e:f9:44:c2:1c:e8: + 6f:ea:ab:8b:92:4c:93:8c:69:61:b9:57:b3:1d:d0: + 03:3e:13:9d:30:bd:b2:b9:d9:c7:9b:4d:18:45:b0: + 19:19:15:58:4c:bd:5a:a1:59:4f:f0:1f:99:26:3b: + 4e:76:c6:bb:21:3c:94:bc:d9 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 43:E4:70:39:E3:91:80:2A:C3:BC:1A:F4:A3:51:4B:99:C5:20:93:A6 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 22 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 28:ce:8c:f0:bf:56:c6:a4:02:df:dd:1d:75:dc:cf:62:a0:92: + 58:64:91:8c:bb:96:3c:52:d5:66:6c:31:7e:1c:d9:a8:e5:1c: + a6:9f:5e:26:3f:69:71:c6:d7:5d:02:4f:a7:42:a5:85:fa:38: + 01:43:36:54:75:4c:51:a2:99:5d:72:05:9a:9b:fc:5e:83:9b: + a0:ef:11:b1:a4:dd:a5:50:2f:d0:14:dd:04:0f:8b:93:7e:4b: + 3e:24:04:45:d0:98:46:49:74:9f:d7:b4:68:09:dc:b6:ac:35: + 3f:5d:f9:ee:77:a4:35:46:75:a4:6a:d6:c1:53:4f:d2:0c:38: + 3c:df +-----BEGIN CERTIFICATE----- +MIIC3zCCAkigAwIBAgICEBcwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDEx +NTNaFw0zNTAxMTMxMDExNTNaMIGPMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MT8wPQYDVQQDHjYAcABhAHIAdABpAGEAbABsAHkAIABcAGUAbgBjAGwAbwBz +AGkAbgBnACAAcQB1AG8AdABlAFwwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB +AOfJu4kRLyw5vNP12YbUjtcgEYF1MCV+KylwYYM4JNEPzAuIcSkGBaVT0gAvEgx9 +QuZHM97M+HsqXdnLaSSROL8MGhLPHvlEwhzob+qri5JMk4xpYblXsx3QAz4TnTC9 +srnZx5tNGEWwGRkVWEy9WqFZT/AfmSY7TnbGuyE8lLzZAgMBAAGjeDB2MAsGA1Ud +DwQEAwIF4DAdBgNVHQ4EFgQUQ+RwOeORgCrDvBr0o1FLmcUgk6YwHwYDVR0jBBgw +FoAU6Gq7wpDqbHAiPvb2SBsD5r63plUwJwYDVR0RBCAwHqQcMBoxGDAWBgNVBAMT +D1VzZXIgMjIgUm9vdCAxMTANBgkqhkiG9w0BAQUFAAOBgQAozozwv1bGpALf3R11 +3M9ioJJYZJGMu5Y8UtVmbDF+HNmo5Rymn14mP2lxxtddAk+nQqWF+jgBQzZUdUxR +opldcgWam/xeg5ug7xGxpN2lUC/QFN0ED4uTfks+JARF0JhGSXSf17RoCdy2rDU/ +Xfnud6Q1RnWkatbBU0/SDDg83w== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1018.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1018.pem new file mode 100644 index 0000000000..d134dc5f3e --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1018.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4120 (0x1018) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 10:13:38 2010 GMT + Not After : Jan 13 10:13:38 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00\\x00U\x00s\x00e\x00r\x00 \x002\x003\x00,\x00 \x00s\x00t\x00a\x00r\x00t\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:b9:e3:64:f8:02:be:98:47:de:c6:f4:22:14:4f: + 22:fe:17:8c:14:7f:b8:27:44:51:9d:5a:79:33:b4: + d0:21:27:b0:ed:f9:9f:3d:54:ef:ba:3a:d8:89:2a: + ca:a8:8f:f3:f6:a7:6b:5f:0a:58:2d:a0:e3:05:3a: + 26:a6:1e:b6:89:a1:e1:71:11:e7:16:93:29:69:f8: + 14:a2:e3:d7:4e:e5:60:40:d7:40:c5:37:d6:95:7c: + 4f:35:fd:a8:82:7f:90:32:1d:99:e7:8a:b9:93:a4: + f3:23:0a:a5:f9:56:31:73:d8:e3:cb:d6:0e:2f:2b: + ee:8e:b5:ca:eb:63:82:1c:0b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 80:A8:F7:13:E3:E8:F8:A6:60:94:21:C1:FE:54:54:89:AC:4B:DF:45 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 23 Root 11 + Signature Algorithm: sha1WithRSAEncryption + be:31:bd:4a:56:80:64:f0:1e:ea:77:4a:f3:e3:ec:f0:ad:27: + cc:05:01:fa:d2:12:7c:8e:85:5b:37:54:9c:4f:96:2d:1c:81: + e4:21:3d:4b:d9:86:1a:6c:29:5e:88:f2:ae:04:f1:70:87:25: + b9:9a:4a:ef:dd:21:f9:17:33:ee:a1:eb:38:fb:c4:73:72:70: + 0c:67:58:96:95:8c:2c:5a:4a:31:28:50:52:64:65:5c:63:60: + de:24:df:a0:e9:0d:c0:b6:d6:4c:51:a7:5a:e8:dd:f6:ff:49: + e6:6f:7f:86:38:5d:c7:f9:eb:55:f1:b2:89:3b:cd:41:f7:5d: + a8:b0 +-----BEGIN CERTIFICATE----- +MIIC2TCCAkKgAwIBAgICEBgwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDEz +MzhaFw0zNTAxMTMxMDEzMzhaMIGJMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MTkwNwYDVQQDHjAAXABVAHMAZQByACAAMgAzACwAIABzAHQAYQByAHQAaQBu +AGcAIABxAHUAbwB0AGUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALnjZPgC +vphH3sb0IhRPIv4XjBR/uCdEUZ1aeTO00CEnsO35nz1U77o62IkqyqiP8/ana18K +WC2g4wU6JqYetomh4XER5xaTKWn4FKLj107lYEDXQMU31pV8TzX9qIJ/kDIdmeeK +uZOk8yMKpflWMXPY48vWDi8r7o61yutjghwLAgMBAAGjeDB2MAsGA1UdDwQEAwIF +4DAdBgNVHQ4EFgQUgKj3E+Po+KZglCHB/lRUiaxL30UwHwYDVR0jBBgwFoAU6Gq7 +wpDqbHAiPvb2SBsD5r63plUwJwYDVR0RBCAwHqQcMBoxGDAWBgNVBAMTD1VzZXIg +MjMgUm9vdCAxMTANBgkqhkiG9w0BAQUFAAOBgQC+Mb1KVoBk8B7qd0rz4+zwrSfM +BQH60hJ8joVbN1ScT5YtHIHkIT1L2YYabCleiPKuBPFwhyW5mkrv3SH5FzPuoes4 ++8RzcnAMZ1iWlYwsWkoxKFBSZGVcY2DeJN+g6Q3AttZMUada6N32/0nmb3+GOF3H ++etV8bKJO81B912osA== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1019.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1019.pem new file mode 100644 index 0000000000..66c3f15bfd --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1019.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4121 (0x1019) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 10:14:50 2010 GMT + Not After : Jan 13 10:14:50 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00U\x00s\x00e\x00r\x00 \x002\x004\x00,\x00 \x00e\x00n\x00d\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00\ + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:9c:cd:78:e7:11:1d:61:d4:0c:c6:87:c9:28:47: + 84:23:6b:86:c3:38:37:62:5a:9a:4b:50:fc:b7:f3: + d9:4b:1b:20:ff:06:42:bb:22:33:c5:22:12:2c:bb: + e6:c8:08:69:0e:af:e9:22:45:9f:ef:2c:26:46:d7: + 1b:36:db:70:58:32:bc:3d:d7:7d:64:27:44:54:6c: + 89:12:88:d7:31:3d:3f:5c:96:cb:69:9f:b1:a9:e0: + 9a:de:50:b7:ad:d8:29:bf:bc:3c:21:e9:a2:79:21: + 46:81:ea:90:df:44:0c:6c:bb:f8:47:c8:e9:79:d1: + 8d:40:1b:5d:d3:75:9b:e4:0b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 81:14:09:35:7F:F6:7A:83:6B:19:C2:22:24:92:E6:D4:EF:52:1C:0B + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 24 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 7c:65:0b:e2:cd:ca:00:e8:40:0f:37:70:a1:89:54:5d:03:06: + 2c:60:56:dc:2f:b7:01:ac:75:58:f6:82:8f:91:63:e2:91:d1: + 17:7b:bd:63:b9:9c:4e:46:86:3e:a6:f5:a6:56:ac:90:2a:f4: + d8:a0:6c:02:15:6e:d9:f6:2a:f8:9a:c4:48:bd:cd:54:82:55: + c6:d5:52:76:09:e3:3d:17:8d:5c:46:16:ae:9e:56:df:9f:c3: + 05:15:6f:ae:d0:b5:76:67:48:2d:5a:3c:59:da:1b:13:c3:84: + 5e:2a:57:8d:86:9a:f1:8a:5d:01:47:93:44:62:af:65:03:e1: + df:10 +-----BEGIN CERTIFICATE----- +MIIC1TCCAj6gAwIBAgICEBkwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDE0 +NTBaFw0zNTAxMTMxMDE0NTBaMIGFMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MTUwMwYDVQQDHiwAVQBzAGUAcgAgADIANAAsACAAZQBuAGQAaQBuAGcAIABx +AHUAbwB0AGUAXDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAnM145xEdYdQM +xofJKEeEI2uGwzg3YlqaS1D8t/PZSxsg/wZCuyIzxSISLLvmyAhpDq/pIkWf7ywm +RtcbNttwWDK8Pdd9ZCdEVGyJEojXMT0/XJbLaZ+xqeCa3lC3rdgpv7w8IemieSFG +geqQ30QMbLv4R8jpedGNQBtd03Wb5AsCAwEAAaN4MHYwCwYDVR0PBAQDAgXgMB0G +A1UdDgQWBBSBFAk1f/Z6g2sZwiIkkubU71IcCzAfBgNVHSMEGDAWgBToarvCkOps +cCI+9vZIGwPmvremVTAnBgNVHREEIDAepBwwGjEYMBYGA1UEAxMPVXNlciAyNCBS +b290IDExMA0GCSqGSIb3DQEBBQUAA4GBAHxlC+LNygDoQA83cKGJVF0DBixgVtwv +twGsdVj2go+RY+KR0Rd7vWO5nE5Ghj6m9aZWrJAq9NigbAIVbtn2KviaxEi9zVSC +VcbVUnYJ4z0XjVxGFq6eVt+fwwUVb67QtXZnSC1aPFnaGxPDhF4qV42GmvGKXQFH +k0Rir2UD4d8Q +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101A.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101A.pem new file mode 100644 index 0000000000..ba352d83d1 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101A.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4122 (0x101a) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 10:16:10 2010 GMT + Not After : Jan 13 10:16:10 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00\\x00U\x00s\x00e\x00r\x00 \x002\x005\x00,\x00 \x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00\ + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:ad:20:4a:85:d2:a8:2a:f8:0e:4c:b5:2d:72:a5: + 1d:0e:b1:8a:76:2c:b0:bf:7a:48:b8:57:29:cb:40: + c5:8a:e8:0e:d3:f6:f9:b1:90:a6:4a:bb:82:45:fd: + c2:ff:03:fa:fc:4a:5d:93:0b:52:a2:17:10:b1:7e: + 13:1d:9d:28:26:e3:44:bd:fd:26:da:b2:7b:47:e1: + c4:35:ea:53:1b:94:76:cc:f2:f6:c1:86:f2:18:46: + e1:71:c0:5d:e5:8f:0a:10:7a:ea:61:af:d0:ba:28: + 22:13:77:0f:7d:9e:e0:0a:f0:92:ce:dd:b3:5d:a6: + df:c1:eb:a8:29:57:e6:71:65 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + C3:EE:4A:7E:AC:46:2D:BA:42:F7:33:1F:E7:49:FA:21:D3:BC:DD:49 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 25 Root 11 + Signature Algorithm: sha1WithRSAEncryption + bf:63:34:12:e3:4b:83:4e:e5:c5:08:c3:b3:ea:be:38:33:38: + 3c:99:c3:ca:08:84:05:d4:21:53:7a:7d:43:86:c2:63:e2:d3: + 7c:21:3c:72:fa:c6:f3:bf:2b:10:5e:ca:4b:2c:2c:1c:e3:10: + eb:7c:ff:b1:20:b2:47:1b:b3:3e:77:b6:74:fb:83:85:ac:b8: + c9:5b:ca:8a:14:2f:e4:81:6e:04:6f:c8:37:c0:9f:c0:41:0f: + b4:6e:21:82:69:51:e8:68:09:72:c4:8c:72:db:47:0b:a5:52: + d7:e7:b3:5d:10:9c:ed:14:af:1c:fd:0b:11:a3:fd:f9:b9:2d: + 48:b5 +-----BEGIN CERTIFICATE----- +MIIC3TCCAkagAwIBAgICEBowDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDE2 +MTBaFw0zNTAxMTMxMDE2MTBaMIGNMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MT0wOwYDVQQDHjQAXABVAHMAZQByACAAMgA1ACwAIABlAG4AYwBsAG8AcwBp +AG4AZwAgAHEAdQBvAHQAZQBcMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCt +IEqF0qgq+A5MtS1ypR0OsYp2LLC/eki4VynLQMWK6A7T9vmxkKZKu4JF/cL/A/r8 +Sl2TC1KiFxCxfhMdnSgm40S9/SbasntH4cQ16lMblHbM8vbBhvIYRuFxwF3ljwoQ +euphr9C6KCITdw99nuAK8JLO3bNdpt/B66gpV+ZxZQIDAQABo3gwdjALBgNVHQ8E +BAMCBeAwHQYDVR0OBBYEFMPuSn6sRi26QvczH+dJ+iHTvN1JMB8GA1UdIwQYMBaA +FOhqu8KQ6mxwIj729kgbA+a+t6ZVMCcGA1UdEQQgMB6kHDAaMRgwFgYDVQQDEw9V +c2VyIDI1IFJvb3QgMTEwDQYJKoZIhvcNAQEFBQADgYEAv2M0EuNLg07lxQjDs+q+ +ODM4PJnDygiEBdQhU3p9Q4bCY+LTfCE8cvrG878rEF7KSywsHOMQ63z/sSCyRxuz +Pne2dPuDhay4yVvKihQv5IFuBG/IN8CfwEEPtG4hgmlR6GgJcsSMcttHC6VS1+ez +XRCc7RSvHP0LEaP9+bktSLU= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101B.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101B.pem new file mode 100644 index 0000000000..4c03562a8e --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101B.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4123 (0x101b) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 10:17:45 2010 GMT + Not After : Jan 13 10:17:45 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00U\x00s\x00e\x00r\x00 \x002\x006\x00\\x00,\x00 \x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00q\x00u\x00o\x00t\x00e + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:ec:4c:2b:ba:b1:e5:ba:83:e8:64:6c:67:fe:f9: + 84:9a:71:68:0b:10:b0:2e:2c:21:d8:6d:c8:cc:de: + 82:76:15:b8:74:a0:4b:3c:39:f0:ee:3a:08:6c:0e: + 0c:36:51:ed:44:04:ca:2b:76:30:6f:85:d4:f6:f0: + 7e:53:2b:17:90:6a:7b:79:e0:c2:00:f2:5f:dd:19: + 8f:09:7a:a2:c8:85:95:24:e0:41:39:ec:75:e1:c7: + 03:ba:6d:e9:81:48:8b:36:38:e0:99:3e:58:04:e3: + 03:8d:e4:3b:95:98:0a:23:96:f1:96:50:06:5d:71: + 6f:02:e1:c5:cd:e0:5c:c4:7b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 1D:A3:64:F0:93:51:C2:F2:1A:BB:D0:2D:20:95:5E:19:94:4C:72:BB + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 26 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 8c:c1:56:7d:d9:a8:f7:af:4b:57:4a:a5:2a:32:11:12:e0:d8: + 0e:10:39:8f:17:53:25:f5:c6:57:55:e4:f0:16:f2:11:cc:af: + cc:44:6b:23:6f:8e:2a:df:ee:ff:f0:d4:3f:0a:85:7e:19:de: + f8:cf:69:be:8b:59:ad:3c:be:3c:d7:32:ac:ba:82:91:28:23: + 71:ba:b5:29:05:e4:98:ee:2b:bb:56:04:7f:8b:69:c5:f9:4c: + 1b:0b:2e:3a:46:41:8e:da:16:68:9f:c7:57:71:8e:97:0d:b0: + a1:92:ae:7c:75:46:ef:b4:6d:8e:e7:53:07:23:a4:e1:e0:f0: + e7:3b +-----BEGIN CERTIFICATE----- +MIIC1TCCAj6gAwIBAgICEBswDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDE3 +NDVaFw0zNTAxMTMxMDE3NDVaMIGFMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MTUwMwYDVQQDHiwAVQBzAGUAcgAgADIANgBcACwAIABtAGkAZABkAGwAZQAg +AHEAdQBvAHQAZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA7EwrurHluoPo +ZGxn/vmEmnFoCxCwLiwh2G3IzN6CdhW4dKBLPDnw7joIbA4MNlHtRATKK3Ywb4XU +9vB+UysXkGp7eeDCAPJf3RmPCXqiyIWVJOBBOex14ccDum3pgUiLNjjgmT5YBOMD +jeQ7lZgKI5bxllAGXXFvAuHFzeBcxHsCAwEAAaN4MHYwCwYDVR0PBAQDAgXgMB0G +A1UdDgQWBBQdo2Twk1HC8hq70C0glV4ZlExyuzAfBgNVHSMEGDAWgBToarvCkOps +cCI+9vZIGwPmvremVTAnBgNVHREEIDAepBwwGjEYMBYGA1UEAxMPVXNlciAyNiBS +b290IDExMA0GCSqGSIb3DQEBBQUAA4GBAIzBVn3ZqPevS1dKpSoyERLg2A4QOY8X +UyX1xldV5PAW8hHMr8xEayNvjirf7v/w1D8KhX4Z3vjPab6LWa08vjzXMqy6gpEo +I3G6tSkF5JjuK7tWBH+LacX5TBsLLjpGQY7aFmifx1dxjpcNsKGSrnx1Ru+0bY7n +UwcjpOHg8Oc7 +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101C.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101C.pem new file mode 100644 index 0000000000..c403402f3d --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101C.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4124 (0x101c) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 10:19:13 2010 GMT + Not After : Jan 13 10:19:13 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=comma, comma, comma , + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:af:2e:02:1a:b8:ed:7e:6e:27:2f:6e:ca:dc:57: + 11:17:88:37:38:37:26:d0:fb:d0:ee:ad:f3:a8:ad: + f5:8a:53:04:6a:82:a7:31:b5:e6:ce:88:24:fa:22: + 75:84:1b:a8:8c:fd:7f:63:0c:fc:13:41:82:60:a3: + 19:33:3d:d3:18:6e:09:c5:c7:e7:e9:9e:49:dd:f4: + 77:ef:f1:06:91:9a:c5:57:68:e5:0f:59:19:8d:53: + ff:cb:ae:11:33:48:5c:eb:72:e8:2f:67:ae:94:42: + d3:5b:2e:31:e3:6f:a7:5e:5e:9c:ea:2c:d2:c3:af: + 66:10:34:32:e5:2d:3f:55:c1 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + A1:FB:82:9C:27:AD:83:67:5E:8C:CC:A2:BA:32:3C:30:26:74:F4:CE + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 27 Root 11 + Signature Algorithm: sha1WithRSAEncryption + c6:72:8b:f8:57:9e:b7:bf:b1:f3:99:41:1c:8c:47:a1:93:d8: + 62:8e:2d:68:6c:db:12:02:86:e0:66:65:c1:7c:c4:83:35:4c: + 16:53:fd:34:c1:3c:60:15:fc:3d:3b:90:07:68:ca:af:a1:10: + 39:c4:6b:15:a6:1a:71:51:20:ea:35:84:ef:8f:ac:51:bc:d7: + 84:d8:35:71:44:8e:8c:4f:59:76:3d:b3:5f:5c:26:9e:bc:ee: + 09:40:13:3b:38:85:02:56:7d:97:db:4d:3d:b5:a1:66:cf:df: + 19:7a:2f:71:b7:a4:12:c3:9b:df:83:f9:a8:8a:00:68:e4:3a: + ee:25 +-----BEGIN CERTIFICATE----- +MIICvTCCAiagAwIBAgICEBwwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDE5 +MTNaFw0zNTAxMTMxMDE5MTNaMG4xCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxHjAcBgNVBAMTFWNvbW1hLCBjb21tYSwgY29tbWEgLDCBnzANBgkqhkiG9w0B +AQEFAAOBjQAwgYkCgYEAry4CGrjtfm4nL27K3FcRF4g3ODcm0PvQ7q3zqK31ilME +aoKnMbXmzogk+iJ1hBuojP1/Ywz8E0GCYKMZMz3TGG4Jxcfn6Z5J3fR37/EGkZrF +V2jlD1kZjVP/y64RM0hc63LoL2eulELTWy4x42+nXl6c6izSw69mEDQy5S0/VcEC +AwEAAaN4MHYwCwYDVR0PBAQDAgXgMB0GA1UdDgQWBBSh+4KcJ62DZ16MzKK6Mjww +JnT0zjAfBgNVHSMEGDAWgBToarvCkOpscCI+9vZIGwPmvremVTAnBgNVHREEIDAe +pBwwGjEYMBYGA1UEAxMPVXNlciAyNyBSb290IDExMA0GCSqGSIb3DQEBBQUAA4GB +AMZyi/hXnre/sfOZQRyMR6GT2GKOLWhs2xIChuBmZcF8xIM1TBZT/TTBPGAV/D07 +kAdoyq+hEDnEaxWmGnFRIOo1hO+PrFG814TYNXFEjoxPWXY9s19cJp687glAEzs4 +hQJWfZfbTT21oWbP3xl6L3G3pBLDm9+D+aiKAGjkOu4l +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101D.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101D.pem new file mode 100644 index 0000000000..2790a2abd2 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101D.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4125 (0x101d) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 10:20:47 2010 GMT + Not After : Jan 13 10:20:47 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=equal CN=User 28 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:ae:df:12:64:ab:d9:2f:ee:21:64:b5:08:c5:c8: + 8f:a1:ad:0e:b9:28:91:69:74:13:a5:aa:49:fe:fa: + 02:9d:37:db:0a:3b:26:6a:20:25:3d:f9:2d:b2:3b: + 39:c8:c6:e3:a7:aa:a1:0b:b2:1b:58:43:e6:3c:3f: + 67:fe:bb:bd:9b:b5:d9:de:e9:ed:76:ab:fd:f5:c8: + 15:b2:fb:a6:3f:23:ef:9f:5f:71:43:b3:be:55:1e: + 85:5f:13:b1:6b:9d:42:d7:30:a8:d2:9b:fe:71:7a: + c7:d3:60:7a:cf:e2:83:75:83:b8:1c:d3:ef:ee:94: + 3f:14:63:aa:7c:15:4e:42:1d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 3B:2D:2B:5F:2E:E6:32:23:AE:47:B7:30:25:CB:ED:B0:6D:0C:30:E4 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 28 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 5b:cf:de:92:f8:ac:39:fb:0a:81:70:5b:17:d0:0d:0d:85:5e: + 2e:7d:be:d1:1a:ad:1d:99:a4:a6:f0:48:5a:7b:04:39:e2:93: + ff:80:84:f6:a1:e6:8a:52:12:55:46:c0:57:84:d9:c3:13:92: + 61:d7:41:af:39:09:57:05:25:01:90:68:7c:7c:5c:85:c6:f2: + fe:0e:37:e3:58:68:f9:32:fc:41:2c:35:36:f4:cf:ea:55:2d: + 52:7c:fb:37:32:35:cf:82:eb:fc:f1:39:f1:51:f1:e1:5b:d6: + 58:e1:7f:d4:50:ce:cf:07:f2:e5:f5:e2:dd:fe:55:3f:64:07: + 90:4f +-----BEGIN CERTIFICATE----- +MIICuDCCAiGgAwIBAgICEB0wDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDIw +NDdaFw0zNTAxMTMxMDIwNDdaMGkxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxGTAXBgNVBAMTEGVxdWFsIENOPVVzZXIgMjgwgZ8wDQYJKoZIhvcNAQEBBQAD +gY0AMIGJAoGBAK7fEmSr2S/uIWS1CMXIj6GtDrkokWl0E6WqSf76Ap032wo7Jmog +JT35LbI7OcjG46eqoQuyG1hD5jw/Z/67vZu12d7p7Xar/fXIFbL7pj8j759fcUOz +vlUehV8TsWudQtcwqNKb/nF6x9Nges/ig3WDuBzT7+6UPxRjqnwVTkIdAgMBAAGj +eDB2MAsGA1UdDwQEAwIF4DAdBgNVHQ4EFgQUOy0rXy7mMiOuR7cwJcvtsG0MMOQw +HwYDVR0jBBgwFoAU6Gq7wpDqbHAiPvb2SBsD5r63plUwJwYDVR0RBCAwHqQcMBox +GDAWBgNVBAMTD1VzZXIgMjggUm9vdCAxMTANBgkqhkiG9w0BAQUFAAOBgQBbz96S ++Kw5+wqBcFsX0A0NhV4ufb7RGq0dmaSm8EhaewQ54pP/gIT2oeaKUhJVRsBXhNnD +E5Jh10GvOQlXBSUBkGh8fFyFxvL+DjfjWGj5MvxBLDU29M/qVS1SfPs3MjXPguv8 +8TnxUfHhW9ZY4X/UUM7PB/Ll9eLd/lU/ZAeQTw== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101E.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101E.pem new file mode 100644 index 0000000000..f12a0c1c0d --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101E.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4126 (0x101e) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 10:22:13 2010 GMT + Not After : Jan 13 10:22:13 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 29+OU=ooo + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:ae:12:dc:26:fe:7f:b8:3f:47:a2:dc:83:a1:70: + 6d:ab:db:e5:3c:28:d5:18:32:2c:8d:ee:85:c6:f9: + f4:8b:31:34:71:de:91:79:fb:56:b4:9c:af:3e:b1: + c6:de:06:3f:32:fc:45:9d:9b:dd:15:0f:b5:c3:98: + ab:8c:1e:3d:63:7c:2a:c5:b9:38:3d:50:6c:81:9e: + f0:b3:5b:41:1a:ec:15:b2:7f:2b:b4:d4:42:aa:ca: + e6:89:b0:c6:58:bd:2d:38:f3:4d:85:c3:08:d7:45: + 48:42:d7:fe:ee:7a:c0:22:41:c0:c6:cb:77:7c:22: + 43:07:35:dc:88:7c:49:3a:9b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + E0:19:7F:AC:F8:6A:42:7E:84:CA:8C:84:45:75:4E:9D:A1:D1:2A:72 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 29 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 85:c9:ea:82:e2:ac:f6:b3:15:51:11:bd:69:81:31:8f:ee:d3: + f9:f4:8e:d5:27:34:20:89:76:eb:8a:5b:02:69:9b:97:89:d7: + 6b:aa:03:7f:b5:40:f9:ac:54:ce:8f:30:fd:3e:78:72:91:96: + dc:a6:bd:64:42:f8:e4:18:1a:e3:b5:db:08:fe:1e:fc:3d:a2: + 55:21:ad:0f:1a:87:df:f2:65:87:4d:91:52:c1:46:c1:c0:7c: + cc:81:79:97:dc:2e:41:cc:ae:8c:8e:79:4e:02:49:7c:c5:b0: + 3e:8e:d9:f0:aa:6b:a6:2f:e7:d2:21:5b:7f:57:e8:f7:f6:00: + 3c:ad +-----BEGIN CERTIFICATE----- +MIICtjCCAh+gAwIBAgICEB4wDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDIy +MTNaFw0zNTAxMTMxMDIyMTNaMGcxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxFzAVBgNVBAMTDlVzZXIgMjkrT1U9b29vMIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQCuEtwm/n+4P0ei3IOhcG2r2+U8KNUYMiyN7oXG+fSLMTRx3pF5+1a0 +nK8+scbeBj8y/EWdm90VD7XDmKuMHj1jfCrFuTg9UGyBnvCzW0Ea7BWyfyu01EKq +yuaJsMZYvS04802FwwjXRUhC1/7uesAiQcDGy3d8IkMHNdyIfEk6mwIDAQABo3gw +djALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFOAZf6z4akJ+hMqMhEV1Tp2h0SpyMB8G +A1UdIwQYMBaAFOhqu8KQ6mxwIj729kgbA+a+t6ZVMCcGA1UdEQQgMB6kHDAaMRgw +FgYDVQQDEw9Vc2VyIDI5IFJvb3QgMTEwDQYJKoZIhvcNAQEFBQADgYEAhcnqguKs +9rMVURG9aYExj+7T+fSO1Sc0IIl264pbAmmbl4nXa6oDf7VA+axUzo8w/T54cpGW +3Ka9ZEL45Bga47XbCP4e/D2iVSGtDxqH3/Jlh02RUsFGwcB8zIF5l9wuQcyujI55 +TgJJfMWwPo7Z8Kprpi/n0iFbf1fo9/YAPK0= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101F.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101F.pem new file mode 100644 index 0000000000..1393b9ed3e --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101F.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4127 (0x101f) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 10:26:01 2010 GMT + Not After : Jan 13 10:26:01 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00U\x00s\x00e\x00r\x00 \x003\x000\x00<\x00 \x00>\x00#\x00;\x00 \x00"\x00+\x00" + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:cf:40:99:4d:a5:5d:73:2a:78:72:9c:32:94:15: + 1e:01:40:b4:68:8f:b8:4e:38:aa:b9:82:96:5a:5c: + 03:d5:db:09:42:46:d8:2d:f0:da:f8:1a:f0:85:10: + f2:cb:1f:be:50:b7:ae:6f:22:80:f2:bf:14:73:84: + da:30:b9:54:26:0d:72:1c:55:99:50:c6:78:a3:37: + 15:b2:9c:03:22:dc:ea:8b:f5:07:32:f3:d9:76:64: + 92:a3:4f:73:12:e2:43:79:0e:e6:44:17:99:79:49: + 73:65:da:03:3d:be:db:e3:4f:ae:6c:d0:6c:e6:4a: + d3:83:45:5d:83:18:d5:cc:29 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + D9:EA:10:1D:D3:F5:30:AD:30:0E:80:73:14:22:1A:26:35:90:DC:67 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 30 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 42:3a:02:d5:7b:23:9f:cc:5b:b8:d4:c8:e8:0c:e3:0d:8a:17: + 65:b6:87:ce:c9:dc:f7:84:95:e0:17:ea:11:8b:15:30:e1:a2: + 42:6c:4e:f0:31:fa:fd:ff:03:37:d4:ec:4c:1d:29:8d:07:8a: + c8:de:0b:d6:df:d7:2e:12:8a:00:a0:ca:be:48:af:17:36:63: + 8e:f2:cf:80:8b:a1:e2:33:ef:42:db:91:d3:8e:4b:02:55:5e: + f7:79:11:5c:6d:ef:64:8b:53:a6:af:f5:0f:e2:75:7a:d6:85: + f6:60:d5:7e:d6:8c:0e:37:84:a9:50:2b:c7:e6:63:bf:1d:14: + aa:bf +-----BEGIN CERTIFICATE----- +MIICyDCCAjGgAwIBAgICEB8wDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDI2 +MDFaFw0zNTAxMTMxMDI2MDFaMHkxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxKTAnBgNVBAMeIABVAHMAZQByACAAMwAwADwAIAA+ACMAOwAgACIAKwAiMIGf +MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDPQJlNpV1zKnhynDKUFR4BQLRoj7hO +OKq5gpZaXAPV2wlCRtgt8Nr4GvCFEPLLH75Qt65vIoDyvxRzhNowuVQmDXIcVZlQ +xnijNxWynAMi3OqL9Qcy89l2ZJKjT3MS4kN5DuZEF5l5SXNl2gM9vtvjT65s0Gzm +StODRV2DGNXMKQIDAQABo3gwdjALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFNnqEB3T +9TCtMA6AcxQiGiY1kNxnMB8GA1UdIwQYMBaAFOhqu8KQ6mxwIj729kgbA+a+t6ZV +MCcGA1UdEQQgMB6kHDAaMRgwFgYDVQQDEw9Vc2VyIDMwIFJvb3QgMTEwDQYJKoZI +hvcNAQEFBQADgYEAQjoC1Xsjn8xbuNTI6AzjDYoXZbaHzsnc94SV4BfqEYsVMOGi +QmxO8DH6/f8DN9TsTB0pjQeKyN4L1t/XLhKKAKDKvkivFzZjjvLPgIuh4jPvQtuR +045LAlVe93kRXG3vZItTpq/1D+J1etaF9mDVftaMDjeEqVArx+Zjvx0Uqr8= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1020.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1020.pem new file mode 100644 index 0000000000..40e90d4cbe --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1020.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4128 (0x1020) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 10:28:47 2010 GMT + Not After : Jan 13 10:28:47 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00U\x00s\x00e\x00r\x00 \x003\x001\x00 \x00\\x00"\x00a\x00,\x00b\x00"\x00+\x00C\x00N\x00=\x00U\x00S\x00,\x00 \x00>\x00 \x00\\x00\\x00d\x00e\x00 \x00< + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:ac:02:18:e0:1c:54:bb:76:97:2e:d3:67:78:b7: + 14:78:46:83:7c:e9:5c:2b:2f:25:bb:bf:90:c0:52: + ea:2c:79:d6:9d:af:b5:f8:86:a2:bf:56:9b:0f:33: + ed:ef:d2:2c:57:c6:0a:25:b3:f7:9b:a1:7a:3b:75: + 0b:18:86:23:64:2a:23:b0:60:f1:d8:05:b4:a6:7b: + 77:21:30:b4:0d:f1:af:e1:fb:d6:88:a8:5b:5d:7e: + a2:bf:ce:20:f6:c0:7a:89:f2:0f:33:47:6d:49:0f: + 3d:59:27:f9:95:c0:3b:a3:1c:18:a1:2d:95:09:e8: + d2:95:ac:10:92:fc:db:84:e3 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + F8:BA:7E:78:BC:70:33:D3:45:68:37:59:3A:06:AC:65:B1:15:74:F0 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 31 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 0f:a8:53:f0:56:76:df:a8:b3:5b:d1:e8:98:62:8f:a6:13:96: + c3:6b:ca:3f:e1:09:37:54:6f:ac:15:4b:74:0c:6c:3f:fe:de: + 36:58:a2:9d:a0:1f:18:97:2c:1d:bc:c6:df:ee:aa:5b:d3:da: + 2f:51:02:7a:ba:a9:7e:4d:cf:47:16:0b:f1:b1:e1:28:2b:fe: + a4:9d:50:96:cd:c5:45:09:35:50:93:9b:97:a9:23:2a:5e:f0: + 2e:16:18:3f:50:7a:83:59:c5:6c:79:99:d3:ea:12:ef:15:a9: + b0:93:1e:4b:26:6c:63:13:7f:d3:5a:0c:4d:0b:f4:51:21:98: + 4f:81 +-----BEGIN CERTIFICATE----- +MIIC5TCCAk6gAwIBAgICECAwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDI4 +NDdaFw0zNTAxMTMxMDI4NDdaMIGVMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MUUwQwYDVQQDHjwAVQBzAGUAcgAgADMAMQAgAFwAIgBhACwAYgAiACsAQwBO +AD0AVQBTACwAIAA+ACAAXABcAGQAZQAgADwwgZ8wDQYJKoZIhvcNAQEBBQADgY0A +MIGJAoGBAKwCGOAcVLt2ly7TZ3i3FHhGg3zpXCsvJbu/kMBS6ix51p2vtfiGor9W +mw8z7e/SLFfGCiWz95uhejt1CxiGI2QqI7Bg8dgFtKZ7dyEwtA3xr+H71oioW11+ +or/OIPbAeonyDzNHbUkPPVkn+ZXAO6McGKEtlQno0pWsEJL824TjAgMBAAGjeDB2 +MAsGA1UdDwQEAwIF4DAdBgNVHQ4EFgQU+Lp+eLxwM9NFaDdZOgasZbEVdPAwHwYD +VR0jBBgwFoAU6Gq7wpDqbHAiPvb2SBsD5r63plUwJwYDVR0RBCAwHqQcMBoxGDAW +BgNVBAMTD1VzZXIgMzEgUm9vdCAxMTANBgkqhkiG9w0BAQUFAAOBgQAPqFPwVnbf +qLNb0eiYYo+mE5bDa8o/4Qk3VG+sFUt0DGw//t42WKKdoB8YlywdvMbf7qpb09ov +UQJ6uql+Tc9HFgvxseEoK/6knVCWzcVFCTVQk5uXqSMqXvAuFhg/UHqDWcVseZnT +6hLvFamwkx5LJmxjE3/TWgxNC/RRIZhPgQ== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1021.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1021.pem new file mode 100644 index 0000000000..443c074628 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1021.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4129 (0x1021) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 10:40:59 2010 GMT + Not After : Jan 13 10:40:59 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00U\x00s\x00e\x00r\x00 \x001\x004\x00 \x00"\x00,\x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00q\x00u\x00o\x00t\x00e + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:da:7a:30:0d:63:da:74:05:ef:3e:d2:f4:2b:1b: + 50:e3:64:67:98:7d:2f:83:e7:77:7b:b8:72:9b:c8: + 9e:65:de:cc:2a:7b:76:c2:08:05:7a:ce:88:3e:ed: + b5:75:89:36:d2:4a:bb:3b:66:ac:57:2b:15:99:c9: + d4:74:ca:f5:eb:ff:80:b7:9f:6b:48:2f:3b:a7:51: + c4:12:af:96:ca:ac:b9:ea:23:fd:93:f7:7d:5b:d1: + ab:7c:24:1e:fe:48:dc:33:de:45:d6:8c:86:5a:b9: + 56:3c:e4:a9:f1:8c:d7:41:01:da:04:2a:7d:06:c3: + 5b:a4:cc:5f:6c:ef:7c:4e:ef + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 49:E2:AE:12:D7:EF:C3:B5:02:65:DD:CF:B2:62:E6:25:ED:3D:10:9C + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 14 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 8b:ca:d2:93:cb:d1:cc:a9:67:a3:be:75:cf:ca:cd:22:78:cc: + 7c:f9:f1:2c:94:2c:60:bd:0f:18:16:26:fe:de:0d:19:5a:87: + de:34:8c:1f:eb:89:37:74:63:d4:d9:cd:59:35:06:24:a5:6f: + f2:c6:69:f4:b5:37:6d:ae:8b:d3:5d:5e:43:8f:36:7d:f8:0c: + 30:3f:74:3d:e2:85:89:75:58:36:0f:df:72:17:47:22:c6:fd: + 47:e3:d6:73:d1:40:89:e8:9a:ba:53:14:5c:3a:de:a9:85:a8: + 8f:b0:27:81:4d:87:ef:bb:6b:bf:8c:8a:71:9b:94:1d:30:d5: + 12:ed +-----BEGIN CERTIFICATE----- +MIIC1TCCAj6gAwIBAgICECEwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDQw +NTlaFw0zNTAxMTMxMDQwNTlaMIGFMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MTUwMwYDVQQDHiwAVQBzAGUAcgAgADEANAAgACIALABtAGkAZABkAGwAZQAg +AHEAdQBvAHQAZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA2nowDWPadAXv +PtL0KxtQ42RnmH0vg+d3e7hym8ieZd7MKnt2wggFes6IPu21dYk20kq7O2asVysV +mcnUdMr16/+At59rSC87p1HEEq+Wyqy56iP9k/d9W9GrfCQe/kjcM95F1oyGWrlW +POSp8YzXQQHaBCp9BsNbpMxfbO98Tu8CAwEAAaN4MHYwCwYDVR0PBAQDAgXgMB0G +A1UdDgQWBBRJ4q4S1+/DtQJl3c+yYuYl7T0QnDAfBgNVHSMEGDAWgBToarvCkOps +cCI+9vZIGwPmvremVTAnBgNVHREEIDAepBwwGjEYMBYGA1UEAxMPVXNlciAxNCBS +b290IDExMA0GCSqGSIb3DQEBBQUAA4GBAIvK0pPL0cypZ6O+dc/KzSJ4zHz58SyU +LGC9DxgWJv7eDRlah940jB/riTd0Y9TZzVk1BiSlb/LGafS1N22ui9NdXkOPNn34 +DDA/dD3ihYl1WDYP33IXRyLG/Ufj1nPRQInomrpTFFw63qmFqI+wJ4FNh++7a7+M +inGblB0w1RLt +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1022.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1022.pem new file mode 100644 index 0000000000..6902605756 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1022.pem @@ -0,0 +1,64 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4130 (0x1022) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Nov 8 10:51:39 2010 GMT + Not After : Nov 8 10:51:39 2011 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 35 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:9b:36:00:64:f3:ce:93:97:62:19:fa:78:d9:6f: + 92:6a:b9:d2:9a:4e:06:2c:02:52:cd:93:50:84:28: + 19:42:a2:4a:34:e2:cd:e6:b0:39:7a:c8:4d:84:bc: + 71:51:ed:5d:6c:7e:f9:cc:01:5a:4b:73:50:a9:3b: + 5d:ad:cc:89:f7:dc:e0:dd:0a:ff:48:01:a9:34:19: + c0:6a:ee:4b:20:f4:cf:3c:94:c1:ae:88:0f:c9:42: + 1a:a6:47:31:fe:37:04:00:bb:ec:07:5f:cb:ee:70: + c4:c7:7c:6f:ee:03:19:76:de:0b:df:d0:48:91:67: + 55:9b:90:91:f4:ce:56:04:d5 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 91:47:AC:29:95:5D:EF:72:14:8F:82:45:07:E2:94:49:75:C6:7D:73 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DNS:alt.openoffice.org, IP Address:192.168.7.1, IP Address:13:0:0:0:0:0:0:17, email:my@other.address, Registered ID:1.2.3.4, othername:<unsupported>, DirName:/C=DE/O=OpenOffice.org/OU=Development/CN=User 32 Root 11, URI:http://my.url.here/ + Signature Algorithm: sha1WithRSAEncryption + 6e:80:e6:1e:86:3d:d2:65:a6:17:fa:80:2d:2e:dc:85:32:05: + a1:69:82:e1:79:d1:dc:de:69:cd:9e:f0:cc:90:75:a9:45:ee: + 73:46:fe:29:69:c0:99:bb:fc:3a:db:c0:5f:69:c6:b7:ea:9a: + 63:b2:8e:29:2c:a5:5a:88:88:94:75:4b:ab:0a:72:f6:3a:aa: + 5d:6b:3a:5c:b6:9b:57:f5:c1:51:af:df:3c:a6:8a:a3:da:70: + 66:61:49:12:06:78:98:9f:bc:78:3c:43:6d:08:94:aa:32:b6: + f3:cc:af:0d:29:fe:96:47:7d:fe:4a:61:48:90:11:0b:bd:0f: + a0:fd +-----BEGIN CERTIFICATE----- +MIIDajCCAtOgAwIBAgICECIwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDExMDgxMDUx +MzlaFw0xMTExMDgxMDUxMzlaMGAxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxEDAOBgNVBAMTB1VzZXIgMzUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB +AJs2AGTzzpOXYhn6eNlvkmq50ppOBiwCUs2TUIQoGUKiSjTizeawOXrITYS8cVHt +XWx++cwBWktzUKk7Xa3Miffc4N0K/0gBqTQZwGruSyD0zzyUwa6ID8lCGqZHMf43 +BAC77Adfy+5wxMd8b+4DGXbeC9/QSJFnVZuQkfTOVgTVAgMBAAGjggExMIIBLTAL +BgNVHQ8EBAMCBeAwHQYDVR0OBBYEFJFHrCmVXe9yFI+CRQfilEl1xn1zMB8GA1Ud +IwQYMBaAFOhqu8KQ6mxwIj729kgbA+a+t6ZVMIHdBgNVHREEgdUwgdKCEmFsdC5v +cGVub2ZmaWNlLm9yZ4cEwKgHAYcQABMAAAAAAAAAAAAAAAAAF4EQbXlAb3RoZXIu +YWRkcmVzc4gDKgMEoB4GAyoDBKAXDBVzb21lIG90aGVyIGlkZW50aWZpZXKkWDBW +MQswCQYDVQQGEwJERTEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsT +C0RldmVsb3BtZW50MRgwFgYDVQQDEw9Vc2VyIDMyIFJvb3QgMTGGE2h0dHA6Ly9t +eS51cmwuaGVyZS8wDQYJKoZIhvcNAQEFBQADgYEAboDmHoY90mWmF/qALS7chTIF +oWmC4XnR3N5pzZ7wzJB1qUXuc0b+KWnAmbv8OtvAX2nGt+qaY7KOKSylWoiIlHVL +qwpy9jqqXWs6XLabV/XBUa/fPKaKo9pwZmFJEgZ4mJ+8eDxDbQiUqjK288yvDSn+ +lkd9/kphSJARC70PoP0= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/private/cakey.pem new file mode 100644 index 0000000000..fb0dd164ef --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,F268674FF1377D42 + +kJQy9qJMCqZyDVs3+ZKQnh22enecltKSYzd0S1dIN1chgQ0RzLEiWBHmHCVP/yB0 +YoKrQ07FUR/uSLqTbyhAl+KDVcNvqrj/NeWs0n8zqN0ZF6wQtxtDrWFWmHNAvQXU +2kO1CvjYiruapgwmVDDJV1qf25byenQv9LMyQMD6EPU1XqFeamklidALdkb7DylA +WL6EIg4vhh96ZaG6PwLcB9rho0QRrXrLS6SHiklNBN5fHUWOfDyhXJ7K4HvzH1SS +/EtqgyKKxH5irTRdoJg2OaDBAahyW93CneEnFdufDgzvCdrsg79Z2GFz7TDJEfW4 +rnoqoXTdei1Ah+t1BC4uXXAU8DR0xusnJi0qJDJ7ETRBhROlNhTRF8TAHll+5dIf +9772GwVT+hADZn1qJgmhPiN4f8Fx33k5NOcwb0X/0Z1mzULrwm1P6lng0DsusDo0 +dr/wFyRjWZEWhMcL/sIO1BwVTBPcE8CACnXutehs44DBWd91EQ4+PWNq7oPtHFw8 +09d30h4aJJZF/SGRi+f/czFyZF4WS2Q+UWmNNKJX8wCGQqzUb02kVwMEWHiNFiEo +V8xI3JXVmKHDWlgdoIz9kVe//3AfY5y+52cYLdqaNW8IsgWZC8SC9Lk9j5uaNZ/I +leNppt4ID7mfYPqjEXEKleC+1ncwFwdVl/zaa/fM78sWqDYrLZC47DToLfoQ9Gez +3dj3554iHTe61Jd7JsK85pYsrIHAeYppOpqzLyQmCu3twBl3uGD7KXxvdZRt8foE +Vrg/QSIB4E6gfSBP0UrXzsnga8tjVyqRW2vAvt0uLn945ducapf9oQ== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/serial b/xmlsecurity/test_docs/CAs/Root_11/demoCA/serial new file mode 100644 index 0000000000..b70608fe85 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/serial @@ -0,0 +1 @@ +1023 diff --git a/xmlsecurity/test_docs/CAs/Root_11/openssl.cfg b/xmlsecurity/test_docs/CAs/Root_11/openssl.cfg new file mode 100644 index 0000000000..dd84cb9069 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/openssl.cfg @@ -0,0 +1,298 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert +utf8 = yes +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask =pkix + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 +commonName_default =User 14 \",middle quote + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +#nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move +subjectAltName=DNS:alt.openoffice.org,IP:192.168.7.1,IP:13::17,email:my@other.address,RID:1.2.3.4,otherName:1.2.3.4;UTF8:some other identifier,dirName:dir_sect,URI:http://my.url.here/ +# Copy subject details +# issuerAltName=issuer:copy + + +[dir_sect] +C=DE +O=OpenOffice.org +OU=Development +CN=User 32 Root 11 + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Root_7.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Root_2/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Root_2/demoCA/cacert.pem new file mode 100644 index 0000000000..e64badeef6 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_2/demoCA/cacert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDBDCCAm2gAwIBAgIJAKKvFYnsc1SGMA0GCSqGSIb3DQEBBQUAMF8xCzAJBgNV +BAYTAkRFMRAwDgYDVQQIEwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9y +ZzEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgMjAeFw0wOTEx +MTgxNTQ2NTJaFw0zNDExMTIxNTQ2NTJaMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgMjCBnzANBgkqhkiG9w0BAQEFAAOBjQAw +gYkCgYEAsJSDLnSsoNY1U8hS0g5cmu7ihp+nvDvx8C75Wav80KumG9gcS3icmSOm +vPVqUmJq5o9CKM8z4vJR7D3e+Wf7S7XHMdL0uXuQi+QQCB1aMAWMxo7xnoWAXZrS +LG1BWUjD9sdKCHuQfFQv9ke3cA2dGZFSMsUD73JYoo0RD72ftFkCAwEAAaOBxzCB +xDAdBgNVHQ4EFgQUX7xM2usKDLUjQ14kMid5QfWCowIwgZEGA1UdIwSBiTCBhoAU +X7xM2usKDLUjQ14kMid5QfWCowKhY6RhMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgMoIJAKKvFYnsc1SGMA8GA1UdEwEB/wQF +MAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAqfEPhXASt24n8P9mDKisEn2EIYmJKLaY +AVwXLPXUOiMlqrfPRKpseQII4WmDCRxMa6bKCwf4pKUWIpTpDhRZCUespaLz1AcU +ntv+HTXq1ECK+akK33fsh5qMvokfzZM+Q0zCiFV/c2aTTGSM5mV3/q810RUlNQY3 +1y+AN+6fRqE= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_2/demoCA/crl/DO_NOT_CREATE_A_CRL b/xmlsecurity/test_docs/CAs/Root_2/demoCA/crl/DO_NOT_CREATE_A_CRL new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_2/demoCA/crl/DO_NOT_CREATE_A_CRL diff --git a/xmlsecurity/test_docs/CAs/Root_2/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Root_2/demoCA/crlnumber new file mode 100644 index 0000000000..83b33d238d --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_2/demoCA/crlnumber @@ -0,0 +1 @@ +1000 diff --git a/xmlsecurity/test_docs/CAs/Root_2/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Root_2/demoCA/index.txt new file mode 100644 index 0000000000..3e79e22d7c --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_2/demoCA/index.txt @@ -0,0 +1 @@ +V 341112155538Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 1 Root 2 diff --git a/xmlsecurity/test_docs/CAs/Root_2/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Root_2/demoCA/index.txt.attr new file mode 100644 index 0000000000..8f7e63a347 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_2/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Root_2/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Root_2/demoCA/newcerts/1000.pem new file mode 100644 index 0000000000..36a8eb3c07 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_2/demoCA/newcerts/1000.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 2 + Validity + Not Before: Nov 18 15:55:38 2009 GMT + Not After : Nov 12 15:55:38 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 2 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:f0:7a:16:4c:ab:06:b2:af:27:9c:7d:3f:86:da: + de:7a:c3:01:67:77:56:49:09:ed:ed:31:72:83:e8: + 75:9c:4c:ce:f9:97:b6:63:3c:e2:ca:83:80:92:03: + 9c:96:e2:de:72:79:c1:cf:3e:3f:b9:0d:b4:87:c7: + 75:e6:56:8d:aa:f8:77:47:11:4e:fe:07:b0:1d:64: + 06:73:4b:6f:d4:ac:da:0f:05:87:b1:f1:98:a9:f5: + 8a:a1:a8:ed:17:9c:26:b8:da:92:63:d2:53:87:e6: + fc:ed:44:de:94:56:90:3e:a2:a1:67:08:cb:38:d4: + cf:17:3b:7e:ff:7a:97:c0:7b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 8C:F3:2C:30:A2:E8:62:50:70:BC:FC:71:A0:41:FA:E0:58:B4:4D:B8 + X509v3 Authority Key Identifier: + keyid:5F:BC:4C:DA:EB:0A:0C:B5:23:43:5E:24:32:27:79:41:F5:82:A3:02 + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 2 + serial:A2:AF:15:89:EC:73:54:86 + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 52:83:16:ab:0e:43:2d:b3:e4:0f:6c:c1:63:d4:86:ac:e7:1e: + ee:7b:ee:9b:0c:ff:4f:e0:59:d5:e4:27:af:68:bf:a7:f5:2a: + a3:c9:e3:2b:8d:b7:31:26:f6:04:80:4e:f2:a5:bf:da:63:5e: + 8c:d6:c6:b2:46:a0:46:10:2f:84:9f:02:76:f3:c8:33:05:62: + 0c:5f:2d:cc:06:23:53:9f:d9:f8:46:e4:2e:5c:da:05:fc:bf: + db:45:b4:ac:8d:8b:b5:4b:60:7b:7b:26:34:7f:b1:4b:41:96: + 41:26:70:7a:9d:78:a2:9b:e0:de:62:a2:04:86:9f:ed:7c:a6: + 20:eb +-----BEGIN CERTIFICATE----- +MIIDBjCCAm+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCAyMB4XDTA5MTExODE1NTUz +OFoXDTM0MTExMjE1NTUzOFowaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCAyMIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDwehZMqwayryecfT+G2t56wwFnd1ZJCe3tMXKD6HWcTM75l7ZjPOLK +g4CSA5yW4t5yecHPPj+5DbSHx3XmVo2q+HdHEU7+B7AdZAZzS2/UrNoPBYex8Zip +9YqhqO0XnCa42pJj0lOH5vztRN6UVpA+oqFnCMs41M8XO37/epfAewIDAQABo4HH +MIHEMB0GA1UdDgQWBBSM8ywwouhiUHC8/HGgQfrgWLRNuDCBkQYDVR0jBIGJMIGG +gBRfvEza6woMtSNDXiQyJ3lB9YKjAqFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCAyggkAoq8ViexzVIYwDwYDVR0TAQH/ +BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBSgxarDkMts+QPbMFj1Ias5x7ue+6b +DP9P4FnV5CevaL+n9SqjyeMrjbcxJvYEgE7ypb/aY16M1sayRqBGEC+EnwJ288gz +BWIMXy3MBiNTn9n4RuQuXNoF/L/bRbSsjYu1S2B7eyY0f7FLQZZBJnB6nXiim+De +YqIEhp/tfKYg6w== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_2/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Root_2/demoCA/private/cakey.pem new file mode 100644 index 0000000000..7ef7ef0a5e --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_2/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,52B792B2B0E03BD6 + +GIFY+N2q5LMcrtTplZUToF0/nuplr7ASLAe7lEcDLTTHeBTO+w4ScB62Dl6veeEU +3/pPevG+V3HIA5ukywX334DuWjL3bFIsPg8a3NKKn0nTpmwqHqXZ53kbSMHIiu6v +MkvGeVLLxLhnCsqQ8HI2ccuxGSXLA0rqlnrZTOtvQpw9ohpCM3CX1GeekLc83bL/ +4HHmw8nNL+OCH4l9g3Y8XpN3ySRgl+lWmoKxl9s2Mn7jFoaqSXuuH3wIu9D2kJxS +qfVs/fo12j8RWXSIMpiCJFCOx1v+zzX7dJ0cyim83WF2OHsOW03UYnWzgk44iz4d +/WVWJuRU3gEwpN3CDdhzBZuYw9DmaG8HLHYT15CSdkQrfHeFM3Axcoju7b887JX7 +sOHU6h4ebMVhAswAXKGlTKOY2PO1GE9cKoa2jxnB2z8Dhe8rxzuvWyr5BfXrS3KT +lM6pjxZSoGMcmG7FtDgU/aAIn+DPR/rdB7tfZwP3GoVV+n3jRi8LU5I3wbi4z70o +bwXMb7zN13WHFszZgPX4tHD3jjyLwk7rFmMJ17L3K6eOAlGg8o+FBgoqYFQo05sY +2SElOibX8RIj9m9lerNLOxB5ty2VDUSaytJ0b1gPTXAdsaryq7tKFxIrNKpiJ1qk +snQSJyr2JwRqBLRwkXZV5CliWwZJGGJsC9I5fAMuuW6qkDhsSQ1fIJsGn/SbbiZj +lnZVY/33vHMltbwEgY4GuQWm29VYJwLWk925BY/nQ5fWPARYsap04JIwtperrZKj +XETzTrnTje6sVl32aCLdYlwsVbh04zRwUFharCz5vtDdVeHrfsBDKA== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Root_2/demoCA/serial b/xmlsecurity/test_docs/CAs/Root_2/demoCA/serial new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_2/demoCA/serial @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Root_2/openssl.cfg b/xmlsecurity/test_docs/CAs/Root_2/openssl.cfg new file mode 100644 index 0000000000..0dd15bd9ec --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_2/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Root_3/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Root_3/demoCA/cacert.pem new file mode 100644 index 0000000000..55be155218 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_3/demoCA/cacert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDBDCCAm2gAwIBAgIJAJVv8OMrvnb5MA0GCSqGSIb3DQEBBQUAMF8xCzAJBgNV +BAYTAkRFMRAwDgYDVQQIEwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9y +ZzEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgMzAeFw0wOTEx +MjAwNzM2MTVaFw0zNDExMTQwNzM2MTVaMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgMzCBnzANBgkqhkiG9w0BAQEFAAOBjQAw +gYkCgYEA3L6zaGhxFC+Mf55dzotmPKxdZndlxSVVOVI93JrxKVfn8mYOCZEjdb9Q +65vgLxGXMC9LCiF6SfT8dIfav1hUugmLaLzBesPu6h4kHN33/7Asj8BzY5I57uvF +sMLNL5hHFRRqtBqHvmO2G8zjHPluObnBzaQNCbdZxYODeh1GFpECAwEAAaOBxzCB +xDAdBgNVHQ4EFgQUaf8w7B80mmc6ayDS33/1BQTt+RwwgZEGA1UdIwSBiTCBhoAU +af8w7B80mmc6ayDS33/1BQTt+RyhY6RhMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgM4IJAJVv8OMrvnb5MA8GA1UdEwEB/wQF +MAMBAf8wDQYJKoZIhvcNAQEFBQADgYEABPdAJer/8FoOAMWszhfz/BEjF97TTFs1 +KqSEiuymswG706weo9tcnP8u81AITQPSWZE1ALQN5L35Zvg6ubJsNM3+VSoQ6hZj +G9oWAJzFN7DhIqs3Xb13eBH/0yqAdTuFB5uLcJdR3GIXGFvcU/5FZBpYnORVqvg4 +irKv2VvyCR0= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_3/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Root_3/demoCA/crlnumber new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_3/demoCA/crlnumber @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Root_3/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Root_3/demoCA/index.txt new file mode 100644 index 0000000000..dd9a47ee64 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_3/demoCA/index.txt @@ -0,0 +1 @@ +V 341114074039Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 1 Root 3 diff --git a/xmlsecurity/test_docs/CAs/Root_3/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Root_3/demoCA/index.txt.attr new file mode 100644 index 0000000000..8f7e63a347 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_3/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Root_3/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Root_3/demoCA/newcerts/1000.pem new file mode 100644 index 0000000000..c14880b580 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_3/demoCA/newcerts/1000.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 3 + Validity + Not Before: Nov 20 07:40:39 2009 GMT + Not After : Nov 14 07:40:39 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 3 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:9e:87:1f:af:f0:a0:1c:f4:9e:f8:c3:e7:ee:d3: + cb:a8:e2:54:98:ba:dd:7e:dc:6e:14:e1:7e:7f:5b: + 1e:ef:53:3d:89:76:ea:e2:b3:6c:08:0d:e8:c8:4d: + 24:40:ff:92:f3:5b:51:f7:90:ac:69:37:29:90:f5: + e8:95:6f:67:d1:10:cd:7b:dd:65:38:d6:25:ec:63: + 39:ba:2e:ea:13:58:8e:7a:82:8e:10:d1:7b:77:7a: + 08:d5:82:66:62:a4:83:39:ad:f5:83:d5:2f:5c:bc: + 23:6e:c8:78:8b:38:9f:eb:a3:67:ba:43:fa:e4:07: + 3f:90:72:db:0c:f9:49:0e:0d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 1B:2D:E0:A2:26:7F:0D:BA:38:7E:EC:06:81:81:0F:12:74:4C:5A:4D + X509v3 Authority Key Identifier: + keyid:69:FF:30:EC:1F:34:9A:67:3A:6B:20:D2:DF:7F:F5:05:04:ED:F9:1C + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 3 + serial:95:6F:F0:E3:2B:BE:76:F9 + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 6f:ac:53:9d:16:6e:95:ed:97:60:ed:c8:a8:96:ab:24:c5:1e: + d5:d7:26:98:fb:b5:aa:ef:da:a4:91:6a:82:55:ec:21:a2:08: + 24:c7:0c:a7:58:0c:06:69:3d:04:7d:08:f1:0b:77:41:ad:1c: + 13:c2:bd:17:c9:9e:ff:df:64:69:8b:58:f1:bc:40:bd:cf:e4: + 57:29:bc:5e:93:84:61:56:4c:e6:c1:3a:2c:6e:71:ea:5d:67: + c0:54:be:4f:2f:27:a8:59:8d:29:94:ba:c6:6c:ff:ed:25:3d: + 0b:fa:93:c9:45:f4:d5:a3:3d:be:8a:f1:9d:c4:92:d5:5c:d2: + 77:7c +-----BEGIN CERTIFICATE----- +MIIDBjCCAm+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCAzMB4XDTA5MTEyMDA3NDAz +OVoXDTM0MTExNDA3NDAzOVowaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCAzMIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQCehx+v8KAc9J74w+fu08uo4lSYut1+3G4U4X5/Wx7vUz2Jduris2wI +DejITSRA/5LzW1H3kKxpNymQ9eiVb2fREM173WU41iXsYzm6LuoTWI56go4Q0Xt3 +egjVgmZipIM5rfWD1S9cvCNuyHiLOJ/ro2e6Q/rkBz+QctsM+UkODQIDAQABo4HH +MIHEMB0GA1UdDgQWBBQbLeCiJn8Nujh+7AaBgQ8SdExaTTCBkQYDVR0jBIGJMIGG +gBRp/zDsHzSaZzprINLff/UFBO35HKFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCAzggkAlW/w4yu+dvkwDwYDVR0TAQH/ +BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBvrFOdFm6V7Zdg7ciolqskxR7V1yaY ++7Wq79qkkWqCVewhoggkxwynWAwGaT0EfQjxC3dBrRwTwr0XyZ7/32Rpi1jxvEC9 +z+RXKbxek4RhVkzmwTosbnHqXWfAVL5PLyeoWY0plLrGbP/tJT0L+pPJRfTVoz2+ +ivGdxJLVXNJ3fA== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_3/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Root_3/demoCA/private/cakey.pem new file mode 100644 index 0000000000..445d86f995 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_3/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,24B61B9BC2D90894 + +pJUmVTVcjD3b4WKoSDJHrxHYOJ5/6P0FyQRYaJhnDXpcC5cQywl7yuD3HpRh3cXT +Y5k6d1E64St3I/IDImdbiEEDbjlSG9gfFf9vYeP/Xlpaja0Y9Q2ePnQvJY47HB7+ +qkrt6b+3yIW024wHi83dzaeYeNUJaY1jGsra2TzGk/+hYrf6yvnyehEAsy5WChof +bfaQ29RrGTlzf6IpSRpiHUL7nVl+eHfbGLX4Ih8aEFXpcnoWtpY8FgQ5+bJxMeR4 +R2ge0c3G0VIBXBRRUoGsU0ZcRLdxYUFcDGZse50ZboUwvROfPCimowcyWKluV9yj +l4+e3glYcwGHRqHYArsLDUV2hzHHEJ1IKn4E+oExqQSGgDQgUDN0kjlRPPxWQb29 +6dZSHW4VXW609Q10FKbPuCocgQ2Ut2bNGWqXsiNNTr39iB0r/hA/V4bKy3G8ogsH +AQFp6D9LaFlt9ZFA49Y4WoPzSY9J2C4eFJzQ+jhCpeapzQ54BWNTYMQe+SJHkp1O +PWVovUrRbTDesIUeY1UJuSnbDotOc6vzEAsP+FIL2qUySUGG/CPyAf3R4FyahwjL +bgU5kmpzBKsgqRYrO2yfLz5/3/e9xUGfHVi8lbI5f21NQKesqHY2xS2NmGvakzbe +ZvD3bhythAR5L0Pp+tiiHE1LUAbcKp90aFPeaONDpUtrRU21gqqvEKnnubCvnjmE +l6GrH2WKSgxJbQ3GGqNaDg1ivB8XXyjx7guvBzpA0Pe2YCYMa0RI27GywNkv+RsR +eo3ox2QhUpvPxUl3ijwOPN3EFXrq0gdlYQJBWW3GLlX4Q71KJF+jUQ== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Root_3/demoCA/serial b/xmlsecurity/test_docs/CAs/Root_3/demoCA/serial new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_3/demoCA/serial @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Root_3/openssl.cfg b/xmlsecurity/test_docs/CAs/Root_3/openssl.cfg new file mode 100644 index 0000000000..51e5205253 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_3/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Root_4/README.txt b/xmlsecurity/test_docs/CAs/Root_4/README.txt new file mode 100644 index 0000000000..b9fb278a27 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_4/README.txt @@ -0,0 +1,4 @@ +Revoked certificates: + +- Sub CA 2 Root 4 + diff --git a/xmlsecurity/test_docs/CAs/Root_4/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Root_4/demoCA/cacert.pem new file mode 100644 index 0000000000..45b4ce8a5f --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_4/demoCA/cacert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDBDCCAm2gAwIBAgIJAKKTRnQ7puOtMA0GCSqGSIb3DQEBBQUAMF8xCzAJBgNV +BAYTAkRFMRAwDgYDVQQIEwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9y +ZzEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgNDAeFw0wOTEx +MjAwODM1MDRaFw0zNDExMTQwODM1MDRaMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgNDCBnzANBgkqhkiG9w0BAQEFAAOBjQAw +gYkCgYEA2k+jPArotoY09an0BpF3RYIPP/5RN04E4S+Ulp/ipttaVxtAC0ojJSlp +0PGp/vIodFT9pkBb0nq56LHjFLj+lyW5tKAR+4B+VVvzwJhUBD8qHjYJE30vWZ88 +3+3I+GmXDzy962kQxrb4J6dBwGImoqhBTXWOxGnPjXxtovzYmMECAwEAAaOBxzCB +xDAdBgNVHQ4EFgQUuo2hl9zEOR+QtVFrEBnyRg2pZY4wgZEGA1UdIwSBiTCBhoAU +uo2hl9zEOR+QtVFrEBnyRg2pZY6hY6RhMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgNIIJAKKTRnQ7puOtMA8GA1UdEwEB/wQF +MAMBAf8wDQYJKoZIhvcNAQEFBQADgYEARdHX1KRJ/DE1zOkbjINPX4pFjTMIIfKd +ncEBM7Po20it75Hbl8bHoxwCrjOu+9L1xaTCWcunyqv26yrjVpORPHPODLMc2W8x +FQm39hL6a0RjqurDlhcrjor3HD7hQ+GjEUDAX6Pk9RDxN+uMHvF5/5WCEhSn2aLT +IozGu5SmZys= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_4/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Root_4/demoCA/crlnumber new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_4/demoCA/crlnumber @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Root_4/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Root_4/demoCA/index.txt new file mode 100644 index 0000000000..f07b3377de --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_4/demoCA/index.txt @@ -0,0 +1,2 @@ +V 341114083727Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 1 Root 4 +R 341114092227Z 091120092718Z,keyCompromise 1001 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 2 Root 4 diff --git a/xmlsecurity/test_docs/CAs/Root_4/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Root_4/demoCA/index.txt.attr new file mode 100644 index 0000000000..8f7e63a347 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_4/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Root_4/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Root_4/demoCA/newcerts/1000.pem new file mode 100644 index 0000000000..3910371181 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_4/demoCA/newcerts/1000.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 4 + Validity + Not Before: Nov 20 08:37:27 2009 GMT + Not After : Nov 14 08:37:27 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 4 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:da:b0:21:94:89:b0:00:89:cb:69:59:9b:0d:fe: + 1f:b9:a0:a8:44:92:55:5f:0b:d5:e5:08:63:bd:47: + 6b:11:4d:b1:a8:12:6f:c1:cf:cb:9e:ae:e2:c1:03: + 68:46:59:0b:96:7c:21:45:9b:14:81:d8:f1:83:70: + 6b:3d:b4:56:65:49:87:1d:ab:e2:08:6a:49:66:0e: + 59:b4:da:7a:3f:72:23:b8:1f:fb:78:f5:f0:2d:c4: + fe:d9:94:6e:2e:c3:6e:95:ba:38:60:d1:0b:fa:16: + c7:02:71:ef:3e:71:72:63:26:56:35:1e:8b:ec:47: + 87:25:6e:bc:90:d0:8b:37:2d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 96:9A:2D:06:F6:76:4F:83:68:7B:9C:69:C4:18:BB:4A:EB:46:38:E4 + X509v3 Authority Key Identifier: + keyid:BA:8D:A1:97:DC:C4:39:1F:90:B5:51:6B:10:19:F2:46:0D:A9:65:8E + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 4 + serial:A2:93:46:74:3B:A6:E3:AD + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 45:77:ba:6b:b6:a7:2a:0f:6b:38:90:9f:0a:18:11:c7:54:7b: + c9:3b:9a:93:90:96:f0:04:0a:56:87:30:e0:f5:d8:84:40:39: + 90:85:ca:e7:38:1b:d8:df:2f:bd:73:91:13:cb:a6:c9:b0:7a: + f7:59:77:6b:9a:d5:86:78:06:dc:40:14:ce:ea:43:a8:ae:ed: + a2:03:64:51:3a:47:7a:9f:df:2d:65:49:56:a5:39:cf:28:2a: + ac:ab:fd:e1:93:fd:3e:56:e8:eb:7a:11:a8:f7:f9:1a:a1:83: + 1f:92:f7:da:4e:c6:d9:67:dd:67:ff:be:6f:e5:24:e1:6e:cc: + 94:3c +-----BEGIN CERTIFICATE----- +MIIDBjCCAm+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA0MB4XDTA5MTEyMDA4Mzcy +N1oXDTM0MTExNDA4MzcyN1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA0MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDasCGUibAAictpWZsN/h+5oKhEklVfC9XlCGO9R2sRTbGoEm/Bz8ue +ruLBA2hGWQuWfCFFmxSB2PGDcGs9tFZlSYcdq+IIaklmDlm02no/ciO4H/t49fAt +xP7ZlG4uw26Vujhg0Qv6FscCce8+cXJjJlY1HovsR4clbryQ0Is3LQIDAQABo4HH +MIHEMB0GA1UdDgQWBBSWmi0G9nZPg2h7nGnEGLtK60Y45DCBkQYDVR0jBIGJMIGG +gBS6jaGX3MQ5H5C1UWsQGfJGDalljqFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA0ggkAopNGdDum460wDwYDVR0TAQH/ +BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBFd7prtqcqD2s4kJ8KGBHHVHvJO5qT +kJbwBApWhzDg9diEQDmQhcrnOBvY3y+9c5ETy6bJsHr3WXdrmtWGeAbcQBTO6kOo +ru2iA2RROkd6n98tZUlWpTnPKCqsq/3hk/0+VujrehGo9/kaoYMfkvfaTsbZZ91n +/75v5SThbsyUPA== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_4/demoCA/newcerts/1001.pem b/xmlsecurity/test_docs/CAs/Root_4/demoCA/newcerts/1001.pem new file mode 100644 index 0000000000..9d951ee267 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_4/demoCA/newcerts/1001.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4097 (0x1001) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 4 + Validity + Not Before: Nov 20 09:22:27 2009 GMT + Not After : Nov 14 09:22:27 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 2 Root 4 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:e5:8d:27:4e:09:53:08:61:c6:23:25:9e:dd:9c: + 07:bf:81:38:5c:5c:10:8f:e4:12:2f:4e:2e:b1:a1: + cf:21:46:53:bf:e8:5e:de:17:3a:9d:f7:e8:ef:3e: + 9c:b4:29:37:4c:31:35:15:dc:98:e0:93:9c:ce:6a: + d6:e1:35:19:6b:d4:1d:3b:81:86:b1:e7:ff:1f:b8: + 34:a9:f9:de:4d:b8:62:ac:3b:d4:58:8e:5c:76:b5: + 07:7f:32:8a:3a:90:73:71:d5:da:f1:79:39:14:ed: + 1b:f1:8a:3e:be:48:bc:07:ec:f9:7c:03:14:fc:e7: + 55:a3:65:81:c7:6c:70:0b:ff + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 69:DE:B6:99:C4:95:F7:5A:FA:41:6B:4C:F6:C3:6D:89:AA:37:31:9D + X509v3 Authority Key Identifier: + keyid:BA:8D:A1:97:DC:C4:39:1F:90:B5:51:6B:10:19:F2:46:0D:A9:65:8E + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 4 + serial:A2:93:46:74:3B:A6:E3:AD + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + bc:cf:43:eb:72:b1:71:a7:94:8e:cd:5b:fc:d8:21:31:83:db: + a9:de:c7:5b:14:e5:7b:90:43:e6:05:df:db:6e:95:5f:24:ac: + 0c:a1:8a:ac:c6:cf:f2:03:cd:a0:30:ae:d3:a9:41:07:c9:b1: + be:4b:e0:fc:a2:76:09:07:75:6a:fa:e4:2f:a3:3a:cd:81:68: + ab:f6:06:c4:32:08:25:6e:e8:e7:36:9c:1a:f7:42:73:f8:b0: + d8:42:3e:85:c2:11:23:10:d6:6a:e4:8f:53:cb:8b:8b:1b:5a: + 4d:6d:9d:34:45:26:52:d2:ee:6d:8f:23:ff:00:92:f5:99:62: + 4c:41 +-----BEGIN CERTIFICATE----- +MIIDBjCCAm+gAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA0MB4XDTA5MTEyMDA5MjIy +N1oXDTM0MTExNDA5MjIyN1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDIgUm9vdCA0MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDljSdOCVMIYcYjJZ7dnAe/gThcXBCP5BIvTi6xoc8hRlO/6F7eFzqd +9+jvPpy0KTdMMTUV3Jjgk5zOatbhNRlr1B07gYax5/8fuDSp+d5NuGKsO9RYjlx2 +tQd/Moo6kHNx1drxeTkU7Rvxij6+SLwH7Pl8AxT851WjZYHHbHAL/wIDAQABo4HH +MIHEMB0GA1UdDgQWBBRp3raZxJX3WvpBa0z2w22JqjcxnTCBkQYDVR0jBIGJMIGG +gBS6jaGX3MQ5H5C1UWsQGfJGDalljqFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA0ggkAopNGdDum460wDwYDVR0TAQH/ +BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQC8z0PrcrFxp5SOzVv82CExg9up3sdb +FOV7kEPmBd/bbpVfJKwMoYqsxs/yA82gMK7TqUEHybG+S+D8onYJB3Vq+uQvozrN +gWir9gbEMgglbujnNpwa90Jz+LDYQj6FwhEjENZq5I9Ty4uLG1pNbZ00RSZS0u5t +jyP/AJL1mWJMQQ== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_4/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Root_4/demoCA/private/cakey.pem new file mode 100644 index 0000000000..003d2f3b56 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_4/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,26D3AA1ECCD64EF2 + +Smy62JNi1/1qKZI1q2lF13336vwJWfw+ii4g/ZwMJWuwTWUGXWZ1o9B9pZFo78KM +pMlasoCwAoI3lepMIwxtSRMgstxacJ4QRVPdevo7Qq6+++qNXdkqq9pYM19dsOiu +UNpbPXVvKQZnvm0ZFCjqiylvjCaQVQRScdwu9cJyq2qIQ1laXQoW2fPYBb8KSsCO +B5E76zAGdRlzEglT9Qkjbi2dQWxWpMHFfWZydFJnNbuh7O+RxCSOJN3jXlDRGPag +IwL4mFX8dElCwWhNpdd1pXF2ZXQ2S6Ke1MoOXRvJ7XVvEfnGyHpHQRdNB0M9gJCf +3ynJ0UUiCvXJs/6NEcOZzZ+R38XfMvsOcG1jNuh2KE5hW3cGbQMV2TPZMHjGE/qn +EhX+vzIOhRUPTUQjrjmV/lgioL4pMKFBXyfr2tkNLVOfzQtIXVfgxF1ooVmZFGKR +fAmHRbXKSrGWPJkX75bdlVnQ15qz5dU7PkIohGwGojOHuTWLXzKtOuLs7KMmH/i1 +5MhxcoXbI4R+hX/oj2Es4MKYFcSI0MID9Z5Se6z/yaz++5P9OrEGrXydg4W5YSuc +Q+MovUuqNoDH+Mo0z2P2DL4OxcIkBYoUVFOnIL2v5thRgbdWk05m0OBWYnvue9MG +CiuA49Lqg0H2ViZrDCyGDQNBkDkW7AKHYhVe3afHSDENX+wsgB1oj1bMvWNLQfCB +2IOYjv+of7tNOvIH6AuaJDqF2TYOm4ipcjSD/SEuKfrOgXlq6702tRhL4aAfHa6K +o1yrUfAxLwqN/TjSDNfOIUr5ro24tYnUaUnYPpn/zwZ5WfitZ4RGBg== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Root_4/demoCA/serial b/xmlsecurity/test_docs/CAs/Root_4/demoCA/serial new file mode 100644 index 0000000000..7d802a3e71 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_4/demoCA/serial @@ -0,0 +1 @@ +1002 diff --git a/xmlsecurity/test_docs/CAs/Root_4/openssl.cfg b/xmlsecurity/test_docs/CAs/Root_4/openssl.cfg new file mode 100644 index 0000000000..51e5205253 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_4/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Root_5/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Root_5/demoCA/cacert.pem new file mode 100644 index 0000000000..631deb24de --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_5/demoCA/cacert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDBDCCAm2gAwIBAgIJAPA9tqmpnKNOMA0GCSqGSIb3DQEBBQUAMF8xCzAJBgNV +BAYTAkRFMRAwDgYDVQQIEwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9y +ZzEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgNTAeFw0wOTEx +MjAxMDEwMzdaFw0zNDExMTQxMDEwMzdaMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgNTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw +gYkCgYEAwbqFK0+BWGylCl9gJj/eVuuNBcSgVetgx0cXwMRPHiwFZ8ilxPJm4kd0 +k2WDKHox5Ol8T0pU4n3fA5VmxjcfGnx03R8rFTn5deetrKQzyWUjz7EIl4mZYSvK +hwlbg5ZB4FJDYUoC/3eVHdQq2jUvRaQad1TvdBmvIMbDaYmTT3cCAwEAAaOBxzCB +xDAdBgNVHQ4EFgQUwdGg1FsLnX4xYfk5EJ8xEODSBrUwgZEGA1UdIwSBiTCBhoAU +wdGg1FsLnX4xYfk5EJ8xEODSBrWhY6RhMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgNYIJAPA9tqmpnKNOMA8GA1UdEwEB/wQF +MAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAeX2QYyrs9an5ObWjzauPCzr8hx6k8dF3 +YXU8f/JCf/fKG5u5WQZmmu0YZXMSaDyzqS3rKupDSm4kbfB9l9oTkgZszueI29pd +C/QIh8vUTiAlV5zxR4ypqmBg489W/uXdQPicuFhGFYX9EWjuGhwk8dL0dcUCufwX +UBYBlUiceFU= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_5/demoCA/crl/DO_NOT_CREATE_A_CRL b/xmlsecurity/test_docs/CAs/Root_5/demoCA/crl/DO_NOT_CREATE_A_CRL new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_5/demoCA/crl/DO_NOT_CREATE_A_CRL diff --git a/xmlsecurity/test_docs/CAs/Root_5/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Root_5/demoCA/crlnumber new file mode 100644 index 0000000000..83b33d238d --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_5/demoCA/crlnumber @@ -0,0 +1 @@ +1000 diff --git a/xmlsecurity/test_docs/CAs/Root_5/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Root_5/demoCA/index.txt new file mode 100644 index 0000000000..d910b9acc9 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_5/demoCA/index.txt @@ -0,0 +1 @@ +V 341114113023Z 1001 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 1 Root 5 diff --git a/xmlsecurity/test_docs/CAs/Root_5/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Root_5/demoCA/index.txt.attr new file mode 100644 index 0000000000..8f7e63a347 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_5/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Root_5/demoCA/newcerts/1001.pem b/xmlsecurity/test_docs/CAs/Root_5/demoCA/newcerts/1001.pem new file mode 100644 index 0000000000..b350f6eb33 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_5/demoCA/newcerts/1001.pem @@ -0,0 +1,66 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4097 (0x1001) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 5 + Validity + Not Before: Nov 20 11:30:23 2009 GMT + Not After : Nov 14 11:30:23 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 5 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:97:fa:a2:49:d3:bf:c1:2e:7a:ed:83:83:3c:78: + 96:c8:b2:b9:67:af:c0:5e:0a:89:89:fb:94:59:32: + a8:2a:e4:20:2f:3b:3d:ce:53:4f:72:fc:6c:0b:93: + 38:c3:df:66:6e:d5:79:d0:a4:4e:41:84:43:3c:99: + 79:0c:e0:5f:19:1a:3d:f5:4b:11:28:0f:80:b0:a0: + 71:34:5b:90:71:c2:ef:1e:85:2e:5b:9f:3b:22:c3: + 18:f8:7c:1f:ef:1b:78:17:a0:44:60:46:7e:88:eb: + a7:60:a0:5c:2a:7c:37:99:fa:27:97:08:e8:89:ba: + bc:69:4b:79:93:8f:ad:b5:9b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 01:E9:B5:99:E4:6D:F9:8C:42:3D:09:10:0F:A7:75:C6:27:78:4A:AF + X509v3 Authority Key Identifier: + keyid:C1:D1:A0:D4:5B:0B:9D:7E:31:61:F9:39:10:9F:31:10:E0:D2:06:B5 + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 5 + serial:F0:3D:B6:A9:A9:9C:A3:4E + + X509v3 CRL Distribution Points: + URI:http://localhost:8901/demoCA/crl/Root_5.crl + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 6d:ca:34:05:99:ff:99:49:d3:6d:9d:ad:c6:99:da:9d:6c:94: + 62:77:ed:1c:39:23:d2:e8:b6:3e:df:63:dc:7c:10:3f:c2:ed: + f4:04:26:58:05:01:4c:ed:a9:83:43:3a:5d:fe:60:6d:5b:58: + dc:93:8c:94:69:b6:7f:02:48:30:9c:31:f4:7d:de:e0:de:04: + d2:dc:79:b7:60:c2:87:f7:c7:92:a2:f5:86:a7:0c:70:3b:a3: + a7:35:11:cf:a4:28:21:aa:8b:24:50:2e:96:41:be:66:01:bd: + b9:ec:04:0c:92:d9:8a:e7:a0:96:24:9b:f1:a2:9f:59:59:4a: + 32:a4 +-----BEGIN CERTIFICATE----- +MIIDRjCCAq+gAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA1MB4XDTA5MTEyMDExMzAy +M1oXDTM0MTExNDExMzAyM1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA1MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQCX+qJJ07/BLnrtg4M8eJbIsrlnr8BeComJ+5RZMqgq5CAvOz3OU09y +/GwLkzjD32Zu1XnQpE5BhEM8mXkM4F8ZGj31SxEoD4CwoHE0W5Bxwu8ehS5bnzsi +wxj4fB/vG3gXoERgRn6I66dgoFwqfDeZ+ieXCOiJurxpS3mTj621mwIDAQABo4IB +BjCCAQIwHQYDVR0OBBYEFAHptZnkbfmMQj0JEA+ndcYneEqvMIGRBgNVHSMEgYkw +gYaAFMHRoNRbC51+MWH5ORCfMRDg0ga1oWOkYTBfMQswCQYDVQQGEwJERTEQMA4G +A1UECBMHSGFtYnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsT +C0RldmVsb3BtZW50MQ8wDQYDVQQDEwZSb290IDWCCQDwPbapqZyjTjA8BgNVHR8E +NTAzMDGgL6AthitodHRwOi8vbG9jYWxob3N0Ojg5MDEvZGVtb0NBL2NybC9Sb290 +XzUuY3JsMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAbco0BZn/ +mUnTbZ2txpnanWyUYnftHDkj0ui2Pt9j3HwQP8Lt9AQmWAUBTO2pg0M6Xf5gbVtY +3JOMlGm2fwJIMJwx9H3e4N4E0tx5t2DCh/fHkqL1hqcMcDujpzURz6QoIaqLJFAu +lkG+ZgG9uewEDJLZiuegliSb8aKfWVlKMqQ= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_5/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Root_5/demoCA/private/cakey.pem new file mode 100644 index 0000000000..222320a9a0 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_5/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,5F2D7F26BBEBD8FB + +qFyJ/G/DFwA+Kx3cVldc6bOMRbbduL7x5DBjCqS20YfoQoyvDcyel8FYz4/8CQ9d +kmb4nrM0Dj8/FgDiite2E8+qJV4U8OIBsXelFd8FWC8hB4z0DtwVxIAiM6mTMMcu +bWta3Lu5xrNvU/vosB967COztoYB5XLLQ/DrRPoV+tvJx0Le3zXLzceIj4PicuIk +/Mh5NVqN5a5blaV1/1JvcfOQLCI0rNebP3iAYhwCkKyu6WkpSNuHIw5gaMC6KXpq +ORPf3m+3/YKHLS9/tg+9CPQrRpyzLV/TOUduq6HFfzh9ZRXd04Dpn0P61JVCypYo +9u62lnNCAtreyvCUttzANLgujbgT9HNsjzKTAD2g+zjwQPgIS4epNm5LBPsQv15A +Vuw7CnNlLa8PxUxuDUjoW2YaGUR3PHNUz+TA1U0UFxlNK/lgeekIvmSvPjVyROOB +SxOH88yAZWe6pWioS3uzeg1kf1F5sj9u+KHPyikUe3nUBrS1cZSRtQczhlWWocgm +GtfwQSSVSwRtd7CWe/nQHuSJyrIJCbWFaDhnVXRhr+tyDpLtoeApCvefvel0p/AY +LTaRcno3zUxZS3G8Cv71hBPR8y5di5dAxBSfLgMYxwBD3UFO6CPkmiJteIhHska9 +FJqR98hfvF+0hwFnaFUTszDMGK1xV20MeTMhLAwSlttbuwtWMTourFKtS6t1SomB +JOTkpiVfojTSAJX40ExQgNtvY+7ayNUBLX9NIuIcOjFbQa1LNmGy9cOPQD49x067 +fALGA+V1KO7sFeUrunkpHncYoux5OThq3iDJ2tPfBmyhTQhOSzN38w== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Root_5/demoCA/serial b/xmlsecurity/test_docs/CAs/Root_5/demoCA/serial new file mode 100644 index 0000000000..7d802a3e71 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_5/demoCA/serial @@ -0,0 +1 @@ +1002 diff --git a/xmlsecurity/test_docs/CAs/Root_5/openssl.cfg b/xmlsecurity/test_docs/CAs/Root_5/openssl.cfg new file mode 100644 index 0000000000..0ea6df2972 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_5/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Root_5.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Root_6/README.txt b/xmlsecurity/test_docs/CAs/Root_6/README.txt new file mode 100644 index 0000000000..e49615a51c --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_6/README.txt @@ -0,0 +1,5 @@ +To provide the CRL via HTTP run + +java -jar ../../tools/httpserv/dist/httpserv.jar -a 8901 + + diff --git a/xmlsecurity/test_docs/CAs/Root_6/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Root_6/demoCA/cacert.pem new file mode 100644 index 0000000000..5a7fc185b4 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_6/demoCA/cacert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDBDCCAm2gAwIBAgIJANhqTyT5yZQnMA0GCSqGSIb3DQEBBQUAMF8xCzAJBgNV +BAYTAkRFMRAwDgYDVQQIEwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9y +ZzEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgNjAeFw0wOTEx +MjAxMjI2MDFaFw0zNDExMTQxMjI2MDFaMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgNjCBnzANBgkqhkiG9w0BAQEFAAOBjQAw +gYkCgYEAslt6KM0bikDy8n0lNMeaNQiZk9Pcfsf6Vaasn9A8FABFn1chxV5zOMag +jo6CyZG1CNLhA841RtgiWVMc8BA+pDKzOQAzfgSk4VjXaY8nYgKEmGDKuNvls+kE +OKMkJibh/scNMDUOx8Bnc6S9LyYJAhZFrxm/lgmoIo7QMcdseIsCAwEAAaOBxzCB +xDAdBgNVHQ4EFgQUrCVem7W6TY69d7Kd2eKErnoxj/IwgZEGA1UdIwSBiTCBhoAU +rCVem7W6TY69d7Kd2eKErnoxj/KhY6RhMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgNoIJANhqTyT5yZQnMA8GA1UdEwEB/wQF +MAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAU6Sjyeo650mhSGK8JJBhDroVJgAryVF4 +wXEKWxK0yuO0TVZJxUWeHOESpegBW1eP5m9Pz0IHnxj6MsGBYq7SZU84awt4HJto +6O1ARZYfT9r+qTts33I/VVQVTJbvETF1vGsuAZfTTDhAJDqS2oueiPDSinzQxNMy +16L4Rajm8LE= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_6/demoCA/crl/DO_NOT_INSTALL_THIS_CRL b/xmlsecurity/test_docs/CAs/Root_6/demoCA/crl/DO_NOT_INSTALL_THIS_CRL new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_6/demoCA/crl/DO_NOT_INSTALL_THIS_CRL diff --git a/xmlsecurity/test_docs/CAs/Root_6/demoCA/crl/Root_6.crl b/xmlsecurity/test_docs/CAs/Root_6/demoCA/crl/Root_6.crl Binary files differnew file mode 100644 index 0000000000..df6dcb21ee --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_6/demoCA/crl/Root_6.crl diff --git a/xmlsecurity/test_docs/CAs/Root_6/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Root_6/demoCA/crlnumber new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_6/demoCA/crlnumber @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Root_6/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Root_6/demoCA/index.txt new file mode 100644 index 0000000000..7f0df0d959 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_6/demoCA/index.txt @@ -0,0 +1 @@ +V 341114122807Z 1001 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 1 Root 6 diff --git a/xmlsecurity/test_docs/CAs/Root_6/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Root_6/demoCA/index.txt.attr new file mode 100644 index 0000000000..8f7e63a347 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_6/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Root_6/demoCA/newcerts/1001.pem b/xmlsecurity/test_docs/CAs/Root_6/demoCA/newcerts/1001.pem new file mode 100644 index 0000000000..0490b88cd7 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_6/demoCA/newcerts/1001.pem @@ -0,0 +1,66 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4097 (0x1001) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 6 + Validity + Not Before: Nov 20 12:28:07 2009 GMT + Not After : Nov 14 12:28:07 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 6 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:c4:d9:ab:27:06:66:41:0e:36:ff:d4:b1:d0:8c: + f7:b4:25:55:cd:fd:fa:a4:5a:e6:4f:d0:05:dc:a3: + e5:bd:8d:53:77:d1:ea:95:5a:52:81:c8:b6:36:a0: + 5f:3a:e1:85:1e:8a:48:91:7d:29:78:ff:ea:c5:e3: + ad:c4:27:d5:b7:8f:59:20:26:d4:45:87:6a:56:db: + ac:f5:f8:0a:88:82:9e:c2:00:06:fc:98:8a:fe:35: + c3:02:a1:67:08:06:42:e3:88:48:e0:8f:33:ff:f8: + a4:87:1a:3a:d9:54:0e:1c:09:3e:a0:f0:70:cd:b5: + b0:b2:7e:07:73:ad:20:64:69 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 89:8C:D7:71:EB:67:78:4E:D6:01:35:B2:AC:A1:B4:88:43:CE:70:A7 + X509v3 Authority Key Identifier: + keyid:AC:25:5E:9B:B5:BA:4D:8E:BD:77:B2:9D:D9:E2:84:AE:7A:31:8F:F2 + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 6 + serial:D8:6A:4F:24:F9:C9:94:27 + + X509v3 CRL Distribution Points: + URI:http://localhost:8901/demoCA/crl/Root_6.crl + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 55:5b:3b:6b:8a:d0:1b:d8:19:d9:96:85:4d:b4:a0:98:b1:bd: + 9f:0b:62:21:92:8b:4e:d3:d0:1b:91:3d:e3:f5:bd:ce:16:57: + fc:b7:84:15:51:fd:98:ab:32:59:28:0b:44:57:49:ec:ac:11: + 67:26:7a:a3:c5:b8:9d:2a:de:b6:7c:76:0a:e9:18:9f:98:87: + e8:80:c8:72:99:56:74:ab:73:1b:f4:e7:b9:b1:3a:f3:7b:0d: + 2f:5d:82:6c:d1:99:9f:23:be:23:fb:4c:0e:15:5e:f5:9f:90: + 88:d7:51:3a:6a:7a:f0:54:a5:c4:89:a5:0d:0a:4e:94:59:64: + 59:54 +-----BEGIN CERTIFICATE----- +MIIDRjCCAq+gAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA2MB4XDTA5MTEyMDEyMjgw +N1oXDTM0MTExNDEyMjgwN1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA2MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDE2asnBmZBDjb/1LHQjPe0JVXN/fqkWuZP0AXco+W9jVN30eqVWlKB +yLY2oF864YUeikiRfSl4/+rF463EJ9W3j1kgJtRFh2pW26z1+AqIgp7CAAb8mIr+ +NcMCoWcIBkLjiEjgjzP/+KSHGjrZVA4cCT6g8HDNtbCyfgdzrSBkaQIDAQABo4IB +BjCCAQIwHQYDVR0OBBYEFImM13HrZ3hO1gE1sqyhtIhDznCnMIGRBgNVHSMEgYkw +gYaAFKwlXpu1uk2OvXeyndnihK56MY/yoWOkYTBfMQswCQYDVQQGEwJERTEQMA4G +A1UECBMHSGFtYnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsT +C0RldmVsb3BtZW50MQ8wDQYDVQQDEwZSb290IDaCCQDYak8k+cmUJzA8BgNVHR8E +NTAzMDGgL6AthitodHRwOi8vbG9jYWxob3N0Ojg5MDEvZGVtb0NBL2NybC9Sb290 +XzYuY3JsMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAVVs7a4rQ +G9gZ2ZaFTbSgmLG9nwtiIZKLTtPQG5E94/W9zhZX/LeEFVH9mKsyWSgLRFdJ7KwR +ZyZ6o8W4nSretnx2CukYn5iH6IDIcplWdKtzG/TnubE683sNL12CbNGZnyO+I/tM +DhVe9Z+QiNdROmp68FSlxImlDQpOlFlkWVQ= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_6/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Root_6/demoCA/private/cakey.pem new file mode 100644 index 0000000000..166be01665 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_6/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,BADC417CBCEF5888 + +5vIfuyyd2rgqSPUElPa2YM8on+FeoYuAIB+mfVHy0nSGisUKjmQQACaeTVD+aO6S +UFBz3W/RJXCj/8x5+ZYa8Rj44DeSwlDrxSy5VBrWegOzujfGPqrzwCL/ASKGPPFN +RwK0i0niJsj6+oQOGgP6AIb08reX1tkT0GItwQMjIQAFETcDP8m1sA1kFpLhvBCF +dHyw0lfnh+NZ9nnpAdpVXwt8teccLUyEHARNscebg8vqjc2gRxi3KpT3pURg0dUc +eaGH8DIB5CuAYW2Mo1LLRQ0uvkFgSl56WcolYiRTy2KUMW7Gz7oBA5Qyb9lz25yV +9djt4Hrs9cI1p1TGmvSklGPKJUaTf0Yrf0XRkS6xknFVX4zzkbD4vYFelITSxeMT +pPVbjLSWiIo+mqBuW6i+LUNMt45b1RWM96pomrPRrGne4saJOkhVXTvv/pR4KB+S +J2iwlEDNOwzkxeqSB7lJuzIce/iUqERAzlXe8e0VVgy0P0UfOIViLWS98cuqR86H +P1rMYtWilAkLKBUYo+lS7f/3YD8E3V10XdBmYJFvmpHPXM2SP5HQZXtoNCXJNcvB +aAlb3c7InxfqLLn+kH6WgPzXXcXO7cxlZ3cXBbJf3IhRT3aBEnAH+s+DDCi0RCII +UiLOnrgfOEZuNyRhGin9R7WFRtnGYJjHTP54FMOY0f0Rj7ElT+xymeAZE8wyXKfi +MWDgswTYYkcC7uPJAJ8HnLtFixr9aEriug7yemGyr686oX8gLPdwrYwPYJBt7Q+b +0nf22SoMqMNWSCWcr89sc1AIb0ebX+FxtsN6j45ztEjZGjXYkk2iXQ== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Root_6/demoCA/serial b/xmlsecurity/test_docs/CAs/Root_6/demoCA/serial new file mode 100644 index 0000000000..7d802a3e71 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_6/demoCA/serial @@ -0,0 +1 @@ +1002 diff --git a/xmlsecurity/test_docs/CAs/Root_6/openssl.cfg b/xmlsecurity/test_docs/CAs/Root_6/openssl.cfg new file mode 100644 index 0000000000..f49c110901 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_6/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Root_6.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Root_7/README.txt b/xmlsecurity/test_docs/CAs/Root_7/README.txt new file mode 100644 index 0000000000..056f1b1339 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_7/README.txt @@ -0,0 +1,10 @@ +Revoked certificates: + +- Sub CA 2 Root 7 + + +To provide the CRL via HTTP run + +java -jar ../../tools/httpserv/dist/httpserv.jar -a 8901 + + diff --git a/xmlsecurity/test_docs/CAs/Root_7/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Root_7/demoCA/cacert.pem new file mode 100644 index 0000000000..01761f55bf --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_7/demoCA/cacert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDBDCCAm2gAwIBAgIJANXmY18YCYKJMA0GCSqGSIb3DQEBBQUAMF8xCzAJBgNV +BAYTAkRFMRAwDgYDVQQIEwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9y +ZzEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgNzAeFw0wOTEx +MjAxMzA0NDhaFw0zNDExMTQxMzA0NDhaMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgNzCBnzANBgkqhkiG9w0BAQEFAAOBjQAw +gYkCgYEAvG//bRySIKOz1hmmH6qx02wtf2ZO2skK/wxPnTAd+LLuH2upOfGkaFCi +hd1zsIshs9/TjtLNa4nplkYSvZlYBsbpIuNQZrEedbvLYV/zNdsnLfht+aX3yMuk +q1dh2BI0LdwXiyMyPwATJwQ96AXq/a+cZi1ZRBToCztZArJK/xMCAwEAAaOBxzCB +xDAdBgNVHQ4EFgQUgMb4C198SeSG/ciSxoBw2cBve94wgZEGA1UdIwSBiTCBhoAU +gMb4C198SeSG/ciSxoBw2cBve96hY6RhMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgN4IJANXmY18YCYKJMA8GA1UdEwEB/wQF +MAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAg15QATKSYmz+XGtnBLDnWu2Gk59nglH4 +gG3p1xiVVgOyQVGsvNr+3ETPTTcf6x+ap1+AHE9SJJ0/WQSuUHtOv6y/prp4MWbw +/QBL2WHS7adTFWxOJ/VWpb8GhTtJdG9PKYeSmVAtC1qzdI1zsjPYvHO3UJnokDkB +fY7kpaTJprg= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_7/demoCA/crl/DO_NOT_INSTALL_THIS_CRL b/xmlsecurity/test_docs/CAs/Root_7/demoCA/crl/DO_NOT_INSTALL_THIS_CRL new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_7/demoCA/crl/DO_NOT_INSTALL_THIS_CRL diff --git a/xmlsecurity/test_docs/CAs/Root_7/demoCA/crl/Root_7.crl b/xmlsecurity/test_docs/CAs/Root_7/demoCA/crl/Root_7.crl Binary files differnew file mode 100644 index 0000000000..0eefbda680 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_7/demoCA/crl/Root_7.crl diff --git a/xmlsecurity/test_docs/CAs/Root_7/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Root_7/demoCA/crlnumber new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_7/demoCA/crlnumber @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Root_7/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Root_7/demoCA/index.txt new file mode 100644 index 0000000000..24c3538724 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_7/demoCA/index.txt @@ -0,0 +1,2 @@ +V 341114130753Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 1 Root 7 +R 341114133506Z 091120133621Z,keyCompromise 1001 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 2 Root 7 diff --git a/xmlsecurity/test_docs/CAs/Root_7/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Root_7/demoCA/index.txt.attr new file mode 100644 index 0000000000..8f7e63a347 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_7/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Root_7/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Root_7/demoCA/newcerts/1000.pem new file mode 100644 index 0000000000..2dda8f2b28 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_7/demoCA/newcerts/1000.pem @@ -0,0 +1,66 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 7 + Validity + Not Before: Nov 20 13:07:53 2009 GMT + Not After : Nov 14 13:07:53 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 7 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:b0:ae:6d:0a:21:ae:8a:92:b1:16:25:d3:08:cb: + ac:b7:4c:53:6d:4b:b3:12:82:40:54:c9:44:28:fc: + 4e:10:e6:65:40:de:70:5d:8b:ab:1f:5c:77:03:43: + 3d:3a:3d:9e:f7:37:66:9a:33:68:a0:cf:ad:8f:f4: + fb:9c:a3:87:57:5d:ec:d6:55:5a:18:b5:e1:2b:d2: + c4:10:fe:f0:01:a5:da:29:ee:c4:af:15:c9:8c:dc: + 7c:45:84:bd:e5:5b:09:1f:16:1d:11:e7:61:e6:22: + e7:1f:c8:86:bf:a1:da:cb:fe:6b:7e:c0:6e:aa:7f: + 97:84:e8:8f:81:69:f1:26:87 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 54:64:15:7E:93:8A:19:C8:F9:B7:EF:60:A0:DF:5C:C8:15:56:C0:EE + X509v3 Authority Key Identifier: + keyid:80:C6:F8:0B:5F:7C:49:E4:86:FD:C8:92:C6:80:70:D9:C0:6F:7B:DE + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 7 + serial:D5:E6:63:5F:18:09:82:89 + + X509v3 CRL Distribution Points: + URI:http://localhost:8901/demoCA/crl/Root_7.crl + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 1a:bc:5a:4b:9a:d5:e8:c0:35:c2:61:0a:58:7d:33:e2:87:01: + 61:83:80:42:8d:1a:7e:b1:9a:58:d5:01:fd:e7:ae:5c:c8:65: + fb:9e:1d:bf:49:ba:ed:40:f4:05:7c:3b:2d:db:0e:53:d0:05: + a0:bd:15:87:c4:37:22:0b:a0:04:a3:ad:cb:57:b2:00:97:ee: + 8f:89:91:8e:7d:0b:e2:27:96:6e:0f:ab:73:33:59:fa:9f:37: + f2:77:79:99:af:72:ad:f9:49:05:ed:55:08:31:eb:97:0f:99: + 6e:9c:a3:df:f0:52:1a:14:4e:78:25:0c:8b:02:cb:56:e9:4d: + f5:9f +-----BEGIN CERTIFICATE----- +MIIDRjCCAq+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA3MB4XDTA5MTEyMDEzMDc1 +M1oXDTM0MTExNDEzMDc1M1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA3MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQCwrm0KIa6KkrEWJdMIy6y3TFNtS7MSgkBUyUQo/E4Q5mVA3nBdi6sf +XHcDQz06PZ73N2aaM2igz62P9Puco4dXXezWVVoYteEr0sQQ/vABpdop7sSvFcmM +3HxFhL3lWwkfFh0R52HmIucfyIa/odrL/mt+wG6qf5eE6I+BafEmhwIDAQABo4IB +BjCCAQIwHQYDVR0OBBYEFFRkFX6TihnI+bfvYKDfXMgVVsDuMIGRBgNVHSMEgYkw +gYaAFIDG+AtffEnkhv3IksaAcNnAb3veoWOkYTBfMQswCQYDVQQGEwJERTEQMA4G +A1UECBMHSGFtYnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsT +C0RldmVsb3BtZW50MQ8wDQYDVQQDEwZSb290IDeCCQDV5mNfGAmCiTA8BgNVHR8E +NTAzMDGgL6AthitodHRwOi8vbG9jYWxob3N0Ojg5MDEvZGVtb0NBL2NybC9Sb290 +XzcuY3JsMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAGrxaS5rV +6MA1wmEKWH0z4ocBYYOAQo0afrGaWNUB/eeuXMhl+54dv0m67UD0BXw7LdsOU9AF +oL0Vh8Q3IgugBKOty1eyAJfuj4mRjn0L4ieWbg+rczNZ+p838nd5ma9yrflJBe1V +CDHrlw+Zbpyj3/BSGhROeCUMiwLLVulN9Z8= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_7/demoCA/newcerts/1001.pem b/xmlsecurity/test_docs/CAs/Root_7/demoCA/newcerts/1001.pem new file mode 100644 index 0000000000..0d2a0f02a3 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_7/demoCA/newcerts/1001.pem @@ -0,0 +1,66 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4097 (0x1001) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 7 + Validity + Not Before: Nov 20 13:35:06 2009 GMT + Not After : Nov 14 13:35:06 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 2 Root 7 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:f9:3f:5e:76:52:9a:ce:5d:98:b0:00:d8:e0:65: + e7:78:11:4c:7b:c7:e2:d3:44:bf:8e:60:42:69:3e: + 75:67:65:24:ab:f7:07:d8:9d:be:0f:23:b5:c1:26: + 00:6b:c3:22:84:72:a9:96:dc:5f:63:fc:f5:e0:e3: + cc:da:0c:74:e9:31:51:91:89:27:8f:e5:17:41:6e: + 3d:5e:2a:13:cd:08:f7:f3:61:34:a1:f7:79:c6:bd: + 5d:2c:34:01:ea:5a:8c:48:97:36:d6:57:e0:80:03: + 2e:7a:03:83:4c:bd:b4:af:a2:fd:d7:4b:1a:f7:ab: + 9f:5a:22:2b:d1:25:73:dd:6f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 3B:50:26:45:6C:E2:FE:28:B1:71:0A:A8:95:2D:78:63:8E:2C:48:92 + X509v3 Authority Key Identifier: + keyid:80:C6:F8:0B:5F:7C:49:E4:86:FD:C8:92:C6:80:70:D9:C0:6F:7B:DE + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 7 + serial:D5:E6:63:5F:18:09:82:89 + + X509v3 CRL Distribution Points: + URI:http://localhost:8901/demoCA/crl/Root_7.crl + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 5f:b4:70:11:4f:d9:df:6a:6a:5a:4a:97:fe:8b:5d:9e:46:84: + e2:27:67:41:7c:a9:2e:9d:77:cc:e4:8c:d6:16:3c:39:7d:51: + 29:60:80:32:4f:a1:d0:b4:7f:2a:e5:60:f4:b8:d3:3b:94:f8: + a5:fb:15:99:cf:a9:c5:a7:59:c1:11:89:67:11:9c:ff:a9:ac: + dd:ca:a9:92:a8:60:26:c3:ab:74:41:86:b9:4d:1e:4a:c5:de: + 63:e6:da:2a:36:39:7b:6c:66:f3:20:57:d1:f1:36:4b:69:c5: + 04:a3:1f:cf:de:0c:10:d0:3f:07:e2:8e:0f:cd:41:26:c9:2e: + e9:1b +-----BEGIN CERTIFICATE----- +MIIDRjCCAq+gAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA3MB4XDTA5MTEyMDEzMzUw +NloXDTM0MTExNDEzMzUwNlowaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDIgUm9vdCA3MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQD5P152UprOXZiwANjgZed4EUx7x+LTRL+OYEJpPnVnZSSr9wfYnb4P +I7XBJgBrwyKEcqmW3F9j/PXg48zaDHTpMVGRiSeP5RdBbj1eKhPNCPfzYTSh93nG +vV0sNAHqWoxIlzbWV+CAAy56A4NMvbSvov3XSxr3q59aIivRJXPdbwIDAQABo4IB +BjCCAQIwHQYDVR0OBBYEFDtQJkVs4v4osXEKqJUteGOOLEiSMIGRBgNVHSMEgYkw +gYaAFIDG+AtffEnkhv3IksaAcNnAb3veoWOkYTBfMQswCQYDVQQGEwJERTEQMA4G +A1UECBMHSGFtYnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsT +C0RldmVsb3BtZW50MQ8wDQYDVQQDEwZSb290IDeCCQDV5mNfGAmCiTA8BgNVHR8E +NTAzMDGgL6AthitodHRwOi8vbG9jYWxob3N0Ojg5MDEvZGVtb0NBL2NybC9Sb290 +XzcuY3JsMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAX7RwEU/Z +32pqWkqX/otdnkaE4idnQXypLp13zOSM1hY8OX1RKWCAMk+h0LR/KuVg9LjTO5T4 +pfsVmc+pxadZwRGJZxGc/6ms3cqpkqhgJsOrdEGGuU0eSsXeY+baKjY5e2xm8yBX +0fE2S2nFBKMfz94MENA/B+KOD81BJsku6Rs= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_7/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Root_7/demoCA/private/cakey.pem new file mode 100644 index 0000000000..147ca4e9b6 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_7/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,B17A06040862AC63 + +9VJMswLGoelYtmpO17/f34Lb7j1I2vaK+RUg7fH09M6rQKurA2SmpsO7kJo7lMUb +lwXEC8+JC5b3OoUcPeHLkZ5e9bB+flMJQq+bkzWs4NWYI17gRs2Tc74xm04XRTsO +OYU+H7uOyRMAuS86hkQF13H3hCHcZkg8RZcvqfDXhsY8S7iyp0gErQv8IDmbIije +R7go3NdZXCmkuINKhhABFYnPxnEpaHxhIMNKykbSn+jby02LX57X/u4JDGfkzjCH +wyJMi9PiO7VbXvi8IPYnFz0IaCMVr5cltTh47/KiqACeAADQ6ETekrX9r7lngkRz +sqFuyqEtdi02ujElsGIaDCImQ5KbD2u2IQ3FX2b6Jwmd/uDmqQQwtEfarEoUxich +chCEUBGAiqRxLcrnRzjT+Reqgx7qGNurjP78kmKeD91hDm3tEHeWtecy4iA3C8z0 +aMZFOZLx1r7kf5/YaRMREcLPmreEWgFmkIMN004GdIvOwlsUjmAM7UMle+cef17v +h1hxbFsznzYLBk0zOYjmsTpI3dQHtxSUVsyUWXXVJ0Y4YhJSjMHlMOOCanGYOpGS +vipUNzLx4aIWfMmQdJePQM4uxO2FNwTc1IGyRpoOhj6vxroICuGK3WkxqZsN3VwR +hwNol0cNMNHbVacKvhh5PQJcmWiqmLEXaQD8VWgCNQVa0otS59vj+SeyW4ZvULBM +Od/9FhFfEBHQDxNSL+c6B/dXFIO1oY159ErdElAn+NPRtQcHAsnu8HknKLhry1NP +b4d+KZcTZAq9q97ltRQf9/hXBpA3ophMtbBFnnnh5WJuMMdDMNgGsg== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Root_7/demoCA/serial b/xmlsecurity/test_docs/CAs/Root_7/demoCA/serial new file mode 100644 index 0000000000..7d802a3e71 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_7/demoCA/serial @@ -0,0 +1 @@ +1002 diff --git a/xmlsecurity/test_docs/CAs/Root_7/openssl.cfg b/xmlsecurity/test_docs/CAs/Root_7/openssl.cfg new file mode 100644 index 0000000000..f2615bef4f --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_7/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Root_7.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Root_8/README.txt b/xmlsecurity/test_docs/CAs/Root_8/README.txt new file mode 100644 index 0000000000..d749d8ebcf --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_8/README.txt @@ -0,0 +1,9 @@ +Revoked certificates: + +- Sub CA 2 Root 8 + + +Start the OCSP responder: +openssl ocsp -index demoCA/index.txt -port 8888 -rsigner demoCA/cacert.pem -rkey demoCA/private/cakey.pem -CA demoCA/cacert.pem -text + + diff --git a/xmlsecurity/test_docs/CAs/Root_8/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Root_8/demoCA/cacert.pem new file mode 100644 index 0000000000..ef431ec952 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_8/demoCA/cacert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDBDCCAm2gAwIBAgIJALJH3moqTIMZMA0GCSqGSIb3DQEBBQUAMF8xCzAJBgNV +BAYTAkRFMRAwDgYDVQQIEwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9y +ZzEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgODAeFw0wOTEx +MjAxNTI4NTZaFw0zNDExMTQxNTI4NTZaMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgODCBnzANBgkqhkiG9w0BAQEFAAOBjQAw +gYkCgYEAmR4R07C/I8zEPsAEQdc/nzH74hLjEwImtiWKL8nVc70fwquIRzWLaavm +DaQE3g/ha00d2hepB2dUiR1nV2GhMYdV64eq1utEPU+tTIYpx163axOGLYLWwKc3 +cBaR2mCqZmAkS+WABHkCX9hsBn+Ju/XNxLDVcpBohVrx882+3kMCAwEAAaOBxzCB +xDAdBgNVHQ4EFgQU1mZ2yQX/qVCIlmDd+8cwGHJnQRkwgZEGA1UdIwSBiTCBhoAU +1mZ2yQX/qVCIlmDd+8cwGHJnQRmhY6RhMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgOIIJALJH3moqTIMZMA8GA1UdEwEB/wQF +MAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAfZylT15q6Dnpvf9jWoCovzvUoBqAwL1Z +UDEikhCpajYsrfXI3MRvKYkTvt18lgg2Y09gJ2vhfLBCaDp+ELUq0Vc5hIbblGGO +EA4vBuH5Yfho3AK3gKAtk7Rc9l/qP2rBPb1JVw79pRaz95IkYGeOp35pVDQfBN+i +jji5JSyOeYQ= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_8/demoCA/crl/DO_NOT_INSTALL_THIS_CRL b/xmlsecurity/test_docs/CAs/Root_8/demoCA/crl/DO_NOT_INSTALL_THIS_CRL new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_8/demoCA/crl/DO_NOT_INSTALL_THIS_CRL diff --git a/xmlsecurity/test_docs/CAs/Root_8/demoCA/crl/Root_8.crl b/xmlsecurity/test_docs/CAs/Root_8/demoCA/crl/Root_8.crl Binary files differnew file mode 100644 index 0000000000..8f91a1949a --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_8/demoCA/crl/Root_8.crl diff --git a/xmlsecurity/test_docs/CAs/Root_8/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Root_8/demoCA/crlnumber new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_8/demoCA/crlnumber @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Root_8/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Root_8/demoCA/index.txt new file mode 100644 index 0000000000..831cbf1a38 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_8/demoCA/index.txt @@ -0,0 +1,2 @@ +V 341114153321Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 1 Root 8 +R 341114155533Z 091120155655Z,superseded 1001 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 2 Root 8 diff --git a/xmlsecurity/test_docs/CAs/Root_8/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Root_8/demoCA/index.txt.attr new file mode 100644 index 0000000000..8f7e63a347 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_8/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Root_8/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Root_8/demoCA/newcerts/1000.pem new file mode 100644 index 0000000000..b2d1deb759 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_8/demoCA/newcerts/1000.pem @@ -0,0 +1,66 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 8 + Validity + Not Before: Nov 20 15:33:21 2009 GMT + Not After : Nov 14 15:33:21 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 8 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:96:79:01:9f:4f:68:c1:09:0d:44:3a:82:e4:eb: + ad:70:7a:cf:b9:71:e5:fb:e0:c8:0c:21:79:3e:cb: + 78:91:7f:4a:a0:de:3e:37:0f:a1:6b:73:10:12:9b: + 08:c4:96:dc:cb:a8:5b:87:9b:75:24:e4:00:5e:4a: + 6f:4c:13:79:1f:57:13:8c:3e:1b:38:31:e1:77:74: + 52:f9:94:47:36:57:33:bd:de:08:11:a3:01:e1:53: + 1c:bd:7b:39:9c:5e:96:5c:a9:61:6c:cc:2b:90:8d: + 5a:3c:9e:f4:4b:6e:e5:97:64:86:f3:8e:e8:72:20: + 5d:0d:50:bf:e9:cf:be:d4:13 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + EF:BD:C8:8E:78:79:F9:76:4B:11:59:B6:C3:32:10:07:C0:BC:E3:8A + X509v3 Authority Key Identifier: + keyid:D6:66:76:C9:05:FF:A9:50:88:96:60:DD:FB:C7:30:18:72:67:41:19 + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 8 + serial:B2:47:DE:6A:2A:4C:83:19 + + Authority Information Access: + OCSP - URI:http://localhost:8888 + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 4c:95:44:3b:57:08:ec:01:ec:f9:3e:7c:89:1c:30:b1:4e:26: + 32:b6:57:fa:25:bc:ed:eb:d4:a2:1c:67:ee:b9:8b:d0:4c:57: + 8a:0e:db:a0:9d:92:e7:de:c6:73:01:e7:de:61:1b:b5:0e:d0: + c5:c1:a7:a6:ab:e0:c6:0b:51:dd:e5:a2:32:1f:c6:52:ea:d3: + 03:68:3a:f5:92:bd:8b:b8:03:bb:50:70:63:cc:ec:ed:3c:11: + 76:ca:ac:72:47:ad:99:6b:8e:07:9e:38:f2:63:e1:ba:d4:df: + a9:73:54:1d:74:89:94:01:2e:68:dd:97:e7:53:f9:cf:b6:7d: + fc:87 +-----BEGIN CERTIFICATE----- +MIIDOTCCAqKgAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA4MB4XDTA5MTEyMDE1MzMy +MVoXDTM0MTExNDE1MzMyMVowaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA4MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQCWeQGfT2jBCQ1EOoLk661wes+5ceX74MgMIXk+y3iRf0qg3j43D6Fr +cxASmwjEltzLqFuHm3Uk5ABeSm9ME3kfVxOMPhs4MeF3dFL5lEc2VzO93ggRowHh +Uxy9ezmcXpZcqWFszCuQjVo8nvRLbuWXZIbzjuhyIF0NUL/pz77UEwIDAQABo4H6 +MIH3MB0GA1UdDgQWBBTvvciOeHn5dksRWbbDMhAHwLzjijCBkQYDVR0jBIGJMIGG +gBTWZnbJBf+pUIiWYN37xzAYcmdBGaFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA4ggkAskfeaipMgxkwMQYIKwYBBQUH +AQEEJTAjMCEGCCsGAQUFBzABhhVodHRwOi8vbG9jYWxob3N0Ojg4ODgwDwYDVR0T +AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBMlUQ7VwjsAez5PnyJHDCxTiYy +tlf6Jbzt69SiHGfuuYvQTFeKDtugnZLn3sZzAefeYRu1DtDFwaemq+DGC1Hd5aIy +H8ZS6tMDaDr1kr2LuAO7UHBjzOztPBF2yqxyR62Za44HnjjyY+G61N+pc1QddImU +AS5o3ZfnU/nPtn38hw== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_8/demoCA/newcerts/1001.pem b/xmlsecurity/test_docs/CAs/Root_8/demoCA/newcerts/1001.pem new file mode 100644 index 0000000000..26368962e8 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_8/demoCA/newcerts/1001.pem @@ -0,0 +1,66 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4097 (0x1001) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 8 + Validity + Not Before: Nov 20 15:55:33 2009 GMT + Not After : Nov 14 15:55:33 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 2 Root 8 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:e9:91:38:d8:c1:36:e5:c1:d0:32:e8:ae:02:11: + 97:e5:c5:07:8f:5b:46:3a:3c:d9:49:5e:9a:4b:51: + 4c:b7:7d:e9:d1:4f:a7:15:8c:c6:10:f6:fa:5f:a9: + 0b:1b:bc:de:56:f5:ad:a3:a0:40:f1:75:10:58:74: + 37:f9:b7:9f:76:ca:46:96:4c:1a:81:f4:a2:ce:88: + 8b:9e:00:6d:42:b3:d6:68:d1:67:d6:9f:b8:9c:3f: + 43:c7:36:bf:41:88:1b:e8:74:26:a0:51:5c:e2:ee: + 6d:9d:73:bb:0d:36:e1:5c:68:9f:21:3b:b2:aa:ed: + 39:1d:ae:fc:b4:ca:38:c2:fb + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 1B:AB:6B:0F:42:91:DC:1E:D4:7A:95:87:30:2D:CC:11:4F:35:B7:73 + X509v3 Authority Key Identifier: + keyid:D6:66:76:C9:05:FF:A9:50:88:96:60:DD:FB:C7:30:18:72:67:41:19 + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 8 + serial:B2:47:DE:6A:2A:4C:83:19 + + Authority Information Access: + OCSP - URI:http://localhost:8888 + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 89:f8:8d:a8:e5:0b:2a:fb:f3:6a:80:2c:26:a1:a7:36:7e:a0: + c5:61:65:9d:7e:d6:47:60:b4:f6:72:e9:6e:2c:d9:f8:7f:c8: + 7a:5d:75:98:ad:88:de:e7:1b:44:a3:96:37:84:c0:b3:20:98: + 3b:b5:f6:ee:70:9c:04:7a:6c:88:05:75:7f:12:cf:b9:76:e8: + c0:17:0c:5e:eb:10:38:1e:54:41:58:56:f6:3c:ec:07:a5:c0: + 74:24:34:af:b3:c7:b2:58:85:47:0f:6c:e4:a0:9f:c8:7b:5c: + 95:77:17:e5:ad:eb:c3:86:44:f7:81:ef:cb:58:12:1a:6a:c7: + 19:95 +-----BEGIN CERTIFICATE----- +MIIDOTCCAqKgAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA4MB4XDTA5MTEyMDE1NTUz +M1oXDTM0MTExNDE1NTUzM1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDIgUm9vdCA4MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDpkTjYwTblwdAy6K4CEZflxQePW0Y6PNlJXppLUUy3fenRT6cVjMYQ +9vpfqQsbvN5W9a2joEDxdRBYdDf5t592ykaWTBqB9KLOiIueAG1Cs9Zo0WfWn7ic +P0PHNr9BiBvodCagUVzi7m2dc7sNNuFcaJ8hO7Kq7Tkdrvy0yjjC+wIDAQABo4H6 +MIH3MB0GA1UdDgQWBBQbq2sPQpHcHtR6lYcwLcwRTzW3czCBkQYDVR0jBIGJMIGG +gBTWZnbJBf+pUIiWYN37xzAYcmdBGaFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA4ggkAskfeaipMgxkwMQYIKwYBBQUH +AQEEJTAjMCEGCCsGAQUFBzABhhVodHRwOi8vbG9jYWxob3N0Ojg4ODgwDwYDVR0T +AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQCJ+I2o5Qsq+/NqgCwmoac2fqDF +YWWdftZHYLT2culuLNn4f8h6XXWYrYje5xtEo5Y3hMCzIJg7tfbucJwEemyIBXV/ +Es+5dujAFwxe6xA4HlRBWFb2POwHpcB0JDSvs8eyWIVHD2zkoJ/Ie1yVdxflrevD +hkT3ge/LWBIaascZlQ== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_8/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Root_8/demoCA/private/cakey.pem new file mode 100644 index 0000000000..dd11db4437 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_8/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,1DE6DE80057C280E + +1pXaFFR4KgVEWQzq73tQrfEkLZn7J0G0fxp1ZZYKOVdL3g/S4su2cXn5zfkSypjG +sTPnj9YuHzZiW1sB5M+U84b0aCSuh4+HK1Y+K6Us99psx/VaDq36uEBJZQviJ4zb +uF7ZT6NRGWMs3pIkFEHqi9TQ6mmeRgHMgkiI/mpM/26Y00dLpXdxBIGOCpKIPXwp +02mx/o9CHqI7ASuXV6ZAhawEmvFKKRNCKsKOaSs0CylGOT5nAaqWRp/IVMrm46wr +o7cErGgCZCPzQ5Ndx4553oSeWTjnm4iTS5UKg0nwPgS6sVhsr3zrTxIhS9zzcW2G +ycREX312K7q0zxtCxdNZxGeSfowRRy54JRoLf+O5yoNTRXYFjLxXGHgCTQRWgpIh +ggOmgUyIeNQXts4Qf6ddUtEcfGzMowCAJWTakXpOBoWj42mF85lDlcAAn8V1L90Q +MDF31HzrDAe3po4g+dNA6qdZrpSpnDDVp0oPsr3ooz1dLlwa8LWpPpq5PRgDWeQF +hcYrywI5tfUJyXv0xkEv+BIGKjGofWHGNtZWazBunhAVgWG/GQbzWxdSBS5w2waE +2Zo65PBqfLgRdnO6HYl15Pc5wm3gEQJo5VYgl7HmRpEt7lQrcnReqLWnsuHmqZ/H +vaEmGnSfXauVTvBVRXnrpznM/ROC9n2FR50lNIO1nAtMM7a0S0PIKgB+uNwAtsAR +Y4dY4YCS/io8wCL+DNBPtdvuY85/y5lnURpj9ojWO916WZsK/EFPJIQFuVwhal2C +Q9NVu8PXPDiBAHTVGZz8HoG32eYYUtqzeIY4Xo5ybUlnsNGlncWSqw== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Root_8/demoCA/serial b/xmlsecurity/test_docs/CAs/Root_8/demoCA/serial new file mode 100644 index 0000000000..7d802a3e71 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_8/demoCA/serial @@ -0,0 +1 @@ +1002 diff --git a/xmlsecurity/test_docs/CAs/Root_8/openssl.cfg b/xmlsecurity/test_docs/CAs/Root_8/openssl.cfg new file mode 100644 index 0000000000..077e13b2b5 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_8/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Root_7.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Root_9/DO_NOT_INSTALL_THIS_ROOT_CERT.txt b/xmlsecurity/test_docs/CAs/Root_9/DO_NOT_INSTALL_THIS_ROOT_CERT.txt new file mode 100644 index 0000000000..ee3d2b339e --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_9/DO_NOT_INSTALL_THIS_ROOT_CERT.txt @@ -0,0 +1 @@ +!!!DO NOT INSTALL THIS ROOT CERTIFICATE!!! diff --git a/xmlsecurity/test_docs/CAs/Root_9/demoCA/DO_NO_INSTALL_THIS_ROOT_CERTIFICATE b/xmlsecurity/test_docs/CAs/Root_9/demoCA/DO_NO_INSTALL_THIS_ROOT_CERTIFICATE new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_9/demoCA/DO_NO_INSTALL_THIS_ROOT_CERTIFICATE diff --git a/xmlsecurity/test_docs/CAs/Root_9/demoCA/Root_9.crt b/xmlsecurity/test_docs/CAs/Root_9/demoCA/Root_9.crt Binary files differnew file mode 100644 index 0000000000..66e316546e --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_9/demoCA/Root_9.crt diff --git a/xmlsecurity/test_docs/CAs/Root_9/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Root_9/demoCA/cacert.pem new file mode 100644 index 0000000000..ca53f28f7a --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_9/demoCA/cacert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDBDCCAm2gAwIBAgIJAKTbFg1LjNSmMA0GCSqGSIb3DQEBBQUAMF8xCzAJBgNV +BAYTAkRFMRAwDgYDVQQIEwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9y +ZzEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgOTAeFw0wOTEx +MjMxMzUyNDNaFw0zNDExMTcxMzUyNDNaMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgOTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw +gYkCgYEAsOgehurKuYszsH2LFeGyHA9WYmCOMZmQfBFOgS/kO1Hkv6tNrDbshzyc +I/qOlpkosXUbQaaJPYoQmv3eTpfYxM9Dju5GkzOL03Q9J8AGe8RW1urMCfD5fC9g +XmhxAnIbrmDhS4K0lV8ngWwTQjmec9CV8SVBLQerrNtmcY/VvcMCAwEAAaOBxzCB +xDAdBgNVHQ4EFgQUzTNeq3MjUYC4A60SAQvFXo5VymQwgZEGA1UdIwSBiTCBhoAU +zTNeq3MjUYC4A60SAQvFXo5VymShY6RhMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgOYIJAKTbFg1LjNSmMA8GA1UdEwEB/wQF +MAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAqQkfiXNJm8l5v6qQzv6HwcDIgSQBuwkp +bN5FgHdLXaae/UOelXpmLSfrAbizw0Om1xLH/tnSeNY9MCGMGA4ScGU1hdNLUTIU +LK9upl/q+cHQayZL/Hz4Z8sqRNrP+E2m0GY0RMF1getJunfYZZV9VcsfbO3SqgAQ +exqICFDFi8M= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_9/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Root_9/demoCA/crlnumber new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_9/demoCA/crlnumber @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Root_9/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Root_9/demoCA/index.txt new file mode 100644 index 0000000000..c741bbfdac --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_9/demoCA/index.txt @@ -0,0 +1 @@ +V 341117135919Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 1 Root 9 diff --git a/xmlsecurity/test_docs/CAs/Root_9/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Root_9/demoCA/index.txt.attr new file mode 100644 index 0000000000..8f7e63a347 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_9/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Root_9/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Root_9/demoCA/newcerts/1000.pem new file mode 100644 index 0000000000..0b38d4db4c --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_9/demoCA/newcerts/1000.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 9 + Validity + Not Before: Nov 23 13:59:19 2009 GMT + Not After : Nov 17 13:59:19 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 9 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:a9:6d:7f:6a:08:fb:e2:3a:5e:83:3f:ff:58:ba: + 92:a1:79:9d:ce:d2:0c:16:15:f2:7e:b3:e4:45:9c: + 02:32:65:9b:02:90:78:05:95:e4:04:1d:4a:05:bb: + ea:f6:ac:ab:15:74:c2:bc:ee:2a:c1:80:55:3e:93: + 1f:5c:94:eb:cf:cf:8f:15:eb:b8:22:fe:69:61:51: + a9:08:b8:80:bd:48:99:da:85:10:1c:75:97:fd:d3: + c3:c4:0b:dd:eb:01:12:5d:ee:62:62:c3:0c:18:ea: + ed:76:ff:9b:1c:1f:c7:81:f9:9a:cd:e5:25:89:b2: + 13:57:56:f3:27:53:72:76:69 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 7B:D3:57:BF:6A:CB:6C:10:81:91:DA:95:DC:88:4F:A5:D0:DB:D1:46 + X509v3 Authority Key Identifier: + keyid:CD:33:5E:AB:73:23:51:80:B8:03:AD:12:01:0B:C5:5E:8E:55:CA:64 + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 9 + serial:A4:DB:16:0D:4B:8C:D4:A6 + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 17:67:b0:21:da:0d:a1:fe:09:62:d0:cf:1d:c0:c8:bd:d4:22: + dd:75:ec:04:e2:23:ae:ea:8c:15:fa:73:2e:83:f4:16:eb:c1: + e1:87:36:bd:58:d0:64:e0:6e:2c:bc:27:cb:dc:4b:58:01:80: + 48:27:53:bb:75:85:a7:19:b8:e2:c0:1f:9f:a2:18:27:82:3f: + 25:bf:17:d1:34:32:de:c4:81:9d:8a:39:6f:6b:1f:b6:12:61: + 74:78:96:6d:6e:52:23:4a:67:30:78:03:91:b7:89:bf:3c:4a: + 36:e3:95:21:38:35:af:05:55:81:05:25:91:78:ca:2f:5d:79: + d2:05 +-----BEGIN CERTIFICATE----- +MIIDBjCCAm+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA5MB4XDTA5MTEyMzEzNTkx +OVoXDTM0MTExNzEzNTkxOVowaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA5MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQCpbX9qCPviOl6DP/9YupKheZ3O0gwWFfJ+s+RFnAIyZZsCkHgFleQE +HUoFu+r2rKsVdMK87irBgFU+kx9clOvPz48V67gi/mlhUakIuIC9SJnahRAcdZf9 +08PEC93rARJd7mJiwwwY6u12/5scH8eB+ZrN5SWJshNXVvMnU3J2aQIDAQABo4HH +MIHEMB0GA1UdDgQWBBR701e/astsEIGR2pXciE+l0NvRRjCBkQYDVR0jBIGJMIGG +gBTNM16rcyNRgLgDrRIBC8VejlXKZKFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA5ggkApNsWDUuM1KYwDwYDVR0TAQH/ +BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQAXZ7Ah2g2h/gli0M8dwMi91CLddewE +4iOu6owV+nMug/QW68Hhhza9WNBk4G4svCfL3EtYAYBIJ1O7dYWnGbjiwB+fohgn +gj8lvxfRNDLexIGdijlvax+2EmF0eJZtblIjSmcweAORt4m/PEo245UhODWvBVWB +BSWReMovXXnSBQ== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_9/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Root_9/demoCA/private/cakey.pem new file mode 100644 index 0000000000..65149ff650 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_9/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,EEC173CF380C4BEC + +3ZAmsMS1aFKb3EfOncYO+hg0ucK80Y7pHg7GaH2/XZ+b6HmVQrHKuDrIcQNGEY5Z +QTCBeCGhmh7hnemBSrco4HURl/2LlA5CoYyd6CCc79VeUQZRJdLjL2thD4x/QwQs +Vh9uG+nunEAXK2kI2sFAxCScoCXSZmAgQqAANQ3SHyJ14e8BlOVgucfD0afYEDNE +udc86lO8+Lz7HfTvysnKO06pgp30ZFJlnBzSBXkXsTShPWEPg8f+2JRc+A5PbxVM +gz/S/ZrPMg8QyIfwwCGjRKzyRBeXVfquXqrwNqtGI+HXo4QaYYT8zuYUn9XuJsac +ZFn2BoXhI6TCBzyM+yuoXp+Xx5plY2A8QXaiLdKO2usV5xcXaBY3XTczrnOfJh7f +F3B2mbfhr/s4UJaFmnG4eULklFGADRY5tN2bIutsWmuuw17/ZwUSZxsjl+TybqVi +uvfmEqrSgoZ9Qz1vvRngVAAwJPAvQqsBQwkq3WapNeoLqmQeSHq/6z4G5RKPbkMs +t21L4SBUGQMhkZWAnJEtECDGsQpDjjwbDuJzrbVTSBiNvDWWeXJuGdyhzI6b17v7 +CZosIrzE82Oo0C+afWJVek2cB8rIMbgqEL+3Sj7x9c/kGeLx957d+geTSStqjD3z +P574kcEDP9ppEHalg1ygJ6t3SjkTNMWrbuYH+GlY8all7rniMDYUDMECIj3Xrv+Q +x3Yzv07FAooDYBE4pdWtTjpBlmwxa68XaMSDG28jQwTHck30GU/gwrM74CKWsg8y +4eZAaeQKHeUYFGsxWeYfmwr7aD4pG+VYGOmRmdia5PA= +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Root_9/demoCA/serial b/xmlsecurity/test_docs/CAs/Root_9/demoCA/serial new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_9/demoCA/serial @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Root_9/openssl.cfg b/xmlsecurity/test_docs/CAs/Root_9/openssl.cfg new file mode 100644 index 0000000000..f48e3d5a34 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_9/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Root_7.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/cacert.pem new file mode 100644 index 0000000000..be26aa5d8f --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/cacert.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 1 + Validity + Not Before: Nov 18 15:07:13 2009 GMT + Not After : Nov 12 15:07:13 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 1 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:d9:3a:8d:64:95:87:76:76:e8:61:c3:e9:65:f4: + a6:b7:0c:77:0e:4b:10:e8:14:a3:e1:84:69:7c:8e: + 97:d2:7d:01:ad:b2:dc:5c:cd:c6:91:a1:f3:93:7c: + 54:36:64:e3:ca:22:ca:00:cb:c6:91:ab:6b:26:88: + 69:60:9a:61:d7:59:17:db:93:7d:09:36:da:28:cb: + ec:2d:a4:26:bb:1a:42:20:b8:08:b2:0f:b9:77:a6: + 80:71:cf:13:f5:37:a2:90:4d:ab:e8:97:49:d2:80: + 94:8f:b1:9d:5a:b4:9f:de:ff:fa:b6:d6:e0:45:5f: + cc:d4:10:1e:32:46:7b:ba:55 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 37:71:74:81:44:DD:1E:B1:60:96:41:B7:4B:38:C4:B7:79:1B:CF:8A + X509v3 Authority Key Identifier: + keyid:0F:FA:C6:EB:DF:CE:B8:BB:B3:A9:3E:42:A6:BA:EC:D2:93:CA:47:A4 + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 1 + serial:95:B0:05:2B:ED:C2:39:2D + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 18:f6:02:5e:75:04:5f:eb:3b:07:41:85:c0:9e:08:29:58:3d: + b5:6f:c2:aa:24:0d:93:1d:17:fc:be:d6:43:ac:43:d7:4d:a0: + 2c:40:fd:3d:d5:7e:91:46:25:49:62:ba:e9:7f:67:c2:fc:8a: + c3:a0:37:bf:ec:f9:54:bf:61:10:35:dd:5b:bb:da:7c:70:54: + 32:13:b9:ae:7d:ea:a5:7d:aa:55:3e:ef:0a:ef:12:fd:c3:f6: + e5:25:98:97:34:02:64:fd:88:79:b3:e2:f4:fc:ff:e7:d3:98: + f1:d9:d5:18:d9:b4:62:ae:99:88:61:2e:ff:02:6a:13:35:fe: + 37:c7 +-----BEGIN CERTIFICATE----- +MIIDBjCCAm+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCAxMB4XDTA5MTExODE1MDcx +M1oXDTM0MTExMjE1MDcxM1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCAxMIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDZOo1klYd2duhhw+ll9Ka3DHcOSxDoFKPhhGl8jpfSfQGtstxczcaR +ofOTfFQ2ZOPKIsoAy8aRq2smiGlgmmHXWRfbk30JNtooy+wtpCa7GkIguAiyD7l3 +poBxzxP1N6KQTavol0nSgJSPsZ1atJ/e//q21uBFX8zUEB4yRnu6VQIDAQABo4HH +MIHEMB0GA1UdDgQWBBQ3cXSBRN0esWCWQbdLOMS3eRvPijCBkQYDVR0jBIGJMIGG +gBQP+sbr3864u7OpPkKmuuzSk8pHpKFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCAxggkAlbAFK+3COS0wDwYDVR0TAQH/ +BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQAY9gJedQRf6zsHQYXAnggpWD21b8Kq +JA2THRf8vtZDrEPXTaAsQP091X6RRiVJYrrpf2fC/IrDoDe/7PlUv2EQNd1bu9p8 +cFQyE7mufeqlfapVPu8K7xL9w/blJZiXNAJk/Yh5s+L0/P/n05jx2dUY2bRirpmI +YS7/AmoTNf43xw== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/crl/DO_NOT_CREATE_A_CRL b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/crl/DO_NOT_CREATE_A_CRL new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/crl/DO_NOT_CREATE_A_CRL diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/crlnumber new file mode 100644 index 0000000000..83b33d238d --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/crlnumber @@ -0,0 +1 @@ +1000 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/index.txt new file mode 100644 index 0000000000..e2027ce9f4 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/index.txt @@ -0,0 +1 @@ +V 341112152323Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 1 Root 1 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/index.txt.attr new file mode 100644 index 0000000000..8f7e63a347 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/newcerts/1000.pem new file mode 100644 index 0000000000..e7d22dfd0c --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/newcerts/1000.pem @@ -0,0 +1,58 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 1 + Validity + Not Before: Nov 18 15:23:23 2009 GMT + Not After : Nov 12 15:23:23 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 1 Root 1 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:c8:41:66:84:c7:d5:c5:72:8f:a6:98:1b:59:e2: + 33:ca:0d:d2:24:b3:c1:47:db:11:e2:bf:23:da:32: + 68:41:cc:ff:28:fe:9a:39:49:e7:08:f0:22:75:15: + 61:99:9e:99:e5:14:65:71:60:00:0f:58:42:70:78: + 5a:1e:d8:fa:97:92:82:0e:e3:0c:ac:20:dc:b8:e3: + 5e:87:8b:89:e3:a1:c3:87:49:1d:92:a5:fd:7c:77: + 79:ce:1f:fa:9c:5a:17:d9:11:0c:f2:7f:1a:fa:d8: + 32:41:f8:69:80:ae:8a:66:bd:36:c2:21:65:57:08: + be:cf:f0:ec:83:15:98:6d:65 + Exponent: 65537 (0x10001) + X509v3 extensions: + Netscape Comment: + OpenSSL Generated Certificate + X509v3 Subject Key Identifier: + FF:BB:B0:7F:E3:0E:E3:8C:CF:EC:88:49:A9:0E:62:B5:D3:60:12:46 + X509v3 Authority Key Identifier: + keyid:37:71:74:81:44:DD:1E:B1:60:96:41:B7:4B:38:C4:B7:79:1B:CF:8A + + Signature Algorithm: sha1WithRSAEncryption + 33:dd:e8:57:3e:69:1b:a0:4c:83:51:99:dd:73:b0:0c:cb:c7: + c0:ff:12:8b:b6:3b:59:12:b9:f1:20:87:75:f0:71:6e:bc:94: + 47:72:62:ae:93:90:05:e2:ff:63:31:5a:d2:80:a5:4a:7f:57: + e9:f7:4e:3e:be:bd:4c:9e:74:07:19:b0:4d:88:97:af:23:a7: + 5a:23:af:d1:a9:98:9b:55:7e:fa:6b:18:77:03:c4:aa:49:bc: + b6:3d:66:3e:8d:0a:80:5f:ac:b9:58:fb:11:ef:60:db:ad:a8: + 79:41:83:1a:6a:61:87:99:64:2d:e4:6a:bb:c0:30:00:dd:69: + e5:92 +-----BEGIN CERTIFICATE----- +MIICvjCCAiegAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCAxMB4XDTA5 +MTExODE1MjMyM1oXDTM0MTExMjE1MjMyM1owbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAxIFN1YiBDQSAxIFJvb3QgMTCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAyEFmhMfVxXKPppgbWeIzyg3SJLPBR9sR +4r8j2jJoQcz/KP6aOUnnCPAidRVhmZ6Z5RRlcWAAD1hCcHhaHtj6l5KCDuMMrCDc +uONeh4uJ46HDh0kdkqX9fHd5zh/6nFoX2REM8n8a+tgyQfhpgK6KZr02wiFlVwi+ +z/DsgxWYbWUCAwEAAaNwMG4wLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJh +dGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBT/u7B/4w7jjM/siEmpDmK102ASRjAf +BgNVHSMEGDAWgBQ3cXSBRN0esWCWQbdLOMS3eRvPijANBgkqhkiG9w0BAQUFAAOB +gQAz3ehXPmkboEyDUZndc7AMy8fA/xKLtjtZErnxIId18HFuvJRHcmKuk5AF4v9j +MVrSgKVKf1fp904+vr1MnnQHGbBNiJevI6daI6/RqZibVX76axh3A8SqSby2PWY+ +jQqAX6y5WPsR72Dbrah5QYMaamGHmWQt5Gq7wDAA3Wnlkg== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/private/cakey.pem new file mode 100644 index 0000000000..602026a470 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,4E900CB191575111 + +vHLTGKUgxa3C35alVr0gWT30x8WW5Pmz4oFv23fMMWIXjrp/QLlRRmd2AO9H8rLb +3MWnA7cby5UTcrcsqwBA30TqhduNDi4iQFcOM60/S7yUFKjF5nj9bGi8XuUzMgTx +OrJuxMGkayLiELskZxEpi6SJvTEsSdreT6OvyhzXQfAFDodoJSW65oF08cuYxXzi +FFYFqvyWXa29WUyinBav5k3Mjax3Av3dYfMf/1u2n4vjGyjkfMg7mHrno19daWqa +FJsxHHFezq//G5+JvePWFQUo1b0fVh13fx9x1dCbCRGQ9duSXaI7BNfl2Jd2rlVk +xUMqnvd8VBNkW1AHxZL4csurQyO8ZQzg46w/kWaIMroeXbUnZYNJV7/TCs6nLGJF +iNwtsFAjunWgWttFbMx3X7L7T6f6cWXocOOTNeIDpH+W6Pw9vltrjzNPAyBBok17 +sboWXDtlihMrSq5lWzUSPE8gOueh7Bcf7fSnLTeXuOXgKooJVXelookSQzsilWmS +Fo5PTM+jOOaXVlbf8zfKFreLawohNkzagIxrCEP+HU+tF52ybJDP4mwPi1sQNcA0 +0luHyCL5EmaH5hVIqYeGUQoNPois5TqgYH1SEujyIuoNdEBi5r5qIRR/zz+BEpKU +Z1B+HmmSWb0hjfenFSSaSSmGyS6VW1wZsU2B+wcPr7r0uFqoWllkxYNmSdky6qmw +4Or0D6ayFUaJOQG6aTEfEVS31B4TUfFGfOLbeuUdwNa4/pNwMeFFSx+Xj7J3oYrn +udjIL0Hz8hhjLVXaPVcu/qkZ7pXhOVlRQJ7byx730G3+elUFalJ/eQ== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/serial new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/serial @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/openssl.cfg new file mode 100644 index 0000000000..0dd15bd9ec --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/DO_NOT_INSTALL_THIS_CERTIFICATE b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/DO_NOT_INSTALL_THIS_CERTIFICATE new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/DO_NOT_INSTALL_THIS_CERTIFICATE diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/README.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/README.txt new file mode 100644 index 0000000000..a18ed9ce0c --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/README.txt @@ -0,0 +1,19 @@ +Do NOT install !!! + + + +To provide the CRL via HTTP run + + + +java -jar ../../tools/httpserv/dist/httpserv.jar -a 8902 + + +To provide the intermediate certificate run + +java -jar ../../tools/httpserv/dist/httpserv.jar -a 8910 + + + + + diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/DO_NOT_INSTALL_THIS_CERTIFICATE b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/DO_NOT_INSTALL_THIS_CERTIFICATE new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/DO_NOT_INSTALL_THIS_CERTIFICATE diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/Sub_CA_1_Root_10.crt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/Sub_CA_1_Root_10.crt Binary files differnew file mode 100644 index 0000000000..2bb9a42894 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/Sub_CA_1_Root_10.crt diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/cacert.pem new file mode 100644 index 0000000000..1f27b97b3d --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/cacert.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 10 + Validity + Not Before: Nov 23 15:14:48 2009 GMT + Not After : Nov 17 15:14:48 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 10 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:e4:d5:66:14:88:9f:79:41:50:b0:d1:a0:1b:98: + bf:b0:21:34:30:36:70:58:6f:8b:58:f1:b9:58:3a: + ce:29:6b:65:b6:11:f7:0d:c8:a6:c3:be:db:0f:2a: + 4e:c7:42:df:c9:0e:13:c0:00:0f:af:b5:71:c4:bc: + dd:82:fc:4a:27:c0:ee:af:ba:e1:7b:67:de:6b:bb: + ac:4c:fe:88:01:1a:73:4e:f5:32:15:3a:d0:cb:6b: + 97:84:1b:6c:d0:d6:91:a8:a4:5a:87:2a:69:61:36: + 1d:42:cc:16:d0:03:9c:c6:90:5c:61:20:8b:b1:be: + b6:54:24:5b:6f:1f:a9:5a:6f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 11:63:A1:BE:8B:E3:56:07:E6:A3:9F:23:39:72:7D:E3:22:B6:53:39 + X509v3 Authority Key Identifier: + keyid:C8:A7:A3:80:20:74:6C:6F:EC:11:7A:F6:BE:26:10:37:31:87:B0:7A + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 10 + serial:BF:C8:0F:BB:D9:A0:3A:6B + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 6b:0f:75:6d:56:b0:4e:45:19:65:ad:50:ef:4e:87:6c:95:5d: + 05:39:5a:43:5c:b4:51:25:9a:ec:f4:93:d1:f0:f6:91:dd:a3: + 77:95:0c:74:3c:a9:7c:c2:f6:62:ce:bf:58:5f:66:1f:d0:55: + ca:d8:2d:c4:1e:29:3a:ad:55:2c:9d:2c:8f:8e:9e:ce:ac:17: + 7e:1b:d1:16:d9:12:76:5c:2d:3f:9d:70:66:aa:39:34:f0:ec: + 31:4b:4b:5a:14:0c:c5:5b:3c:c8:47:02:90:cb:77:d7:4f:88: + 10:a7:80:3d:ca:19:5c:b5:04:c9:f0:e1:1b:5a:5f:fb:61:b2: + 14:b5 +-----BEGIN CERTIFICATE----- +MIIDCTCCAnKgAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMDAeFw0wOTExMjMxNTE0 +NDhaFw0zNDExMTcxNTE0NDhaMGkxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxGTAXBgNVBAMTEFN1YiBDQSAxIFJvb3QgMTAwgZ8wDQYJKoZIhvcNAQEBBQAD +gY0AMIGJAoGBAOTVZhSIn3lBULDRoBuYv7AhNDA2cFhvi1jxuVg6zilrZbYR9w3I +psO+2w8qTsdC38kOE8AAD6+1ccS83YL8SifA7q+64Xtn3mu7rEz+iAEac071MhU6 +0Mtrl4QbbNDWkaikWocqaWE2HULMFtADnMaQXGEgi7G+tlQkW28fqVpvAgMBAAGj +gcgwgcUwHQYDVR0OBBYEFBFjob6L41YH5qOfIzlyfeMitlM5MIGSBgNVHSMEgYow +gYeAFMino4AgdGxv7BF69r4mEDcxh7B6oWSkYjBgMQswCQYDVQQGEwJERTEQMA4G +A1UECBMHSGFtYnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsT +C0RldmVsb3BtZW50MRAwDgYDVQQDEwdSb290IDEwggkAv8gPu9mgOmswDwYDVR0T +AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBrD3VtVrBORRllrVDvTodslV0F +OVpDXLRRJZrs9JPR8PaR3aN3lQx0PKl8wvZizr9YX2Yf0FXK2C3EHik6rVUsnSyP +jp7OrBd+G9EW2RJ2XC0/nXBmqjk08OwxS0taFAzFWzzIRwKQy3fXT4gQp4A9yhlc +tQTJ8OEbWl/7YbIUtQ== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/crl/DO_NOT_INSTALL_THIS_CRL b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/crl/DO_NOT_INSTALL_THIS_CRL new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/crl/DO_NOT_INSTALL_THIS_CRL diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/crl/Sub_CA_1_Root_10.crl b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/crl/Sub_CA_1_Root_10.crl Binary files differnew file mode 100644 index 0000000000..67ed32da5f --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/crl/Sub_CA_1_Root_10.crl diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/crlnumber new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/crlnumber @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/index.txt new file mode 100644 index 0000000000..810ec7ef2f --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/index.txt @@ -0,0 +1 @@ +V 341117153149Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 1 Root 10 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/index.txt.attr new file mode 100644 index 0000000000..8f7e63a347 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/newcerts/1000.pem new file mode 100644 index 0000000000..7449048bbc --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/newcerts/1000.pem @@ -0,0 +1,67 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 10 + Validity + Not Before: Nov 23 15:31:49 2009 GMT + Not After : Nov 17 15:31:49 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 1 Root 10 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:ce:41:53:5f:ba:d9:26:e4:45:14:74:a9:f2:9e: + fa:91:50:ea:fe:e7:76:76:6e:62:26:4c:a2:bd:c9: + 98:ce:1d:b3:74:ea:95:04:ec:d8:24:ac:29:de:2d: + 7f:2f:7f:10:94:24:d2:0c:0b:ff:d0:38:f1:a9:8f: + ee:25:97:bf:bd:b0:1f:24:d7:9d:7a:20:79:c0:73: + 97:12:cb:5a:cf:6d:4f:df:4a:a8:9c:1b:be:49:63: + 1f:b1:03:6d:c6:5f:69:5c:0d:7e:81:23:48:2a:76: + 80:53:53:d2:03:f6:56:6d:dc:e3:cc:be:cb:0f:c3: + 1b:b7:6e:79:33:e0:da:f6:5d + Exponent: 65537 (0x10001) + X509v3 extensions: + Authority Information Access: + CA Issuers - URI:http://localhost:8910/demoCA/Sub_CA_1_Root_10.crt + + X509v3 CRL Distribution Points: + URI:http://localhost:8902/demoCA/crl/Sub_CA_1_Root_10.crl + + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 90:DC:ED:B0:CB:62:A1:BE:8F:23:65:01:79:14:85:22:48:70:7B:A1 + X509v3 Authority Key Identifier: + keyid:11:63:A1:BE:8B:E3:56:07:E6:A3:9F:23:39:72:7D:E3:22:B6:53:39 + + Signature Algorithm: sha1WithRSAEncryption + 54:e3:d2:eb:dc:aa:db:8b:88:34:c6:b9:5b:f6:d8:ca:81:24: + d0:ba:4c:c2:a7:8e:82:22:d3:68:64:c9:61:9b:0a:00:3e:d1: + 4e:cb:83:1d:b9:c7:07:6a:5e:7b:b4:ca:92:0c:93:d7:9e:99: + e1:58:47:17:b0:a7:6d:68:5f:e5:59:f9:2a:d1:96:df:b6:9f: + bc:47:40:f2:71:ed:71:2b:8a:6e:6f:aa:29:9f:4d:98:ee:f1: + aa:63:b4:44:39:58:8a:f8:c2:af:8d:c1:49:92:b4:99:02:2f: + 27:c7:5b:f5:30:7c:ed:67:ff:cd:12:dc:a7:c4:8e:98:4f:2c: + e0:05 +-----BEGIN CERTIFICATE----- +MIIDODCCAqGgAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwaTELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEZMBcGA1UEAxMQU3ViIENBIDEgUm9vdCAxMDAeFw0w +OTExMjMxNTMxNDlaFw0zNDExMTcxNTMxNDlaMHAxCzAJBgNVBAYTAkRFMRAwDgYD +VQQIEwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxML +RGV2ZWxvcG1lbnQxIDAeBgNVBAMTF1VzZXIgMSBTdWIgQ0EgMSBSb290IDEwMIGf +MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOQVNfutkm5EUUdKnynvqRUOr+53Z2 +bmImTKK9yZjOHbN06pUE7NgkrCneLX8vfxCUJNIMC//QOPGpj+4ll7+9sB8k1516 +IHnAc5cSy1rPbU/fSqicG75JYx+xA23GX2lcDX6BI0gqdoBTU9ID9lZt3OPMvssP +wxu3bnkz4Nr2XQIDAQABo4HnMIHkME0GCCsGAQUFBwEBBEEwPzA9BggrBgEFBQcw +AoYxaHR0cDovL2xvY2FsaG9zdDo4OTEwL2RlbW9DQS9TdWJfQ0FfMV9Sb290XzEw +LmNydDBGBgNVHR8EPzA9MDugOaA3hjVodHRwOi8vbG9jYWxob3N0Ojg5MDIvZGVt +b0NBL2NybC9TdWJfQ0FfMV9Sb290XzEwLmNybDALBgNVHQ8EBAMCBeAwHQYDVR0O +BBYEFJDc7bDLYqG+jyNlAXkUhSJIcHuhMB8GA1UdIwQYMBaAFBFjob6L41YH5qOf +IzlyfeMitlM5MA0GCSqGSIb3DQEBBQUAA4GBAFTj0uvcqtuLiDTGuVv22MqBJNC6 +TMKnjoIi02hkyWGbCgA+0U7Lgx25xwdqXnu0ypIMk9eemeFYRxewp21oX+VZ+SrR +lt+2n7xHQPJx7XErim5vqimfTZju8apjtEQ5WIr4wq+NwUmStJkCLyfHW/UwfO1n +/80S3KfEjphPLOAF +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/private/cakey.pem new file mode 100644 index 0000000000..260e3aa946 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,170F9697C268C4B5 + +eIaE0ShuxMcOUBJBlI7PXIuKg69hDunjUz55iy0I+4sGc9tFK+vtjvDZWxx+dpZI +WKGto0fDeobBf3f2xgKQFcwAtUPtiTMXk8C0BYfAbXsTYBgOgvKwJGOIo5FsjukZ +VJCNlUM1mwX5P3OrLdyT0j8OoL6lINztYDhSC8XL12YJk1j05yN4Gl8N108JQMLA +sywA2Q6WIhPloZQXtHkiN2mlQ7WWwbSBbaUbdXNQKk6sXelFLPMOk+JOTCLp9kHU +svTBAg7RyWKBuUmtEmkipNLtYhdkRVJ/dgL3/TAsZET6cjDd/eZg+1Kl0pn93KGv +avSQKppkKNjUcWkZiuM1imS8+0qeMiw56JQGzMdEeSjadcTdsyYb0lssXmndK/z0 +90bA6GegvCnsq6Wj0Nz97GbK+ZMzA76e+HPQLli0j3poAlVwdzBCFRyLO4ET5Qzl +OhTewxKZxe2yx75chECWJS+CLOajHkVyUe3x6QzyVuU+YZqjXWkJP7rTcQJZFcml ++3PHYWy5RnZ2sKOegksr3+QtL+UmDVa1xEeIhk3m0IMiYZ9HNWlrg1gedY02y9yY +MGsCOkCF10KnCNIp4j5s1kGMicdMquDt0jTXwu+8jt6Skh8FWcr9aLf0bNc63oHg +NaI7Y3+Ssl3GLUGFOGwC0lpooZ10SoJJDK9xxEjt48vUfX+Npn3bRv+UlwfLBYLo +GENyNV3OVAsKYQ8fGIh/gTeIqwMUdo7Efcs6bdeqiOrYQhBl04Gty0I4cO6/lFGd +by/4SesYDXoVtaKto1B5VOQn+QxovF7eY1pK6wDBU8+EaJbGSNK9Rw== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/serial new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/serial @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/openssl.cfg new file mode 100644 index 0000000000..431650974b --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/openssl.cfg @@ -0,0 +1,293 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8889 +authorityInfoAccess = caIssuers;URI:http://localhost:8910/demoCA/Sub_CA_1_Root_10.crt +crlDistributionPoints=URI:http://localhost:8902/demoCA/crl/Sub_CA_1_Root_10.crl +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +#nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/cacert.pem new file mode 100644 index 0000000000..36a8eb3c07 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/cacert.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 2 + Validity + Not Before: Nov 18 15:55:38 2009 GMT + Not After : Nov 12 15:55:38 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 2 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:f0:7a:16:4c:ab:06:b2:af:27:9c:7d:3f:86:da: + de:7a:c3:01:67:77:56:49:09:ed:ed:31:72:83:e8: + 75:9c:4c:ce:f9:97:b6:63:3c:e2:ca:83:80:92:03: + 9c:96:e2:de:72:79:c1:cf:3e:3f:b9:0d:b4:87:c7: + 75:e6:56:8d:aa:f8:77:47:11:4e:fe:07:b0:1d:64: + 06:73:4b:6f:d4:ac:da:0f:05:87:b1:f1:98:a9:f5: + 8a:a1:a8:ed:17:9c:26:b8:da:92:63:d2:53:87:e6: + fc:ed:44:de:94:56:90:3e:a2:a1:67:08:cb:38:d4: + cf:17:3b:7e:ff:7a:97:c0:7b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 8C:F3:2C:30:A2:E8:62:50:70:BC:FC:71:A0:41:FA:E0:58:B4:4D:B8 + X509v3 Authority Key Identifier: + keyid:5F:BC:4C:DA:EB:0A:0C:B5:23:43:5E:24:32:27:79:41:F5:82:A3:02 + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 2 + serial:A2:AF:15:89:EC:73:54:86 + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 52:83:16:ab:0e:43:2d:b3:e4:0f:6c:c1:63:d4:86:ac:e7:1e: + ee:7b:ee:9b:0c:ff:4f:e0:59:d5:e4:27:af:68:bf:a7:f5:2a: + a3:c9:e3:2b:8d:b7:31:26:f6:04:80:4e:f2:a5:bf:da:63:5e: + 8c:d6:c6:b2:46:a0:46:10:2f:84:9f:02:76:f3:c8:33:05:62: + 0c:5f:2d:cc:06:23:53:9f:d9:f8:46:e4:2e:5c:da:05:fc:bf: + db:45:b4:ac:8d:8b:b5:4b:60:7b:7b:26:34:7f:b1:4b:41:96: + 41:26:70:7a:9d:78:a2:9b:e0:de:62:a2:04:86:9f:ed:7c:a6: + 20:eb +-----BEGIN CERTIFICATE----- +MIIDBjCCAm+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCAyMB4XDTA5MTExODE1NTUz +OFoXDTM0MTExMjE1NTUzOFowaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCAyMIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDwehZMqwayryecfT+G2t56wwFnd1ZJCe3tMXKD6HWcTM75l7ZjPOLK +g4CSA5yW4t5yecHPPj+5DbSHx3XmVo2q+HdHEU7+B7AdZAZzS2/UrNoPBYex8Zip +9YqhqO0XnCa42pJj0lOH5vztRN6UVpA+oqFnCMs41M8XO37/epfAewIDAQABo4HH +MIHEMB0GA1UdDgQWBBSM8ywwouhiUHC8/HGgQfrgWLRNuDCBkQYDVR0jBIGJMIGG +gBRfvEza6woMtSNDXiQyJ3lB9YKjAqFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCAyggkAoq8ViexzVIYwDwYDVR0TAQH/ +BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBSgxarDkMts+QPbMFj1Ias5x7ue+6b +DP9P4FnV5CevaL+n9SqjyeMrjbcxJvYEgE7ypb/aY16M1sayRqBGEC+EnwJ288gz +BWIMXy3MBiNTn9n4RuQuXNoF/L/bRbSsjYu1S2B7eyY0f7FLQZZBJnB6nXiim+De +YqIEhp/tfKYg6w== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/crlnumber new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/crlnumber @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/index.txt new file mode 100644 index 0000000000..ae1f2d1e4c --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/index.txt @@ -0,0 +1 @@ +V 341112160955Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 1 Root 2 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/index.txt.attr new file mode 100644 index 0000000000..8f7e63a347 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/newcerts/1000.pem new file mode 100644 index 0000000000..a8c0b74caf --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/newcerts/1000.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 2 + Validity + Not Before: Nov 18 16:09:55 2009 GMT + Not After : Nov 12 16:09:55 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 1 Root 2 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:c7:00:aa:e0:5a:42:af:9c:b5:43:8c:f4:7d:7a: + 0f:ee:a9:19:22:d8:47:14:af:b4:e4:dd:5d:41:92: + a1:2b:32:39:5c:71:88:10:e3:77:87:b6:d5:38:85: + de:4b:91:c6:17:97:8e:3d:96:b3:af:8c:9d:74:8c: + 88:7f:2a:72:9a:ca:1a:1b:56:6c:63:2e:a4:a0:fc: + 3a:7b:0d:c2:16:15:d0:80:15:29:de:cd:0b:74:bc: + 5e:31:84:71:a4:fd:be:9b:06:6a:0c:47:1d:f9:e4: + c1:98:ae:46:e6:e2:51:55:d5:bb:ab:05:28:69:b5: + f8:35:32:d6:f0:64:d8:44:81 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + Netscape Comment: + OpenSSL Generated Certificate + X509v3 Subject Key Identifier: + 71:60:2B:22:B5:DF:FC:38:7E:79:F3:EF:7C:96:5F:C1:D2:42:9C:61 + X509v3 Authority Key Identifier: + keyid:8C:F3:2C:30:A2:E8:62:50:70:BC:FC:71:A0:41:FA:E0:58:B4:4D:B8 + + Signature Algorithm: sha1WithRSAEncryption + e5:b8:1a:43:82:75:20:48:e0:52:d0:46:25:6f:f7:5b:a9:3f: + 9e:cd:db:45:da:15:53:95:e7:c8:74:7b:e0:e4:2c:8c:f6:4d: + 1c:73:6e:2c:11:eb:c1:dc:4c:1d:50:e3:e8:10:2f:03:20:06: + ff:d7:4f:c9:a2:2e:ef:85:27:92:31:47:64:c8:75:f2:fc:a4: + 9d:c9:53:55:c5:da:69:b0:96:99:fd:ac:c4:16:40:ea:0c:1b: + 32:c3:fd:65:1d:03:ad:be:60:88:7c:70:53:35:91:ce:13:e2: + 3d:23:6b:e8:23:c0:3c:9a:57:5f:ad:4b:03:94:92:16:62:f9: + d4:01 +-----BEGIN CERTIFICATE----- +MIICyzCCAjSgAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCAyMB4XDTA5 +MTExODE2MDk1NVoXDTM0MTExMjE2MDk1NVowbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAxIFN1YiBDQSAxIFJvb3QgMjCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAxwCq4FpCr5y1Q4z0fXoP7qkZIthHFK+0 +5N1dQZKhKzI5XHGIEON3h7bVOIXeS5HGF5eOPZazr4yddIyIfypymsoaG1ZsYy6k +oPw6ew3CFhXQgBUp3s0LdLxeMYRxpP2+mwZqDEcd+eTBmK5G5uJRVdW7qwUoabX4 +NTLW8GTYRIECAwEAAaN9MHswCwYDVR0PBAQDAgXgMCwGCWCGSAGG+EIBDQQfFh1P +cGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUcWArIrXf/Dh+ +efPvfJZfwdJCnGEwHwYDVR0jBBgwFoAUjPMsMKLoYlBwvPxxoEH64Fi0TbgwDQYJ +KoZIhvcNAQEFBQADgYEA5bgaQ4J1IEjgUtBGJW/3W6k/ns3bRdoVU5XnyHR74OQs +jPZNHHNuLBHrwdxMHVDj6BAvAyAG/9dPyaIu74UnkjFHZMh18vyknclTVcXaabCW +mf2sxBZA6gwbMsP9ZR0Drb5giHxwUzWRzhPiPSNr6CPAPJpXX61LA5SSFmL51AE= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/private/cakey.pem new file mode 100644 index 0000000000..ba6119464f --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,A5EF3D451C410026 + +RByk5Bn7uG1eixW1qTghnNri2bQHvnrNUYcpSL/mJIx6NjuYEY6vE/vQ9A9qcjuZ +8NInLR1w+EmSlDS499za8dfllaJ4/djswWN+4gtkoP/kKF390AcNgIpf/gIiJX6d +tkrw3Esst2gUwdtdhWItQNh0qZoeWpY9KlraDdEYVZt46JmsgwEIufzHyHTHf53C +E9ZP7/vYBQeHPOvMGsvhwZWAZZOO5GnD4fktbVAnybQdnlPgJDrRTGabbTdawQNc +8GJoG6hgJPcwlYm7NbRrtB18L3bG4bxx95fjqeOtvGDSUxSY+FNV7B2xQpivnBu6 +ppLdwTRYHQGOCJSCZoCtW+GYM7wXR2L4kGXMPwB4hHUAQXt+Tva9TP0t96313lMW +bFTRgTcT71eBidEkUIn1OrOL/Al2lXvSaDhm0P2F0yElzj3JN/gqrIUChaXWcLrS +CZuOGA2zGpoBASQ5jF+CyC+5mEkmDgvbmAXiJNjNmK/ColklpTNRSGk65Vr8AufA +d/yoSQCGprhMgqhviue40MGSsOD58TLwR4Tsm5ptze0QYRNC2SkKCrgtS0IEXh/Z +/9cMAgwOypW1T7LMOV+rG9DOyKx9Ye+oxPLCHdS7wN4h6blusiESbbUW0f5wqAzF +FCe6VEd+AjahnQLjw7O8vP4zl8q99cjOYD5SB+wqYrr0beEely7xdpKrDMgXqiBe +tOE9XvgU9KR59GZd0l6FPRkpZCUA+3Wuu4Zvrbam5kEbxVy+VTamWd5cRrxbJBM4 +Ipn414lfeq/5Foz13roErJE6gbWxXeCFDzg0z5fjWc2T41PX58x4Tw== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/req.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/req.pem new file mode 100644 index 0000000000..cc93d02e54 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/req.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIBqDCCARECAQAwaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1cmcxFzAV +BgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVudDEYMBYG +A1UEAxMPU3ViIENBIDEgUm9vdCAyMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB +gQDwehZMqwayryecfT+G2t56wwFnd1ZJCe3tMXKD6HWcTM75l7ZjPOLKg4CSA5yW +4t5yecHPPj+5DbSHx3XmVo2q+HdHEU7+B7AdZAZzS2/UrNoPBYex8Zip9YqhqO0X +nCa42pJj0lOH5vztRN6UVpA+oqFnCMs41M8XO37/epfAewIDAQABoAAwDQYJKoZI +hvcNAQEFBQADgYEADbuni6Yq0l5FJGFDUaabv4T75XxyMWy+k6wSojSt1thtwcJI +Bx5x1ngG5VyxeNmqyjLvd2KeYsVaV8M9J9ty40QGL8F83OArJPGADtBSM+gwmjdu +C+ksYL+5Yl8vSY3M7tKqJB2AFk2QlfP5okMQWRJ5QFTTwA8EFpHFsy4gsks= +-----END CERTIFICATE REQUEST----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/serial new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/serial @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/openssl.cfg new file mode 100644 index 0000000000..51e5205253 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/cacert.pem new file mode 100644 index 0000000000..c14880b580 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/cacert.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 3 + Validity + Not Before: Nov 20 07:40:39 2009 GMT + Not After : Nov 14 07:40:39 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 3 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:9e:87:1f:af:f0:a0:1c:f4:9e:f8:c3:e7:ee:d3: + cb:a8:e2:54:98:ba:dd:7e:dc:6e:14:e1:7e:7f:5b: + 1e:ef:53:3d:89:76:ea:e2:b3:6c:08:0d:e8:c8:4d: + 24:40:ff:92:f3:5b:51:f7:90:ac:69:37:29:90:f5: + e8:95:6f:67:d1:10:cd:7b:dd:65:38:d6:25:ec:63: + 39:ba:2e:ea:13:58:8e:7a:82:8e:10:d1:7b:77:7a: + 08:d5:82:66:62:a4:83:39:ad:f5:83:d5:2f:5c:bc: + 23:6e:c8:78:8b:38:9f:eb:a3:67:ba:43:fa:e4:07: + 3f:90:72:db:0c:f9:49:0e:0d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 1B:2D:E0:A2:26:7F:0D:BA:38:7E:EC:06:81:81:0F:12:74:4C:5A:4D + X509v3 Authority Key Identifier: + keyid:69:FF:30:EC:1F:34:9A:67:3A:6B:20:D2:DF:7F:F5:05:04:ED:F9:1C + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 3 + serial:95:6F:F0:E3:2B:BE:76:F9 + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 6f:ac:53:9d:16:6e:95:ed:97:60:ed:c8:a8:96:ab:24:c5:1e: + d5:d7:26:98:fb:b5:aa:ef:da:a4:91:6a:82:55:ec:21:a2:08: + 24:c7:0c:a7:58:0c:06:69:3d:04:7d:08:f1:0b:77:41:ad:1c: + 13:c2:bd:17:c9:9e:ff:df:64:69:8b:58:f1:bc:40:bd:cf:e4: + 57:29:bc:5e:93:84:61:56:4c:e6:c1:3a:2c:6e:71:ea:5d:67: + c0:54:be:4f:2f:27:a8:59:8d:29:94:ba:c6:6c:ff:ed:25:3d: + 0b:fa:93:c9:45:f4:d5:a3:3d:be:8a:f1:9d:c4:92:d5:5c:d2: + 77:7c +-----BEGIN CERTIFICATE----- +MIIDBjCCAm+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCAzMB4XDTA5MTEyMDA3NDAz +OVoXDTM0MTExNDA3NDAzOVowaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCAzMIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQCehx+v8KAc9J74w+fu08uo4lSYut1+3G4U4X5/Wx7vUz2Jduris2wI +DejITSRA/5LzW1H3kKxpNymQ9eiVb2fREM173WU41iXsYzm6LuoTWI56go4Q0Xt3 +egjVgmZipIM5rfWD1S9cvCNuyHiLOJ/ro2e6Q/rkBz+QctsM+UkODQIDAQABo4HH +MIHEMB0GA1UdDgQWBBQbLeCiJn8Nujh+7AaBgQ8SdExaTTCBkQYDVR0jBIGJMIGG +gBRp/zDsHzSaZzprINLff/UFBO35HKFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCAzggkAlW/w4yu+dvkwDwYDVR0TAQH/ +BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBvrFOdFm6V7Zdg7ciolqskxR7V1yaY ++7Wq79qkkWqCVewhoggkxwynWAwGaT0EfQjxC3dBrRwTwr0XyZ7/32Rpi1jxvEC9 +z+RXKbxek4RhVkzmwTosbnHqXWfAVL5PLyeoWY0plLrGbP/tJT0L+pPJRfTVoz2+ +ivGdxJLVXNJ3fA== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/crl/DO_NOT_CREATE_A_CRL b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/crl/DO_NOT_CREATE_A_CRL new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/crl/DO_NOT_CREATE_A_CRL diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/crlnumber new file mode 100644 index 0000000000..83b33d238d --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/crlnumber @@ -0,0 +1 @@ +1000 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/index.txt new file mode 100644 index 0000000000..bd3b5eaeae --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/index.txt @@ -0,0 +1 @@ +V 341114075225Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 1 Root 3 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/index.txt.attr new file mode 100644 index 0000000000..8f7e63a347 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/newcerts/1000.pem new file mode 100644 index 0000000000..46d60bda0a --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/newcerts/1000.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 3 + Validity + Not Before: Nov 20 07:52:25 2009 GMT + Not After : Nov 14 07:52:25 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 1 Root 3 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:bc:82:f1:75:77:02:f8:fb:3a:c2:8d:3c:1b:cb: + b2:63:2e:89:07:92:6b:b4:e1:ab:ce:30:a1:a4:82: + 38:30:64:2a:ba:01:c6:ac:ee:03:cc:65:bf:83:3e: + 39:b8:ce:ac:45:99:97:f9:94:e2:7d:5d:f3:c5:f7: + d4:a5:d6:57:cf:24:c1:d7:56:eb:00:9c:5d:80:bc: + 23:0c:91:d6:8e:2a:62:f6:af:4d:c9:19:5b:dd:16: + be:21:54:51:71:be:f2:c6:64:c5:bb:8e:37:49:c9: + 4d:68:82:3a:42:8a:e3:de:ab:fa:c7:ff:a5:b4:c7: + 53:8f:17:a4:66:9d:c3:8e:b1 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + Netscape Comment: + OpenSSL Generated Certificate + X509v3 Subject Key Identifier: + 0B:DD:2E:E9:5C:8A:5F:67:C9:75:4C:B3:04:DB:95:2F:D8:74:76:EF + X509v3 Authority Key Identifier: + keyid:1B:2D:E0:A2:26:7F:0D:BA:38:7E:EC:06:81:81:0F:12:74:4C:5A:4D + + Signature Algorithm: sha1WithRSAEncryption + 18:2f:af:1a:27:c7:f8:81:cd:d5:31:a0:f2:06:05:94:d6:12: + 11:88:24:ae:4f:f6:86:18:bf:d0:1b:c9:19:7a:47:30:0e:fb: + 30:b2:50:31:8d:30:6b:8b:54:17:67:bc:b8:c1:d5:1c:6c:95: + c5:e4:c4:ad:12:39:2f:38:ee:53:6a:cf:be:1c:4f:ac:98:0c: + ea:eb:0b:48:3d:5e:7a:2b:ed:02:8b:34:89:0a:d8:32:b4:6f: + f4:b2:06:96:aa:6b:ae:19:38:ec:9f:47:43:3b:7b:bd:71:38: + 99:4f:b4:1e:87:95:73:63:76:d4:ff:21:57:2c:c3:f4:3c:fd: + cb:c3 +-----BEGIN CERTIFICATE----- +MIICyzCCAjSgAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCAzMB4XDTA5 +MTEyMDA3NTIyNVoXDTM0MTExNDA3NTIyNVowbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAxIFN1YiBDQSAxIFJvb3QgMzCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvILxdXcC+Ps6wo08G8uyYy6JB5JrtOGr +zjChpII4MGQqugHGrO4DzGW/gz45uM6sRZmX+ZTifV3zxffUpdZXzyTB11brAJxd +gLwjDJHWjipi9q9NyRlb3Ra+IVRRcb7yxmTFu443SclNaII6Qorj3qv6x/+ltMdT +jxekZp3DjrECAwEAAaN9MHswCwYDVR0PBAQDAgXgMCwGCWCGSAGG+EIBDQQfFh1P +cGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUC90u6VyKX2fJ +dUyzBNuVL9h0du8wHwYDVR0jBBgwFoAUGy3goiZ/Dbo4fuwGgYEPEnRMWk0wDQYJ +KoZIhvcNAQEFBQADgYEAGC+vGifH+IHN1TGg8gYFlNYSEYgkrk/2hhi/0BvJGXpH +MA77MLJQMY0wa4tUF2e8uMHVHGyVxeTErRI5LzjuU2rPvhxPrJgM6usLSD1eeivt +Aos0iQrYMrRv9LIGlqprrhk47J9HQzt7vXE4mU+0HoeVc2N21P8hVyzD9Dz9y8M= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/private/cakey.pem new file mode 100644 index 0000000000..8d893cdf9e --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,EF032FCF0827A7AA + +vTlvOy1d4MK41zEZfeUWDO7kjLqZ53jK6JdXhKT2P9MnstGf1S0QxwbEKP+KWj+4 +lwS7fSXs6/s2Q5OrG9QSV4bm5Sob0OpDfoc1GS24uSGvYXzhuyM9sjiITXvyGKCH ++0VQPV/GSXWShsk5CCzUXIBSBHDVxlEzmBvzWiHfcLEAwF1JJlh6ex9Xju9JL9sN +Gp4VMw9PML11V4iqNXKeyBZ87Bv/yew+bDACLCe7e1liBxdOj2ntc7mtpCrkf/pn +hLnJ1qKodcwgmmMLufa7//E1RCBMn1gml0YXMe+Grrn7tFdVWT/puKiSrKGgIbbB +RNf7JnG5E8Oy2V8NRk4SV5Au784fw5NMykQDCMJFp9aldwP7LlIUBPtPm/jpaY0V +e6tKT20e4Ru2mDzyfef8nhFRogMxvPrxVSxN8aI1u/soPMp55ypWrqg99QlsiZgG +MhpHaFODSWvHaFcwFY+gEDUmEH76S3wuOSgeFolvIPEETjw6Vc46Zi32N1ycQ1wz +NCbIGy2ftEzKIEOeXHAsuQiP+Cic1QYJEOxhvOq9VteYfilT7D9FQ2+QOqrl4+2X +hj2RaTJawpSFoWfEh7QM1ir0TPj3wRSTg6g3e0f+vAvI9AfVEP3ctPm6tpXirUgh +QOA1LZKZzHUYqr0q2TBvItyGsg3w7dxyeB6brCtzOzg+GpvNhaRZ1/+SVPxzYVgf +buLQIfvvLE6TmABxOloop1m61u6c6+Bg5kKHXSnUKehGv+iIxVLZgxrNkCFyyzX0 +Dpu9hkGYzVzE8QCujC09MZCKH/85iYGuEZtP81Mjyjs= +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/req.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/req.pem new file mode 100644 index 0000000000..dd08bf6717 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/req.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIBqDCCARECAQAwaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1cmcxFzAV +BgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVudDEYMBYG +A1UEAxMPU3ViIENBIDEgUm9vdCAzMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB +gQCehx+v8KAc9J74w+fu08uo4lSYut1+3G4U4X5/Wx7vUz2Jduris2wIDejITSRA +/5LzW1H3kKxpNymQ9eiVb2fREM173WU41iXsYzm6LuoTWI56go4Q0Xt3egjVgmZi +pIM5rfWD1S9cvCNuyHiLOJ/ro2e6Q/rkBz+QctsM+UkODQIDAQABoAAwDQYJKoZI +hvcNAQEFBQADgYEAiwW4WbC3V3wEBfPlIFiUagJHOettp5NyCzLULyQZE1FXs/zV +RxIi3Oxdaj643QZ8h6upKf9F60T8+oG15RBdp1ZjmBXnv7ZRx33LynExbxX0XKjo +Pg/8dGLFBomZqE8MpWbQtY5lRkQOkgt5XZLj5SMJQsgpVaAOPQcOg5Sqfag= +-----END CERTIFICATE REQUEST----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/serial new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/serial @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/openssl.cfg new file mode 100644 index 0000000000..51e5205253 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/README.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/README.txt new file mode 100644 index 0000000000..3ac354b8f8 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/README.txt @@ -0,0 +1,4 @@ +Revoked certificates: +--------------------- +- User 2 Sub CA 1 Root 4 + diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/cacert.pem new file mode 100644 index 0000000000..3910371181 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/cacert.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 4 + Validity + Not Before: Nov 20 08:37:27 2009 GMT + Not After : Nov 14 08:37:27 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 4 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:da:b0:21:94:89:b0:00:89:cb:69:59:9b:0d:fe: + 1f:b9:a0:a8:44:92:55:5f:0b:d5:e5:08:63:bd:47: + 6b:11:4d:b1:a8:12:6f:c1:cf:cb:9e:ae:e2:c1:03: + 68:46:59:0b:96:7c:21:45:9b:14:81:d8:f1:83:70: + 6b:3d:b4:56:65:49:87:1d:ab:e2:08:6a:49:66:0e: + 59:b4:da:7a:3f:72:23:b8:1f:fb:78:f5:f0:2d:c4: + fe:d9:94:6e:2e:c3:6e:95:ba:38:60:d1:0b:fa:16: + c7:02:71:ef:3e:71:72:63:26:56:35:1e:8b:ec:47: + 87:25:6e:bc:90:d0:8b:37:2d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 96:9A:2D:06:F6:76:4F:83:68:7B:9C:69:C4:18:BB:4A:EB:46:38:E4 + X509v3 Authority Key Identifier: + keyid:BA:8D:A1:97:DC:C4:39:1F:90:B5:51:6B:10:19:F2:46:0D:A9:65:8E + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 4 + serial:A2:93:46:74:3B:A6:E3:AD + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 45:77:ba:6b:b6:a7:2a:0f:6b:38:90:9f:0a:18:11:c7:54:7b: + c9:3b:9a:93:90:96:f0:04:0a:56:87:30:e0:f5:d8:84:40:39: + 90:85:ca:e7:38:1b:d8:df:2f:bd:73:91:13:cb:a6:c9:b0:7a: + f7:59:77:6b:9a:d5:86:78:06:dc:40:14:ce:ea:43:a8:ae:ed: + a2:03:64:51:3a:47:7a:9f:df:2d:65:49:56:a5:39:cf:28:2a: + ac:ab:fd:e1:93:fd:3e:56:e8:eb:7a:11:a8:f7:f9:1a:a1:83: + 1f:92:f7:da:4e:c6:d9:67:dd:67:ff:be:6f:e5:24:e1:6e:cc: + 94:3c +-----BEGIN CERTIFICATE----- +MIIDBjCCAm+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA0MB4XDTA5MTEyMDA4Mzcy +N1oXDTM0MTExNDA4MzcyN1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA0MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDasCGUibAAictpWZsN/h+5oKhEklVfC9XlCGO9R2sRTbGoEm/Bz8ue +ruLBA2hGWQuWfCFFmxSB2PGDcGs9tFZlSYcdq+IIaklmDlm02no/ciO4H/t49fAt +xP7ZlG4uw26Vujhg0Qv6FscCce8+cXJjJlY1HovsR4clbryQ0Is3LQIDAQABo4HH +MIHEMB0GA1UdDgQWBBSWmi0G9nZPg2h7nGnEGLtK60Y45DCBkQYDVR0jBIGJMIGG +gBS6jaGX3MQ5H5C1UWsQGfJGDalljqFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA0ggkAopNGdDum460wDwYDVR0TAQH/ +BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBFd7prtqcqD2s4kJ8KGBHHVHvJO5qT +kJbwBApWhzDg9diEQDmQhcrnOBvY3y+9c5ETy6bJsHr3WXdrmtWGeAbcQBTO6kOo +ru2iA2RROkd6n98tZUlWpTnPKCqsq/3hk/0+VujrehGo9/kaoYMfkvfaTsbZZ91n +/75v5SThbsyUPA== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/crlnumber new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/crlnumber @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/index.txt new file mode 100644 index 0000000000..88e41b76ac --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/index.txt @@ -0,0 +1,2 @@ +V 341114084401Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 1 Root 4 +R 341114085720Z 091120085929Z,keyCompromise 1001 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 2 Sub CA 1 Root 4 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/index.txt.attr new file mode 100644 index 0000000000..8f7e63a347 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/newcerts/1000.pem new file mode 100644 index 0000000000..73563ed969 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/newcerts/1000.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 4 + Validity + Not Before: Nov 20 08:44:01 2009 GMT + Not After : Nov 14 08:44:01 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 1 Root 4 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:c3:55:aa:1b:4f:f6:b4:78:be:ac:61:2a:92:94: + 73:1b:39:4c:0e:57:7e:da:78:03:7e:65:11:57:97: + e6:f4:0d:72:1f:f6:2b:a4:33:f9:5c:bd:2b:25:6c: + 58:29:73:b9:46:d5:db:e9:03:1d:a2:f8:8e:6e:c2: + b5:95:ec:ba:95:c3:ac:2e:c0:b6:40:ba:23:1d:74: + 75:91:cc:d6:3a:4c:15:4d:15:03:a4:e6:80:4a:93: + fe:6c:91:ab:77:60:3b:43:65:21:cd:04:3d:01:71: + 99:47:28:12:c8:9d:f9:d7:25:7a:30:82:76:c0:27: + 5e:c3:70:42:54:2a:0a:02:97 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + Netscape Comment: + OpenSSL Generated Certificate + X509v3 Subject Key Identifier: + D5:2F:1A:60:8E:F9:2E:8F:51:EB:F7:AB:24:47:80:CE:B6:8D:F1:63 + X509v3 Authority Key Identifier: + keyid:96:9A:2D:06:F6:76:4F:83:68:7B:9C:69:C4:18:BB:4A:EB:46:38:E4 + + Signature Algorithm: sha1WithRSAEncryption + 7a:83:0c:a0:2d:14:52:97:a1:0e:dd:b3:2e:a1:1f:0d:51:e7: + 98:2e:89:9a:36:a3:1b:af:28:95:13:ab:3e:31:2e:f6:fa:5f: + f7:85:8c:01:7a:1b:25:63:7e:d6:f9:8e:ad:84:9e:42:3e:1d: + f4:ad:dc:b1:20:91:83:8b:48:ad:34:2a:b9:cc:ae:06:e6:bc: + e1:05:e6:35:71:ca:43:98:3a:e5:93:52:e1:3c:3a:1b:83:53: + d3:a6:ba:6a:43:38:00:92:ba:fb:8f:a8:17:46:f9:32:ac:42: + 47:87:7f:2e:ae:76:49:88:55:1e:65:70:6c:d6:35:ab:64:48: + a9:66 +-----BEGIN CERTIFICATE----- +MIICyzCCAjSgAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA0MB4XDTA5 +MTEyMDA4NDQwMVoXDTM0MTExNDA4NDQwMVowbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAxIFN1YiBDQSAxIFJvb3QgNDCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAw1WqG0/2tHi+rGEqkpRzGzlMDld+2ngD +fmURV5fm9A1yH/YrpDP5XL0rJWxYKXO5RtXb6QMdoviObsK1ley6lcOsLsC2QLoj +HXR1kczWOkwVTRUDpOaASpP+bJGrd2A7Q2UhzQQ9AXGZRygSyJ351yV6MIJ2wCde +w3BCVCoKApcCAwEAAaN9MHswCwYDVR0PBAQDAgXgMCwGCWCGSAGG+EIBDQQfFh1P +cGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQU1S8aYI75Lo9R +6/erJEeAzraN8WMwHwYDVR0jBBgwFoAUlpotBvZ2T4Noe5xpxBi7SutGOOQwDQYJ +KoZIhvcNAQEFBQADgYEAeoMMoC0UUpehDt2zLqEfDVHnmC6JmjajG68olROrPjEu +9vpf94WMAXobJWN+1vmOrYSeQj4d9K3csSCRg4tIrTQqucyuBua84QXmNXHKQ5g6 +5ZNS4Tw6G4NT06a6akM4AJK6+4+oF0b5MqxCR4d/Lq52SYhVHmVwbNY1q2RIqWY= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/newcerts/1001.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/newcerts/1001.pem new file mode 100644 index 0000000000..7068aa0afd --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/newcerts/1001.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4097 (0x1001) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 4 + Validity + Not Before: Nov 20 08:57:20 2009 GMT + Not After : Nov 14 08:57:20 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 2 Sub CA 1 Root 4 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:ab:2a:df:93:6c:f0:b1:34:54:15:5b:06:4e:15: + bb:94:53:89:96:96:47:db:43:49:e7:66:d5:6b:53: + eb:04:54:d0:96:48:08:8f:8e:cc:70:e1:62:88:6a: + f3:ff:bc:65:55:b9:55:a6:29:22:c1:f6:16:9a:01: + 25:86:a9:72:c8:7c:0f:29:87:b9:14:51:34:d2:fc: + 01:3e:20:46:dc:54:3f:f3:03:d8:07:e0:6b:0c:78: + 70:d0:d0:93:83:e2:cf:53:fc:3b:d5:b0:c9:7d:40: + 8b:ee:5d:d3:30:e9:24:01:1e:b0:ac:de:1a:18:97: + a1:0d:58:79:5e:67:cd:99:bf + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + Netscape Comment: + OpenSSL Generated Certificate + X509v3 Subject Key Identifier: + 47:DB:A7:93:38:C2:0F:34:7F:B7:DE:35:C9:23:75:CC:30:93:A4:42 + X509v3 Authority Key Identifier: + keyid:96:9A:2D:06:F6:76:4F:83:68:7B:9C:69:C4:18:BB:4A:EB:46:38:E4 + + Signature Algorithm: sha1WithRSAEncryption + 97:70:47:74:ce:e1:f6:51:bf:cc:cf:0f:cf:cc:23:75:df:4b: + 3d:36:f0:70:0f:47:5d:c7:96:ad:b0:78:95:89:3a:2a:7a:ba: + 79:45:fe:2f:37:4c:69:76:ab:0a:10:ea:0d:5e:fe:28:04:44: + 9c:f3:8d:43:f5:15:fa:79:be:d3:86:f3:c1:b5:8b:5a:74:a9: + c5:b7:fe:e8:63:6e:1f:13:3a:c9:49:3b:45:0c:a6:64:b9:07: + 9b:1a:30:09:1d:5e:f0:2b:a9:55:aa:41:fa:85:0d:ef:dd:c3: + f5:58:52:bf:7f:6d:f4:18:06:f4:5a:71:af:e4:57:b0:0a:6e: + f6:76 +-----BEGIN CERTIFICATE----- +MIICyzCCAjSgAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA0MB4XDTA5 +MTEyMDA4NTcyMFoXDTM0MTExNDA4NTcyMFowbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAyIFN1YiBDQSAxIFJvb3QgNDCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAqyrfk2zwsTRUFVsGThW7lFOJlpZH20NJ +52bVa1PrBFTQlkgIj47McOFiiGrz/7xlVblVpikiwfYWmgElhqlyyHwPKYe5FFE0 +0vwBPiBG3FQ/8wPYB+BrDHhw0NCTg+LPU/w71bDJfUCL7l3TMOkkAR6wrN4aGJeh +DVh5XmfNmb8CAwEAAaN9MHswCwYDVR0PBAQDAgXgMCwGCWCGSAGG+EIBDQQfFh1P +cGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUR9unkzjCDzR/ +t941ySN1zDCTpEIwHwYDVR0jBBgwFoAUlpotBvZ2T4Noe5xpxBi7SutGOOQwDQYJ +KoZIhvcNAQEFBQADgYEAl3BHdM7h9lG/zM8Pz8wjdd9LPTbwcA9HXceWrbB4lYk6 +Knq6eUX+LzdMaXarChDqDV7+KAREnPONQ/UV+nm+04bzwbWLWnSpxbf+6GNuHxM6 +yUk7RQymZLkHmxowCR1e8CupVapB+oUN793D9VhSv39t9BgG9Fpxr+RXsApu9nY= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/private/cakey.pem new file mode 100644 index 0000000000..4c3de720f9 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,48187111D008BD14 + +9y5tseMMq8fPCuUelw75mRr1ALSrxNWatiMrmFM44I27wxIlaVgePNk3ovpuUpjB +RTArkp0zqA8tHCE/ZzE0cKtkxabTfrghxeKb2lAIrIUFwAFnMPEoB69M23qKblQD +/CbYquy6mpjzLBYwM0Ub8fj4d6fMCJ29Mqlbzj9XJ2oif8zW90lxE4CZNGEWKWaO +pF0ytqUM0aVIBVXZOGmeUpJlAgwdshYHD0JwoULWzFOa+9aks+wjYwQcDxbPq3YC +TBSzHiKd68YSDvK5VevIAIrSKEEqrXgsnL0k23/xkK5ZN8w9gmROrwpqg78Aa/cp +13luMYMRAm+hBfCFzKXvc8hV49UCPWOJcB4/p8to8Bx95UcJ17npG71yrNJgwTA6 +Wgj4pxtddt4QItVqv6usIvkMwD4pQqZ4y+5UMEvw2paG428+SN6YElH6/6yB/9Cc +B7BxhhaazM+AEulpvvfQgjpIqn5+QyaZ7GVcNh/Bi66tenNv9NBVqP1PmuZUMF77 +QddQGzCpxaSb/x/3InhMP2PgGN37B9ezm8ee+AQpmk1VzJ5zpiuoGbQ3oLnDVMKS +aNe7VIyhovq7tnJIuIft8jOEMFfPot9vgIwnHVQ4PF+KK0bzWjSK+6HyO+1Jkw/5 +TpHfQSxEVf8brC8g9l7+FjGSbHF80EzOUx1lMDe/BUzuVvRhiewqrlkCrPf90uuy +hEf1UKqrDK2i2iLBzZ0+OXba3wj20jFRaYLN5YykE6fKo/H6UjEn203nMI2Qi+2m +5j5dgDAOXnNWQN45MxIMu6xxPSaEcb8YUgfMqwytfVmo/xSioyoV+w== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/serial new file mode 100644 index 0000000000..7d802a3e71 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/serial @@ -0,0 +1 @@ +1002 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/openssl.cfg new file mode 100644 index 0000000000..51e5205253 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/README.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/README.txt new file mode 100644 index 0000000000..b266749a9e --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/README.txt @@ -0,0 +1,5 @@ +To provide the CRL via HTTP run + +java -jar ../../tools/httpserv/dist/httpserv.jar -a 8902 + + diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/cacert.pem new file mode 100644 index 0000000000..b350f6eb33 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/cacert.pem @@ -0,0 +1,66 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4097 (0x1001) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 5 + Validity + Not Before: Nov 20 11:30:23 2009 GMT + Not After : Nov 14 11:30:23 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 5 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:97:fa:a2:49:d3:bf:c1:2e:7a:ed:83:83:3c:78: + 96:c8:b2:b9:67:af:c0:5e:0a:89:89:fb:94:59:32: + a8:2a:e4:20:2f:3b:3d:ce:53:4f:72:fc:6c:0b:93: + 38:c3:df:66:6e:d5:79:d0:a4:4e:41:84:43:3c:99: + 79:0c:e0:5f:19:1a:3d:f5:4b:11:28:0f:80:b0:a0: + 71:34:5b:90:71:c2:ef:1e:85:2e:5b:9f:3b:22:c3: + 18:f8:7c:1f:ef:1b:78:17:a0:44:60:46:7e:88:eb: + a7:60:a0:5c:2a:7c:37:99:fa:27:97:08:e8:89:ba: + bc:69:4b:79:93:8f:ad:b5:9b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 01:E9:B5:99:E4:6D:F9:8C:42:3D:09:10:0F:A7:75:C6:27:78:4A:AF + X509v3 Authority Key Identifier: + keyid:C1:D1:A0:D4:5B:0B:9D:7E:31:61:F9:39:10:9F:31:10:E0:D2:06:B5 + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 5 + serial:F0:3D:B6:A9:A9:9C:A3:4E + + X509v3 CRL Distribution Points: + URI:http://localhost:8901/demoCA/crl/Root_5.crl + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 6d:ca:34:05:99:ff:99:49:d3:6d:9d:ad:c6:99:da:9d:6c:94: + 62:77:ed:1c:39:23:d2:e8:b6:3e:df:63:dc:7c:10:3f:c2:ed: + f4:04:26:58:05:01:4c:ed:a9:83:43:3a:5d:fe:60:6d:5b:58: + dc:93:8c:94:69:b6:7f:02:48:30:9c:31:f4:7d:de:e0:de:04: + d2:dc:79:b7:60:c2:87:f7:c7:92:a2:f5:86:a7:0c:70:3b:a3: + a7:35:11:cf:a4:28:21:aa:8b:24:50:2e:96:41:be:66:01:bd: + b9:ec:04:0c:92:d9:8a:e7:a0:96:24:9b:f1:a2:9f:59:59:4a: + 32:a4 +-----BEGIN CERTIFICATE----- +MIIDRjCCAq+gAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA1MB4XDTA5MTEyMDExMzAy +M1oXDTM0MTExNDExMzAyM1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA1MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQCX+qJJ07/BLnrtg4M8eJbIsrlnr8BeComJ+5RZMqgq5CAvOz3OU09y +/GwLkzjD32Zu1XnQpE5BhEM8mXkM4F8ZGj31SxEoD4CwoHE0W5Bxwu8ehS5bnzsi +wxj4fB/vG3gXoERgRn6I66dgoFwqfDeZ+ieXCOiJurxpS3mTj621mwIDAQABo4IB +BjCCAQIwHQYDVR0OBBYEFAHptZnkbfmMQj0JEA+ndcYneEqvMIGRBgNVHSMEgYkw +gYaAFMHRoNRbC51+MWH5ORCfMRDg0ga1oWOkYTBfMQswCQYDVQQGEwJERTEQMA4G +A1UECBMHSGFtYnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsT +C0RldmVsb3BtZW50MQ8wDQYDVQQDEwZSb290IDWCCQDwPbapqZyjTjA8BgNVHR8E +NTAzMDGgL6AthitodHRwOi8vbG9jYWxob3N0Ojg5MDEvZGVtb0NBL2NybC9Sb290 +XzUuY3JsMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAbco0BZn/ +mUnTbZ2txpnanWyUYnftHDkj0ui2Pt9j3HwQP8Lt9AQmWAUBTO2pg0M6Xf5gbVtY +3JOMlGm2fwJIMJwx9H3e4N4E0tx5t2DCh/fHkqL1hqcMcDujpzURz6QoIaqLJFAu +lkG+ZgG9uewEDJLZiuegliSb8aKfWVlKMqQ= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/crl/DO_NOT_INSTALL_THIS_CRL b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/crl/DO_NOT_INSTALL_THIS_CRL new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/crl/DO_NOT_INSTALL_THIS_CRL diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/crl/Sub_CA_1_Root_5.crl b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/crl/Sub_CA_1_Root_5.crl Binary files differnew file mode 100644 index 0000000000..3aec2bba1d --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/crl/Sub_CA_1_Root_5.crl diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/crlnumber new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/crlnumber @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/index.txt new file mode 100644 index 0000000000..2f83d6f9b7 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/index.txt @@ -0,0 +1 @@ +V 341114113322Z 1002 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 1 Root 5 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/index.txt.attr new file mode 100644 index 0000000000..8f7e63a347 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/newcerts/1002.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/newcerts/1002.pem new file mode 100644 index 0000000000..59d5f7a2b4 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/newcerts/1002.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4098 (0x1002) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 5 + Validity + Not Before: Nov 20 11:33:22 2009 GMT + Not After : Nov 14 11:33:22 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 1 Root 5 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:d3:fd:a7:4f:ea:02:e2:b4:32:80:3f:64:bb:37: + 9d:9e:fa:86:b2:25:b3:1d:f6:5d:05:8e:2b:0c:bd: + 60:1e:e6:52:39:4c:84:9e:93:6c:d2:b4:2d:34:1a: + e7:42:b6:bf:34:bd:ca:44:31:fb:06:5e:20:0a:a1: + 22:ca:9b:4f:01:57:bd:b1:30:57:a9:0f:fc:06:ae: + 18:6c:2d:9e:70:7a:21:2a:fd:0c:f8:03:00:32:60: + 5d:37:c5:11:56:74:30:e4:03:3c:88:71:d5:79:d3: + 76:02:e1:85:87:63:4b:5b:cd:c9:1f:ca:85:7a:8c: + 3a:fd:a9:83:94:b9:6d:f6:95 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 CRL Distribution Points: + URI:http://localhost:8902/demoCA/crl/Sub_CA_1_Root_5.crl + + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + E0:53:2E:E4:6B:0B:99:C0:AD:C1:02:40:46:6C:35:EE:49:73:5D:0B + X509v3 Authority Key Identifier: + keyid:01:E9:B5:99:E4:6D:F9:8C:42:3D:09:10:0F:A7:75:C6:27:78:4A:AF + + Signature Algorithm: sha1WithRSAEncryption + 5f:6a:81:3b:56:e8:6d:33:0e:1e:6a:73:b1:e8:69:b7:3f:83: + 81:6c:73:7c:9d:f7:12:c9:bf:99:16:cf:56:38:e4:58:db:28: + a5:9c:e3:8e:ed:27:d2:da:53:41:80:2a:d4:c3:92:5d:b5:b4: + 5a:d6:17:f7:74:9d:83:13:06:7f:20:8e:50:5f:60:5b:3a:9a: + 9f:c2:58:5f:fa:07:90:df:a0:02:cf:c4:d7:7d:2e:b7:72:df: + 8f:93:ce:5a:b3:17:ba:73:93:20:64:b9:b2:ad:6e:89:63:c5: + 08:e1:a0:6a:b2:9d:1e:33:31:83:98:d1:05:7d:ec:48:72:1f: + dd:60 +-----BEGIN CERTIFICATE----- +MIIC5jCCAk+gAwIBAgICEAIwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA1MB4XDTA5 +MTEyMDExMzMyMloXDTM0MTExNDExMzMyMlowbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAxIFN1YiBDQSAxIFJvb3QgNTCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0/2nT+oC4rQygD9kuzednvqGsiWzHfZd +BY4rDL1gHuZSOUyEnpNs0rQtNBrnQra/NL3KRDH7Bl4gCqEiyptPAVe9sTBXqQ/8 +Bq4YbC2ecHohKv0M+AMAMmBdN8URVnQw5AM8iHHVedN2AuGFh2NLW83JH8qFeow6 +/amDlLlt9pUCAwEAAaOBlzCBlDBFBgNVHR8EPjA8MDqgOKA2hjRodHRwOi8vbG9j +YWxob3N0Ojg5MDIvZGVtb0NBL2NybC9TdWJfQ0FfMV9Sb290XzUuY3JsMAsGA1Ud +DwQEAwIF4DAdBgNVHQ4EFgQU4FMu5GsLmcCtwQJARmw17klzXQswHwYDVR0jBBgw +FoAUAem1meRt+YxCPQkQD6d1xid4Sq8wDQYJKoZIhvcNAQEFBQADgYEAX2qBO1bo +bTMOHmpzsehptz+DgWxzfJ33Esm/mRbPVjjkWNsopZzjju0n0tpTQYAq1MOSXbW0 +WtYX93SdgxMGfyCOUF9gWzqan8JYX/oHkN+gAs/E130ut3Lfj5POWrMXunOTIGS5 +sq1uiWPFCOGgarKdHjMxg5jRBX3sSHIf3WA= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/private/cakey.pem new file mode 100644 index 0000000000..fb9af1caa3 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,30B50FFE9747C5F2 + +pXO59gJmBcDztjZDwRRcJV+m/BBdF/NlI0WD7WBr4vR663B6hZw0hqAkCn3o0VbO +DzLsoQUMUv/70aXc2SgvS8LleG+mWCkPE+huzFjPAn6Z6+p0MhHrYRJ7iulPAVV0 ++wCs8+1UbvKyozLy+BfvEwGHEho8sr3w81y2noE2pjaQOE1JGKY91VnFz1yPhYHC +r26sO1DqoqtWS8XSe2FdREG/guKpoHtoUazQhCkgeBk18OImKlrxp1pT/haObv5i +5qILjSvMBjmrTCJDi1vgShEiAZTE318ipK5wCLKiA6UvZ3GMxb2xjy+na3CUTrzf +AAefrW4NaoyIWI8dRtPxFic678ZgqcRMdMW7BgdffLXX5IueCqHeTNS7xcr2T2gd +hzKxinZnY8MQosFeyzP3fYWxv5PY54HNmCnsN2SXJSOq+CPSsIvbDR5p1bhrcEf9 +1O815NhJTx2nPAkIC+7bemAkz2f3g09SuhtQTaCnZMwcAmnMAT0ewWJSxDCVOg5s +B/OPe8RJ1tiO7DnaZH6RQDPUCKaUgS9xSzCu1q0IWWbzUWioPIX13fFlvl9gAxbY ++FI6dD2DwHBTyiPLLyT7FBfwjnHul2zSn/jXnby7n1sILQIP0AQK0cJDS1ZdC2CB +oe4gwzSVCxp7v3Zfp1ZoyYOtei0gT6+bDvjBYsl90jyvyucWfKjlZiEauQV8gSOQ +G2iY5QZ0clAFg7MQKmHuTaAALk0IrauSW20eR/HF0/2R6xCt91zcyhwbOiZFNyQ3 +gtvwLu9ZzAHfWcnIEWxpYF68O+vj+g6Jpl/q6j8KaTta3smEBzgpow== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/serial new file mode 100644 index 0000000000..baccd0398f --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/serial @@ -0,0 +1 @@ +1003 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/openssl.cfg new file mode 100644 index 0000000000..963ab884f6 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ +crlDistributionPoints=URI:http://localhost:8902/demoCA/crl/Sub_CA_1_Root_5.crl +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +#nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/cacert.pem new file mode 100644 index 0000000000..0490b88cd7 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/cacert.pem @@ -0,0 +1,66 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4097 (0x1001) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 6 + Validity + Not Before: Nov 20 12:28:07 2009 GMT + Not After : Nov 14 12:28:07 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 6 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:c4:d9:ab:27:06:66:41:0e:36:ff:d4:b1:d0:8c: + f7:b4:25:55:cd:fd:fa:a4:5a:e6:4f:d0:05:dc:a3: + e5:bd:8d:53:77:d1:ea:95:5a:52:81:c8:b6:36:a0: + 5f:3a:e1:85:1e:8a:48:91:7d:29:78:ff:ea:c5:e3: + ad:c4:27:d5:b7:8f:59:20:26:d4:45:87:6a:56:db: + ac:f5:f8:0a:88:82:9e:c2:00:06:fc:98:8a:fe:35: + c3:02:a1:67:08:06:42:e3:88:48:e0:8f:33:ff:f8: + a4:87:1a:3a:d9:54:0e:1c:09:3e:a0:f0:70:cd:b5: + b0:b2:7e:07:73:ad:20:64:69 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 89:8C:D7:71:EB:67:78:4E:D6:01:35:B2:AC:A1:B4:88:43:CE:70:A7 + X509v3 Authority Key Identifier: + keyid:AC:25:5E:9B:B5:BA:4D:8E:BD:77:B2:9D:D9:E2:84:AE:7A:31:8F:F2 + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 6 + serial:D8:6A:4F:24:F9:C9:94:27 + + X509v3 CRL Distribution Points: + URI:http://localhost:8901/demoCA/crl/Root_6.crl + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 55:5b:3b:6b:8a:d0:1b:d8:19:d9:96:85:4d:b4:a0:98:b1:bd: + 9f:0b:62:21:92:8b:4e:d3:d0:1b:91:3d:e3:f5:bd:ce:16:57: + fc:b7:84:15:51:fd:98:ab:32:59:28:0b:44:57:49:ec:ac:11: + 67:26:7a:a3:c5:b8:9d:2a:de:b6:7c:76:0a:e9:18:9f:98:87: + e8:80:c8:72:99:56:74:ab:73:1b:f4:e7:b9:b1:3a:f3:7b:0d: + 2f:5d:82:6c:d1:99:9f:23:be:23:fb:4c:0e:15:5e:f5:9f:90: + 88:d7:51:3a:6a:7a:f0:54:a5:c4:89:a5:0d:0a:4e:94:59:64: + 59:54 +-----BEGIN CERTIFICATE----- +MIIDRjCCAq+gAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA2MB4XDTA5MTEyMDEyMjgw +N1oXDTM0MTExNDEyMjgwN1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA2MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDE2asnBmZBDjb/1LHQjPe0JVXN/fqkWuZP0AXco+W9jVN30eqVWlKB +yLY2oF864YUeikiRfSl4/+rF463EJ9W3j1kgJtRFh2pW26z1+AqIgp7CAAb8mIr+ +NcMCoWcIBkLjiEjgjzP/+KSHGjrZVA4cCT6g8HDNtbCyfgdzrSBkaQIDAQABo4IB +BjCCAQIwHQYDVR0OBBYEFImM13HrZ3hO1gE1sqyhtIhDznCnMIGRBgNVHSMEgYkw +gYaAFKwlXpu1uk2OvXeyndnihK56MY/yoWOkYTBfMQswCQYDVQQGEwJERTEQMA4G +A1UECBMHSGFtYnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsT +C0RldmVsb3BtZW50MQ8wDQYDVQQDEwZSb290IDaCCQDYak8k+cmUJzA8BgNVHR8E +NTAzMDGgL6AthitodHRwOi8vbG9jYWxob3N0Ojg5MDEvZGVtb0NBL2NybC9Sb290 +XzYuY3JsMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAVVs7a4rQ +G9gZ2ZaFTbSgmLG9nwtiIZKLTtPQG5E94/W9zhZX/LeEFVH9mKsyWSgLRFdJ7KwR +ZyZ6o8W4nSretnx2CukYn5iH6IDIcplWdKtzG/TnubE683sNL12CbNGZnyO+I/tM +DhVe9Z+QiNdROmp68FSlxImlDQpOlFlkWVQ= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/crl/DO_NOT_CREATE_A_CRL b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/crl/DO_NOT_CREATE_A_CRL new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/crl/DO_NOT_CREATE_A_CRL diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/crlnumber new file mode 100644 index 0000000000..83b33d238d --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/crlnumber @@ -0,0 +1 @@ +1000 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/index.txt new file mode 100644 index 0000000000..6e4d7577df --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/index.txt @@ -0,0 +1 @@ +V 341114123743Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 1 Root 6 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/index.txt.attr new file mode 100644 index 0000000000..8f7e63a347 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/newcerts/1000.pem new file mode 100644 index 0000000000..538cb4e0bf --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/newcerts/1000.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 6 + Validity + Not Before: Nov 20 12:37:43 2009 GMT + Not After : Nov 14 12:37:43 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 1 Root 6 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:bb:ac:68:10:41:28:94:fd:fe:39:5e:63:cf:eb: + 9f:2b:20:82:f3:86:d2:e1:38:05:7e:95:cc:46:e5: + 42:8b:5c:0d:2c:ad:ad:44:c0:4c:2f:7c:75:e8:bd: + aa:cd:f2:05:16:18:a5:a3:fa:e7:a0:ba:57:31:e2: + b0:4d:85:9d:60:e4:41:92:49:3f:e1:79:47:52:e8: + 9e:71:be:88:10:6c:30:89:9f:55:84:9d:83:d0:c9: + 11:66:95:33:8b:44:38:86:45:05:b3:3a:54:c4:cf: + 4e:72:4c:00:07:d7:59:3a:8d:2f:cd:5e:0c:a0:95: + be:00:85:7a:a4:42:c2:f3:b7 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 CRL Distribution Points: + URI:http://localhost:8902/demoCA/crl/Sub_CA_1_Root_6.crl + + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 57:51:A4:44:AE:92:01:3C:9F:7E:82:67:C0:E5:B9:D7:A6:8F:A5:79 + X509v3 Authority Key Identifier: + keyid:89:8C:D7:71:EB:67:78:4E:D6:01:35:B2:AC:A1:B4:88:43:CE:70:A7 + + Signature Algorithm: sha1WithRSAEncryption + 7b:de:f2:2b:d7:94:ce:12:e2:f9:a7:b2:91:08:c6:51:3f:bc: + e2:87:ed:79:6d:3b:f5:38:6e:02:d4:63:e6:b8:a7:e5:df:f4: + 6e:b0:8a:bd:bb:b1:0b:e0:c2:cf:fa:af:0a:6a:a5:1f:28:ff: + de:21:bd:8a:f7:ec:48:35:bb:ab:97:c2:7a:31:6d:d1:73:8e: + ae:74:9b:94:86:73:06:06:da:6a:2c:82:04:b1:49:19:62:a9: + 05:e5:e7:2c:68:a1:3b:f4:bf:80:85:5b:1b:dc:21:7b:3d:c1: + ee:97:6c:72:35:2d:80:19:90:b4:ab:19:34:bb:88:5e:ea:70: + 27:df +-----BEGIN CERTIFICATE----- +MIIC5jCCAk+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA2MB4XDTA5 +MTEyMDEyMzc0M1oXDTM0MTExNDEyMzc0M1owbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAxIFN1YiBDQSAxIFJvb3QgNjCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAu6xoEEEolP3+OV5jz+ufKyCC84bS4TgF +fpXMRuVCi1wNLK2tRMBML3x16L2qzfIFFhilo/rnoLpXMeKwTYWdYORBkkk/4XlH +Uuiecb6IEGwwiZ9VhJ2D0MkRZpUzi0Q4hkUFszpUxM9OckwAB9dZOo0vzV4MoJW+ +AIV6pELC87cCAwEAAaOBlzCBlDBFBgNVHR8EPjA8MDqgOKA2hjRodHRwOi8vbG9j +YWxob3N0Ojg5MDIvZGVtb0NBL2NybC9TdWJfQ0FfMV9Sb290XzYuY3JsMAsGA1Ud +DwQEAwIF4DAdBgNVHQ4EFgQUV1GkRK6SATyffoJnwOW516aPpXkwHwYDVR0jBBgw +FoAUiYzXcetneE7WATWyrKG0iEPOcKcwDQYJKoZIhvcNAQEFBQADgYEAe97yK9eU +zhLi+aeykQjGUT+84ofteW079ThuAtRj5rin5d/0brCKvbuxC+DCz/qvCmqlHyj/ +3iG9ivfsSDW7q5fCejFt0XOOrnSblIZzBgbaaiyCBLFJGWKpBeXnLGihO/S/gIVb +G9whez3B7pdscjUtgBmQtKsZNLuIXupwJ98= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/private/cakey.pem new file mode 100644 index 0000000000..9912ee0880 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,8F1C89446B1EC221 + +joSSrVc7E1RavSuMdWDDAozXOV4Z0XIusMv5NjIWHLyKdW/SmFv6yfPy7PeuK1Qj +p/DuEO/ULU6SLmAhESXrdC8UzyL/B3hfPK3UzUzJzIRrDitF21SXLjMKU+KVxMrb +GkmstfsIQM157TZHOHJbk4F9zs9Xkl8ipKYDBpJrtVJo8gf4SeLfcEVXW9J0tlLU +Qi13SWWn4kGK+Latypx684S247Y0JfKSJ5BVHUGunmd+b/3mRpH1WARU03JmNqG9 +tyCJxyvCkkQh5Jnm4UEI72ywxSscemtFAzd5fa5LOrsVWOImSixfP1VdJvU0jCTv +gyXK03e/L+B+DhbUm2a6xkt+u83hQ2QjoGdmnfKwhX4vdYZBYINlBnHtHn2B8x2o +IXgLQmBFO/heY/K9wJ1BwwqPW31wHG3MhjRY7ooac1JAZsxS0/pU8cR/GNMpKjvE +fer3tGGUvPL3H1v3pT2XAA4Gm9pOtvnOHuLjbzg2mgNZScYMpcqa/vaQ5gXqCnhw +dtFrGVxEEQ5jTL23EAh4WfhPvsnewujr7Rkc6+a8xKpDJOHejgAPJYpXrYHg4poA +L0aQlIFSX1jriGu4KYAQiZO7bouhVWqcf9B3BNewr0kTaD7qq0gDvygCKLyrUyb7 +hqk0TwVfvmk7nYNFLBsTEcsB/el6jqH40oOfFo+ErlQzmdzRrKy9gBEaecDj8DxV +Fa8XPapE81O8WjS09a/WJNPW+3NdrI5wYMg72srOW8ll+AMtiUTWrAY2hIRxzZGt +VntCKwG/3j0v60jg+0wCP+l/IV4pPbV4He3ysxwM6lH1Y86XfaUBiA== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/serial new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/serial @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/openssl.cfg new file mode 100644 index 0000000000..188ed62e2a --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ +crlDistributionPoints=URI:http://localhost:8902/demoCA/crl/Sub_CA_1_Root_6.crl +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +#nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/README.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/README.txt new file mode 100644 index 0000000000..d70e0550a9 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/README.txt @@ -0,0 +1,3 @@ +To provide the CRL run: + +java -jar ../../tools/httpserv/dist/httpserv.jar -a 8902 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/cacert.pem new file mode 100644 index 0000000000..2dda8f2b28 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/cacert.pem @@ -0,0 +1,66 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 7 + Validity + Not Before: Nov 20 13:07:53 2009 GMT + Not After : Nov 14 13:07:53 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 7 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:b0:ae:6d:0a:21:ae:8a:92:b1:16:25:d3:08:cb: + ac:b7:4c:53:6d:4b:b3:12:82:40:54:c9:44:28:fc: + 4e:10:e6:65:40:de:70:5d:8b:ab:1f:5c:77:03:43: + 3d:3a:3d:9e:f7:37:66:9a:33:68:a0:cf:ad:8f:f4: + fb:9c:a3:87:57:5d:ec:d6:55:5a:18:b5:e1:2b:d2: + c4:10:fe:f0:01:a5:da:29:ee:c4:af:15:c9:8c:dc: + 7c:45:84:bd:e5:5b:09:1f:16:1d:11:e7:61:e6:22: + e7:1f:c8:86:bf:a1:da:cb:fe:6b:7e:c0:6e:aa:7f: + 97:84:e8:8f:81:69:f1:26:87 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 54:64:15:7E:93:8A:19:C8:F9:B7:EF:60:A0:DF:5C:C8:15:56:C0:EE + X509v3 Authority Key Identifier: + keyid:80:C6:F8:0B:5F:7C:49:E4:86:FD:C8:92:C6:80:70:D9:C0:6F:7B:DE + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 7 + serial:D5:E6:63:5F:18:09:82:89 + + X509v3 CRL Distribution Points: + URI:http://localhost:8901/demoCA/crl/Root_7.crl + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 1a:bc:5a:4b:9a:d5:e8:c0:35:c2:61:0a:58:7d:33:e2:87:01: + 61:83:80:42:8d:1a:7e:b1:9a:58:d5:01:fd:e7:ae:5c:c8:65: + fb:9e:1d:bf:49:ba:ed:40:f4:05:7c:3b:2d:db:0e:53:d0:05: + a0:bd:15:87:c4:37:22:0b:a0:04:a3:ad:cb:57:b2:00:97:ee: + 8f:89:91:8e:7d:0b:e2:27:96:6e:0f:ab:73:33:59:fa:9f:37: + f2:77:79:99:af:72:ad:f9:49:05:ed:55:08:31:eb:97:0f:99: + 6e:9c:a3:df:f0:52:1a:14:4e:78:25:0c:8b:02:cb:56:e9:4d: + f5:9f +-----BEGIN CERTIFICATE----- +MIIDRjCCAq+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA3MB4XDTA5MTEyMDEzMDc1 +M1oXDTM0MTExNDEzMDc1M1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA3MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQCwrm0KIa6KkrEWJdMIy6y3TFNtS7MSgkBUyUQo/E4Q5mVA3nBdi6sf +XHcDQz06PZ73N2aaM2igz62P9Puco4dXXezWVVoYteEr0sQQ/vABpdop7sSvFcmM +3HxFhL3lWwkfFh0R52HmIucfyIa/odrL/mt+wG6qf5eE6I+BafEmhwIDAQABo4IB +BjCCAQIwHQYDVR0OBBYEFFRkFX6TihnI+bfvYKDfXMgVVsDuMIGRBgNVHSMEgYkw +gYaAFIDG+AtffEnkhv3IksaAcNnAb3veoWOkYTBfMQswCQYDVQQGEwJERTEQMA4G +A1UECBMHSGFtYnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsT +C0RldmVsb3BtZW50MQ8wDQYDVQQDEwZSb290IDeCCQDV5mNfGAmCiTA8BgNVHR8E +NTAzMDGgL6AthitodHRwOi8vbG9jYWxob3N0Ojg5MDEvZGVtb0NBL2NybC9Sb290 +XzcuY3JsMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAGrxaS5rV +6MA1wmEKWH0z4ocBYYOAQo0afrGaWNUB/eeuXMhl+54dv0m67UD0BXw7LdsOU9AF +oL0Vh8Q3IgugBKOty1eyAJfuj4mRjn0L4ieWbg+rczNZ+p838nd5ma9yrflJBe1V +CDHrlw+Zbpyj3/BSGhROeCUMiwLLVulN9Z8= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/crl/DO_NOT_INSTALL_THIS_CRL b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/crl/DO_NOT_INSTALL_THIS_CRL new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/crl/DO_NOT_INSTALL_THIS_CRL diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/crl/Sub_CA_1_Root_7.crl b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/crl/Sub_CA_1_Root_7.crl Binary files differnew file mode 100644 index 0000000000..f3f7e5cba2 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/crl/Sub_CA_1_Root_7.crl diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/crlnumber new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/crlnumber @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/index.txt new file mode 100644 index 0000000000..8bcb130f6c --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/index.txt @@ -0,0 +1,2 @@ +V 341114131904Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 1 Root 7 +R 341114132648Z 091120132827Z,CACompromise 1001 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 2 Sub CA 1 Root 7 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/index.txt.attr new file mode 100644 index 0000000000..8f7e63a347 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/newcerts/1000.pem new file mode 100644 index 0000000000..234638d8ce --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/newcerts/1000.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 7 + Validity + Not Before: Nov 20 13:19:04 2009 GMT + Not After : Nov 14 13:19:04 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 1 Root 7 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:ce:23:98:19:ac:0d:7c:f0:60:a2:94:72:c3:ab: + a5:a1:6b:d3:af:8c:cb:b9:c9:ee:0b:3e:a4:2e:0e: + 08:a5:a9:4c:09:2f:1a:a0:fe:87:89:41:4a:aa:b6: + ac:b4:bc:d3:0e:f9:c3:12:1f:b1:90:b3:6d:72:a6: + 38:5b:9d:05:7e:97:ff:f4:e1:31:2b:b4:08:de:b1: + 43:fe:1d:7e:32:54:ce:db:d5:14:21:f3:ad:9f:26: + f3:c6:0b:77:51:e4:11:88:ad:86:e1:30:d1:af:87: + 29:c0:7b:92:db:68:06:74:ca:27:ac:0b:61:3a:ac: + ba:03:35:e7:8e:08:28:58:7d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 CRL Distribution Points: + URI:http://localhost:8902/demoCA/crl/Sub_CA_1_Root_7.crl + + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + DE:66:84:E4:9B:BF:70:00:BD:60:3D:34:45:96:FE:FD:D5:88:9B:CD + X509v3 Authority Key Identifier: + keyid:54:64:15:7E:93:8A:19:C8:F9:B7:EF:60:A0:DF:5C:C8:15:56:C0:EE + + Signature Algorithm: sha1WithRSAEncryption + 6e:da:66:d2:3b:00:d6:0b:5a:9f:21:28:de:e1:10:fe:fd:26: + db:a6:75:86:74:47:e4:b0:b7:c4:c1:dc:43:82:51:71:00:8f: + bf:71:9a:23:db:2d:79:27:a2:80:2e:12:a4:5f:13:0c:73:53: + 1e:5c:33:6a:e9:31:be:e2:ae:4f:55:b0:e8:0a:0f:54:f0:3a: + 7e:14:41:d7:34:18:58:90:26:63:7d:2c:1a:ab:93:7f:4a:3d: + 5e:cf:f1:9d:c3:76:ee:a4:76:1c:d8:f9:d0:ac:53:3c:1a:4d: + c7:fa:b6:23:54:4b:04:a1:e2:76:a5:e3:0d:b8:db:8e:d3:39: + c2:65 +-----BEGIN CERTIFICATE----- +MIIC5jCCAk+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA3MB4XDTA5 +MTEyMDEzMTkwNFoXDTM0MTExNDEzMTkwNFowbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAxIFN1YiBDQSAxIFJvb3QgNzCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAziOYGawNfPBgopRyw6uloWvTr4zLucnu +Cz6kLg4IpalMCS8aoP6HiUFKqrastLzTDvnDEh+xkLNtcqY4W50Ffpf/9OExK7QI +3rFD/h1+MlTO29UUIfOtnybzxgt3UeQRiK2G4TDRr4cpwHuS22gGdMonrAthOqy6 +AzXnjggoWH0CAwEAAaOBlzCBlDBFBgNVHR8EPjA8MDqgOKA2hjRodHRwOi8vbG9j +YWxob3N0Ojg5MDIvZGVtb0NBL2NybC9TdWJfQ0FfMV9Sb290XzcuY3JsMAsGA1Ud +DwQEAwIF4DAdBgNVHQ4EFgQU3maE5Ju/cAC9YD00RZb+/dWIm80wHwYDVR0jBBgw +FoAUVGQVfpOKGcj5t+9goN9cyBVWwO4wDQYJKoZIhvcNAQEFBQADgYEAbtpm0jsA +1gtanyEo3uEQ/v0m26Z1hnRH5LC3xMHcQ4JRcQCPv3GaI9steSeigC4SpF8TDHNT +HlwzaukxvuKuT1Ww6AoPVPA6fhRB1zQYWJAmY30sGquTf0o9Xs/xncN27qR2HNj5 +0KxTPBpNx/q2I1RLBKHidqXjDbjbjtM5wmU= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/newcerts/1001.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/newcerts/1001.pem new file mode 100644 index 0000000000..ddc504d77c --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/newcerts/1001.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4097 (0x1001) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 7 + Validity + Not Before: Nov 20 13:26:48 2009 GMT + Not After : Nov 14 13:26:48 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 2 Sub CA 1 Root 7 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:b3:58:b2:22:45:b9:37:83:e5:a4:6f:5d:4e:59: + 60:60:4e:46:26:27:9a:70:4d:34:89:cf:cb:4f:4f: + 0b:22:6e:e4:21:e6:ab:c9:0a:4a:c4:cd:6f:3c:db: + e8:a3:52:55:2d:26:1d:13:9a:8b:cf:38:25:4e:4f: + 4a:e3:39:01:fa:5b:10:a5:3e:e1:93:65:19:ca:8b: + 5c:9f:e8:19:ed:0a:ef:47:e9:11:73:28:ce:b0:95: + 10:3a:ce:b5:46:89:79:a3:90:ea:d5:ca:ac:c9:af: + ee:55:0d:6c:32:5f:d2:f1:76:1c:b9:e7:d2:ac:07: + 61:83:82:c5:95:5a:62:ff:67 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 CRL Distribution Points: + URI:http://localhost:8902/demoCA/crl/Sub_CA_1_Root_7.crl + + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 12:7A:7A:69:C5:FE:E0:23:FD:8E:51:25:55:94:9F:C8:44:D8:F2:29 + X509v3 Authority Key Identifier: + keyid:54:64:15:7E:93:8A:19:C8:F9:B7:EF:60:A0:DF:5C:C8:15:56:C0:EE + + Signature Algorithm: sha1WithRSAEncryption + 4a:57:08:6a:66:af:b4:05:4f:b3:4c:39:23:2b:5d:c9:88:7b: + 6f:b5:28:a3:5a:72:e6:0b:e2:9e:64:65:ce:8f:b5:31:0f:5f: + c7:b7:56:96:4f:d3:34:65:1a:ea:84:60:2b:fe:27:1f:75:fd: + 0f:53:e5:eb:25:d3:f6:2c:21:72:59:40:32:ba:ec:72:cc:64: + d6:1d:db:cf:ca:ec:91:0a:81:ef:f5:e4:56:31:a3:c2:9a:1d: + e9:5c:48:b0:7c:7b:e2:51:35:33:ad:a8:5c:79:ac:ee:bf:42: + fa:0b:a0:02:72:cc:5e:07:c0:d4:d3:96:26:16:3e:8c:32:8d: + b4:09 +-----BEGIN CERTIFICATE----- +MIIC5jCCAk+gAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA3MB4XDTA5 +MTEyMDEzMjY0OFoXDTM0MTExNDEzMjY0OFowbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAyIFN1YiBDQSAxIFJvb3QgNzCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAs1iyIkW5N4PlpG9dTllgYE5GJieacE00 +ic/LT08LIm7kIearyQpKxM1vPNvoo1JVLSYdE5qLzzglTk9K4zkB+lsQpT7hk2UZ +yotcn+gZ7QrvR+kRcyjOsJUQOs61Rol5o5Dq1cqsya/uVQ1sMl/S8XYcuefSrAdh +g4LFlVpi/2cCAwEAAaOBlzCBlDBFBgNVHR8EPjA8MDqgOKA2hjRodHRwOi8vbG9j +YWxob3N0Ojg5MDIvZGVtb0NBL2NybC9TdWJfQ0FfMV9Sb290XzcuY3JsMAsGA1Ud +DwQEAwIF4DAdBgNVHQ4EFgQUEnp6acX+4CP9jlElVZSfyETY8ikwHwYDVR0jBBgw +FoAUVGQVfpOKGcj5t+9goN9cyBVWwO4wDQYJKoZIhvcNAQEFBQADgYEASlcIamav +tAVPs0w5IytdyYh7b7Uoo1py5gvinmRlzo+1MQ9fx7dWlk/TNGUa6oRgK/4nH3X9 +D1Pl6yXT9iwhcllAMrrscsxk1h3bz8rskQqB7/XkVjGjwpod6VxIsHx74lE1M62o +XHms7r9C+gugAnLMXgfA1NOWJhY+jDKNtAk= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/private/cakey.pem new file mode 100644 index 0000000000..c107913a2f --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,D710D797627524D4 + +SC46mzOOSpNMZ9t2F3syLy0MmYOk3zBJnY/qcm/ggD4ETOse6zGpqhXVSeZdn3OG +Uwj+b9tCjVC/7GMWanH4DmshCv89IRljMyy5DShsOVmgAr0hqLZNlkKqQRRRHC4d +y9ozYq1J9Zcj16jTmCbpPJW8Ul7kblelNbD0nVgJABc6m6Di/syCFEC0KVGmoJZv +5QjxyNiulh0UNmmP+X6iEGPWw4s5JJdcAg5DFXjPiCvvGazvjCGTT38Hcnya4GkB +9aHo7KbjFU4P98zQKUAV0fSVU7+tzJrLxH0aefenbkIKI45xegOTJmcv8NEZ3YgQ +64r+OlmqOONmvcWrtUdhADvsl8oJ8Lz+1UYcyPpbYLUvMhj8Potf6C6rCz1GuQPS +EmGPltUAOcaylpnP/neyuErAMHGQI9Mn2dhLc/NGK6gxqZi1SawGbrit7Uv5il/n +O3zc7D+d1Jmdkcqm/BZKsMW5hwM3KF4gzb6zMe/8ZCmtqT4iH4eDqjFQfaWeBXNK +kTM8vMUNCU8yQjMYoWL8iL4NNJxRheD0l2FABcGTbWI159eXy8laenk5eBfYKIwl +YGnoylDD2F4W0mdMl2MJIYNYTRP7pAQhLnMbVNSgGDgk5Z0kUF2Kl2rNz+3w1c36 +L3VC/CGFp5/spnQHhYMH2oUAkliS0iev7bNJyhvycVQkMlwYu8KZKMtqyn9bnpU4 +Kd6XlXPwF3BHGrVVdcb6RQo65GrwT6j+hWRwUKgEvcxC7BjtsY1ZV3xRfsRQpA/b +1sTQ/W0ev09+OJAHWEedIg2sTTp5WSiF2whCz6yviFxEAeYIUEGVHw== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/serial new file mode 100644 index 0000000000..7d802a3e71 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/serial @@ -0,0 +1 @@ +1002 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/openssl.cfg new file mode 100644 index 0000000000..7cbc4664fa --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ +crlDistributionPoints=URI:http://localhost:8902/demoCA/crl/Sub_CA_1_Root_7.crl +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +#nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/README.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/README.txt new file mode 100644 index 0000000000..4d510fe39b --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/README.txt @@ -0,0 +1,13 @@ +Revoked certificates: + +- User 2 Sub CA 1 Root 8 + + +Start the OCSP responder: +openssl ocsp -index demoCA/index.txt -port 8889 -rsigner demoCA/cacert.pem -rkey demoCA/private/cakey.pem -CA demoCA/cacert.pem -text + + + + + + diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/cacert.pem new file mode 100644 index 0000000000..b2d1deb759 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/cacert.pem @@ -0,0 +1,66 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 8 + Validity + Not Before: Nov 20 15:33:21 2009 GMT + Not After : Nov 14 15:33:21 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 8 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:96:79:01:9f:4f:68:c1:09:0d:44:3a:82:e4:eb: + ad:70:7a:cf:b9:71:e5:fb:e0:c8:0c:21:79:3e:cb: + 78:91:7f:4a:a0:de:3e:37:0f:a1:6b:73:10:12:9b: + 08:c4:96:dc:cb:a8:5b:87:9b:75:24:e4:00:5e:4a: + 6f:4c:13:79:1f:57:13:8c:3e:1b:38:31:e1:77:74: + 52:f9:94:47:36:57:33:bd:de:08:11:a3:01:e1:53: + 1c:bd:7b:39:9c:5e:96:5c:a9:61:6c:cc:2b:90:8d: + 5a:3c:9e:f4:4b:6e:e5:97:64:86:f3:8e:e8:72:20: + 5d:0d:50:bf:e9:cf:be:d4:13 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + EF:BD:C8:8E:78:79:F9:76:4B:11:59:B6:C3:32:10:07:C0:BC:E3:8A + X509v3 Authority Key Identifier: + keyid:D6:66:76:C9:05:FF:A9:50:88:96:60:DD:FB:C7:30:18:72:67:41:19 + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 8 + serial:B2:47:DE:6A:2A:4C:83:19 + + Authority Information Access: + OCSP - URI:http://localhost:8888 + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 4c:95:44:3b:57:08:ec:01:ec:f9:3e:7c:89:1c:30:b1:4e:26: + 32:b6:57:fa:25:bc:ed:eb:d4:a2:1c:67:ee:b9:8b:d0:4c:57: + 8a:0e:db:a0:9d:92:e7:de:c6:73:01:e7:de:61:1b:b5:0e:d0: + c5:c1:a7:a6:ab:e0:c6:0b:51:dd:e5:a2:32:1f:c6:52:ea:d3: + 03:68:3a:f5:92:bd:8b:b8:03:bb:50:70:63:cc:ec:ed:3c:11: + 76:ca:ac:72:47:ad:99:6b:8e:07:9e:38:f2:63:e1:ba:d4:df: + a9:73:54:1d:74:89:94:01:2e:68:dd:97:e7:53:f9:cf:b6:7d: + fc:87 +-----BEGIN CERTIFICATE----- +MIIDOTCCAqKgAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA4MB4XDTA5MTEyMDE1MzMy +MVoXDTM0MTExNDE1MzMyMVowaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA4MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQCWeQGfT2jBCQ1EOoLk661wes+5ceX74MgMIXk+y3iRf0qg3j43D6Fr +cxASmwjEltzLqFuHm3Uk5ABeSm9ME3kfVxOMPhs4MeF3dFL5lEc2VzO93ggRowHh +Uxy9ezmcXpZcqWFszCuQjVo8nvRLbuWXZIbzjuhyIF0NUL/pz77UEwIDAQABo4H6 +MIH3MB0GA1UdDgQWBBTvvciOeHn5dksRWbbDMhAHwLzjijCBkQYDVR0jBIGJMIGG +gBTWZnbJBf+pUIiWYN37xzAYcmdBGaFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA4ggkAskfeaipMgxkwMQYIKwYBBQUH +AQEEJTAjMCEGCCsGAQUFBzABhhVodHRwOi8vbG9jYWxob3N0Ojg4ODgwDwYDVR0T +AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBMlUQ7VwjsAez5PnyJHDCxTiYy +tlf6Jbzt69SiHGfuuYvQTFeKDtugnZLn3sZzAefeYRu1DtDFwaemq+DGC1Hd5aIy +H8ZS6tMDaDr1kr2LuAO7UHBjzOztPBF2yqxyR62Za44HnjjyY+G61N+pc1QddImU +AS5o3ZfnU/nPtn38hw== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/crl/DO_NOT_INSTALL_THIS_CRL b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/crl/DO_NOT_INSTALL_THIS_CRL new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/crl/DO_NOT_INSTALL_THIS_CRL diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/crl/Sub_CA_1_Root_8.crl b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/crl/Sub_CA_1_Root_8.crl Binary files differnew file mode 100644 index 0000000000..7a9ee345ea --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/crl/Sub_CA_1_Root_8.crl diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/crlnumber new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/crlnumber @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/index.txt new file mode 100644 index 0000000000..ff1b3fe194 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/index.txt @@ -0,0 +1,2 @@ +V 341114154212Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 1 Root 8 +R 341114154716Z 091120155036Z,superseded 1001 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 2 Sub CA 1 Root 8 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/index.txt.attr new file mode 100644 index 0000000000..8f7e63a347 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/newcerts/1000.pem new file mode 100644 index 0000000000..71456d01b1 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/newcerts/1000.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 8 + Validity + Not Before: Nov 20 15:42:12 2009 GMT + Not After : Nov 14 15:42:12 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 1 Root 8 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:b6:aa:34:ec:31:e5:9a:aa:fe:90:31:1f:e5:83: + 90:cb:9a:9e:15:cd:bb:35:1b:fc:3c:8b:d9:3d:29: + de:f4:07:3f:4c:06:9b:4f:db:21:a2:4b:87:8b:fd: + b4:61:31:de:34:6c:14:10:f9:a7:7a:e0:0a:e9:bf: + b3:83:a3:35:44:f4:ad:c3:d0:60:e8:71:8e:6d:c0: + 70:9a:16:85:65:7a:82:68:7c:67:ee:57:31:6b:e8: + fd:f2:3f:5f:c7:ec:4e:db:e7:8a:98:d6:15:45:13: + 14:03:bc:4e:8a:03:48:c2:e4:aa:c5:32:cf:80:82: + 45:16:8b:63:37:4b:d5:7a:97 + Exponent: 65537 (0x10001) + X509v3 extensions: + Authority Information Access: + OCSP - URI:http://localhost:8889 + + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 4E:0B:28:05:B5:07:8F:77:1E:A6:37:CB:CC:F0:CB:09:A4:8C:4A:1E + X509v3 Authority Key Identifier: + keyid:EF:BD:C8:8E:78:79:F9:76:4B:11:59:B6:C3:32:10:07:C0:BC:E3:8A + + Signature Algorithm: sha1WithRSAEncryption + 3e:f7:c5:94:58:2f:18:c9:11:29:29:28:33:bb:e7:6c:70:7c: + f8:c7:60:4a:e5:37:f2:bb:78:d9:52:1e:c2:a3:dd:b1:7f:da: + e1:8a:8b:9c:7e:d6:ee:ec:ef:94:37:b5:b8:97:26:92:01:56: + 78:15:44:4b:95:4d:d9:59:12:b0:89:86:e4:b5:7d:b4:73:0f: + f1:0d:a8:04:69:e4:3f:2a:6a:65:b9:0e:9a:06:f7:16:29:94: + 4d:ac:64:ab:e9:0f:06:3c:74:fe:4c:e1:71:98:bd:9f:bb:c1: + 2d:47:70:6a:3c:b3:76:0b:fc:c8:05:d6:4e:bf:33:9f:dd:58: + 74:9c +-----BEGIN CERTIFICATE----- +MIIC0jCCAjugAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA4MB4XDTA5 +MTEyMDE1NDIxMloXDTM0MTExNDE1NDIxMlowbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAxIFN1YiBDQSAxIFJvb3QgODCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAtqo07DHlmqr+kDEf5YOQy5qeFc27NRv8 +PIvZPSne9Ac/TAabT9shokuHi/20YTHeNGwUEPmneuAK6b+zg6M1RPStw9Bg6HGO +bcBwmhaFZXqCaHxn7lcxa+j98j9fx+xO2+eKmNYVRRMUA7xOigNIwuSqxTLPgIJF +FotjN0vVepcCAwEAAaOBgzCBgDAxBggrBgEFBQcBAQQlMCMwIQYIKwYBBQUHMAGG +FWh0dHA6Ly9sb2NhbGhvc3Q6ODg4OTALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFE4L +KAW1B493HqY3y8zwywmkjEoeMB8GA1UdIwQYMBaAFO+9yI54efl2SxFZtsMyEAfA +vOOKMA0GCSqGSIb3DQEBBQUAA4GBAD73xZRYLxjJESkpKDO752xwfPjHYErlN/K7 +eNlSHsKj3bF/2uGKi5x+1u7s75Q3tbiXJpIBVngVREuVTdlZErCJhuS1fbRzD/EN +qARp5D8qamW5DpoG9xYplE2sZKvpDwY8dP5M4XGYvZ+7wS1HcGo8s3YL/MgF1k6/ +M5/dWHSc +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/newcerts/1001.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/newcerts/1001.pem new file mode 100644 index 0000000000..51102e24a5 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/newcerts/1001.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4097 (0x1001) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 8 + Validity + Not Before: Nov 20 15:47:16 2009 GMT + Not After : Nov 14 15:47:16 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 2 Sub CA 1 Root 8 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:a1:55:67:7e:e5:7a:62:eb:2b:36:45:fa:1d:4d: + c7:0e:6d:db:f6:54:65:4d:55:39:14:ea:c1:ad:75: + 1b:2f:2f:3c:6e:67:e0:6d:c6:76:66:0c:11:a2:89: + fe:70:3b:24:3e:0d:2a:13:9f:86:b4:8a:a3:27:50: + 52:77:1f:b8:7b:85:4e:36:94:68:4f:23:2c:f6:a1: + 0f:01:bc:6d:d4:e9:a4:54:12:15:37:bd:6c:ba:ad: + ed:78:ed:00:cc:be:a9:20:99:f5:a5:db:96:ba:cb: + 89:6b:ff:30:36:5c:84:77:a8:0d:28:d3:f8:20:99: + 01:4d:0f:8e:b3:8e:de:8d:09 + Exponent: 65537 (0x10001) + X509v3 extensions: + Authority Information Access: + OCSP - URI:http://localhost:8889 + + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + FC:DC:A7:1C:CE:D2:A9:DA:9A:76:9D:AE:8F:C8:1E:56:BA:D2:D5:D5 + X509v3 Authority Key Identifier: + keyid:EF:BD:C8:8E:78:79:F9:76:4B:11:59:B6:C3:32:10:07:C0:BC:E3:8A + + Signature Algorithm: sha1WithRSAEncryption + 87:30:ed:08:e6:03:fa:cf:65:5a:ed:9e:83:db:64:5f:bb:6b: + 5c:f3:db:8d:b7:d0:95:35:8c:f6:c1:1c:2c:d9:0c:0a:41:27: + f9:1f:e4:aa:25:95:59:3c:45:85:ac:0f:02:42:92:67:e2:09: + 45:d3:c1:7b:6e:db:42:84:7b:0d:57:47:f5:07:38:dd:cf:38: + ac:29:b9:14:79:2e:04:a5:a0:d6:71:be:fa:6d:9e:b5:cd:89: + 99:d1:47:58:56:81:8c:d4:b0:96:c6:dc:a7:1b:b0:ef:6b:0c: + 25:5f:92:b8:01:b7:74:f0:e3:49:eb:30:29:9f:f3:b5:bd:ae: + 45:99 +-----BEGIN CERTIFICATE----- +MIIC0jCCAjugAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA4MB4XDTA5 +MTEyMDE1NDcxNloXDTM0MTExNDE1NDcxNlowbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAyIFN1YiBDQSAxIFJvb3QgODCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAoVVnfuV6YusrNkX6HU3HDm3b9lRlTVU5 +FOrBrXUbLy88bmfgbcZ2ZgwRoon+cDskPg0qE5+GtIqjJ1BSdx+4e4VONpRoTyMs +9qEPAbxt1OmkVBIVN71suq3teO0AzL6pIJn1pduWusuJa/8wNlyEd6gNKNP4IJkB +TQ+Os47ejQkCAwEAAaOBgzCBgDAxBggrBgEFBQcBAQQlMCMwIQYIKwYBBQUHMAGG +FWh0dHA6Ly9sb2NhbGhvc3Q6ODg4OTALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFPzc +pxzO0qnamnadro/IHla60tXVMB8GA1UdIwQYMBaAFO+9yI54efl2SxFZtsMyEAfA +vOOKMA0GCSqGSIb3DQEBBQUAA4GBAIcw7QjmA/rPZVrtnoPbZF+7a1zz24230JU1 +jPbBHCzZDApBJ/kf5KollVk8RYWsDwJCkmfiCUXTwXtu20KEew1XR/UHON3POKwp +uRR5LgSloNZxvvptnrXNiZnRR1hWgYzUsJbG3KcbsO9rDCVfkrgBt3Tw40nrMCmf +87W9rkWZ +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/private/cakey.pem new file mode 100644 index 0000000000..6c934e3ec8 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,D40C0B2149B20A3E + +u5VzDci4c2i/pIElAbIAVT81F72A2V3fpvZv8yUpQRai5ZPzciSc4oYgavdu3tLV +p8bS+60akNpr3/ti7sB4tQBcql/3FMdKLFCgflJgCH9ivr2UrUSIJOyu9UNoG2ym +UcJrvCSAqtksL11VLMb3SJO7TRYxJ/xOl69Auf0R+aRwdof9nSBO4jDPTqvR/X8L +j/plBnw7ENO0ravRnEEEAEiSgx/z0LkhzAsPTkrrkNN5eZ+kR2Sk/Uo5aTx3FTpB +RU+iZQxmbNTrxCErfYvSnMJ4w6soT+Bzezwfn2tVGLwbur/3gtuNMEHJpL0Y2st9 +aRBHHF6+DlJ30rqNWCVV5ZY+2wMUEPBtcRftLdmh3caw/9aN/NqVUGuvqmhWyTt7 +TJmnKLJhE9NSztQM2PuV7ka9jWp5D6KLv0g+cbedpEOw6VjYL5e1EKt0AOu4Pp2r +HerL1ouRmpzIQLpskFTwkccjVDQm/H2fnB/nVrjdWxi/U4QJ0EPHL8iCyyox5np+ +3HilWBkpyBSvMOhyGfPkUucsMZA6O7/XhDcciBSsCJ4SSMa5gQmfYfixQHKRwixS +O5sJADUnJkbo4hyvrptAolM/JJU+HN8IYnq541mJ72dXbyodheedRPIOpTCiLQam +1Y04wfuIFMN4w98O0oMpCbqcDsOHysxN1XYg2kMzlxYbwooFC5cud5+cEW6d9FWQ +kpZ8Wkigno3ytjpUXWb9TmsRcMNiQdgxlpkvN/eYhk4xsUpwzhA/M/HTkLkn8WtC +52EwCv9KcxF31AA0lOeI+oNfcyMruwNXwEkFn3eD36axZQ8QjPHfhw== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/serial new file mode 100644 index 0000000000..7d802a3e71 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/serial @@ -0,0 +1 @@ +1002 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/openssl.cfg new file mode 100644 index 0000000000..571237e7da --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +authorityInfoAccess = OCSP;URI:http://localhost:8889 +#crlDistributionPoints=URI:http://localhost:8902/demoCA/crl/Sub_CA_2_Root_7.crl +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +#nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/cacert.pem new file mode 100644 index 0000000000..0b38d4db4c --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/cacert.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 9 + Validity + Not Before: Nov 23 13:59:19 2009 GMT + Not After : Nov 17 13:59:19 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 9 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:a9:6d:7f:6a:08:fb:e2:3a:5e:83:3f:ff:58:ba: + 92:a1:79:9d:ce:d2:0c:16:15:f2:7e:b3:e4:45:9c: + 02:32:65:9b:02:90:78:05:95:e4:04:1d:4a:05:bb: + ea:f6:ac:ab:15:74:c2:bc:ee:2a:c1:80:55:3e:93: + 1f:5c:94:eb:cf:cf:8f:15:eb:b8:22:fe:69:61:51: + a9:08:b8:80:bd:48:99:da:85:10:1c:75:97:fd:d3: + c3:c4:0b:dd:eb:01:12:5d:ee:62:62:c3:0c:18:ea: + ed:76:ff:9b:1c:1f:c7:81:f9:9a:cd:e5:25:89:b2: + 13:57:56:f3:27:53:72:76:69 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 7B:D3:57:BF:6A:CB:6C:10:81:91:DA:95:DC:88:4F:A5:D0:DB:D1:46 + X509v3 Authority Key Identifier: + keyid:CD:33:5E:AB:73:23:51:80:B8:03:AD:12:01:0B:C5:5E:8E:55:CA:64 + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 9 + serial:A4:DB:16:0D:4B:8C:D4:A6 + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 17:67:b0:21:da:0d:a1:fe:09:62:d0:cf:1d:c0:c8:bd:d4:22: + dd:75:ec:04:e2:23:ae:ea:8c:15:fa:73:2e:83:f4:16:eb:c1: + e1:87:36:bd:58:d0:64:e0:6e:2c:bc:27:cb:dc:4b:58:01:80: + 48:27:53:bb:75:85:a7:19:b8:e2:c0:1f:9f:a2:18:27:82:3f: + 25:bf:17:d1:34:32:de:c4:81:9d:8a:39:6f:6b:1f:b6:12:61: + 74:78:96:6d:6e:52:23:4a:67:30:78:03:91:b7:89:bf:3c:4a: + 36:e3:95:21:38:35:af:05:55:81:05:25:91:78:ca:2f:5d:79: + d2:05 +-----BEGIN CERTIFICATE----- +MIIDBjCCAm+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA5MB4XDTA5MTEyMzEzNTkx +OVoXDTM0MTExNzEzNTkxOVowaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA5MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQCpbX9qCPviOl6DP/9YupKheZ3O0gwWFfJ+s+RFnAIyZZsCkHgFleQE +HUoFu+r2rKsVdMK87irBgFU+kx9clOvPz48V67gi/mlhUakIuIC9SJnahRAcdZf9 +08PEC93rARJd7mJiwwwY6u12/5scH8eB+ZrN5SWJshNXVvMnU3J2aQIDAQABo4HH +MIHEMB0GA1UdDgQWBBR701e/astsEIGR2pXciE+l0NvRRjCBkQYDVR0jBIGJMIGG +gBTNM16rcyNRgLgDrRIBC8VejlXKZKFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA5ggkApNsWDUuM1KYwDwYDVR0TAQH/ +BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQAXZ7Ah2g2h/gli0M8dwMi91CLddewE +4iOu6owV+nMug/QW68Hhhza9WNBk4G4svCfL3EtYAYBIJ1O7dYWnGbjiwB+fohgn +gj8lvxfRNDLexIGdijlvax+2EmF0eJZtblIjSmcweAORt4m/PEo245UhODWvBVWB +BSWReMovXXnSBQ== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/crlnumber new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/crlnumber @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/index.txt new file mode 100644 index 0000000000..8c466eaffd --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/index.txt @@ -0,0 +1 @@ +V 341117140202Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 1 Root 9 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/index.txt.attr new file mode 100644 index 0000000000..8f7e63a347 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/newcerts/1000.pem new file mode 100644 index 0000000000..e3ca26a8a3 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/newcerts/1000.pem @@ -0,0 +1,58 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 9 + Validity + Not Before: Nov 23 14:02:02 2009 GMT + Not After : Nov 17 14:02:02 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 1 Root 9 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:f2:d3:15:3c:73:42:ce:22:e4:40:3a:6b:02:f6: + 59:bd:66:0d:87:91:f4:c0:be:a9:ce:33:21:09:d9: + 4e:4b:03:51:87:c3:e9:75:91:e9:80:5e:fc:a1:f7: + 43:9b:c6:32:af:6d:77:4b:b6:dc:b1:08:a3:1f:a0: + 6d:ec:81:12:23:48:36:2d:7a:5a:d0:88:88:49:7c: + ce:ae:98:45:d8:ff:9f:15:72:ab:b4:85:f6:a5:23: + af:43:e4:64:45:da:20:e1:e0:3e:f2:87:ea:67:ea: + 0e:08:8a:c8:1c:ef:85:a5:e6:f3:54:68:02:fd:de: + bc:4d:a2:eb:7d:0d:7d:80:59 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 1B:56:DD:11:CE:38:A0:97:FF:BE:39:9C:AF:F4:60:82:3A:CA:5D:51 + X509v3 Authority Key Identifier: + keyid:7B:D3:57:BF:6A:CB:6C:10:81:91:DA:95:DC:88:4F:A5:D0:DB:D1:46 + + Signature Algorithm: sha1WithRSAEncryption + 54:5e:40:1d:83:35:67:23:01:28:35:e3:02:7f:9e:9f:ce:83: + fb:45:dd:5c:96:62:f5:28:45:c8:90:2a:7e:84:88:e9:e9:b7: + 21:17:e0:3b:ea:de:6d:a1:d5:37:90:ae:15:86:30:7f:82:81: + d1:bb:ca:d2:6c:7c:39:2e:e9:65:57:2b:74:47:04:49:99:74: + 63:c7:03:cc:7d:f4:b0:6e:92:75:bb:aa:28:dc:71:d3:95:73: + 15:f4:4f:38:43:9e:4f:9f:e3:97:5c:8d:dc:1e:ad:ad:1e:b7: + c2:b2:ca:87:ee:8e:a2:93:12:60:95:1a:fb:bf:42:c8:31:48: + 8a:43 +-----BEGIN CERTIFICATE----- +MIICnTCCAgagAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA5MB4XDTA5 +MTEyMzE0MDIwMloXDTM0MTExNzE0MDIwMlowbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAxIFN1YiBDQSAxIFJvb3QgOTCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA8tMVPHNCziLkQDprAvZZvWYNh5H0wL6p +zjMhCdlOSwNRh8PpdZHpgF78ofdDm8Yyr213S7bcsQijH6Bt7IESI0g2LXpa0IiI +SXzOrphF2P+fFXKrtIX2pSOvQ+RkRdog4eA+8ofqZ+oOCIrIHO+FpebzVGgC/d68 +TaLrfQ19gFkCAwEAAaNPME0wCwYDVR0PBAQDAgXgMB0GA1UdDgQWBBQbVt0Rzjig +l/++OZyv9GCCOspdUTAfBgNVHSMEGDAWgBR701e/astsEIGR2pXciE+l0NvRRjAN +BgkqhkiG9w0BAQUFAAOBgQBUXkAdgzVnIwEoNeMCf56fzoP7Rd1clmL1KEXIkCp+ +hIjp6bchF+A76t5todU3kK4VhjB/goHRu8rSbHw5LullVyt0RwRJmXRjxwPMffSw +bpJ1u6oo3HHTlXMV9E84Q55Pn+OXXI3cHq2tHrfCssqH7o6ikxJglRr7v0LIMUiK +Qw== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/private/cakey.pem new file mode 100644 index 0000000000..be54b542a4 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,6D4A43A204C02659 + +ZPB/XY3gNrLz1f2DqTRkoZiL64CjVUEPw6ujRi/cAaMfAB+p32O/obtFbMyZWfpv +aLaoPmQH5hagNgsQqOW6OrSguxQ9i64Wv795TzRBrSYRHJ1as73AfDcS9aeI61AM +kiweFkVFAOPfgKOczYO152uXxtdRm4kpVr/CMsYuViE7966dzFvjDlY4vTDAD32+ +KJemzfjwsyErT/nYJaaabEkxxn+O3nwhgVqueoYWI8VeLYotFU41wO1NrOQvshs0 +tyrs5meiuSNPVuKagTltWfHv9PlMyVne7XYiRv1k7CIPmEansBge9/lY5KoPLHGQ +CHjuuwPykf6jnW7QG9IAGKRNPSdlMBpOT97EvKgNZ9I0FB4lSumhrxkjPHrRKz/J +usV+mEcGGYrfAb2OT0B/YSddOk1rCtKXpRVUMF8dzD7AyVxnU0Sdub6lwjNojAGh +Nb8exIFnVBM0/ka19xvlcdY0q9du7e0MuVvy8NhE0vkoqqDrUUnCP8iqg+uRBVts +0P7yk1lucsrNw8JQveLuiHm6zxN91iUAsBguwoOHG6szp3X9GLvvGhpQWPxTIOyo +obPMw6lY0y9MHY6eW9ekXVWGMZL2GDpIKLq9kqzLTqhY9kDw9OXYio4UYLl9vQG4 +Akr4ogzm8SKNQkPnGHprCdQV5J4V7fOa4HTNJb6NlTvMFuC99Sst+PYdE4RAn3sT +Jn+Lj2g0fDDSjvLNohmrT08DAYAAinbNt/+6gI975syPxuqxggrgfis4cliI7pf8 +ecmKIoSlbsJVCSfgd5a/d7e+9KwNuqBqopLu2vfgUN1YiFlEwAEQaQ== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/serial new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/serial @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/openssl.cfg new file mode 100644 index 0000000000..4a5b97f530 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8889 +#crlDistributionPoints=URI:http://localhost:8902/demoCA/crl/Sub_CA_2_Root_7.crl +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +#nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/README.txt b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/README.txt new file mode 100644 index 0000000000..e020f03a54 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/README.txt @@ -0,0 +1,4 @@ +Revoked certificates: + +- User 2 Sub CA 2 Root 4 + diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/cacert.pem new file mode 100644 index 0000000000..9d951ee267 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/cacert.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4097 (0x1001) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 4 + Validity + Not Before: Nov 20 09:22:27 2009 GMT + Not After : Nov 14 09:22:27 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 2 Root 4 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:e5:8d:27:4e:09:53:08:61:c6:23:25:9e:dd:9c: + 07:bf:81:38:5c:5c:10:8f:e4:12:2f:4e:2e:b1:a1: + cf:21:46:53:bf:e8:5e:de:17:3a:9d:f7:e8:ef:3e: + 9c:b4:29:37:4c:31:35:15:dc:98:e0:93:9c:ce:6a: + d6:e1:35:19:6b:d4:1d:3b:81:86:b1:e7:ff:1f:b8: + 34:a9:f9:de:4d:b8:62:ac:3b:d4:58:8e:5c:76:b5: + 07:7f:32:8a:3a:90:73:71:d5:da:f1:79:39:14:ed: + 1b:f1:8a:3e:be:48:bc:07:ec:f9:7c:03:14:fc:e7: + 55:a3:65:81:c7:6c:70:0b:ff + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 69:DE:B6:99:C4:95:F7:5A:FA:41:6B:4C:F6:C3:6D:89:AA:37:31:9D + X509v3 Authority Key Identifier: + keyid:BA:8D:A1:97:DC:C4:39:1F:90:B5:51:6B:10:19:F2:46:0D:A9:65:8E + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 4 + serial:A2:93:46:74:3B:A6:E3:AD + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + bc:cf:43:eb:72:b1:71:a7:94:8e:cd:5b:fc:d8:21:31:83:db: + a9:de:c7:5b:14:e5:7b:90:43:e6:05:df:db:6e:95:5f:24:ac: + 0c:a1:8a:ac:c6:cf:f2:03:cd:a0:30:ae:d3:a9:41:07:c9:b1: + be:4b:e0:fc:a2:76:09:07:75:6a:fa:e4:2f:a3:3a:cd:81:68: + ab:f6:06:c4:32:08:25:6e:e8:e7:36:9c:1a:f7:42:73:f8:b0: + d8:42:3e:85:c2:11:23:10:d6:6a:e4:8f:53:cb:8b:8b:1b:5a: + 4d:6d:9d:34:45:26:52:d2:ee:6d:8f:23:ff:00:92:f5:99:62: + 4c:41 +-----BEGIN CERTIFICATE----- +MIIDBjCCAm+gAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA0MB4XDTA5MTEyMDA5MjIy +N1oXDTM0MTExNDA5MjIyN1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDIgUm9vdCA0MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDljSdOCVMIYcYjJZ7dnAe/gThcXBCP5BIvTi6xoc8hRlO/6F7eFzqd +9+jvPpy0KTdMMTUV3Jjgk5zOatbhNRlr1B07gYax5/8fuDSp+d5NuGKsO9RYjlx2 +tQd/Moo6kHNx1drxeTkU7Rvxij6+SLwH7Pl8AxT851WjZYHHbHAL/wIDAQABo4HH +MIHEMB0GA1UdDgQWBBRp3raZxJX3WvpBa0z2w22JqjcxnTCBkQYDVR0jBIGJMIGG +gBS6jaGX3MQ5H5C1UWsQGfJGDalljqFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA0ggkAopNGdDum460wDwYDVR0TAQH/ +BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQC8z0PrcrFxp5SOzVv82CExg9up3sdb +FOV7kEPmBd/bbpVfJKwMoYqsxs/yA82gMK7TqUEHybG+S+D8onYJB3Vq+uQvozrN +gWir9gbEMgglbujnNpwa90Jz+LDYQj6FwhEjENZq5I9Ty4uLG1pNbZ00RSZS0u5t +jyP/AJL1mWJMQQ== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/crlnumber new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/crlnumber @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/index.txt new file mode 100644 index 0000000000..554a773b4a --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/index.txt @@ -0,0 +1,2 @@ +V 341114093339Z 1001 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 2 Root 4 +R 341114095105Z 091120095246Z,keyCompromise 1002 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 2 Sub CA 2 Root 4 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/index.txt.attr new file mode 100644 index 0000000000..8f7e63a347 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/newcerts/1001.pem b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/newcerts/1001.pem new file mode 100644 index 0000000000..3fbf2133fb --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/newcerts/1001.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4097 (0x1001) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 2 Root 4 + Validity + Not Before: Nov 20 09:33:39 2009 GMT + Not After : Nov 14 09:33:39 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 2 Root 4 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:c6:b2:8e:e4:f1:67:0b:07:3c:8c:b8:78:d9:79: + b1:2e:d5:10:c5:e8:76:9a:25:3f:dd:a3:0b:e0:3f: + 9f:50:87:e9:f1:15:74:86:ce:a0:01:07:b2:37:d0: + 74:dc:96:69:b4:f1:0e:cd:15:37:ca:ba:ed:ea:a3: + 99:ec:43:d4:ac:1c:8b:9b:18:d0:cd:80:78:49:80: + ca:e3:85:c6:2d:9a:15:02:73:d3:97:08:1d:4b:68: + 95:52:e6:92:57:c7:f6:76:0c:f1:a7:3d:90:10:0c: + 35:a8:9c:d3:e4:10:30:20:04:7f:ea:ad:ef:39:0c: + 65:05:43:f4:b6:51:3a:e7:95 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + Netscape Comment: + OpenSSL Generated Certificate + X509v3 Subject Key Identifier: + 79:C2:63:88:76:DF:C6:6F:BD:1D:AF:57:6E:87:08:AC:55:5D:AD:D1 + X509v3 Authority Key Identifier: + keyid:69:DE:B6:99:C4:95:F7:5A:FA:41:6B:4C:F6:C3:6D:89:AA:37:31:9D + + Signature Algorithm: sha1WithRSAEncryption + 07:68:5f:e9:01:bc:e4:d7:78:16:2b:19:7f:c2:9d:15:74:91: + ea:6d:fb:c9:ee:29:07:ff:62:e2:6a:85:5e:85:7d:5f:b4:bc: + 48:e1:89:24:3e:03:21:42:c1:10:3f:c6:41:7e:04:30:86:db: + c5:7e:7e:9f:04:49:a0:1e:fc:93:8e:b3:d1:cf:39:e3:41:89: + c3:06:51:3f:15:d5:02:49:2a:0b:15:d1:25:30:12:b6:2a:f9: + 03:06:f1:03:84:ae:4e:86:e1:dc:e6:a3:36:a4:27:24:2b:db: + 3a:3c:15:48:6f:c7:9f:ce:38:34:06:94:e3:d3:64:f7:4d:9e: + b6:c0 +-----BEGIN CERTIFICATE----- +MIICyzCCAjSgAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDIgUm9vdCA0MB4XDTA5 +MTEyMDA5MzMzOVoXDTM0MTExNDA5MzMzOVowbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAxIFN1YiBDQSAyIFJvb3QgNDCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAxrKO5PFnCwc8jLh42XmxLtUQxeh2miU/ +3aML4D+fUIfp8RV0hs6gAQeyN9B03JZptPEOzRU3yrrt6qOZ7EPUrByLmxjQzYB4 +SYDK44XGLZoVAnPTlwgdS2iVUuaSV8f2dgzxpz2QEAw1qJzT5BAwIAR/6q3vOQxl +BUP0tlE655UCAwEAAaN9MHswCwYDVR0PBAQDAgXgMCwGCWCGSAGG+EIBDQQfFh1P +cGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUecJjiHbfxm+9 +Ha9XbocIrFVdrdEwHwYDVR0jBBgwFoAUad62mcSV91r6QWtM9sNtiao3MZ0wDQYJ +KoZIhvcNAQEFBQADgYEAB2hf6QG85Nd4FisZf8KdFXSR6m37ye4pB/9i4mqFXoV9 +X7S8SOGJJD4DIULBED/GQX4EMIbbxX5+nwRJoB78k46z0c8540GJwwZRPxXVAkkq +CxXRJTAStir5AwbxA4SuTobh3OajNqQnJCvbOjwVSG/Hn844NAaU49Nk902etsA= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/newcerts/1002.pem b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/newcerts/1002.pem new file mode 100644 index 0000000000..595fbbfafb --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/newcerts/1002.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4098 (0x1002) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 2 Root 4 + Validity + Not Before: Nov 20 09:51:05 2009 GMT + Not After : Nov 14 09:51:05 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 2 Sub CA 2 Root 4 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:f5:2d:4a:b8:5d:39:da:58:5c:3c:a5:7d:4c:98: + b8:32:db:43:a0:13:cb:25:f8:5b:0b:6a:f2:e0:8d: + de:8f:c6:ea:c5:1c:03:bf:e0:b1:c9:14:a4:85:4b: + ed:95:87:f7:88:88:86:9e:65:3d:6e:e8:c5:be:17: + e6:9b:09:8e:44:c1:0a:20:00:ae:b4:3d:ba:68:9f: + 3e:ea:76:3c:96:64:ee:a7:91:65:31:03:f5:fd:01: + e5:60:a0:5e:62:a0:37:7b:db:cf:71:78:58:cc:dd: + 74:fc:b3:b1:2e:6b:f3:ec:ad:ac:75:ae:d8:d6:42: + 28:0a:20:68:8d:20:4a:30:61 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + Netscape Comment: + OpenSSL Generated Certificate + X509v3 Subject Key Identifier: + 32:E4:11:DF:CD:54:D6:80:67:68:85:36:A0:C5:14:88:D6:85:DB:C9 + X509v3 Authority Key Identifier: + keyid:69:DE:B6:99:C4:95:F7:5A:FA:41:6B:4C:F6:C3:6D:89:AA:37:31:9D + + Signature Algorithm: sha1WithRSAEncryption + e1:c2:5d:63:42:27:f4:df:a2:f0:f5:61:c3:e3:ac:f7:b6:29: + a9:dd:34:63:0c:cc:c9:7b:5c:1b:ac:77:8f:1a:e1:f4:3b:c8: + 96:8a:89:f6:c0:f0:c4:3b:bd:6e:b7:e7:84:5c:38:4f:d3:66: + 55:d6:d3:f8:70:1f:14:ce:9f:d3:04:68:be:6b:81:fc:6c:b6: + 2f:31:3d:de:2a:4e:6c:66:c0:c2:09:c8:ef:be:c4:88:39:28: + e8:62:da:44:63:f4:5c:f4:bb:cf:4b:54:c9:c0:ce:b4:27:7b: + 1e:9c:2f:90:9e:18:da:8a:27:af:e5:37:ea:3f:99:86:f8:5d: + d1:cb +-----BEGIN CERTIFICATE----- +MIICyzCCAjSgAwIBAgICEAIwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDIgUm9vdCA0MB4XDTA5 +MTEyMDA5NTEwNVoXDTM0MTExNDA5NTEwNVowbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAyIFN1YiBDQSAyIFJvb3QgNDCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA9S1KuF052lhcPKV9TJi4MttDoBPLJfhb +C2ry4I3ej8bqxRwDv+CxyRSkhUvtlYf3iIiGnmU9bujFvhfmmwmORMEKIACutD26 +aJ8+6nY8lmTup5FlMQP1/QHlYKBeYqA3e9vPcXhYzN10/LOxLmvz7K2sda7Y1kIo +CiBojSBKMGECAwEAAaN9MHswCwYDVR0PBAQDAgXgMCwGCWCGSAGG+EIBDQQfFh1P +cGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUMuQR381U1oBn +aIU2oMUUiNaF28kwHwYDVR0jBBgwFoAUad62mcSV91r6QWtM9sNtiao3MZ0wDQYJ +KoZIhvcNAQEFBQADgYEA4cJdY0In9N+i8PVhw+Os97Ypqd00YwzMyXtcG6x3jxrh +9DvIloqJ9sDwxDu9brfnhFw4T9NmVdbT+HAfFM6f0wRovmuB/Gy2LzE93ipObGbA +wgnI777EiDko6GLaRGP0XPS7z0tUycDOtCd7HpwvkJ4Y2oonr+U36j+Zhvhd0cs= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/private/cakey.pem new file mode 100644 index 0000000000..a8f9640c8a --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,1BD121CFCC6764E4 + +k3SMhf7UEWvpfhEyvd7Zc6kJFmiZ1JTg7KAawQhFhoRbGIVA1rSmRbuBdJm4XdQ5 +OxEAC5bVx5o3yxyhGmEkZr1dkGXkzQ1tc2a4Exf2p0O5zjlHUaxd2A4/mRYVAT0e +LAIQ+D+yqSd2wmLkLaz3EGGlfIPS8amTpnhSOvai40NjbLlRpw5DqDP/2KVWp7jH +T4JNzU33Xd6QuBsTSWyXuhIEeuzyrDbou0LceHIZSaa8Jqvp3yKX6OBTUdCNakwR +QtLLag63ie87qEhqeHg2VvZuVVEyhNCjPf2zRfxsCx742wI4TyY28JpxjYlFzJxX +Zd9toqIGFwritEOcr6wAqVX7NlE8/dDFFdEK9fPuv/jLoOYCCwDRvIMgDTE76c1k +foRMDMmqe0KcMdp+fbcfNDnV/U8gle2902AbEOXJLhdDEVUG/LCwrnIeUrfMOKiY +LwPysGwVndUb3uTFJ2e+PqV9i96G+ewpN9/hI9fThE12t8rhkpIsozEMl7WsBMgD +tdKrA5l7eibshCpk+zkIwGhkdMYXhj7hmioWWBJeMdJ93Ba8f91kt1IvI+J2Mn2K +1/5D0ZKEGPoTSAlEgMZ888sYWkT6WMk0UXH2Nq8BqdrrSTUypY2Uz0nDbWvhLrCf +zac6RZu9TtFsKAY6CQnXHFUJ+dvRmcSNQMhrIKS2VZ2UkL2oXASzXW2c9Hx6LO7T +WHuR7bXZiJhI63gUGI9pMRCs5NoRuXdg3KutzSTy8EWKJDXDKcvTemiomUZFB6i5 +zduXL73Wf/VjMcs7iOAijd7czGre0LBwyvgeNUAK2gj7SaGkR3bPZg== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/serial new file mode 100644 index 0000000000..baccd0398f --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/serial @@ -0,0 +1 @@ +1003 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/openssl.cfg new file mode 100644 index 0000000000..51e5205253 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/README.txt b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/README.txt new file mode 100644 index 0000000000..e04f69532d --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/README.txt @@ -0,0 +1,12 @@ +Revoked certificates: + +- User 2 Sub 2 Root 7 + + +To provide the CRL via HTTP run + +java -jar ../../tools/httpserv/dist/httpserv.jar -a 8902 + + + + diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/cacert.pem new file mode 100644 index 0000000000..0d2a0f02a3 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/cacert.pem @@ -0,0 +1,66 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4097 (0x1001) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 7 + Validity + Not Before: Nov 20 13:35:06 2009 GMT + Not After : Nov 14 13:35:06 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 2 Root 7 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:f9:3f:5e:76:52:9a:ce:5d:98:b0:00:d8:e0:65: + e7:78:11:4c:7b:c7:e2:d3:44:bf:8e:60:42:69:3e: + 75:67:65:24:ab:f7:07:d8:9d:be:0f:23:b5:c1:26: + 00:6b:c3:22:84:72:a9:96:dc:5f:63:fc:f5:e0:e3: + cc:da:0c:74:e9:31:51:91:89:27:8f:e5:17:41:6e: + 3d:5e:2a:13:cd:08:f7:f3:61:34:a1:f7:79:c6:bd: + 5d:2c:34:01:ea:5a:8c:48:97:36:d6:57:e0:80:03: + 2e:7a:03:83:4c:bd:b4:af:a2:fd:d7:4b:1a:f7:ab: + 9f:5a:22:2b:d1:25:73:dd:6f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 3B:50:26:45:6C:E2:FE:28:B1:71:0A:A8:95:2D:78:63:8E:2C:48:92 + X509v3 Authority Key Identifier: + keyid:80:C6:F8:0B:5F:7C:49:E4:86:FD:C8:92:C6:80:70:D9:C0:6F:7B:DE + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 7 + serial:D5:E6:63:5F:18:09:82:89 + + X509v3 CRL Distribution Points: + URI:http://localhost:8901/demoCA/crl/Root_7.crl + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 5f:b4:70:11:4f:d9:df:6a:6a:5a:4a:97:fe:8b:5d:9e:46:84: + e2:27:67:41:7c:a9:2e:9d:77:cc:e4:8c:d6:16:3c:39:7d:51: + 29:60:80:32:4f:a1:d0:b4:7f:2a:e5:60:f4:b8:d3:3b:94:f8: + a5:fb:15:99:cf:a9:c5:a7:59:c1:11:89:67:11:9c:ff:a9:ac: + dd:ca:a9:92:a8:60:26:c3:ab:74:41:86:b9:4d:1e:4a:c5:de: + 63:e6:da:2a:36:39:7b:6c:66:f3:20:57:d1:f1:36:4b:69:c5: + 04:a3:1f:cf:de:0c:10:d0:3f:07:e2:8e:0f:cd:41:26:c9:2e: + e9:1b +-----BEGIN CERTIFICATE----- +MIIDRjCCAq+gAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA3MB4XDTA5MTEyMDEzMzUw +NloXDTM0MTExNDEzMzUwNlowaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDIgUm9vdCA3MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQD5P152UprOXZiwANjgZed4EUx7x+LTRL+OYEJpPnVnZSSr9wfYnb4P +I7XBJgBrwyKEcqmW3F9j/PXg48zaDHTpMVGRiSeP5RdBbj1eKhPNCPfzYTSh93nG +vV0sNAHqWoxIlzbWV+CAAy56A4NMvbSvov3XSxr3q59aIivRJXPdbwIDAQABo4IB +BjCCAQIwHQYDVR0OBBYEFDtQJkVs4v4osXEKqJUteGOOLEiSMIGRBgNVHSMEgYkw +gYaAFIDG+AtffEnkhv3IksaAcNnAb3veoWOkYTBfMQswCQYDVQQGEwJERTEQMA4G +A1UECBMHSGFtYnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsT +C0RldmVsb3BtZW50MQ8wDQYDVQQDEwZSb290IDeCCQDV5mNfGAmCiTA8BgNVHR8E +NTAzMDGgL6AthitodHRwOi8vbG9jYWxob3N0Ojg5MDEvZGVtb0NBL2NybC9Sb290 +XzcuY3JsMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAX7RwEU/Z +32pqWkqX/otdnkaE4idnQXypLp13zOSM1hY8OX1RKWCAMk+h0LR/KuVg9LjTO5T4 +pfsVmc+pxadZwRGJZxGc/6ms3cqpkqhgJsOrdEGGuU0eSsXeY+baKjY5e2xm8yBX +0fE2S2nFBKMfz94MENA/B+KOD81BJsku6Rs= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/crl/DO_NOT_INSTALL_THIS_CRL b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/crl/DO_NOT_INSTALL_THIS_CRL new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/crl/DO_NOT_INSTALL_THIS_CRL diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/crl/Sub_CA_2_Root_7.crl b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/crl/Sub_CA_2_Root_7.crl Binary files differnew file mode 100644 index 0000000000..c4dd13d839 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/crl/Sub_CA_2_Root_7.crl diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/crlnumber new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/crlnumber @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/index.txt new file mode 100644 index 0000000000..a5e282ddd1 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/index.txt @@ -0,0 +1,2 @@ +V 341114134608Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 2 Root 7 +R 341114135230Z 091120135413Z,CACompromise 1001 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 2 Sub CA 2 Root 7 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/index.txt.attr new file mode 100644 index 0000000000..8f7e63a347 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/newcerts/1000.pem new file mode 100644 index 0000000000..ff1f1fa667 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/newcerts/1000.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 2 Root 7 + Validity + Not Before: Nov 20 13:46:08 2009 GMT + Not After : Nov 14 13:46:08 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 2 Root 7 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:a7:6b:af:a2:6e:61:33:2e:71:7b:e2:38:44:d9: + 4c:da:6e:86:bb:c6:f5:64:8e:2e:8b:e8:71:c8:46: + ad:c5:46:05:d2:06:a6:89:e2:ce:1f:1c:a7:4c:94: + a4:24:56:93:07:b1:c4:52:44:69:27:0b:34:eb:31: + 20:71:63:5c:0a:33:aa:0c:39:71:ac:08:49:c3:66: + ac:cb:e3:a8:66:ab:5c:a2:00:7a:bb:24:e6:93:91: + 1e:0e:7c:83:9e:f2:10:87:3f:0e:c0:f6:e5:bf:2c: + d3:cc:17:4c:d5:9a:96:35:4b:4e:ca:72:3a:9b:90: + c8:4c:24:04:2f:51:99:20:95 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 CRL Distribution Points: + URI:http://localhost:8902/demoCA/crl/Sub_CA_2_Root_7.crl + + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 27:98:7E:F6:AD:82:6D:F4:7A:32:AE:F1:54:D1:07:AE:08:0E:0E:2B + X509v3 Authority Key Identifier: + keyid:3B:50:26:45:6C:E2:FE:28:B1:71:0A:A8:95:2D:78:63:8E:2C:48:92 + + Signature Algorithm: sha1WithRSAEncryption + 06:7d:0a:e8:fa:8b:87:1d:75:61:2b:c7:d1:6d:56:5f:26:e3: + 29:b4:c3:27:05:35:0f:b7:c1:20:42:95:0b:9d:34:16:5d:9b: + c2:48:c8:67:e1:e7:43:eb:10:9e:45:3e:44:da:7c:4b:19:05: + 00:66:91:83:ea:82:86:48:e8:87:ea:a0:9f:c9:1d:f8:af:13: + fd:2e:4e:50:7e:a0:d2:b0:5e:a4:6f:dd:e6:c8:11:60:bc:41: + e5:b6:01:4c:7a:af:32:f6:cc:5b:57:e6:e4:87:21:ec:17:98: + 67:eb:4d:2f:07:db:8f:70:e2:f3:77:8f:c7:ff:60:d6:d9:f7: + 82:e3 +-----BEGIN CERTIFICATE----- +MIIC5jCCAk+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDIgUm9vdCA3MB4XDTA5 +MTEyMDEzNDYwOFoXDTM0MTExNDEzNDYwOFowbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAxIFN1YiBDQSAyIFJvb3QgNzCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAp2uvom5hMy5xe+I4RNlM2m6Gu8b1ZI4u +i+hxyEatxUYF0gamieLOHxynTJSkJFaTB7HEUkRpJws06zEgcWNcCjOqDDlxrAhJ +w2asy+OoZqtcogB6uyTmk5EeDnyDnvIQhz8OwPblvyzTzBdM1ZqWNUtOynI6m5DI +TCQEL1GZIJUCAwEAAaOBlzCBlDBFBgNVHR8EPjA8MDqgOKA2hjRodHRwOi8vbG9j +YWxob3N0Ojg5MDIvZGVtb0NBL2NybC9TdWJfQ0FfMl9Sb290XzcuY3JsMAsGA1Ud +DwQEAwIF4DAdBgNVHQ4EFgQUJ5h+9q2CbfR6Mq7xVNEHrggODiswHwYDVR0jBBgw +FoAUO1AmRWzi/iixcQqolS14Y44sSJIwDQYJKoZIhvcNAQEFBQADgYEABn0K6PqL +hx11YSvH0W1WXybjKbTDJwU1D7fBIEKVC500Fl2bwkjIZ+HnQ+sQnkU+RNp8SxkF +AGaRg+qChkjoh+qgn8kd+K8T/S5OUH6g0rBepG/d5sgRYLxB5bYBTHqvMvbMW1fm +5Ich7BeYZ+tNLwfbj3Di83ePx/9g1tn3guM= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/newcerts/1001.pem b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/newcerts/1001.pem new file mode 100644 index 0000000000..f16cdf4aab --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/newcerts/1001.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4097 (0x1001) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 2 Root 7 + Validity + Not Before: Nov 20 13:52:30 2009 GMT + Not After : Nov 14 13:52:30 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 2 Sub CA 2 Root 7 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:d3:1f:7e:28:b6:fd:f0:bb:01:21:88:04:c4:da: + 3d:6a:ce:09:8e:04:29:a5:0f:38:db:74:d0:ee:ad: + 5c:95:79:16:11:c0:b1:51:69:95:bb:a8:8f:8b:1c: + 7b:8c:82:27:16:21:82:82:d7:36:6f:b3:bb:36:a8: + ad:69:e2:e3:cd:6f:ef:81:ac:fa:e3:a9:ac:86:b7: + 31:1d:75:11:a3:2e:1d:89:0b:9c:5e:03:45:7a:b0: + a9:9d:ee:31:f1:15:c1:c5:f6:26:8e:d4:89:72:8f: + f4:86:94:d1:49:37:24:56:84:10:db:cc:f2:1d:3e: + 58:66:97:b2:17:6f:15:cb:81 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 CRL Distribution Points: + URI:http://localhost:8902/demoCA/crl/Sub_CA_2_Root_7.crl + + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + CD:A2:AE:51:D0:CF:A2:89:3A:53:23:74:1D:69:10:EE:2A:40:3A:22 + X509v3 Authority Key Identifier: + keyid:3B:50:26:45:6C:E2:FE:28:B1:71:0A:A8:95:2D:78:63:8E:2C:48:92 + + Signature Algorithm: sha1WithRSAEncryption + 40:8a:be:55:1f:d9:0f:96:fd:54:dd:9f:6b:1d:b1:34:ed:b7: + 11:6d:72:a9:65:9a:39:bd:79:3b:d3:4e:0c:22:60:39:e8:c0: + 2c:34:64:09:2c:0c:aa:f7:f9:9d:f1:d9:b9:04:d6:e2:c4:cb: + d5:05:33:75:5e:87:c0:2c:80:06:8b:6e:9c:ad:0c:7f:03:c0: + f5:91:e4:3a:64:b9:52:3b:5a:e0:e5:79:32:89:fb:4a:54:68: + 9a:e6:72:3e:61:93:a3:2a:67:aa:95:d0:3d:37:33:5c:da:6e: + a6:ac:3d:b6:b1:ac:68:f0:8c:8b:6b:96:a5:f7:ed:2d:6e:64: + c7:11 +-----BEGIN CERTIFICATE----- +MIIC5jCCAk+gAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDIgUm9vdCA3MB4XDTA5 +MTEyMDEzNTIzMFoXDTM0MTExNDEzNTIzMFowbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAyIFN1YiBDQSAyIFJvb3QgNzCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0x9+KLb98LsBIYgExNo9as4JjgQppQ84 +23TQ7q1clXkWEcCxUWmVu6iPixx7jIInFiGCgtc2b7O7NqitaeLjzW/vgaz646ms +hrcxHXURoy4diQucXgNFerCpne4x8RXBxfYmjtSJco/0hpTRSTckVoQQ28zyHT5Y +ZpeyF28Vy4ECAwEAAaOBlzCBlDBFBgNVHR8EPjA8MDqgOKA2hjRodHRwOi8vbG9j +YWxob3N0Ojg5MDIvZGVtb0NBL2NybC9TdWJfQ0FfMl9Sb290XzcuY3JsMAsGA1Ud +DwQEAwIF4DAdBgNVHQ4EFgQUzaKuUdDPook6UyN0HWkQ7ipAOiIwHwYDVR0jBBgw +FoAUO1AmRWzi/iixcQqolS14Y44sSJIwDQYJKoZIhvcNAQEFBQADgYEAQIq+VR/Z +D5b9VN2fax2xNO23EW1yqWWaOb15O9NODCJgOejALDRkCSwMqvf5nfHZuQTW4sTL +1QUzdV6HwCyABotunK0MfwPA9ZHkOmS5Ujta4OV5Mon7SlRomuZyPmGToypnqpXQ +PTczXNpupqw9trGsaPCMi2uWpfftLW5kxxE= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/private/cakey.pem new file mode 100644 index 0000000000..1f95ffa3c3 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,70BBA561902B1296 + ++Pbay3A7tcxOMNFXIlyQ6Hpl4QxJJmzZzXT5UOfGZYYRYrFKv1489pqvzLNgp06z +nWvyILc3AUd4dWnzfkWvPN3fjJazGWXoZaYLfGgdccA0LdXh+TmqVHHxFjOZVFeO +lYlKqK6dUsybaciOhkYBKPs1ZFAaNtQLZc1/GVAA9jVYnfwNVmW14d5Q8gurZTp8 +qYwQmT9Sjm2j9USIFcD9MDH94gW77PI+XD1hu6PJTF8m7n8eSY9KcWfVmd/Qj9Ly +nzLRaS6SOKETWL4+fUaN6aDtddKGwFgagyDwlRRuizX18ZSue2qoK73AhLtZ8Gx/ +vgFLTsvcniZus9kzVrRm2dsWvzaVAmOwqN04IqD6bEr+kXq1obP/T+deGsRwR54K +wEy7NrkkMSGw4AOuxVNSO7NYgU2kXueAfvGU8SQiXuU1S7fdZpWci8T5Dm7FuP9B +iKsHqUH9GYgAVl+Y3dwa9n+mDaFkn4wxeVHDdL40XJT0LYCMz9PGKRy3JSTiHF// +j9BHDpIC+E8L9N01cJ74+p0bzLLOhZ7vyjx8umVJbNIAAlDbCrEi4ZFqwGvmdjHF +2dti2S0ALixAFQybub4s9Cp3QxfaWnYQOvV7A0SGhtHkjycaJwO0cSonQ8yEjJJJ +PQkIW9SK+xz/yDYMHqa/Yo5t53GkpCTKBo2STSdnXjnABNk3FAusf72POkIPcH99 +5uyje8bo+lS2VB/O/pm8tbf9mW9YEh/xd3VAglWiAMzYSfO1x0rSTpdqJMSDfOhK +ogim9NdrVwASi0JrE8nCovwO3auOPu+5sRvYstnt18IVNisZZoW/Qg== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/serial new file mode 100644 index 0000000000..7d802a3e71 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/serial @@ -0,0 +1 @@ +1002 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/openssl.cfg new file mode 100644 index 0000000000..c6acf751f5 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ +crlDistributionPoints=URI:http://localhost:8902/demoCA/crl/Sub_CA_2_Root_7.crl +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +#nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/README.txt b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/README.txt new file mode 100644 index 0000000000..645ae6037d --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/README.txt @@ -0,0 +1,13 @@ +Revoked certificates: + +- User 2 Sub CA 2 Root 8 + + +Start the OCSP responder: +openssl ocsp -index demoCA/index.txt -port 8889 -rsigner demoCA/cacert.pem -rkey demoCA/private/cakey.pem -CA demoCA/cacert.pem -text + + + + + + diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/cacert.pem new file mode 100644 index 0000000000..26368962e8 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/cacert.pem @@ -0,0 +1,66 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4097 (0x1001) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 8 + Validity + Not Before: Nov 20 15:55:33 2009 GMT + Not After : Nov 14 15:55:33 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 2 Root 8 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:e9:91:38:d8:c1:36:e5:c1:d0:32:e8:ae:02:11: + 97:e5:c5:07:8f:5b:46:3a:3c:d9:49:5e:9a:4b:51: + 4c:b7:7d:e9:d1:4f:a7:15:8c:c6:10:f6:fa:5f:a9: + 0b:1b:bc:de:56:f5:ad:a3:a0:40:f1:75:10:58:74: + 37:f9:b7:9f:76:ca:46:96:4c:1a:81:f4:a2:ce:88: + 8b:9e:00:6d:42:b3:d6:68:d1:67:d6:9f:b8:9c:3f: + 43:c7:36:bf:41:88:1b:e8:74:26:a0:51:5c:e2:ee: + 6d:9d:73:bb:0d:36:e1:5c:68:9f:21:3b:b2:aa:ed: + 39:1d:ae:fc:b4:ca:38:c2:fb + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 1B:AB:6B:0F:42:91:DC:1E:D4:7A:95:87:30:2D:CC:11:4F:35:B7:73 + X509v3 Authority Key Identifier: + keyid:D6:66:76:C9:05:FF:A9:50:88:96:60:DD:FB:C7:30:18:72:67:41:19 + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 8 + serial:B2:47:DE:6A:2A:4C:83:19 + + Authority Information Access: + OCSP - URI:http://localhost:8888 + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 89:f8:8d:a8:e5:0b:2a:fb:f3:6a:80:2c:26:a1:a7:36:7e:a0: + c5:61:65:9d:7e:d6:47:60:b4:f6:72:e9:6e:2c:d9:f8:7f:c8: + 7a:5d:75:98:ad:88:de:e7:1b:44:a3:96:37:84:c0:b3:20:98: + 3b:b5:f6:ee:70:9c:04:7a:6c:88:05:75:7f:12:cf:b9:76:e8: + c0:17:0c:5e:eb:10:38:1e:54:41:58:56:f6:3c:ec:07:a5:c0: + 74:24:34:af:b3:c7:b2:58:85:47:0f:6c:e4:a0:9f:c8:7b:5c: + 95:77:17:e5:ad:eb:c3:86:44:f7:81:ef:cb:58:12:1a:6a:c7: + 19:95 +-----BEGIN CERTIFICATE----- +MIIDOTCCAqKgAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA4MB4XDTA5MTEyMDE1NTUz +M1oXDTM0MTExNDE1NTUzM1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDIgUm9vdCA4MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDpkTjYwTblwdAy6K4CEZflxQePW0Y6PNlJXppLUUy3fenRT6cVjMYQ +9vpfqQsbvN5W9a2joEDxdRBYdDf5t592ykaWTBqB9KLOiIueAG1Cs9Zo0WfWn7ic +P0PHNr9BiBvodCagUVzi7m2dc7sNNuFcaJ8hO7Kq7Tkdrvy0yjjC+wIDAQABo4H6 +MIH3MB0GA1UdDgQWBBQbq2sPQpHcHtR6lYcwLcwRTzW3czCBkQYDVR0jBIGJMIGG +gBTWZnbJBf+pUIiWYN37xzAYcmdBGaFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA4ggkAskfeaipMgxkwMQYIKwYBBQUH +AQEEJTAjMCEGCCsGAQUFBzABhhVodHRwOi8vbG9jYWxob3N0Ojg4ODgwDwYDVR0T +AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQCJ+I2o5Qsq+/NqgCwmoac2fqDF +YWWdftZHYLT2culuLNn4f8h6XXWYrYje5xtEo5Y3hMCzIJg7tfbucJwEemyIBXV/ +Es+5dujAFwxe6xA4HlRBWFb2POwHpcB0JDSvs8eyWIVHD2zkoJ/Ie1yVdxflrevD +hkT3ge/LWBIaascZlQ== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/crl/DO_NOT_INSTALL_THIS_CRL b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/crl/DO_NOT_INSTALL_THIS_CRL new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/crl/DO_NOT_INSTALL_THIS_CRL diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/crl/Sub_CA_2_Root_8.crl b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/crl/Sub_CA_2_Root_8.crl Binary files differnew file mode 100644 index 0000000000..f4e88754b5 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/crl/Sub_CA_2_Root_8.crl diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/crlnumber new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/crlnumber @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/index.txt new file mode 100644 index 0000000000..cdace00f7e --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/index.txt @@ -0,0 +1,2 @@ +V 341114161332Z 1002 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 2 Root 8 +R 341114161602Z 091120161700Z,superseded 1003 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 2 Sub CA 2 Root 8 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/index.txt.attr new file mode 100644 index 0000000000..8f7e63a347 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/newcerts/1002.pem b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/newcerts/1002.pem new file mode 100644 index 0000000000..1107a4327f --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/newcerts/1002.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4098 (0x1002) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 2 Root 8 + Validity + Not Before: Nov 20 16:13:32 2009 GMT + Not After : Nov 14 16:13:32 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 2 Root 8 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:d2:f6:25:c0:95:4b:07:1e:a0:57:67:52:36:b3: + 3e:5d:32:7f:61:25:e9:dd:31:a1:67:6e:02:9f:4f: + ca:ff:82:50:64:2e:ed:4e:8d:09:73:48:91:e1:90: + ca:df:06:ab:f4:c3:3d:8b:7d:d1:6b:5f:f8:f8:d6: + c0:f4:81:59:7c:0e:53:32:a9:cd:e4:34:3c:20:a9: + 08:b6:c2:b3:b7:91:d2:db:46:06:09:55:ff:f9:f4: + 4e:2a:28:36:46:0e:04:f1:78:7d:a3:ff:ac:08:1b: + 21:99:f5:b4:5b:f6:be:fd:1a:89:26:4b:eb:b9:58: + fc:c2:5f:44:42:a9:00:76:ff + Exponent: 65537 (0x10001) + X509v3 extensions: + Authority Information Access: + OCSP - URI:http://localhost:8889 + + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 9D:91:CD:7F:70:3B:00:C1:2A:FD:2F:5D:64:C4:8F:EB:0E:37:25:1B + X509v3 Authority Key Identifier: + keyid:1B:AB:6B:0F:42:91:DC:1E:D4:7A:95:87:30:2D:CC:11:4F:35:B7:73 + + Signature Algorithm: sha1WithRSAEncryption + 2c:68:5e:5b:2e:d7:48:ca:2a:01:b4:a0:99:0e:06:2d:e8:23: + b3:66:31:97:cd:9e:73:61:35:af:9d:d9:2f:7c:e6:87:7f:2a: + ae:3e:b0:99:c9:20:10:30:e3:a0:5b:28:8b:57:f2:12:3a:87: + c1:7a:5e:c8:21:b9:ae:49:c1:aa:4f:1c:9e:a8:ae:0f:ad:a2: + 3e:aa:61:94:64:41:f8:d7:19:8d:a1:be:c0:15:04:25:2c:35: + 29:af:00:1e:40:7c:e7:d7:41:89:a7:ab:2d:dd:78:dd:c7:ba: + d0:1b:7b:68:fa:7e:a4:0f:4c:ab:02:6e:d2:ff:b8:5b:05:f6: + 47:29 +-----BEGIN CERTIFICATE----- +MIIC0jCCAjugAwIBAgICEAIwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDIgUm9vdCA4MB4XDTA5 +MTEyMDE2MTMzMloXDTM0MTExNDE2MTMzMlowbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAxIFN1YiBDQSAyIFJvb3QgODCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0vYlwJVLBx6gV2dSNrM+XTJ/YSXp3TGh +Z24Cn0/K/4JQZC7tTo0Jc0iR4ZDK3war9MM9i33Ra1/4+NbA9IFZfA5TMqnN5DQ8 +IKkItsKzt5HS20YGCVX/+fROKig2Rg4E8Xh9o/+sCBshmfW0W/a+/RqJJkvruVj8 +wl9EQqkAdv8CAwEAAaOBgzCBgDAxBggrBgEFBQcBAQQlMCMwIQYIKwYBBQUHMAGG +FWh0dHA6Ly9sb2NhbGhvc3Q6ODg4OTALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFJ2R +zX9wOwDBKv0vXWTEj+sONyUbMB8GA1UdIwQYMBaAFBuraw9Ckdwe1HqVhzAtzBFP +NbdzMA0GCSqGSIb3DQEBBQUAA4GBACxoXlsu10jKKgG0oJkOBi3oI7NmMZfNnnNh +Na+d2S985od/Kq4+sJnJIBAw46BbKItX8hI6h8F6Xsghua5JwapPHJ6org+toj6q +YZRkQfjXGY2hvsAVBCUsNSmvAB5AfOfXQYmnqy3deN3HutAbe2j6fqQPTKsCbtL/ +uFsF9kcp +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/newcerts/1003.pem b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/newcerts/1003.pem new file mode 100644 index 0000000000..53268ff52d --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/newcerts/1003.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4099 (0x1003) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 2 Root 8 + Validity + Not Before: Nov 20 16:16:02 2009 GMT + Not After : Nov 14 16:16:02 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 2 Sub CA 2 Root 8 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:b4:58:05:7c:f5:f2:48:af:35:03:82:62:af:d3: + ef:50:f0:0b:b1:a9:a1:9b:14:1c:54:a9:71:b4:f6: + e0:7d:8a:25:b3:21:e2:53:ab:a5:08:9e:ed:5a:ef: + 8b:4f:be:75:40:b0:10:05:eb:08:3b:94:c2:57:37: + 51:41:08:57:b9:1c:a5:2f:e9:cc:3c:a8:70:2b:eb: + 00:92:43:64:44:18:23:9f:85:5f:7f:a5:c9:30:b3: + 14:c0:2b:fc:94:a5:a6:ad:46:a8:37:12:20:ab:cf: + e0:02:74:5d:1f:2e:ec:1c:9f:27:1f:83:fc:c4:62: + d2:0b:6b:f4:65:21:1d:94:ff + Exponent: 65537 (0x10001) + X509v3 extensions: + Authority Information Access: + OCSP - URI:http://localhost:8889 + + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 1E:C7:A3:43:33:6B:EC:90:B5:66:81:64:D6:43:72:45:DB:D9:E4:57 + X509v3 Authority Key Identifier: + keyid:1B:AB:6B:0F:42:91:DC:1E:D4:7A:95:87:30:2D:CC:11:4F:35:B7:73 + + Signature Algorithm: sha1WithRSAEncryption + a8:66:0d:4b:6a:00:fc:31:e3:f5:8f:49:44:3d:60:26:76:2e: + 51:f8:41:35:3b:5b:7f:87:e3:00:d7:ae:85:bb:d9:81:a5:30: + db:6a:0a:a0:d2:e8:69:f5:47:d8:19:e5:2a:bd:c5:8e:99:f9: + 57:fc:b0:64:f5:43:bc:37:4a:8e:28:70:a4:6d:7d:da:2c:9e: + c1:55:8d:00:89:fe:f7:ef:c9:d9:8d:fe:01:3e:83:23:58:c3: + 3e:41:09:ab:5c:60:0e:9e:18:69:9e:99:7f:a2:cd:b7:95:5c: + ea:31:02:79:32:eb:1a:07:dc:75:98:80:8e:56:f2:0a:8f:0e: + cf:4f +-----BEGIN CERTIFICATE----- +MIIC0jCCAjugAwIBAgICEAMwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDIgUm9vdCA4MB4XDTA5 +MTEyMDE2MTYwMloXDTM0MTExNDE2MTYwMlowbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAyIFN1YiBDQSAyIFJvb3QgODCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAtFgFfPXySK81A4Jir9PvUPALsamhmxQc +VKlxtPbgfYolsyHiU6ulCJ7tWu+LT751QLAQBesIO5TCVzdRQQhXuRylL+nMPKhw +K+sAkkNkRBgjn4Vff6XJMLMUwCv8lKWmrUaoNxIgq8/gAnRdHy7sHJ8nH4P8xGLS +C2v0ZSEdlP8CAwEAAaOBgzCBgDAxBggrBgEFBQcBAQQlMCMwIQYIKwYBBQUHMAGG +FWh0dHA6Ly9sb2NhbGhvc3Q6ODg4OTALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFB7H +o0Mza+yQtWaBZNZDckXb2eRXMB8GA1UdIwQYMBaAFBuraw9Ckdwe1HqVhzAtzBFP +NbdzMA0GCSqGSIb3DQEBBQUAA4GBAKhmDUtqAPwx4/WPSUQ9YCZ2LlH4QTU7W3+H +4wDXroW72YGlMNtqCqDS6Gn1R9gZ5Sq9xY6Z+Vf8sGT1Q7w3So4ocKRtfdosnsFV +jQCJ/vfvydmN/gE+gyNYwz5BCatcYA6eGGmemX+izbeVXOoxAnky6xoH3HWYgI5W +8gqPDs9P +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/private/cakey.pem new file mode 100644 index 0000000000..e063b97262 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,B84323C471CC815A + +UrT9eGAJB4+hzdjcS7YBCJi6jCL9n9/vZC0fC6mjZRK/dw4CxLka0KapKUVd+pj/ +I+XG6JOqa5tmsHcp9OWaWpzyu9W5DJqjodTum6pNlig68GVVSs21u7q0mF5mA6OR +PmRu+iOe2oZO6kVaRnpdGBnbsUsvlsbayiY3nHjXeDPxyc+XGnIMjT7mBOO360iR +h6IEOyapRho8klyuOXLy8hHZuUyspm66Nq+czorGdv3nlEdSI4t4LPTcqJGUMiHb +hLYsCK9Zwu7RQWne3OmGjAspU37TB3F1YrWjnHFIKE6YSvtdYMwXosMbybdUZFwQ +w4dGUhIxCxWLDF99Qfnygi8HJOC1FiFcJslVem0Xi3M654sshGLCiA4jMjdUAEmL +R+rzjUNZEHqvO/bGm7zsEoLWQFWEYqQZguwxDScam9Sii/fcnEBcSERbEi3yjvlX +7L3q4j/7/PlpYuRVB+f21ZuoI8R6M+omwF1ZzuSQNMSvUMyhAgQ+yB/pFJbArU68 +4l7ks0wNcSlLyGzjsexrzU9UB8Y8avFOMGuRiWGt4Kh54hNxgaCRGp9ugoyEq5H5 ++QNB1x8tBJSe1YC4T06olH2xZTYCd5e9qTyjQrbnqTK4SEBDrOL+XSASkleH3vVH +SO1paXDjh9fSSTxPo1T8DnAadIcouVlUNdvO4WrtqO4Kbf0rDHbqzZDtrNYG3Hwd +w86nEo6J1AKrTKyXysOLdhuAhNr+hGx4ITT5HfV/H5BE3ba0/fmLxvenqTxBXrJc +wkEeORwtu1XWW1hxYKRi3lRgfi4OH/ciMwxU530mKZzIJTOdvsKPgw== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/serial new file mode 100644 index 0000000000..59c1122662 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/serial @@ -0,0 +1 @@ +1004 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/openssl.cfg new file mode 100644 index 0000000000..571237e7da --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +authorityInfoAccess = OCSP;URI:http://localhost:8889 +#crlDistributionPoints=URI:http://localhost:8902/demoCA/crl/Sub_CA_2_Root_7.crl +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +#nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/certs/ca_certs/Root_1.crt b/xmlsecurity/test_docs/certs/ca_certs/Root_1.crt Binary files differnew file mode 100644 index 0000000000..ff4f23a90f --- /dev/null +++ b/xmlsecurity/test_docs/certs/ca_certs/Root_1.crt diff --git a/xmlsecurity/test_docs/certs/ca_certs/Root_10.crt b/xmlsecurity/test_docs/certs/ca_certs/Root_10.crt Binary files differnew file mode 100644 index 0000000000..64f80334b1 --- /dev/null +++ b/xmlsecurity/test_docs/certs/ca_certs/Root_10.crt diff --git a/xmlsecurity/test_docs/certs/ca_certs/Root_11.crt b/xmlsecurity/test_docs/certs/ca_certs/Root_11.crt Binary files differnew file mode 100644 index 0000000000..bbf0819dd5 --- /dev/null +++ b/xmlsecurity/test_docs/certs/ca_certs/Root_11.crt diff --git a/xmlsecurity/test_docs/certs/ca_certs/Root_2.crt b/xmlsecurity/test_docs/certs/ca_certs/Root_2.crt Binary files differnew file mode 100644 index 0000000000..5f4bd15cd8 --- /dev/null +++ b/xmlsecurity/test_docs/certs/ca_certs/Root_2.crt diff --git a/xmlsecurity/test_docs/certs/ca_certs/Root_3.crt b/xmlsecurity/test_docs/certs/ca_certs/Root_3.crt Binary files differnew file mode 100644 index 0000000000..306aa56491 --- /dev/null +++ b/xmlsecurity/test_docs/certs/ca_certs/Root_3.crt diff --git a/xmlsecurity/test_docs/certs/ca_certs/Root_4.crt b/xmlsecurity/test_docs/certs/ca_certs/Root_4.crt Binary files differnew file mode 100644 index 0000000000..a4c1dd84db --- /dev/null +++ b/xmlsecurity/test_docs/certs/ca_certs/Root_4.crt diff --git a/xmlsecurity/test_docs/certs/ca_certs/Root_5.crt b/xmlsecurity/test_docs/certs/ca_certs/Root_5.crt Binary files differnew file mode 100644 index 0000000000..e9af2c3303 --- /dev/null +++ b/xmlsecurity/test_docs/certs/ca_certs/Root_5.crt diff --git a/xmlsecurity/test_docs/certs/ca_certs/Root_6.crt b/xmlsecurity/test_docs/certs/ca_certs/Root_6.crt Binary files differnew file mode 100644 index 0000000000..03f2ff0b31 --- /dev/null +++ b/xmlsecurity/test_docs/certs/ca_certs/Root_6.crt diff --git a/xmlsecurity/test_docs/certs/ca_certs/Root_7.crt b/xmlsecurity/test_docs/certs/ca_certs/Root_7.crt Binary files differnew file mode 100644 index 0000000000..96eb504595 --- /dev/null +++ b/xmlsecurity/test_docs/certs/ca_certs/Root_7.crt diff --git a/xmlsecurity/test_docs/certs/ca_certs/Root_8.crt b/xmlsecurity/test_docs/certs/ca_certs/Root_8.crt Binary files differnew file mode 100644 index 0000000000..c714844ad9 --- /dev/null +++ b/xmlsecurity/test_docs/certs/ca_certs/Root_8.crt diff --git a/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_1.crt b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_1.crt Binary files differnew file mode 100644 index 0000000000..d83ce86dea --- /dev/null +++ b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_1.crt diff --git a/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_2.crt b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_2.crt Binary files differnew file mode 100644 index 0000000000..c4857c541a --- /dev/null +++ b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_2.crt diff --git a/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_3.crt b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_3.crt Binary files differnew file mode 100644 index 0000000000..d39b18b572 --- /dev/null +++ b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_3.crt diff --git a/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_4.crt b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_4.crt Binary files differnew file mode 100644 index 0000000000..b881f8a12e --- /dev/null +++ b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_4.crt diff --git a/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_5.crt b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_5.crt Binary files differnew file mode 100644 index 0000000000..61391a8c25 --- /dev/null +++ b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_5.crt diff --git a/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_6.crt b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_6.crt Binary files differnew file mode 100644 index 0000000000..223d047ca9 --- /dev/null +++ b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_6.crt diff --git a/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_7.crt b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_7.crt Binary files differnew file mode 100644 index 0000000000..af6a360033 --- /dev/null +++ b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_7.crt diff --git a/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_8.crt b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_8.crt Binary files differnew file mode 100644 index 0000000000..05297a3277 --- /dev/null +++ b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_8.crt diff --git a/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_9.crt b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_9.crt Binary files differnew file mode 100644 index 0000000000..209059facd --- /dev/null +++ b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_9.crt diff --git a/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_2_Root_4.crt b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_2_Root_4.crt Binary files differnew file mode 100644 index 0000000000..a981a091cc --- /dev/null +++ b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_2_Root_4.crt diff --git a/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_2_Root_7.crt b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_2_Root_7.crt Binary files differnew file mode 100644 index 0000000000..d73827e103 --- /dev/null +++ b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_2_Root_7.crt diff --git a/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_2_Root_8.crt b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_2_Root_8.crt Binary files differnew file mode 100644 index 0000000000..69da1318b0 --- /dev/null +++ b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_2_Root_8.crt diff --git a/xmlsecurity/test_docs/certs/crl/Root_10.crl b/xmlsecurity/test_docs/certs/crl/Root_10.crl Binary files differnew file mode 100644 index 0000000000..e7fee3ade8 --- /dev/null +++ b/xmlsecurity/test_docs/certs/crl/Root_10.crl diff --git a/xmlsecurity/test_docs/certs/crl/Root_11.crl b/xmlsecurity/test_docs/certs/crl/Root_11.crl Binary files differnew file mode 100644 index 0000000000..95e18ae6af --- /dev/null +++ b/xmlsecurity/test_docs/certs/crl/Root_11.crl diff --git a/xmlsecurity/test_docs/certs/crl/Root_3.crl b/xmlsecurity/test_docs/certs/crl/Root_3.crl Binary files differnew file mode 100644 index 0000000000..5978b2613d --- /dev/null +++ b/xmlsecurity/test_docs/certs/crl/Root_3.crl diff --git a/xmlsecurity/test_docs/certs/crl/Root_4.crl b/xmlsecurity/test_docs/certs/crl/Root_4.crl Binary files differnew file mode 100644 index 0000000000..10b370c149 --- /dev/null +++ b/xmlsecurity/test_docs/certs/crl/Root_4.crl diff --git a/xmlsecurity/test_docs/certs/crl/Root_9.crl b/xmlsecurity/test_docs/certs/crl/Root_9.crl Binary files differnew file mode 100644 index 0000000000..90bf8eba4a --- /dev/null +++ b/xmlsecurity/test_docs/certs/crl/Root_9.crl diff --git a/xmlsecurity/test_docs/certs/crl/Sub_CA_1_Root_2.crl b/xmlsecurity/test_docs/certs/crl/Sub_CA_1_Root_2.crl Binary files differnew file mode 100644 index 0000000000..c9f5420293 --- /dev/null +++ b/xmlsecurity/test_docs/certs/crl/Sub_CA_1_Root_2.crl diff --git a/xmlsecurity/test_docs/certs/crl/Sub_CA_1_Root_4.crl b/xmlsecurity/test_docs/certs/crl/Sub_CA_1_Root_4.crl Binary files differnew file mode 100644 index 0000000000..7fc03f255e --- /dev/null +++ b/xmlsecurity/test_docs/certs/crl/Sub_CA_1_Root_4.crl diff --git a/xmlsecurity/test_docs/certs/crl/Sub_CA_1_Root_9.crl b/xmlsecurity/test_docs/certs/crl/Sub_CA_1_Root_9.crl Binary files differnew file mode 100644 index 0000000000..567b8b5d11 --- /dev/null +++ b/xmlsecurity/test_docs/certs/crl/Sub_CA_1_Root_9.crl diff --git a/xmlsecurity/test_docs/certs/crl/Sub_CA_2_Root_4.crl b/xmlsecurity/test_docs/certs/crl/Sub_CA_2_Root_4.crl Binary files differnew file mode 100644 index 0000000000..a2ce79b3a0 --- /dev/null +++ b/xmlsecurity/test_docs/certs/crl/Sub_CA_2_Root_4.crl diff --git a/xmlsecurity/test_docs/certs/end_certs/User_10_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_10_Root_11.crt Binary files differnew file mode 100644 index 0000000000..16abebe511 --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_10_Root_11.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_11_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_11_Root_11.crt Binary files differnew file mode 100644 index 0000000000..08f5040ced --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_11_Root_11.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_12_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_12_Root_11.crt Binary files differnew file mode 100644 index 0000000000..18bd2475cd --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_12_Root_11.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_13_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_13_Root_11.crt Binary files differnew file mode 100644 index 0000000000..c7c83cf19a --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_13_Root_11.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_14_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_14_Root_11.crt Binary files differnew file mode 100644 index 0000000000..3ff2118d28 --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_14_Root_11.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_15_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_15_Root_11.crt Binary files differnew file mode 100644 index 0000000000..0fcd6393ac --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_15_Root_11.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_16_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_16_Root_11.crt Binary files differnew file mode 100644 index 0000000000..9f28740601 --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_16_Root_11.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_17_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_17_Root_11.crt Binary files differnew file mode 100644 index 0000000000..49442c6df7 --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_17_Root_11.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_18_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_18_Root_11.crt Binary files differnew file mode 100644 index 0000000000..27109c5bb0 --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_18_Root_11.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_19_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_19_Root_11.crt Binary files differnew file mode 100644 index 0000000000..5cce769b44 --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_19_Root_11.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_1_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_1_Root_11.crt Binary files differnew file mode 100644 index 0000000000..09f2a54f44 --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_1_Root_11.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_1.crt b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_1.crt Binary files differnew file mode 100644 index 0000000000..c3810ab508 --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_1.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_10.crt b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_10.crt Binary files differnew file mode 100644 index 0000000000..1531d1e8d3 --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_10.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_2.crt b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_2.crt Binary files differnew file mode 100644 index 0000000000..3dab258778 --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_2.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_3.crt b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_3.crt Binary files differnew file mode 100644 index 0000000000..278b11b77e --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_3.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_4.crt b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_4.crt Binary files differnew file mode 100644 index 0000000000..fa6e84547f --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_4.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_5.crt b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_5.crt Binary files differnew file mode 100644 index 0000000000..863f6f613e --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_5.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_6.crt b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_6.crt Binary files differnew file mode 100644 index 0000000000..cae3959d17 --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_6.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_7.crt b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_7.crt Binary files differnew file mode 100644 index 0000000000..e5786dc6c0 --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_7.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_8.crt b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_8.crt Binary files differnew file mode 100644 index 0000000000..a63a9f8c95 --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_8.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_9.crt b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_9.crt Binary files differnew file mode 100644 index 0000000000..59a77df71e --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_9.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_2_Root_4.crt b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_2_Root_4.crt Binary files differnew file mode 100644 index 0000000000..3b12b29c16 --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_2_Root_4.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_2_Root_7.crt b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_2_Root_7.crt Binary files differnew file mode 100644 index 0000000000..c11e716d7c --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_2_Root_7.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_2_Root_8.crt b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_2_Root_8.crt Binary files differnew file mode 100644 index 0000000000..026274f632 --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_2_Root_8.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_20_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_20_Root_11.crt Binary files differnew file mode 100644 index 0000000000..4a026790e7 --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_20_Root_11.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_21_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_21_Root_11.crt Binary files differnew file mode 100644 index 0000000000..46b008eebf --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_21_Root_11.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_22_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_22_Root_11.crt Binary files differnew file mode 100644 index 0000000000..7c1c2cb29f --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_22_Root_11.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_23_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_23_Root_11.crt Binary files differnew file mode 100644 index 0000000000..cc6185cc93 --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_23_Root_11.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_24_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_24_Root_11.crt Binary files differnew file mode 100644 index 0000000000..fa646e4029 --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_24_Root_11.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_25_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_25_Root_11.crt Binary files differnew file mode 100644 index 0000000000..673db6cc92 --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_25_Root_11.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_26_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_26_Root_11.crt Binary files differnew file mode 100644 index 0000000000..e284dca9b5 --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_26_Root_11.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_27_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_27_Root_11.crt Binary files differnew file mode 100644 index 0000000000..5b2cda4613 --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_27_Root_11.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_28_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_28_Root_11.crt Binary files differnew file mode 100644 index 0000000000..532010b18c --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_28_Root_11.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_29_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_29_Root_11.crt Binary files differnew file mode 100644 index 0000000000..282aa47af3 --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_29_Root_11.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_2_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_2_Root_11.crt Binary files differnew file mode 100644 index 0000000000..26a51418fd --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_2_Root_11.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_1_Root_4.crt b/xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_1_Root_4.crt Binary files differnew file mode 100644 index 0000000000..8a00d30080 --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_1_Root_4.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_1_Root_7.crt b/xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_1_Root_7.crt Binary files differnew file mode 100644 index 0000000000..935da38c23 --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_1_Root_7.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_1_Root_8.crt b/xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_1_Root_8.crt Binary files differnew file mode 100644 index 0000000000..79ea4fbcfe --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_1_Root_8.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_2_Root_4.crt b/xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_2_Root_4.crt Binary files differnew file mode 100644 index 0000000000..011c4ae2a8 --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_2_Root_4.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_2_Root_7.crt b/xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_2_Root_7.crt Binary files differnew file mode 100644 index 0000000000..b142544288 --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_2_Root_7.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_2_Root_8.crt b/xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_2_Root_8.crt Binary files differnew file mode 100644 index 0000000000..8c8689e10e --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_2_Root_8.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_30_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_30_Root_11.crt Binary files differnew file mode 100644 index 0000000000..ed39bea1ec --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_30_Root_11.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_31_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_31_Root_11.crt Binary files differnew file mode 100644 index 0000000000..7f9e136986 --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_31_Root_11.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_32_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_32_Root_11.crt Binary files differnew file mode 100644 index 0000000000..dc28470c8b --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_32_Root_11.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_33_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_33_Root_11.crt Binary files differnew file mode 100644 index 0000000000..df9d81d8d1 --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_33_Root_11.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_34_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_34_Root_11.crt Binary files differnew file mode 100644 index 0000000000..018da383d7 --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_34_Root_11.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_35_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_35_Root_11.crt new file mode 100644 index 0000000000..0092d16c7a --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_35_Root_11.crt @@ -0,0 +1,64 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4130 (0x1022) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Nov 8 10:51:39 2010 GMT + Not After : Nov 8 10:51:39 2011 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 35 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:9b:36:00:64:f3:ce:93:97:62:19:fa:78:d9:6f: + 92:6a:b9:d2:9a:4e:06:2c:02:52:cd:93:50:84:28: + 19:42:a2:4a:34:e2:cd:e6:b0:39:7a:c8:4d:84:bc: + 71:51:ed:5d:6c:7e:f9:cc:01:5a:4b:73:50:a9:3b: + 5d:ad:cc:89:f7:dc:e0:dd:0a:ff:48:01:a9:34:19: + c0:6a:ee:4b:20:f4:cf:3c:94:c1:ae:88:0f:c9:42: + 1a:a6:47:31:fe:37:04:00:bb:ec:07:5f:cb:ee:70: + c4:c7:7c:6f:ee:03:19:76:de:0b:df:d0:48:91:67: + 55:9b:90:91:f4:ce:56:04:d5 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 91:47:AC:29:95:5D:EF:72:14:8F:82:45:07:E2:94:49:75:C6:7D:73 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DNS:alt.openoffice.org, IP Address:192.168.7.1, IP Address:13:0:0:0:0:0:0:17, email:my@other.address, Registered ID:1.2.3.4, othername:<unsupported>, DirName:/C=DE/O=OpenOffice.org/OU=Development/CN=User 32 Root 11, URI:http://my.url.here/ + Signature Algorithm: sha1WithRSAEncryption + 6e:80:e6:1e:86:3d:d2:65:a6:17:fa:80:2d:2e:dc:85:32:05: + a1:69:82:e1:79:d1:dc:de:69:cd:9e:f0:cc:90:75:a9:45:ee: + 73:46:fe:29:69:c0:99:bb:fc:3a:db:c0:5f:69:c6:b7:ea:9a: + 63:b2:8e:29:2c:a5:5a:88:88:94:75:4b:ab:0a:72:f6:3a:aa: + 5d:6b:3a:5c:b6:9b:57:f5:c1:51:af:df:3c:a6:8a:a3:da:70: + 66:61:49:12:06:78:98:9f:bc:78:3c:43:6d:08:94:aa:32:b6: + f3:cc:af:0d:29:fe:96:47:7d:fe:4a:61:48:90:11:0b:bd:0f: + a0:fd +-----BEGIN CERTIFICATE----- +MIIDajCCAtOgAwIBAgICECIwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDExMDgxMDUx +MzlaFw0xMTExMDgxMDUxMzlaMGAxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxEDAOBgNVBAMTB1VzZXIgMzUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB +AJs2AGTzzpOXYhn6eNlvkmq50ppOBiwCUs2TUIQoGUKiSjTizeawOXrITYS8cVHt +XWx++cwBWktzUKk7Xa3Miffc4N0K/0gBqTQZwGruSyD0zzyUwa6ID8lCGqZHMf43 +BAC77Adfy+5wxMd8b+4DGXbeC9/QSJFnVZuQkfTOVgTVAgMBAAGjggExMIIBLTAL +BgNVHQ8EBAMCBeAwHQYDVR0OBBYEFJFHrCmVXe9yFI+CRQfilEl1xn1zMB8GA1Ud +IwQYMBaAFOhqu8KQ6mxwIj729kgbA+a+t6ZVMIHdBgNVHREEgdUwgdKCEmFsdC5v +cGVub2ZmaWNlLm9yZ4cEwKgHAYcQABMAAAAAAAAAAAAAAAAAF4EQbXlAb3RoZXIu +YWRkcmVzc4gDKgMEoB4GAyoDBKAXDBVzb21lIG90aGVyIGlkZW50aWZpZXKkWDBW +MQswCQYDVQQGEwJERTEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsT +C0RldmVsb3BtZW50MRgwFgYDVQQDEw9Vc2VyIDMyIFJvb3QgMTGGE2h0dHA6Ly9t +eS51cmwuaGVyZS8wDQYJKoZIhvcNAQEFBQADgYEAboDmHoY90mWmF/qALS7chTIF +oWmC4XnR3N5pzZ7wzJB1qUXuc0b+KWnAmbv8OtvAX2nGt+qaY7KOKSylWoiIlHVL +qwpy9jqqXWs6XLabV/XBUa/fPKaKo9pwZmFJEgZ4mJ+8eDxDbQiUqjK288yvDSn+ +lkd9/kphSJARC70PoP0= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/certs/end_certs/User_3_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_3_Root_11.crt Binary files differnew file mode 100644 index 0000000000..879f4578c0 --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_3_Root_11.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_4_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_4_Root_11.crt Binary files differnew file mode 100644 index 0000000000..75a9c7c843 --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_4_Root_11.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_5_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_5_Root_11.crt Binary files differnew file mode 100644 index 0000000000..cf07f4aa2c --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_5_Root_11.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_6_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_6_Root_11.crt Binary files differnew file mode 100644 index 0000000000..993a09f957 --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_6_Root_11.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_7_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_7_Root_11.crt Binary files differnew file mode 100644 index 0000000000..a1cebacb3b --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_7_Root_11.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_8_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_8_Root_11.crt Binary files differnew file mode 100644 index 0000000000..12410ebc81 --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_8_Root_11.crt diff --git a/xmlsecurity/test_docs/certs/end_certs/User_9_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_9_Root_11.crt Binary files differnew file mode 100644 index 0000000000..f7372d09f3 --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_9_Root_11.crt diff --git a/xmlsecurity/test_docs/certs/p12/Root_11.p12 b/xmlsecurity/test_docs/certs/p12/Root_11.p12 Binary files differnew file mode 100644 index 0000000000..7df592643e --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/Root_11.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_10_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_10_Root_11.p12 Binary files differnew file mode 100644 index 0000000000..048ca8e8f5 --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_10_Root_11.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_11_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_11_Root_11.p12 Binary files differnew file mode 100644 index 0000000000..4498cdb76e --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_11_Root_11.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_12_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_12_Root_11.p12 Binary files differnew file mode 100644 index 0000000000..d85e0b7d47 --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_12_Root_11.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_13_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_13_Root_11.p12 Binary files differnew file mode 100644 index 0000000000..ff666ff1e5 --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_13_Root_11.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_14_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_14_Root_11.p12 Binary files differnew file mode 100644 index 0000000000..55e0d6233e --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_14_Root_11.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_15_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_15_Root_11.p12 Binary files differnew file mode 100644 index 0000000000..baa32f26b7 --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_15_Root_11.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_16_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_16_Root_11.p12 Binary files differnew file mode 100644 index 0000000000..7b20ff98cf --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_16_Root_11.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_17_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_17_Root_11.p12 Binary files differnew file mode 100644 index 0000000000..6e980df49e --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_17_Root_11.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_18_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_18_Root_11.p12 Binary files differnew file mode 100644 index 0000000000..4d343d6e76 --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_18_Root_11.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_19_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_19_Root_11.p12 Binary files differnew file mode 100644 index 0000000000..aa5f27d2d9 --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_19_Root_11.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_1_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_1_Root_11.p12 Binary files differnew file mode 100644 index 0000000000..80e5bf47c0 --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_1_Root_11.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_1.p12 b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_1.p12 Binary files differnew file mode 100644 index 0000000000..1e9a14cb8a --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_1.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_10.p12 b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_10.p12 Binary files differnew file mode 100644 index 0000000000..d7096919be --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_10.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_2.p12 b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_2.p12 Binary files differnew file mode 100644 index 0000000000..adc61fff40 --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_2.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_3.p12 b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_3.p12 Binary files differnew file mode 100644 index 0000000000..9213427a16 --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_3.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_4.p12 b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_4.p12 Binary files differnew file mode 100644 index 0000000000..005191d164 --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_4.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_5.p12 b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_5.p12 Binary files differnew file mode 100644 index 0000000000..e4599b113a --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_5.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_6.p12 b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_6.p12 Binary files differnew file mode 100644 index 0000000000..32b4926ad7 --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_6.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_7.p12 b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_7.p12 Binary files differnew file mode 100644 index 0000000000..2c0ea4acbf --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_7.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_8.p12 b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_8.p12 Binary files differnew file mode 100644 index 0000000000..b69a19e4e1 --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_8.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_9.p12 b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_9.p12 Binary files differnew file mode 100644 index 0000000000..7897733c4e --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_9.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_2_Root_4.p12 b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_2_Root_4.p12 Binary files differnew file mode 100644 index 0000000000..99eb944528 --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_2_Root_4.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_2_Root_7.p12 b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_2_Root_7.p12 Binary files differnew file mode 100644 index 0000000000..1aefff504e --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_2_Root_7.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_2_Root_8.p12 b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_2_Root_8.p12 Binary files differnew file mode 100644 index 0000000000..6b6d5fd4e7 --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_2_Root_8.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_20_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_20_Root_11.p12 Binary files differnew file mode 100644 index 0000000000..bebfdc88a6 --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_20_Root_11.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_21_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_21_Root_11.p12 Binary files differnew file mode 100644 index 0000000000..cbd6730a84 --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_21_Root_11.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_22_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_22_Root_11.p12 Binary files differnew file mode 100644 index 0000000000..ab2b651c1f --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_22_Root_11.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_23_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_23_Root_11.p12 Binary files differnew file mode 100644 index 0000000000..518388c5b4 --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_23_Root_11.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_24_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_24_Root_11.p12 Binary files differnew file mode 100644 index 0000000000..775b1359dc --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_24_Root_11.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_25_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_25_Root_11.p12 Binary files differnew file mode 100644 index 0000000000..f76a61869c --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_25_Root_11.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_26_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_26_Root_11.p12 Binary files differnew file mode 100644 index 0000000000..ef1273c724 --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_26_Root_11.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_27_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_27_Root_11.p12 Binary files differnew file mode 100644 index 0000000000..4208dc4316 --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_27_Root_11.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_28_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_28_Root_11.p12 Binary files differnew file mode 100644 index 0000000000..4826f2d045 --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_28_Root_11.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_29_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_29_Root_11.p12 Binary files differnew file mode 100644 index 0000000000..bc211718a5 --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_29_Root_11.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_2_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_2_Root_11.p12 Binary files differnew file mode 100644 index 0000000000..876151de3f --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_2_Root_11.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_1_Root_4.p12 b/xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_1_Root_4.p12 Binary files differnew file mode 100644 index 0000000000..268eeb9387 --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_1_Root_4.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_1_Root_7.p12 b/xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_1_Root_7.p12 Binary files differnew file mode 100644 index 0000000000..2fc86b9afd --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_1_Root_7.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_1_Root_8.p12 b/xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_1_Root_8.p12 Binary files differnew file mode 100644 index 0000000000..80dd6a8b08 --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_1_Root_8.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_2_Root_4.p12 b/xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_2_Root_4.p12 Binary files differnew file mode 100644 index 0000000000..821bb8ea50 --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_2_Root_4.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_2_Root_7.p12 b/xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_2_Root_7.p12 Binary files differnew file mode 100644 index 0000000000..3671d176d9 --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_2_Root_7.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_2_Root_8.p12 b/xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_2_Root_8.p12 Binary files differnew file mode 100644 index 0000000000..a4c63b7f23 --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_2_Root_8.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_30_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_30_Root_11.p12 Binary files differnew file mode 100644 index 0000000000..99b0be699a --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_30_Root_11.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_31_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_31_Root_11.p12 Binary files differnew file mode 100644 index 0000000000..5dbaf524c3 --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_31_Root_11.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_32_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_32_Root_11.p12 Binary files differnew file mode 100644 index 0000000000..17e22f7a5b --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_32_Root_11.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_33_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_33_Root_11.p12 Binary files differnew file mode 100644 index 0000000000..5982532a97 --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_33_Root_11.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_34_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_34_Root_11.p12 Binary files differnew file mode 100644 index 0000000000..4c00b21d45 --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_34_Root_11.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_3_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_3_Root_11.p12 Binary files differnew file mode 100644 index 0000000000..bc476b2572 --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_3_Root_11.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_4_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_4_Root_11.p12 Binary files differnew file mode 100644 index 0000000000..0b9bd319b5 --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_4_Root_11.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_5_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_5_Root_11.p12 Binary files differnew file mode 100644 index 0000000000..99de803de3 --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_5_Root_11.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_6_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_6_Root_11.p12 Binary files differnew file mode 100644 index 0000000000..a663a92d9b --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_6_Root_11.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_7_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_7_Root_11.p12 Binary files differnew file mode 100644 index 0000000000..c3d4e7532f --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_7_Root_11.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_8_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_8_Root_11.p12 Binary files differnew file mode 100644 index 0000000000..9db9c0ad4a --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_8_Root_11.p12 diff --git a/xmlsecurity/test_docs/certs/p12/User_9_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_9_Root_11.p12 Binary files differnew file mode 100644 index 0000000000..ccb03b327d --- /dev/null +++ b/xmlsecurity/test_docs/certs/p12/User_9_Root_11.p12 diff --git a/xmlsecurity/test_docs/documents/aia_ca_issuers.odt b/xmlsecurity/test_docs/documents/aia_ca_issuers.odt Binary files differnew file mode 100644 index 0000000000..8c34889df7 --- /dev/null +++ b/xmlsecurity/test_docs/documents/aia_ca_issuers.odt diff --git a/xmlsecurity/test_docs/documents/aia_ocsp.odt b/xmlsecurity/test_docs/documents/aia_ocsp.odt Binary files differnew file mode 100644 index 0000000000..6a1b48c6ae --- /dev/null +++ b/xmlsecurity/test_docs/documents/aia_ocsp.odt diff --git a/xmlsecurity/test_docs/documents/aia_ocsp_revoked_chain.odt b/xmlsecurity/test_docs/documents/aia_ocsp_revoked_chain.odt Binary files differnew file mode 100644 index 0000000000..248fcceddc --- /dev/null +++ b/xmlsecurity/test_docs/documents/aia_ocsp_revoked_chain.odt diff --git a/xmlsecurity/test_docs/documents/aia_ocsp_revoked_leaf.odt b/xmlsecurity/test_docs/documents/aia_ocsp_revoked_leaf.odt Binary files differnew file mode 100644 index 0000000000..2e0dbd6f7a --- /dev/null +++ b/xmlsecurity/test_docs/documents/aia_ocsp_revoked_leaf.odt diff --git a/xmlsecurity/test_docs/documents/aia_ocsp_revoked_leaf_chain.odt b/xmlsecurity/test_docs/documents/aia_ocsp_revoked_leaf_chain.odt Binary files differnew file mode 100644 index 0000000000..3519e4a818 --- /dev/null +++ b/xmlsecurity/test_docs/documents/aia_ocsp_revoked_leaf_chain.odt diff --git a/xmlsecurity/test_docs/documents/crl.odt b/xmlsecurity/test_docs/documents/crl.odt Binary files differnew file mode 100644 index 0000000000..06e412fa3c --- /dev/null +++ b/xmlsecurity/test_docs/documents/crl.odt diff --git a/xmlsecurity/test_docs/documents/crl_revoked_chain.odt b/xmlsecurity/test_docs/documents/crl_revoked_chain.odt Binary files differnew file mode 100644 index 0000000000..851fc87e76 --- /dev/null +++ b/xmlsecurity/test_docs/documents/crl_revoked_chain.odt diff --git a/xmlsecurity/test_docs/documents/crl_revoked_leaf.odt b/xmlsecurity/test_docs/documents/crl_revoked_leaf.odt Binary files differnew file mode 100644 index 0000000000..a97598d554 --- /dev/null +++ b/xmlsecurity/test_docs/documents/crl_revoked_leaf.odt diff --git a/xmlsecurity/test_docs/documents/crl_revoked_leaf_chain.odt b/xmlsecurity/test_docs/documents/crl_revoked_leaf_chain.odt Binary files differnew file mode 100644 index 0000000000..f82a02a454 --- /dev/null +++ b/xmlsecurity/test_docs/documents/crl_revoked_leaf_chain.odt diff --git a/xmlsecurity/test_docs/documents/crldp.odt b/xmlsecurity/test_docs/documents/crldp.odt Binary files differnew file mode 100644 index 0000000000..5cbf289de3 --- /dev/null +++ b/xmlsecurity/test_docs/documents/crldp.odt diff --git a/xmlsecurity/test_docs/documents/crldp_no_intermediate_ca_revocation_info.odt b/xmlsecurity/test_docs/documents/crldp_no_intermediate_ca_revocation_info.odt Binary files differnew file mode 100644 index 0000000000..20c28d9252 --- /dev/null +++ b/xmlsecurity/test_docs/documents/crldp_no_intermediate_ca_revocation_info.odt diff --git a/xmlsecurity/test_docs/documents/crldp_no_root_revocation_info.odt b/xmlsecurity/test_docs/documents/crldp_no_root_revocation_info.odt Binary files differnew file mode 100644 index 0000000000..d3f59e6015 --- /dev/null +++ b/xmlsecurity/test_docs/documents/crldp_no_root_revocation_info.odt diff --git a/xmlsecurity/test_docs/documents/crldp_revoked_chain.odt b/xmlsecurity/test_docs/documents/crldp_revoked_chain.odt Binary files differnew file mode 100644 index 0000000000..8c6416b808 --- /dev/null +++ b/xmlsecurity/test_docs/documents/crldp_revoked_chain.odt diff --git a/xmlsecurity/test_docs/documents/crldp_revoked_leaf.odt b/xmlsecurity/test_docs/documents/crldp_revoked_leaf.odt Binary files differnew file mode 100644 index 0000000000..fce479cc66 --- /dev/null +++ b/xmlsecurity/test_docs/documents/crldp_revoked_leaf.odt diff --git a/xmlsecurity/test_docs/documents/crldp_revoked_leaf_chain.odt b/xmlsecurity/test_docs/documents/crldp_revoked_leaf_chain.odt Binary files differnew file mode 100644 index 0000000000..53d1e01e7a --- /dev/null +++ b/xmlsecurity/test_docs/documents/crldp_revoked_leaf_chain.odt diff --git a/xmlsecurity/test_docs/documents/dn_cyrillic_bmpstring.odt b/xmlsecurity/test_docs/documents/dn_cyrillic_bmpstring.odt Binary files differnew file mode 100644 index 0000000000..1f69a32482 --- /dev/null +++ b/xmlsecurity/test_docs/documents/dn_cyrillic_bmpstring.odt diff --git a/xmlsecurity/test_docs/documents/dn_latin_ext_greak_bmpstring.odt b/xmlsecurity/test_docs/documents/dn_latin_ext_greak_bmpstring.odt Binary files differnew file mode 100644 index 0000000000..53a29310e9 --- /dev/null +++ b/xmlsecurity/test_docs/documents/dn_latin_ext_greak_bmpstring.odt diff --git a/xmlsecurity/test_docs/documents/dn_multivalue_rdn.odt b/xmlsecurity/test_docs/documents/dn_multivalue_rdn.odt Binary files differnew file mode 100644 index 0000000000..4d34bc0f58 --- /dev/null +++ b/xmlsecurity/test_docs/documents/dn_multivalue_rdn.odt diff --git a/xmlsecurity/test_docs/documents/dn_quoting.odt b/xmlsecurity/test_docs/documents/dn_quoting.odt Binary files differnew file mode 100644 index 0000000000..ca17f6aab6 --- /dev/null +++ b/xmlsecurity/test_docs/documents/dn_quoting.odt diff --git a/xmlsecurity/test_docs/documents/dn_single_multivalue_rdn.odt b/xmlsecurity/test_docs/documents/dn_single_multivalue_rdn.odt Binary files differnew file mode 100644 index 0000000000..798f25a353 --- /dev/null +++ b/xmlsecurity/test_docs/documents/dn_single_multivalue_rdn.odt diff --git a/xmlsecurity/test_docs/documents/dn_single_multivalue_rdn_with_quoting.odt b/xmlsecurity/test_docs/documents/dn_single_multivalue_rdn_with_quoting.odt Binary files differnew file mode 100644 index 0000000000..591f9aa4d6 --- /dev/null +++ b/xmlsecurity/test_docs/documents/dn_single_multivalue_rdn_with_quoting.odt diff --git a/xmlsecurity/test_docs/documents/incomplete_path.odt b/xmlsecurity/test_docs/documents/incomplete_path.odt Binary files differnew file mode 100644 index 0000000000..cb0763b0a1 --- /dev/null +++ b/xmlsecurity/test_docs/documents/incomplete_path.odt diff --git a/xmlsecurity/test_docs/documents/invalid_ooo2_x_doc1.odt b/xmlsecurity/test_docs/documents/invalid_ooo2_x_doc1.odt Binary files differnew file mode 100644 index 0000000000..f0555b1a2d --- /dev/null +++ b/xmlsecurity/test_docs/documents/invalid_ooo2_x_doc1.odt diff --git a/xmlsecurity/test_docs/documents/invalid_ooo2_x_doc2.odt b/xmlsecurity/test_docs/documents/invalid_ooo2_x_doc2.odt Binary files differnew file mode 100644 index 0000000000..b2e24fc617 --- /dev/null +++ b/xmlsecurity/test_docs/documents/invalid_ooo2_x_doc2.odt diff --git a/xmlsecurity/test_docs/documents/invalid_ooo2_x_macro1.odt b/xmlsecurity/test_docs/documents/invalid_ooo2_x_macro1.odt Binary files differnew file mode 100644 index 0000000000..640a80dced --- /dev/null +++ b/xmlsecurity/test_docs/documents/invalid_ooo2_x_macro1.odt diff --git a/xmlsecurity/test_docs/documents/invalid_ooo2_x_macro2.odt b/xmlsecurity/test_docs/documents/invalid_ooo2_x_macro2.odt Binary files differnew file mode 100644 index 0000000000..35847216be --- /dev/null +++ b/xmlsecurity/test_docs/documents/invalid_ooo2_x_macro2.odt diff --git a/xmlsecurity/test_docs/documents/invalid_ooo2_x_macro3.odt b/xmlsecurity/test_docs/documents/invalid_ooo2_x_macro3.odt Binary files differnew file mode 100644 index 0000000000..575f3a12d0 --- /dev/null +++ b/xmlsecurity/test_docs/documents/invalid_ooo2_x_macro3.odt diff --git a/xmlsecurity/test_docs/documents/invalid_ooo2_x_macro4.odt b/xmlsecurity/test_docs/documents/invalid_ooo2_x_macro4.odt Binary files differnew file mode 100644 index 0000000000..75a417cab6 --- /dev/null +++ b/xmlsecurity/test_docs/documents/invalid_ooo2_x_macro4.odt diff --git a/xmlsecurity/test_docs/documents/invalid_ooo2_x_macro5.odt b/xmlsecurity/test_docs/documents/invalid_ooo2_x_macro5.odt Binary files differnew file mode 100644 index 0000000000..f7d71762fd --- /dev/null +++ b/xmlsecurity/test_docs/documents/invalid_ooo2_x_macro5.odt diff --git a/xmlsecurity/test_docs/documents/invalid_ooo3_2_doc1.odt b/xmlsecurity/test_docs/documents/invalid_ooo3_2_doc1.odt Binary files differnew file mode 100644 index 0000000000..9984aa1bbb --- /dev/null +++ b/xmlsecurity/test_docs/documents/invalid_ooo3_2_doc1.odt diff --git a/xmlsecurity/test_docs/documents/invalid_ooo3_2_doc3.odt b/xmlsecurity/test_docs/documents/invalid_ooo3_2_doc3.odt Binary files differnew file mode 100644 index 0000000000..5ad7b68abb --- /dev/null +++ b/xmlsecurity/test_docs/documents/invalid_ooo3_2_doc3.odt diff --git a/xmlsecurity/test_docs/documents/invalid_ooo3_2_doc4.odt b/xmlsecurity/test_docs/documents/invalid_ooo3_2_doc4.odt Binary files differnew file mode 100644 index 0000000000..d126a8dff5 --- /dev/null +++ b/xmlsecurity/test_docs/documents/invalid_ooo3_2_doc4.odt diff --git a/xmlsecurity/test_docs/documents/invalid_ooo_3_2_doc2.odt b/xmlsecurity/test_docs/documents/invalid_ooo_3_2_doc2.odt Binary files differnew file mode 100644 index 0000000000..dd475c3549 --- /dev/null +++ b/xmlsecurity/test_docs/documents/invalid_ooo_3_2_doc2.odt diff --git a/xmlsecurity/test_docs/documents/ocsp_crl.odt b/xmlsecurity/test_docs/documents/ocsp_crl.odt Binary files differnew file mode 100644 index 0000000000..f8ab95c046 --- /dev/null +++ b/xmlsecurity/test_docs/documents/ocsp_crl.odt diff --git a/xmlsecurity/test_docs/documents/ocsp_crl_revoked_leaf.odt b/xmlsecurity/test_docs/documents/ocsp_crl_revoked_leaf.odt Binary files differnew file mode 100644 index 0000000000..4d7c5cd809 --- /dev/null +++ b/xmlsecurity/test_docs/documents/ocsp_crl_revoked_leaf.odt diff --git a/xmlsecurity/test_docs/documents/stateOrProvinceName.odt b/xmlsecurity/test_docs/documents/stateOrProvinceName.odt Binary files differnew file mode 100644 index 0000000000..0979ae5a9d --- /dev/null +++ b/xmlsecurity/test_docs/documents/stateOrProvinceName.odt diff --git a/xmlsecurity/test_docs/documents/valid_no_revocation.odt b/xmlsecurity/test_docs/documents/valid_no_revocation.odt Binary files differnew file mode 100644 index 0000000000..f7c9bbf5ed --- /dev/null +++ b/xmlsecurity/test_docs/documents/valid_no_revocation.odt diff --git a/xmlsecurity/test_docs/documents/valid_no_root_revocation_info.odt b/xmlsecurity/test_docs/documents/valid_no_root_revocation_info.odt Binary files differnew file mode 100644 index 0000000000..d26eb58f02 --- /dev/null +++ b/xmlsecurity/test_docs/documents/valid_no_root_revocation_info.odt diff --git a/xmlsecurity/test_docs/documents/valid_no_sub_ca_revocation_info.odt b/xmlsecurity/test_docs/documents/valid_no_sub_ca_revocation_info.odt Binary files differnew file mode 100644 index 0000000000..5d6c053c2b --- /dev/null +++ b/xmlsecurity/test_docs/documents/valid_no_sub_ca_revocation_info.odt diff --git a/xmlsecurity/test_docs/documents/valid_ooo2_x_doc1.odt b/xmlsecurity/test_docs/documents/valid_ooo2_x_doc1.odt Binary files differnew file mode 100644 index 0000000000..cb6401c164 --- /dev/null +++ b/xmlsecurity/test_docs/documents/valid_ooo2_x_doc1.odt diff --git a/xmlsecurity/test_docs/documents/valid_ooo2_x_doc_macro.odt b/xmlsecurity/test_docs/documents/valid_ooo2_x_doc_macro.odt Binary files differnew file mode 100644 index 0000000000..09b63b40a3 --- /dev/null +++ b/xmlsecurity/test_docs/documents/valid_ooo2_x_doc_macro.odt diff --git a/xmlsecurity/test_docs/documents/valid_ooo2_x_doc_unsigned_macro.odt b/xmlsecurity/test_docs/documents/valid_ooo2_x_doc_unsigned_macro.odt Binary files differnew file mode 100644 index 0000000000..e810d785d1 --- /dev/null +++ b/xmlsecurity/test_docs/documents/valid_ooo2_x_doc_unsigned_macro.odt diff --git a/xmlsecurity/test_docs/documents/valid_ooo3_0_doc1.odt b/xmlsecurity/test_docs/documents/valid_ooo3_0_doc1.odt Binary files differnew file mode 100644 index 0000000000..6c2bbd045a --- /dev/null +++ b/xmlsecurity/test_docs/documents/valid_ooo3_0_doc1.odt diff --git a/xmlsecurity/test_docs/documents/valid_ooo3_0_doc_macro.odt b/xmlsecurity/test_docs/documents/valid_ooo3_0_doc_macro.odt Binary files differnew file mode 100644 index 0000000000..b8b036cc8f --- /dev/null +++ b/xmlsecurity/test_docs/documents/valid_ooo3_0_doc_macro.odt diff --git a/xmlsecurity/test_docs/documents/valid_ooo3_0_doc_unsigned_macro.odt b/xmlsecurity/test_docs/documents/valid_ooo3_0_doc_unsigned_macro.odt Binary files differnew file mode 100644 index 0000000000..6ba0ec52a9 --- /dev/null +++ b/xmlsecurity/test_docs/documents/valid_ooo3_0_doc_unsigned_macro.odt diff --git a/xmlsecurity/test_docs/documents/valid_ooo3_2_doc1.odt b/xmlsecurity/test_docs/documents/valid_ooo3_2_doc1.odt Binary files differnew file mode 100644 index 0000000000..de1c635c19 --- /dev/null +++ b/xmlsecurity/test_docs/documents/valid_ooo3_2_doc1.odt diff --git a/xmlsecurity/test_docs/documents/valid_ooo3_2_doc_macro.odt b/xmlsecurity/test_docs/documents/valid_ooo3_2_doc_macro.odt Binary files differnew file mode 100644 index 0000000000..f6575ec885 --- /dev/null +++ b/xmlsecurity/test_docs/documents/valid_ooo3_2_doc_macro.odt diff --git a/xmlsecurity/test_docs/documents/valid_ooo3_2_doc_unsigned_macro.odt b/xmlsecurity/test_docs/documents/valid_ooo3_2_doc_unsigned_macro.odt Binary files differnew file mode 100644 index 0000000000..41f676f637 --- /dev/null +++ b/xmlsecurity/test_docs/documents/valid_ooo3_2_doc_unsigned_macro.odt diff --git a/xmlsecurity/test_docs/test_description.odt b/xmlsecurity/test_docs/test_description.odt Binary files differnew file mode 100644 index 0000000000..45bbb5b0d4 --- /dev/null +++ b/xmlsecurity/test_docs/test_description.odt diff --git a/xmlsecurity/test_docs/tools/README.txt b/xmlsecurity/test_docs/tools/README.txt new file mode 100644 index 0000000000..b253a78b69 --- /dev/null +++ b/xmlsecurity/test_docs/tools/README.txt @@ -0,0 +1,24 @@ +httpserv +============ +Simple http server for testing of Certificate Revocation Lists (CRL). + +Netbeans 6.7.1 project. httpserv.jar requires java 6. + +Run with + +java -jar httpserv/dist/httpserv.jar --accept portnumber + +portnumber: an arbitrary port number to which the server should listen. + +httpserv looks for the requested file relative to the current directory. For +example, you are in +$(SRC_ROOT)/xmlsecurity/$(INPATH)/httpserv/dist/javadoc, +a directory which contains the index.html. From there you run httpserv.jar: + +java -jar <path_to_wherever_it_is>/httpserv.jar --accept 8000 + +now enter in the Browser: + +localhost:8000/index.html + + diff --git a/xmlsecurity/test_docs/tools/httpserv/build.xml b/xmlsecurity/test_docs/tools/httpserv/build.xml new file mode 100644 index 0000000000..3492d3aa61 --- /dev/null +++ b/xmlsecurity/test_docs/tools/httpserv/build.xml @@ -0,0 +1,79 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- You may freely edit this file. See commented blocks below for --> +<!-- some examples of how to customize the build. --> +<!-- (If you delete it and reopen the project it will be recreated.) --> +<!-- By default, only the Clean and Build commands use this build script. --> +<!-- Commands such as Run, Debug, and Test only use this build script if --> +<!-- the Compile on Save feature is turned off for the project. --> +<!-- You can turn off the Compile on Save (or Deploy on Save) setting --> +<!-- in the project's Project Properties dialog box.--> +<project name="httpserv" default="default" basedir="."> + <description>Builds, tests, and runs the project httpserv.</description> + <import file="nbproject/build-impl.xml"/> + <!-- + + There exist several targets which are by default empty and which can be + used for execution of your tasks. These targets are usually executed + before and after some main targets. They are: + + -pre-init: called before initialization of project properties + -post-init: called after initialization of project properties + -pre-compile: called before javac compilation + -post-compile: called after javac compilation + -pre-compile-single: called before javac compilation of single file + -post-compile-single: called after javac compilation of single file + -pre-compile-test: called before javac compilation of JUnit tests + -post-compile-test: called after javac compilation of JUnit tests + -pre-compile-test-single: called before javac compilation of single JUnit test + -post-compile-test-single: called after javac compilation of single JUnit test + -pre-jar: called before JAR building + -post-jar: called after JAR building + -post-clean: called after cleaning build products + + (Targets beginning with '-' are not intended to be called on their own.) + + Example of inserting an obfuscator after compilation could look like this: + + <target name="-post-compile"> + <obfuscate> + <fileset dir="${build.classes.dir}"/> + </obfuscate> + </target> + + For list of available properties check the imported + nbproject/build-impl.xml file. + + + Another way to customize the build is by overriding existing main targets. + The targets of interest are: + + -init-macrodef-javac: defines macro for javac compilation + -init-macrodef-junit: defines macro for junit execution + -init-macrodef-debug: defines macro for class debugging + -init-macrodef-java: defines macro for class execution + -do-jar-with-manifest: JAR building (if you are using a manifest) + -do-jar-without-manifest: JAR building (if you are not using a manifest) + run: execution of project + -javadoc-build: Javadoc generation + test-report: JUnit report generation + + An example of overriding the target for project execution could look like this: + + <target name="run" depends="httpserv-impl.jar"> + <exec dir="bin" executable="launcher.exe"> + <arg file="${dist.jar}"/> + </exec> + </target> + + Notice that the overridden target depends on the jar target and not only on + the compile target as the regular run target does. Again, for a list of available + properties which you can use, check the target you are overriding in the + nbproject/build-impl.xml file. + + --> + <!-- Import the environment as properties to make them available in project.properties + --> + <target name="-pre-init"> + <property environment="env" /> + </target> +</project> diff --git a/xmlsecurity/test_docs/tools/httpserv/manifest.mf b/xmlsecurity/test_docs/tools/httpserv/manifest.mf new file mode 100644 index 0000000000..328e8e5bc3 --- /dev/null +++ b/xmlsecurity/test_docs/tools/httpserv/manifest.mf @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +X-COMMENT: Main-Class will be added automatically by build + diff --git a/xmlsecurity/test_docs/tools/httpserv/nbproject/build-impl.xml b/xmlsecurity/test_docs/tools/httpserv/nbproject/build-impl.xml new file mode 100644 index 0000000000..9064a3305e --- /dev/null +++ b/xmlsecurity/test_docs/tools/httpserv/nbproject/build-impl.xml @@ -0,0 +1,700 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +*** GENERATED FROM project.xml - DO NOT EDIT *** +*** EDIT ../build.xml INSTEAD *** + +For the purpose of easier reading the script +is divided into following sections: + + - initialization + - compilation + - jar + - execution + - debugging + - javadoc + - junit compilation + - junit execution + - junit debugging + - applet + - cleanup + + --> +<project xmlns:j2seproject1="http://www.netbeans.org/ns/j2se-project/1" xmlns:j2seproject3="http://www.netbeans.org/ns/j2se-project/3" xmlns:jaxrpc="http://www.netbeans.org/ns/j2se-project/jax-rpc" basedir=".." default="default" name="httpserv-impl"> + <fail message="Please build using Ant 1.7.1 or higher."> + <condition> + <not> + <antversion atleast="1.7.1"/> + </not> + </condition> + </fail> + <target depends="test,jar,javadoc" description="Build and test whole project." name="default"/> + <!-- + ====================== + INITIALIZATION SECTION + ====================== + --> + <target name="-pre-init"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target depends="-pre-init" name="-init-private"> + <property file="nbproject/private/config.properties"/> + <property file="nbproject/private/configs/${config}.properties"/> + <property file="nbproject/private/private.properties"/> + </target> + <target depends="-pre-init,-init-private" name="-init-user"> + <property file="${user.properties.file}"/> + <!-- The two properties below are usually overridden --> + <!-- by the active platform. Just a fallback. --> + <property name="default.javac.source" value="1.4"/> + <property name="default.javac.target" value="1.4"/> + </target> + <target depends="-pre-init,-init-private,-init-user" name="-init-project"> + <property file="nbproject/configs/${config}.properties"/> + <property file="nbproject/project.properties"/> + </target> + <target depends="-pre-init,-init-private,-init-user,-init-project,-init-macrodef-property" name="-do-init"> + <available file="${manifest.file}" property="manifest.available"/> + <condition property="manifest.available+main.class"> + <and> + <isset property="manifest.available"/> + <isset property="main.class"/> + <not> + <equals arg1="${main.class}" arg2="" trim="true"/> + </not> + </and> + </condition> + <condition property="manifest.available+main.class+mkdist.available"> + <and> + <istrue value="${manifest.available+main.class}"/> + <isset property="libs.CopyLibs.classpath"/> + </and> + </condition> + <condition property="have.tests"> + <or> + <available file="${test.src.dir}"/> + </or> + </condition> + <condition property="have.sources"> + <or> + <available file="${src.dir}"/> + </or> + </condition> + <condition property="netbeans.home+have.tests"> + <and> + <isset property="netbeans.home"/> + <isset property="have.tests"/> + </and> + </condition> + <condition property="no.javadoc.preview"> + <and> + <isset property="javadoc.preview"/> + <isfalse value="${javadoc.preview}"/> + </and> + </condition> + <property name="run.jvmargs" value=""/> + <property name="javac.compilerargs" value=""/> + <property name="work.dir" value="${basedir}"/> + <condition property="no.deps"> + <and> + <istrue value="${no.dependencies}"/> + </and> + </condition> + <property name="javac.debug" value="true"/> + <property name="javadoc.preview" value="true"/> + <property name="application.args" value=""/> + <property name="source.encoding" value="${file.encoding}"/> + <condition property="javadoc.encoding.used" value="${javadoc.encoding}"> + <and> + <isset property="javadoc.encoding"/> + <not> + <equals arg1="${javadoc.encoding}" arg2=""/> + </not> + </and> + </condition> + <property name="javadoc.encoding.used" value="${source.encoding}"/> + <property name="includes" value="**"/> + <property name="excludes" value=""/> + <property name="do.depend" value="false"/> + <condition property="do.depend.true"> + <istrue value="${do.depend}"/> + </condition> + <condition else="" property="javac.compilerargs.jaxws" value="-Djava.endorsed.dirs='${jaxws.endorsed.dir}'"> + <and> + <isset property="jaxws.endorsed.dir"/> + <available file="nbproject/jaxws-build.xml"/> + </and> + </condition> + </target> + <target name="-post-init"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target depends="-pre-init,-init-private,-init-user,-init-project,-do-init" name="-init-check"> + <fail unless="src.dir">Must set src.dir</fail> + <fail unless="test.src.dir">Must set test.src.dir</fail> + <fail unless="build.dir">Must set build.dir</fail> + <fail unless="dist.dir">Must set dist.dir</fail> + <fail unless="build.classes.dir">Must set build.classes.dir</fail> + <fail unless="dist.javadoc.dir">Must set dist.javadoc.dir</fail> + <fail unless="build.test.classes.dir">Must set build.test.classes.dir</fail> + <fail unless="build.test.results.dir">Must set build.test.results.dir</fail> + <fail unless="build.classes.excludes">Must set build.classes.excludes</fail> + <fail unless="dist.jar">Must set dist.jar</fail> + </target> + <target name="-init-macrodef-property"> + <macrodef name="property" uri="http://www.netbeans.org/ns/j2se-project/1"> + <attribute name="name"/> + <attribute name="value"/> + <sequential> + <property name="@{name}" value="${@{value}}"/> + </sequential> + </macrodef> + </target> + <target name="-init-macrodef-javac"> + <macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3"> + <attribute default="${src.dir}" name="srcdir"/> + <attribute default="${build.classes.dir}" name="destdir"/> + <attribute default="${javac.classpath}" name="classpath"/> + <attribute default="${includes}" name="includes"/> + <attribute default="${excludes}" name="excludes"/> + <attribute default="${javac.debug}" name="debug"/> + <attribute default="${empty.dir}" name="sourcepath"/> + <attribute default="${empty.dir}" name="gensrcdir"/> + <element name="customize" optional="true"/> + <sequential> + <property location="${build.dir}/empty" name="empty.dir"/> + <mkdir dir="${empty.dir}"/> + <javac debug="@{debug}" deprecation="${javac.deprecation}" destdir="@{destdir}" encoding="${source.encoding}" excludes="@{excludes}" includeantruntime="false" includes="@{includes}" source="${javac.source}" sourcepath="@{sourcepath}" srcdir="@{srcdir}" target="${javac.target}"> + <src> + <dirset dir="@{gensrcdir}" erroronmissingdir="false"> + <include name="*"/> + </dirset> + </src> + <classpath> + <path path="@{classpath}"/> + </classpath> + <compilerarg line="${javac.compilerargs} ${javac.compilerargs.jaxws}"/> + <customize/> + </javac> + </sequential> + </macrodef> + <macrodef name="depend" uri="http://www.netbeans.org/ns/j2se-project/3"> + <attribute default="${src.dir}" name="srcdir"/> + <attribute default="${build.classes.dir}" name="destdir"/> + <attribute default="${javac.classpath}" name="classpath"/> + <sequential> + <depend cache="${build.dir}/depcache" destdir="@{destdir}" excludes="${excludes}" includes="${includes}" srcdir="@{srcdir}"> + <classpath> + <path path="@{classpath}"/> + </classpath> + </depend> + </sequential> + </macrodef> + <macrodef name="force-recompile" uri="http://www.netbeans.org/ns/j2se-project/3"> + <attribute default="${build.classes.dir}" name="destdir"/> + <sequential> + <fail unless="javac.includes">Must set javac.includes</fail> + <pathconvert pathsep="," property="javac.includes.binary"> + <path> + <filelist dir="@{destdir}" files="${javac.includes}"/> + </path> + <globmapper from="*.java" to="*.class"/> + </pathconvert> + <delete> + <files includes="${javac.includes.binary}"/> + </delete> + </sequential> + </macrodef> + </target> + <target name="-init-macrodef-junit"> + <macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3"> + <attribute default="${includes}" name="includes"/> + <attribute default="${excludes}" name="excludes"/> + <attribute default="**" name="testincludes"/> + <sequential> + <junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" showoutput="true"> + <batchtest todir="${build.test.results.dir}"> + <fileset dir="${test.src.dir}" excludes="@{excludes},${excludes}" includes="@{includes}"> + <filename name="@{testincludes}"/> + </fileset> + </batchtest> + <classpath> + <path path="${run.test.classpath}"/> + </classpath> + <syspropertyset> + <propertyref prefix="test-sys-prop."/> + <mapper from="test-sys-prop.*" to="*" type="glob"/> + </syspropertyset> + <formatter type="brief" usefile="false"/> + <formatter type="xml"/> + <jvmarg line="${run.jvmargs}"/> + </junit> + </sequential> + </macrodef> + </target> + <target depends="-init-debug-args" name="-init-macrodef-nbjpda"> + <macrodef name="nbjpdastart" uri="http://www.netbeans.org/ns/j2se-project/1"> + <attribute default="${main.class}" name="name"/> + <attribute default="${debug.classpath}" name="classpath"/> + <attribute default="" name="stopclassname"/> + <sequential> + <nbjpdastart addressproperty="jpda.address" name="@{name}" stopclassname="@{stopclassname}" transport="${debug-transport}"> + <classpath> + <path path="@{classpath}"/> + </classpath> + </nbjpdastart> + </sequential> + </macrodef> + <macrodef name="nbjpdareload" uri="http://www.netbeans.org/ns/j2se-project/1"> + <attribute default="${build.classes.dir}" name="dir"/> + <sequential> + <nbjpdareload> + <fileset dir="@{dir}" includes="${fix.classes}"> + <include name="${fix.includes}*.class"/> + </fileset> + </nbjpdareload> + </sequential> + </macrodef> + </target> + <target name="-init-debug-args"> + <property name="version-output" value="java version "${ant.java.version}"/> + <condition property="have-jdk-older-than-1.4"> + <or> + <contains string="${version-output}" substring="java version "1.0"/> + <contains string="${version-output}" substring="java version "1.1"/> + <contains string="${version-output}" substring="java version "1.2"/> + <contains string="${version-output}" substring="java version "1.3"/> + </or> + </condition> + <condition else="-Xdebug" property="debug-args-line" value="-Xdebug -Xnoagent -Djava.compiler=none"> + <istrue value="${have-jdk-older-than-1.4}"/> + </condition> + <condition else="dt_socket" property="debug-transport-by-os" value="dt_shmem"> + <os family="windows"/> + </condition> + <condition else="${debug-transport-by-os}" property="debug-transport" value="${debug.transport}"> + <isset property="debug.transport"/> + </condition> + </target> + <target depends="-init-debug-args" name="-init-macrodef-debug"> + <macrodef name="debug" uri="http://www.netbeans.org/ns/j2se-project/3"> + <attribute default="${main.class}" name="classname"/> + <attribute default="${debug.classpath}" name="classpath"/> + <element name="customize" optional="true"/> + <sequential> + <java classname="@{classname}" dir="${work.dir}" fork="true"> + <jvmarg line="${debug-args-line}"/> + <jvmarg value="-Xrunjdwp:transport=${debug-transport},address=${jpda.address}"/> + <jvmarg value="-Dfile.encoding=${source.encoding}"/> + <redirector errorencoding="${source.encoding}" inputencoding="${source.encoding}" outputencoding="${source.encoding}"/> + <jvmarg line="${run.jvmargs}"/> + <classpath> + <path path="@{classpath}"/> + </classpath> + <syspropertyset> + <propertyref prefix="run-sys-prop."/> + <mapper from="run-sys-prop.*" to="*" type="glob"/> + </syspropertyset> + <customize/> + </java> + </sequential> + </macrodef> + </target> + <target name="-init-macrodef-java"> + <macrodef name="java" uri="http://www.netbeans.org/ns/j2se-project/1"> + <attribute default="${main.class}" name="classname"/> + <attribute default="${run.classpath}" name="classpath"/> + <element name="customize" optional="true"/> + <sequential> + <java classname="@{classname}" dir="${work.dir}" fork="true"> + <jvmarg value="-Dfile.encoding=${source.encoding}"/> + <redirector errorencoding="${source.encoding}" inputencoding="${source.encoding}" outputencoding="${source.encoding}"/> + <jvmarg line="${run.jvmargs}"/> + <classpath> + <path path="@{classpath}"/> + </classpath> + <syspropertyset> + <propertyref prefix="run-sys-prop."/> + <mapper from="run-sys-prop.*" to="*" type="glob"/> + </syspropertyset> + <customize/> + </java> + </sequential> + </macrodef> + </target> + <target name="-init-presetdef-jar"> + <presetdef name="jar" uri="http://www.netbeans.org/ns/j2se-project/1"> + <jar compress="${jar.compress}" jarfile="${dist.jar}"> + <j2seproject1:fileset dir="${build.classes.dir}"/> + </jar> + </presetdef> + </target> + <target depends="-pre-init,-init-private,-init-user,-init-project,-do-init,-post-init,-init-check,-init-macrodef-property,-init-macrodef-javac,-init-macrodef-junit,-init-macrodef-nbjpda,-init-macrodef-debug,-init-macrodef-java,-init-presetdef-jar" name="init"/> + <!-- + =================== + COMPILATION SECTION + =================== + --> + <target depends="init" name="deps-jar" unless="no.deps"/> + <target depends="init,-check-automatic-build,-clean-after-automatic-build" name="-verify-automatic-build"/> + <target depends="init" name="-check-automatic-build"> + <available file="${build.classes.dir}/.netbeans_automatic_build" property="netbeans.automatic.build"/> + </target> + <target depends="init" if="netbeans.automatic.build" name="-clean-after-automatic-build"> + <antcall target="clean"/> + </target> + <target depends="init,deps-jar" name="-pre-pre-compile"> + <mkdir dir="${build.classes.dir}"/> + </target> + <target name="-pre-compile"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target if="do.depend.true" name="-compile-depend"> + <pathconvert property="build.generated.subdirs"> + <dirset dir="${build.generated.sources.dir}" erroronmissingdir="false"> + <include name="*"/> + </dirset> + </pathconvert> + <j2seproject3:depend srcdir="${src.dir}:${build.generated.subdirs}"/> + </target> + <target depends="init,deps-jar,-pre-pre-compile,-pre-compile,-compile-depend" if="have.sources" name="-do-compile"> + <j2seproject3:javac gensrcdir="${build.generated.sources.dir}"/> + <copy todir="${build.classes.dir}"> + <fileset dir="${src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/> + </copy> + </target> + <target name="-post-compile"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile,-do-compile,-post-compile" description="Compile project." name="compile"/> + <target name="-pre-compile-single"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target depends="init,deps-jar,-pre-pre-compile" name="-do-compile-single"> + <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail> + <j2seproject3:force-recompile/> + <j2seproject3:javac excludes="" gensrcdir="${build.generated.sources.dir}" includes="${javac.includes}" sourcepath="${src.dir}"/> + </target> + <target name="-post-compile-single"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile-single,-do-compile-single,-post-compile-single" name="compile-single"/> + <!-- + ==================== + JAR BUILDING SECTION + ==================== + --> + <target depends="init" name="-pre-pre-jar"> + <dirname file="${dist.jar}" property="dist.jar.dir"/> + <mkdir dir="${dist.jar.dir}"/> + </target> + <target name="-pre-jar"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target depends="init,compile,-pre-pre-jar,-pre-jar" name="-do-jar-without-manifest" unless="manifest.available"> + <j2seproject1:jar/> + </target> + <target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available" name="-do-jar-with-manifest" unless="manifest.available+main.class"> + <j2seproject1:jar manifest="${manifest.file}"/> + </target> + <target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available+main.class" name="-do-jar-with-mainclass" unless="manifest.available+main.class+mkdist.available"> + <j2seproject1:jar manifest="${manifest.file}"> + <j2seproject1:manifest> + <j2seproject1:attribute name="Main-Class" value="${main.class}"/> + </j2seproject1:manifest> + </j2seproject1:jar> + <echo>To run this application from the command line without Ant, try:</echo> + <property location="${build.classes.dir}" name="build.classes.dir.resolved"/> + <property location="${dist.jar}" name="dist.jar.resolved"/> + <pathconvert property="run.classpath.with.dist.jar"> + <path path="${run.classpath}"/> + <map from="${build.classes.dir.resolved}" to="${dist.jar.resolved}"/> + </pathconvert> + <echo>java -cp "${run.classpath.with.dist.jar}" ${main.class}</echo> + </target> + <target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available+main.class+mkdist.available" name="-do-jar-with-libraries"> + <property location="${build.classes.dir}" name="build.classes.dir.resolved"/> + <pathconvert property="run.classpath.without.build.classes.dir"> + <path path="${run.classpath}"/> + <map from="${build.classes.dir.resolved}" to=""/> + </pathconvert> + <pathconvert pathsep=" " property="jar.classpath"> + <path path="${run.classpath.without.build.classes.dir}"/> + <chainedmapper> + <flattenmapper/> + <globmapper from="*" to="lib/*"/> + </chainedmapper> + </pathconvert> + <taskdef classname="org.netbeans.modules.java.j2seproject.copylibstask.CopyLibs" classpath="${libs.CopyLibs.classpath}" name="copylibs"/> + <copylibs compress="${jar.compress}" jarfile="${dist.jar}" manifest="${manifest.file}" runtimeclasspath="${run.classpath.without.build.classes.dir}"> + <fileset dir="${build.classes.dir}"/> + <manifest> + <attribute name="Main-Class" value="${main.class}"/> + <attribute name="Class-Path" value="${jar.classpath}"/> + </manifest> + </copylibs> + <echo>To run this application from the command line without Ant, try:</echo> + <property location="${dist.jar}" name="dist.jar.resolved"/> + <echo>java -jar "${dist.jar.resolved}"</echo> + </target> + <target depends="init,compile,-pre-pre-jar,-pre-jar" if="libs.CopyLibs.classpath" name="-do-jar-with-libraries-without-manifest" unless="manifest.available+main.class"> + <property location="${build.classes.dir}" name="build.classes.dir.resolved"/> + <pathconvert property="run.classpath.without.build.classes.dir"> + <path path="${run.classpath}"/> + <map from="${build.classes.dir.resolved}" to=""/> + </pathconvert> + <pathconvert pathsep=" " property="jar.classpath"> + <path path="${run.classpath.without.build.classes.dir}"/> + <chainedmapper> + <flattenmapper/> + <globmapper from="*" to="lib/*"/> + </chainedmapper> + </pathconvert> + <taskdef classname="org.netbeans.modules.java.j2seproject.copylibstask.CopyLibs" classpath="${libs.CopyLibs.classpath}" name="copylibs"/> + <copylibs compress="${jar.compress}" jarfile="${dist.jar}" runtimeclasspath="${run.classpath.without.build.classes.dir}"> + <fileset dir="${build.classes.dir}"/> + </copylibs> + </target> + <target name="-post-jar"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target depends="init,compile,-pre-jar,-do-jar-with-manifest,-do-jar-without-manifest,-do-jar-with-mainclass,-do-jar-with-libraries,-do-jar-with-libraries-without-manifest,-post-jar" description="Build JAR." name="jar"/> + <!-- + ================= + EXECUTION SECTION + ================= + --> + <target depends="init,compile" description="Run a main class." name="run"> + <j2seproject1:java> + <customize> + <arg line="${application.args}"/> + </customize> + </j2seproject1:java> + </target> + <target name="-do-not-recompile"> + <property name="javac.includes.binary" value=""/> + </target> + <target depends="init,-do-not-recompile,compile-single" name="run-single"> + <fail unless="run.class">Must select one file in the IDE or set run.class</fail> + <j2seproject1:java classname="${run.class}"/> + </target> + <target depends="init,-do-not-recompile,compile-test-single" name="run-test-with-main"> + <fail unless="run.class">Must select one file in the IDE or set run.class</fail> + <j2seproject1:java classname="${run.class}" classpath="${run.test.classpath}"/> + </target> + <!-- + ================= + DEBUGGING SECTION + ================= + --> + <target depends="init" if="netbeans.home" name="-debug-start-debugger"> + <j2seproject1:nbjpdastart name="${debug.class}"/> + </target> + <target depends="init" if="netbeans.home" name="-debug-start-debugger-main-test"> + <j2seproject1:nbjpdastart classpath="${debug.test.classpath}" name="${debug.class}"/> + </target> + <target depends="init,compile" name="-debug-start-debuggee"> + <j2seproject3:debug> + <customize> + <arg line="${application.args}"/> + </customize> + </j2seproject3:debug> + </target> + <target depends="init,compile,-debug-start-debugger,-debug-start-debuggee" description="Debug project in IDE." if="netbeans.home" name="debug"/> + <target depends="init" if="netbeans.home" name="-debug-start-debugger-stepinto"> + <j2seproject1:nbjpdastart stopclassname="${main.class}"/> + </target> + <target depends="init,compile,-debug-start-debugger-stepinto,-debug-start-debuggee" if="netbeans.home" name="debug-stepinto"/> + <target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-single"> + <fail unless="debug.class">Must select one file in the IDE or set debug.class</fail> + <j2seproject3:debug classname="${debug.class}"/> + </target> + <target depends="init,-do-not-recompile,compile-single,-debug-start-debugger,-debug-start-debuggee-single" if="netbeans.home" name="debug-single"/> + <target depends="init,compile-test-single" if="netbeans.home" name="-debug-start-debuggee-main-test"> + <fail unless="debug.class">Must select one file in the IDE or set debug.class</fail> + <j2seproject3:debug classname="${debug.class}" classpath="${debug.test.classpath}"/> + </target> + <target depends="init,-do-not-recompile,compile-test-single,-debug-start-debugger-main-test,-debug-start-debuggee-main-test" if="netbeans.home" name="debug-test-with-main"/> + <target depends="init" name="-pre-debug-fix"> + <fail unless="fix.includes">Must set fix.includes</fail> + <property name="javac.includes" value="${fix.includes}.java"/> + </target> + <target depends="init,-pre-debug-fix,compile-single" if="netbeans.home" name="-do-debug-fix"> + <j2seproject1:nbjpdareload/> + </target> + <target depends="init,-pre-debug-fix,-do-debug-fix" if="netbeans.home" name="debug-fix"/> + <!-- + =============== + JAVADOC SECTION + =============== + --> + <target depends="init" name="-javadoc-build"> + <mkdir dir="${dist.javadoc.dir}"/> + <javadoc additionalparam="${javadoc.additionalparam}" author="${javadoc.author}" charset="UTF-8" destdir="${dist.javadoc.dir}" docencoding="UTF-8" encoding="${javadoc.encoding.used}" failonerror="true" noindex="${javadoc.noindex}" nonavbar="${javadoc.nonavbar}" notree="${javadoc.notree}" private="${javadoc.private}" source="${javac.source}" splitindex="${javadoc.splitindex}" use="${javadoc.use}" useexternalfile="true" version="${javadoc.version}" windowtitle="${javadoc.windowtitle}"> + <classpath> + <path path="${javac.classpath}"/> + </classpath> + <fileset dir="${src.dir}" excludes="${excludes}" includes="${includes}"> + <filename name="**/*.java"/> + </fileset> + <fileset dir="${build.generated.sources.dir}" erroronmissingdir="false"> + <include name="**/*.java"/> + </fileset> + </javadoc> + </target> + <target depends="init,-javadoc-build" if="netbeans.home" name="-javadoc-browse" unless="no.javadoc.preview"> + <nbbrowse file="${dist.javadoc.dir}/index.html"/> + </target> + <target depends="init,-javadoc-build,-javadoc-browse" description="Build Javadoc." name="javadoc"/> + <!-- + ========================= + JUNIT COMPILATION SECTION + ========================= + --> + <target depends="init,compile" if="have.tests" name="-pre-pre-compile-test"> + <mkdir dir="${build.test.classes.dir}"/> + </target> + <target name="-pre-compile-test"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target if="do.depend.true" name="-compile-test-depend"> + <j2seproject3:depend classpath="${javac.test.classpath}" destdir="${build.test.classes.dir}" srcdir="${test.src.dir}"/> + </target> + <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-compile-test-depend" if="have.tests" name="-do-compile-test"> + <j2seproject3:javac classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" srcdir="${test.src.dir}"/> + <copy todir="${build.test.classes.dir}"> + <fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/> + </copy> + </target> + <target name="-post-compile-test"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-do-compile-test,-post-compile-test" name="compile-test"/> + <target name="-pre-compile-test-single"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single" if="have.tests" name="-do-compile-test-single"> + <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail> + <j2seproject3:force-recompile destdir="${build.test.classes.dir}"/> + <j2seproject3:javac classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" excludes="" includes="${javac.includes}" sourcepath="${test.src.dir}" srcdir="${test.src.dir}"/> + <copy todir="${build.test.classes.dir}"> + <fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/> + </copy> + </target> + <target name="-post-compile-test-single"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single,-do-compile-test-single,-post-compile-test-single" name="compile-test-single"/> + <!-- + ======================= + JUNIT EXECUTION SECTION + ======================= + --> + <target depends="init" if="have.tests" name="-pre-test-run"> + <mkdir dir="${build.test.results.dir}"/> + </target> + <target depends="init,compile-test,-pre-test-run" if="have.tests" name="-do-test-run"> + <j2seproject3:junit testincludes="**/*Test.java"/> + </target> + <target depends="init,compile-test,-pre-test-run,-do-test-run" if="have.tests" name="-post-test-run"> + <fail if="tests.failed" unless="ignore.failing.tests">Some tests failed; see details above.</fail> + </target> + <target depends="init" if="have.tests" name="test-report"/> + <target depends="init" if="netbeans.home+have.tests" name="-test-browse"/> + <target depends="init,compile-test,-pre-test-run,-do-test-run,test-report,-post-test-run,-test-browse" description="Run unit tests." name="test"/> + <target depends="init" if="have.tests" name="-pre-test-run-single"> + <mkdir dir="${build.test.results.dir}"/> + </target> + <target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-do-test-run-single"> + <fail unless="test.includes">Must select some files in the IDE or set test.includes</fail> + <j2seproject3:junit excludes="" includes="${test.includes}"/> + </target> + <target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single" if="have.tests" name="-post-test-run-single"> + <fail if="tests.failed" unless="ignore.failing.tests">Some tests failed; see details above.</fail> + </target> + <target depends="init,-do-not-recompile,compile-test-single,-pre-test-run-single,-do-test-run-single,-post-test-run-single" description="Run single unit test." name="test-single"/> + <!-- + ======================= + JUNIT DEBUGGING SECTION + ======================= + --> + <target depends="init,compile-test" if="have.tests" name="-debug-start-debuggee-test"> + <fail unless="test.class">Must select one file in the IDE or set test.class</fail> + <property location="${build.test.results.dir}/TEST-${test.class}.xml" name="test.report.file"/> + <delete file="${test.report.file}"/> + <mkdir dir="${build.test.results.dir}"/> + <j2seproject3:debug classname="org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner" classpath="${ant.home}/lib/ant.jar:${ant.home}/lib/ant-junit.jar:${debug.test.classpath}"> + <customize> + <syspropertyset> + <propertyref prefix="test-sys-prop."/> + <mapper from="test-sys-prop.*" to="*" type="glob"/> + </syspropertyset> + <arg value="${test.class}"/> + <arg value="showoutput=true"/> + <arg value="formatter=org.apache.tools.ant.taskdefs.optional.junit.BriefJUnitResultFormatter"/> + <arg value="formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,${test.report.file}"/> + </customize> + </j2seproject3:debug> + </target> + <target depends="init,compile-test" if="netbeans.home+have.tests" name="-debug-start-debugger-test"> + <j2seproject1:nbjpdastart classpath="${debug.test.classpath}" name="${test.class}"/> + </target> + <target depends="init,-do-not-recompile,compile-test-single,-debug-start-debugger-test,-debug-start-debuggee-test" name="debug-test"/> + <target depends="init,-pre-debug-fix,compile-test-single" if="netbeans.home" name="-do-debug-fix-test"> + <j2seproject1:nbjpdareload dir="${build.test.classes.dir}"/> + </target> + <target depends="init,-pre-debug-fix,-do-debug-fix-test" if="netbeans.home" name="debug-fix-test"/> + <!-- + ========================= + APPLET EXECUTION SECTION + ========================= + --> + <target depends="init,compile-single" name="run-applet"> + <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail> + <j2seproject1:java classname="sun.applet.AppletViewer"> + <customize> + <arg value="${applet.url}"/> + </customize> + </j2seproject1:java> + </target> + <!-- + ========================= + APPLET DEBUGGING SECTION + ========================= + --> + <target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-applet"> + <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail> + <j2seproject3:debug classname="sun.applet.AppletViewer"> + <customize> + <arg value="${applet.url}"/> + </customize> + </j2seproject3:debug> + </target> + <target depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-applet" if="netbeans.home" name="debug-applet"/> + <!-- + =============== + CLEANUP SECTION + =============== + --> + <target depends="init" name="deps-clean" unless="no.deps"/> + <target depends="init" name="-do-clean"> + <delete dir="${build.dir}"/> + <delete dir="${dist.dir}"/> + </target> + <target name="-post-clean"> + <!-- Empty placeholder for easier customization. --> + <!-- You can override this target in the ../build.xml file. --> + </target> + <target depends="init,deps-clean,-do-clean,-post-clean" description="Clean build products." name="clean"/> +</project> diff --git a/xmlsecurity/test_docs/tools/httpserv/nbproject/genfiles.properties b/xmlsecurity/test_docs/tools/httpserv/nbproject/genfiles.properties new file mode 100644 index 0000000000..d8139c8889 --- /dev/null +++ b/xmlsecurity/test_docs/tools/httpserv/nbproject/genfiles.properties @@ -0,0 +1,9 @@ +# x-no-translate +build.xml.data.CRC32=8071b819 +build.xml.script.CRC32=deb21e95 +build.xml.stylesheet.CRC32=958a1d3e@1.26.2.45 +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. +nbproject/build-impl.xml.data.CRC32=8071b819 +nbproject/build-impl.xml.script.CRC32=21d1be7e +nbproject/build-impl.xml.stylesheet.CRC32=5c621a33@1.26.2.45 diff --git a/xmlsecurity/test_docs/tools/httpserv/nbproject/project.properties b/xmlsecurity/test_docs/tools/httpserv/nbproject/project.properties new file mode 100644 index 0000000000..a0ec60ac7c --- /dev/null +++ b/xmlsecurity/test_docs/tools/httpserv/nbproject/project.properties @@ -0,0 +1,65 @@ +# x-no-translate +application.title=httpserv +application.vendor=jochen +build.classes.dir=${build.dir}/classes +build.classes.excludes=**/*.java,**/*.form +# This directory is removed when the project is cleaned: +build.dir=build +build.generated.dir=${build.dir}/generated +build.generated.sources.dir=${build.dir}/generated-sources +# Only compile against the classpath explicitly listed here: +build.sysclasspath=ignore +build.test.classes.dir=${build.dir}/test/classes +build.test.results.dir=${build.dir}/test/results +# Uncomment to specify the preferred debugger connection transport: +#debug.transport=dt_socket +debug.classpath=\ + ${run.classpath} +debug.test.classpath=\ + ${run.test.classpath} +# This directory is removed when the project is cleaned: +dist.dir=../../../${env.INPATH}/misc/httpserv +dist.jar=${dist.dir}/httpserv.jar +dist.javadoc.dir=${dist.dir}/javadoc +excludes= +includes=** +jar.compress=false +javac.classpath= +# Space-separated list of extra javac options +javac.compilerargs= +javac.deprecation=false +javac.source=1.5 +javac.target=1.5 +javac.test.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir}:\ + ${libs.junit.classpath}:\ + ${libs.junit_4.classpath} +javadoc.additionalparam= +javadoc.author=false +javadoc.encoding=${source.encoding} +javadoc.noindex=false +javadoc.nonavbar=false +javadoc.notree=false +javadoc.private=false +javadoc.splitindex=true +javadoc.use=true +javadoc.version=false +javadoc.windowtitle= +main.class=httpserv.Main +manifest.file=manifest.mf +meta.inf.dir=${src.dir}/META-INF +platform.active=default_platform +run.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir} +# Space-separated list of JVM arguments used when running the project +# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value +# or test-sys-prop.name=value to set system properties for unit tests): +run.jvmargs= +run.test.classpath=\ + ${javac.test.classpath}:\ + ${build.test.classes.dir} +source.encoding=UTF-8 +src.dir=src +test.src.dir=test diff --git a/xmlsecurity/test_docs/tools/httpserv/nbproject/project.xml b/xmlsecurity/test_docs/tools/httpserv/nbproject/project.xml new file mode 100644 index 0000000000..6fc771ca76 --- /dev/null +++ b/xmlsecurity/test_docs/tools/httpserv/nbproject/project.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://www.netbeans.org/ns/project/1"> + <type>org.netbeans.modules.java.j2seproject</type> + <configuration> + <data xmlns="http://www.netbeans.org/ns/j2se-project/3"> + <name>httpserv</name> + <source-roots> + <root id="src.dir"/> + </source-roots> + <test-roots> + <root id="test.src.dir"/> + </test-roots> + </data> + </configuration> +</project> diff --git a/xmlsecurity/test_docs/tools/httpserv/src/httpserv/Main.java b/xmlsecurity/test_docs/tools/httpserv/src/httpserv/Main.java new file mode 100644 index 0000000000..1f9fd91d23 --- /dev/null +++ b/xmlsecurity/test_docs/tools/httpserv/src/httpserv/Main.java @@ -0,0 +1,190 @@ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +package httpserv; + +import com.sun.net.httpserver.Headers; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.net.InetSocketAddress; + +public class Main { + + /** + * @param args the command line arguments + */ + public static void main(String[] args) { + try { + + Option[] opts = new Option[2]; + opts[0] = new Option("--help", "-h", false); + opts[1] = new Option("--accept", "-a", true); + if (!parseOptions(args, opts)) { + return; + } + HttpServer server = HttpServer.create( + new InetSocketAddress((Integer) opts[1].value), 0); + server.createContext("/", new MyHandler()); + server.setExecutor(null); + server.start(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + static boolean parseOptions(String[] args, Option[] inout_options) { + if (args.length == 0) { + printUsage(); + return false; + } + + boolean bWrongArgs = true; + Option currentOpt = null; + + for (String s : args) { + // get the value for an option + if (currentOpt != null && currentOpt.bHasValue) { + //now we expect the value for the option + //check the type + try { + if (currentOpt.sLong.equals("--accept")) { + currentOpt.value = Integer.decode(s); + } + } catch (Exception e ) { + printUsage(); + return false; + } + currentOpt = null; + continue; + } else { + currentOpt = null; + } + + + // get the option + for (Option o : inout_options) { + if (s.equals(o.sLong) || s.equals(o.sShort)) { + bWrongArgs = false; + //special handling for --help + if (o.sLong.equals("--help")) { + printUsage(); + return false; + } + else + { + currentOpt = o; + break; + } + } + } + } + + if (bWrongArgs) { + printUsage(); + return false; + } + return true; + } + + static void printUsage() { + String usage = + "Usage: \n" + + "java -jar httpserv [options] \n" + + "\n" + + "Options are: \n" + + "-h --help \t this help \n" + + "-a --accept port \t the port number to which this server listens \n"; + System.out.println(usage); + } +} + +class MyHandler implements HttpHandler { + + public void handle(HttpExchange xchange) throws IOException { + try { + //First get the path to the file + String sRequestPath = xchange.getRequestURI().getPath(); + System.out.println("requested: " + sRequestPath); + File fileRequest = new File(new File(".").getCanonicalPath(), sRequestPath); + if (!fileRequest.exists()) { + throw new IOException("The file " + fileRequest + " does not exist!"); + } + else if (fileRequest.isDirectory()) { + throw new IOException(fileRequest + " is a directory!"); + } + + + //Read the file into a byte array + byte[] data = new byte[(int) fileRequest.length()]; + FileInputStream fr = new FileInputStream(fileRequest); + fr.read(data); + fr.close(); + + //set the Content-type header + Headers h = xchange.getResponseHeaders(); + String canonicalPath = fileRequest.getCanonicalPath(); + int lastIndex = canonicalPath.lastIndexOf("."); + String fileExtension = canonicalPath.substring(lastIndex + 1); + + if (fileExtension.equalsIgnoreCase("crl")) + { + h.set("Content-Type","application/pkix-crl"); + } + else if (fileExtension.equalsIgnoreCase("crt") + || fileExtension.equalsIgnoreCase("cer") + || fileExtension.equalsIgnoreCase("der")) + { + h.set("Content-Type", "application/x-x509-ca-cert"); + } + + //write out the requested file + xchange.sendResponseHeaders(200, data.length); + OutputStream os = xchange.getResponseBody(); + os.write(data); + os.close(); + System.out.println("delivered: " + fileRequest.toString()); + + } catch (Exception e) { + xchange.sendResponseHeaders(404, e.getMessage().length()); + OutputStream os = xchange.getResponseBody(); + os.write(e.getMessage().getBytes()); + os.close(); + System.out.println("Error: " + e.getMessage()); + } + } +} + +class Option { + + Option(String _sLong, String _sShort, boolean _bHasValue) { + sLong = _sLong; + sShort = _sShort; + bHasValue = _bHasValue; + } + String sLong; + String sShort; + boolean bHasValue; + Object value; +} + + diff --git a/xmlsecurity/uiconfig/ui/certdetails.ui b/xmlsecurity/uiconfig/ui/certdetails.ui new file mode 100644 index 0000000000..cc4ba21993 --- /dev/null +++ b/xmlsecurity/uiconfig/ui/certdetails.ui @@ -0,0 +1,119 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Generated with glade 3.36.0 --> +<interface domain="xsc"> + <requires lib="gtk+" version="3.20"/> + <object class="GtkTreeStore" id="liststore3"> + <columns> + <!-- column-name text --> + <column type="gchararray"/> + <!-- column-name text2 --> + <column type="gchararray"/> + <!-- column-name id --> + <column type="gchararray"/> + </columns> + </object> + <object class="GtkBox" id="CertDetails"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <property name="border_width">6</property> + <property name="orientation">vertical</property> + <property name="spacing">12</property> + <property name="homogeneous">True</property> + <child> + <object class="GtkScrolledWindow"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <property name="hscrollbar_policy">external</property> + <property name="shadow_type">in</property> + <child> + <object class="GtkTreeView" id="tablecontainer"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <property name="model">liststore3</property> + <property name="search_column">0</property> + <property name="show_expanders">False</property> + <child internal-child="selection"> + <object class="GtkTreeSelection" id="Macro Library List-selection2"/> + </child> + <child> + <object class="GtkTreeViewColumn" id="treeviewcolumn3"> + <property name="resizable">True</property> + <property name="spacing">6</property> + <property name="title" translatable="yes" context="certdetails|field">Field</property> + <child> + <object class="GtkCellRendererText" id="cellrenderer1"/> + <attributes> + <attribute name="text">0</attribute> + </attributes> + </child> + </object> + </child> + <child> + <object class="GtkTreeViewColumn" id="treeviewcolumn4"> + <property name="resizable">True</property> + <property name="spacing">6</property> + <property name="title" translatable="yes" context="certdetails|value">Value</property> + <child> + <object class="GtkCellRendererText" id="cellrenderer2"/> + <attributes> + <attribute name="text">1</attribute> + </attributes> + </child> + </object> + </child> + <child internal-child="accessible"> + <object class="AtkObject" id="tablecontainer-atkobject"> + <property name="AtkObject::accessible-description" translatable="yes" context="extended_tip|tablecontainer">The Details page of the View Certificate dialog displays detailed information about the certificate.</property> + </object> + </child> + </object> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkScrolledWindow"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <property name="hscrollbar_policy">never</property> + <property name="shadow_type">in</property> + <child> + <object class="GtkTextView" id="valuedetails"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <child internal-child="accessible"> + <object class="AtkObject" id="valuedetails-atkobject"> + <property name="AtkObject::accessible-description" translatable="yes" context="extended_tip|valuedetails">Use the value list box to view values and copy them to the clipboard.</property> + </object> + </child> + </object> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child internal-child="accessible"> + <object class="AtkObject" id="CertDetails-atkobject"> + <property name="AtkObject::accessible-description" translatable="yes" context="extended_tip|CertDetails">The Details page of the View Certificate dialog displays detailed information about the certificate.</property> + </object> + </child> + </object> +</interface> diff --git a/xmlsecurity/uiconfig/ui/certgeneral.ui b/xmlsecurity/uiconfig/ui/certgeneral.ui new file mode 100644 index 0000000000..e0c0b48acd --- /dev/null +++ b/xmlsecurity/uiconfig/ui/certgeneral.ui @@ -0,0 +1,254 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Generated with glade 3.36.0 --> +<interface domain="xsc"> + <requires lib="gtk+" version="3.20"/> + <object class="GtkBox" id="CertGeneral"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="border_width">6</property> + <property name="orientation">vertical</property> + <property name="spacing">6</property> + <child> + <object class="GtkBox" id="box1"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="spacing">6</property> + <child> + <object class="GtkImage" id="certimage"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="icon_name">xmlsecurity/res/certificate_40x56.png</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="padding">6</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label1"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes" context="certgeneral|label1">Certificate Information</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child internal-child="accessible"> + <object class="AtkObject" id="box1-atkobject"> + <property name="AtkObject::accessible-description" translatable="yes" context="extended_tip|box1">The General page of the View Certificate dialog displays basic information about the certificate.</property> + </object> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="padding">6</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkSeparator" id="separator1"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="hintnotrust"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin-start">36</property> + <property name="margin-end">36</property> + <property name="margin_bottom">108</property> + <property name="label" translatable="yes" context="certgeneral|hintnotrust">This certificate is validated.</property> + <property name="xalign">0</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkSeparator" id="separator2"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">3</property> + </packing> + </child> + <child> + <!-- n-columns=1 n-rows=1 --> + <object class="GtkGrid" id="grid1"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="row_spacing">6</property> + <property name="column_spacing">6</property> + <child> + <object class="GtkLabel" id="issued_to"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes" context="certgeneral|issued_to">Issued to: </property> + <property name="xalign">0</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="issued_to_value"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="hexpand">True</property> + <property name="xalign">0</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="issued_by"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes" context="certgeneral|issued_by">Issued by: </property> + <property name="xalign">0</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="issued_by_value"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="xalign">0</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="valid_from"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes" context="certgeneral|valid_from">Valid from:</property> + <property name="xalign">0</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">2</property> + </packing> + </child> + <child> + <object class="GtkBox" id="box2"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="spacing">6</property> + <child> + <object class="GtkImage" id="keyimage"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="icon_name">xmlsecurity/res/key_12.png</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="privatekey"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes" context="certgeneral|privatekey">You have a private key that corresponds to this certificate.</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">4</property> + <property name="width">2</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="valid_to"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes" context="certgeneral|valid_to">Valid to:</property> + <property name="xalign">0</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">3</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="valid_from_value"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="xalign">0</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">2</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="valid_to_value"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="xalign">0</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">3</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">4</property> + </packing> + </child> + </object> +</interface> diff --git a/xmlsecurity/uiconfig/ui/certpage.ui b/xmlsecurity/uiconfig/ui/certpage.ui new file mode 100644 index 0000000000..4e0579ac53 --- /dev/null +++ b/xmlsecurity/uiconfig/ui/certpage.ui @@ -0,0 +1,196 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Generated with glade 3.36.0 --> +<interface domain="xsc"> + <requires lib="gtk+" version="3.20"/> + <object class="GtkTreeStore" id="liststore3"> + <columns> + <!-- column-name text --> + <column type="gchararray"/> + <!-- column-name id --> + <column type="gchararray"/> + </columns> + </object> + <object class="GtkBox" id="CertPage"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <property name="border_width">6</property> + <property name="orientation">vertical</property> + <property name="spacing">12</property> + <child> + <!-- n-columns=1 n-rows=1 --> + <object class="GtkGrid" id="grid2"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <property name="row_spacing">6</property> + <child> + <object class="GtkLabel" id="label1"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes" context="certpage|label1">Certification path</property> + <property name="use_underline">True</property> + <property name="mnemonic_widget">signatures</property> + <property name="xalign">0</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkButton" id="viewcert"> + <property name="label" translatable="yes" context="certpage|viewcert">View Certificate...</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="halign">end</property> + <property name="use_underline">True</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">2</property> + </packing> + </child> + <child> + <object class="GtkScrolledWindow"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <property name="shadow_type">in</property> + <child> + <object class="GtkTreeView" id="signatures"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <property name="model">liststore3</property> + <property name="headers_visible">False</property> + <property name="search_column">0</property> + <property name="enable_tree_lines">True</property> + <child internal-child="selection"> + <object class="GtkTreeSelection" id="Macro Library List-selection2"/> + </child> + <child> + <object class="GtkTreeViewColumn" id="treeviewcolumn3"> + <property name="resizable">True</property> + <property name="spacing">6</property> + <child> + <object class="GtkCellRendererText" id="cellrenderer1"/> + <attributes> + <attribute name="text">0</attribute> + </attributes> + </child> + </object> + </child> + <child internal-child="accessible"> + <object class="AtkObject" id="signatures-atkobject"> + <property name="AtkObject::accessible-description" translatable="yes" context="extended_tip|signatures">The Certificate Path page of the View Certificate dialog displays the location and the status of the certificate.</property> + </object> + </child> + </object> + </child> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <!-- n-columns=1 n-rows=1 --> + <object class="GtkGrid" id="grid1"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <property name="row_spacing">6</property> + <child> + <object class="GtkLabel" id="label2"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes" context="certpage|label2">Certification status</property> + <property name="use_underline">True</property> + <property name="mnemonic_widget">status</property> + <property name="xalign">0</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkScrolledWindow"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <property name="hscrollbar_policy">never</property> + <property name="shadow_type">in</property> + <child> + <object class="GtkTextView" id="status"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <child internal-child="accessible"> + <object class="AtkObject" id="status-atkobject"> + <property name="AtkObject::accessible-description" translatable="yes" context="extended_tip|status">The Certificate Path page of the View Certificate dialog displays the location and the status of the certificate.</property> + </object> + </child> + </object> + </child> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="certok"> + <property name="can_focus">False</property> + <property name="no_show_all">True</property> + <property name="label" translatable="yes" context="certpage|certok">The certificate is OK.</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="certnotok"> + <property name="can_focus">False</property> + <property name="no_show_all">True</property> + <property name="label" translatable="yes" context="certpage|certnotok">The certificate could not be validated.</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">3</property> + </packing> + </child> + <child internal-child="accessible"> + <object class="AtkObject" id="CertPage-atkobject"> + <property name="AtkObject::accessible-description" translatable="yes" context="extended_tip|CertPage">The Certificate Path page of the View Certificate dialog displays the location and the status of the certificate.</property> + </object> + </child> + </object> +</interface> diff --git a/xmlsecurity/uiconfig/ui/digitalsignaturesdialog.ui b/xmlsecurity/uiconfig/ui/digitalsignaturesdialog.ui new file mode 100644 index 0000000000..f701468e62 --- /dev/null +++ b/xmlsecurity/uiconfig/ui/digitalsignaturesdialog.ui @@ -0,0 +1,508 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Generated with glade 3.36.0 --> +<interface domain="xsc"> + <requires lib="gtk+" version="3.20"/> + <object class="GtkTreeStore" id="liststore3"> + <columns> + <!-- column-name image --> + <column type="GdkPixbuf"/> + <!-- column-name text --> + <column type="gchararray"/> + <!-- column-name text2 --> + <column type="gchararray"/> + <!-- column-name text3 --> + <column type="gchararray"/> + <!-- column-name text4 --> + <column type="gchararray"/> + <!-- column-name text5 --> + <column type="gchararray"/> + <!-- column-name id --> + <column type="gchararray"/> + </columns> + </object> + <object class="GtkDialog" id="DigitalSignaturesDialog"> + <property name="can_focus">False</property> + <property name="border_width">6</property> + <property name="title" translatable="yes" context="digitalsignaturesdialog|DigitalSignaturesDialog">Digital Signatures</property> + <property name="modal">True</property> + <property name="type_hint">dialog</property> + <child internal-child="vbox"> + <object class="GtkBox" id="dialog-vbox1"> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <property name="spacing">12</property> + <child internal-child="action_area"> + <object class="GtkButtonBox" id="dialog-action_area1"> + <property name="can_focus">False</property> + <property name="layout_style">end</property> + <child> + <object class="GtkButton" id="help"> + <property name="label" translatable="yes" context="stock">_Help</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="use-underline">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + <property name="secondary">True</property> + </packing> + </child> + <child> + <object class="GtkButton" id="close"> + <property name="label" translatable="yes" context="stock">_Close</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="can_default">True</property> + <property name="has_default">True</property> + <property name="receives_default">True</property> + <property name="use-underline">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">end</property> + <property name="position">0</property> + </packing> + </child> + <child> + <!-- n-columns=1 n-rows=1 --> + <object class="GtkGrid" id="grid1"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <property name="row_spacing">6</property> + <child> + <object class="GtkLabel" id="dochint"> + <property name="can_focus">False</property> + <property name="no_show_all">True</property> + <property name="label" translatable="yes" context="digitalsignaturesdialog|dochint">The following have signed the document content: </property> + <property name="xalign">0</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkScrolledWindow"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <property name="shadow_type">in</property> + <child> + <object class="GtkTreeView" id="signatures"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <property name="model">liststore3</property> + <property name="search_column">0</property> + <property name="show_expanders">False</property> + <child internal-child="selection"> + <object class="GtkTreeSelection" id="Macro Library List-selection2"/> + </child> + <child> + <object class="GtkTreeViewColumn" id="treeviewcolumn2"> + <property name="resizable">True</property> + <property name="spacing">6</property> + <child> + <object class="GtkCellRendererPixbuf" id="cellrenderertext0"/> + <attributes> + <attribute name="pixbuf">0</attribute> + </attributes> + </child> + </object> + </child> + <child> + <object class="GtkTreeViewColumn" id="treeviewcolumn3"> + <property name="resizable">True</property> + <property name="spacing">6</property> + <property name="title" translatable="yes" context="digitalsignaturesdialog|signed">Signed by </property> + <child> + <object class="GtkCellRendererText" id="cellrenderer1"/> + <attributes> + <attribute name="text">1</attribute> + </attributes> + </child> + </object> + </child> + <child> + <object class="GtkTreeViewColumn" id="treeviewcolumn4"> + <property name="resizable">True</property> + <property name="spacing">6</property> + <property name="title" translatable="yes" context="digitalsignaturesdialog|issued">Digital ID issued by </property> + <child> + <object class="GtkCellRendererText" id="cellrenderer2"/> + <attributes> + <attribute name="text">2</attribute> + </attributes> + </child> + </object> + </child> + <child> + <object class="GtkTreeViewColumn" id="treeviewcolumn5"> + <property name="resizable">True</property> + <property name="spacing">6</property> + <property name="title" translatable="yes" context="digitalsignaturesdialog|date">Date</property> + <child> + <object class="GtkCellRendererText" id="cellrenderer3"/> + <attributes> + <attribute name="text">3</attribute> + </attributes> + </child> + </object> + </child> + <child> + <object class="GtkTreeViewColumn" id="treeviewcolumn6"> + <property name="resizable">True</property> + <property name="spacing">6</property> + <property name="title" translatable="yes" context="digitalsignaturesdialog|description">Description</property> + <child> + <object class="GtkCellRendererText" id="cellrenderer4"/> + <attributes> + <attribute name="text">4</attribute> + </attributes> + </child> + </object> + </child> + <child> + <object class="GtkTreeViewColumn" id="treeviewcolumn7"> + <property name="resizable">True</property> + <property name="spacing">6</property> + <property name="title" translatable="yes" context="digitalsignaturesdialog|type">Signature type</property> + <child> + <object class="GtkCellRendererText" id="cellrenderer5"/> + <attributes> + <attribute name="text">5</attribute> + </attributes> + </child> + </object> + </child> + <child internal-child="accessible"> + <object class="AtkObject" id="signatures-atkobject"> + <property name="AtkObject::accessible-description" translatable="yes" context="digitalsignaturesdialog|extended_tip|signatures">Lists the digital signatures for the current document.</property> + </object> + </child> + </object> + </child> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">4</property> + </packing> + </child> + <child> + <object class="GtkButtonBox" id="buttonbox1"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="spacing">12</property> + <property name="homogeneous">True</property> + <property name="layout_style">end</property> + <child> + <object class="GtkButton" id="view"> + <property name="label" translatable="yes" context="digitalsignaturesdialog|view">View Certificate...</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <child internal-child="accessible"> + <object class="AtkObject" id="view-atkobject"> + <property name="AtkObject::accessible-description" translatable="yes" context="digitalsignaturesdialog|extended_tip|view">Opens the View Certificate dialog.</property> + </object> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkButton" id="sign"> + <property name="label" translatable="yes" context="digitalsignaturesdialog|sign">Sign Document...</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="can_default">True</property> + <property name="receives_default">True</property> + <child internal-child="accessible"> + <object class="AtkObject" id="sign-atkobject"> + <property name="AtkObject::accessible-description" translatable="yes" context="digitalsignaturesdialog|extended_tip|sign">Opens the Select Certificate dialog.</property> + </object> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkButton" id="remove"> + <property name="label" translatable="yes" context="digitalsignaturesdialog|remove">Remove</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <child internal-child="accessible"> + <object class="AtkObject" id="remove-atkobject"> + <property name="AtkObject::accessible-description" translatable="yes" context="digitalsignaturesdialog|extended_tip|remove">Removes the selected signature from the list. Removes all subsequent signatures as well, in case of PDF.</property> + </object> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkButton" id="start_certmanager"> + <property name="label" translatable="yes" context="digitalsignaturesdialog|start_certmanager">Start Certificate Manager...</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">3</property> + </packing> + </child> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">7</property> + </packing> + </child> + <child> + <!-- n-columns=1 n-rows=1 --> + <object class="GtkGrid" id="grid2"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="hexpand">True</property> + <property name="column_spacing">12</property> + <child> + <object class="GtkLabel" id="signed"> + <property name="can_focus">False</property> + <property name="no_show_all">True</property> + <property name="hexpand">True</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="issued"> + <property name="can_focus">False</property> + <property name="no_show_all">True</property> + <property name="hexpand">True</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="date"> + <property name="can_focus">False</property> + <property name="no_show_all">True</property> + <property name="hexpand">True</property> + </object> + <packing> + <property name="left_attach">2</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="description"> + <property name="can_focus">False</property> + <property name="no_show_all">True</property> + </object> + <packing> + <property name="left_attach">3</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="type"> + <property name="can_focus">False</property> + <property name="no_show_all">True</property> + </object> + <packing> + <property name="left_attach">4</property> + <property name="top_attach">0</property> + </packing> + </child> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">3</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="macrohint"> + <property name="can_focus">False</property> + <property name="no_show_all">True</property> + <property name="label" translatable="yes" context="digitalsignaturesdialog|macrohint">The following have signed the document macro:</property> + <property name="xalign">0</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="packagehint"> + <property name="can_focus">False</property> + <property name="no_show_all">True</property> + <property name="label" translatable="yes" context="digitalsignaturesdialog|packagehint">The following have signed this package:</property> + <property name="xalign">0</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">2</property> + </packing> + </child> + <child> + <!-- n-columns=1 n-rows=1 --> + <object class="GtkGrid" id="grid3"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="column_spacing">12</property> + <child> + <object class="GtkLabel" id="validft"> + <property name="can_focus">False</property> + <property name="no_show_all">True</property> + <property name="hexpand">True</property> + <property name="label" translatable="yes" context="digitalsignaturesdialog|validft">The signatures in this document are valid</property> + <property name="xalign">0</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkImage" id="validimg"> + <property name="can_focus">False</property> + <property name="no_show_all">True</property> + <property name="icon_name">xmlsecurity/res/signet_11x16.png</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="invalidft"> + <property name="can_focus">False</property> + <property name="no_show_all">True</property> + <property name="hexpand">True</property> + <property name="label" translatable="yes" context="digitalsignaturesdialog|invalidft">The signatures in this document are invalid</property> + <property name="xalign">0</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">2</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="oldsignatureft"> + <property name="can_focus">False</property> + <property name="no_show_all">True</property> + <property name="hexpand">True</property> + <property name="label" translatable="yes" context="digitalsignaturesdialog|oldsignatureft">At least one signature has problems: the document is only partially signed.</property> + <property name="xalign">0</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="notvalidatedft"> + <property name="can_focus">False</property> + <property name="no_show_all">True</property> + <property name="hexpand">True</property> + <property name="label" translatable="yes" context="digitalsignaturesdialog|notvalidatedft">At least one signature has problems: the certificate could not be validated.</property> + <property name="xalign">0</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">3</property> + </packing> + </child> + <child> + <object class="GtkImage" id="invalidimg"> + <property name="can_focus">False</property> + <property name="no_show_all">True</property> + <property name="icon_name">svx/res/caution_11x16.png</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">2</property> + </packing> + </child> + <child> + <object class="GtkImage" id="oldsignatureimg"> + <property name="can_focus">False</property> + <property name="no_show_all">True</property> + <property name="icon_name">svx/res/caution_11x16.png</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkImage" id="notvalidatedimg"> + <property name="can_focus">False</property> + <property name="no_show_all">True</property> + <property name="icon_name">xmlsecurity/res/notcertificate_16.png</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">3</property> + </packing> + </child> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">5</property> + </packing> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + </child> + <action-widgets> + <action-widget response="-11">help</action-widget> + <action-widget response="-7">close</action-widget> + </action-widgets> + <child type="titlebar"> + <placeholder/> + </child> + <child internal-child="accessible"> + <object class="AtkObject" id="DigitalSignaturesDialog-atkobject"> + <property name="AtkObject::accessible-description" translatable="yes" context="digitalsignaturesdialog|extended_tip|DigitalSignaturesDialog">Adds and removes digital signatures to and from your document. You can also use the dialog to view certificates.</property> + </object> + </child> + </object> +</interface> diff --git a/xmlsecurity/uiconfig/ui/macrosecuritydialog.ui b/xmlsecurity/uiconfig/ui/macrosecuritydialog.ui new file mode 100644 index 0000000000..06699d588f --- /dev/null +++ b/xmlsecurity/uiconfig/ui/macrosecuritydialog.ui @@ -0,0 +1,208 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Generated with glade 3.22.1 --> +<interface domain="xsc"> + <requires lib="gtk+" version="3.20"/> + <object class="GtkDialog" id="MacroSecurityDialog"> + <property name="can_focus">False</property> + <property name="border_width">6</property> + <property name="title" translatable="yes" context="macrosecuritydialog|MacroSecurityDialog">Macro Security</property> + <property name="modal">True</property> + <property name="default_width">0</property> + <property name="default_height">0</property> + <property name="type_hint">dialog</property> + <child> + <placeholder/> + </child> + <child internal-child="vbox"> + <object class="GtkBox" id="dialog-vbox1"> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <property name="spacing">12</property> + <child internal-child="action_area"> + <object class="GtkButtonBox" id="dialog-action_area1"> + <property name="can_focus">False</property> + <property name="layout_style">end</property> + <child> + <object class="GtkButton" id="reset"> + <property name="label" translatable="yes" context="stock">_Reset</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="use-underline">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkButton" id="ok"> + <property name="label" translatable="yes" context="stock">_OK</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="can_default">True</property> + <property name="has_default">True</property> + <property name="receives_default">True</property> + <property name="use-underline">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkButton" id="cancel"> + <property name="label" translatable="yes" context="stock">_Cancel</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="use-underline">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkButton" id="help"> + <property name="label" translatable="yes" context="stock">_Help</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="use-underline">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">3</property> + <property name="secondary">True</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">end</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkNotebook" id="tabcontrol"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <property name="scrollable">True</property> + <property name="enable_popup">True</property> + <child> + <!-- n-columns=1 n-rows=1 --> + <object class="GtkGrid"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + </object> + </child> + <child type="tab"> + <object class="GtkLabel" id="SecurityLevelPage"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes" context="macrosecuritydialog|SecurityLevelPage">Security Level</property> + </object> + <packing> + <property name="tab_fill">False</property> + </packing> + </child> + <child> + <!-- n-columns=1 n-rows=1 --> + <object class="GtkGrid"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + </object> + <packing> + <property name="position">1</property> + </packing> + </child> + <child type="tab"> + <object class="GtkLabel" id="SecurityTrustPage"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes" context="macrosecuritydialog|SecurityTrustPage">Trusted Sources</property> + </object> + <packing> + <property name="position">1</property> + <property name="tab_fill">False</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + </child> + <action-widgets> + <action-widget response="101">reset</action-widget> + <action-widget response="-5">ok</action-widget> + <action-widget response="-6">cancel</action-widget> + <action-widget response="-11">help</action-widget> + </action-widgets> + </object> +</interface> diff --git a/xmlsecurity/uiconfig/ui/securitylevelpage.ui b/xmlsecurity/uiconfig/ui/securitylevelpage.ui new file mode 100644 index 0000000000..5292a72fcf --- /dev/null +++ b/xmlsecurity/uiconfig/ui/securitylevelpage.ui @@ -0,0 +1,160 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Generated with glade 3.36.0 --> +<interface domain="xsc"> + <requires lib="gtk+" version="3.20"/> + <!-- n-columns=1 n-rows=1 --> + <object class="GtkGrid" id="SecurityLevelPage"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <property name="border_width">6</property> + <property name="orientation">vertical</property> + <property name="row_spacing">6</property> + <property name="column_spacing">12</property> + <property name="row_homogeneous">True</property> + <child> + <object class="GtkRadioButton" id="low"> + <property name="label" translatable="yes" context="securitylevelpage|low">_Low (not recommended). +All macros will be executed without confirmation. +Use this setting only if you are certain that all documents that will be opened are safe.</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="hexpand">True</property> + <property name="use_underline">True</property> + <property name="draw_indicator">True</property> + <property name="group">high</property> + <child internal-child="accessible"> + <object class="AtkObject" id="low-atkobject"> + <property name="AtkObject::accessible-description" translatable="yes" context="extended_tip|low">A macro can be set to auto-start, and it can perform potentially damaging actions, as for example delete or rename files. This setting is not recommended when you open documents from other authors.</property> + </object> + </child> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">3</property> + </packing> + </child> + <child> + <object class="GtkRadioButton" id="med"> + <property name="label" translatable="yes" context="securitylevelpage|med">_Medium. +Confirmation required before executing macros from untrusted sources.</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="hexpand">True</property> + <property name="use_underline">True</property> + <property name="draw_indicator">True</property> + <property name="group">high</property> + <child internal-child="accessible"> + <object class="AtkObject" id="med-atkobject"> + <property name="AtkObject::accessible-description" translatable="yes" context="extended_tip|med">Trusted sources can be set on the Trusted Sources tab page. Signed macros from a trusted source are allowed to run. In addition, any macro from a trusted file location is allowed to run. All other macros require your confirmation.</property> + </object> + </child> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">2</property> + </packing> + </child> + <child> + <object class="GtkRadioButton" id="high"> + <property name="label" translatable="yes" context="securitylevelpage|high">H_igh. +Only signed macros and macros from trusted file locations are executed. +Unsigned macros are disabled.</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="hexpand">True</property> + <property name="use_underline">True</property> + <property name="active">True</property> + <property name="draw_indicator">True</property> + <child internal-child="accessible"> + <object class="AtkObject" id="high-atkobject"> + <property name="AtkObject::accessible-description" translatable="yes" context="extended_tip|high">Only signed macros or macros from a trusted file location are allowed to run. Macros signed with untrusted certificates will require confirmation to run, when located in untrusted file locations. Trusted certificates and trusted file locations can be set on the Trusted Sources tab page.</property> + </object> + </child> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkRadioButton" id="vhigh"> + <property name="label" translatable="yes" context="securitylevelpage|vhigh">_Very high. +Only macros from trusted file locations are allowed to run. +All other macros, regardless whether signed or not, are disabled.</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="hexpand">True</property> + <property name="use_underline">True</property> + <property name="draw_indicator">True</property> + <property name="group">high</property> + <child internal-child="accessible"> + <object class="AtkObject" id="vhigh-atkobject"> + <property name="AtkObject::accessible-description" translatable="yes" context="extended_tip|vhigh">Trusted file locations can be set on the Trusted Sources tab page. Any macro from a trusted file location is allowed to run.</property> + </object> + </child> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkImage" id="vhighimg"> + <property name="can_focus">False</property> + <property name="no_show_all">True</property> + <property name="halign">center</property> + <property name="valign">center</property> + <property name="icon_name">res/lock.png</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkImage" id="highimg"> + <property name="can_focus">False</property> + <property name="no_show_all">True</property> + <property name="halign">center</property> + <property name="valign">center</property> + <property name="icon_name">res/lock.png</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkImage" id="medimg"> + <property name="can_focus">False</property> + <property name="no_show_all">True</property> + <property name="halign">center</property> + <property name="valign">center</property> + <property name="icon_name">res/lock.png</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">2</property> + </packing> + </child> + <child> + <object class="GtkImage" id="lowimg"> + <property name="can_focus">False</property> + <property name="no_show_all">True</property> + <property name="halign">center</property> + <property name="valign">center</property> + <property name="icon_name">res/lock.png</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">3</property> + </packing> + </child> + </object> +</interface> diff --git a/xmlsecurity/uiconfig/ui/securitytrustpage.ui b/xmlsecurity/uiconfig/ui/securitytrustpage.ui new file mode 100644 index 0000000000..267efa8f08 --- /dev/null +++ b/xmlsecurity/uiconfig/ui/securitytrustpage.ui @@ -0,0 +1,392 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Generated with glade 3.36.0 --> +<interface domain="xsc"> + <requires lib="gtk+" version="3.20"/> + <object class="GtkTreeStore" id="liststore2"> + <columns> + <!-- column-name text --> + <column type="gchararray"/> + <!-- column-name id --> + <column type="gchararray"/> + </columns> + </object> + <object class="GtkTreeStore" id="liststore3"> + <columns> + <!-- column-name text --> + <column type="gchararray"/> + <!-- column-name text2 --> + <column type="gchararray"/> + <!-- column-name text3 --> + <column type="gchararray"/> + <!-- column-name id --> + <column type="gchararray"/> + </columns> + </object> + <object class="GtkBox" id="SecurityTrustPage"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <property name="border_width">6</property> + <property name="orientation">vertical</property> + <property name="spacing">12</property> + <child> + <object class="GtkFrame" id="frame1"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <property name="label_xalign">0</property> + <property name="shadow_type">none</property> + <child> + <!-- n-columns=1 n-rows=1 --> + <object class="GtkGrid" id="grid1"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <property name="row_spacing">6</property> + <property name="column_spacing">6</property> + <property name="margin-start">12</property> + <property name="margin-top">6</property> + <child> + <object class="GtkButtonBox" id="buttonbox1"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="hexpand">True</property> + <property name="spacing">12</property> + <property name="layout_style">end</property> + <child> + <object class="GtkButton" id="viewcert"> + <property name="label" translatable="yes" context="securitytrustpage|viewcert">_View...</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="use_underline">True</property> + <child internal-child="accessible"> + <object class="AtkObject" id="viewcert-atkobject"> + <property name="AtkObject::accessible-description" translatable="yes" context="extended_tip|viewcert">Opens the View Certificate dialog for the selected certificate.</property> + </object> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkButton" id="removecert"> + <property name="label" translatable="yes" context="stock">_Remove</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="use-underline">True</property> + <child internal-child="accessible"> + <object class="AtkObject" id="removecert-atkobject"> + <property name="AtkObject::accessible-description" translatable="yes" context="extended_tip|removecert">Removes the selected certificate from the list of trusted certificates.</property> + </object> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkScrolledWindow"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <property name="shadow_type">in</property> + <child> + <object class="GtkTreeView" id="certificates"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <property name="model">liststore3</property> + <property name="search_column">0</property> + <property name="show_expanders">False</property> + <child internal-child="selection"> + <object class="GtkTreeSelection" id="Macro Library List-selection2"/> + </child> + <child> + <object class="GtkTreeViewColumn" id="treeviewcolumn3"> + <property name="resizable">True</property> + <property name="spacing">6</property> + <property name="title" translatable="yes" context="securitytrustpage|to">Issued to</property> + <child> + <object class="GtkCellRendererText" id="cellrenderer1"/> + <attributes> + <attribute name="text">0</attribute> + </attributes> + </child> + </object> + </child> + <child> + <object class="GtkTreeViewColumn" id="treeviewcolumn4"> + <property name="resizable">True</property> + <property name="spacing">6</property> + <property name="title" translatable="yes" context="securitytrustpage|by">Issued by</property> + <child> + <object class="GtkCellRendererText" id="cellrenderer2"/> + <attributes> + <attribute name="text">1</attribute> + </attributes> + </child> + </object> + </child> + <child> + <object class="GtkTreeViewColumn" id="treeviewcolumn5"> + <property name="resizable">True</property> + <property name="spacing">6</property> + <property name="title" translatable="yes" context="securitytrustpage|date">Expiration date</property> + <child> + <object class="GtkCellRendererText" id="cellrenderer3"/> + <attributes> + <attribute name="text">2</attribute> + </attributes> + </child> + </object> + </child> + <child internal-child="accessible"> + <object class="AtkObject" id="certificates-atkobject"> + <property name="AtkObject::accessible-description" translatable="yes" context="extended_tip|certificates">Lists the trusted certificates.</property> + </object> + </child> + </object> + </child> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkImage" id="lockcertimg"> + <property name="can_focus">False</property> + <property name="no_show_all">True</property> + <property name="halign">center</property> + <property name="valign">center</property> + <property name="icon_name">res/lock.png</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <placeholder/> + </child> + </object> + </child> + <child type="label"> + <object class="GtkLabel" id="label3"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes" context="securitytrustpage|label3">Trusted Certificates</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> + </object> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkFrame" id="frame2"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <property name="label_xalign">0</property> + <property name="shadow_type">none</property> + <child> + <!-- n-columns=1 n-rows=1 --> + <object class="GtkGrid" id="grid3"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <property name="row_spacing">12</property> + <property name="column_spacing">6</property> + <property name="margin-start">12</property> + <property name="margin-top">6</property> + <child> + <object class="GtkLabel" id="label8"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes" context="securitytrustpage|label8">Document macros are always executed if they have been opened from one of the following locations.</property> + <property name="wrap">True</property> + <property name="width_chars">56</property> + <property name="max_width_chars">56</property> + <property name="xalign">0</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkButtonBox" id="buttonbox2"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="spacing">12</property> + <property name="layout_style">end</property> + <child> + <object class="GtkButton" id="addfile"> + <property name="label" translatable="yes" context="securitytrustpage|addfile">A_dd...</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="use_underline">True</property> + <child internal-child="accessible"> + <object class="AtkObject" id="addfile-atkobject"> + <property name="AtkObject::accessible-description" translatable="yes" context="extended_tip|addfile">Opens a folder selection dialog. Select a folder from which all macros are allowed to execute.</property> + </object> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkButton" id="removefile"> + <property name="label" translatable="yes" context="stock">_Remove</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="use-underline">True</property> + <child internal-child="accessible"> + <object class="AtkObject" id="removefile-atkobject"> + <property name="AtkObject::accessible-description" translatable="yes" context="extended_tip|removefile">Removes the selected folder from the list of trusted file locations.</property> + </object> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">2</property> + </packing> + </child> + <child> + <object class="GtkScrolledWindow"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <property name="shadow_type">in</property> + <child> + <object class="GtkTreeView" id="locations"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <property name="model">liststore2</property> + <property name="headers_visible">False</property> + <property name="search_column">0</property> + <property name="show_expanders">False</property> + <child internal-child="selection"> + <object class="GtkTreeSelection" id="Macro Library List-selection1"/> + </child> + <child> + <object class="GtkTreeViewColumn" id="treeviewcolumn9"> + <property name="resizable">True</property> + <property name="spacing">6</property> + <child> + <object class="GtkCellRendererText" id="cellrenderer0"/> + <attributes> + <attribute name="text">0</attribute> + </attributes> + </child> + </object> + </child> + <child internal-child="accessible"> + <object class="AtkObject" id="locations-atkobject"> + <property name="AtkObject::accessible-description" translatable="yes" context="extended_tip|locations">Document macros are only executed if they have been opened from one of the following locations.</property> + </object> + </child> + </object> + </child> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkImage" id="lockfileimg"> + <property name="can_focus">False</property> + <property name="no_show_all">True</property> + <property name="halign">center</property> + <property name="valign">center</property> + <property name="icon_name">res/lock.png</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + </object> + </child> + <child type="label"> + <object class="GtkLabel" id="label4"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes" context="securitytrustpage|label4">Trusted File Locations</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> + </object> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <object class="GtkSizeGroup" id="sizegroup1"> + <widgets> + <widget name="viewcert"/> + <widget name="addfile"/> + </widgets> + </object> + <object class="GtkSizeGroup" id="sizegroup2"> + <property name="mode">vertical</property> + <widgets> + <widget name="certificates"/> + <widget name="locations"/> + </widgets> + </object> +</interface> diff --git a/xmlsecurity/uiconfig/ui/selectcertificatedialog.ui b/xmlsecurity/uiconfig/ui/selectcertificatedialog.ui new file mode 100644 index 0000000000..aae6bd4402 --- /dev/null +++ b/xmlsecurity/uiconfig/ui/selectcertificatedialog.ui @@ -0,0 +1,324 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Generated with glade 3.40.0 --> +<interface domain="xsc"> + <requires lib="gtk+" version="3.20"/> + <object class="GtkTreeStore" id="liststore3"> + <columns> + <!-- column-name text --> + <column type="gchararray"/> + <!-- column-name text2 --> + <column type="gchararray"/> + <!-- column-name text4 --> + <column type="gchararray"/> + <!-- column-name id --> + <column type="gchararray"/> + </columns> + </object> + <object class="GtkDialog" id="SelectCertificateDialog"> + <property name="can-focus">False</property> + <property name="border-width">6</property> + <property name="title" translatable="yes" context="selectcertificatedialog|SelectCertificateDialog">Select Certificate</property> + <property name="resizable">False</property> + <property name="modal">True</property> + <property name="type-hint">dialog</property> + <child internal-child="vbox"> + <object class="GtkBox" id="dialog-vbox1"> + <property name="can-focus">False</property> + <property name="orientation">vertical</property> + <property name="spacing">12</property> + <child internal-child="action_area"> + <object class="GtkButtonBox" id="dialog-action_area1"> + <property name="can-focus">False</property> + <property name="layout-style">end</property> + <child> + <object class="GtkButton" id="ok"> + <property name="label" translatable="yes" context="stock">_OK</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="can-default">True</property> + <property name="has-default">True</property> + <property name="receives-default">True</property> + <property name="use-underline">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkButton" id="cancel"> + <property name="label" translatable="yes" context="stock">_Cancel</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="receives-default">True</property> + <property name="use-underline">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkButton" id="help"> + <property name="label" translatable="yes" context="stock">_Help</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="receives-default">True</property> + <property name="use-underline">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + <property name="secondary">True</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack-type">end</property> + <property name="position">0</property> + </packing> + </child> + <child> + <!-- n-columns=1 n-rows=6 --> + <object class="GtkGrid" id="grid1"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <property name="row-spacing">12</property> + <property name="column-spacing">12</property> + <child> + <object class="GtkLabel" id="sign"> + <property name="can-focus">False</property> + <property name="label" translatable="yes" context="selectcertificatedialog|sign">Select the certificate you want to use for signing:</property> + <property name="xalign">0</property> + </object> + <packing> + <property name="left-attach">0</property> + <property name="top-attach">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="encrypt"> + <property name="can-focus">False</property> + <property name="label" translatable="yes" context="selectcertificatedialog|encrypt">Select the certificate you want to use for encryption:</property> + <property name="xalign">0</property> + </object> + <packing> + <property name="left-attach">0</property> + <property name="top-attach">1</property> + </packing> + </child> + <child> + <object class="GtkScrolledWindow"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <property name="shadow-type">in</property> + <child> + <object class="GtkTreeView" id="signatures"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="receives-default">True</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <property name="model">liststore3</property> + <property name="search-column">0</property> + <property name="show-expanders">False</property> + <child internal-child="selection"> + <object class="GtkTreeSelection"/> + </child> + <child> + <object class="GtkTreeViewColumn" id="treeviewcolumn3"> + <property name="resizable">True</property> + <property name="spacing">6</property> + <property name="title" translatable="yes" context="selectcertificatedialog|issuedto">Issued to</property> + <property name="sort-indicator">True</property> + <property name="sort-column-id">0</property> + <child> + <object class="GtkCellRendererText" id="cellrenderer1"/> + <attributes> + <attribute name="text">0</attribute> + </attributes> + </child> + </object> + </child> + <child> + <object class="GtkTreeViewColumn" id="treeviewcolumn4"> + <property name="resizable">True</property> + <property name="spacing">6</property> + <property name="title" translatable="yes" context="selectcertificatedialog|issuedby">Issued by</property> + <property name="sort-indicator">True</property> + <property name="sort-column-id">1</property> + <child> + <object class="GtkCellRendererText" id="cellrenderer2"/> + <attributes> + <attribute name="text">1</attribute> + </attributes> + </child> + </object> + </child> + <child> + <object class="GtkTreeViewColumn" id="treeviewcolumn5"> + <property name="resizable">True</property> + <property name="spacing">6</property> + <property name="title" translatable="yes" context="selectcertificatedialog|type">Expiration date</property> + <property name="sort-indicator">True</property> + <property name="sort-column-id">2</property> + <child> + <object class="GtkCellRendererText" id="cellrenderer3"/> + <attributes> + <attribute name="text">2</attribute> + </attributes> + </child> + </object> + </child> + <child internal-child="accessible"> + <object class="AtkObject" id="signatures-atkobject"> + <property name="AtkObject::accessible-description" translatable="yes" context="selectcertificatedialog|extended_tip|signatures">Select the certificate that you want to digitally sign the current document with.</property> + </object> + </child> + </object> + </child> + </object> + <packing> + <property name="left-attach">0</property> + <property name="top-attach">3</property> + </packing> + </child> + <child> + <object class="GtkEntry" id="searchbox"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="activates-default">True</property> + <property name="truncate-multiline">True</property> + <property name="primary-icon-stock">gtk-find</property> + <child internal-child="accessible"> + <object class="AtkObject" id="searchbox-atkobject"> + <property name="AtkObject::accessible-description" translatable="yes" context="selectcertificatedialog|extended_tip|searchbox">Search for certificate by issuer name or email.</property> + </object> + </child> + </object> + <packing> + <property name="left-attach">0</property> + <property name="top-attach">2</property> + </packing> + </child> + <child> + <object class="GtkBox" id="dialog-hbox1"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="spacing">12</property> + <child> + <object class="GtkLabel" id="description-label"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="label" translatable="yes" context="selectcertificatedialog|label2">Description:</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkEntry" id="description"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="activates-default">True</property> + <property name="truncate-multiline">True</property> + <child internal-child="accessible"> + <object class="AtkObject" id="description-atkobject"> + <property name="AtkObject::accessible-description" translatable="yes" context="selectcertificatedialog|extended_tip|description">Type a purpose for the signature.</property> + </object> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="left-attach">0</property> + <property name="top-attach">5</property> + </packing> + </child> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="halign">end</property> + <property name="spacing">12</property> + <child> + <object class="GtkButton" id="viewcert"> + <property name="label" translatable="yes" context="selectcertificatedialog|viewcert">View Certificate...</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="receives-default">True</property> + <property name="halign">end</property> + <child internal-child="accessible"> + <object class="AtkObject" id="viewcert-atkobject"> + <property name="AtkObject::accessible-description" translatable="yes" context="selectcertificatedialog|extended_tip|viewcert">Opens the View Certificate dialog where you can examine the selected certificate.</property> + </object> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkButton" id="reloadcert"> + <property name="label" translatable="yes" context="selectcertificatedialog|reloadcert">Reload Certificates</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="receives-default">True</property> + <property name="halign">end</property> + <child internal-child="accessible"> + <object class="AtkObject" id="reloadcert-atkobject"> + <property name="AtkObject::accessible-description" translatable="yes" context="selectcertificatedialog|extended_tip|reloadcert">Reload the list of certificates.</property> + </object> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="left-attach">0</property> + <property name="top-attach">4</property> + </packing> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + </child> + <action-widgets> + <action-widget response="-5">ok</action-widget> + <action-widget response="-6">cancel</action-widget> + <action-widget response="-11">help</action-widget> + </action-widgets> + <child internal-child="accessible"> + <object class="AtkObject" id="SelectCertificateDialog-atkobject"> + <property name="AtkObject::accessible-description" translatable="yes" context="selectcertificatedialog|extended_tip|SelectCertificateDialog">Select the certificate that you want to digitally sign the current document with.</property> + </object> + </child> + </object> +</interface> diff --git a/xmlsecurity/uiconfig/ui/viewcertdialog.ui b/xmlsecurity/uiconfig/ui/viewcertdialog.ui new file mode 100644 index 0000000000..12cf4b40e6 --- /dev/null +++ b/xmlsecurity/uiconfig/ui/viewcertdialog.ui @@ -0,0 +1,227 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Generated with glade 3.22.1 --> +<interface domain="xsc"> + <requires lib="gtk+" version="3.20"/> + <object class="GtkDialog" id="ViewCertDialog"> + <property name="can_focus">False</property> + <property name="border_width">6</property> + <property name="title" translatable="yes" context="viewcertdialog|ViewCertDialog">View Certificate</property> + <property name="resizable">False</property> + <property name="modal">True</property> + <property name="default_width">0</property> + <property name="default_height">0</property> + <property name="type_hint">dialog</property> + <child> + <placeholder/> + </child> + <child internal-child="vbox"> + <object class="GtkBox" id="dialog-vbox1"> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <property name="spacing">12</property> + <child internal-child="action_area"> + <object class="GtkButtonBox" id="dialog-action_area1"> + <property name="can_focus">False</property> + <property name="layout_style">end</property> + <child> + <object class="GtkButton" id="ok"> + <property name="label" translatable="yes" context="stock">_OK</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="can_default">True</property> + <property name="has_default">True</property> + <property name="receives_default">True</property> + <property name="use-underline">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkButton" id="help"> + <property name="label" translatable="yes" context="stock">_Help</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="use-underline">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + <property name="secondary">True</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">end</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkNotebook" id="tabcontrol"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <property name="scrollable">True</property> + <property name="enable_popup">True</property> + <child> + <!-- n-columns=1 n-rows=1 --> + <object class="GtkGrid"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + </object> + </child> + <child type="tab"> + <object class="GtkLabel" id="general"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes" context="viewcertdialog|general">General</property> + </object> + <packing> + <property name="tab_fill">False</property> + </packing> + </child> + <child> + <!-- n-columns=1 n-rows=1 --> + <object class="GtkGrid"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + </object> + <packing> + <property name="position">1</property> + </packing> + </child> + <child type="tab"> + <object class="GtkLabel" id="details"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes" context="viewcertdialog|details">Details</property> + </object> + <packing> + <property name="position">1</property> + <property name="tab_fill">False</property> + </packing> + </child> + <child> + <!-- n-columns=1 n-rows=1 --> + <object class="GtkGrid"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + </object> + <packing> + <property name="position">2</property> + </packing> + </child> + <child type="tab"> + <object class="GtkLabel" id="path"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes" context="viewcertdialog|path">Certification Path</property> + </object> + <packing> + <property name="position">2</property> + <property name="tab_fill">False</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + </child> + <action-widgets> + <action-widget response="-5">ok</action-widget> + <action-widget response="-11">help</action-widget> + </action-widgets> + </object> +</interface> diff --git a/xmlsecurity/util/xmlsecurity.component b/xmlsecurity/util/xmlsecurity.component new file mode 100644 index 0000000000..7dfe91a0d9 --- /dev/null +++ b/xmlsecurity/util/xmlsecurity.component @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + --> + +<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.security.CertificateContainer" + constructor="com_sun_star_security_CertificateContainer_get_implementation"> + <service name="com.sun.star.security.CertificateContainer"/> + </implementation> + <implementation name="com.sun.star.security.DocumentDigitalSignatures" + constructor="com_sun_star_security_DocumentDigitalSignatures_get_implementation"> + <service name="com.sun.star.security.DocumentDigitalSignatures"/> + <optional/> + </implementation> +</component> diff --git a/xmlsecurity/util/xmlsecurity.component.dds b/xmlsecurity/util/xmlsecurity.component.dds new file mode 100644 index 0000000000..5dc5f67653 --- /dev/null +++ b/xmlsecurity/util/xmlsecurity.component.dds @@ -0,0 +1,7 @@ +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +com.sun.star.security.DocumentDigitalSignatures diff --git a/xmlsecurity/util/xsec_xmlsec.component b/xmlsecurity/util/xsec_xmlsec.component new file mode 100644 index 0000000000..f2b072949a --- /dev/null +++ b/xmlsecurity/util/xsec_xmlsec.component @@ -0,0 +1,60 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + --> + +<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.xml.crypto.NSSInitializer" + constructor="com_sun_star_xml_crypto_NSSInitializer_get_implementation"> + <service name="com.sun.star.xml.crypto.NSSInitializer"/> + <optional/> + </implementation> + <implementation name="com.sun.star.xml.crypto.SEInitializer" + constructor="com_sun_star_xml_crypto_SEInitializer_get_implementation"> + <service name="com.sun.star.xml.crypto.SEInitializer"/> + <optional/> + </implementation> + <implementation name="com.sun.star.xml.security.SEInitializer_Gpg" + constructor="com_sun_star_xml_security_SEInitializer_Gpg_get_implementation"> + <service name="com.sun.star.xml.crypto.GPGSEInitializer"/> + <optional/> + </implementation> + <implementation name="com.sun.star.xml.crypto.SecurityEnvironment" + constructor="com_sun_star_xml_crypto_SecurityEnvironment_get_implementation"> + <service name="com.sun.star.xml.crypto.SecurityEnvironment"/> + <optional/> + </implementation> + <implementation name="com.sun.star.xml.wrapper.XMLDocumentWrapper" + constructor="com_sun_star_xml_wrapper_XMLDocumentWrapper_get_implementation"> + <service name="com.sun.star.xml.wrapper.XMLDocumentWrapper"/> + </implementation> + <implementation name="com.sun.star.xml.wrapper.XMLElementWrapper" + constructor="com_sun_star_xml_wrapper_XMLElementWrapper_get_implementation"> + <service name="com.sun.star.xml.wrapper.XMLElementWrapper"/> + </implementation> + <implementation name="com.sun.star.xml.crypto.XMLSecurityContext" + constructor="com_sun_star_xml_crypto_XMLSecurityContext_get_implementation"> + <service name="com.sun.star.xml.crypto.XMLSecurityContext"/> + <optional/> + </implementation> + <implementation name="com.sun.star.xml.crypto.XMLSignature" + constructor="com_sun_star_xml_crypto_XMLSignature_get_implementation"> + <service name="com.sun.star.xml.crypto.XMLSignature"/> + <optional/> + </implementation> +</component> diff --git a/xmlsecurity/util/xsec_xmlsec.component.gpg b/xmlsecurity/util/xsec_xmlsec.component.gpg new file mode 100644 index 0000000000..c770a555ba --- /dev/null +++ b/xmlsecurity/util/xsec_xmlsec.component.gpg @@ -0,0 +1,7 @@ +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +com.sun.star.xml.security.SEInitializer_Gpg diff --git a/xmlsecurity/util/xsec_xmlsec.component.nss b/xmlsecurity/util/xsec_xmlsec.component.nss new file mode 100644 index 0000000000..3ff9557b92 --- /dev/null +++ b/xmlsecurity/util/xsec_xmlsec.component.nss @@ -0,0 +1,7 @@ +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +com.sun.star.xml.crypto.NSSInitializer diff --git a/xmlsecurity/util/xsec_xmlsec.component.nss_mscrypt b/xmlsecurity/util/xsec_xmlsec.component.nss_mscrypt new file mode 100644 index 0000000000..c713c1e83f --- /dev/null +++ b/xmlsecurity/util/xsec_xmlsec.component.nss_mscrypt @@ -0,0 +1,10 @@ +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +com.sun.star.xml.crypto.SecurityEnvironment +com.sun.star.xml.crypto.SEInitializer +com.sun.star.xml.crypto.XMLSecurityContext +com.sun.star.xml.crypto.XMLSignature diff --git a/xmlsecurity/workben/pdfverify.cxx b/xmlsecurity/workben/pdfverify.cxx new file mode 100644 index 0000000000..361e0ae4ae --- /dev/null +++ b/xmlsecurity/workben/pdfverify.cxx @@ -0,0 +1,216 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <iostream> +#include <string_view> + +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/xml/crypto/SEInitializer.hpp> + +#include <comphelper/processfactory.hxx> +#include <cppuhelper/bootstrap.hxx> +#include <osl/file.hxx> +#include <sal/log.hxx> +#include <sal/main.h> +#include <comphelper/diagnose_ex.hxx> +#include <vcl/filter/PngImageWriter.hxx> +#include <vcl/svapp.hxx> +#include <vcl/graphicfilter.hxx> +#include <vcl/filter/pdfdocument.hxx> +#include <comphelper/scopeguard.hxx> +#include <svl/sigstruct.hxx> + +#include <pdfsignaturehelper.hxx> + +using namespace com::sun::star; + +namespace +{ +/// Does PDF to PNG conversion using pdfium. +void generatePreview(std::string_view rPdfPath, std::string_view rPngPath) +{ + GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter(); + Graphic aGraphic; + OUString aInURL; + osl::FileBase::getFileURLFromSystemPath(OUString::fromUtf8(rPdfPath), aInURL); + SvFileStream aInStream(aInURL, StreamMode::READ); + if (rFilter.ImportGraphic(aGraphic, u"", aInStream, GRFILTER_FORMAT_DONTKNOW, nullptr, + GraphicFilterImportFlags::NONE) + != ERRCODE_NONE) + return; + + BitmapEx aBitmapEx = aGraphic.GetBitmapEx(); + OUString aOutURL; + osl::FileBase::getFileURLFromSystemPath(OUString::fromUtf8(rPngPath), aOutURL); + SvFileStream aOutStream(aOutURL, StreamMode::WRITE); + vcl::PngImageWriter aWriter(aOutStream); + aWriter.write(aBitmapEx); +} + +int pdfVerify(int nArgc, char** pArgv) +{ + if (nArgc < 2) + { + SAL_WARN("xmlsecurity.workben", "not enough parameters"); + return 1; + } + + // Initialize nss / mscrypto. + uno::Reference<uno::XComponentContext> xComponentContext; + try + { + xComponentContext = cppu::defaultBootstrap_InitialComponentContext(); + } + catch (const uno::RuntimeException&) + { + TOOLS_WARN_EXCEPTION("xmlsecurity.workben", + "cppu::defaultBootstrap_InitialComponentContext() failed:"); + return 1; + } + uno::Reference<lang::XMultiComponentFactory> xMultiComponentFactory + = xComponentContext->getServiceManager(); + uno::Reference<lang::XMultiServiceFactory> xMultiServiceFactory(xMultiComponentFactory, + uno::UNO_QUERY); + comphelper::setProcessServiceFactory(xMultiServiceFactory); + + InitVCL(); + comphelper::ScopeGuard g([] { DeInitVCL(); }); + if (nArgc > 3 && pArgv[3] == std::string_view("-p")) + { + generatePreview(pArgv[1], pArgv[2]); + return 0; + } + + uno::Reference<xml::crypto::XSEInitializer> xSEInitializer; + try + { + xSEInitializer = xml::crypto::SEInitializer::create(xComponentContext); + } + catch (const uno::DeploymentException&) + { + TOOLS_WARN_EXCEPTION("xmlsecurity.workben", + "DeploymentException while creating SEInitializer:"); + return 1; + } + uno::Reference<xml::crypto::XXMLSecurityContext> xSecurityContext + = xSEInitializer->createSecurityContext(OUString()); + + OUString aInURL; + osl::FileBase::getFileURLFromSystemPath(OUString::fromUtf8(pArgv[1]), aInURL); + OUString aOutURL; + if (nArgc > 2) + osl::FileBase::getFileURLFromSystemPath(OUString::fromUtf8(pArgv[2]), aOutURL); + + bool bRemoveSignature = false; + if (nArgc > 3 && pArgv[3] == std::string_view("-r")) + bRemoveSignature = true; + + SvFileStream aStream(aInURL, StreamMode::READ); + if (aOutURL.isEmpty() && !bRemoveSignature) + { + std::cerr << "verifying signatures" << std::endl; + PDFSignatureHelper aHelper; + aStream.Seek(0); + aHelper.ReadAndVerifySignatureSvStream(aStream); + if (aHelper.GetSignatureInformations().empty()) + std::cerr << "found no signatures" << std::endl; + else + { + std::cerr << "found " << aHelper.GetSignatureInformations().size() << " signatures" + << std::endl; + for (size_t i = 0; i < aHelper.GetSignatureInformations().size(); ++i) + { + const SignatureInformation& rInfo = aHelper.GetSignatureInformations()[i]; + bool bSuccess + = rInfo.nStatus == xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED; + std::cerr << "signature #" << i << ": digest match? " << bSuccess << std::endl; + std::cerr << "signature #" << i << ": partial? " << rInfo.bPartialDocumentSignature + << std::endl; + } + } + + return 0; + } + + vcl::filter::PDFDocument aDocument; + if (!aDocument.Read(aStream)) + { + SAL_WARN("xmlsecurity.workben", "failed to read the document"); + return 1; + } + + if (bRemoveSignature) + { + std::cerr << "removing the last signature" << std::endl; + std::vector<vcl::filter::PDFObjectElement*> aSignatures = aDocument.GetSignatureWidgets(); + if (aSignatures.empty()) + { + std::cerr << "found no signatures" << std::endl; + return 1; + } + + size_t nPosition = aSignatures.size() - 1; + if (!aDocument.RemoveSignature(nPosition)) + { + SAL_WARN("xmlsecurity.workben", "failed to remove signature #" << nPosition); + return 1; + } + + SvFileStream aOutStream(aOutURL, StreamMode::WRITE | StreamMode::TRUNC); + if (!aDocument.Write(aOutStream)) + { + SAL_WARN("xmlsecurity.workben", "failed to write the document"); + return 1; + } + + return 0; + } + + std::cerr << "adding a new signature" << std::endl; + uno::Reference<xml::crypto::XSecurityEnvironment> xSecurityEnvironment + = xSecurityContext->getSecurityEnvironment(); + uno::Sequence<uno::Reference<security::XCertificate>> aCertificates + = xSecurityEnvironment->getPersonalCertificates(); + if (!aCertificates.hasElements()) + { + SAL_WARN("xmlsecurity.workben", "no signing certificates found"); + return 1; + } + if (!aDocument.Sign(aCertificates[0], "pdfverify", /*bAdES=*/true)) + { + SAL_WARN("xmlsecurity.workben", "failed to sign"); + return 1; + } + + SvFileStream aOutStream(aOutURL, StreamMode::WRITE | StreamMode::TRUNC); + if (!aDocument.Write(aOutStream)) + { + SAL_WARN("xmlsecurity.workben", "failed to write the document"); + return 1; + } + + return 0; +} +} + +SAL_IMPLEMENT_MAIN_WITH_ARGS(nArgc, pArgv) +{ + try + { + return pdfVerify(nArgc, pArgv); + } + catch (...) + { + std::cerr << "pdfverify: uncaught exception while invoking pdfVerify()" << std::endl; + return 1; + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |