diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
commit | ed5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch) | |
tree | 7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /xmlsecurity | |
parent | Initial commit. (diff) | |
download | libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.tar.xz libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.zip |
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'xmlsecurity')
699 files changed, 58122 insertions, 0 deletions
diff --git a/xmlsecurity/AllLangMoTarget_xsc.mk b/xmlsecurity/AllLangMoTarget_xsc.mk new file mode 100644 index 000000000..90b80207c --- /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 000000000..faa5459d3 --- /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 000000000..945c33af7 --- /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 000000000..667acc97e --- /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 000000000..91b4ae39f --- /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 \ + xmlsecurity/qa/unit/signing/signing2 \ +)) + +$(eval $(call gb_CppunitTest_use_libraries,xmlsecurity_signing, \ + comphelper \ + cppuhelper \ + cppu \ + sal \ + sax \ + sfx \ + svx \ + 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/Executable_pdfverify.mk b/xmlsecurity/Executable_pdfverify.mk new file mode 100644 index 000000000..ed8e9559f --- /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 000000000..b3ea0f00e --- /dev/null +++ b/xmlsecurity/IwyuFilter_xmlsecurity.yaml @@ -0,0 +1,134 @@ +--- +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/GpgComponentFactory.cxx: + # Silence warning due to incorrect include path + - com/sun/star/lang/XSingleServiceFactory.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 000000000..8507b4bab --- /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 000000000..615c3eba0 --- /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 000000000..0997e6284 --- /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 000000000..62852c0a4 --- /dev/null +++ b/xmlsecurity/Module_xmlsecurity.mk @@ -0,0 +1,48 @@ +# -*- 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_Module_add_slowcheck_targets,xmlsecurity,\ + CppunitTest_xmlsecurity_pdfsigning \ +)) + +$(eval $(call gb_Module_add_subsequentcheck_targets,xmlsecurity,\ + CppunitTest_xmlsecurity_signing \ +)) + +$(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 000000000..b983f5dc5 --- /dev/null +++ b/xmlsecurity/README.md @@ -0,0 +1,32 @@ +# Stuff for Document Signing + +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. + +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 000000000..06482e2a2 --- /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.sxw b/xmlsecurity/doc/OpenDocumentSignatures-TestIntegration.sxw Binary files differnew file mode 100644 index 000000000..2973f08c8 --- /dev/null +++ b/xmlsecurity/doc/OpenDocumentSignatures-TestIntegration.sxw diff --git a/xmlsecurity/doc/OpenDocumentSignatures-Workflow.sxd b/xmlsecurity/doc/OpenDocumentSignatures-Workflow.sxd Binary files differnew file mode 100644 index 000000000..abc5f32c6 --- /dev/null +++ b/xmlsecurity/doc/OpenDocumentSignatures-Workflow.sxd diff --git a/xmlsecurity/doc/OpenDocumentSignatures.sxw b/xmlsecurity/doc/OpenDocumentSignatures.sxw Binary files differnew file mode 100644 index 000000000..9b453e0d8 --- /dev/null +++ b/xmlsecurity/doc/OpenDocumentSignatures.sxw diff --git a/xmlsecurity/doc/XMLSecurityFramework.sxw b/xmlsecurity/doc/XMLSecurityFramework.sxw Binary files differnew file mode 100644 index 000000000..c778e1c1e --- /dev/null +++ b/xmlsecurity/doc/XMLSecurityFramework.sxw diff --git a/xmlsecurity/inc/UriBindingHelper.hxx b/xmlsecurity/inc/UriBindingHelper.hxx new file mode 100644 index 000000000..67c9ae69f --- /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 000000000..fc99320c7 --- /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 000000000..2d4ccd0c4 --- /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 OUStringLiteral BMP_STATE_NOT_VALIDATED = u"xmlecurity/res/notcertificate_40x56.png"; + +#define BMP_CERT_OK "xmlsecurity/res/certificate_16.png" +#define BMP_CERT_NOT_OK "xmlsecurity/res/notcertificate_16.png" + +inline constexpr OUStringLiteral BMP_SIG_VALID = u"xmlsecurity/res/signet_11x16.png"; +inline constexpr OUStringLiteral BMP_SIG_INVALID = u"svx/res/caution_11x16.png"; +inline constexpr OUStringLiteral BMP_SIG_NOT_VALIDATED = u"xmlsecurity/res/notcertificate_16.png"; + +/* 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 000000000..bd24bcd72 --- /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 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 000000000..8ad4c3190 --- /dev/null +++ b/xmlsecurity/inc/certificatechooser.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/uno/Sequence.hxx> +#include <vcl/weld.hxx> +#include <unotools/resmgr.hxx> + +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: + 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; + + DECL_LINK(ViewButtonHdl, weld::Button&, void); + DECL_LINK(CertificateHighlightHdl, weld::TreeView&, void); + DECL_LINK(CertificateSelectHdl, weld::TreeView&, bool); + + void ImplShowCertificateDetails(); + void ImplInitialize(); + + 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; + + 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 000000000..ea47c4102 --- /dev/null +++ b/xmlsecurity/inc/certificateviewer.hxx @@ -0,0 +1,158 @@ +/* -*- 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> + +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 OString&, 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 OString& 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(const OUString& rTxt, bool bFixedWidthFont) + : maTxt(rTxt) + , 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> const & xCert, bool bValid) + : mxCert(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 000000000..28ed32ccb --- /dev/null +++ b/xmlsecurity/inc/digitalsignaturesdialog.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 <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; + + 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::CheckButton> m_xAdESCompliantCB; + 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(AdESCompliantCheckBoxHdl, weld::Toggleable&, void); + 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, const 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 000000000..b18ccf103 --- /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(const OUString & sODFVersion); + bool isOOo3_2_Signature(const SignatureInformation & sigInfo); + + DocumentSignatureAlgorithm getDocumentAlgorithm( + const OUString & sODFVersion, const SignatureInformation & sigInfo); + + bool CanSignWithGPG(const css::uno::Reference < css::embed::XStorage >& rxStore, + const OUString& 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 000000000..06dd200de --- /dev/null +++ b/xmlsecurity/inc/documentsignaturemanager.hxx @@ -0,0 +1,135 @@ +/* -*- 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> + +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; + css::uno::Reference<css::io::XStream> 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 000000000..161b9a936 --- /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 000000000..bebf07306 --- /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 000000000..d0fc1dc33 --- /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 000000000..6446c2f36 --- /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 000000000..15c79643e --- /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 000000000..c0dee1173 --- /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 000000000..e4da22029 --- /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 000000000..906a51d19 --- /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 000000000..233ef2c1d --- /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 OString&, void); + DECL_LINK(OkBtnHdl, weld::Button&, void); +public: + MacroSecurity(weld::Window* pParent, + const css::uno::Reference<css::xml::crypto::XSecurityEnvironment>& rxSecurityEnvironment); + + 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 OString& 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 000000000..16ace305f --- /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 000000000..21e6b93a9 --- /dev/null +++ b/xmlsecurity/inc/pch/precompiled_xmlsecurity.hxx @@ -0,0 +1,201 @@ +/* -*- 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 <vcl/errcode.hxx> +#include <vcl/fntstyle.hxx> +#include <vcl/font.hxx> +#include <vcl/mapmod.hxx> +#include <vcl/region.hxx> +#include <vcl/scopedbitmapaccess.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 000000000..74123c2f1 --- /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 000000000..3ed774968 --- /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 <vcl/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 000000000..ea24685d2 --- /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 000000000..1dc5b2987 --- /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 000000000..8cf89b211 --- /dev/null +++ b/xmlsecurity/inc/strings.hrc @@ -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 + +#define NC_(Context, String) TranslateId(Context, reinterpret_cast<char const *>(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_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 000000000..e4048de94 --- /dev/null +++ b/xmlsecurity/inc/xmlsec-wrapper.h @@ -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 . + */ + +#pragma once + +#include <sal/config.h> + +#include <sal/types.h> + +// Cf. xmlsec's configure.in: +#if SAL_TYPES_SIZEOFPOINTER != 4 && !defined SYSTEM_XMLSEC +#define XMLSEC_NO_SIZE_T +#endif + +#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 000000000..80ba564e9 --- /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 000000000..a49ccef18 --- /dev/null +++ b/xmlsecurity/inc/xmlsec/saxhelper.hxx @@ -0,0 +1,85 @@ +/* -*- 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/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 000000000..8f5695d10 --- /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 000000000..417acd288 --- /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 000000000..6e3d506a4 --- /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 000000000..7f31e6f8f --- /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 000000000..de7de9908 --- /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, const OUString& 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 000000000..adfd251b1 --- /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 OUStringLiteral NS_XMLDSIG = u"http://www.w3.org/2000/09/xmldsig#"; +inline constexpr OUStringLiteral NS_DC = u"http://purl.org/dc/elements/1.1/"; +inline constexpr OUStringLiteral NS_XD = u"http://uri.etsi.org/01903/v1.3.2#"; +inline constexpr OUStringLiteral NS_MDSSI = u"http://schemas.openxmlformats.org/package/2006/digital-signature"; +inline constexpr OUStringLiteral NS_LOEXT = u"urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0"; + +inline constexpr OUStringLiteral ALGO_C14N = u"http://www.w3.org/TR/2001/REC-xml-c14n-20010315"; +inline constexpr OUStringLiteral ALGO_RSASHA1 = u"http://www.w3.org/2000/09/xmldsig#rsa-sha1"; +inline constexpr OUStringLiteral ALGO_RSASHA256 = u"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"; +inline constexpr OUStringLiteral ALGO_RSASHA512 = u"http://www.w3.org/2001/04/xmldsig-more#rsa-sha512"; +inline constexpr OUStringLiteral ALGO_ECDSASHA1 = u"http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1"; +inline constexpr OUStringLiteral ALGO_ECDSASHA256 = u"http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256"; +inline constexpr OUStringLiteral ALGO_ECDSASHA512 = u"http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512"; +inline constexpr OUStringLiteral ALGO_XMLDSIGSHA1 = u"http://www.w3.org/2000/09/xmldsig#sha1"; +inline constexpr OUStringLiteral ALGO_XMLDSIGSHA256 = u"http://www.w3.org/2001/04/xmlenc#sha256"; +inline constexpr OUStringLiteral ALGO_XMLDSIGSHA512 = u"http://www.w3.org/2001/04/xmlenc#sha512"; +inline constexpr OUStringLiteral ALGO_RELATIONSHIP = u"http://schemas.openxmlformats.org/package/2006/RelationshipTransform"; + +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(const css::uno::Reference<css::uno::XComponentContext>& rxCtx); + 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 000000000..36f8ad52a --- /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 000000000..c117f4c00 --- /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 000000000..0092d16c7 --- /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 000000000..5a4c244c6 --- /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/templates/intermediate.cnf b/xmlsecurity/qa/create-certs/templates/intermediate.cnf new file mode 100644 index 000000000..c6fd12d0a --- /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 000000000..1298d74d3 --- /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 000000000..1f8ee2b62 --- /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 000000000..10528c57f --- /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 000000000..04d995058 --- /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 000000000..b30f5b038 --- /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 000000000..b1aae07a2 --- /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
bWEH/k3lnCx4nfoDyT/1atM/6Rof+qePCvErWvlvyZJKtNH011rvS0hI6f8AGPAY7KJbph/hXyT/
ANWPTf8ApCh/6pZXwlnYb/wr5K/6sem/9IUP/VLHhK2Hf4U8lf8AVj03/pDh/wCqWPCVsN/4T8l/
9WPTf+kOH/qljRW3f4S8mf8AVi03/pDh/wCqWNJtv/CHk3/qxab/ANIcH/VPBS23/g/yd/1YtN/6
Q4P+qeNKl975W8nxTEHRdOQAA/7yQgf8m8sjGwwlKihf0B5J/wCrVpn/AEiw/wDVPDwo4nfoDyT/
ANWrTP8ApFh/6p48K8SNsvLHkt1YtoumsNqE2cJ/5lZGUWUZIn/Cvkn/AKsem/8ASFD/ANUsjwlN
hv8Awp5K/wCrHpv/AEhQ/wDVLHhK2Hf4U8lf9WPTf+kOH/qljRW2/wDCfkv/AKsem/8ASHD/ANUs
aK27/CXkz/qxab/0hw/9UsaTbf8AhDyb/wBWLTf+kOD/AKp4KVAa/wCSfLlxoOpwaXoWni/ltJ0t
DHbQRuJmjcRcXKLxPKlDUUxpUhVVbyJoAbp9Vs/2Vb/j28HdBlh5MBzSpLdZHEcY5uxoqrDEST7A
T5FLJNDebT0W1/R04aZwJJ/TWNaE0BZQ7fZByQQWTPoek3/G4vLWOaUqAXYGtB075CXNkOS+10HR
7Kdbm1tI4po68XUGoqCp7+BwJa8wwSXOj3EESGV34URUWUmjofsOyA9PHFWE/oK//wCWKX/pBh/7
KcKHfoK//wCWKX/pBh/7KcVVbXy5e3NwkMlu8CuTWWWyi4rtXelwTiqdWfksW91FPLcQSpGwYotq
qE0/yhIaYLSn2ooJLcKTT4gf15KB3YzGzCtV0y1kv5Xk066uWPGssRojfCvTft0yZq2I5IaHRrCW
VI20q8jDsFLs2ygmnI/F0GCh3J372SaZo1ppnJbQPRiXK1qSQOgrhugjmV/6Suv+rRffdH/1UyPE
ypMrFWu4BNJDLasSR6cwHLbv8JODiTSC1bVINJmSF4pJjIvOqtGoG5FP3jqe2PEtIH/FdsP+PSb/
AJGQf9VcbWl3+LLb/lkl/wCRkH/VXG1pv/F1t/yyTf8AIyD/AKq4LVO7PULK8SP0p4/VlUP6PNGd
aipUhWO4742qF1S0juZJI5CeMicGA8CKHJwOzGQ3SH/B2j/yv/wRw0Fsu/wdo/8AK/8AwRxoLZTF
5bfRLKP4HljBWFFVkBACmlTIy+GCUlAQ3+J7X/llm/5GQf8AVbBxJpv/ABRa/wDLLN/yMg/6q4OJ
ab/xTa/8ss3/ACMg/wCquNppsea7Yf8AHpN/yMg/6q42tN/4stv+WSb/AJGQf9VcbVNtL1K11OMM
hEUu/wC4Z0ZwB+1RGbbBartcvW0jRNR1WNRI9jaz3Ko2wYxRtIFNPHjjaaYbZ3Edt5I0GSSKGcG0
s143Cs6g/VwagKr77ZPow6oWPWoYnWSKz09HU1VlhlBB9iIcFppONK8yRXcnoXjRpK7KsKxLKeRP
iXjAGEFBCO1LzJcaZcLaxiAqEVv3gn5b/wDGKF1/HInmyHJB/wCNLz+W1+66/wCyfBSU1j8wPLoM
uqr6RlhcIwpMIwSyDvF6n2XHRcCpV/jS8/ltfuuv+yfDSu/xpefy2v3XX/ZPjSu/xpefy2v3XX/Z
PjSp7oGry6vDNJKIgY2Cj0hIBuK7+tHGcCo69/uf9kMlDmxlySC613SbOdra5uBHKlOSlWNKgMOi
nscnYY0o/wCJ9C/5ax/wD/8ANGPEFoppp97bXCJewyc4CGbnQjZeQbYivbBLkkc2v8X+XP8AluT/
AIF/+aMrZplZX9pqMAubKQTRElQ4BG46/aAxVj3mqLS5LyE32oRWTiL4UktknJHJt+To1PliqRi2
8vHYa1b/APcPi/6p4UO+r+Xf+r1b/wDcPi/6p4q76v5d/wCr1b/9w+L/AKpYqyLy1pFnE36TtrmK
9jdWSN0to4SprRiGRVb2wJTO8/vj8hlkeTGXNQwsXYqlPmQA6fHUoP3w/vBAR9l/+Wohfu3yMmUW
M0T+e3/4HTv+a8il1E/nt/8AgdO/5rxV1E/nt/8AgdO/5rxV1E/nt/8AgdO/5rxVHfoHV/8Alhf/
AKRrLFUVpum65Y3sM8drLGA6iThDaR8k5AspaM8qGmKsh85/8ofr3/bNvP8AkxJgSxnTrC41HyVo
UFsUDrZ2bnmzIKC3A6xgnvllWGF7qH+FtX/ng/5HT/8ANOPCVtXsvLF6lyj3jp6Kmp9KaUtUdKc1
p1xEVtNtV0DU9RuFubVohGUUfHPNGaj/ACYlK5E82Q5IP/CWufz2/wD0lXX/ADTgSn0XlmwihmgW
S4K3AVXJmYkBWDjie24wKpf4Q0z/AH7df8j3xtXf4Q0z/ft1/wAj3xtV8HlbTreeO4SW5LROrqGm
YglTUVHcbYqnWKoe9/uf9kMlDmxlyS/LGLsVVrb+/T5/wwS5JjzTLKmbsVYl5ue4W9hEMjIPS3Aa
5Xfk3/LMjL9+EKkHq3v+/n/5Gah/1SxQ71b3/fz/APIzUP8AqliqrbJqN1OlvFMech4rylv1Ffdm
jAGKs50e2urPT4ra8ZWmQtUq7yAgsWHxy0Y9cCVHVZGhWaVKco4yy1qRUAkV475OPJiebEP8T6r/
AC23/Iu5/wCaMbWkzh8zWJjjEwk9UqOfCJ+PKm/GorSuG0Um1xb3dzb8bSG1ncOCVvQxQCh3Xirb
4Jpihf0Xrf8A1b9F/wCAk/6pZBknC6TplBysrflTekSUr/wOKsSudSeG5miTT9O4xuyrytbgmgJA
rxgI+7ChT/S0v/Vv03/pFuf+yfFUV/izWf5LX/kVef8AVHGkqkHmzU/Wj+spbiHkPU9OG7L8a/Fx
5RAVpjSpn5ukWbyXrcqV4yaXdstRQ0NvIdwcCsX0kaivk/RDZTx2zmztPjmYBSvoLsKht8u6NXVr
l5k/6udn/wAGv/VPBZ707Jzp7XUlsqzzpcTp/etCwK7k06U7e2SBDEhNo5vSRUlmVGpXizgH7i2Q
JFsxdL0uEdgiTozNsAJFJJ/4LBYTurN6sal5G4KOrM1APpJxsLupi7g/5aI/+Ri/81Y2FbF5b/8A
LRH/AMjF/wCasGyVwvbbvcR/8jF/5qx2VViuIZW4RSpI3WiuCafQcCuvK+jv/MMMeaJJDdWmrSzt
JbaiLeI04xGBX40AB+IsK75Pdio/UNd/6uw/6RU/5rxorYR2l22oxSMLq9FyzikTeksfA0beiseX
UYDySOar+jfMf/V6T/pDT/qplbNNLWO4it0juphcTKPjlCCPlv8AyAmmKpPr8+uRXMY0szCIpV/S
t45hyqerSSoRtiqVC8839zdf9IUH/ZRhV31zzh/Ndf8ASFB/2UYq7655v8br/pCg/wCyjFU10O+1
hpTb6pDcPzNVnkhjhRAB0IjletcCo68/vj8hlkeTGXNQwsXYqjLHo/zGQmyii8iydirzq+sLhr24
YWE7AyuQwt7sg1Y7grcAfdhQofo+5/6t1x/0jXn/AGU4qmlr5Su7q3S4Cww8xX05hdI4oafEpuNs
VVf8F3n81r991/2UY2lMPMVhBp3kXW7W3Xgo028LDkzfEYJORBkZj+OBWO208Nv5H0F5oIrlTaWY
CTNxUH6uN6+OWdGHVA/pOw/6tdl/yMH9MFppkNhqXlu2ISzkhhkn4hlQEVbsOnvkgQggo3ULK4nn
WSLRLbUF4KPXmkRWPtRgemQPNkOSnZWF5HdwSHy7aW4WRSZklQtGKirqAvUYEp1rkscOlXEs0Udw
iqOUUxCo3xL9omuBWHW19ZXk6W1toenSyybIizJU0Ff5PbChMf0bef8AUsWX/I6P/mnFLv0bef8A
UsWX/I6P/mnFU40PT44Fa5m0yDTbmpQCEq9Y6Ka8lA6ntgVH3v8Ac/7IZKHNjLkkF1pAup2n+uXc
POnwQzFEFABstPbJ0xtTTQwjq/1++biQeLTkg07EUxpbTeFecgSpXkCKqaEVB3BxlyTHmo/4bT/q
56l/0lN/TKmaZ2dqLK3W3Ess/Ek+pO5kc1Nd2OKsZ83XUsF7Csd1LbgxV4xyzxg/E29IIpBhVIBq
NyN/0jcf9JN5/wBk2KHfpG5/6uNx/wBJN5/2TYq79IXP/VxuP+km8/7JsVZVoVhrlpdiW8kaW3kQ
g+pdSTEdwVR0XfAlHaqJSswgr6pjPp0IB5UPGhbbrk48mJ5sQ9Hzd4XH/I23x3XZNY9K1P4WfVZu
xZCifSK4aRacm1ubuEpbXb2TKwJeNVYkUO3xg4Jpipro+qggnWpyAdx6cW//AAuQZJzirAb3W9Vj
vLiNL1lVJXVV+sWYoAxAFG3H04UKH6e1f/lub/pJssVd+ntX/wCW5/8ApJssVVrXzJqcFwks1wbm
NT8UT3VmA23itDirIvNkhm8k61KV4GTSrpitQ1K28hpyGxwJY/pLunkzQjHPb25+pWg53dOB/cLs
K03yzow6tfWLn/q5aT/wv/NWKphZXunpCPr15YvMCTyiZFFO3U4QVRt5qF1BIiQapp9qhRSI7k/v
N+/94ux7ZWebIcm7DUb6a8iifVtNuFY7xQGsjClaL+9OBKbak7R2UrpLDAwApLc/3S7j7e4xVjw1
C7U8l1jRgR0IoP8AmbhVf+ltQ/6vmkff/wBfsVd+ltQ/6vekff8A9fcVTjSJL2aFprq5trtGI9KS
0B47V5VPJq4FRF7/AHP+yGShzYy5JBdasbadoPqN3Pwp+8hjDIagHY8x45O2NKP6dP8A1bL/AP5E
j/qpja0i9N1Y3F0E+o3cPFWessYUGg+yPjO57YJHZIG6I/xE/wD1aNS/5Er/ANVcrZpjY3hvofWN
vNa/EV9O4UI+1N6Bm23xVJfMcmmJdRC+t7yd/T+FrV+KgVOx/ex74qlAm8vf8sOqf8jT/wBlOFCt
a3+h2dwlzDY6n6kZqvN+Q3FN1a4I74pTP/GFp/yw3v8AwEf/AFWwKmum6jHqdubmOKSEBinGYANt
Tf4WYd8VU7z++PyGWR5MZc1DCxdiqMsej/MZCbKKLyLJ2KsKu/L2tS3U0kccpR5GZaXcaihJI2Ns
affhQpf4b13/AH3L/wBJkf8A2S4qmNl5SaWANfXN1bzVNUSaNxTseXoDAlH2fli0s7hZzcXFzxBH
pzmNkNRTcCJcVd5yAHk/XQBQDTLwAD/jBJirHtHhmn8m6EkFtBdsLK0JS5FUA9BfiGx3yzow6t/o
/Uf+rRpn/Aj/AJpxpbTK20qxaBDdWFqkxHxqkSFQfYlcNItXvNPup5EeDS9PukCKBJcj95t2/u22
HbKzzZjk1Z6fqMF1FL+iNMgCuOUsO0iqdmKfuhvTAlM9alSDS7iWSOKZFArHOpaM/EPtKqufwxVh
v6YsP+rZpX/SPN/2SYUO/TFh/wBWzSv+keb/ALJcVd+mLD/q2aX/ANI83/ZLiqP0/wAyXbPHYadb
2MfM0jiRbiNanf8A5Z1UYpZPcGQ2qGYBZDx5hTUBqb0OGHNjLkkd1ruk2c7W1zcCOVKclKsaVAYd
FPY5Owxp1rruk3k621tcCSV68VCsK0BY9VHYY2FpM4XWOQSOaKgLMfAAEnGXJMeaNs7y2v7dLu0c
SwyV4OAQDxJU9adxlTNXxVi3mqLS5LyE32oRWTiL4UktknJHJt+To1PliqR/V/Lv/V6t/wDuHxf9
U8KHfV/Lv/V6t/8AuHxf9U8VTOzn8jQW6RXUtrdTLXlMbfgWqSR8KR0FBtilk2lrpv1NJNJVEtZS
XX014qT9kmlB4YFQ+qxGZZoVpWSMoK1pVgRvShyceTE82Ir5SueQ5m2K1FQDPWn/ACMw0tpuvlrR
UYMtuQVNR+9l6j/npjQRabHTLLU4TDexmREYMoDum9COsbKe+CaYqX+EdA/5Zn/5Hzf9VcgyTaGG
O3hjgiHGOJQiAkmiqKDc1OKvPr6wuGvbhhYTsDK5DC3uyDVjuCtwB92FCh+j7np+jrj/AKRrz/sp
xV36Puf+rdcf9I15/wBlOKr4tMupZEi+oTJzYLye3vAoqaVY/Wdhiqeappcmk+RPMNtKYyWsb2T9
16hFDbMv+7nc1+HxwJQeh6hHpvk7Q55Y5JVaxtE4xAE1MCmvxMu22Wg0GFbq8fme3lbhFZXkjdaL
GhP4SY8S0jLPUzdzekbO6t9iec8YVdu1eRxtFJhLrDWRWAafeXNFB9S3jV037VLrlcubMcnW+utP
MkJ0y/i9RgvqSRKEWvdj6h2wJROrmBdNnNykskQA5pAaSH4h9k8k/XirFYbvQYJo547HVOcTB15S
VFVNRUG5ocKE2/xjaf8ALBe/8BH/ANVsCXf4wtP+WG9/4CP/AKrYqjrLWWvJ1g/R97bhgT6s8SrG
KCu7CRuuKou9/uf9kMlDmxlySxoYXPJ41YnqSATljFywwoeSRqpHQgAHFURbbzoD7/qwS5JjzTJV
VRxUBQOw2GVM28VYh5wlMd9ABcPDWLokk6A/E29IYZBhCse+st/y2y/8j7v/ALJcUO+st/y2y/8A
I+7/AOyXFXfWW/5bZf8Akfd/9kuKsz8s3OnvC0Fpd3F3KFV5RcGVghpQhGljTauBKJ1USMsyw19Q
xkJQhTyoaUJ6b5OPJiebEPqnmnwuf+kuL/qnjuuyOs9J1WaHnd311ayVI9MSJJt48lUYaRaex2E1
zarBHeTW7RceUsRXm9AR8XJT164JJit/QN5/1eb374/+qeQZJwilEVSxYqACx6mnc4q8/vdavo72
4jW8lULK6gC8hUABiKcTbmmFCj+nb/8A5bZf+k6H/smxV36dv/8Altl/6Tof+ybFXfp2/wD+W2X/
AKTof+ybFU3vL+TUPy8155TzaGwvYi5lWYtS3Z6syIgr8XSmBKzy5aW155R0OK6iWZBYWjBXFRUQ
IK/jlo5NZ5plbaXp1pJ61tbpFJSnJRQ0ONLaKwqmdv8A3CfLKpc2Y5KuBKA1yCW40q4hgQySOoCo
FR6/Ep+zL8J+nFWE/oHV/wDlhf8A6RrLCh36B1f/AJYX/wCkayxVGaf5VvbsuLpRZBAOJktLRuVa
9OFemKswsYLm2txFdXBu5AT+9KLHt2HFNtsCW73+5/2QyUObGXJi9/5iisLuS0aB5DHT4g6AHkob
ozA98mSilO380200yRPC0SuaGR5I+K+5+PBxLSdWd9ayzUtpkuHQFvTidWYgDwBxlyUc3fp68/6s
1790f/VTK2abxOZI0kZTGXUMUbqpIrQ/LFWO+ZZdNju4hewXEzmP4TDOIgByPUGWOuKpN9Z0H/lj
vf8ApMX/ALKMKHfWdB/5Y73/AKTF/wCyjFUTHbWUqCSLSdTdG3VluCQR7ET4qm+h6barKbxbW7s5
IjxVbqVmDBhuQvqOMCUdef3x+QyyPJhLmoYUOxVGWPR/mMhNlFF5Fk7FXml/elb65X64y0mkFPrc
q0+I7cRHthQh/rx/5bX/AOkyb/qliqJsEvtUma3sLiSaRVLlReyCiggV+KMd2xVObHS/MtjN64gF
x8JXhcXbSJvTfiV67YpR/mX6x/gbWzdRJBOdMvDJHEaqD6MvQ/LAqRabZXd/5L0KGzdUkWztHJZ3
QcRbqOsYJ75ZWzDqus/Ll/63+nz0hof7ieUtXt9sUxpbTux0+LT1dYpJZA5BJlcuRTwrhARaMl0S
3vytxLPcxsVA4wzPGu3+SpyuXNmOTdt5ftbWdLhLi6dozULJO7KfmpO+BKpr5caRcmMlW4ihBcft
L3hBf7sVYJ6t7/v5v+Dv/wDqlhQr2cGp39wttbz/ALxgSOc18g2FftNGBiqZf4Z8x/7/AIv+ku7/
AOacUozTPLeoJPz1Oc+mgBT6vdTsSwI+0JABTFU/vf7n/ZDDDmxlyYtqFtdSXcjx6TaXSnjSaUpz
b4R15KTt0yZQEN9Tvf8AqxWP3x/80YPgqdaTaR2/CdLKC2uyrBliVRv1481UbbDEjZRzTWwl1CWN
m1G3S2kDUVY5PUBWnWvFcrZovFWMeaNSsbK7hjurKzumaPkGuvtAcmFB+6k2xVJf09pH/Vq0r8P+
ybCh36e0j/q1aV+H/ZNiqMi87CCNYYLezijQUVEldVA9gIMUsxt5DNBFKwAMiKxANQCRXY7YFQOo
CRmcRMEkKURiKgNTY0yyPJhLmkf1TzH/ANXCH/kT/bh3XZsWnmOorfwkd/3P9uO67JwYtQlhK6dc
JbSBgWaSP1AVodqclyM0xUvqfmf/AKuVv/0jf9fMgyVrO216O4R72+hngFecaQ8GOxpRuZ74qx67
8w61FdTRxyShEkZVpaRsKAkDc3Ir92FCl/iTXP8Afkv/AEhx/wDZVirv8Sa7/vyX/pDj/wCyrFU3
0PWdSnl4X0FzMkxAimFssUaU5cizLM+BKJ85/wDKH69/2zbz/kxJiqR+X4bubyhoa2dwLWQWNoS5
jElV9BPh4sRlo5NZ5on6hrv/AFdh/wBIqf8ANeNFbCY2yTxwIlzL68oryk4hOW/8orTCqtLZ6xOV
kstSW0i4gCI26y79zyZ1yqXNmOTrew16OZHn1ZZolYF4xaonIdxyEhpgSiNZnmttMnnt3McqAFXC
q1PiA+zIyL95xVh/+Idb/wCW5/8ApHtf+yrCh3+Idb/5bn/6R7X/ALKsVb/xDrf/AC3P/wBI9r/2
VYqyDRdUBtvW1PVIZXloVjcRQtHSoIYJK4NcCU0u2V7cOhDKxBBG4II6jJQ5sZcmN3vmC2sbl7WS
3nkaOlWjVSpqA21ZB45MljTVr5itry4S2jtrlWkNAzIvEe5pIdsbWk6hbhIHoW4gniu5NAdhjLkm
PNR/xE//AFaNS/5Er/1Vypm7/ET/APVo1L/kSv8A1VxVDeY5bGO6iF0l+zGOoNk/BKVP2h6ib4ql
SXmko6uItZJUggGUEbeI9fChN/8AGNp/yw3v/AR/9VsCVW281WlxOkBtbmHmaepKsaovuxEpxVOI
p4Jq+jIknHrwYNSvjTFUBqcvoLNPTl6UZehNAeIJpXtk48mJ5sU/xm3/ACyRf9JK/wDVPDxLSNtd
b1S+i9e00xZY6leQukpUfNMbRSdi41CG2ElnZi6mYr6kRmEfDYk/EVau+2CaYqf6S8x/9WVP+kxP
+qeQZJvEztGjSr6bsoLJXlxJG4r3pirB7zVtHS7nR9GsZHWRwztcRhmIY1YgxHc4UKP6Y0T/AKsl
h/0kx/8AVHFXfpjRP+rJYf8ASTH/ANUcVRtv5yitIVt7WwtYYkrxRLxAoqeRoPS8TilM/Mly955D
1e6dBEZ9KupOCsHADQSEUYAV2wKlOgahaab5P0Oe9k9KNrG0QNxZviMCGnwg+GWg0GFboj/FWg/8
tX/JOT/mjHiC0Uxs7y2v4Bc2j+pExIDUK7jY7MAcKFWfzJoumMtrfXPpTBQxX05G2PTdEYZVLmzH
J1t5s8v3c8drb3fOWZgiL6coqx6CrRgYEorXPq36KuPrkogg4jnIYxLxHJf2Cr139sVYTTyp/wBX
dP8AuHp/2TYUIqwufJlrM0lzexXiFSojksVUA1B5VS3B7YpTA6v+X4p+7td+n+ht/wBUMVTaz07y
5f2yXdpY2skMoJR/q6LUA06MgPbAqLukSO2VEUKikKqqKAACgAAyUObGXJI7nRdLu5muLm2WSV6c
mNamgCjofAZOgxtu20bS7OZbi2t1jlWtGFaiooepxoLaZ239+nz/AIYy5JjzTLKmbsVYp5s065vL
2GSG3eYLFxJS3jmAPJjTk8sdMKpF+gr/AP5Ypf8ApBh/7KcUO/QV/wD8sUv/AEgw/wDZTirv0Ff/
APLFL/0gw/8AZTirLfLVvDbwyImnSWEgWMSySKqeswDfEFV3pvXb3wJRl4F9RuVOPHevSmTjyYnm
gaaf/wAU/wDC5JCuiIi0jAVetFFB+GKou1dEVi7BQSOppkJpiiVkjfZGDU8CDkWS7FWFXeiaxJdT
SJcUR5GZR9ekWgJJHwiPb5YUKX6C1v8A5aP+5hJ/1TxV36C1v/lo/wC5hJ/1TxV36C1v/lo/7mEn
/VPFU28wRtD5B1eF39R49Juldi/qHl9Xk5DmeuBKC8ryxQ+U9EaZ1jU6faAFyAK+injlo5NZ5pl9
esv+WiL/AINf642rvr1l/wAtEX/Br/XG1TWK6tY4kWSaNDxBozAGh+ZyuXNmOSol5aSMESeNmOwU
OpJ/HAlQ1eKWfTZ4oXWKRgOLu7RqPiHV0+IYqxL9D6r/AMt9r/0n3OFDv0Pqv/Lfa/8ASfc4q79E
ar/y32v/AEn3OKp1osl/ZBba9ubF7ZQx5JcSSTVJqN5abYEpveENAGU1BIII6EZKHNjLkkN1pAup
2n+uXcPOnwQzFEFABstPbJ0xtR/QI/6uF/8A9JB/pjS2mtlB6YjtvUkailPUZqyHYivLxwS5JHNb
/htP+rnqX/SU39MrZpjY2YsYfQE81x8RbncOZH3ptyPbbFWN+brqWC9hWO6ltwYq8Y5Z4wfibekE
UgwqkH6Quf8Aq43H/STef9k2KHfpC5/6uNx/0k3n/ZNiqM0+LWNULrY3s8hiAL1vLlKVrT+8gXwx
VnNjDJb2cMMrtJIiAOzsXYt3q53O+BKhexJMXikHJHXiy+IIoRk48mJSj/DOh/8ALGn3t/zVhpbT
JUCqFUUCigHsMUIbUtHOsWywCVIvTkD1kiEwOzD7JZadcjJkELZeVtR012ex1KKBnFGKWabgf89c
ilN7C01W3kZr/UFvEK0VBAsVDXrVXauKpHc+SnuLiWf61Avquz0NorEciTu3qiuG1U/8Cv8A8tdv
/wBIa/8AVXG1d/gV/wDlrt/+kNf+quNq7/Ar/wDLXb/9Ia/9VcbVV1jSho/kPX7UOkhawvZGaOMR
AkwOPshm7DAqF8uWlteeUdDiuolmQWFowVxUVECCv45aOTWeaN/QOjf8scX/AAONBbLv0Do3/LHF
/wADjQWymv6G0m7RJbmzhmcKF5OgJoOg3yuXNmOS+HQ9HtpVngsoY5UNVdUAIPscCVPzFT9DXVSo
HFd3EZH2l6+tRPvxV5/RP57f/gdO/wCa8KHUT+e3/wCB07/mvFXcY/57f/gdO/5rxVOtN0Gx1BYu
GpWhmccmtlt7R3AHUH064pZfdIkdsscYColFVRsAAKADDDmxlySC6t9akuHe0vIoYTTijRciNhXe
vjk92Oyl9U8x/wDVwh/5E/247p2TPTY71EVLmZZLj4qSKvFdwePw+2A8lHNMLCLUIo2XUbhLmQtV
Wjj9MBadKcmytmi8VY55j1bUbC6ijs2dUaPk3CBZRWpHVpo6fdiqUf4k13/fkv8A0hx/9lWFCpFr
vmOavo/WJOPXhZI1K+NLnFV/6W81f77uv+kBf+ynFKa6Be6xczypqSTKgSqGW2EArXxEslcCojVo
ZnEzxuIf3ZpKxACGh+I18MsiRTCQ3YpGl4siM/mK2ZFYFl9SPcA7j7WN+a15J3+kdN/5b7b/AJHx
/wDNeS4gx4SiYru0SD6y13AsLtxWUyoELCuwblSuAyCQCi7crdR+taypPGTTnG6utR7qTkeIMqKs
Lebw/HHiC0UEdU0tGKvf2qspoQZ4wQR2+3jYWmxq+k/9XC1/5Hx/8142tLv0xpH/AFcbX/kfH/zX
gtKKtbm2vFLWc8VwqGjGJ1cA+/EnBat39zb6fYXN9emltawyTTmnKkcal3+EVr8I6Y2rFPL99a6f
5Q0Oa7cxo1jaICFZtzAh6IGPbLAdmB5on/E2if8ALQf+RUv/AFTx4gtF3+JtE/5aD/yKl/6p48QW
im8uv6TpxW2vJmjlChioikfY9N0RhlcubMcnW/mbRbqZLeCdmklYKgMMq1J6btGBgSiNZFs2mTi7
laCAgc5EXmVHIdF4vX7sVYf6Xlj/AKutx/0if9muFDvS8sf9XW4/6RP+zXFVSFfK0U0cralNKqMG
Mb2nwsAa8Wpa9DirJtJuNBvXkk0mOMPDQOywGIgPWm7Rp/L2wJRl7/c/7IZKHNjLkw7VPMsmn38t
mscLCPju7sG+JVbcBD45IyQA7TfMd1qN2ltHDCQd3KyNUID8RFUGINqQyWEsJAUHJgDxBNATQ0Fc
MuSx5qP1zzP/ANW23/6Sf+veVM01tmneBGukEUxHxorcgD4BqCuKsb81X9ha3kKXdnaXTNFUNcsQ
wHJthSN9sKpH+mNF/wCrXpv/AAbf9UMUImz81Wmn8/qVnY2/qU5+nK68uNaVpB74qmun+dbGUuNR
kgtgAOBjZ5OR3rX90tMFJZBZ3ltf26Xdo4lhkrwcAgHiSp607jFVl56axSyTDlGqMXWnKqgbjj32
yQQWNfpXyp/yxf8ATp/zZirv0r5U/wCWL/p0/wCbMVVr1tGu9IhkUy2lqZTwENvU8gGrWMxvQe9M
BVDWQsi8dnZ6pqMXqNRVWD005N4/uABirI9P06eyd2lvp7wOKBZytF9xxVcCWKXFvoZnkL3d4G5t
UC0BANex+rnChM4tS8rRxpG1oZCihS7WTVYgUqf3XfAlf+lfKv8Ayxf9OTf9UsVVoPMOgWwK20Mk
IbciO1kUE+/GMYq35slSfyVrU8deEul3TryBBo1vIRUHcYqxmze1TyRoJu45JE+qWYAicRmv1cb1
JXLOjDq1pt5ZwXBlsLG6mlCkECUSUBpvx5nEFSn1jqM93KY5bKa1AUtzlAoTUDjseu+EFFJhLqlx
aFYYtOubpQoPqQhOO/b4nGVy5sxyU/09ef8AVmvfuj/6qYEoxNQnewa8NlOsimgtiF9U7gbfFT8c
VQf6evP+rNe/dH/1UxV36evP+rNe/dH/ANVMVd+nrz/qzXv3R/8ANeKu/T15/wBWa9+6P/qpiqZX
v9z/ALIZKHNjLkw7VNS1y3v5YrOKR4F48GW2eQGqqT8amh3yRJQAFlleeZb2UxAC3opblPbOimhA
oCT13xBK7MmtBP8AuwzL6/Ghanw8+PWnhXGXJRzR9mt2tui3zpJcCvNogVQ7mlAST0ytmr4qkOv6
jrFlcxx6dE8kbJyYpbPOOVSPtIy0+WKpV+nfNH/LPL/3D5v+qmFUyspPNV7AJxLBb1JHC4tpI327
8TJgVX9DzX/y12X/ACJf/mvFUzs1u1t0W+dJLgV5tECqHc0oCSemKr5nEUTy8Wk4KW4IKs1BWiju
TiqS/wCJx/1Z9V/6Rv8Am/Ch3+Jx/wBWfVf+kb/m/FXDzQB00fVf+kb/AJvxS3/ij/tT6r/0jf8A
N+BXf4o/7U+q/wDSN/zfiqTuuhSO0j+X9XLOSxPCYbnftcYVVLWXR7K4S6ttA1dJYzVWMcrUqKdG
nI74qmn+KP8AtT6r/wBI3/N+BXf4o/7U+q/9I3/N+KqXmS7+veR9cufQmtuWm3o9K4ThIKQyjdan
FWOW1xBb+R9Be4hiuFNpZgJMSFB+rjfYHfbLOjDqh7XzBbWTmS1s7SF2HEsjsCR1p/d+2C00mun+
bLSYuL947cjj6fAu/Kta1+DbthEkEMiluNbiKrY2UVxDxFHebga9xx4HIS5shyV9Pn1aV3Go2sds
oHwGOX1CT4EcVwJRN09ylu72kazTgfBG7cATXu1DTFUr+ueZ/wDq22//AEk/9e8Vd9c8z/8AVtt/
+kn/AK94qj9Pl1GVHOo26WzA/AI5PUBHiTxXFUXiqHvf7n/ZDJQ5sZcmPXWl3FzcPNHqFxbq1KRx
kcRQAbVHtk6Y2pro12rBjql0wBBoStD+GNJtOYVLyBQxUsCAw6ioO4xlyWPNR/QN5/1eb374/wDq
nlTNH2FnLZRtHLdS3hZuQebjUClKDiFxVj/mzUbmzvYY4bh4Q0XIhLiOEE8mFeLxSVwqkX6dv/8A
ltl/6Tof+ybFDX6dv/8Alul/6Tof+ybFW/07f/8ALbL/ANJ0P/ZNirNtL0+5tmFxPfXF16kdPSmK
Mqk8WqCqLuKUwJRV/T6jc1pT0ZK8iQPsnqRuMVeaf6P/AC2X/SXP/wA14UOrb/y2X/SXP/zXirv9
H/lsv+kuf/mvFXf6P/LZf9Jc/wDzXirq2/8ALZf9Jc//AFUxV3+j/wAtl/0lz/8ANeKurbfy2X/S
VP8A9VMVd/o/8tl/0lz/APNeKtH6v1C2X/SVP/1UxVlut2f1D8vtYtigjddLvC6Bi4DtBIWozEml
cCUm0+7vLLyVoMtlT1DZ2amqNJ8JtweifLLOjDqh/wBPa/4L/wBI8v8ATGymgrWuq+Yru4S3jMaM
9aNJBIqigLbkj2xsooMolj8yMIzp81okPBaiZXLcv2vs9sgebIcl9nH5nW5Q301m1uCfUWJXDkU/
Z5bdcCUXq09xa6dPPaUMyAFKo0m9QPsJ8RxViv8AiLzN/Kn/AEh3GFDX+IvM38qf9Idx/TFW/wDE
Xmb+VP8ApDuMVVrTzHrS3KG+jLWwJ9RYrScORQ0oSKdcUsluJBLapKoID8WAYUIBFdxhhzYy5MR1
TWtVtL+W3too2iTjxLQzOd1Vj8SGnU5IkoAW2OreYL+UwxR20ZVS9ZYp0FAQOpbrviCVoMltPX/d
8uHr8d6V4c+P30rjLko5qdPN/wDPpv8AwM//ADXlbNN4vU9NPW4+pxHPhXjypvxrvSuKsf8AMd9e
2t1EltbQzq0dS0ttLOQanYNFsPliqUfpjVf+WC1/6QLnCh36Y1X/AJYLX/pAucVThbHzCwDCHSNx
XeGX/mrAlOrEXwtwNRMJnqf95wwSnb7ZJxVu+r9SuKVr6T04qHP2T0Q0DfLFXnXG4/5ff+4TB/1W
wodxuP8Al9/7hMH/AFWxV3G4/wCX3/uEwf8AVbFXcbjb/ezf/tUwf9VsVdxuP+X3/uEwf9VsVdxu
P+X3/uEwf9VsVdxuP+X3/uEwf9VsVdxuP+X3/uEwf9VsVZNoGgnit9eyJdQzRnjbzWcULoxI+JuJ
begO3vgSjPOf/KH69/2zbz/kxJiqR+X4bqfyhoaWlybRxY2hLhFkqPQT4aPtlo5NZ5on9Ha3/wBX
c/8ASNFjRWwuSw1lXVn1YuoILL9XiFR3FRjRWwmstjq1wVks9Uazi4gCIQRybjqeTiuVy5sxydb6
drUcyST6w08asC8Rt4l5DuvJRUYEq+tTzW2l3E8EnoyIAVk+Db4gP93EJ9+KsN/xDrX/AFc/xsP+
qmFDv8Q61/1c/wAbD/qpirv8Q61/1c/xsP8AqpirMtJury5th9dt3gkQKpaQofVNN3AjJAqcCVe9
/uf9kMlDmxlyYXqw8wfpCX6ibgW/w8PTEZX7K1pyNeuSNoFKNpB5luJ1imuLm2Q1rKyRkCgr0DY7
rsy6FWaQKrcGYEBhvQkHfDLkseana6Tq8FxHLPrElxGhq0RhRQw8KjfKmacYqx/zCNeNzF+imuBF
6fx+iIiOVT19VgemKpbbxeb5ZkilnvIUdgGkZLchQe5AeuFCa/oXXf8Aq+y/8iI8CXfoXXf+r7L/
AMiI8VRmm6fqNpKz3movfIy0VHjVApr9qq4qi7uNpbWaJV5s8bKFJ4gkginIdMVYX/hjUf8Aq2Rf
9Jkv/NWFDv8ADGo/9WyL/pMl/wCasVd/hjUf+rZF/wBJkv8AzViqta+Vrl7iNbzT0jgJ/eOl3KzA
ew5Yqm/+DdC/33L/AMjpP+asFpd/g3Qv99y/8jpP+asbV3+DdC/33L/yOk/5qxtXf4N0L/fcv/I6
T/mrG1R2maNY6T6v1JXX1uPPm7P9nlSnIn+bFUJ5z/5Q/Xv+2bef8mJMVY1puoyaZ5L0KeLgS1na
J+85kUNup/3WrH9nLLoMK3Uv8W3fhbfdP/1Tx4l4U60TVW1SGRpOHqRNQiMOBxI+H+8Vd6g4QbQQ
v1LzJcaZcLaxiAqEVv3gn5b/APGKF1/HIHmzHJB/41vP5bX7rr/snwUlN/0q1z5dk1KeOCQ71Rlk
aI0cLuGj5/8AC4FY7+n7f/lg03/kTP8A9kuFDv0/b/8ALBpv/Imf/slxV36ft/8Alg03/kTP/wBk
uKsl0u91u89CeSC1WylFecbyc+NDSiPGvfxwJTG9/uf9kMlDmxlyYXq2l39zqEs0FzDHG3GivPKj
CiqN1QUHTJEIBQf6E1T/AJbLf/pKm/pjRTbKNEtzFaQ20sgdgHV3Ry27ciaO2/fE8kDmv/w/pn/L
ddf9Jb/81ZWzTSxtobS2WCCR5UUmjyOZG3Nd2OKpR5h03Ub25iks54okWPiwkuJoSTUn7MQocVQm
n+X5iX/St4QKD0/q15MTXevL1KYVR3+H9M/5brr/AKS3/wCasCqkGgWCypJHd3TtGQ4U3LsDQ13F
emKpzirTcuJ4/aptXxxVJYNO1+DmDfiUFQELdQQoWpDI/cb+Neviqrm31wMvG6RlUmvMLVl7fZhA
U/fT3xVEWFvewBze3H1h2puAAooT0UKKbUxVGYq7FXYq7FXYq7FUl85/8ofr3/bNvP8AkxJiqV+U
v+UV0T/tn2v/ACZjy0cms802wq7FUBqWg6jqFwtzbNAIyirSSS4Vqj2hkVcrPNmOSja+U7/6wn11
4Tb1/eCGa6D0p+zzlI64LSyazs4bC3W2t+XpqSRzYudzX7TEnAqvirsVdirsVQ97/c/7IZKHNjLk
xLUvLJ1C9kvBcJH6nH4WgDkcVC/aLivTJGKAWrLypaQM5vTHdggcQIvT4n/Yua4iK2nmnWNpa0tY
IgkLFqoK0PIUPXGXJRzVP8LeX/8Algi+4/1ytmj7SytbCEW9nEsMQJIRelT1xVKtd8uNrNxHOJ4o
vTThSSATE7k/aLrTriqXReRgsiNLcwSIrAsn1RV5AHcV9XauG1Tf/C3l/wD5YIvuP9cCoiy0bS9O
lM9jbJBIylCyVqVJBp+GKo7FVC+5fUrjhXl6T8aVrXiaU4/F92KvOqat/Pcf8Dff814UOpq389x/
wN9/zXirqat/Pcf8Dff814q6mrfz3H/A33/NeKupq389x/wN9/zXirqat/Pcf8Dff814q6mrfz3H
/A33/NeKupq389x/wN9/zXiqN0/Std1L1PRuDF6XGvrteR15V+zyffpiqZ6tp91p3kTX4ryX1pns
L1iweR1p6DgU9Us3bAlb5S/5RXRP+2fa/wDJmPLRyazzTbCrsVTO3/uE+WVS5sxyVcCXYq7FXYq7
FXYqh73+5/2QyUObGXJL8sYuxVWtv79Pn/DBLkmPNMsqZuxV2KuxV2KuxV2KuxV2KuxV2KuxV2Ku
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 000000000..cd87f71ec --- /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 000000000..9edccb47f --- /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 000000000..2c532cbf6 --- /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 000000000..8e5b21511 --- /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 000000000..987169eee --- /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 000000000..f28566442 --- /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 000000000..ac152793c --- /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 000000000..9ae7e23bb --- /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 000000000..5d552421a --- /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 000000000..d870f896c --- /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 000000000..211a111cb --- /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 000000000..890f56217 --- /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 000000000..58aadb492 --- /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 000000000..5270151eb --- /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 000000000..ac1c5f37b --- /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 000000000..60675454f --- /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 000000000..db063f366 --- /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 000000000..086e18eed --- /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 000000000..a736e5bb9 --- /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 000000000..6ff43f87e --- /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 000000000..c4c5dcf07 --- /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 OUStringLiteral DATA_DIRECTORY = u"/xmlsecurity/qa/unit/pdfsigning/data/"; +} + +/// 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 000000000..d63e4b6b7 --- /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 000000000..0190abb00 --- /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 000000000..f4b4198f9 --- /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 000000000..558bdee47 --- /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 000000000..4136b32e5 --- /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 000000000..8dedb6998 --- /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 000000000..86d0eda49 --- /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 000000000..75c39d5d8 --- /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 000000000..f3f056f2b --- /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 000000000..032ddbf7a --- /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 000000000..252ea26b0 --- /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 000000000..9490a0ce5 --- /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 000000000..e738c2f6d --- /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 000000000..4f96d4bd8 --- /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 000000000..8c6019d0a --- /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 000000000..4a506c1e1 --- /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 000000000..a02af3016 --- /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 000000000..f2b1a7109 --- /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 000000000..aba69508e --- /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 000000000..22cf7683a --- /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 000000000..5d552421a --- /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 000000000..4f96d4bd8 --- /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 000000000..3e90f4514 --- /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 000000000..3d6ca4685 --- /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 000000000..e1dae6698 --- /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 000000000..d3a3e4671 --- /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 000000000..5e519dd8b --- /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 000000000..95162a627 --- /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 000000000..ecff48709 --- /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 000000000..58d1b2c77 --- /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 000000000..f0356513c --- /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 000000000..e1b36d544 --- /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 000000000..c3c5d254b --- /dev/null +++ b/xmlsecurity/qa/unit/signing/signing.cxx @@ -0,0 +1,1696 @@ +/* -*- 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/bootstrapfixture.hxx> +#include <unotest/macros_test.hxx> +#include <test/xmltesttools.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/Desktop.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/mediadescriptor.hxx> +#include <unotools/tempfile.hxx> +#include <unotools/ucbstreamhelper.hxx> +#include <comphelper/storagehelper.hxx> +#include <sfx2/sfxbasemodel.hxx> +#include <sfx2/objsh.hxx> +#include <osl/file.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; + +namespace +{ +constexpr OUStringLiteral DATA_DIRECTORY = u"/xmlsecurity/qa/unit/signing/data/"; +} + +/// Testsuite for the document signing feature. +class SigningTest : public test::BootstrapFixture, public unotest::MacrosTest, public XmlTestTools +{ +protected: + uno::Reference<lang::XComponent> mxComponent; + 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: + void createDoc(const OUString& rURL); + void createCalc(const OUString& rURL); + 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() {} + +void SigningTest::setUp() +{ + test::BootstrapFixture::setUp(); + MacrosTest::setUpNssGpg(m_directories, "xmlsecurity_signing"); + + // Initialize crypto after setting up the environment variables. + mxDesktop.set(frame::Desktop::create(mxComponentContext)); + 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() +{ + if (mxComponent.is()) + mxComponent->dispose(); + + MacrosTest::tearDownNssGpg(); + test::BootstrapFixture::tearDown(); +} + +void SigningTest::createDoc(const OUString& rURL) +{ + if (mxComponent.is()) + mxComponent->dispose(); + if (rURL.isEmpty()) + mxComponent = loadFromDesktop("private:factory/swriter", "com.sun.star.text.TextDocument"); + else + mxComponent = loadFromDesktop(rURL, "com.sun.star.text.TextDocument"); +} + +void SigningTest::createCalc(const OUString& rURL) +{ + if (mxComponent.is()) + mxComponent->dispose(); + if (rURL.isEmpty()) + mxComponent + = loadFromDesktop("private:factory/swriter", "com.sun.star.sheet.SpreadsheetDocument"); + else + mxComponent = loadFromDesktop(rURL, "com.sun.star.sheet.SpreadsheetDocument"); +} + +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)) + 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. + createDoc(""); + + utl::TempFile aTempFile; + aTempFile.EnableKillingFile(); + uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY); + utl::MediaDescriptor aMediaDescriptor; + aMediaDescriptor["FilterName"] <<= OUString("writer8"); + xStorable->storeAsURL(aTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList()); + + DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content); + CPPUNIT_ASSERT(aManager.init()); + uno::Reference<embed::XStorage> xStorage + = comphelper::OStorageHelper::GetStorageOfFormatFromURL( + ZIP_STORAGE_FORMAT_STRING, aTempFile.GetURL(), embed::ElementModes::READWRITE); + CPPUNIT_ASSERT(xStorage.is()); + aManager.setStore(xStorage); + aManager.getSignatureHelper().SetStorage(xStorage, "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. + createDoc(""); + + utl::TempFile aTempFile; + aTempFile.EnableKillingFile(); + uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY); + utl::MediaDescriptor aMediaDescriptor; + aMediaDescriptor["FilterName"] <<= OUString("writer8"); + xStorable->storeAsURL(aTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList()); + + DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content); + CPPUNIT_ASSERT(aManager.init()); + uno::Reference<embed::XStorage> xStorage + = comphelper::OStorageHelper::GetStorageOfFormatFromURL( + ZIP_STORAGE_FORMAT_STRING, aTempFile.GetURL(), embed::ElementModes::READWRITE); + CPPUNIT_ASSERT(xStorage.is()); + aManager.setStore(xStorage); + aManager.getSignatureHelper().SetStorage(xStorage, "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. + createDoc(""); + + utl::TempFile aTempFile; + aTempFile.EnableKillingFile(); + uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY); + utl::MediaDescriptor aMediaDescriptor; + aMediaDescriptor["FilterName"] <<= OUString("MS Word 2007 XML"); + xStorable->storeAsURL(aTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList()); + + DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content); + CPPUNIT_ASSERT(aManager.init()); + uno::Reference<embed::XStorage> xStorage + = comphelper::OStorageHelper::GetStorageOfFormatFromURL( + ZIP_STORAGE_FORMAT_STRING, aTempFile.GetURL(), embed::ElementModes::READWRITE); + CPPUNIT_ASSERT(xStorage.is()); + aManager.setStore(xStorage); + aManager.getSignatureHelper().SetStorage(xStorage, "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. + createDoc(""); + + utl::TempFile aTempFile; + aTempFile.EnableKillingFile(); + uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY); + utl::MediaDescriptor aMediaDescriptor; + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + xStorable->storeToURL(aTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList()); + + DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content); + CPPUNIT_ASSERT(aManager.init()); + std::unique_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream( + aTempFile.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. + createDoc(""); + + utl::TempFile aTempFile; + aTempFile.EnableKillingFile(); + uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY); + utl::MediaDescriptor aMediaDescriptor; + aMediaDescriptor["FilterName"] <<= OUString("MS Word 2007 XML"); + xStorable->storeAsURL(aTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList()); + + DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content); + CPPUNIT_ASSERT(aManager.init()); + uno::Reference<embed::XStorage> xStorage + = comphelper::OStorageHelper::GetStorageOfFormatFromURL( + ZIP_STORAGE_FORMAT_STRING, aTempFile.GetURL(), embed::ElementModes::READWRITE); + CPPUNIT_ASSERT(xStorage.is()); + aManager.setStore(xStorage); + aManager.getSignatureHelper().SetStorage(xStorage, "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. + utl::TempFile aTempFile; + aTempFile.EnableKillingFile(); + OUString aURL = aTempFile.GetURL(); + CPPUNIT_ASSERT_EQUAL( + osl::File::RC::E_None, + osl::File::copy(m_directories.getURLFromSrc(DATA_DIRECTORY) + "partial.docx", aURL)); + // 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, aURL, + embed::ElementModes::READWRITE); + CPPUNIT_ASSERT(xStorage.is()); + aManager.setStore(xStorage); + aManager.getSignatureHelper().SetStorage(xStorage, "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()); + utl::TempFile aTempFile; + aTempFile.EnableKillingFile(); + OUString aURL = aTempFile.GetURL(); + CPPUNIT_ASSERT_EQUAL( + osl::File::RC::E_None, + osl::File::copy(m_directories.getURLFromSrc(DATA_DIRECTORY) + "multi.docx", aURL)); + uno::Reference<embed::XStorage> xStorage + = comphelper::OStorageHelper::GetStorageOfFormatFromURL(ZIP_STORAGE_FORMAT_STRING, aURL, + embed::ElementModes::READWRITE); + CPPUNIT_ASSERT(xStorage.is()); + aManager.setStore(xStorage); + aManager.getSignatureHelper().SetStorage(xStorage, "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. + utl::TempFile aTempFile; + aTempFile.EnableKillingFile(); + OUString aURL = aTempFile.GetURL(); + CPPUNIT_ASSERT_EQUAL( + osl::File::RC::E_None, + osl::File::copy(m_directories.getURLFromSrc(DATA_DIRECTORY) + "partial.docx", aURL)); + // 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, aURL, + embed::ElementModes::READWRITE); + CPPUNIT_ASSERT(xStorage.is()); + aManager.setStore(xStorage); + aManager.getSignatureHelper().SetStorage(xStorage, "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) +{ + createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "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) +{ + createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "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) +{ + createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "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) +{ + createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + + "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) +{ + createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + + "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) +{ + createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + + "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) +{ + createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + + "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) +{ + createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + + "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) +{ + createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + + "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 const msDN("CN=\"\"\"ABC\"\".\", O=\"Enterprise \"\"ABC\"\"\""); + OUString const nssDN("CN=\\\"ABC\\\".,O=Enterprise \\\"ABC\\\""); + // 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) +{ + createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "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) +{ + createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "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) +{ + createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "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) +{ + createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "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) +{ + createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + + "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) +{ + createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "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())); +} + +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. + utl::TempFile aTempFile; + aTempFile.EnableKillingFile(); + OUString aSourceURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "add-visible-signature.pdf"; + OUString aURL = aTempFile.GetURL(); + osl::File::RC eRet = osl::File::copy(aSourceURL, aURL); + CPPUNIT_ASSERT_EQUAL(osl::File::RC::E_None, eRet); + + // Open it. + uno::Sequence<beans::PropertyValue> aArgs = { comphelper::makePropertyValue("ReadOnly", true) }; + mxComponent = loadFromDesktop(aURL, "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]); + + // When: do the actual signing. + pObjectShell->SignDocumentContentUsingCertificate(aCertificates[0]); + + // Then: count the # of shapes on the signature widget/annotation. + SvFileStream aFile(aTempFile.GetURL(), StreamMode::READ); + SvMemoryStream aMemory; + aMemory.WriteStream(aFile); + std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument + = pPDFium->openDocument(aMemory.GetData(), aMemory.GetSize(), OString()); + 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()); +} + +#endif + +CPPUNIT_TEST_FIXTURE(SigningTest, test96097Calc) +{ + createCalc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "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 + utl::TempFile aTempFileSaveCopy; + aTempFileSaveCopy.EnableKillingFile(); + uno::Sequence<beans::PropertyValue> descSaveACopy(comphelper::InitPropertySequence( + { { "SaveACopy", uno::Any(true) }, { "FilterName", uno::Any(OUString("calc8")) } })); + xDocStorable->storeToURL(aTempFileSaveCopy.GetURL(), descSaveACopy); + + try + { + // Save As + utl::TempFile aTempFileSaveAs; + aTempFileSaveAs.EnableKillingFile(); + uno::Sequence<beans::PropertyValue> descSaveAs( + comphelper::InitPropertySequence({ { "FilterName", uno::Any(OUString("calc8")) } })); + xDocStorable->storeAsURL(aTempFileSaveAs.GetURL(), descSaveAs); + } + catch (...) + { + CPPUNIT_FAIL("Fail to save as the document"); + } +} + +CPPUNIT_TEST_FIXTURE(SigningTest, test96097Doc) +{ + createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "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 + utl::TempFile aTempFileSaveCopy; + aTempFileSaveCopy.EnableKillingFile(); + uno::Sequence<beans::PropertyValue> descSaveACopy(comphelper::InitPropertySequence( + { { "SaveACopy", uno::Any(true) }, { "FilterName", uno::Any(OUString("writer8")) } })); + xDocStorable->storeToURL(aTempFileSaveCopy.GetURL(), descSaveACopy); + + try + { + // Save As + utl::TempFile aTempFileSaveAs; + aTempFileSaveAs.EnableKillingFile(); + uno::Sequence<beans::PropertyValue> descSaveAs( + comphelper::InitPropertySequence({ { "FilterName", uno::Any(OUString("writer8")) } })); + xDocStorable->storeAsURL(aTempFileSaveAs.GetURL(), descSaveAs); + } + catch (...) + { + CPPUNIT_FAIL("Fail to save as the document"); + } +} + +CPPUNIT_TEST_FIXTURE(SigningTest, testXAdESNotype) +{ + // Create a working copy. + utl::TempFile aTempFile; + aTempFile.EnableKillingFile(); + OUString aURL = aTempFile.GetURL(); + CPPUNIT_ASSERT_EQUAL( + osl::File::RC::E_None, + osl::File::copy(m_directories.getURLFromSrc(DATA_DIRECTORY) + "notype-xades.odt", aURL)); + + // Read existing signature. + DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content); + CPPUNIT_ASSERT(aManager.init()); + uno::Reference<embed::XStorage> xStorage + = comphelper::OStorageHelper::GetStorageOfFormatFromURL( + ZIP_STORAGE_FORMAT_STRING, aTempFile.GetURL(), embed::ElementModes::READWRITE); + CPPUNIT_ASSERT(xStorage.is()); + aManager.setStore(xStorage); + aManager.getSignatureHelper().SetStorage(xStorage, "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')]", + "Type"); + + // New signature always has the Type attribute. + assertXPath(pXmlDoc, + "/odfds:document-signatures/dsig:Signature[2]/dsig:SignedInfo/" + "dsig:Reference[starts-with(@URI, '#idSignedProperties')]", + "Type", "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. + createDoc(OUString()); + + utl::TempFile aTempFile; + aTempFile.EnableKillingFile(); + uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY); + utl::MediaDescriptor aMediaDescriptor; + aMediaDescriptor["FilterName"] <<= OUString("writer8"); + xStorable->storeAsURL(aTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList()); + + DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content); + CPPUNIT_ASSERT(aManager.init()); + uno::Reference<embed::XStorage> xStorage + = comphelper::OStorageHelper::GetStorageOfFormatFromURL( + ZIP_STORAGE_FORMAT_STRING, aTempFile.GetURL(), embed::ElementModes::READWRITE); + CPPUNIT_ASSERT(xStorage.is()); + aManager.setStore(xStorage); + aManager.getSignatureHelper().SetStorage(xStorage, "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", + "Algorithm", ALGO_XMLDSIGSHA256); + + // Assert that the digest of the signing certificate is included. + assertXPath(pXmlDoc, "//xd:CertDigest", 1); + + // Assert that the Type attribute is set on all URI's that start with #idSignedProperties + assertXPath(pXmlDoc, "//dsig:Reference[starts-with(@URI, '#idSignedProperties')]", "Type", + "http://uri.etsi.org/01903#SignedProperties"); +} + +CPPUNIT_TEST_FIXTURE(SigningTest, testSigningMultipleTimes_ODT) +{ + createDoc(""); + + utl::TempFile aTempFile; + aTempFile.EnableKillingFile(); + uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY); + utl::MediaDescriptor aMediaDescriptor; + aMediaDescriptor["FilterName"] <<= OUString("writer8"); + xStorable->storeAsURL(aTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList()); + + { + DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content); + CPPUNIT_ASSERT(aManager.init()); + uno::Reference<embed::XStorage> xStorage + = comphelper::OStorageHelper::GetStorageOfFormatFromURL( + ZIP_STORAGE_FORMAT_STRING, aTempFile.GetURL(), embed::ElementModes::READWRITE); + CPPUNIT_ASSERT(xStorage.is()); + aManager.setStore(xStorage); + aManager.getSignatureHelper().SetStorage(xStorage, "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(); + + createDoc(aTempFile.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) +{ + createDoc(""); + + utl::TempFile aTempFile; + aTempFile.EnableKillingFile(); + uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY); + utl::MediaDescriptor aMediaDescriptor; + aMediaDescriptor["FilterName"] <<= OUString("MS Word 2007 XML"); + xStorable->storeAsURL(aTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList()); + + { + DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content); + CPPUNIT_ASSERT(aManager.init()); + uno::Reference<embed::XStorage> xStorage + = comphelper::OStorageHelper::GetStorageOfFormatFromURL( + ZIP_STORAGE_FORMAT_STRING, aTempFile.GetURL(), embed::ElementModes::READWRITE); + CPPUNIT_ASSERT(xStorage.is()); + aManager.setStore(xStorage); + aManager.getSignatureHelper().SetStorage(xStorage, "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(); + + createDoc(aTempFile.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) +{ + createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "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, + m_directories.getURLFromSrc(DATA_DIRECTORY) + "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) +{ + createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "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) +{ + createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "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) +{ + createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "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) +{ + createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "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) +{ + createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "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 + createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "encryptedGPG.odt"); + SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + + // ODF1.3 flavour + createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "encryptedGPG_odf13.odt"); + pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + + // export and import again + utl::TempFile aTempFile; + { + uno::Sequence<beans::PropertyValue> props( + comphelper::InitPropertySequence({ { "FilterName", uno::Any(OUString("writer8")) } })); + uno::Reference<frame::XStorable> xDocStorable(mxComponent, uno::UNO_QUERY); + xDocStorable->storeToURL(aTempFile.GetURL(), props); + } + validate(aTempFile.GetFileName(), test::ODF); + + createDoc(aTempFile.GetURL()); + pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + + aTempFile.EnableKillingFile(); +} + +#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 aURL(m_directories.getURLFromSrc(DATA_DIRECTORY) + "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 + mxComponent->dispose(); + mxComponent = mxDesktop->loadComponentFromURL(aURL, "_default", 0, {}); + 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); + + // save as new ODT document + utl::TempFile aTempFileSaveAsODT; + aTempFileSaveAsODT.EnableKillingFile(); + try + { + uno::Reference<frame::XStorable> xDocStorable(mxComponent, uno::UNO_QUERY); + uno::Sequence<beans::PropertyValue> descSaveAs( + comphelper::InitPropertySequence({ { "FilterName", uno::Any(OUString("writer8")) } })); + xDocStorable->storeAsURL(aTempFileSaveAsODT.GetURL(), descSaveAs); + } + catch (...) + { + CPPUNIT_FAIL("Failed to save ODT document"); + } + + // save as new OTT template + utl::TempFile aTempFileSaveAsOTT; + aTempFileSaveAsOTT.EnableKillingFile(); + try + { + uno::Reference<frame::XStorable> xDocStorable(mxComponent, uno::UNO_QUERY); + uno::Sequence<beans::PropertyValue> descSaveAs(comphelper::InitPropertySequence( + { { "FilterName", uno::Any(OUString("writer8_template")) } })); + xDocStorable->storeAsURL(aTempFileSaveAsOTT.GetURL(), descSaveAs); + } + catch (...) + { + CPPUNIT_FAIL("Failed to save OTT template"); + } + + // load the saved OTT template as-is to validate signatures + mxComponent->dispose(); + mxComponent + = loadFromDesktop(aTempFileSaveAsOTT.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); + + // load saved ODT document + createDoc(aTempFileSaveAsODT.GetURL()); + + // the loaded document is a ODT with a macro signature + assertDocument(CPPUNIT_SOURCELINE(), "writer8", SignatureState::NOSIGNATURES, + SignatureState::OK, ODFVER_013_TEXT); + + // save as new OTT template + utl::TempFile aTempFileSaveAsODT_OTT; + aTempFileSaveAsODT_OTT.EnableKillingFile(); + try + { + uno::Reference<frame::XStorable> xDocStorable(mxComponent, uno::UNO_QUERY); + uno::Sequence<beans::PropertyValue> descSaveAs(comphelper::InitPropertySequence( + { { "FilterName", uno::Any(OUString("writer8_template")) } })); + xDocStorable->storeAsURL(aTempFileSaveAsODT_OTT.GetURL(), descSaveAs); + } + catch (...) + { + CPPUNIT_FAIL("Failed to save OTT template"); + } + + // load the template as-is to validate signatures + mxComponent->dispose(); + mxComponent + = loadFromDesktop(aTempFileSaveAsODT_OTT.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); +} + +/// Test if a macro signature from an OTT 1.0 is dropped for ODT 1.2 +CPPUNIT_TEST_FIXTURE(SigningTest, testDropMacroTemplateSignature) +{ + const OUString aURL(m_directories.getURLFromSrc(DATA_DIRECTORY) + "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 + mxComponent->dispose(); + mxComponent = mxDesktop->loadComponentFromURL(aURL, "_default", 0, {}); + 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 + utl::TempFile aTempFileSaveAs; + aTempFileSaveAs.EnableKillingFile(); + try + { + uno::Reference<frame::XStorable> xDocStorable(mxComponent, uno::UNO_QUERY); + uno::Sequence<beans::PropertyValue> descSaveAs( + comphelper::InitPropertySequence({ { "FilterName", uno::Any(OUString("writer8")) } })); + xDocStorable->storeAsURL(aTempFileSaveAs.GetURL(), descSaveAs); + } + catch (...) + { + CPPUNIT_FAIL("Failed to save ODT document"); + } + + // load saved document + createDoc(aTempFileSaveAs.GetURL()); + + // 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 + utl::TempFile aTempFileSaveAsOTT; + aTempFileSaveAsOTT.EnableKillingFile(); + try + { + uno::Reference<frame::XStorable> xDocStorable(mxComponent, uno::UNO_QUERY); + uno::Sequence<beans::PropertyValue> descSaveAs(comphelper::InitPropertySequence( + { { "FilterName", uno::Any(OUString("writer8_template")) } })); + xDocStorable->storeAsURL(aTempFileSaveAsOTT.GetURL(), descSaveAs); + } + catch (...) + { + CPPUNIT_FAIL("Failed to save OTT template"); + } + + // load the template as-is to validate signatures + mxComponent->dispose(); + mxComponent + = loadFromDesktop(aTempFileSaveAsOTT.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 aURL(m_directories.getURLFromSrc(DATA_DIRECTORY) + "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 + mxComponent->dispose(); + mxComponent = mxDesktop->loadComponentFromURL(aURL, "_default", 0, {}); + 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 + utl::TempFile aTempFileSaveAsODT; + aTempFileSaveAsODT.EnableKillingFile(); + try + { + uno::Reference<frame::XStorable> xDocStorable(mxComponent, uno::UNO_QUERY); + uno::Sequence<beans::PropertyValue> descSaveAs( + comphelper::InitPropertySequence({ { "FilterName", uno::Any(OUString("writer8")) } })); + xDocStorable->storeAsURL(aTempFileSaveAsODT.GetURL(), descSaveAs); + } + catch (...) + { + CPPUNIT_FAIL("Failed to save ODT document"); + } + + // save as new OTT template + utl::TempFile aTempFileSaveAsOTT; + aTempFileSaveAsOTT.EnableKillingFile(); + try + { + uno::Reference<frame::XStorable> xDocStorable(mxComponent, uno::UNO_QUERY); + uno::Sequence<beans::PropertyValue> descSaveAs(comphelper::InitPropertySequence( + { { "FilterName", uno::Any(OUString("writer8_template")) } })); + xDocStorable->storeAsURL(aTempFileSaveAsOTT.GetURL(), descSaveAs); + } + catch (...) + { + CPPUNIT_FAIL("Failed to save OTT template"); + } + + // load the saved OTT template as-is to validate signatures + mxComponent->dispose(); + mxComponent + = loadFromDesktop(aTempFileSaveAsOTT.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()); + + // load saved ODT document + createDoc(aTempFileSaveAsODT.GetURL()); + + // the loaded document is a ODT with a non-invalid macro signature + assertDocument(CPPUNIT_SOURCELINE(), "writer8", SignatureState::NOSIGNATURES, + SignatureState::NOTVALIDATED, OUString()); + + // save as new OTT template + utl::TempFile aTempFileSaveAsODT_OTT; + aTempFileSaveAsODT_OTT.EnableKillingFile(); + try + { + uno::Reference<frame::XStorable> xDocStorable(mxComponent, uno::UNO_QUERY); + uno::Sequence<beans::PropertyValue> descSaveAs(comphelper::InitPropertySequence( + { { "FilterName", uno::Any(OUString("writer8_template")) } })); + xDocStorable->storeAsURL(aTempFileSaveAsODT_OTT.GetURL(), descSaveAs); + } + catch (...) + { + CPPUNIT_FAIL("Failed to save OTT template"); + } + + // load the template as-is to validate signatures + mxComponent->dispose(); + mxComponent + = loadFromDesktop(aTempFileSaveAsODT_OTT.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()); +} + +#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 000000000..a436711ca --- /dev/null +++ b/xmlsecurity/qa/unit/signing/signing2.cxx @@ -0,0 +1,127 @@ +/* -*- 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/bootstrapfixture.hxx> +#include <unotest/macros_test.hxx> +#include <test/xmltesttools.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; + +namespace +{ +constexpr OUStringLiteral DATA_DIRECTORY = u"/xmlsecurity/qa/unit/signing/data/"; +} + +/// Testsuite for the document signing feature. +class SigningTest2 : public test::BootstrapFixture, public unotest::MacrosTest, public XmlTestTools +{ +protected: + uno::Reference<lang::XComponent> mxComponent; + uno::Reference<xml::crypto::XSEInitializer> mxSEInitializer; + uno::Reference<xml::crypto::XXMLSecurityContext> mxSecurityContext; + +public: + SigningTest2(); + virtual void setUp() override; + virtual void tearDown() override; + void registerNamespaces(xmlXPathContextPtr& pXmlXpathCtx) override; +}; + +SigningTest2::SigningTest2() {} + +void SigningTest2::setUp() +{ + test::BootstrapFixture::setUp(); + + // Initialize crypto after setting up the environment variables. + mxDesktop.set(frame::Desktop::create(mxComponentContext)); +} + +void SigningTest2::tearDown() +{ + if (mxComponent.is()) + { + css::uno::Reference<css::util::XCloseable> closer(mxComponent, css::uno::UNO_QUERY); + if (closer.is()) + { + closer->close(true); + } + mxComponent->dispose(); + } + + test::BootstrapFixture::tearDown(); +} + +/// Test if a macro signature from a ODF Database is preserved when saving +CPPUNIT_TEST_FIXTURE(SigningTest2, testPreserveMacroSignatureODB) +{ + const OUString aURL(m_directories.getURLFromSrc(DATA_DIRECTORY) + "odb_signed_macros.odb"); + + // load the file + mxComponent = loadFromDesktop(aURL, "com.sun.star.sdb.OfficeDatabaseDocument"); + + // save as ODB + utl::TempFile aTempFileSaveAsODB; + aTempFileSaveAsODB.EnableKillingFile(); + try + { + uno::Reference<frame::XStorable> xDocStorable(mxComponent, uno::UNO_QUERY); + uno::Sequence<beans::PropertyValue> descSaveAs(comphelper::InitPropertySequence( + { { "FilterName", uno::Any(OUString("StarOffice XML (Base)")) } })); + xDocStorable->storeAsURL(aTempFileSaveAsODB.GetURL(), descSaveAs); + } + catch (...) + { + CPPUNIT_FAIL("Failed to save ODB file"); + } + + // Parse the resulting XML. + uno::Reference<embed::XStorage> xStorage + = comphelper::OStorageHelper::GetStorageOfFormatFromURL( + ZIP_STORAGE_FORMAT_STRING, aTempFileSaveAsODB.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", "Id", + "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#")); +} + +/* 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 000000000..b5b16c3a7 --- /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 000000000..e230c7b2c --- /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 000000000..990fa5dea --- /dev/null +++ b/xmlsecurity/source/component/documentdigitalsignatures.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 <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(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 = 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 000000000..3ac503521 --- /dev/null +++ b/xmlsecurity/source/dialogs/certificatechooser.cxx @@ -0,0 +1,332 @@ +/* -*- 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/useroptions.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")) +{ + auto nControlWidth = m_xCertLB->get_approximate_digit_width() * 105; + m_xCertLB->set_size_request(nControlWidth, m_xCertLB->get_height_rows(12)); + + std::vector<int> aWidths + { + o3tl::narrowing<int>(30*nControlWidth/100), + o3tl::narrowing<int>(30*nControlWidth/100), + o3tl::narrowing<int>(10*nControlWidth/100), + o3tl::narrowing<int>(20*nControlWidth/100) + }; + m_xCertLB->set_column_fixed_widths(aWidths); + 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 ) ); + + 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() +{ + if ( mbInitialized ) + return; + + SvtUserOptions aUserOpts; + + 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; + + } + + for (auto &secContext : mxSecurityContexts) + { + if (!secContext.is()) + continue; + auto secEnvironment = secContext->getSecurityEnvironment(); + if (!secEnvironment.is()) + continue; + + uno::Sequence< uno::Reference< security::XCertificate > > xCerts; + try + { + if ( meAction == UserAction::Sign || meAction == UserAction::SelectSign) + xCerts = secEnvironment->getPersonalCertificates(); + else + xCerts = secEnvironment->getAllCertificates(); + } + catch (security::NoPasswordException&) + { + } + + 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 ); + } + } + + + // 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()); + + m_xCertLB->append(); + int nRow = m_xCertLB->n_children() - 1; + m_xCertLB->set_text(nRow, xmlsec::GetContentPart(xCert->getSubjectName(), xCert->getCertificateKind()), 0); + m_xCertLB->set_text(nRow, sIssuer, 1); + m_xCertLB->set_text(nRow, xmlsec::GetCertificateKind(xCert->getCertificateKind()), 2); + m_xCertLB->set_text(nRow, utl::GetDateString(xCert->getNotValidAfter()), 3); + m_xCertLB->set_text(nRow, UsageInClearText(xCert->getCertificateUsage()), 4); + OUString sId(weld::toId(userData.get())); + m_xCertLB->set_id(nRow, sId); + +#if HAVE_FEATURE_GPGME + // only GPG has preferred keys + if ( !sIssuer.isEmpty() && !msPreferredKey.isEmpty() ) { + if ( sIssuer == msPreferredKey ) + { + if ( meAction == UserAction::Sign || meAction == UserAction::SelectSign ) + m_xCertLB->select(nRow); + else if ( meAction == UserAction::Encrypt && + aUserOpts.GetEncryptToSelf() ) + mxEncryptToSelf = xCert; + } + } +#endif + } + } + + // enable/disable buttons + 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(); +} + +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 000000000..1801cdf53 --- /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 OString&, rPage, void) +{ + if (rPage == "path") + mxPathId->ActivatePage(); +} + +CertificateViewerTP::CertificateViewerTP(weld::Container* pParent, const OUString& rUIXMLDescription, + const OString& 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 000000000..1d40e7562 --- /dev/null +++ b/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx @@ -0,0 +1,801 @@ +/* -*- 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 <digitalsignaturesdialog.hxx> +#include <certificatechooser.hxx> +#include <certificateviewer.hxx> +#include <biginteger.hxx> +#include <sax/tools/converter.hxx> +#include <tools/diagnose_ex.h> + +#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 <vcl/weld.hxx> +#include <vcl/svapp.hxx> +#include <unotools/configitem.hxx> + +#ifdef _WIN32 +#include <o3tl/char16_t2wchar_t.hxx> +#include <prewin.h> +#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: + sal_Int16 m_nODF; + + virtual void ImplCommit() override; + + public: + virtual void Notify( const css::uno::Sequence< OUString >& aPropertyNames ) override; + SaveODFItem(); + //See group ODF in Common.xcs + bool isLessODF1_2() const + { + return m_nODF < 3; + } + }; + + void SaveODFItem::ImplCommit() {} + void SaveODFItem::Notify( const css::uno::Sequence< OUString >& ) {} + + SaveODFItem::SaveODFItem(): utl::ConfigItem("Office.Common/Save"), m_nODF(0) + { + 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 ); + + m_nODF = nTmp; + } +} + +DigitalSignaturesDialog::DigitalSignaturesDialog( + weld::Window* pParent, + const uno::Reference< uno::XComponentContext >& rxCtx, DocumentSignatureMode eMode, + bool bReadOnly, const OUString& sODFVersion, bool bHasDocumentSignature) + : GenericDialogController(pParent, "xmlsec/ui/digitalsignaturesdialog.ui", "DigitalSignaturesDialog") + , maSignatureManager(rxCtx, eMode) + , m_sODFVersion (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_xAdESCompliantCB(m_xBuilder->weld_check_button("adescompliant")) + , 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")) +{ + m_bAdESCompliant = !DocumentSignatureHelper::isODFPre_1_2(m_sODFVersion); + + 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_xAdESCompliantCB->connect_toggled( LINK( this, DigitalSignaturesDialog, AdESCompliantCheckBoxHdl ) ); + m_xAdESCompliantCB->set_active(m_bAdESCompliant); + + 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(); + } +} + +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; + m_xAdESCompliantCB->set_active(m_bAdESCompliant); + return; + } + + 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 + bool ret = true; + + 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 ret; + + if (!maSignatureManager.getStore().is()) + // It's always possible to append a PDF signature. + return ret; + + OSL_ASSERT(maSignatureManager.getStore().is()); + bool bDoc1_1 = DocumentSignatureHelper::isODFPre_1_2(m_sODFVersion); + SaveODFItem item; + bool bSave1_1 = item.isLessODF1_2(); + + // 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 ( (!bSave1_1 && bDoc1_1) || (bSave1_1 && 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(); + ret = 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 + && ret) + { + 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) + ret = false; + else + m_bWarningShowSignMacro = true; + + } + } + return ret; +} + +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, AdESCompliantCheckBoxHdl, weld::Toggleable&, void) +{ + m_bAdESCompliant = m_xAdESCompliantCB->get_active(); +} + +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(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) +{ +#ifdef _WIN32 + // FIXME: call GpgME::dirInfo("bindir") somewhere in + // SecurityEnvironmentGpg or whatnot + // FIXME: perhaps poke GpgME for uiserver, and hope it returns something useful? + static const 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", + }; + static const OUString aPath = [] { + OUString sRet; + PWSTR sPath = nullptr; + HRESULT hr + = SHGetKnownFolderPath(FOLDERID_ProgramFilesX86, KF_FLAG_DEFAULT, nullptr, &sPath); + if (SUCCEEDED(hr)) + { + sRet = o3tl::toU(sPath); + CoTaskMemFree(sPath); + } + return sRet; + }(); + if (aPath.isEmpty()) + return; +#else + static const std::u16string_view aGUIServers[] = { u"kleopatra", u"seahorse", u"gpa", u"kgpg" }; + const char* cPath = getenv("PATH"); + if (!cPath) + return; + OUString aPath(cPath, strlen(cPath), osl_getThreadTextEncoding()); +#endif + + OUString sFoundGUIServer, sExecutable; + + for ( auto const &rServer : aGUIServers ) + { + osl::FileBase::RC searchError = osl::File::searchFileURL(OUString(rServer), aPath, sFoundGUIServer ); + if (searchError == osl::FileBase::E_None) + { + osl::File::getSystemPathFromFileURL( sFoundGUIServer, sExecutable ); + break; + } + + } + + 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 ); + } + else + { + std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Info, VclButtonsType::Ok, + XsResId(STR_XMLSECDLG_NO_CERT_MANAGER))); + 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) +{ + if (xCert->getCertificateKind() == CertificateKind_OPENPGP) + return maSignatureManager.getGpgSecurityEnvironment(); + else if (xCert->getCertificateKind() == CertificateKind_X509) + return maSignatureManager.getSecurityEnvironment(); + + 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 000000000..bf82606f4 --- /dev/null +++ b/xmlsecurity/source/dialogs/macrosecurity.cxx @@ -0,0 +1,446 @@ +/* -*- 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 <tools/diagnose_ex.h> +#include <tools/urlobj.hxx> +#include <unotools/datetime.hxx> + +#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, + const css::uno::Reference<css::xml::crypto::XSecurityEnvironment>& rxSecurityEnvironment) + : GenericDialogController(pParent, "xmlsec/ui/macrosecuritydialog.ui", "MacroSecurityDialog") + , m_xSecurityEnvironment(rxSecurityEnvironment) + , 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 OString&, rPage, void) +{ + if (rPage == "SecurityLevelPage") + m_xLevelTP->ActivatePage(); + else if (rPage == "SecurityTrustPage") + m_xTrustSrcTP->ActivatePage(); +} + +MacroSecurityTP::MacroSecurityTP(weld::Container* pParent, const OUString& rUIXMLDescription, + const OString& 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 000000000..cc6c37c18 --- /dev/null +++ b/xmlsecurity/source/framework/buffernode.cxx @@ -0,0 +1,886 @@ +/* -*- 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> + +BufferNode::BufferNode( const css::uno::Reference< css::xml::wrapper::XXMLElementWrapper >& xXMLElement ) + :m_pParent(nullptr), + m_pBlocker(nullptr), + m_bAllReceived(false), + m_xXMLElement(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 000000000..0202195de --- /dev/null +++ b/xmlsecurity/source/framework/buffernode.hxx @@ -0,0 +1,119 @@ +/* -*- 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( + const 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 000000000..7801d6328 --- /dev/null +++ b/xmlsecurity/source/framework/elementcollector.cxx @@ -0,0 +1,137 @@ +/* -*- 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> + +ElementCollector::ElementCollector( + sal_Int32 nBufferId, + css::xml::crypto::sax::ElementMarkPriority nPriority, + bool bToModify, + const 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(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 000000000..0f797572a --- /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, + const 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 000000000..71444d7cd --- /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 000000000..94ca71fdf --- /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 000000000..b5a7f0272 --- /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 000000000..e276163d4 --- /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 000000000..4371b7ae6 --- /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 000000000..0390ea7e6 --- /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 000000000..44e9e4c0a --- /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 000000000..203f0fea2 --- /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 000000000..a0a08fc80 --- /dev/null +++ b/xmlsecurity/source/gpg/CertificateImpl.cxx @@ -0,0 +1,261 @@ +/* -*- 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; +} + +/* XUnoTunnel */ +sal_Int64 SAL_CALL CertificateImpl::getSomething(const Sequence< sal_Int8 >& aIdentifier) +{ + return comphelper::getSomethingImpl(aIdentifier, this); +} + +/* XUnoTunnel extension */ + +const Sequence< sal_Int8>& CertificateImpl::getUnoTunnelId() { + static const comphelper::UnoIdInit theCertificateImplUnoTunnelId; + return theCertificateImplUnoTunnelId.getSeq(); +} + +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 000000000..b6c50cb2e --- /dev/null +++ b/xmlsecurity/source/gpg/CertificateImpl.hxx @@ -0,0 +1,100 @@ +/* -*- 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/lang/XUnoTunnel.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::XUnoTunnel, + 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; + + //Methods from XUnoTunnel + virtual sal_Int64 SAL_CALL getSomething(const css::uno::Sequence< sal_Int8 >& aIdentifier) override; + + static const css::uno::Sequence< sal_Int8 >& getUnoTunnelId(); + + /// @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 000000000..291db0ba6 --- /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 000000000..2c0ffcdc9 --- /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 000000000..4864191bb --- /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 000000000..2d48daf34 --- /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 000000000..5cfe325aa --- /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 000000000..da2310765 --- /dev/null +++ b/xmlsecurity/source/gpg/SecurityEnvironment.cxx @@ -0,0 +1,232 @@ +/* -*- 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() +{ +} + +/* XUnoTunnel */ +sal_Int64 SAL_CALL SecurityEnvironmentGpg::getSomething( const Sequence< sal_Int8 >& aIdentifier ) +{ + return comphelper::getSomethingImpl(aIdentifier, this); +} + +/* XUnoTunnel extension */ + +namespace +{ +} + +const Sequence< sal_Int8>& SecurityEnvironmentGpg::getUnoTunnelId() { + static const comphelper::UnoIdInit theSecurityEnvironmentUnoTunnelId; + return theSecurityEnvironmentUnoTunnelId.getSeq(); +} + +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()); + if(xmlSecBase64Decode(strKeyId, const_cast<xmlSecByte*>(strKeyId), xmlStrlen(strKeyId)) < 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 (comphelper::getFromUnoTunnel<CertificateImpl>(aCert) == 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 000000000..262578682 --- /dev/null +++ b/xmlsecurity/source/gpg/SecurityEnvironment.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/. + */ + +#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> +#include <com/sun/star/lang/XUnoTunnel.hpp> + +namespace com::sun::star::security { class XCertificate; } +namespace GpgME { class Context; } + +class SecurityEnvironmentGpg : public cppu::WeakImplHelper< css::xml::crypto::XSecurityEnvironment, + css::lang::XUnoTunnel > +{ + 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; + + //Methods from XUnoTunnel + virtual sal_Int64 SAL_CALL getSomething( const css::uno::Sequence< sal_Int8 >& aIdentifier ) override; + + static const css::uno::Sequence< sal_Int8 >& getUnoTunnelId() ; + + 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 000000000..65083ff68 --- /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 000000000..4ff47ccc4 --- /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 000000000..1fb407113 --- /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 000000000..e3dea7310 --- /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 000000000..3b4e138ae --- /dev/null +++ b/xmlsecurity/source/gpg/xmlsignature_gpgimpl.cxx @@ -0,0 +1,527 @@ +/* -*- 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 <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); + if(xmlSecBase64Decode(pKey, reinterpret_cast<xmlSecByte*>(pKey), xmlStrlen(pKey)) < 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); + int nSigSize = xmlSecBase64Decode(pSignatureValue, reinterpret_cast<xmlSecByte*>(pSignatureValue), xmlStrlen(pSignatureValue)); + if( nSigSize < 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); + int nKeyLen = xmlSecBase64Decode(pKeyPacket, reinterpret_cast<xmlSecByte*>(pKeyPacket), xmlStrlen(pKeyPacket)); + if( nKeyLen < 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 000000000..f6c36d2c8 --- /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 000000000..af3d51154 --- /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/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 <tools/diagnose_ex.h> +#include <xmloff/attrlist.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 +{ +OUString getElement(OUString const & version, ::sal_Int32 * index) +{ + while (*index < version.getLength() && version[*index] == '0') { + ++*index; + } + return version.getToken(0, '.', *index); +} + + +// Return 1 if version1 is greater than version 2, 0 if they are equal +//and -1 if version1 is less version 2 +int compareVersions( + OUString const & version1, OUString const & version2) +{ + for (::sal_Int32 i1 = 0, i2 = 0; i1 >= 0 || i2 >= 0;) { + OUString e1(getElement(version1, &i1)); + OUString e2(getElement(version2, &i2)); + if (e1.getLength() < e2.getLength()) { + return -1; + } else if (e1.getLength() > e2.getLength()) { + return 1; + } else if (e1 < e2) { + return -1; + } else if (e1 > e2) { + return 1; + } + } + return 0; +} +} + +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(const OUString & sVersion) +{ + //The property version exists only if the document is at least version 1.2 + //That is, if the document has version 1.1 and sVersion is empty. + //The constant is defined in comphelper/documentconstants.hxx + 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( + const OUString & sODFVersion, const SignatureInformation & sigInfo) +{ + OSL_ASSERT(!sODFVersion.isEmpty()); + 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, OUStringConcatenation(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, OUStringConcatenation(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, OUStringConcatenation(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, OUStringConcatenation(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, OUStringConcatenation(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, OUStringConcatenation(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 == OUStringConcatenation("/" + 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(OUStringConcatenation("." + 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, + const OUString& 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<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); + 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 SvXMLAttributeList())); + xDocumentHandler->startElement("xd:CertDigest", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + DocumentSignatureHelper::writeDigestMethod(xDocumentHandler); + xDocumentHandler->startElement("DigestValue", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + 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 SvXMLAttributeList())); + xDocumentHandler->startElement("X509IssuerName", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + xDocumentHandler->characters(rCertInfo.X509IssuerName); + xDocumentHandler->endElement("X509IssuerName"); + xDocumentHandler->startElement("X509SerialNumber", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + 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<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); + 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 SvXMLAttributeList())); + xDocumentHandler->startElement("xd:SigningTime", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + xDocumentHandler->characters(sDate); + xDocumentHandler->endElement("xd:SigningTime"); + xDocumentHandler->startElement("xd:SigningCertificate", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + 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 SvXMLAttributeList())); + xDocumentHandler->startElement("xd:SignaturePolicyImplied", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + xDocumentHandler->endElement("xd:SignaturePolicyImplied"); + xDocumentHandler->endElement("xd:SignaturePolicyIdentifier"); + + if (bWriteSignatureLineData && !signatureInfo.ouSignatureLineId.isEmpty() + && signatureInfo.aValidSignatureImage.is() && signatureInfo.aInvalidSignatureImage.is()) + { + rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); + 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 SvXMLAttributeList())); + xDocumentHandler->characters(signatureInfo.ouSignatureLineId); + xDocumentHandler->endElement("loext:SignatureLineId"); + } + + { + // Write SignatureLineValidImage element + xDocumentHandler->startElement( + "loext:SignatureLineValidImage", + Reference<XAttributeList>(new SvXMLAttributeList())); + + 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 SvXMLAttributeList())); + 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 000000000..83606dc96 --- /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/TempFile.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 const OUStringLiteral sPropFullPath(u"FullPath"); + static const OUStringLiteral sPropMediaType(u"MediaType"); + static const 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.set(io::TempFile::create(mxContext), uno::UNO_QUERY_THROW); + 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 000000000..2294af680 --- /dev/null +++ b/xmlsecurity/source/helper/ooxmlsecexporter.cxx @@ -0,0 +1,558 @@ +/* -*- 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/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 <xmloff/attrlist.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 SvXMLAttributeList())); + + writeCanonicalizationMethod(); + writeSignatureMethod(); + writeSignedInfoReferences(); + + m_xDocumentHandler->endElement("SignedInfo"); +} + +void OOXMLSecExporter::Impl::writeCanonicalizationMethod() +{ + rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); + 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<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); + 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<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); + + 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<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); + 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 SvXMLAttributeList())); + writeCanonicalizationTransform(); + m_xDocumentHandler->endElement("Transforms"); + } + + DocumentSignatureHelper::writeDigestMethod(m_xDocumentHandler); + m_xDocumentHandler->startElement( + "DigestValue", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + 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 SvXMLAttributeList())); + m_xDocumentHandler->characters(m_rInformation.ouSignatureValue); + m_xDocumentHandler->endElement("SignatureValue"); +} + +void OOXMLSecExporter::Impl::writeKeyInfo() +{ + m_xDocumentHandler->startElement( + "KeyInfo", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + assert(m_rInformation.GetSigningCertificate()); + for (auto const& rData : m_rInformation.X509Datas) + { + m_xDocumentHandler->startElement( + "X509Data", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + for (auto const& it : rData) + { + m_xDocumentHandler->startElement( + "X509Certificate", + uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + m_xDocumentHandler->characters(it.X509Certificate); + m_xDocumentHandler->endElement("X509Certificate"); + } + m_xDocumentHandler->endElement("X509Data"); + } + m_xDocumentHandler->endElement("KeyInfo"); +} + +void OOXMLSecExporter::Impl::writePackageObject() +{ + rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); + 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 SvXMLAttributeList())); + 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<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); + 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<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); + 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 SvXMLAttributeList())); + { + rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); + 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<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); + 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 SvXMLAttributeList())); + m_xDocumentHandler->characters("YYYY-MM-DDThh:mm:ssTZD"); + m_xDocumentHandler->endElement("mdssi:Format"); + + m_xDocumentHandler->startElement( + "mdssi:Value", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + 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<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); + 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 SvXMLAttributeList())); + + writeRelationshipTransform(aURI); + writeCanonicalizationTransform(); + + m_xDocumentHandler->endElement("Transforms"); + } + + DocumentSignatureHelper::writeDigestMethod(m_xDocumentHandler); + m_xDocumentHandler->startElement( + "DigestValue", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + m_xDocumentHandler->characters(rReference.ouDigestValue); + m_xDocumentHandler->endElement("DigestValue"); + m_xDocumentHandler->endElement("Reference"); +} + +void OOXMLSecExporter::Impl::writeOfficeObject() +{ + { + rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); + 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 SvXMLAttributeList())); + { + rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); + 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<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); + 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 SvXMLAttributeList())); + m_xDocumentHandler->characters(m_rInformation.ouSignatureLineId); + m_xDocumentHandler->endElement("SetupID"); + m_xDocumentHandler->startElement( + "SignatureText", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + m_xDocumentHandler->endElement("SignatureText"); + m_xDocumentHandler->startElement( + "SignatureImage", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + m_xDocumentHandler->endElement("SignatureImage"); + m_xDocumentHandler->startElement( + "SignatureComments", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + 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 SvXMLAttributeList())); + m_xDocumentHandler->characters("6.1"); + m_xDocumentHandler->endElement("WindowsVersion"); + m_xDocumentHandler->startElement( + "OfficeVersion", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + m_xDocumentHandler->characters("16.0"); + m_xDocumentHandler->endElement("OfficeVersion"); + m_xDocumentHandler->startElement( + "ApplicationVersion", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + m_xDocumentHandler->characters("16.0"); + m_xDocumentHandler->endElement("ApplicationVersion"); + m_xDocumentHandler->startElement( + "Monitors", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + m_xDocumentHandler->characters("1"); + m_xDocumentHandler->endElement("Monitors"); + m_xDocumentHandler->startElement( + "HorizontalResolution", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + m_xDocumentHandler->characters("1280"); + m_xDocumentHandler->endElement("HorizontalResolution"); + m_xDocumentHandler->startElement( + "VerticalResolution", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + m_xDocumentHandler->characters("800"); + m_xDocumentHandler->endElement("VerticalResolution"); + m_xDocumentHandler->startElement( + "ColorDepth", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + m_xDocumentHandler->characters("32"); + m_xDocumentHandler->endElement("ColorDepth"); + m_xDocumentHandler->startElement( + "SignatureProviderId", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + m_xDocumentHandler->characters("{00000000-0000-0000-0000-000000000000}"); + m_xDocumentHandler->endElement("SignatureProviderId"); + m_xDocumentHandler->startElement( + "SignatureProviderUrl", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + m_xDocumentHandler->endElement("SignatureProviderUrl"); + m_xDocumentHandler->startElement( + "SignatureProviderDetails", + uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + 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 SvXMLAttributeList())); + 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 SvXMLAttributeList())); + { + rtl::Reference<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); + 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<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); + 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<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); + 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<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); + 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 000000000..77ea7c484 --- /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 000000000..2692190cc --- /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 000000000..1ac72a46f --- /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 000000000..48d5c7f2d --- /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 <tools/diagnose_ex.h> +#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 000000000..0d9755d0e --- /dev/null +++ b/xmlsecurity/source/helper/xmlsignaturehelper.cxx @@ -0,0 +1,714 @@ +/* -*- 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 <xmloff/attrlist.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/ofopxmlhelper.hxx> +#include <comphelper/sequence.hxx> +#include <tools/diagnose_ex.h> +#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 OUStringLiteral OOXML_SIGNATURE_ORIGIN = u"http://schemas.openxmlformats.org/package/2006/relationships/digital-signature/origin"; +constexpr OUStringLiteral OOXML_SIGNATURE_SIGNATURE = u"http://schemas.openxmlformats.org/package/2006/relationships/digital-signature/signature"; + +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, + const OUString& 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<SvXMLAttributeList> pAttributeList = new SvXMLAttributeList(); + 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); + aOverrides.erase(std::remove_if(aOverrides.begin(), aOverrides.end(), [](const beans::StringPair& rPair) + { + return rPair.First.startsWith("/_xmlsignatures/sig"); + }), aOverrides.end()); + + // 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 000000000..5a9bf57ec --- /dev/null +++ b/xmlsecurity/source/helper/xsecctl.cxx @@ -0,0 +1,1004 @@ +/* -*- 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 <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 <xmloff/attrlist.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( const css::uno::Reference<css::uno::XComponentContext>& rxCtx ) + : mxCtx(rxCtx) + , 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<SvXMLAttributeList> pAttributeList(new SvXMLAttributeList()); + 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 SvXMLAttributeList())); + + { + xDocumentHandler->startElement("xd:CertificateValues", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + + { + for (const auto& i: signatureInfo.maEncapsulatedX509Certificates) + { + xDocumentHandler->startElement("xd:EncapsulatedX509Certificate", uno::Reference<xml::sax::XAttributeList>(new SvXMLAttributeList())); + 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<SvXMLAttributeList> pAttributeList; + + /* + * Write Signature element + */ + pAttributeList = new SvXMLAttributeList(); + 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 SvXMLAttributeList())); + { + /* Write CanonicalizationMethod element */ + pAttributeList = new SvXMLAttributeList(); + pAttributeList->AddAttribute( + "Algorithm", + ALGO_C14N); + xDocumentHandler->startElement( "CanonicalizationMethod", pAttributeList ); + xDocumentHandler->endElement( "CanonicalizationMethod" ); + + /* Write SignatureMethod element */ + pAttributeList = new SvXMLAttributeList(); + + // 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 SvXMLAttributeList(); + 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 SvXMLAttributeList())); + { + pAttributeList = new SvXMLAttributeList(); + pAttributeList->AddAttribute( + "Algorithm", + ALGO_C14N); + xDocumentHandler->startElement( + "Transform", + pAttributeList ); + xDocumentHandler->endElement( "Transform" ); + } + xDocumentHandler->endElement( "Transforms" ); + } + + /* Write DigestMethod element */ + pAttributeList = new SvXMLAttributeList(); + 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 SvXMLAttributeList())); + 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 SvXMLAttributeList())); + xDocumentHandler->characters( signatureInfo.ouSignatureValue ); + xDocumentHandler->endElement( "SignatureValue" ); + + /* Write KeyInfo element */ + xDocumentHandler->startElement( + "KeyInfo", + css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList())); + { + // GPG or X509 key? + if (!signatureInfo.ouGpgCertificate.isEmpty()) + { + pAttributeList = new SvXMLAttributeList(); + 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 SvXMLAttributeList())); + 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 SvXMLAttributeList())); + xDocumentHandler->characters( signatureInfo.ouGpgCertificate ); + xDocumentHandler->endElement( "PGPKeyPacket" ); + } + + /* Write PGPOwner element */ + xDocumentHandler->startElement( + "loext:PGPOwner", + css::uno::Reference< css::xml::sax::XAttributeList >(new SvXMLAttributeList())); + 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 SvXMLAttributeList())); + { + for (auto const& it : rData) + { + /* Write X509IssuerSerial element */ + xDocumentHandler->startElement( + "X509IssuerSerial", + css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList())); + { + /* Write X509IssuerName element */ + xDocumentHandler->startElement( + "X509IssuerName", + css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList())); + xDocumentHandler->characters(it.X509IssuerName); + xDocumentHandler->endElement( "X509IssuerName" ); + + /* Write X509SerialNumber element */ + xDocumentHandler->startElement( + "X509SerialNumber", + css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList())); + 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 SvXMLAttributeList())); + 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 SvXMLAttributeList())); + { + /* Write SignatureProperties element */ + xDocumentHandler->startElement( + "SignatureProperties", + css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList())); + { + /* Write SignatureProperty element */ + pAttributeList = new SvXMLAttributeList(); + pAttributeList->AddAttribute( + "Id", + signatureInfo.ouDateTimePropertyId); + pAttributeList->AddAttribute( + "Target", + "#" + signatureInfo.ouSignatureId); + xDocumentHandler->startElement( + "SignatureProperty", + pAttributeList); + { + /* Write timestamp element */ + + pAttributeList = new SvXMLAttributeList(); + 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 SvXMLAttributeList(); + pAttributeList->AddAttribute("Id", signatureInfo.ouDescriptionPropertyId); + pAttributeList->AddAttribute("Target", "#" + signatureInfo.ouSignatureId); + xDocumentHandler->startElement("SignatureProperty", pAttributeList); + + { + // Description element. + pAttributeList = new SvXMLAttributeList(); + 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 SvXMLAttributeList(); + pAttributeList->AddAttribute("xmlns:xd", NS_XD); + xDocumentHandler->startElement( + "Object", + pAttributeList); + { + pAttributeList = new SvXMLAttributeList(); + 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 000000000..af3562f46 --- /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 000000000..6279d6543 --- /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 000000000..5634ed502 --- /dev/null +++ b/xmlsecurity/source/helper/xsecsign.cxx @@ -0,0 +1,460 @@ +/* -*- 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) + { + length += sprintf(str+length, "%04x", i); + } + + 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 000000000..c45bece5f --- /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 000000000..1a4ab6fd9 --- /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 000000000..d7325759d --- /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 000000000..ac84596c8 --- /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 000000000..9db5867fc --- /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 000000000..a535ffa77 --- /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 000000000..ec3cecd4a --- /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 000000000..e5942ba2a --- /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 000000000..ce573d882 --- /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 000000000..6ded5fa0c --- /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 000000000..6c65c84f8 --- /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 000000000..f198f839f --- /dev/null +++ b/xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.cxx @@ -0,0 +1,1118 @@ +/* -*- 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/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::lang::XMultiServiceFactory ; +using ::com::sun::star::lang::XSingleServiceFactory ; + +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 (std::size_t i = 1; i < SAL_N_ELEMENTS(arErrStrings); i++) + { + if (arErrStrings[i].error & err) + SAL_INFO("xmlsecurity.xmlsec", " " << arErrStrings[i].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" }; +} + +/* XUnoTunnel */ +UNO3_GETIMPLEMENTATION_IMPL(SecurityEnvironment_MSCryptImpl); + +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 ; + + uno::Reference< XUnoTunnel > xCertTunnel( begin, uno::UNO_QUERY_THROW ) ; + const auto* xcert = comphelper::getFromUnoTunnel<X509Certificate_MSCryptImpl>(xCertTunnel); + 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 = xmlSecBase64Decode( chCert, chCert, xmlStrlen( chCert ) ) ; + + uno::Sequence< sal_Int8 > rawCert( certSize ) ; + auto rawCertRange = asNonConstRange(rawCert); + for( xmlSecSize i = 0 ; i < certSize ; i ++ ) + rawCertRange[i] = *( chCert + i ) ; + + 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; + + uno::Reference< XUnoTunnel > xCertTunnel( aCert, uno::UNO_QUERY_THROW ) ; + + SAL_INFO("xmlsecurity.xmlsec", "Start verification of certificate: " << aCert->getSubjectName()); + + const auto* xcert = comphelper::getFromUnoTunnel<X509Certificate_MSCryptImpl>(xCertTunnel); + 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 ; + + uno::Reference< XUnoTunnel > xCertTunnel( aCert, uno::UNO_QUERY_THROW ) ; + const auto* xcert = comphelper::getFromUnoTunnel<X509Certificate_MSCryptImpl>(xCertTunnel); + 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 000000000..a4ae45742 --- /dev/null +++ b/xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.hxx @@ -0,0 +1,173 @@ +/* -*- 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 <com/sun/star/lang/XUnoTunnel.hpp> + +#include <vector> +#include <xmlsec-wrapper.h> + +#include <sal/types.h> + + +class SecurityEnvironment_MSCryptImpl : public ::cppu::WeakImplHelper< + css::xml::crypto::XSecurityEnvironment , + css::lang::XServiceInfo, + css::lang::XUnoTunnel > +{ + 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; + + //Methods from XUnoTunnel + UNO3_GETIMPLEMENTATION_DECL(SecurityEnvironment_MSCryptImpl) + + /// @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 000000000..08143f992 --- /dev/null +++ b/xmlsecurity/source/xmlsec/mscrypt/seinitializer_mscryptimpl.cxx @@ -0,0 +1,173 @@ +/* -*- 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 = OString(sCertDB.getStr(), sCertDB.getLength(), 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 */ + uno::Reference< cssl::XUnoTunnel > xSecEnvTunnel( xSecEnv, uno::UNO_QUERY_THROW ); + SecurityEnvironment_MSCryptImpl* pSecEnv = comphelper::getFromUnoTunnel<SecurityEnvironment_MSCryptImpl>(xSecEnvTunnel); + 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 000000000..182ba5e5a --- /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 000000000..5e0ca9094 --- /dev/null +++ b/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx @@ -0,0 +1,786 @@ +/* -*- 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 <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) + { + OUString sType = rRawString.copy(nTypeNameStart, i - nTypeNameStart); + sType = sType.trim(); + if (sType.equalsIgnoreAsciiCase(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() ) ; + } +} + +/* XUnoTunnel */ +UNO3_GETIMPLEMENTATION_IMPL(X509Certificate_MSCryptImpl); + +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('"'); + buf.append(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 000000000..9bd6a34ce --- /dev/null +++ b/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.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 + +#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/XUnoTunnel.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::XUnoTunnel, + 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; + + //Methods from XUnoTunnel + UNO3_GETIMPLEMENTATION_DECL(X509Certificate_MSCryptImpl) + + /// @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 000000000..7d71d4863 --- /dev/null +++ b/xmlsecurity/source/xmlsec/mscrypt/xmlsecuritycontext_mscryptimpl.cxx @@ -0,0 +1,155 @@ +/* -*- 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::lang::XMultiServiceFactory ; +using ::com::sun::star::lang::XSingleServiceFactory ; + +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 000000000..87af0f040 --- /dev/null +++ b/xmlsecurity/source/xmlsec/mscrypt/xmlsignature_mscryptimpl.cxx @@ -0,0 +1,312 @@ +/* -*- 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::lang::XMultiServiceFactory ; +using ::com::sun::star::lang::XSingleServiceFactory ; + +using ::com::sun::star::xml::wrapper::XXMLElementWrapper ; +using ::com::sun::star::xml::wrapper::XXMLDocumentWrapper ; +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 + Reference< XUnoTunnel > xSecTunnel( aEnvironment , UNO_QUERY_THROW ) ; + SecurityEnvironment_MSCryptImpl* pSecEnv = comphelper::getFromUnoTunnel<SecurityEnvironment_MSCryptImpl>(xSecTunnel); + if( pSecEnv == nullptr ) + throw RuntimeException() ; + + //Get the xml node + Reference< XXMLElementWrapper > xElement = aTemplate->getTemplate() ; + if( !xElement.is() ) { + throw RuntimeException() ; + } + + Reference< XUnoTunnel > xNodTunnel( xElement , UNO_QUERY_THROW ) ; + XMLElementWrapper_XmlSecImpl* pElement = comphelper::getFromUnoTunnel<XMLElementWrapper_XmlSecImpl>(xNodTunnel); + 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()); + Reference< XUnoTunnel > xSecTunnel( xSecEnv , UNO_QUERY_THROW ) ; + SecurityEnvironment_MSCryptImpl* pSecEnv = comphelper::getFromUnoTunnel<SecurityEnvironment_MSCryptImpl>(xSecTunnel); + if( pSecEnv == nullptr ) + throw RuntimeException() ; + + //Get the xml node + Reference< XXMLElementWrapper > xElement = aTemplate->getTemplate() ; + if( !xElement.is() ) + throw RuntimeException() ; + + Reference< XUnoTunnel > xNodTunnel( xElement , UNO_QUERY_THROW ) ; + XMLElementWrapper_XmlSecImpl* pElement = comphelper::getFromUnoTunnel<XMLElementWrapper_XmlSecImpl>(xNodTunnel); + 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 000000000..e8b7b3873 --- /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 000000000..ff3441249 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/ciphercontext.cxx @@ -0,0 +1,265 @@ +/* -*- 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 <osl/diagnose.h> +#include <rtl/random.h> +#include <rtl/ref.hxx> + +#include "ciphercontext.hxx" +#include <pk11pub.h> + +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 ) + { + 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 ) + { + 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 ) + { + xResult->m_pContext = PK11_CreateContextBySymKey( nNSSCipherID, bEncryption ? CKA_ENCRYPT : CKA_DECRYPT, xResult->m_pSymKey, xResult->m_pSecParam); + if ( xResult->m_pContext ) + { + xResult->m_bEncryption = bEncryption; + xResult->m_bW3CPadding = bW3CPadding; + xResult->m_bPadding = bW3CPadding || ( PK11_GetPadMechanism( nNSSCipherID ) == nNSSCipherID ); + xResult->m_nBlockSize = PK11_GetBlockSize( nNSSCipherID, xResult->m_pSecParam ); + if ( xResult->m_nBlockSize <= SAL_MAX_INT8 ) + return xResult; + } + } + } + } + + return uno::Reference< xml::crypto::XCipherContext >(); +} + +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(); + + uno::Sequence< sal_Int8 > aToConvert; + if ( aData.hasElements() ) + { + sal_Int32 nOldLastBlockLen = m_aLastBlock.getLength(); + OSL_ENSURE( nOldLastBlockLen <= m_nBlockSize, "Unexpected last block size!" ); + + sal_Int32 nAvailableData = nOldLastBlockLen + aData.getLength(); + sal_Int32 nToConvertLen; + if ( m_bEncryption || !m_bW3CPadding ) + { + if ( nAvailableData % m_nBlockSize == 0 ) + nToConvertLen = nAvailableData; + else if ( nAvailableData < m_nBlockSize ) + nToConvertLen = 0; + else + nToConvertLen = nAvailableData - nAvailableData % m_nBlockSize; + } + else + { + // 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; + OSL_ENSURE( aToConvert.getLength() % m_nBlockSize == 0, "Unexpected size of the data to encrypt!" ); + 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(); + } + + 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(); + + OSL_ENSURE( m_nBlockSize <= SAL_MAX_INT8, "Unexpected block size!" ); + OSL_ENSURE( m_nConverted % m_nBlockSize == 0, "Unexpected amount of bytes is already 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 + OSL_ENSURE( m_aLastBlock.getLength() < m_nBlockSize, "Unexpected size of cashed incomplete last block!" ); + + // 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 + OSL_ENSURE( m_aLastBlock.getLength() < m_nBlockSize * 2 , "Unexpected size of cashed incomplete last block!" ); + + 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(); + } + + 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(); + } + + aResult.realloc( nPrefixLen + nFinalLen ); + + if ( m_bW3CPadding && !m_bEncryption ) + { + // W3CPadding handling for decryption + // aResult should have enough data, since we let m_aLastBlock be big enough in case of decryption + OSL_ENSURE( aResult.getLength() >= m_nBlockSize, "Not enough data to handle the padding!" ); + + sal_Int8 nBytesToRemove = aResult[aResult.getLength() - 1]; + if ( nBytesToRemove <= 0 || nBytesToRemove > aResult.getLength() ) + { + m_bBroken = true; + Dispose(); + throw uno::RuntimeException(); + } + + aResult.realloc( aResult.getLength() - nBytesToRemove ); + } + + 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 000000000..40b610ef5 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/ciphercontext.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 <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; + + 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 000000000..63c128e70 --- /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 000000000..72e186485 --- /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 000000000..29b26734e --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/nssinitializer.cxx @@ -0,0 +1,638 @@ +/* -*- 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 <tools/diagnose_ex.h> +#include <unotools/tempfile.hxx> +#include <salhelper/singletonref.hxx> +#include <comphelper/sequence.hxx> + +#include <nss/nssinitializer.hxx> + +#include "digestcontext.hxx" +#include "ciphercontext.hxx" + +#include <cstddef> +#include <memory> +#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::unique_ptr<utl::TempFile> m_pTempFileDatabaseDirectory; + +public: + OUString getTempDatabasePath() + { + if (!m_pTempFileDatabaseDirectory) + { + m_pTempFileDatabaseDirectory.reset(new utl::TempFile(nullptr, true)); + m_pTempFileDatabaseDirectory->EnableKillingFile(); + } + return m_pTempFileDatabaseDirectory->GetFileName(); + } + + void reset() + { + if (m_pTempFileDatabaseDirectory) + { + m_pTempFileDatabaseDirectory.reset(); + } + } +}; + +salhelper::SingletonRef<InitNSSPrivate>* getInitNSSPrivate() +{ + static salhelper::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 (std::size_t i=0; i<SAL_N_ELEMENTS(productTypes); ++i) + { + OUString profile = xMozillaBootstrap->getDefaultProfile(productTypes[i]); + + if (!profile.isEmpty()) + { + OUString sProfilePath = xMozillaBootstrap->getProfilePath(productTypes[i], 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 (std::size_t i=0; i<SAL_N_ELEMENTS(productTypes); ++i) + { + uno::Sequence<OUString> aProductProfileList; + xMozillaBootstrap->getProfileList(productTypes[i], aProductProfileList); + for (const auto& sProfile : std::as_const(aProductProfileList)) + aProfileList.push_back({sProfile, xMozillaBootstrap->getProfilePath(productTypes[i], sProfile), productTypes[i]}); + } + } + + 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(const css::uno::Reference< css::uno::XComponentContext > &rxContext) + : m_xContext(rxContext) +{ +} + +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; + if ( nCipherID != css::xml::crypto::CipherID::AES_CBC_W3C_PADDING ) + throw css::lang::IllegalArgumentException("Unexpected cipher requested.", css::uno::Reference< css::uno::XInterface >(), 1 ); + + nNSSCipherID = CKM_AES_CBC; + bW3CPadding = true; + + 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 ); + } + + 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 000000000..fa861c298 --- /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 OUStringLiteral NSS_SERVICE_NAME = u"com.sun.star.xml.crypto.NSSInitializer"; + +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(const css::uno::Reference<css::uno::XComponentContext> &rxContext); + 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 000000000..47280408b --- /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 000000000..e37a5473c --- /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; + OString oid("OID."); + if (oidString.match(oid)) + objID = oidString.copy(oid.getLength()); + 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 000000000..3716d414e --- /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 000000000..b7e623ce0 --- /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 000000000..bd5907826 --- /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 000000000..f6c35257f --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.cxx @@ -0,0 +1,890 @@ +/* -*- 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::xml::crypto::XSecurityEnvironment ; +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; +} + +/* XUnoTunnel */ +sal_Int64 SAL_CALL SecurityEnvironment_NssImpl::getSomething( const Sequence< sal_Int8 >& aIdentifier ) +{ + return comphelper::getSomethingImpl(aIdentifier, this); +} + +/* XUnoTunnel extension */ + +const Sequence< sal_Int8>& SecurityEnvironment_NssImpl::getUnoTunnelId() { + static const comphelper::UnoIdInit theSecurityEnvironment_NssImplUnoTunnelId; + return theSecurityEnvironment_NssImplUnoTunnelId.getSeq(); +} + +OUString SecurityEnvironment_NssImpl::getSecurityEnvironmentInformation() +{ + OUStringBuffer buff; + for (auto& slot : m_Slots) + { + buff.append(OUString::createFromAscii(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 ) { + // Remember the signing certificate. + m_xSigningCertificate = begin; + + Reference< XUnoTunnel > xCertTunnel( begin, UNO_QUERY_THROW ) ; + const X509Certificate_NssImpl* xcert = comphelper::getFromUnoTunnel<X509Certificate_NssImpl>(xCertTunnel); + if( xcert == nullptr ) { + throw RuntimeException() ; + } + + 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()) ) ; + int certSize = xmlSecBase64Decode( chCert, reinterpret_cast<xmlSecByte*>(chCert), xmlStrlen( chCert ) ) ; + if (certSize == 0) + 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 ; + Reference< XUnoTunnel > xCertTunnel( aCert, UNO_QUERY_THROW ) ; + + SAL_INFO("xmlsecurity.xmlsec", "Start verification of certificate: " << aCert->getSubjectName()); + + const X509Certificate_NssImpl* xcert = comphelper::getFromUnoTunnel<X509Certificate_NssImpl>(xCertTunnel); + 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 = SAL_N_ELEMENTS(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 ; + + Reference< XUnoTunnel > xCertTunnel( aCert, UNO_QUERY_THROW ) ; + const X509Certificate_NssImpl* xcert = comphelper::getFromUnoTunnel<X509Certificate_NssImpl>(xCertTunnel); + 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 (auto pCertificate = dynamic_cast<X509Certificate_NssImpl*>(m_xSigningCertificate.get())) + { + SECKEYPrivateKey* pPrivateKey = SECKEY_CopyPrivateKey(pCertificate->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 000000000..123103720 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.hxx @@ -0,0 +1,146 @@ +/* -*- 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 <com/sun/star/lang/XUnoTunnel.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, + css::lang::XUnoTunnel > +{ +private: + + std::vector< PK11SlotInfo* > m_Slots; + /// The last used certificate which has the private key for signing. + css::uno::Reference<css::security::XCertificate> 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; + + //Methods from XUnoTunnel + virtual sal_Int64 SAL_CALL getSomething( const css::uno::Sequence< sal_Int8 >& aIdentifier ) override; + + static const css::uno::Sequence< sal_Int8 >& getUnoTunnelId() ; + + /// @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 000000000..6ada0522b --- /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 ); + uno::Reference< lang::XUnoTunnel > xSecEnvTunnel(xSecEnv, uno::UNO_QUERY_THROW); + SecurityEnvironment_NssImpl* pSecEnv = comphelper::getFromUnoTunnel<SecurityEnvironment_NssImpl>(xSecEnvTunnel); + 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 000000000..f078f387a --- /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 000000000..7e28cbc61 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx @@ -0,0 +1,614 @@ +/* -*- 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 <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; + OString oid("OID."); + if (oidString.match(oid)) + objID = oidString.copy(oid.getLength()); + 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; +} + +/* XUnoTunnel */ +sal_Int64 SAL_CALL X509Certificate_NssImpl::getSomething( const css::uno::Sequence< sal_Int8 >& aIdentifier ) { + return comphelper::getSomethingImpl(aIdentifier, this); +} + +/* XUnoTunnel extension */ + +const css::uno::Sequence< sal_Int8>& X509Certificate_NssImpl::getUnoTunnelId() { + static const comphelper::UnoIdInit theX509Certificate_NssImplUnoTunnelId; + return theX509Certificate_NssImplUnoTunnelId.getSeq(); +} + +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(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 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.getLength() != i+1 && rDN[i+1] == '"') + { + buf.append('\\'); + buf.append(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(OUString(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 000000000..dbfb6c6b0 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.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 <sal/config.h> +#include <rtl/ustring.hxx> +#include <cppuhelper/implbase.hxx> +#include <com/sun/star/lang/XUnoTunnel.hpp> +#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::XUnoTunnel, + 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 ; + + //Methods from XUnoTunnel + virtual sal_Int64 SAL_CALL getSomething( const css::uno::Sequence< sal_Int8 >& aIdentifier ) override; + + /// @see xmlsecurity::Certificate::getSHA256Thumbprint(). + virtual css::uno::Sequence<sal_Int8> getSHA256Thumbprint() override; + + /// @see xmlsecurity::Certificate::getSignatureMethodAlgorithm(). + virtual svl::crypto::SignatureMethodAlgorithm getSignatureMethodAlgorithm() override; + + static const css::uno::Sequence< sal_Int8 >& getUnoTunnelId() ; + + //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 000000000..9ccf0ab98 --- /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 000000000..94e84a71b --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/xmlsignature_nssimpl.cxx @@ -0,0 +1,325 @@ +/* -*- 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() ; + } + + Reference< XUnoTunnel > xNodTunnel( xElement , UNO_QUERY_THROW ) ; + XMLElementWrapper_XmlSecImpl* pElement + = comphelper::getFromUnoTunnel<XMLElementWrapper_XmlSecImpl>(xNodTunnel); + 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 + Reference< XUnoTunnel > xSecTunnel( aEnvironment , UNO_QUERY_THROW ) ; + + // the key manager should be retrieved from SecurityEnvironment, instead of SecurityContext + SecurityEnvironment_NssImpl* pSecEnv + = comphelper::getFromUnoTunnel<SecurityEnvironment_NssImpl>(xSecTunnel); + 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() ; + + Reference< XUnoTunnel > xNodTunnel( xElement , UNO_QUERY_THROW ) ; + XMLElementWrapper_XmlSecImpl* pElement + = comphelper::getFromUnoTunnel<XMLElementWrapper_XmlSecImpl>(xNodTunnel); + 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 + Reference< XUnoTunnel > xSecTunnel( aEnvironment , UNO_QUERY_THROW ) ; + SecurityEnvironment_NssImpl* pSecEnv + = comphelper::getFromUnoTunnel<SecurityEnvironment_NssImpl>(xSecTunnel); + 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 000000000..ff576db49 --- /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 000000000..1694e30c8 --- /dev/null +++ b/xmlsecurity/source/xmlsec/xmldocumentwrapper_xmlsecimpl.cxx @@ -0,0 +1,902 @@ +/* -*- 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 <xmloff/attrlist.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<SvXMLAttributeList> pAttributeList = new SvXMLAttributeList(); + + 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()) + { + uno::Reference< css::lang::XUnoTunnel > xNodTunnel( xXMLElement, uno::UNO_QUERY_THROW ) ; + XMLElementWrapper_XmlSecImpl* pElement + = comphelper::getFromUnoTunnel<XMLElementWrapper_XmlSecImpl>(xNodTunnel); + + 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 000000000..910496618 --- /dev/null +++ b/xmlsecurity/source/xmlsec/xmlelementwrapper_xmlsecimpl.cxx @@ -0,0 +1,70 @@ +/* -*- 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 ) +{ +} + +/* XUnoTunnel */ +const uno::Sequence< sal_Int8 > & XMLElementWrapper_XmlSecImpl::getUnoTunnelId() +{ + static const comphelper::UnoIdInit implId; + return implId.getSeq(); +} + +sal_Int64 SAL_CALL XMLElementWrapper_XmlSecImpl::getSomething( const uno::Sequence< sal_Int8 >& aIdentifier ) +{ + return comphelper::getSomethingImpl(aIdentifier, this); +} + +/* 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 000000000..de833d25a --- /dev/null +++ b/xmlsecurity/source/xmlsec/xmlelementwrapper_xmlsecimpl.hxx @@ -0,0 +1,79 @@ +/* -*- 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/XUnoTunnel.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::XUnoTunnel, + 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::XUnoTunnel */ + virtual sal_Int64 SAL_CALL getSomething( const css::uno::Sequence< sal_Int8 >& aIdentifier ) override; + /// @throws css::uno::RuntimeException + static const css::uno::Sequence < sal_Int8 > & getUnoTunnelId(); + + /* 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 000000000..410408ed2 --- /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 000000000..b3ee76712 --- /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 000000000..b454f1faf --- /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 000000000..091052e3a --- /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 000000000..e69de29bb --- /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 000000000..83b33d238 --- /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 000000000..9a6e64301 --- /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 000000000..8f7e63a34 --- /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 000000000..be26aa5d8 --- /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 000000000..6d38b24e6 --- /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 000000000..dd1172404 --- /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 000000000..0dd15bd9e --- /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 000000000..72e6c66e2 --- /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 000000000..dd1172404 --- /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 000000000..2db3924ce --- /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 000000000..8f7e63a34 --- /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 000000000..1f27b97b3 --- /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 000000000..f75ccc08e --- /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 000000000..dd1172404 --- /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 000000000..f48e3d5a3 --- /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 000000000..8cfffd9a6 --- /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 000000000..83b33d238 --- /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 000000000..f6c52e5ac --- /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 000000000..8f7e63a34 --- /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 000000000..6efde26f7 --- /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 000000000..037410ad7 --- /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 000000000..95589b227 --- /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 000000000..6f57ca684 --- /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 000000000..3a2f7522d --- /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 000000000..cb72b8d16 --- /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 000000000..ce9b36d12 --- /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 000000000..8d6f2bd25 --- /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 000000000..c1a94dae5 --- /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 000000000..a3a79bf83 --- /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 000000000..75684732d --- /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 000000000..115190ca6 --- /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 000000000..95e419a17 --- /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 000000000..f91766a0a --- /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 000000000..34a9b97c5 --- /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 000000000..ae0a41747 --- /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 000000000..21222706f --- /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 000000000..b75551711 --- /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 000000000..2b48a29b0 --- /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 000000000..a2027e9d8 --- /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 000000000..d9d3f941e --- /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 000000000..9f4e006f0 --- /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 000000000..7bb12fa78 --- /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 000000000..d134dc5f3 --- /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 000000000..66c3f15bf --- /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 000000000..ba352d83d --- /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 000000000..4c03562a8 --- /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 000000000..c403402f3 --- /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 000000000..2790a2abd --- /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 000000000..f12a0c1c0 --- /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 000000000..1393b9ed3 --- /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 000000000..40e90d4cb --- /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 000000000..443c07462 --- /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 000000000..690260575 --- /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 000000000..fb0dd164e --- /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 000000000..b70608fe8 --- /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 000000000..dd84cb906 --- /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 000000000..e64badeef --- /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 000000000..e69de29bb --- /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 000000000..83b33d238 --- /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 000000000..3e79e22d7 --- /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 000000000..8f7e63a34 --- /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 000000000..36a8eb3c0 --- /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 000000000..7ef7ef0a5 --- /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 000000000..dd1172404 --- /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 000000000..0dd15bd9e --- /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 000000000..55be15521 --- /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 000000000..dd1172404 --- /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 000000000..dd9a47ee6 --- /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 000000000..8f7e63a34 --- /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 000000000..c14880b58 --- /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 000000000..445d86f99 --- /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 000000000..dd1172404 --- /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 000000000..51e520525 --- /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 000000000..b9fb278a2 --- /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 000000000..45b4ce8a5 --- /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 000000000..dd1172404 --- /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 000000000..f07b3377d --- /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 000000000..8f7e63a34 --- /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 000000000..391037118 --- /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 000000000..9d951ee26 --- /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 000000000..003d2f3b5 --- /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 000000000..7d802a3e7 --- /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 000000000..51e520525 --- /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 000000000..631deb24d --- /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 000000000..e69de29bb --- /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 000000000..83b33d238 --- /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 000000000..d910b9acc --- /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 000000000..8f7e63a34 --- /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 000000000..b350f6eb3 --- /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 000000000..222320a9a --- /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 000000000..7d802a3e7 --- /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 000000000..0ea6df297 --- /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 000000000..e49615a51 --- /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 000000000..5a7fc185b --- /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 000000000..e69de29bb --- /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 000000000..df6dcb21e --- /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 000000000..dd1172404 --- /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 000000000..7f0df0d95 --- /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 000000000..8f7e63a34 --- /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 000000000..0490b88cd --- /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 000000000..166be0166 --- /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 000000000..7d802a3e7 --- /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 000000000..f49c11090 --- /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 000000000..056f1b133 --- /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 000000000..01761f55b --- /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 000000000..e69de29bb --- /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 000000000..0eefbda68 --- /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 000000000..dd1172404 --- /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 000000000..24c353872 --- /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 000000000..8f7e63a34 --- /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 000000000..2dda8f2b2 --- /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 000000000..0d2a0f02a --- /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 000000000..147ca4e9b --- /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 000000000..7d802a3e7 --- /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 000000000..f2615bef4 --- /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 000000000..d749d8ebc --- /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 000000000..ef431ec95 --- /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 000000000..e69de29bb --- /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 000000000..8f91a1949 --- /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 000000000..dd1172404 --- /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 000000000..831cbf1a3 --- /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 000000000..8f7e63a34 --- /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 000000000..b2d1deb75 --- /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 000000000..26368962e --- /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 000000000..dd11db443 --- /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 000000000..7d802a3e7 --- /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 000000000..077e13b2b --- /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 000000000..ee3d2b339 --- /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 000000000..e69de29bb --- /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 000000000..66e316546 --- /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 000000000..ca53f28f7 --- /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 000000000..dd1172404 --- /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 000000000..c741bbfda --- /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 000000000..8f7e63a34 --- /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 000000000..0b38d4db4 --- /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 000000000..65149ff65 --- /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 000000000..dd1172404 --- /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 000000000..f48e3d5a3 --- /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 000000000..be26aa5d8 --- /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 000000000..e69de29bb --- /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 000000000..83b33d238 --- /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 000000000..e2027ce9f --- /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 000000000..8f7e63a34 --- /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 000000000..e7d22dfd0 --- /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 000000000..602026a47 --- /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 000000000..dd1172404 --- /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 000000000..0dd15bd9e --- /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 000000000..e69de29bb --- /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 000000000..a18ed9ce0 --- /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 000000000..e69de29bb --- /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 000000000..2bb9a4289 --- /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 000000000..1f27b97b3 --- /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 000000000..e69de29bb --- /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 000000000..67ed32da5 --- /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 000000000..dd1172404 --- /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 000000000..810ec7ef2 --- /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 000000000..8f7e63a34 --- /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 000000000..7449048bb --- /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 000000000..260e3aa94 --- /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 000000000..dd1172404 --- /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 000000000..431650974 --- /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 000000000..36a8eb3c0 --- /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 000000000..dd1172404 --- /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 000000000..ae1f2d1e4 --- /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 000000000..8f7e63a34 --- /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 000000000..a8c0b74ca --- /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 000000000..ba6119464 --- /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 000000000..cc93d02e5 --- /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 000000000..dd1172404 --- /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 000000000..51e520525 --- /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 000000000..c14880b58 --- /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 000000000..e69de29bb --- /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 000000000..83b33d238 --- /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 000000000..bd3b5eaea --- /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 000000000..8f7e63a34 --- /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 000000000..46d60bda0 --- /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 000000000..8d893cdf9 --- /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 000000000..dd08bf671 --- /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 000000000..dd1172404 --- /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 000000000..51e520525 --- /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 000000000..3ac354b8f --- /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 000000000..391037118 --- /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 000000000..dd1172404 --- /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 000000000..88e41b76a --- /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 000000000..8f7e63a34 --- /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 000000000..73563ed96 --- /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 000000000..7068aa0af --- /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 000000000..4c3de720f --- /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 000000000..7d802a3e7 --- /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 000000000..51e520525 --- /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 000000000..b266749a9 --- /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 000000000..b350f6eb3 --- /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 000000000..e69de29bb --- /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 000000000..3aec2bba1 --- /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 000000000..dd1172404 --- /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 000000000..2f83d6f9b --- /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 000000000..8f7e63a34 --- /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 000000000..59d5f7a2b --- /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 000000000..fb9af1caa --- /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 000000000..baccd0398 --- /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 000000000..963ab884f --- /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 000000000..0490b88cd --- /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 000000000..e69de29bb --- /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 000000000..83b33d238 --- /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 000000000..6e4d7577d --- /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 000000000..8f7e63a34 --- /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 000000000..538cb4e0b --- /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 000000000..9912ee088 --- /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 000000000..dd1172404 --- /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 000000000..188ed62e2 --- /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 000000000..d70e0550a --- /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 000000000..2dda8f2b2 --- /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 000000000..e69de29bb --- /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 000000000..f3f7e5cba --- /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 000000000..dd1172404 --- /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 000000000..8bcb130f6 --- /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 000000000..8f7e63a34 --- /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 000000000..234638d8c --- /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 000000000..ddc504d77 --- /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 000000000..c107913a2 --- /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 000000000..7d802a3e7 --- /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 000000000..7cbc4664f --- /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 000000000..4d510fe39 --- /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 000000000..b2d1deb75 --- /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 000000000..e69de29bb --- /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 000000000..7a9ee345e --- /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 000000000..dd1172404 --- /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 000000000..ff1b3fe19 --- /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 000000000..8f7e63a34 --- /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 000000000..71456d01b --- /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 000000000..51102e24a --- /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 000000000..6c934e3ec --- /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 000000000..7d802a3e7 --- /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 000000000..571237e7d --- /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 000000000..0b38d4db4 --- /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 000000000..dd1172404 --- /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 000000000..8c466eaff --- /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 000000000..8f7e63a34 --- /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 000000000..e3ca26a8a --- /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 000000000..be54b542a --- /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 000000000..dd1172404 --- /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 000000000..4a5b97f53 --- /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 000000000..e020f03a5 --- /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 000000000..9d951ee26 --- /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 000000000..dd1172404 --- /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 000000000..554a773b4 --- /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 000000000..8f7e63a34 --- /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 000000000..3fbf2133f --- /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 000000000..595fbbfaf --- /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 000000000..a8f9640c8 --- /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 000000000..baccd0398 --- /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 000000000..51e520525 --- /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 000000000..e04f69532 --- /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 000000000..0d2a0f02a --- /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 000000000..e69de29bb --- /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 000000000..c4dd13d83 --- /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 000000000..dd1172404 --- /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 000000000..a5e282ddd --- /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 000000000..8f7e63a34 --- /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 000000000..ff1f1fa66 --- /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 000000000..f16cdf4aa --- /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 000000000..1f95ffa3c --- /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 000000000..7d802a3e7 --- /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 000000000..c6acf751f --- /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 000000000..645ae6037 --- /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 000000000..26368962e --- /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 000000000..e69de29bb --- /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 000000000..f4e88754b --- /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 000000000..dd1172404 --- /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 000000000..cdace00f7 --- /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 000000000..8f7e63a34 --- /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 000000000..1107a4327 --- /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 000000000..53268ff52 --- /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 000000000..e063b9726 --- /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 000000000..59c112266 --- /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 000000000..571237e7d --- /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 000000000..ff4f23a90 --- /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 000000000..64f80334b --- /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 000000000..bbf0819dd --- /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 000000000..5f4bd15cd --- /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 000000000..306aa5649 --- /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 000000000..a4c1dd84d --- /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 000000000..e9af2c330 --- /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 000000000..03f2ff0b3 --- /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 000000000..96eb50459 --- /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 000000000..c714844ad --- /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 000000000..d83ce86de --- /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 000000000..c4857c541 --- /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 000000000..d39b18b57 --- /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 000000000..b881f8a12 --- /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 000000000..61391a8c2 --- /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 000000000..223d047ca --- /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 000000000..af6a36003 --- /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 000000000..05297a327 --- /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 000000000..209059fac --- /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 000000000..a981a091c --- /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 000000000..d73827e10 --- /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 000000000..69da1318b --- /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 000000000..e7fee3ade --- /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 000000000..95e18ae6a --- /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 000000000..5978b2613 --- /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 000000000..10b370c14 --- /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 000000000..90bf8eba4 --- /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 000000000..c9f542029 --- /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 000000000..7fc03f255 --- /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 000000000..567b8b5d1 --- /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 000000000..a2ce79b3a --- /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 000000000..16abebe51 --- /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 000000000..08f5040ce --- /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 000000000..18bd2475c --- /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 000000000..c7c83cf19 --- /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 000000000..3ff2118d2 --- /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 000000000..0fcd6393a --- /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 000000000..9f2874060 --- /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 000000000..49442c6df --- /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 000000000..27109c5bb --- /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 000000000..5cce769b4 --- /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 000000000..09f2a54f4 --- /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 000000000..c3810ab50 --- /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 000000000..1531d1e8d --- /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 000000000..3dab25877 --- /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 000000000..278b11b77 --- /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 000000000..fa6e84547 --- /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 000000000..863f6f613 --- /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 000000000..cae3959d1 --- /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 000000000..e5786dc6c --- /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 000000000..a63a9f8c9 --- /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 000000000..59a77df71 --- /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 000000000..3b12b29c1 --- /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 000000000..c11e716d7 --- /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 000000000..026274f63 --- /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 000000000..4a026790e --- /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 000000000..46b008eeb --- /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 000000000..7c1c2cb29 --- /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 000000000..cc6185cc9 --- /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 000000000..fa646e402 --- /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 000000000..673db6cc9 --- /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 000000000..e284dca9b --- /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 000000000..5b2cda461 --- /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 000000000..532010b18 --- /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 000000000..282aa47af --- /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 000000000..26a51418f --- /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 000000000..8a00d3008 --- /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 000000000..935da38c2 --- /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 000000000..79ea4fbcf --- /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 000000000..011c4ae2a --- /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 000000000..b14254428 --- /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 000000000..8c8689e10 --- /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 000000000..ed39bea1e --- /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 000000000..7f9e13698 --- /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 000000000..dc28470c8 --- /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 000000000..df9d81d8d --- /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 000000000..018da383d --- /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 000000000..0092d16c7 --- /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 000000000..879f4578c --- /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 000000000..75a9c7c84 --- /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 000000000..cf07f4aa2 --- /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 000000000..993a09f95 --- /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 000000000..a1cebacb3 --- /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 000000000..12410ebc8 --- /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 000000000..f7372d09f --- /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 000000000..7df592643 --- /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 000000000..048ca8e8f --- /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 000000000..4498cdb76 --- /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 000000000..d85e0b7d4 --- /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 000000000..ff666ff1e --- /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 000000000..55e0d6233 --- /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 000000000..baa32f26b --- /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 000000000..7b20ff98c --- /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 000000000..6e980df49 --- /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 000000000..4d343d6e7 --- /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 000000000..aa5f27d2d --- /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 000000000..80e5bf47c --- /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 000000000..1e9a14cb8 --- /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 000000000..d7096919b --- /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 000000000..adc61fff4 --- /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 000000000..9213427a1 --- /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 000000000..005191d16 --- /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 000000000..e4599b113 --- /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 000000000..32b4926ad --- /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 000000000..2c0ea4acb --- /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 000000000..b69a19e4e --- /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 000000000..7897733c4 --- /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 000000000..99eb94452 --- /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 000000000..1aefff504 --- /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 000000000..6b6d5fd4e --- /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 000000000..bebfdc88a --- /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 000000000..cbd6730a8 --- /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 000000000..ab2b651c1 --- /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 000000000..518388c5b --- /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 000000000..775b1359d --- /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 000000000..f76a61869 --- /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 000000000..ef1273c72 --- /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 000000000..4208dc431 --- /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 000000000..4826f2d04 --- /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 000000000..bc211718a --- /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 000000000..876151de3 --- /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 000000000..268eeb938 --- /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 000000000..2fc86b9af --- /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 000000000..80dd6a8b0 --- /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 000000000..821bb8ea5 --- /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 000000000..3671d176d --- /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 000000000..a4c63b7f2 --- /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 000000000..99b0be699 --- /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 000000000..5dbaf524c --- /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 000000000..17e22f7a5 --- /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 000000000..5982532a9 --- /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 000000000..4c00b21d4 --- /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 000000000..bc476b257 --- /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 000000000..0b9bd319b --- /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 000000000..99de803de --- /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 000000000..a663a92d9 --- /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 000000000..c3d4e7532 --- /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 000000000..9db9c0ad4 --- /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 000000000..ccb03b327 --- /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 000000000..8c34889df --- /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 000000000..6a1b48c6a --- /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 000000000..248fccedd --- /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 000000000..2e0dbd6f7 --- /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 000000000..3519e4a81 --- /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 000000000..06e412fa3 --- /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 000000000..851fc87e7 --- /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 000000000..a97598d55 --- /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 000000000..f82a02a45 --- /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 000000000..5cbf289de --- /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 000000000..20c28d925 --- /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 000000000..d3f59e601 --- /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 000000000..8c6416b80 --- /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 000000000..fce479cc6 --- /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 000000000..53d1e01e7 --- /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 000000000..1f69a3248 --- /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 000000000..53a29310e --- /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 000000000..4d34bc0f5 --- /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 000000000..ca17f6aab --- /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 000000000..798f25a35 --- /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 000000000..591f9aa4d --- /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 000000000..cb0763b0a --- /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 000000000..f0555b1a2 --- /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 000000000..b2e24fc61 --- /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 000000000..640a80dce --- /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 000000000..35847216b --- /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 000000000..575f3a12d --- /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 000000000..75a417cab --- /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 000000000..f7d71762f --- /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 000000000..9984aa1bb --- /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 000000000..5ad7b68ab --- /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 000000000..d126a8dff --- /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 000000000..dd475c354 --- /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 000000000..f8ab95c04 --- /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 000000000..4d7c5cd80 --- /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 000000000..0979ae5a9 --- /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 000000000..f7c9bbf5e --- /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 000000000..d26eb58f0 --- /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 000000000..5d6c053c2 --- /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 000000000..cb6401c16 --- /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 000000000..09b63b40a --- /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 000000000..e810d785d --- /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 000000000..6c2bbd045 --- /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 000000000..b8b036cc8 --- /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 000000000..6ba0ec52a --- /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 000000000..de1c635c1 --- /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 000000000..f6575ec88 --- /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 000000000..41f676f63 --- /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 000000000..45bbb5b0d --- /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 000000000..b253a78b6 --- /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 000000000..3492d3aa6 --- /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 000000000..328e8e5bc --- /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 000000000..9064a3305 --- /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 000000000..d8139c888 --- /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 000000000..a0ec60ac7 --- /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 000000000..6fc771ca7 --- /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 000000000..1f9fd91d2 --- /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 000000000..cc4ba2199 --- /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 000000000..e0c0b48ac --- /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 000000000..4e0579ac5 --- /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 000000000..cf2404c61 --- /dev/null +++ b/xmlsecurity/uiconfig/ui/digitalsignaturesdialog.ui @@ -0,0 +1,528 @@ +<?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">spread</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">False</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">False</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">False</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> + <child> + <object class="GtkCheckButton" id="adescompliant"> + <property name="label" translatable="yes" context="digitalsignaturesdialog|adescompliant">Use AdES-compliant signature when there is a choice</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="halign">start</property> + <property name="use_underline">True</property> + <property name="draw_indicator">True</property> + <child internal-child="accessible"> + <object class="AtkObject" id="adescompliant-atkobject"> + <property name="AtkObject::accessible-description" translatable="yes" context="digitalsignaturesdialog|extended_tip|adescompliant">Prefers creating XAdES signatures for ODF and OOXML, PAdES signatures for PDF.</property> + </object> + </child> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">6</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 000000000..06699d588 --- /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 000000000..9c601b494 --- /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 from trusted sources are allowed to run. +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">Trusted sources can be set on the Trusted Sources tab page. Only signed macros from a trusted source are allowed to run. In addition, 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">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 000000000..267efa8f0 --- /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 000000000..668379055 --- /dev/null +++ b/xmlsecurity/uiconfig/ui/selectcertificatedialog.ui @@ -0,0 +1,301 @@ +<?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 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="SelectCertificateDialog"> + <property name="can_focus">False</property> + <property name="border_width">6</property> + <property name="title" translatable="yes" context="selectcertificatedialog|SelectCertificateDialog">Select X.509 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=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">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" 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="selectcertificatedialog|issuedto">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="selectcertificatedialog|issuedby">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="selectcertificatedialog|type">Type</property> + <child> + <object class="GtkCellRendererText" id="cellrenderer3"/> + <attributes> + <attribute name="text">2</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="selectcertificatedialog|expiration">Expiration date</property> + <child> + <object class="GtkCellRendererText" id="cellrenderer4"/> + <attributes> + <attribute name="text">3</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="selectcertificatedialog|usage">Certificate usage</property> + <child> + <object class="GtkCellRendererText" id="cellrenderer5"/> + <attributes> + <attribute name="text">4</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">2</property> + </packing> + </child> + <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="left_attach">0</property> + <property name="top_attach">3</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">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 type="titlebar"> + <placeholder/> + </child> + <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 000000000..12cf4b40e --- /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 000000000..7dfe91a0d --- /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 000000000..5dc5f6765 --- /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 000000000..f2b072949 --- /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 000000000..c770a555b --- /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 000000000..3ff9557b9 --- /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 000000000..c713c1e83 --- /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 000000000..f04db1fa6 --- /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 <tools/diagnose_ex.h> +#include <vcl/pngwrite.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(); + vcl::PNGWriter aWriter(aBitmapEx); + OUString aOutURL; + osl::FileBase::getFileURLFromSystemPath(OUString::fromUtf8(rPngPath), aOutURL); + SvFileStream aOutStream(aOutURL, StreamMode::WRITE); + aWriter.Write(aOutStream); +} + +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: */ |