From 267c6f2ac71f92999e969232431ba04678e7437e Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Mon, 15 Apr 2024 07:54:39 +0200 Subject: Adding upstream version 4:24.2.0. Signed-off-by: Daniel Baumann --- xmlsecurity/AllLangMoTarget_xsc.mk | 13 + xmlsecurity/CppunitTest_qa_certext.mk | 27 + .../CppunitTest_xmlsecurity_dialogs_test.mk | 68 + xmlsecurity/CppunitTest_xmlsecurity_pdfsigning.mk | 70 + xmlsecurity/CppunitTest_xmlsecurity_signing.mk | 94 + xmlsecurity/CppunitTest_xmlsecurity_signing2.mk | 94 + xmlsecurity/Executable_pdfverify.mk | 35 + xmlsecurity/IwyuFilter_xmlsecurity.yaml | 131 + xmlsecurity/Library_xmlsecurity.mk | 112 + xmlsecurity/Library_xsec_xmlsec.mk | 188 + xmlsecurity/Makefile | 14 + xmlsecurity/Module_xmlsecurity.mk | 53 + xmlsecurity/README.md | 59 + xmlsecurity/UIConfig_xmlsec.mk | 24 + .../doc/OpenDocumentSignatures-TestIntegration.odt | Bin 0 -> 26268 bytes .../doc/OpenDocumentSignatures-Workflow.odg | Bin 0 -> 32729 bytes xmlsecurity/doc/OpenDocumentSignatures.odt | Bin 0 -> 23079 bytes xmlsecurity/doc/XMLSecurityFramework.odt | Bin 0 -> 196857 bytes xmlsecurity/inc/UriBindingHelper.hxx | 51 + xmlsecurity/inc/biginteger.hxx | 51 + xmlsecurity/inc/bitmaps.hlst | 21 + xmlsecurity/inc/certificate.hxx | 43 + xmlsecurity/inc/certificatechooser.hxx | 117 + xmlsecurity/inc/certificateviewer.hxx | 159 + xmlsecurity/inc/digitalsignaturesdialog.hxx | 124 + xmlsecurity/inc/documentsignaturehelper.hxx | 104 + xmlsecurity/inc/documentsignaturemanager.hxx | 136 + xmlsecurity/inc/framework/saxeventkeeperimpl.hxx | 290 ++ xmlsecurity/inc/framework/securityengine.hxx | 142 + xmlsecurity/inc/framework/signaturecreatorimpl.hxx | 96 + xmlsecurity/inc/framework/signatureengine.hxx | 116 + .../inc/framework/signatureverifierimpl.hxx | 88 + .../inc/framework/xmlsignaturetemplateimpl.hxx | 95 + xmlsecurity/inc/gpg/SEInitializer.hxx | 47 + xmlsecurity/inc/gpg/xmlsignature_gpgimpl.hxx | 77 + xmlsecurity/inc/macrosecurity.hxx | 126 + xmlsecurity/inc/pch/precompiled_xmlsecurity.cxx | 12 + xmlsecurity/inc/pch/precompiled_xmlsecurity.hxx | 200 + xmlsecurity/inc/pch/precompiled_xsec_xmlsec.cxx | 12 + xmlsecurity/inc/pch/precompiled_xsec_xmlsec.hxx | 149 + xmlsecurity/inc/pdfsignaturehelper.hxx | 73 + xmlsecurity/inc/resourcemanager.hxx | 26 + xmlsecurity/inc/strings.hrc | 68 + xmlsecurity/inc/xmlsec-wrapper.h | 43 + xmlsecurity/inc/xmlsec/errorcallback.hxx | 30 + xmlsecurity/inc/xmlsec/saxhelper.hxx | 86 + .../inc/xmlsec/xmldocumentwrapper_xmlsecimpl.hxx | 208 + xmlsecurity/inc/xmlsec/xmlsec_init.hxx | 17 + xmlsecurity/inc/xmlsec/xmlstreamio.hxx | 39 + xmlsecurity/inc/xmlsecuritydllapi.h | 20 + xmlsecurity/inc/xmlsignaturehelper.hxx | 176 + xmlsecurity/inc/xsecctl.hxx | 408 ++ xmlsecurity/inc/xsecxmlsecdllapi.h | 20 + xmlsecurity/qa/certext/SanCertExt.cxx | 260 ++ xmlsecurity/qa/certext/User_35_Root_11.crt | 64 + xmlsecurity/qa/create-certs/create-certs.sh | 187 + xmlsecurity/qa/create-certs/create-dump-certs.sh | 31 + .../qa/create-certs/templates/intermediate.cnf | 132 + xmlsecurity/qa/create-certs/templates/root.cnf | 132 + .../qa/unit/data/xmlsecurity-dialogs-test.txt | 45 + xmlsecurity/qa/unit/pdfsigning/data/2good.pdf | Bin 0 -> 109682 bytes .../qa/unit/pdfsigning/data/bad-cert-p1.pdf | Bin 0 -> 29646 bytes .../qa/unit/pdfsigning/data/bad-cert-p3-stamp.pdf | Bin 0 -> 22023 bytes xmlsecurity/qa/unit/pdfsigning/data/cr-comment.pdf | 4480 ++++++++++++++++++++ xmlsecurity/qa/unit/pdfsigning/data/dict-bool.pdf | Bin 0 -> 145552 bytes .../qa/unit/pdfsigning/data/forcepoint16.pdf | Bin 0 -> 51200 bytes .../qa/unit/pdfsigning/data/good-custom-magic.pdf | Bin 0 -> 57404 bytes .../qa/unit/pdfsigning/data/good-non-detached.pdf | Bin 0 -> 29815 bytes xmlsecurity/qa/unit/pdfsigning/data/good-pades.pdf | Bin 0 -> 58008 bytes xmlsecurity/qa/unit/pdfsigning/data/good.pdf | Bin 0 -> 58796 bytes .../qa/unit/pdfsigning/data/name-bracket.pdf | 2241 ++++++++++ xmlsecurity/qa/unit/pdfsigning/data/no-eof.pdf | Bin 0 -> 174879 bytes xmlsecurity/qa/unit/pdfsigning/data/no.pdf | Bin 0 -> 6865 bytes xmlsecurity/qa/unit/pdfsigning/data/noeol.pdf | Bin 0 -> 83693 bytes .../qa/unit/pdfsigning/data/partial-in-between.pdf | Bin 0 -> 104501 bytes xmlsecurity/qa/unit/pdfsigning/data/partial.pdf | Bin 0 -> 52004 bytes xmlsecurity/qa/unit/pdfsigning/data/pdf14adobe.pdf | Bin 0 -> 141054 bytes xmlsecurity/qa/unit/pdfsigning/data/pdf14lowin.pdf | Bin 0 -> 58575 bytes xmlsecurity/qa/unit/pdfsigning/data/pdf16adobe.pdf | Bin 0 -> 81882 bytes xmlsecurity/qa/unit/pdfsigning/data/small.pdf | Bin 0 -> 834 bytes xmlsecurity/qa/unit/pdfsigning/data/tdf107149.pdf | 97 + xmlsecurity/qa/unit/pdfsigning/data/tdf107782.pdf | Bin 0 -> 157668 bytes xmlsecurity/qa/unit/pdfsigning/data/tdf114460.pdf | Bin 0 -> 12669 bytes xmlsecurity/qa/unit/pdfsigning/data/tdf145312.pdf | Bin 0 -> 148303 bytes xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx | 646 +++ ...2_doc_macros_signed_by_attacker_manipulated.odt | Bin 0 -> 14045 bytes .../data/02_doc_signed_by_attacker_manipulated.odt | Bin 0 -> 13139 bytes .../02_doc_signed_by_attacker_manipulated2.odt | Bin 0 -> 13160 bytes ...2_doc_signed_by_attacker_manipulated_triple.odt | Bin 0 -> 13237 bytes ...02_doc_signed_by_trusted_person_manipulated.odt | Bin 0 -> 14003 bytes .../qa/unit/signing/data/add-visible-signature.pdf | Bin 0 -> 2235 bytes xmlsecurity/qa/unit/signing/data/bad.docx | Bin 0 -> 17962 bytes xmlsecurity/qa/unit/signing/data/bad.odt | Bin 0 -> 10920 bytes xmlsecurity/qa/unit/signing/data/bad.pdf | Bin 0 -> 57587 bytes xmlsecurity/qa/unit/signing/data/badDsigGPG.odt | Bin 0 -> 13047 bytes xmlsecurity/qa/unit/signing/data/badStreamGPG.odt | Bin 0 -> 13046 bytes xmlsecurity/qa/unit/signing/data/encryptedGPG.odt | Bin 0 -> 13081 bytes .../qa/unit/signing/data/encryptedGPG_odf13.odt | Bin 0 -> 12982 bytes xmlsecurity/qa/unit/signing/data/good-xades.odt | Bin 0 -> 13918 bytes xmlsecurity/qa/unit/signing/data/good.odt | Bin 0 -> 10878 bytes xmlsecurity/qa/unit/signing/data/good.pdf | Bin 0 -> 57587 bytes xmlsecurity/qa/unit/signing/data/goodGPG.odt | Bin 0 -> 11587 bytes .../data/hide-and-replace-shadow-file-signed-2.pdf | Bin 0 -> 17896 bytes xmlsecurity/qa/unit/signing/data/multi.docx | Bin 0 -> 23767 bytes xmlsecurity/qa/unit/signing/data/no.odt | Bin 0 -> 8345 bytes xmlsecurity/qa/unit/signing/data/no.pdf | Bin 0 -> 6865 bytes xmlsecurity/qa/unit/signing/data/notype-xades.odt | Bin 0 -> 13918 bytes .../qa/unit/signing/data/odb_signed_macros.odb | Bin 0 -> 8823 bytes xmlsecurity/qa/unit/signing/data/partial.docx | Bin 0 -> 17918 bytes .../qa/unit/signing/data/signatureline.docx | Bin 0 -> 22877 bytes xmlsecurity/qa/unit/signing/data/signatureline.odt | Bin 0 -> 27142 bytes .../data/signed_with_x509certificate_chain.odt | Bin 0 -> 13585 bytes xmlsecurity/qa/unit/signing/data/tdf42316.ott | Bin 0 -> 10242 bytes .../qa/unit/signing/data/tdf42316_odt12.ott | Bin 0 -> 14625 bytes xmlsecurity/qa/unit/signing/data/tdf96097.ods | Bin 0 -> 13767 bytes xmlsecurity/qa/unit/signing/data/tdf96097.odt | Bin 0 -> 11791 bytes .../qa/unit/signing/data/untrustedGoodGPG.odt | Bin 0 -> 12274 bytes xmlsecurity/qa/unit/signing/signing.cxx | 1473 +++++++ xmlsecurity/qa/unit/signing/signing2.cxx | 80 + xmlsecurity/qa/unit/xmlsecurity-dialogs-test.cxx | 61 + .../source/component/certificatecontainer.cxx | 152 + .../source/component/documentdigitalsignatures.cxx | 906 ++++ xmlsecurity/source/dialogs/certificatechooser.cxx | 377 ++ xmlsecurity/source/dialogs/certificateviewer.cxx | 377 ++ .../source/dialogs/digitalsignaturesdialog.cxx | 826 ++++ xmlsecurity/source/dialogs/macrosecurity.cxx | 447 ++ xmlsecurity/source/framework/buffernode.cxx | 887 ++++ xmlsecurity/source/framework/buffernode.hxx | 118 + xmlsecurity/source/framework/elementcollector.cxx | 138 + xmlsecurity/source/framework/elementcollector.hxx | 80 + xmlsecurity/source/framework/elementmark.cxx | 64 + xmlsecurity/source/framework/elementmark.hxx | 67 + .../source/framework/saxeventkeeperimpl.cxx | 1152 +++++ xmlsecurity/source/framework/securityengine.cxx | 67 + .../source/framework/signaturecreatorimpl.cxx | 175 + xmlsecurity/source/framework/signatureengine.cxx | 197 + .../source/framework/signatureverifierimpl.cxx | 130 + .../source/framework/xmlsignaturetemplateimpl.cxx | 113 + xmlsecurity/source/gpg/CertificateImpl.cxx | 248 ++ xmlsecurity/source/gpg/CertificateImpl.hxx | 93 + xmlsecurity/source/gpg/CipherContext.cxx | 27 + xmlsecurity/source/gpg/CipherContext.hxx | 26 + xmlsecurity/source/gpg/DigestContext.cxx | 23 + xmlsecurity/source/gpg/DigestContext.hxx | 24 + xmlsecurity/source/gpg/SEInitializer.cxx | 80 + xmlsecurity/source/gpg/SecurityEnvironment.cxx | 217 + xmlsecurity/source/gpg/SecurityEnvironment.hxx | 65 + xmlsecurity/source/gpg/XMLEncryption.cxx | 37 + xmlsecurity/source/gpg/XMLEncryption.hxx | 37 + xmlsecurity/source/gpg/XMLSecurityContext.cxx | 87 + xmlsecurity/source/gpg/XMLSecurityContext.hxx | 58 + xmlsecurity/source/gpg/xmlsignature_gpgimpl.cxx | 532 +++ xmlsecurity/source/helper/UriBindingHelper.cxx | 113 + .../source/helper/documentsignaturehelper.cxx | 650 +++ .../source/helper/documentsignaturemanager.cxx | 705 +++ xmlsecurity/source/helper/ooxmlsecexporter.cxx | 565 +++ xmlsecurity/source/helper/ooxmlsecexporter.hxx | 47 + xmlsecurity/source/helper/ooxmlsecparser.cxx | 1352 ++++++ xmlsecurity/source/helper/ooxmlsecparser.hxx | 110 + xmlsecurity/source/helper/pdfsignaturehelper.cxx | 626 +++ xmlsecurity/source/helper/xmlsignaturehelper.cxx | 713 ++++ xmlsecurity/source/helper/xsecctl.cxx | 1005 +++++ xmlsecurity/source/helper/xsecparser.cxx | 1632 +++++++ xmlsecurity/source/helper/xsecparser.hxx | 159 + xmlsecurity/source/helper/xsecsign.cxx | 462 ++ xmlsecurity/source/helper/xsecverify.cxx | 630 +++ xmlsecurity/source/xmlsec/biginteger.cxx | 106 + .../xmlsec/certificateextension_certextn.cxx | 47 + .../xmlsec/certificateextension_certextn.hxx | 36 + .../xmlsec/certificateextension_xmlsecimpl.hxx | 56 + xmlsecurity/source/xmlsec/errorcallback.cxx | 68 + xmlsecurity/source/xmlsec/mscrypt/akmngr.cxx | 229 + xmlsecurity/source/xmlsec/mscrypt/akmngr.hxx | 56 + xmlsecurity/source/xmlsec/mscrypt/oid.hxx | 153 + .../xmlsec/mscrypt/sanextension_mscryptimpl.cxx | 131 + .../xmlsec/mscrypt/sanextension_mscryptimpl.hxx | 66 + .../mscrypt/securityenvironment_mscryptimpl.cxx | 1110 +++++ .../mscrypt/securityenvironment_mscryptimpl.hxx | 168 + .../xmlsec/mscrypt/seinitializer_mscryptimpl.cxx | 172 + .../xmlsec/mscrypt/seinitializer_mscryptimpl.hxx | 71 + .../xmlsec/mscrypt/x509certificate_mscryptimpl.cxx | 783 ++++ .../xmlsec/mscrypt/x509certificate_mscryptimpl.hxx | 91 + .../mscrypt/xmlsecuritycontext_mscryptimpl.cxx | 153 + .../xmlsec/mscrypt/xmlsignature_mscryptimpl.cxx | 305 ++ xmlsecurity/source/xmlsec/nss/certerrors.h | 385 ++ xmlsecurity/source/xmlsec/nss/ciphercontext.cxx | 389 ++ xmlsecurity/source/xmlsec/nss/ciphercontext.hxx | 81 + xmlsecurity/source/xmlsec/nss/digestcontext.cxx | 94 + xmlsecurity/source/xmlsec/nss/digestcontext.hxx | 59 + xmlsecurity/source/xmlsec/nss/nssinitializer.cxx | 647 +++ xmlsecurity/source/xmlsec/nss/nssinitializer.hxx | 68 + xmlsecurity/source/xmlsec/nss/nssrenam.h | 41 + .../source/xmlsec/nss/sanextension_nssimpl.cxx | 164 + .../source/xmlsec/nss/sanextension_nssimpl.hxx | 65 + xmlsecurity/source/xmlsec/nss/secerror.cxx | 152 + xmlsecurity/source/xmlsec/nss/secerror.hxx | 31 + .../xmlsec/nss/securityenvironment_nssimpl.cxx | 878 ++++ .../xmlsec/nss/securityenvironment_nssimpl.hxx | 139 + .../source/xmlsec/nss/seinitializer_nssimpl.cxx | 144 + .../source/xmlsec/nss/seinitializer_nssimpl.hxx | 55 + .../source/xmlsec/nss/x509certificate_nssimpl.cxx | 602 +++ .../source/xmlsec/nss/x509certificate_nssimpl.hxx | 97 + .../xmlsec/nss/xmlsecuritycontext_nssimpl.cxx | 150 + .../source/xmlsec/nss/xmlsignature_nssimpl.cxx | 321 ++ xmlsecurity/source/xmlsec/saxhelper.cxx | 364 ++ .../xmlsec/xmldocumentwrapper_xmlsecimpl.cxx | 900 ++++ .../source/xmlsec/xmlelementwrapper_xmlsecimpl.cxx | 58 + .../source/xmlsec/xmlelementwrapper_xmlsecimpl.hxx | 72 + xmlsecurity/source/xmlsec/xmlsec_init.cxx | 73 + xmlsecurity/source/xmlsec/xmlstreamio.cxx | 251 ++ xmlsecurity/test_docs/CAs/README.txt | 383 ++ xmlsecurity/test_docs/CAs/Root_1/demoCA/cacert.pem | 19 + .../CAs/Root_1/demoCA/crl/DO_NOT_CREATE_A_CRL | 0 xmlsecurity/test_docs/CAs/Root_1/demoCA/crlnumber | 1 + xmlsecurity/test_docs/CAs/Root_1/demoCA/index.txt | 1 + .../test_docs/CAs/Root_1/demoCA/index.txt.attr | 1 + .../test_docs/CAs/Root_1/demoCA/newcerts/1000.pem | 62 + .../test_docs/CAs/Root_1/demoCA/private/cakey.pem | 18 + xmlsecurity/test_docs/CAs/Root_1/demoCA/serial | 1 + xmlsecurity/test_docs/CAs/Root_1/openssl.cfg | 292 ++ .../test_docs/CAs/Root_10/demoCA/cacert.pem | 19 + xmlsecurity/test_docs/CAs/Root_10/demoCA/crlnumber | 1 + xmlsecurity/test_docs/CAs/Root_10/demoCA/index.txt | 1 + .../test_docs/CAs/Root_10/demoCA/index.txt.attr | 1 + .../test_docs/CAs/Root_10/demoCA/newcerts/1000.pem | 62 + .../test_docs/CAs/Root_10/demoCA/private/cakey.pem | 18 + xmlsecurity/test_docs/CAs/Root_10/demoCA/serial | 1 + xmlsecurity/test_docs/CAs/Root_10/openssl.cfg | 292 ++ .../test_docs/CAs/Root_11/demoCA/cacert.pem | 19 + xmlsecurity/test_docs/CAs/Root_11/demoCA/crlnumber | 1 + xmlsecurity/test_docs/CAs/Root_11/demoCA/index.txt | 35 + .../test_docs/CAs/Root_11/demoCA/index.txt.attr | 1 + .../test_docs/CAs/Root_11/demoCA/newcerts/1000.pem | 57 + .../test_docs/CAs/Root_11/demoCA/newcerts/1002.pem | 60 + .../test_docs/CAs/Root_11/demoCA/newcerts/1003.pem | 60 + .../test_docs/CAs/Root_11/demoCA/newcerts/1004.pem | 60 + .../test_docs/CAs/Root_11/demoCA/newcerts/1005.pem | 61 + .../test_docs/CAs/Root_11/demoCA/newcerts/1006.pem | 61 + .../test_docs/CAs/Root_11/demoCA/newcerts/1007.pem | 60 + .../test_docs/CAs/Root_11/demoCA/newcerts/1008.pem | 60 + .../test_docs/CAs/Root_11/demoCA/newcerts/1009.pem | 60 + .../test_docs/CAs/Root_11/demoCA/newcerts/100A.pem | 61 + .../test_docs/CAs/Root_11/demoCA/newcerts/100B.pem | 61 + .../test_docs/CAs/Root_11/demoCA/newcerts/100C.pem | 61 + .../test_docs/CAs/Root_11/demoCA/newcerts/100D.pem | 61 + .../test_docs/CAs/Root_11/demoCA/newcerts/100E.pem | 61 + .../test_docs/CAs/Root_11/demoCA/newcerts/100F.pem | 61 + .../test_docs/CAs/Root_11/demoCA/newcerts/1010.pem | 60 + .../test_docs/CAs/Root_11/demoCA/newcerts/1011.pem | 61 + .../test_docs/CAs/Root_11/demoCA/newcerts/1012.pem | 61 + .../test_docs/CAs/Root_11/demoCA/newcerts/1013.pem | 60 + .../test_docs/CAs/Root_11/demoCA/newcerts/1014.pem | 60 + .../test_docs/CAs/Root_11/demoCA/newcerts/1015.pem | 60 + .../test_docs/CAs/Root_11/demoCA/newcerts/1016.pem | 61 + .../test_docs/CAs/Root_11/demoCA/newcerts/1017.pem | 61 + .../test_docs/CAs/Root_11/demoCA/newcerts/1018.pem | 61 + .../test_docs/CAs/Root_11/demoCA/newcerts/1019.pem | 61 + .../test_docs/CAs/Root_11/demoCA/newcerts/101A.pem | 61 + .../test_docs/CAs/Root_11/demoCA/newcerts/101B.pem | 61 + .../test_docs/CAs/Root_11/demoCA/newcerts/101C.pem | 60 + .../test_docs/CAs/Root_11/demoCA/newcerts/101D.pem | 60 + .../test_docs/CAs/Root_11/demoCA/newcerts/101E.pem | 60 + .../test_docs/CAs/Root_11/demoCA/newcerts/101F.pem | 60 + .../test_docs/CAs/Root_11/demoCA/newcerts/1020.pem | 61 + .../test_docs/CAs/Root_11/demoCA/newcerts/1021.pem | 61 + .../test_docs/CAs/Root_11/demoCA/newcerts/1022.pem | 64 + .../test_docs/CAs/Root_11/demoCA/private/cakey.pem | 18 + xmlsecurity/test_docs/CAs/Root_11/demoCA/serial | 1 + xmlsecurity/test_docs/CAs/Root_11/openssl.cfg | 298 ++ xmlsecurity/test_docs/CAs/Root_2/demoCA/cacert.pem | 19 + .../CAs/Root_2/demoCA/crl/DO_NOT_CREATE_A_CRL | 0 xmlsecurity/test_docs/CAs/Root_2/demoCA/crlnumber | 1 + xmlsecurity/test_docs/CAs/Root_2/demoCA/index.txt | 1 + .../test_docs/CAs/Root_2/demoCA/index.txt.attr | 1 + .../test_docs/CAs/Root_2/demoCA/newcerts/1000.pem | 62 + .../test_docs/CAs/Root_2/demoCA/private/cakey.pem | 18 + xmlsecurity/test_docs/CAs/Root_2/demoCA/serial | 1 + xmlsecurity/test_docs/CAs/Root_2/openssl.cfg | 292 ++ xmlsecurity/test_docs/CAs/Root_3/demoCA/cacert.pem | 19 + xmlsecurity/test_docs/CAs/Root_3/demoCA/crlnumber | 1 + xmlsecurity/test_docs/CAs/Root_3/demoCA/index.txt | 1 + .../test_docs/CAs/Root_3/demoCA/index.txt.attr | 1 + .../test_docs/CAs/Root_3/demoCA/newcerts/1000.pem | 62 + .../test_docs/CAs/Root_3/demoCA/private/cakey.pem | 18 + xmlsecurity/test_docs/CAs/Root_3/demoCA/serial | 1 + xmlsecurity/test_docs/CAs/Root_3/openssl.cfg | 292 ++ xmlsecurity/test_docs/CAs/Root_4/README.txt | 4 + xmlsecurity/test_docs/CAs/Root_4/demoCA/cacert.pem | 19 + xmlsecurity/test_docs/CAs/Root_4/demoCA/crlnumber | 1 + xmlsecurity/test_docs/CAs/Root_4/demoCA/index.txt | 2 + .../test_docs/CAs/Root_4/demoCA/index.txt.attr | 1 + .../test_docs/CAs/Root_4/demoCA/newcerts/1000.pem | 62 + .../test_docs/CAs/Root_4/demoCA/newcerts/1001.pem | 62 + .../test_docs/CAs/Root_4/demoCA/private/cakey.pem | 18 + xmlsecurity/test_docs/CAs/Root_4/demoCA/serial | 1 + xmlsecurity/test_docs/CAs/Root_4/openssl.cfg | 292 ++ xmlsecurity/test_docs/CAs/Root_5/demoCA/cacert.pem | 19 + .../CAs/Root_5/demoCA/crl/DO_NOT_CREATE_A_CRL | 0 xmlsecurity/test_docs/CAs/Root_5/demoCA/crlnumber | 1 + xmlsecurity/test_docs/CAs/Root_5/demoCA/index.txt | 1 + .../test_docs/CAs/Root_5/demoCA/index.txt.attr | 1 + .../test_docs/CAs/Root_5/demoCA/newcerts/1001.pem | 66 + .../test_docs/CAs/Root_5/demoCA/private/cakey.pem | 18 + xmlsecurity/test_docs/CAs/Root_5/demoCA/serial | 1 + xmlsecurity/test_docs/CAs/Root_5/openssl.cfg | 292 ++ xmlsecurity/test_docs/CAs/Root_6/README.txt | 5 + xmlsecurity/test_docs/CAs/Root_6/demoCA/cacert.pem | 19 + .../CAs/Root_6/demoCA/crl/DO_NOT_INSTALL_THIS_CRL | 0 .../test_docs/CAs/Root_6/demoCA/crl/Root_6.crl | Bin 0 -> 316 bytes xmlsecurity/test_docs/CAs/Root_6/demoCA/crlnumber | 1 + xmlsecurity/test_docs/CAs/Root_6/demoCA/index.txt | 1 + .../test_docs/CAs/Root_6/demoCA/index.txt.attr | 1 + .../test_docs/CAs/Root_6/demoCA/newcerts/1001.pem | 66 + .../test_docs/CAs/Root_6/demoCA/private/cakey.pem | 18 + xmlsecurity/test_docs/CAs/Root_6/demoCA/serial | 1 + xmlsecurity/test_docs/CAs/Root_6/openssl.cfg | 292 ++ xmlsecurity/test_docs/CAs/Root_7/README.txt | 10 + xmlsecurity/test_docs/CAs/Root_7/demoCA/cacert.pem | 19 + .../CAs/Root_7/demoCA/crl/DO_NOT_INSTALL_THIS_CRL | 0 .../test_docs/CAs/Root_7/demoCA/crl/Root_7.crl | Bin 0 -> 353 bytes xmlsecurity/test_docs/CAs/Root_7/demoCA/crlnumber | 1 + xmlsecurity/test_docs/CAs/Root_7/demoCA/index.txt | 2 + .../test_docs/CAs/Root_7/demoCA/index.txt.attr | 1 + .../test_docs/CAs/Root_7/demoCA/newcerts/1000.pem | 66 + .../test_docs/CAs/Root_7/demoCA/newcerts/1001.pem | 66 + .../test_docs/CAs/Root_7/demoCA/private/cakey.pem | 18 + xmlsecurity/test_docs/CAs/Root_7/demoCA/serial | 1 + xmlsecurity/test_docs/CAs/Root_7/openssl.cfg | 292 ++ xmlsecurity/test_docs/CAs/Root_8/README.txt | 9 + xmlsecurity/test_docs/CAs/Root_8/demoCA/cacert.pem | 19 + .../CAs/Root_8/demoCA/crl/DO_NOT_INSTALL_THIS_CRL | 0 .../test_docs/CAs/Root_8/demoCA/crl/Root_8.crl | Bin 0 -> 353 bytes xmlsecurity/test_docs/CAs/Root_8/demoCA/crlnumber | 1 + xmlsecurity/test_docs/CAs/Root_8/demoCA/index.txt | 2 + .../test_docs/CAs/Root_8/demoCA/index.txt.attr | 1 + .../test_docs/CAs/Root_8/demoCA/newcerts/1000.pem | 66 + .../test_docs/CAs/Root_8/demoCA/newcerts/1001.pem | 66 + .../test_docs/CAs/Root_8/demoCA/private/cakey.pem | 18 + xmlsecurity/test_docs/CAs/Root_8/demoCA/serial | 1 + xmlsecurity/test_docs/CAs/Root_8/openssl.cfg | 292 ++ .../CAs/Root_9/DO_NOT_INSTALL_THIS_ROOT_CERT.txt | 1 + .../demoCA/DO_NO_INSTALL_THIS_ROOT_CERTIFICATE | 0 xmlsecurity/test_docs/CAs/Root_9/demoCA/Root_9.crt | Bin 0 -> 776 bytes xmlsecurity/test_docs/CAs/Root_9/demoCA/cacert.pem | 19 + xmlsecurity/test_docs/CAs/Root_9/demoCA/crlnumber | 1 + xmlsecurity/test_docs/CAs/Root_9/demoCA/index.txt | 1 + .../test_docs/CAs/Root_9/demoCA/index.txt.attr | 1 + .../test_docs/CAs/Root_9/demoCA/newcerts/1000.pem | 62 + .../test_docs/CAs/Root_9/demoCA/private/cakey.pem | 18 + xmlsecurity/test_docs/CAs/Root_9/demoCA/serial | 1 + xmlsecurity/test_docs/CAs/Root_9/openssl.cfg | 292 ++ .../CAs/Sub_CA_1_Root_1/demoCA/cacert.pem | 62 + .../Sub_CA_1_Root_1/demoCA/crl/DO_NOT_CREATE_A_CRL | 0 .../test_docs/CAs/Sub_CA_1_Root_1/demoCA/crlnumber | 1 + .../test_docs/CAs/Sub_CA_1_Root_1/demoCA/index.txt | 1 + .../CAs/Sub_CA_1_Root_1/demoCA/index.txt.attr | 1 + .../CAs/Sub_CA_1_Root_1/demoCA/newcerts/1000.pem | 58 + .../CAs/Sub_CA_1_Root_1/demoCA/private/cakey.pem | 18 + .../test_docs/CAs/Sub_CA_1_Root_1/demoCA/serial | 1 + .../test_docs/CAs/Sub_CA_1_Root_1/openssl.cfg | 292 ++ .../DO_NOT_INSTALL_THIS_CERTIFICATE | 0 .../test_docs/CAs/Sub_CA_1_Root_10/README.txt | 19 + .../demoCA/DO_NOT_INSTALL_THIS_CERTIFICATE | 0 .../Sub_CA_1_Root_10/demoCA/Sub_CA_1_Root_10.crt | Bin 0 -> 781 bytes .../CAs/Sub_CA_1_Root_10/demoCA/cacert.pem | 62 + .../demoCA/crl/DO_NOT_INSTALL_THIS_CRL | 0 .../demoCA/crl/Sub_CA_1_Root_10.crl | Bin 0 -> 326 bytes .../CAs/Sub_CA_1_Root_10/demoCA/crlnumber | 1 + .../CAs/Sub_CA_1_Root_10/demoCA/index.txt | 1 + .../CAs/Sub_CA_1_Root_10/demoCA/index.txt.attr | 1 + .../CAs/Sub_CA_1_Root_10/demoCA/newcerts/1000.pem | 67 + .../CAs/Sub_CA_1_Root_10/demoCA/private/cakey.pem | 18 + .../test_docs/CAs/Sub_CA_1_Root_10/demoCA/serial | 1 + .../test_docs/CAs/Sub_CA_1_Root_10/openssl.cfg | 293 ++ .../CAs/Sub_CA_1_Root_2/demoCA/cacert.pem | 62 + .../test_docs/CAs/Sub_CA_1_Root_2/demoCA/crlnumber | 1 + .../test_docs/CAs/Sub_CA_1_Root_2/demoCA/index.txt | 1 + .../CAs/Sub_CA_1_Root_2/demoCA/index.txt.attr | 1 + .../CAs/Sub_CA_1_Root_2/demoCA/newcerts/1000.pem | 60 + .../CAs/Sub_CA_1_Root_2/demoCA/private/cakey.pem | 18 + .../test_docs/CAs/Sub_CA_1_Root_2/demoCA/req.pem | 11 + .../test_docs/CAs/Sub_CA_1_Root_2/demoCA/serial | 1 + .../test_docs/CAs/Sub_CA_1_Root_2/openssl.cfg | 292 ++ .../CAs/Sub_CA_1_Root_3/demoCA/cacert.pem | 62 + .../Sub_CA_1_Root_3/demoCA/crl/DO_NOT_CREATE_A_CRL | 0 .../test_docs/CAs/Sub_CA_1_Root_3/demoCA/crlnumber | 1 + .../test_docs/CAs/Sub_CA_1_Root_3/demoCA/index.txt | 1 + .../CAs/Sub_CA_1_Root_3/demoCA/index.txt.attr | 1 + .../CAs/Sub_CA_1_Root_3/demoCA/newcerts/1000.pem | 60 + .../CAs/Sub_CA_1_Root_3/demoCA/private/cakey.pem | 18 + .../test_docs/CAs/Sub_CA_1_Root_3/demoCA/req.pem | 11 + .../test_docs/CAs/Sub_CA_1_Root_3/demoCA/serial | 1 + .../test_docs/CAs/Sub_CA_1_Root_3/openssl.cfg | 292 ++ .../test_docs/CAs/Sub_CA_1_Root_4/README.txt | 4 + .../CAs/Sub_CA_1_Root_4/demoCA/cacert.pem | 62 + .../test_docs/CAs/Sub_CA_1_Root_4/demoCA/crlnumber | 1 + .../test_docs/CAs/Sub_CA_1_Root_4/demoCA/index.txt | 2 + .../CAs/Sub_CA_1_Root_4/demoCA/index.txt.attr | 1 + .../CAs/Sub_CA_1_Root_4/demoCA/newcerts/1000.pem | 60 + .../CAs/Sub_CA_1_Root_4/demoCA/newcerts/1001.pem | 60 + .../CAs/Sub_CA_1_Root_4/demoCA/private/cakey.pem | 18 + .../test_docs/CAs/Sub_CA_1_Root_4/demoCA/serial | 1 + .../test_docs/CAs/Sub_CA_1_Root_4/openssl.cfg | 292 ++ .../test_docs/CAs/Sub_CA_1_Root_5/README.txt | 5 + .../CAs/Sub_CA_1_Root_5/demoCA/cacert.pem | 66 + .../demoCA/crl/DO_NOT_INSTALL_THIS_CRL | 0 .../Sub_CA_1_Root_5/demoCA/crl/Sub_CA_1_Root_5.crl | Bin 0 -> 325 bytes .../test_docs/CAs/Sub_CA_1_Root_5/demoCA/crlnumber | 1 + .../test_docs/CAs/Sub_CA_1_Root_5/demoCA/index.txt | 1 + .../CAs/Sub_CA_1_Root_5/demoCA/index.txt.attr | 1 + .../CAs/Sub_CA_1_Root_5/demoCA/newcerts/1002.pem | 62 + .../CAs/Sub_CA_1_Root_5/demoCA/private/cakey.pem | 18 + .../test_docs/CAs/Sub_CA_1_Root_5/demoCA/serial | 1 + .../test_docs/CAs/Sub_CA_1_Root_5/openssl.cfg | 292 ++ .../CAs/Sub_CA_1_Root_6/demoCA/cacert.pem | 66 + .../Sub_CA_1_Root_6/demoCA/crl/DO_NOT_CREATE_A_CRL | 0 .../test_docs/CAs/Sub_CA_1_Root_6/demoCA/crlnumber | 1 + .../test_docs/CAs/Sub_CA_1_Root_6/demoCA/index.txt | 1 + .../CAs/Sub_CA_1_Root_6/demoCA/index.txt.attr | 1 + .../CAs/Sub_CA_1_Root_6/demoCA/newcerts/1000.pem | 62 + .../CAs/Sub_CA_1_Root_6/demoCA/private/cakey.pem | 18 + .../test_docs/CAs/Sub_CA_1_Root_6/demoCA/serial | 1 + .../test_docs/CAs/Sub_CA_1_Root_6/openssl.cfg | 292 ++ .../test_docs/CAs/Sub_CA_1_Root_7/README.txt | 3 + .../CAs/Sub_CA_1_Root_7/demoCA/cacert.pem | 66 + .../demoCA/crl/DO_NOT_INSTALL_THIS_CRL | 0 .../Sub_CA_1_Root_7/demoCA/crl/Sub_CA_1_Root_7.crl | Bin 0 -> 362 bytes .../test_docs/CAs/Sub_CA_1_Root_7/demoCA/crlnumber | 1 + .../test_docs/CAs/Sub_CA_1_Root_7/demoCA/index.txt | 2 + .../CAs/Sub_CA_1_Root_7/demoCA/index.txt.attr | 1 + .../CAs/Sub_CA_1_Root_7/demoCA/newcerts/1000.pem | 62 + .../CAs/Sub_CA_1_Root_7/demoCA/newcerts/1001.pem | 62 + .../CAs/Sub_CA_1_Root_7/demoCA/private/cakey.pem | 18 + .../test_docs/CAs/Sub_CA_1_Root_7/demoCA/serial | 1 + .../test_docs/CAs/Sub_CA_1_Root_7/openssl.cfg | 292 ++ .../test_docs/CAs/Sub_CA_1_Root_8/README.txt | 13 + .../CAs/Sub_CA_1_Root_8/demoCA/cacert.pem | 66 + .../demoCA/crl/DO_NOT_INSTALL_THIS_CRL | 0 .../Sub_CA_1_Root_8/demoCA/crl/Sub_CA_1_Root_8.crl | Bin 0 -> 362 bytes .../test_docs/CAs/Sub_CA_1_Root_8/demoCA/crlnumber | 1 + .../test_docs/CAs/Sub_CA_1_Root_8/demoCA/index.txt | 2 + .../CAs/Sub_CA_1_Root_8/demoCA/index.txt.attr | 1 + .../CAs/Sub_CA_1_Root_8/demoCA/newcerts/1000.pem | 62 + .../CAs/Sub_CA_1_Root_8/demoCA/newcerts/1001.pem | 62 + .../CAs/Sub_CA_1_Root_8/demoCA/private/cakey.pem | 18 + .../test_docs/CAs/Sub_CA_1_Root_8/demoCA/serial | 1 + .../test_docs/CAs/Sub_CA_1_Root_8/openssl.cfg | 292 ++ .../CAs/Sub_CA_1_Root_9/demoCA/cacert.pem | 62 + .../test_docs/CAs/Sub_CA_1_Root_9/demoCA/crlnumber | 1 + .../test_docs/CAs/Sub_CA_1_Root_9/demoCA/index.txt | 1 + .../CAs/Sub_CA_1_Root_9/demoCA/index.txt.attr | 1 + .../CAs/Sub_CA_1_Root_9/demoCA/newcerts/1000.pem | 58 + .../CAs/Sub_CA_1_Root_9/demoCA/private/cakey.pem | 18 + .../test_docs/CAs/Sub_CA_1_Root_9/demoCA/serial | 1 + .../test_docs/CAs/Sub_CA_1_Root_9/openssl.cfg | 292 ++ .../test_docs/CAs/Sub_CA_2_Root_4/README.txt | 4 + .../CAs/Sub_CA_2_Root_4/demoCA/cacert.pem | 62 + .../test_docs/CAs/Sub_CA_2_Root_4/demoCA/crlnumber | 1 + .../test_docs/CAs/Sub_CA_2_Root_4/demoCA/index.txt | 2 + .../CAs/Sub_CA_2_Root_4/demoCA/index.txt.attr | 1 + .../CAs/Sub_CA_2_Root_4/demoCA/newcerts/1001.pem | 60 + .../CAs/Sub_CA_2_Root_4/demoCA/newcerts/1002.pem | 60 + .../CAs/Sub_CA_2_Root_4/demoCA/private/cakey.pem | 18 + .../test_docs/CAs/Sub_CA_2_Root_4/demoCA/serial | 1 + .../test_docs/CAs/Sub_CA_2_Root_4/openssl.cfg | 292 ++ .../test_docs/CAs/Sub_CA_2_Root_7/README.txt | 12 + .../CAs/Sub_CA_2_Root_7/demoCA/cacert.pem | 66 + .../demoCA/crl/DO_NOT_INSTALL_THIS_CRL | 0 .../Sub_CA_2_Root_7/demoCA/crl/Sub_CA_2_Root_7.crl | Bin 0 -> 362 bytes .../test_docs/CAs/Sub_CA_2_Root_7/demoCA/crlnumber | 1 + .../test_docs/CAs/Sub_CA_2_Root_7/demoCA/index.txt | 2 + .../CAs/Sub_CA_2_Root_7/demoCA/index.txt.attr | 1 + .../CAs/Sub_CA_2_Root_7/demoCA/newcerts/1000.pem | 62 + .../CAs/Sub_CA_2_Root_7/demoCA/newcerts/1001.pem | 62 + .../CAs/Sub_CA_2_Root_7/demoCA/private/cakey.pem | 18 + .../test_docs/CAs/Sub_CA_2_Root_7/demoCA/serial | 1 + .../test_docs/CAs/Sub_CA_2_Root_7/openssl.cfg | 292 ++ .../test_docs/CAs/Sub_CA_2_Root_8/README.txt | 13 + .../CAs/Sub_CA_2_Root_8/demoCA/cacert.pem | 66 + .../demoCA/crl/DO_NOT_INSTALL_THIS_CRL | 0 .../Sub_CA_2_Root_8/demoCA/crl/Sub_CA_2_Root_8.crl | Bin 0 -> 362 bytes .../test_docs/CAs/Sub_CA_2_Root_8/demoCA/crlnumber | 1 + .../test_docs/CAs/Sub_CA_2_Root_8/demoCA/index.txt | 2 + .../CAs/Sub_CA_2_Root_8/demoCA/index.txt.attr | 1 + .../CAs/Sub_CA_2_Root_8/demoCA/newcerts/1002.pem | 62 + .../CAs/Sub_CA_2_Root_8/demoCA/newcerts/1003.pem | 62 + .../CAs/Sub_CA_2_Root_8/demoCA/private/cakey.pem | 18 + .../test_docs/CAs/Sub_CA_2_Root_8/demoCA/serial | 1 + .../test_docs/CAs/Sub_CA_2_Root_8/openssl.cfg | 292 ++ xmlsecurity/test_docs/certs/ca_certs/Root_1.crt | Bin 0 -> 776 bytes xmlsecurity/test_docs/certs/ca_certs/Root_10.crt | Bin 0 -> 779 bytes xmlsecurity/test_docs/certs/ca_certs/Root_11.crt | Bin 0 -> 779 bytes xmlsecurity/test_docs/certs/ca_certs/Root_2.crt | Bin 0 -> 776 bytes xmlsecurity/test_docs/certs/ca_certs/Root_3.crt | Bin 0 -> 776 bytes xmlsecurity/test_docs/certs/ca_certs/Root_4.crt | Bin 0 -> 776 bytes xmlsecurity/test_docs/certs/ca_certs/Root_5.crt | Bin 0 -> 776 bytes xmlsecurity/test_docs/certs/ca_certs/Root_6.crt | Bin 0 -> 776 bytes xmlsecurity/test_docs/certs/ca_certs/Root_7.crt | Bin 0 -> 776 bytes xmlsecurity/test_docs/certs/ca_certs/Root_8.crt | Bin 0 -> 776 bytes .../test_docs/certs/ca_certs/Sub_CA_1_Root_1.crt | Bin 0 -> 778 bytes .../test_docs/certs/ca_certs/Sub_CA_1_Root_2.crt | Bin 0 -> 778 bytes .../test_docs/certs/ca_certs/Sub_CA_1_Root_3.crt | Bin 0 -> 778 bytes .../test_docs/certs/ca_certs/Sub_CA_1_Root_4.crt | Bin 0 -> 778 bytes .../test_docs/certs/ca_certs/Sub_CA_1_Root_5.crt | Bin 0 -> 842 bytes .../test_docs/certs/ca_certs/Sub_CA_1_Root_6.crt | Bin 0 -> 842 bytes .../test_docs/certs/ca_certs/Sub_CA_1_Root_7.crt | Bin 0 -> 842 bytes .../test_docs/certs/ca_certs/Sub_CA_1_Root_8.crt | Bin 0 -> 829 bytes .../test_docs/certs/ca_certs/Sub_CA_1_Root_9.crt | Bin 0 -> 778 bytes .../test_docs/certs/ca_certs/Sub_CA_2_Root_4.crt | Bin 0 -> 778 bytes .../test_docs/certs/ca_certs/Sub_CA_2_Root_7.crt | Bin 0 -> 842 bytes .../test_docs/certs/ca_certs/Sub_CA_2_Root_8.crt | Bin 0 -> 829 bytes xmlsecurity/test_docs/certs/crl/Root_10.crl | Bin 0 -> 317 bytes xmlsecurity/test_docs/certs/crl/Root_11.crl | Bin 0 -> 317 bytes xmlsecurity/test_docs/certs/crl/Root_3.crl | Bin 0 -> 316 bytes xmlsecurity/test_docs/certs/crl/Root_4.crl | Bin 0 -> 353 bytes xmlsecurity/test_docs/certs/crl/Root_9.crl | Bin 0 -> 316 bytes .../test_docs/certs/crl/Sub_CA_1_Root_2.crl | Bin 0 -> 325 bytes .../test_docs/certs/crl/Sub_CA_1_Root_4.crl | Bin 0 -> 362 bytes .../test_docs/certs/crl/Sub_CA_1_Root_9.crl | Bin 0 -> 325 bytes .../test_docs/certs/crl/Sub_CA_2_Root_4.crl | Bin 0 -> 362 bytes .../test_docs/certs/end_certs/User_10_Root_11.crt | Bin 0 -> 739 bytes .../test_docs/certs/end_certs/User_11_Root_11.crt | Bin 0 -> 733 bytes .../test_docs/certs/end_certs/User_12_Root_11.crt | Bin 0 -> 729 bytes .../test_docs/certs/end_certs/User_13_Root_11.crt | Bin 0 -> 739 bytes .../test_docs/certs/end_certs/User_14_Root_11.crt | Bin 0 -> 729 bytes .../test_docs/certs/end_certs/User_15_Root_11.crt | Bin 0 -> 720 bytes .../test_docs/certs/end_certs/User_16_Root_11.crt | Bin 0 -> 739 bytes .../test_docs/certs/end_certs/User_17_Root_11.crt | Bin 0 -> 749 bytes .../test_docs/certs/end_certs/User_18_Root_11.crt | Bin 0 -> 714 bytes .../test_docs/certs/end_certs/User_19_Root_11.crt | Bin 0 -> 710 bytes .../test_docs/certs/end_certs/User_1_Root_11.crt | Bin 0 -> 699 bytes .../certs/end_certs/User_1_Sub_CA_1_Root_1.crt | Bin 0 -> 706 bytes .../certs/end_certs/User_1_Sub_CA_1_Root_10.crt | Bin 0 -> 828 bytes .../certs/end_certs/User_1_Sub_CA_1_Root_2.crt | Bin 0 -> 719 bytes .../certs/end_certs/User_1_Sub_CA_1_Root_3.crt | Bin 0 -> 719 bytes .../certs/end_certs/User_1_Sub_CA_1_Root_4.crt | Bin 0 -> 719 bytes .../certs/end_certs/User_1_Sub_CA_1_Root_5.crt | Bin 0 -> 746 bytes .../certs/end_certs/User_1_Sub_CA_1_Root_6.crt | Bin 0 -> 746 bytes .../certs/end_certs/User_1_Sub_CA_1_Root_7.crt | Bin 0 -> 746 bytes .../certs/end_certs/User_1_Sub_CA_1_Root_8.crt | Bin 0 -> 726 bytes .../certs/end_certs/User_1_Sub_CA_1_Root_9.crt | Bin 0 -> 673 bytes .../certs/end_certs/User_1_Sub_CA_2_Root_4.crt | Bin 0 -> 719 bytes .../certs/end_certs/User_1_Sub_CA_2_Root_7.crt | Bin 0 -> 746 bytes .../certs/end_certs/User_1_Sub_CA_2_Root_8.crt | Bin 0 -> 726 bytes .../test_docs/certs/end_certs/User_20_Root_11.crt | Bin 0 -> 710 bytes .../test_docs/certs/end_certs/User_21_Root_11.crt | Bin 0 -> 727 bytes .../test_docs/certs/end_certs/User_22_Root_11.crt | Bin 0 -> 739 bytes .../test_docs/certs/end_certs/User_23_Root_11.crt | Bin 0 -> 733 bytes .../test_docs/certs/end_certs/User_24_Root_11.crt | Bin 0 -> 729 bytes .../test_docs/certs/end_certs/User_25_Root_11.crt | Bin 0 -> 737 bytes .../test_docs/certs/end_certs/User_26_Root_11.crt | Bin 0 -> 729 bytes .../test_docs/certs/end_certs/User_27_Root_11.crt | Bin 0 -> 705 bytes .../test_docs/certs/end_certs/User_28_Root_11.crt | Bin 0 -> 700 bytes .../test_docs/certs/end_certs/User_29_Root_11.crt | Bin 0 -> 698 bytes .../test_docs/certs/end_certs/User_2_Root_11.crt | Bin 0 -> 695 bytes .../certs/end_certs/User_2_Sub_CA_1_Root_4.crt | Bin 0 -> 719 bytes .../certs/end_certs/User_2_Sub_CA_1_Root_7.crt | Bin 0 -> 746 bytes .../certs/end_certs/User_2_Sub_CA_1_Root_8.crt | Bin 0 -> 726 bytes .../certs/end_certs/User_2_Sub_CA_2_Root_4.crt | Bin 0 -> 719 bytes .../certs/end_certs/User_2_Sub_CA_2_Root_7.crt | Bin 0 -> 746 bytes .../certs/end_certs/User_2_Sub_CA_2_Root_8.crt | Bin 0 -> 726 bytes .../test_docs/certs/end_certs/User_30_Root_11.crt | Bin 0 -> 716 bytes .../test_docs/certs/end_certs/User_31_Root_11.crt | Bin 0 -> 745 bytes .../test_docs/certs/end_certs/User_32_Root_11.crt | Bin 0 -> 591 bytes .../test_docs/certs/end_certs/User_33_Root_11.crt | Bin 0 -> 620 bytes .../test_docs/certs/end_certs/User_34_Root_11.crt | Bin 0 -> 637 bytes .../test_docs/certs/end_certs/User_35_Root_11.crt | 64 + .../test_docs/certs/end_certs/User_3_Root_11.crt | Bin 0 -> 719 bytes .../test_docs/certs/end_certs/User_4_Root_11.crt | Bin 0 -> 738 bytes .../test_docs/certs/end_certs/User_5_Root_11.crt | Bin 0 -> 748 bytes .../test_docs/certs/end_certs/User_6_Root_11.crt | Bin 0 -> 713 bytes .../test_docs/certs/end_certs/User_7_Root_11.crt | Bin 0 -> 709 bytes .../test_docs/certs/end_certs/User_8_Root_11.crt | Bin 0 -> 709 bytes .../test_docs/certs/end_certs/User_9_Root_11.crt | Bin 0 -> 726 bytes xmlsecurity/test_docs/certs/p12/Root_11.p12 | Bin 0 -> 1797 bytes .../test_docs/certs/p12/User_10_Root_11.p12 | Bin 0 -> 1757 bytes .../test_docs/certs/p12/User_11_Root_11.p12 | Bin 0 -> 1749 bytes .../test_docs/certs/p12/User_12_Root_11.p12 | Bin 0 -> 1749 bytes .../test_docs/certs/p12/User_13_Root_11.p12 | Bin 0 -> 1757 bytes .../test_docs/certs/p12/User_14_Root_11.p12 | Bin 0 -> 1749 bytes .../test_docs/certs/p12/User_15_Root_11.p12 | Bin 0 -> 1741 bytes .../test_docs/certs/p12/User_16_Root_11.p12 | Bin 0 -> 1757 bytes .../test_docs/certs/p12/User_17_Root_11.p12 | Bin 0 -> 1765 bytes .../test_docs/certs/p12/User_18_Root_11.p12 | Bin 0 -> 1733 bytes .../test_docs/certs/p12/User_19_Root_11.p12 | Bin 0 -> 1725 bytes xmlsecurity/test_docs/certs/p12/User_1_Root_11.p12 | Bin 0 -> 1717 bytes .../test_docs/certs/p12/User_1_Sub_CA_1_Root_1.p12 | Bin 0 -> 1725 bytes .../certs/p12/User_1_Sub_CA_1_Root_10.p12 | Bin 0 -> 1845 bytes .../test_docs/certs/p12/User_1_Sub_CA_1_Root_2.p12 | Bin 0 -> 1733 bytes .../test_docs/certs/p12/User_1_Sub_CA_1_Root_3.p12 | Bin 0 -> 1733 bytes .../test_docs/certs/p12/User_1_Sub_CA_1_Root_4.p12 | Bin 0 -> 1733 bytes .../test_docs/certs/p12/User_1_Sub_CA_1_Root_5.p12 | Bin 0 -> 1765 bytes .../test_docs/certs/p12/User_1_Sub_CA_1_Root_6.p12 | Bin 0 -> 1765 bytes .../test_docs/certs/p12/User_1_Sub_CA_1_Root_7.p12 | Bin 0 -> 1765 bytes .../test_docs/certs/p12/User_1_Sub_CA_1_Root_8.p12 | Bin 0 -> 1741 bytes .../test_docs/certs/p12/User_1_Sub_CA_1_Root_9.p12 | Bin 0 -> 1693 bytes .../test_docs/certs/p12/User_1_Sub_CA_2_Root_4.p12 | Bin 0 -> 1733 bytes .../test_docs/certs/p12/User_1_Sub_CA_2_Root_7.p12 | Bin 0 -> 1765 bytes .../test_docs/certs/p12/User_1_Sub_CA_2_Root_8.p12 | Bin 0 -> 1741 bytes .../test_docs/certs/p12/User_20_Root_11.p12 | Bin 0 -> 1725 bytes .../test_docs/certs/p12/User_21_Root_11.p12 | Bin 0 -> 1741 bytes .../test_docs/certs/p12/User_22_Root_11.p12 | Bin 0 -> 1757 bytes .../test_docs/certs/p12/User_23_Root_11.p12 | Bin 0 -> 1749 bytes .../test_docs/certs/p12/User_24_Root_11.p12 | Bin 0 -> 1749 bytes .../test_docs/certs/p12/User_25_Root_11.p12 | Bin 0 -> 1757 bytes .../test_docs/certs/p12/User_26_Root_11.p12 | Bin 0 -> 1749 bytes .../test_docs/certs/p12/User_27_Root_11.p12 | Bin 0 -> 1725 bytes .../test_docs/certs/p12/User_28_Root_11.p12 | Bin 0 -> 1717 bytes .../test_docs/certs/p12/User_29_Root_11.p12 | Bin 0 -> 1717 bytes xmlsecurity/test_docs/certs/p12/User_2_Root_11.p12 | Bin 0 -> 1709 bytes .../test_docs/certs/p12/User_2_Sub_CA_1_Root_4.p12 | Bin 0 -> 1733 bytes .../test_docs/certs/p12/User_2_Sub_CA_1_Root_7.p12 | Bin 0 -> 1765 bytes .../test_docs/certs/p12/User_2_Sub_CA_1_Root_8.p12 | Bin 0 -> 1741 bytes .../test_docs/certs/p12/User_2_Sub_CA_2_Root_4.p12 | Bin 0 -> 1733 bytes .../test_docs/certs/p12/User_2_Sub_CA_2_Root_7.p12 | Bin 0 -> 1765 bytes .../test_docs/certs/p12/User_2_Sub_CA_2_Root_8.p12 | Bin 0 -> 1741 bytes .../test_docs/certs/p12/User_30_Root_11.p12 | Bin 0 -> 1733 bytes .../test_docs/certs/p12/User_31_Root_11.p12 | Bin 0 -> 1765 bytes .../test_docs/certs/p12/User_32_Root_11.p12 | Bin 0 -> 1605 bytes .../test_docs/certs/p12/User_33_Root_11.p12 | Bin 0 -> 1732 bytes .../test_docs/certs/p12/User_34_Root_11.p12 | Bin 0 -> 1714 bytes xmlsecurity/test_docs/certs/p12/User_3_Root_11.p12 | Bin 0 -> 1733 bytes xmlsecurity/test_docs/certs/p12/User_4_Root_11.p12 | Bin 0 -> 1757 bytes xmlsecurity/test_docs/certs/p12/User_5_Root_11.p12 | Bin 0 -> 1765 bytes xmlsecurity/test_docs/certs/p12/User_6_Root_11.p12 | Bin 0 -> 1733 bytes xmlsecurity/test_docs/certs/p12/User_7_Root_11.p12 | Bin 0 -> 1725 bytes xmlsecurity/test_docs/certs/p12/User_8_Root_11.p12 | Bin 0 -> 1725 bytes xmlsecurity/test_docs/certs/p12/User_9_Root_11.p12 | Bin 0 -> 1741 bytes xmlsecurity/test_docs/documents/aia_ca_issuers.odt | Bin 0 -> 9511 bytes xmlsecurity/test_docs/documents/aia_ocsp.odt | Bin 0 -> 9376 bytes .../test_docs/documents/aia_ocsp_revoked_chain.odt | Bin 0 -> 9370 bytes .../test_docs/documents/aia_ocsp_revoked_leaf.odt | Bin 0 -> 9379 bytes .../documents/aia_ocsp_revoked_leaf_chain.odt | Bin 0 -> 9378 bytes xmlsecurity/test_docs/documents/crl.odt | Bin 0 -> 9354 bytes .../test_docs/documents/crl_revoked_chain.odt | Bin 0 -> 9352 bytes .../test_docs/documents/crl_revoked_leaf.odt | Bin 0 -> 9363 bytes .../test_docs/documents/crl_revoked_leaf_chain.odt | Bin 0 -> 9351 bytes xmlsecurity/test_docs/documents/crldp.odt | Bin 0 -> 9379 bytes .../crldp_no_intermediate_ca_revocation_info.odt | Bin 0 -> 9382 bytes .../documents/crldp_no_root_revocation_info.odt | Bin 0 -> 9379 bytes .../test_docs/documents/crldp_revoked_chain.odt | Bin 0 -> 9381 bytes .../test_docs/documents/crldp_revoked_leaf.odt | Bin 0 -> 9380 bytes .../documents/crldp_revoked_leaf_chain.odt | Bin 0 -> 9383 bytes .../test_docs/documents/dn_cyrillic_bmpstring.odt | Bin 0 -> 9392 bytes .../documents/dn_latin_ext_greak_bmpstring.odt | Bin 0 -> 9388 bytes .../test_docs/documents/dn_multivalue_rdn.odt | Bin 0 -> 9272 bytes xmlsecurity/test_docs/documents/dn_quoting.odt | Bin 0 -> 28429 bytes .../documents/dn_single_multivalue_rdn.odt | Bin 0 -> 9299 bytes .../dn_single_multivalue_rdn_with_quoting.odt | Bin 0 -> 9313 bytes .../test_docs/documents/incomplete_path.odt | Bin 0 -> 9308 bytes .../test_docs/documents/invalid_ooo2_x_doc1.odt | Bin 0 -> 9550 bytes .../test_docs/documents/invalid_ooo2_x_doc2.odt | Bin 0 -> 6989 bytes .../test_docs/documents/invalid_ooo2_x_macro1.odt | Bin 0 -> 12911 bytes .../test_docs/documents/invalid_ooo2_x_macro2.odt | Bin 0 -> 12929 bytes .../test_docs/documents/invalid_ooo2_x_macro3.odt | Bin 0 -> 13043 bytes .../test_docs/documents/invalid_ooo2_x_macro4.odt | Bin 0 -> 13079 bytes .../test_docs/documents/invalid_ooo2_x_macro5.odt | Bin 0 -> 20336 bytes .../test_docs/documents/invalid_ooo3_2_doc1.odt | Bin 0 -> 9200 bytes .../test_docs/documents/invalid_ooo3_2_doc3.odt | Bin 0 -> 8908 bytes .../test_docs/documents/invalid_ooo3_2_doc4.odt | Bin 0 -> 8997 bytes .../test_docs/documents/invalid_ooo_3_2_doc2.odt | Bin 0 -> 9199 bytes xmlsecurity/test_docs/documents/ocsp_crl.odt | Bin 0 -> 9444 bytes .../test_docs/documents/ocsp_crl_revoked_leaf.odt | Bin 0 -> 9447 bytes .../test_docs/documents/stateOrProvinceName.odt | Bin 0 -> 10534 bytes .../test_docs/documents/valid_no_revocation.odt | Bin 0 -> 9341 bytes .../documents/valid_no_root_revocation_info.odt | Bin 0 -> 9349 bytes .../documents/valid_no_sub_ca_revocation_info.odt | Bin 0 -> 9352 bytes .../test_docs/documents/valid_ooo2_x_doc1.odt | Bin 0 -> 9880 bytes .../test_docs/documents/valid_ooo2_x_doc_macro.odt | Bin 0 -> 12425 bytes .../documents/valid_ooo2_x_doc_unsigned_macro.odt | Bin 0 -> 10821 bytes .../test_docs/documents/valid_ooo3_0_doc1.odt | Bin 0 -> 12565 bytes .../test_docs/documents/valid_ooo3_0_doc_macro.odt | Bin 0 -> 15656 bytes .../documents/valid_ooo3_0_doc_unsigned_macro.odt | Bin 0 -> 13975 bytes .../test_docs/documents/valid_ooo3_2_doc1.odt | Bin 0 -> 12514 bytes .../test_docs/documents/valid_ooo3_2_doc_macro.odt | Bin 0 -> 15579 bytes .../documents/valid_ooo3_2_doc_unsigned_macro.odt | Bin 0 -> 13929 bytes xmlsecurity/test_docs/test_description.odt | Bin 0 -> 25782 bytes xmlsecurity/test_docs/tools/README.txt | 24 + xmlsecurity/test_docs/tools/httpserv/build.xml | 79 + xmlsecurity/test_docs/tools/httpserv/manifest.mf | 3 + .../tools/httpserv/nbproject/build-impl.xml | 700 +++ .../tools/httpserv/nbproject/genfiles.properties | 9 + .../tools/httpserv/nbproject/project.properties | 65 + .../test_docs/tools/httpserv/nbproject/project.xml | 15 + .../tools/httpserv/src/httpserv/Main.java | 190 + xmlsecurity/uiconfig/ui/certdetails.ui | 119 + xmlsecurity/uiconfig/ui/certgeneral.ui | 254 ++ xmlsecurity/uiconfig/ui/certpage.ui | 196 + xmlsecurity/uiconfig/ui/digitalsignaturesdialog.ui | 508 +++ xmlsecurity/uiconfig/ui/macrosecuritydialog.ui | 208 + xmlsecurity/uiconfig/ui/securitylevelpage.ui | 160 + xmlsecurity/uiconfig/ui/securitytrustpage.ui | 392 ++ xmlsecurity/uiconfig/ui/selectcertificatedialog.ui | 324 ++ xmlsecurity/uiconfig/ui/viewcertdialog.ui | 227 + xmlsecurity/util/xmlsecurity.component | 31 + xmlsecurity/util/xmlsecurity.component.dds | 7 + xmlsecurity/util/xsec_xmlsec.component | 60 + xmlsecurity/util/xsec_xmlsec.component.gpg | 7 + xmlsecurity/util/xsec_xmlsec.component.nss | 7 + xmlsecurity/util/xsec_xmlsec.component.nss_mscrypt | 10 + xmlsecurity/workben/pdfverify.cxx | 216 + 701 files changed, 58117 insertions(+) create mode 100644 xmlsecurity/AllLangMoTarget_xsc.mk create mode 100644 xmlsecurity/CppunitTest_qa_certext.mk create mode 100644 xmlsecurity/CppunitTest_xmlsecurity_dialogs_test.mk create mode 100644 xmlsecurity/CppunitTest_xmlsecurity_pdfsigning.mk create mode 100644 xmlsecurity/CppunitTest_xmlsecurity_signing.mk create mode 100644 xmlsecurity/CppunitTest_xmlsecurity_signing2.mk create mode 100644 xmlsecurity/Executable_pdfverify.mk create mode 100644 xmlsecurity/IwyuFilter_xmlsecurity.yaml create mode 100644 xmlsecurity/Library_xmlsecurity.mk create mode 100644 xmlsecurity/Library_xsec_xmlsec.mk create mode 100644 xmlsecurity/Makefile create mode 100644 xmlsecurity/Module_xmlsecurity.mk create mode 100644 xmlsecurity/README.md create mode 100644 xmlsecurity/UIConfig_xmlsec.mk create mode 100644 xmlsecurity/doc/OpenDocumentSignatures-TestIntegration.odt create mode 100644 xmlsecurity/doc/OpenDocumentSignatures-Workflow.odg create mode 100644 xmlsecurity/doc/OpenDocumentSignatures.odt create mode 100644 xmlsecurity/doc/XMLSecurityFramework.odt create mode 100644 xmlsecurity/inc/UriBindingHelper.hxx create mode 100644 xmlsecurity/inc/biginteger.hxx create mode 100644 xmlsecurity/inc/bitmaps.hlst create mode 100644 xmlsecurity/inc/certificate.hxx create mode 100644 xmlsecurity/inc/certificatechooser.hxx create mode 100644 xmlsecurity/inc/certificateviewer.hxx create mode 100644 xmlsecurity/inc/digitalsignaturesdialog.hxx create mode 100644 xmlsecurity/inc/documentsignaturehelper.hxx create mode 100644 xmlsecurity/inc/documentsignaturemanager.hxx create mode 100644 xmlsecurity/inc/framework/saxeventkeeperimpl.hxx create mode 100644 xmlsecurity/inc/framework/securityengine.hxx create mode 100644 xmlsecurity/inc/framework/signaturecreatorimpl.hxx create mode 100644 xmlsecurity/inc/framework/signatureengine.hxx create mode 100644 xmlsecurity/inc/framework/signatureverifierimpl.hxx create mode 100644 xmlsecurity/inc/framework/xmlsignaturetemplateimpl.hxx create mode 100644 xmlsecurity/inc/gpg/SEInitializer.hxx create mode 100644 xmlsecurity/inc/gpg/xmlsignature_gpgimpl.hxx create mode 100644 xmlsecurity/inc/macrosecurity.hxx create mode 100644 xmlsecurity/inc/pch/precompiled_xmlsecurity.cxx create mode 100644 xmlsecurity/inc/pch/precompiled_xmlsecurity.hxx create mode 100644 xmlsecurity/inc/pch/precompiled_xsec_xmlsec.cxx create mode 100644 xmlsecurity/inc/pch/precompiled_xsec_xmlsec.hxx create mode 100644 xmlsecurity/inc/pdfsignaturehelper.hxx create mode 100644 xmlsecurity/inc/resourcemanager.hxx create mode 100644 xmlsecurity/inc/strings.hrc create mode 100644 xmlsecurity/inc/xmlsec-wrapper.h create mode 100644 xmlsecurity/inc/xmlsec/errorcallback.hxx create mode 100644 xmlsecurity/inc/xmlsec/saxhelper.hxx create mode 100644 xmlsecurity/inc/xmlsec/xmldocumentwrapper_xmlsecimpl.hxx create mode 100644 xmlsecurity/inc/xmlsec/xmlsec_init.hxx create mode 100644 xmlsecurity/inc/xmlsec/xmlstreamio.hxx create mode 100644 xmlsecurity/inc/xmlsecuritydllapi.h create mode 100644 xmlsecurity/inc/xmlsignaturehelper.hxx create mode 100644 xmlsecurity/inc/xsecctl.hxx create mode 100644 xmlsecurity/inc/xsecxmlsecdllapi.h create mode 100644 xmlsecurity/qa/certext/SanCertExt.cxx create mode 100644 xmlsecurity/qa/certext/User_35_Root_11.crt create mode 100755 xmlsecurity/qa/create-certs/create-certs.sh create mode 100644 xmlsecurity/qa/create-certs/create-dump-certs.sh create mode 100644 xmlsecurity/qa/create-certs/templates/intermediate.cnf create mode 100644 xmlsecurity/qa/create-certs/templates/root.cnf create mode 100644 xmlsecurity/qa/unit/data/xmlsecurity-dialogs-test.txt create mode 100644 xmlsecurity/qa/unit/pdfsigning/data/2good.pdf create mode 100644 xmlsecurity/qa/unit/pdfsigning/data/bad-cert-p1.pdf create mode 100644 xmlsecurity/qa/unit/pdfsigning/data/bad-cert-p3-stamp.pdf create mode 100644 xmlsecurity/qa/unit/pdfsigning/data/cr-comment.pdf create mode 100644 xmlsecurity/qa/unit/pdfsigning/data/dict-bool.pdf create mode 100644 xmlsecurity/qa/unit/pdfsigning/data/forcepoint16.pdf create mode 100644 xmlsecurity/qa/unit/pdfsigning/data/good-custom-magic.pdf create mode 100644 xmlsecurity/qa/unit/pdfsigning/data/good-non-detached.pdf create mode 100644 xmlsecurity/qa/unit/pdfsigning/data/good-pades.pdf create mode 100644 xmlsecurity/qa/unit/pdfsigning/data/good.pdf create mode 100644 xmlsecurity/qa/unit/pdfsigning/data/name-bracket.pdf create mode 100644 xmlsecurity/qa/unit/pdfsigning/data/no-eof.pdf create mode 100644 xmlsecurity/qa/unit/pdfsigning/data/no.pdf create mode 100644 xmlsecurity/qa/unit/pdfsigning/data/noeol.pdf create mode 100644 xmlsecurity/qa/unit/pdfsigning/data/partial-in-between.pdf create mode 100644 xmlsecurity/qa/unit/pdfsigning/data/partial.pdf create mode 100644 xmlsecurity/qa/unit/pdfsigning/data/pdf14adobe.pdf create mode 100644 xmlsecurity/qa/unit/pdfsigning/data/pdf14lowin.pdf create mode 100644 xmlsecurity/qa/unit/pdfsigning/data/pdf16adobe.pdf create mode 100644 xmlsecurity/qa/unit/pdfsigning/data/small.pdf create mode 100644 xmlsecurity/qa/unit/pdfsigning/data/tdf107149.pdf create mode 100644 xmlsecurity/qa/unit/pdfsigning/data/tdf107782.pdf create mode 100644 xmlsecurity/qa/unit/pdfsigning/data/tdf114460.pdf create mode 100644 xmlsecurity/qa/unit/pdfsigning/data/tdf145312.pdf create mode 100644 xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx create mode 100644 xmlsecurity/qa/unit/signing/data/02_doc_macros_signed_by_attacker_manipulated.odt create mode 100644 xmlsecurity/qa/unit/signing/data/02_doc_signed_by_attacker_manipulated.odt create mode 100644 xmlsecurity/qa/unit/signing/data/02_doc_signed_by_attacker_manipulated2.odt create mode 100644 xmlsecurity/qa/unit/signing/data/02_doc_signed_by_attacker_manipulated_triple.odt create mode 100644 xmlsecurity/qa/unit/signing/data/02_doc_signed_by_trusted_person_manipulated.odt create mode 100644 xmlsecurity/qa/unit/signing/data/add-visible-signature.pdf create mode 100644 xmlsecurity/qa/unit/signing/data/bad.docx create mode 100644 xmlsecurity/qa/unit/signing/data/bad.odt create mode 100644 xmlsecurity/qa/unit/signing/data/bad.pdf create mode 100644 xmlsecurity/qa/unit/signing/data/badDsigGPG.odt create mode 100644 xmlsecurity/qa/unit/signing/data/badStreamGPG.odt create mode 100644 xmlsecurity/qa/unit/signing/data/encryptedGPG.odt create mode 100644 xmlsecurity/qa/unit/signing/data/encryptedGPG_odf13.odt create mode 100644 xmlsecurity/qa/unit/signing/data/good-xades.odt create mode 100644 xmlsecurity/qa/unit/signing/data/good.odt create mode 100644 xmlsecurity/qa/unit/signing/data/good.pdf create mode 100644 xmlsecurity/qa/unit/signing/data/goodGPG.odt create mode 100644 xmlsecurity/qa/unit/signing/data/hide-and-replace-shadow-file-signed-2.pdf create mode 100644 xmlsecurity/qa/unit/signing/data/multi.docx create mode 100644 xmlsecurity/qa/unit/signing/data/no.odt create mode 100644 xmlsecurity/qa/unit/signing/data/no.pdf create mode 100644 xmlsecurity/qa/unit/signing/data/notype-xades.odt create mode 100644 xmlsecurity/qa/unit/signing/data/odb_signed_macros.odb create mode 100644 xmlsecurity/qa/unit/signing/data/partial.docx create mode 100644 xmlsecurity/qa/unit/signing/data/signatureline.docx create mode 100644 xmlsecurity/qa/unit/signing/data/signatureline.odt create mode 100644 xmlsecurity/qa/unit/signing/data/signed_with_x509certificate_chain.odt create mode 100644 xmlsecurity/qa/unit/signing/data/tdf42316.ott create mode 100644 xmlsecurity/qa/unit/signing/data/tdf42316_odt12.ott create mode 100644 xmlsecurity/qa/unit/signing/data/tdf96097.ods create mode 100644 xmlsecurity/qa/unit/signing/data/tdf96097.odt create mode 100644 xmlsecurity/qa/unit/signing/data/untrustedGoodGPG.odt create mode 100644 xmlsecurity/qa/unit/signing/signing.cxx create mode 100644 xmlsecurity/qa/unit/signing/signing2.cxx create mode 100644 xmlsecurity/qa/unit/xmlsecurity-dialogs-test.cxx create mode 100644 xmlsecurity/source/component/certificatecontainer.cxx create mode 100644 xmlsecurity/source/component/documentdigitalsignatures.cxx create mode 100644 xmlsecurity/source/dialogs/certificatechooser.cxx create mode 100644 xmlsecurity/source/dialogs/certificateviewer.cxx create mode 100644 xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx create mode 100644 xmlsecurity/source/dialogs/macrosecurity.cxx create mode 100644 xmlsecurity/source/framework/buffernode.cxx create mode 100644 xmlsecurity/source/framework/buffernode.hxx create mode 100644 xmlsecurity/source/framework/elementcollector.cxx create mode 100644 xmlsecurity/source/framework/elementcollector.hxx create mode 100644 xmlsecurity/source/framework/elementmark.cxx create mode 100644 xmlsecurity/source/framework/elementmark.hxx create mode 100644 xmlsecurity/source/framework/saxeventkeeperimpl.cxx create mode 100644 xmlsecurity/source/framework/securityengine.cxx create mode 100644 xmlsecurity/source/framework/signaturecreatorimpl.cxx create mode 100644 xmlsecurity/source/framework/signatureengine.cxx create mode 100644 xmlsecurity/source/framework/signatureverifierimpl.cxx create mode 100644 xmlsecurity/source/framework/xmlsignaturetemplateimpl.cxx create mode 100644 xmlsecurity/source/gpg/CertificateImpl.cxx create mode 100644 xmlsecurity/source/gpg/CertificateImpl.hxx create mode 100644 xmlsecurity/source/gpg/CipherContext.cxx create mode 100644 xmlsecurity/source/gpg/CipherContext.hxx create mode 100644 xmlsecurity/source/gpg/DigestContext.cxx create mode 100644 xmlsecurity/source/gpg/DigestContext.hxx create mode 100644 xmlsecurity/source/gpg/SEInitializer.cxx create mode 100644 xmlsecurity/source/gpg/SecurityEnvironment.cxx create mode 100644 xmlsecurity/source/gpg/SecurityEnvironment.hxx create mode 100644 xmlsecurity/source/gpg/XMLEncryption.cxx create mode 100644 xmlsecurity/source/gpg/XMLEncryption.hxx create mode 100644 xmlsecurity/source/gpg/XMLSecurityContext.cxx create mode 100644 xmlsecurity/source/gpg/XMLSecurityContext.hxx create mode 100644 xmlsecurity/source/gpg/xmlsignature_gpgimpl.cxx create mode 100644 xmlsecurity/source/helper/UriBindingHelper.cxx create mode 100644 xmlsecurity/source/helper/documentsignaturehelper.cxx create mode 100644 xmlsecurity/source/helper/documentsignaturemanager.cxx create mode 100644 xmlsecurity/source/helper/ooxmlsecexporter.cxx create mode 100644 xmlsecurity/source/helper/ooxmlsecexporter.hxx create mode 100644 xmlsecurity/source/helper/ooxmlsecparser.cxx create mode 100644 xmlsecurity/source/helper/ooxmlsecparser.hxx create mode 100644 xmlsecurity/source/helper/pdfsignaturehelper.cxx create mode 100644 xmlsecurity/source/helper/xmlsignaturehelper.cxx create mode 100644 xmlsecurity/source/helper/xsecctl.cxx create mode 100644 xmlsecurity/source/helper/xsecparser.cxx create mode 100644 xmlsecurity/source/helper/xsecparser.hxx create mode 100644 xmlsecurity/source/helper/xsecsign.cxx create mode 100644 xmlsecurity/source/helper/xsecverify.cxx create mode 100644 xmlsecurity/source/xmlsec/biginteger.cxx create mode 100644 xmlsecurity/source/xmlsec/certificateextension_certextn.cxx create mode 100644 xmlsecurity/source/xmlsec/certificateextension_certextn.hxx create mode 100644 xmlsecurity/source/xmlsec/certificateextension_xmlsecimpl.hxx create mode 100644 xmlsecurity/source/xmlsec/errorcallback.cxx create mode 100644 xmlsecurity/source/xmlsec/mscrypt/akmngr.cxx create mode 100644 xmlsecurity/source/xmlsec/mscrypt/akmngr.hxx create mode 100644 xmlsecurity/source/xmlsec/mscrypt/oid.hxx create mode 100644 xmlsecurity/source/xmlsec/mscrypt/sanextension_mscryptimpl.cxx create mode 100644 xmlsecurity/source/xmlsec/mscrypt/sanextension_mscryptimpl.hxx create mode 100644 xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.cxx create mode 100644 xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.hxx create mode 100644 xmlsecurity/source/xmlsec/mscrypt/seinitializer_mscryptimpl.cxx create mode 100644 xmlsecurity/source/xmlsec/mscrypt/seinitializer_mscryptimpl.hxx create mode 100644 xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx create mode 100644 xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.hxx create mode 100644 xmlsecurity/source/xmlsec/mscrypt/xmlsecuritycontext_mscryptimpl.cxx create mode 100644 xmlsecurity/source/xmlsec/mscrypt/xmlsignature_mscryptimpl.cxx create mode 100644 xmlsecurity/source/xmlsec/nss/certerrors.h create mode 100644 xmlsecurity/source/xmlsec/nss/ciphercontext.cxx create mode 100644 xmlsecurity/source/xmlsec/nss/ciphercontext.hxx create mode 100644 xmlsecurity/source/xmlsec/nss/digestcontext.cxx create mode 100644 xmlsecurity/source/xmlsec/nss/digestcontext.hxx create mode 100644 xmlsecurity/source/xmlsec/nss/nssinitializer.cxx create mode 100644 xmlsecurity/source/xmlsec/nss/nssinitializer.hxx create mode 100644 xmlsecurity/source/xmlsec/nss/nssrenam.h create mode 100644 xmlsecurity/source/xmlsec/nss/sanextension_nssimpl.cxx create mode 100644 xmlsecurity/source/xmlsec/nss/sanextension_nssimpl.hxx create mode 100644 xmlsecurity/source/xmlsec/nss/secerror.cxx create mode 100644 xmlsecurity/source/xmlsec/nss/secerror.hxx create mode 100644 xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.cxx create mode 100644 xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.hxx create mode 100644 xmlsecurity/source/xmlsec/nss/seinitializer_nssimpl.cxx create mode 100644 xmlsecurity/source/xmlsec/nss/seinitializer_nssimpl.hxx create mode 100644 xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx create mode 100644 xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.hxx create mode 100644 xmlsecurity/source/xmlsec/nss/xmlsecuritycontext_nssimpl.cxx create mode 100644 xmlsecurity/source/xmlsec/nss/xmlsignature_nssimpl.cxx create mode 100644 xmlsecurity/source/xmlsec/saxhelper.cxx create mode 100644 xmlsecurity/source/xmlsec/xmldocumentwrapper_xmlsecimpl.cxx create mode 100644 xmlsecurity/source/xmlsec/xmlelementwrapper_xmlsecimpl.cxx create mode 100644 xmlsecurity/source/xmlsec/xmlelementwrapper_xmlsecimpl.hxx create mode 100644 xmlsecurity/source/xmlsec/xmlsec_init.cxx create mode 100644 xmlsecurity/source/xmlsec/xmlstreamio.cxx create mode 100644 xmlsecurity/test_docs/CAs/README.txt create mode 100644 xmlsecurity/test_docs/CAs/Root_1/demoCA/cacert.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_1/demoCA/crl/DO_NOT_CREATE_A_CRL create mode 100644 xmlsecurity/test_docs/CAs/Root_1/demoCA/crlnumber create mode 100644 xmlsecurity/test_docs/CAs/Root_1/demoCA/index.txt create mode 100644 xmlsecurity/test_docs/CAs/Root_1/demoCA/index.txt.attr create mode 100644 xmlsecurity/test_docs/CAs/Root_1/demoCA/newcerts/1000.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_1/demoCA/private/cakey.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_1/demoCA/serial create mode 100644 xmlsecurity/test_docs/CAs/Root_1/openssl.cfg create mode 100644 xmlsecurity/test_docs/CAs/Root_10/demoCA/cacert.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_10/demoCA/crlnumber create mode 100644 xmlsecurity/test_docs/CAs/Root_10/demoCA/index.txt create mode 100644 xmlsecurity/test_docs/CAs/Root_10/demoCA/index.txt.attr create mode 100644 xmlsecurity/test_docs/CAs/Root_10/demoCA/newcerts/1000.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_10/demoCA/private/cakey.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_10/demoCA/serial create mode 100644 xmlsecurity/test_docs/CAs/Root_10/openssl.cfg create mode 100644 xmlsecurity/test_docs/CAs/Root_11/demoCA/cacert.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_11/demoCA/crlnumber create mode 100644 xmlsecurity/test_docs/CAs/Root_11/demoCA/index.txt create mode 100644 xmlsecurity/test_docs/CAs/Root_11/demoCA/index.txt.attr create mode 100644 xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1000.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1002.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1003.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1004.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1005.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1006.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1007.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1008.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1009.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100A.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100B.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100C.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100D.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100E.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100F.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1010.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1011.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1012.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1013.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1014.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1015.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1016.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1017.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1018.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1019.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101A.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101B.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101C.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101D.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101E.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101F.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1020.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1021.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1022.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_11/demoCA/private/cakey.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_11/demoCA/serial create mode 100644 xmlsecurity/test_docs/CAs/Root_11/openssl.cfg create mode 100644 xmlsecurity/test_docs/CAs/Root_2/demoCA/cacert.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_2/demoCA/crl/DO_NOT_CREATE_A_CRL create mode 100644 xmlsecurity/test_docs/CAs/Root_2/demoCA/crlnumber create mode 100644 xmlsecurity/test_docs/CAs/Root_2/demoCA/index.txt create mode 100644 xmlsecurity/test_docs/CAs/Root_2/demoCA/index.txt.attr create mode 100644 xmlsecurity/test_docs/CAs/Root_2/demoCA/newcerts/1000.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_2/demoCA/private/cakey.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_2/demoCA/serial create mode 100644 xmlsecurity/test_docs/CAs/Root_2/openssl.cfg create mode 100644 xmlsecurity/test_docs/CAs/Root_3/demoCA/cacert.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_3/demoCA/crlnumber create mode 100644 xmlsecurity/test_docs/CAs/Root_3/demoCA/index.txt create mode 100644 xmlsecurity/test_docs/CAs/Root_3/demoCA/index.txt.attr create mode 100644 xmlsecurity/test_docs/CAs/Root_3/demoCA/newcerts/1000.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_3/demoCA/private/cakey.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_3/demoCA/serial create mode 100644 xmlsecurity/test_docs/CAs/Root_3/openssl.cfg create mode 100644 xmlsecurity/test_docs/CAs/Root_4/README.txt create mode 100644 xmlsecurity/test_docs/CAs/Root_4/demoCA/cacert.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_4/demoCA/crlnumber create mode 100644 xmlsecurity/test_docs/CAs/Root_4/demoCA/index.txt create mode 100644 xmlsecurity/test_docs/CAs/Root_4/demoCA/index.txt.attr create mode 100644 xmlsecurity/test_docs/CAs/Root_4/demoCA/newcerts/1000.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_4/demoCA/newcerts/1001.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_4/demoCA/private/cakey.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_4/demoCA/serial create mode 100644 xmlsecurity/test_docs/CAs/Root_4/openssl.cfg create mode 100644 xmlsecurity/test_docs/CAs/Root_5/demoCA/cacert.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_5/demoCA/crl/DO_NOT_CREATE_A_CRL create mode 100644 xmlsecurity/test_docs/CAs/Root_5/demoCA/crlnumber create mode 100644 xmlsecurity/test_docs/CAs/Root_5/demoCA/index.txt create mode 100644 xmlsecurity/test_docs/CAs/Root_5/demoCA/index.txt.attr create mode 100644 xmlsecurity/test_docs/CAs/Root_5/demoCA/newcerts/1001.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_5/demoCA/private/cakey.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_5/demoCA/serial create mode 100644 xmlsecurity/test_docs/CAs/Root_5/openssl.cfg create mode 100644 xmlsecurity/test_docs/CAs/Root_6/README.txt create mode 100644 xmlsecurity/test_docs/CAs/Root_6/demoCA/cacert.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_6/demoCA/crl/DO_NOT_INSTALL_THIS_CRL create mode 100644 xmlsecurity/test_docs/CAs/Root_6/demoCA/crl/Root_6.crl create mode 100644 xmlsecurity/test_docs/CAs/Root_6/demoCA/crlnumber create mode 100644 xmlsecurity/test_docs/CAs/Root_6/demoCA/index.txt create mode 100644 xmlsecurity/test_docs/CAs/Root_6/demoCA/index.txt.attr create mode 100644 xmlsecurity/test_docs/CAs/Root_6/demoCA/newcerts/1001.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_6/demoCA/private/cakey.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_6/demoCA/serial create mode 100644 xmlsecurity/test_docs/CAs/Root_6/openssl.cfg create mode 100644 xmlsecurity/test_docs/CAs/Root_7/README.txt create mode 100644 xmlsecurity/test_docs/CAs/Root_7/demoCA/cacert.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_7/demoCA/crl/DO_NOT_INSTALL_THIS_CRL create mode 100644 xmlsecurity/test_docs/CAs/Root_7/demoCA/crl/Root_7.crl create mode 100644 xmlsecurity/test_docs/CAs/Root_7/demoCA/crlnumber create mode 100644 xmlsecurity/test_docs/CAs/Root_7/demoCA/index.txt create mode 100644 xmlsecurity/test_docs/CAs/Root_7/demoCA/index.txt.attr create mode 100644 xmlsecurity/test_docs/CAs/Root_7/demoCA/newcerts/1000.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_7/demoCA/newcerts/1001.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_7/demoCA/private/cakey.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_7/demoCA/serial create mode 100644 xmlsecurity/test_docs/CAs/Root_7/openssl.cfg create mode 100644 xmlsecurity/test_docs/CAs/Root_8/README.txt create mode 100644 xmlsecurity/test_docs/CAs/Root_8/demoCA/cacert.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_8/demoCA/crl/DO_NOT_INSTALL_THIS_CRL create mode 100644 xmlsecurity/test_docs/CAs/Root_8/demoCA/crl/Root_8.crl create mode 100644 xmlsecurity/test_docs/CAs/Root_8/demoCA/crlnumber create mode 100644 xmlsecurity/test_docs/CAs/Root_8/demoCA/index.txt create mode 100644 xmlsecurity/test_docs/CAs/Root_8/demoCA/index.txt.attr create mode 100644 xmlsecurity/test_docs/CAs/Root_8/demoCA/newcerts/1000.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_8/demoCA/newcerts/1001.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_8/demoCA/private/cakey.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_8/demoCA/serial create mode 100644 xmlsecurity/test_docs/CAs/Root_8/openssl.cfg create mode 100644 xmlsecurity/test_docs/CAs/Root_9/DO_NOT_INSTALL_THIS_ROOT_CERT.txt create mode 100644 xmlsecurity/test_docs/CAs/Root_9/demoCA/DO_NO_INSTALL_THIS_ROOT_CERTIFICATE create mode 100644 xmlsecurity/test_docs/CAs/Root_9/demoCA/Root_9.crt create mode 100644 xmlsecurity/test_docs/CAs/Root_9/demoCA/cacert.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_9/demoCA/crlnumber create mode 100644 xmlsecurity/test_docs/CAs/Root_9/demoCA/index.txt create mode 100644 xmlsecurity/test_docs/CAs/Root_9/demoCA/index.txt.attr create mode 100644 xmlsecurity/test_docs/CAs/Root_9/demoCA/newcerts/1000.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_9/demoCA/private/cakey.pem create mode 100644 xmlsecurity/test_docs/CAs/Root_9/demoCA/serial create mode 100644 xmlsecurity/test_docs/CAs/Root_9/openssl.cfg create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/cacert.pem create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/crl/DO_NOT_CREATE_A_CRL create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/crlnumber create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/index.txt create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/index.txt.attr create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/newcerts/1000.pem create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/private/cakey.pem create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/serial create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/openssl.cfg create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/DO_NOT_INSTALL_THIS_CERTIFICATE create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/README.txt create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/DO_NOT_INSTALL_THIS_CERTIFICATE create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/Sub_CA_1_Root_10.crt create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/cacert.pem create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/crl/DO_NOT_INSTALL_THIS_CRL create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/crl/Sub_CA_1_Root_10.crl create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/crlnumber create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/index.txt create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/index.txt.attr create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/newcerts/1000.pem create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/private/cakey.pem create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/serial create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/openssl.cfg create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/cacert.pem create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/crlnumber create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/index.txt create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/index.txt.attr create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/newcerts/1000.pem create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/private/cakey.pem create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/req.pem create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/serial create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/openssl.cfg create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/cacert.pem create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/crl/DO_NOT_CREATE_A_CRL create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/crlnumber create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/index.txt create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/index.txt.attr create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/newcerts/1000.pem create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/private/cakey.pem create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/req.pem create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/serial create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/openssl.cfg create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/README.txt create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/cacert.pem create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/crlnumber create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/index.txt create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/index.txt.attr create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/newcerts/1000.pem create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/newcerts/1001.pem create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/private/cakey.pem create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/serial create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/openssl.cfg create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/README.txt create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/cacert.pem create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/crl/DO_NOT_INSTALL_THIS_CRL create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/crl/Sub_CA_1_Root_5.crl create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/crlnumber create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/index.txt create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/index.txt.attr create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/newcerts/1002.pem create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/private/cakey.pem create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/serial create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/openssl.cfg create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/cacert.pem create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/crl/DO_NOT_CREATE_A_CRL create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/crlnumber create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/index.txt create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/index.txt.attr create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/newcerts/1000.pem create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/private/cakey.pem create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/serial create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/openssl.cfg create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/README.txt create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/cacert.pem create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/crl/DO_NOT_INSTALL_THIS_CRL create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/crl/Sub_CA_1_Root_7.crl create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/crlnumber create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/index.txt create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/index.txt.attr create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/newcerts/1000.pem create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/newcerts/1001.pem create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/private/cakey.pem create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/serial create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/openssl.cfg create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/README.txt create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/cacert.pem create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/crl/DO_NOT_INSTALL_THIS_CRL create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/crl/Sub_CA_1_Root_8.crl create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/crlnumber create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/index.txt create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/index.txt.attr create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/newcerts/1000.pem create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/newcerts/1001.pem create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/private/cakey.pem create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/serial create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/openssl.cfg create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/cacert.pem create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/crlnumber create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/index.txt create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/index.txt.attr create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/newcerts/1000.pem create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/private/cakey.pem create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/serial create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/openssl.cfg create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/README.txt create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/cacert.pem create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/crlnumber create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/index.txt create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/index.txt.attr create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/newcerts/1001.pem create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/newcerts/1002.pem create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/private/cakey.pem create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/serial create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/openssl.cfg create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/README.txt create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/cacert.pem create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/crl/DO_NOT_INSTALL_THIS_CRL create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/crl/Sub_CA_2_Root_7.crl create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/crlnumber create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/index.txt create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/index.txt.attr create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/newcerts/1000.pem create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/newcerts/1001.pem create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/private/cakey.pem create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/serial create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/openssl.cfg create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/README.txt create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/cacert.pem create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/crl/DO_NOT_INSTALL_THIS_CRL create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/crl/Sub_CA_2_Root_8.crl create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/crlnumber create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/index.txt create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/index.txt.attr create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/newcerts/1002.pem create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/newcerts/1003.pem create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/private/cakey.pem create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/serial create mode 100644 xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/openssl.cfg create mode 100644 xmlsecurity/test_docs/certs/ca_certs/Root_1.crt create mode 100644 xmlsecurity/test_docs/certs/ca_certs/Root_10.crt create mode 100644 xmlsecurity/test_docs/certs/ca_certs/Root_11.crt create mode 100644 xmlsecurity/test_docs/certs/ca_certs/Root_2.crt create mode 100644 xmlsecurity/test_docs/certs/ca_certs/Root_3.crt create mode 100644 xmlsecurity/test_docs/certs/ca_certs/Root_4.crt create mode 100644 xmlsecurity/test_docs/certs/ca_certs/Root_5.crt create mode 100644 xmlsecurity/test_docs/certs/ca_certs/Root_6.crt create mode 100644 xmlsecurity/test_docs/certs/ca_certs/Root_7.crt create mode 100644 xmlsecurity/test_docs/certs/ca_certs/Root_8.crt create mode 100644 xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_1.crt create mode 100644 xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_2.crt create mode 100644 xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_3.crt create mode 100644 xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_4.crt create mode 100644 xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_5.crt create mode 100644 xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_6.crt create mode 100644 xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_7.crt create mode 100644 xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_8.crt create mode 100644 xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_9.crt create mode 100644 xmlsecurity/test_docs/certs/ca_certs/Sub_CA_2_Root_4.crt create mode 100644 xmlsecurity/test_docs/certs/ca_certs/Sub_CA_2_Root_7.crt create mode 100644 xmlsecurity/test_docs/certs/ca_certs/Sub_CA_2_Root_8.crt create mode 100644 xmlsecurity/test_docs/certs/crl/Root_10.crl create mode 100644 xmlsecurity/test_docs/certs/crl/Root_11.crl create mode 100644 xmlsecurity/test_docs/certs/crl/Root_3.crl create mode 100644 xmlsecurity/test_docs/certs/crl/Root_4.crl create mode 100644 xmlsecurity/test_docs/certs/crl/Root_9.crl create mode 100644 xmlsecurity/test_docs/certs/crl/Sub_CA_1_Root_2.crl create mode 100644 xmlsecurity/test_docs/certs/crl/Sub_CA_1_Root_4.crl create mode 100644 xmlsecurity/test_docs/certs/crl/Sub_CA_1_Root_9.crl create mode 100644 xmlsecurity/test_docs/certs/crl/Sub_CA_2_Root_4.crl create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_10_Root_11.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_11_Root_11.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_12_Root_11.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_13_Root_11.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_14_Root_11.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_15_Root_11.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_16_Root_11.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_17_Root_11.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_18_Root_11.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_19_Root_11.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_1_Root_11.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_1.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_10.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_2.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_3.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_4.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_5.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_6.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_7.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_8.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_9.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_2_Root_4.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_2_Root_7.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_2_Root_8.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_20_Root_11.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_21_Root_11.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_22_Root_11.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_23_Root_11.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_24_Root_11.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_25_Root_11.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_26_Root_11.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_27_Root_11.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_28_Root_11.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_29_Root_11.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_2_Root_11.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_1_Root_4.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_1_Root_7.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_1_Root_8.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_2_Root_4.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_2_Root_7.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_2_Root_8.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_30_Root_11.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_31_Root_11.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_32_Root_11.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_33_Root_11.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_34_Root_11.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_35_Root_11.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_3_Root_11.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_4_Root_11.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_5_Root_11.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_6_Root_11.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_7_Root_11.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_8_Root_11.crt create mode 100644 xmlsecurity/test_docs/certs/end_certs/User_9_Root_11.crt create mode 100644 xmlsecurity/test_docs/certs/p12/Root_11.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_10_Root_11.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_11_Root_11.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_12_Root_11.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_13_Root_11.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_14_Root_11.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_15_Root_11.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_16_Root_11.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_17_Root_11.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_18_Root_11.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_19_Root_11.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_1_Root_11.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_1.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_10.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_2.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_3.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_4.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_5.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_6.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_7.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_8.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_9.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_2_Root_4.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_2_Root_7.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_2_Root_8.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_20_Root_11.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_21_Root_11.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_22_Root_11.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_23_Root_11.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_24_Root_11.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_25_Root_11.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_26_Root_11.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_27_Root_11.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_28_Root_11.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_29_Root_11.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_2_Root_11.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_1_Root_4.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_1_Root_7.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_1_Root_8.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_2_Root_4.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_2_Root_7.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_2_Root_8.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_30_Root_11.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_31_Root_11.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_32_Root_11.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_33_Root_11.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_34_Root_11.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_3_Root_11.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_4_Root_11.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_5_Root_11.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_6_Root_11.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_7_Root_11.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_8_Root_11.p12 create mode 100644 xmlsecurity/test_docs/certs/p12/User_9_Root_11.p12 create mode 100644 xmlsecurity/test_docs/documents/aia_ca_issuers.odt create mode 100644 xmlsecurity/test_docs/documents/aia_ocsp.odt create mode 100644 xmlsecurity/test_docs/documents/aia_ocsp_revoked_chain.odt create mode 100644 xmlsecurity/test_docs/documents/aia_ocsp_revoked_leaf.odt create mode 100644 xmlsecurity/test_docs/documents/aia_ocsp_revoked_leaf_chain.odt create mode 100644 xmlsecurity/test_docs/documents/crl.odt create mode 100644 xmlsecurity/test_docs/documents/crl_revoked_chain.odt create mode 100644 xmlsecurity/test_docs/documents/crl_revoked_leaf.odt create mode 100644 xmlsecurity/test_docs/documents/crl_revoked_leaf_chain.odt create mode 100644 xmlsecurity/test_docs/documents/crldp.odt create mode 100644 xmlsecurity/test_docs/documents/crldp_no_intermediate_ca_revocation_info.odt create mode 100644 xmlsecurity/test_docs/documents/crldp_no_root_revocation_info.odt create mode 100644 xmlsecurity/test_docs/documents/crldp_revoked_chain.odt create mode 100644 xmlsecurity/test_docs/documents/crldp_revoked_leaf.odt create mode 100644 xmlsecurity/test_docs/documents/crldp_revoked_leaf_chain.odt create mode 100644 xmlsecurity/test_docs/documents/dn_cyrillic_bmpstring.odt create mode 100644 xmlsecurity/test_docs/documents/dn_latin_ext_greak_bmpstring.odt create mode 100644 xmlsecurity/test_docs/documents/dn_multivalue_rdn.odt create mode 100644 xmlsecurity/test_docs/documents/dn_quoting.odt create mode 100644 xmlsecurity/test_docs/documents/dn_single_multivalue_rdn.odt create mode 100644 xmlsecurity/test_docs/documents/dn_single_multivalue_rdn_with_quoting.odt create mode 100644 xmlsecurity/test_docs/documents/incomplete_path.odt create mode 100644 xmlsecurity/test_docs/documents/invalid_ooo2_x_doc1.odt create mode 100644 xmlsecurity/test_docs/documents/invalid_ooo2_x_doc2.odt create mode 100644 xmlsecurity/test_docs/documents/invalid_ooo2_x_macro1.odt create mode 100644 xmlsecurity/test_docs/documents/invalid_ooo2_x_macro2.odt create mode 100644 xmlsecurity/test_docs/documents/invalid_ooo2_x_macro3.odt create mode 100644 xmlsecurity/test_docs/documents/invalid_ooo2_x_macro4.odt create mode 100644 xmlsecurity/test_docs/documents/invalid_ooo2_x_macro5.odt create mode 100644 xmlsecurity/test_docs/documents/invalid_ooo3_2_doc1.odt create mode 100644 xmlsecurity/test_docs/documents/invalid_ooo3_2_doc3.odt create mode 100644 xmlsecurity/test_docs/documents/invalid_ooo3_2_doc4.odt create mode 100644 xmlsecurity/test_docs/documents/invalid_ooo_3_2_doc2.odt create mode 100644 xmlsecurity/test_docs/documents/ocsp_crl.odt create mode 100644 xmlsecurity/test_docs/documents/ocsp_crl_revoked_leaf.odt create mode 100644 xmlsecurity/test_docs/documents/stateOrProvinceName.odt create mode 100644 xmlsecurity/test_docs/documents/valid_no_revocation.odt create mode 100644 xmlsecurity/test_docs/documents/valid_no_root_revocation_info.odt create mode 100644 xmlsecurity/test_docs/documents/valid_no_sub_ca_revocation_info.odt create mode 100644 xmlsecurity/test_docs/documents/valid_ooo2_x_doc1.odt create mode 100644 xmlsecurity/test_docs/documents/valid_ooo2_x_doc_macro.odt create mode 100644 xmlsecurity/test_docs/documents/valid_ooo2_x_doc_unsigned_macro.odt create mode 100644 xmlsecurity/test_docs/documents/valid_ooo3_0_doc1.odt create mode 100644 xmlsecurity/test_docs/documents/valid_ooo3_0_doc_macro.odt create mode 100644 xmlsecurity/test_docs/documents/valid_ooo3_0_doc_unsigned_macro.odt create mode 100644 xmlsecurity/test_docs/documents/valid_ooo3_2_doc1.odt create mode 100644 xmlsecurity/test_docs/documents/valid_ooo3_2_doc_macro.odt create mode 100644 xmlsecurity/test_docs/documents/valid_ooo3_2_doc_unsigned_macro.odt create mode 100644 xmlsecurity/test_docs/test_description.odt create mode 100644 xmlsecurity/test_docs/tools/README.txt create mode 100644 xmlsecurity/test_docs/tools/httpserv/build.xml create mode 100644 xmlsecurity/test_docs/tools/httpserv/manifest.mf create mode 100644 xmlsecurity/test_docs/tools/httpserv/nbproject/build-impl.xml create mode 100644 xmlsecurity/test_docs/tools/httpserv/nbproject/genfiles.properties create mode 100644 xmlsecurity/test_docs/tools/httpserv/nbproject/project.properties create mode 100644 xmlsecurity/test_docs/tools/httpserv/nbproject/project.xml create mode 100644 xmlsecurity/test_docs/tools/httpserv/src/httpserv/Main.java create mode 100644 xmlsecurity/uiconfig/ui/certdetails.ui create mode 100644 xmlsecurity/uiconfig/ui/certgeneral.ui create mode 100644 xmlsecurity/uiconfig/ui/certpage.ui create mode 100644 xmlsecurity/uiconfig/ui/digitalsignaturesdialog.ui create mode 100644 xmlsecurity/uiconfig/ui/macrosecuritydialog.ui create mode 100644 xmlsecurity/uiconfig/ui/securitylevelpage.ui create mode 100644 xmlsecurity/uiconfig/ui/securitytrustpage.ui create mode 100644 xmlsecurity/uiconfig/ui/selectcertificatedialog.ui create mode 100644 xmlsecurity/uiconfig/ui/viewcertdialog.ui create mode 100644 xmlsecurity/util/xmlsecurity.component create mode 100644 xmlsecurity/util/xmlsecurity.component.dds create mode 100644 xmlsecurity/util/xsec_xmlsec.component create mode 100644 xmlsecurity/util/xsec_xmlsec.component.gpg create mode 100644 xmlsecurity/util/xsec_xmlsec.component.nss create mode 100644 xmlsecurity/util/xsec_xmlsec.component.nss_mscrypt create mode 100644 xmlsecurity/workben/pdfverify.cxx (limited to 'xmlsecurity') diff --git a/xmlsecurity/AllLangMoTarget_xsc.mk b/xmlsecurity/AllLangMoTarget_xsc.mk new file mode 100644 index 0000000000..90b80207ce --- /dev/null +++ b/xmlsecurity/AllLangMoTarget_xsc.mk @@ -0,0 +1,13 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +$(eval $(call gb_AllLangMoTarget_AllLangMoTarget,xsc)) + +$(eval $(call gb_AllLangMoTarget_set_polocation,xsc,xmlsecurity)) + +# vim: set noet sw=4 ts=4: diff --git a/xmlsecurity/CppunitTest_qa_certext.mk b/xmlsecurity/CppunitTest_qa_certext.mk new file mode 100644 index 0000000000..faa5459d3e --- /dev/null +++ b/xmlsecurity/CppunitTest_qa_certext.mk @@ -0,0 +1,27 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +$(eval $(call gb_CppunitTest_CppunitTest,xmlsecurity_qa_certext)) + +$(eval $(call gb_CppunitTest_use_sdk_api,xmlsecurity_qa_certext)) + +$(eval $(call gb_CppunitTest_use_libraries,xmlsecurity_qa_certext,\ + cppu \ + neon \ + sal \ + svl \ + test \ + tl \ +)) + +$(eval $(call gb_CppunitTest_add_exception_objects,xmlsecurity_qa_certext,\ + xmlsecurity/qa/certext/SanCertExt \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/xmlsecurity/CppunitTest_xmlsecurity_dialogs_test.mk b/xmlsecurity/CppunitTest_xmlsecurity_dialogs_test.mk new file mode 100644 index 0000000000..945c33af7b --- /dev/null +++ b/xmlsecurity/CppunitTest_xmlsecurity_dialogs_test.mk @@ -0,0 +1,68 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +#************************************************************************* +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +#************************************************************************* + +$(eval $(call gb_CppunitTest_CppunitScreenShot,xmlsecurity_dialogs_test)) + +$(eval $(call gb_CppunitTest_add_exception_objects,xmlsecurity_dialogs_test, \ + xmlsecurity/qa/unit/xmlsecurity-dialogs-test \ +)) + +$(eval $(call gb_CppunitTest_use_sdk_api,xmlsecurity_dialogs_test)) + +$(eval $(call gb_CppunitTest_set_include,desktop_dialogs_test,\ + -I$(SRCDIR)/xmlsecurity/inc \ + $$(INCLUDE) \ +)) + +$(eval $(call gb_CppunitTest_use_libraries,xmlsecurity_dialogs_test, \ + basegfx \ + comphelper \ + cppu \ + cppuhelper \ + drawinglayer \ + editeng \ + i18nlangtag \ + i18nutil \ + msfilter \ + oox \ + sal \ + salhelper \ + sax \ + sfx \ + sot \ + svl \ + svt \ + test \ + tl \ + tk \ + ucbhelper \ + unotest \ + utl \ + vcl \ + xo \ +)) + +$(eval $(call gb_CppunitTest_use_external,xmlsecurity_dialogs_test,boost_headers)) + +$(eval $(call gb_CppunitTest_use_sdk_api,xmlsecurity_dialogs_test)) + +$(eval $(call gb_CppunitTest_use_ure,xmlsecurity_dialogs_test)) +$(eval $(call gb_CppunitTest_use_vcl_non_headless_with_windows,xmlsecurity_dialogs_test)) + +$(eval $(call gb_CppunitTest_use_rdb,xmlsecurity_dialogs_test,services)) + +$(eval $(call gb_CppunitTest_use_configuration,xmlsecurity_dialogs_test)) + +$(eval $(call gb_CppunitTest_use_uiconfigs,xmlsecurity_dialogs_test,\ + xmlsec \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/xmlsecurity/CppunitTest_xmlsecurity_pdfsigning.mk b/xmlsecurity/CppunitTest_xmlsecurity_pdfsigning.mk new file mode 100644 index 0000000000..667acc97e3 --- /dev/null +++ b/xmlsecurity/CppunitTest_xmlsecurity_pdfsigning.mk @@ -0,0 +1,70 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +#************************************************************************* +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +#************************************************************************* + +$(eval $(call gb_CppunitTest_CppunitTest,xmlsecurity_pdfsigning)) + +$(eval $(call gb_CppunitTest_add_exception_objects,xmlsecurity_pdfsigning, \ + xmlsecurity/qa/unit/pdfsigning/pdfsigning \ +)) + +$(eval $(call gb_CppunitTest_use_libraries,xmlsecurity_pdfsigning, \ + comphelper \ + cppuhelper \ + cppu \ + sal \ + sax \ + sfx \ + test \ + tl \ + unotest \ + utl \ + xmlsecurity \ + vcl \ +)) + +$(eval $(call gb_CppunitTest_use_externals,xmlsecurity_pdfsigning,\ + boost_headers \ +)) + +ifneq ($(OS),WNT) +ifneq (,$(ENABLE_NSS)) +$(eval $(call gb_CppunitTest_use_externals,xmlsecurity_pdfsigning,\ + nssutil3 \ +)) +endif +endif + +$(eval $(call gb_CppunitTest_set_include,xmlsecurity_pdfsigning,\ + -I$(SRCDIR)/xmlsecurity/inc \ + $$(INCLUDE) \ +)) + +$(eval $(call gb_CppunitTest_use_sdk_api,xmlsecurity_pdfsigning)) + +$(eval $(call gb_CppunitTest_use_ure,xmlsecurity_pdfsigning)) +$(eval $(call gb_CppunitTest_use_vcl,xmlsecurity_pdfsigning)) + +$(eval $(call gb_CppunitTest_use_rdb,xmlsecurity_pdfsigning,services)) + +$(eval $(call gb_CppunitTest_use_configuration,xmlsecurity_pdfsigning)) + +ifeq ($(ENABLE_POPPLER),TRUE) +$(eval $(call gb_CppunitTest_use_executable,xmlsecurity_pdfsigning,xpdfimport)) +endif + +ifeq ($(OS),WNT) +# Initializing DocumentSignatureManager will require gpgme-w32spawn.exe in workdir/LinkTarget/Executable +$(eval $(call gb_CppunitTest_use_packages,xmlsecurity_pdfsigning,\ + $(call gb_Helper_optional,GPGMEPP,gpgmepp)\ +)) +endif + +# vim: set noet sw=4 ts=4: diff --git a/xmlsecurity/CppunitTest_xmlsecurity_signing.mk b/xmlsecurity/CppunitTest_xmlsecurity_signing.mk new file mode 100644 index 0000000000..7339800107 --- /dev/null +++ b/xmlsecurity/CppunitTest_xmlsecurity_signing.mk @@ -0,0 +1,94 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +#************************************************************************* +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +#************************************************************************* + +$(eval $(call gb_CppunitTest_CppunitTest,xmlsecurity_signing)) + +$(eval $(call gb_CppunitTest_add_exception_objects,xmlsecurity_signing, \ + xmlsecurity/qa/unit/signing/signing \ +)) + +$(eval $(call gb_CppunitTest_use_libraries,xmlsecurity_signing, \ + comphelper \ + cppuhelper \ + cppu \ + sal \ + sax \ + sfx \ + svx \ + subsequenttest \ + test \ + tl \ + unotest \ + utl \ + vcl \ + xmlsecurity \ + xsec_xmlsec \ +)) + +$(eval $(call gb_CppunitTest_use_externals,xmlsecurity_signing,\ + boost_headers \ + libxml2 \ +)) + +ifneq ($(OS),WNT) +ifneq (,$(ENABLE_NSS)) +$(eval $(call gb_CppunitTest_use_externals,xmlsecurity_signing,\ + nssutil3 \ +)) +endif +endif + +$(eval $(call gb_CppunitTest_set_include,xmlsecurity_signing,\ + -I$(SRCDIR)/xmlsecurity/inc \ + $$(INCLUDE) \ +)) + +$(eval $(call gb_CppunitTest_use_sdk_api,xmlsecurity_signing)) + +$(eval $(call gb_CppunitTest_use_ure,xmlsecurity_signing)) +$(eval $(call gb_CppunitTest_use_vcl,xmlsecurity_signing)) + +$(eval $(call gb_CppunitTest_use_uiconfigs,xmlsecurity_signing, \ + svt \ +)) + +$(eval $(call gb_CppunitTest_use_rdb,xmlsecurity_signing,services)) + +$(eval $(call gb_CppunitTest_use_configuration,xmlsecurity_signing)) + +ifeq ($(ENABLE_POPPLER),TRUE) +$(eval $(call gb_CppunitTest_use_executable,xmlsecurity_signing,xpdfimport)) +endif + +# various hacks to make unit test work on Linux more often +ifeq ($(OS),LINUX) +# reset the LD_LIBRARY_PATH for spawned GPG processes +$(call gb_CppunitTest_get_target,xmlsecurity_signing): \ + EXTRA_ENV_VARS += \ + LIBO_LD_PATH=$$LD_LIBRARY_PATH +endif + +$(eval $(call gb_CppunitTest_use_custom_headers,xmlsecurity_signing,\ + officecfg/registry \ +)) + +ifeq ($(OS),WNT) +# Initializing DocumentSignatureManager will require gpgme-w32spawn.exe in workdir/LinkTarget/Executable +$(eval $(call gb_CppunitTest_use_packages,xmlsecurity_signing,\ + $(call gb_Helper_optional,GPGMEPP,gpgmepp)\ +)) +endif + +$(eval $(call gb_CppunitTest_add_arguments,xmlsecurity_signing, \ + -env:arg-env=$(gb_Helper_LIBRARY_PATH_VAR)"$$$${$(gb_Helper_LIBRARY_PATH_VAR)+=$$$$$(gb_Helper_LIBRARY_PATH_VAR)}" \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/xmlsecurity/CppunitTest_xmlsecurity_signing2.mk b/xmlsecurity/CppunitTest_xmlsecurity_signing2.mk new file mode 100644 index 0000000000..0cd4501219 --- /dev/null +++ b/xmlsecurity/CppunitTest_xmlsecurity_signing2.mk @@ -0,0 +1,94 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +#************************************************************************* +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +#************************************************************************* + +$(eval $(call gb_CppunitTest_CppunitTest,xmlsecurity_signing2)) + +$(eval $(call gb_CppunitTest_add_exception_objects,xmlsecurity_signing2, \ + xmlsecurity/qa/unit/signing/signing2 \ +)) + +$(eval $(call gb_CppunitTest_use_libraries,xmlsecurity_signing2, \ + comphelper \ + cppuhelper \ + cppu \ + sal \ + sax \ + sfx \ + svx \ + subsequenttest \ + test \ + tl \ + unotest \ + utl \ + vcl \ + xmlsecurity \ + xsec_xmlsec \ +)) + +$(eval $(call gb_CppunitTest_use_externals,xmlsecurity_signing2,\ + boost_headers \ + libxml2 \ +)) + +ifneq ($(OS),WNT) +ifneq (,$(ENABLE_NSS)) +$(eval $(call gb_CppunitTest_use_externals,xmlsecurity_signing2,\ + nssutil3 \ +)) +endif +endif + +$(eval $(call gb_CppunitTest_set_include,xmlsecurity_signing2,\ + -I$(SRCDIR)/xmlsecurity/inc \ + $$(INCLUDE) \ +)) + +$(eval $(call gb_CppunitTest_use_sdk_api,xmlsecurity_signing2)) + +$(eval $(call gb_CppunitTest_use_ure,xmlsecurity_signing2)) +$(eval $(call gb_CppunitTest_use_vcl,xmlsecurity_signing2)) + +$(eval $(call gb_CppunitTest_use_uiconfigs,xmlsecurity_signing2, \ + svt \ +)) + +$(eval $(call gb_CppunitTest_use_rdb,xmlsecurity_signing2,services)) + +$(eval $(call gb_CppunitTest_use_configuration,xmlsecurity_signing2)) + +ifeq ($(ENABLE_POPPLER),TRUE) +$(eval $(call gb_CppunitTest_use_executable,xmlsecurity_signing2,xpdfimport)) +endif + +# various hacks to make unit test work on Linux more often +ifeq ($(OS),LINUX) +# reset the LD_LIBRARY_PATH for spawned GPG processes +$(call gb_CppunitTest_get_target,xmlsecurity_signing2): \ + EXTRA_ENV_VARS += \ + LIBO_LD_PATH=$$LD_LIBRARY_PATH +endif + +$(eval $(call gb_CppunitTest_use_custom_headers,xmlsecurity_signing2,\ + officecfg/registry \ +)) + +ifeq ($(OS),WNT) +# Initializing DocumentSignatureManager will require gpgme-w32spawn.exe in workdir/LinkTarget/Executable +$(eval $(call gb_CppunitTest_use_packages,xmlsecurity_signing2,\ + $(call gb_Helper_optional,GPGMEPP,gpgmepp)\ +)) +endif + +$(eval $(call gb_CppunitTest_add_arguments,xmlsecurity_signing2, \ + -env:arg-env=$(gb_Helper_LIBRARY_PATH_VAR)"$$$${$(gb_Helper_LIBRARY_PATH_VAR)+=$$$$$(gb_Helper_LIBRARY_PATH_VAR)}" \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/xmlsecurity/Executable_pdfverify.mk b/xmlsecurity/Executable_pdfverify.mk new file mode 100644 index 0000000000..ed8e9559fc --- /dev/null +++ b/xmlsecurity/Executable_pdfverify.mk @@ -0,0 +1,35 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +$(eval $(call gb_Executable_Executable,pdfverify)) + +$(eval $(call gb_Executable_use_sdk_api,pdfverify)) + +$(eval $(call gb_Executable_use_external,pdfverify,boost_headers)) + +$(eval $(call gb_Executable_set_include,pdfverify,\ + $$(INCLUDE) \ + -I$(SRCDIR)/xmlsecurity/inc \ +)) + +$(eval $(call gb_Executable_use_libraries,pdfverify,\ + comphelper \ + cppu \ + cppuhelper \ + sal \ + tl \ + vcl \ + xmlsecurity \ +)) + +$(eval $(call gb_Executable_add_exception_objects,pdfverify,\ + xmlsecurity/workben/pdfverify \ +)) + +# vim:set noet sw=4 ts=4: diff --git a/xmlsecurity/IwyuFilter_xmlsecurity.yaml b/xmlsecurity/IwyuFilter_xmlsecurity.yaml new file mode 100644 index 0000000000..b27a552751 --- /dev/null +++ b/xmlsecurity/IwyuFilter_xmlsecurity.yaml @@ -0,0 +1,131 @@ +--- +assumeFilename: xmlsecurity/source/xmlsec/xmlsec_init.cxx +excludelist: + xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx: + # complete type is needed + - com/sun/star/security/DocumentSignatureInformation.hpp + xmlsecurity/inc/UriBindingHelper.hxx: + # Base class needs complete type + - com/sun/star/xml/crypto/XUriBinding.hpp + xmlsecurity/inc/xsecctl.hxx: + # Base class needs complete type + - com/sun/star/xml/crypto/sax/XSAXEventKeeperStatusChangeListener.hpp + - com/sun/star/xml/crypto/sax/XSignatureCreationResultListener.hpp + - com/sun/star/xml/crypto/sax/XSignatureVerifyResultListener.hpp + # Needed on WIN32 for rtl::Reference to compile + - UriBindingHelper.hxx + xmlsecurity/inc/framework/securityengine.hxx: + # Base class needs complete type + - com/sun/star/xml/crypto/XXMLSignature.hpp + - com/sun/star/xml/crypto/sax/XReferenceResolvedBroadcaster.hpp + - com/sun/star/xml/crypto/sax/XSAXEventKeeper.hpp + xmlsecurity/inc/framework/signaturecreatorimpl.hxx: + # Base class needs complete type + - framework/signatureengine.hxx + - com/sun/star/xml/crypto/sax/XBlockerMonitor.hpp + - com/sun/star/xml/crypto/sax/XSignatureCreationResultBroadcaster.hpp + - com/sun/star/lang/XInitialization.hpp + - com/sun/star/lang/XServiceInfo.hpp + xmlsecurity/inc/framework/saxeventkeeperimpl.hxx: + # Base class needs complete type + - com/sun/star/xml/crypto/sax/XSecuritySAXEventKeeper.hpp + - com/sun/star/xml/crypto/sax/XReferenceResolvedBroadcaster.hpp + - com/sun/star/xml/crypto/sax/XSAXEventKeeperStatusChangeBroadcaster.hpp + - com/sun/star/xml/sax/XDocumentHandler.hpp + - com/sun/star/lang/XInitialization.hpp + - com/sun/star/lang/XServiceInfo.hpp + xmlsecurity/inc/framework/signatureverifierimpl.hxx: + # Base class needs complete type + - framework/signatureengine.hxx + - com/sun/star/xml/crypto/sax/XSignatureVerifyResultBroadcaster.hpp + - com/sun/star/lang/XServiceInfo.hpp + - com/sun/star/lang/XInitialization.hpp + xmlsecurity/inc/framework/xmlsignaturetemplateimpl.hxx: + # Base class needs complete type + - com/sun/star/xml/crypto/XXMLSignatureTemplate.hpp + - com/sun/star/lang/XServiceInfo.hpp + xmlsecurity/inc/gpg/SEInitializer.hxx: + # Base class needs complete type + - com/sun/star/xml/crypto/XSEInitializer.hpp + - com/sun/star/lang/XServiceInfo.hpp + xmlsecurity/inc/gpg/xmlsignature_gpgimpl.hxx: + # Base class needs complete type + - com/sun/star/xml/crypto/XXMLSignature.hpp + - com/sun/star/lang/XServiceInfo.hpp + xmlsecurity/inc/xmlsec/xmldocumentwrapper_xmlsecimpl.hxx: + # Base class needs complete type + - com/sun/star/xml/wrapper/XXMLDocumentWrapper.hpp + - com/sun/star/xml/csax/XCompressedDocumentHandler.hpp + - com/sun/star/lang/XServiceInfo.hpp + xmlsecurity/source/gpg/CipherContext.hxx: + # Base class needs complete type + - com/sun/star/xml/crypto/XCipherContext.hpp + xmlsecurity/source/gpg/DigestContext.hxx: + # Base class needs complete type + - com/sun/star/xml/crypto/XDigestContext.hpp + xmlsecurity/source/gpg/CertificateImpl.hxx: + # Base class needs complete type + - com/sun/star/security/XCertificate.hpp + - com/sun/star/lang/XUnoTunnel.hpp + - com/sun/star/lang/XServiceInfo.hpp + xmlsecurity/source/gpg/SecurityEnvironment.hxx: + # Base class needs complete type + - com/sun/star/xml/crypto/XSecurityEnvironment.hpp + - com/sun/star/lang/XUnoTunnel.hpp + xmlsecurity/source/gpg/XMLSecurityContext.hxx: + # Base class needs complete type + - com/sun/star/xml/crypto/XXMLSecurityContext.hpp + - com/sun/star/lang/XServiceInfo.hpp + xmlsecurity/source/gpg/XMLEncryption.hxx: + # Base class needs complete type + - com/sun/star/xml/crypto/XXMLEncryption.hpp + xmlsecurity/source/helper/ooxmlsecparser.hxx: + # Base class needs complete type + - com/sun/star/xml/sax/XDocumentHandler.hpp + - com/sun/star/lang/XInitialization.hpp + xmlsecurity/source/helper/xsecparser.hxx: + # Base class needs complete type + - com/sun/star/xml/sax/XDocumentHandler.hpp + - com/sun/star/lang/XInitialization.hpp + xmlsecurity/source/xmlsec/certificateextension_xmlsecimpl.hxx: + # Base class needs complete type + - com/sun/star/security/XCertificateExtension.hpp + xmlsecurity/source/xmlsec/xmlelementwrapper_xmlsecimpl.hxx: + # Base class needs complete type + - com/sun/star/lang/XServiceInfo.hpp + - com/sun/star/lang/XUnoTunnel.hpp + - com/sun/star/xml/wrapper/XXMLElementWrapper.hpp + xmlsecurity/source/xmlsec/errorcallback.cxx: + # Needed for xmlsec/errors.h + - xmlsec-wrapper.h + xmlsecurity/source/xmlsec/xmlstreamio.cxx: + # comphelper::ScopeGuard is in use but not noticed by IWYU + - comphelper/scopeguard.hxx + xmlsecurity/source/xmlsec/nss/sanextension_nssimpl.hxx: + # Base class needs complete type + - com/sun/star/security/XSanExtension.hpp + xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.hxx: + # Base class needs complete type + - com/sun/star/security/XCertificate.hpp + - com/sun/star/lang/XUnoTunnel.hpp + - com/sun/star/lang/XServiceInfo.hpp + xmlsecurity/source/xmlsec/nss/seinitializer_nssimpl.hxx: + # Base class needs complete type + - nssinitializer.hxx + - com/sun/star/xml/crypto/XSEInitializer.hpp + xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.hxx: + # Base class needs complete type + - com/sun/star/xml/crypto/XSecurityEnvironment.hpp + - com/sun/star/xml/crypto/XCertificateCreator.hpp + - com/sun/star/lang/XServiceInfo.hpp + - com/sun/star/lang/XUnoTunnel.hpp + xmlsecurity/source/xmlsec/nss/secerror.cxx: + # Used as array initializer + - certerrors.h + # Needed for macros used by certerrors.h + - nss.h + xmlsecurity/qa/unit/signing/signing.cxx: + # Don't replace URE header with impl. detail + - osl/thread.hxx + xmlsecurity/workben/pdfverify.cxx: + - comphelper/scopeguard.hxx diff --git a/xmlsecurity/Library_xmlsecurity.mk b/xmlsecurity/Library_xmlsecurity.mk new file mode 100644 index 0000000000..8507b4bab2 --- /dev/null +++ b/xmlsecurity/Library_xmlsecurity.mk @@ -0,0 +1,112 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +$(eval $(call gb_Library_Library,xmlsecurity)) + +$(eval $(call gb_Library_set_componentfile,xmlsecurity,xmlsecurity/util/xmlsecurity,services)) + +$(eval $(call gb_Library_set_include,xmlsecurity,\ + $$(INCLUDE) \ + -I$(SRCDIR)/xmlsecurity/inc \ +)) + +$(eval $(call gb_Library_add_defs,xmlsecurity,\ + -DXMLSECURITY_DLLIMPLEMENTATION \ +)) + +$(eval $(call gb_Library_use_externals,xmlsecurity,\ + boost_headers \ +)) + +$(eval $(call gb_Library_set_precompiled_header,xmlsecurity,xmlsecurity/inc/pch/precompiled_xmlsecurity)) + +$(eval $(call gb_Library_use_sdk_api,xmlsecurity)) + +$(eval $(call gb_Library_use_libraries,xmlsecurity,\ + comphelper \ + cppu \ + cppuhelper \ + sal \ + sax \ + svl \ + sfx \ + svt \ + svxcore \ + tl \ + ucbhelper \ + utl \ + vcl \ + xo \ + i18nlangtag \ + xsec_xmlsec \ +)) + +$(eval $(call gb_Library_add_exception_objects,xmlsecurity,\ + xmlsecurity/source/component/certificatecontainer \ + xmlsecurity/source/dialogs/certificatechooser \ + xmlsecurity/source/dialogs/certificateviewer \ + xmlsecurity/source/dialogs/digitalsignaturesdialog \ + xmlsecurity/source/dialogs/macrosecurity \ + xmlsecurity/source/framework/buffernode \ + xmlsecurity/source/framework/elementcollector \ + xmlsecurity/source/framework/elementmark \ + xmlsecurity/source/framework/saxeventkeeperimpl \ + xmlsecurity/source/framework/securityengine \ + xmlsecurity/source/framework/signaturecreatorimpl \ + xmlsecurity/source/framework/signatureengine \ + xmlsecurity/source/framework/signatureverifierimpl \ + xmlsecurity/source/framework/xmlsignaturetemplateimpl \ + xmlsecurity/source/helper/documentsignaturehelper \ + xmlsecurity/source/helper/documentsignaturemanager \ + xmlsecurity/source/helper/ooxmlsecparser \ + xmlsecurity/source/helper/ooxmlsecexporter \ + xmlsecurity/source/helper/pdfsignaturehelper \ + xmlsecurity/source/helper/UriBindingHelper \ + xmlsecurity/source/helper/xsecctl \ + xmlsecurity/source/helper/xsecparser \ + xmlsecurity/source/helper/xsecsign \ +)) + +ifneq (,$(or $(ENABLE_NSS),$(filter WNT,$(OS)))) +$(eval $(call gb_Library_add_exception_objects,xmlsecurity,\ + xmlsecurity/source/component/documentdigitalsignatures \ + xmlsecurity/source/helper/xmlsignaturehelper \ + xmlsecurity/source/helper/xsecverify \ +)) + +$(eval $(call gb_Library_add_componentimpl,xmlsecurity,dds)) +endif + +$(eval $(call gb_Library_use_externals,xmlsecurity,\ + libxml2 \ +)) +ifeq ($(OS),WNT) +$(eval $(call gb_Library_add_defs,xmlsecurity,\ + -DXMLSEC_CRYPTO_MSCRYPTO \ +)) +$(eval $(call gb_Library_use_system_win32_libs,xmlsecurity,\ + crypt32 \ + Ole32 \ + Shell32 \ +)) +else +ifneq (,$(filter DESKTOP,$(BUILD_TYPE))$(filter ANDROID,$(OS))) +ifeq (TRUE,$(ENABLE_NSS)) +$(eval $(call gb_Library_add_defs,xmlsecurity,\ + -DXMLSEC_CRYPTO_NSS \ +)) +$(eval $(call gb_Library_use_externals,xmlsecurity,\ + nss3 \ + plc4 \ +)) +endif +endif # BUILD_TYPE=DESKTOP +endif + +# vim: set noet sw=4 ts=4: diff --git a/xmlsecurity/Library_xsec_xmlsec.mk b/xmlsecurity/Library_xsec_xmlsec.mk new file mode 100644 index 0000000000..615c3eba00 --- /dev/null +++ b/xmlsecurity/Library_xsec_xmlsec.mk @@ -0,0 +1,188 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +$(eval $(call gb_Library_Library,xsec_xmlsec)) + +$(eval $(call gb_Library_set_componentfile,xsec_xmlsec,xmlsecurity/util/xsec_xmlsec,services)) + +$(eval $(call gb_Library_add_componentimpls,xsec_xmlsec, \ + $(if $(ENABLE_GPGMEPP),gpg) \ + $(if $(or $(ENABLE_NSS),$(filter WNT,$(OS))),nss_mscrypt) \ + $(if $(ENABLE_NSS),nss) \ +)) + +$(eval $(call gb_Library_set_include,xsec_xmlsec,\ + $$(INCLUDE) \ + -I$(SRCDIR)/xmlsecurity/inc \ + -I$(SRCDIR)/xmlsecurity/source/gpg \ + -I$(SRCDIR)/xmlsecurity/source/xmlsec \ + -I$(call gb_UnpackedTarball_get_dir,xmlsec/include) \ +)) + +$(eval $(call gb_Library_use_custom_headers,xsec_xmlsec,\ + officecfg/registry \ +)) + +$(eval $(call gb_Library_use_sdk_api,xsec_xmlsec)) + +$(eval $(call gb_Library_add_defs,xsec_xmlsec,\ + -DXMLSEC_NO_XSLT \ + -DXSECXMLSEC_DLLIMPLEMENTATION \ +)) + +$(eval $(call gb_Library_set_precompiled_header,xsec_xmlsec,xmlsecurity/inc/pch/precompiled_xsec_xmlsec)) + +$(eval $(call gb_Library_use_libraries,xsec_xmlsec,\ + comphelper \ + cppu \ + cppuhelper \ + sal \ + svl \ + tl \ + xo \ + utl \ +)) + +ifeq ($(SYSTEM_XMLSEC),) +$(eval $(call gb_Library_use_packages,xsec_xmlsec,\ + xmlsec \ +)) +endif + +$(eval $(call gb_Library_use_externals,xsec_xmlsec,\ + boost_headers \ + $(if $(ENABLE_GPGMEPP),gpgmepp) \ + libxml2 \ + xmlsec \ +)) + +$(eval $(call gb_Library_add_exception_objects,xsec_xmlsec,\ + xmlsecurity/source/xmlsec/biginteger \ + xmlsecurity/source/xmlsec/certificateextension_certextn \ + xmlsecurity/source/xmlsec/errorcallback \ + xmlsecurity/source/xmlsec/saxhelper \ + xmlsecurity/source/xmlsec/xmldocumentwrapper_xmlsecimpl \ + xmlsecurity/source/xmlsec/xmlelementwrapper_xmlsecimpl \ + xmlsecurity/source/xmlsec/xmlsec_init \ + xmlsecurity/source/xmlsec/xmlstreamio \ +)) + +ifeq ($(ENABLE_GPGMEPP),TRUE) +$(eval $(call gb_Library_add_exception_objects,xsec_xmlsec,\ + xmlsecurity/source/gpg/CertificateImpl \ + xmlsecurity/source/gpg/CipherContext \ + xmlsecurity/source/gpg/DigestContext \ + xmlsecurity/source/gpg/SecurityEnvironment \ + xmlsecurity/source/gpg/SEInitializer \ + xmlsecurity/source/gpg/XMLEncryption \ + xmlsecurity/source/gpg/XMLSecurityContext \ + xmlsecurity/source/gpg/xmlsignature_gpgimpl \ +)) +endif + +ifeq ($(OS),WNT) + +$(eval $(call gb_Library_add_defs,xsec_xmlsec,\ + -DXMLSEC_CRYPTO_MSCRYPTO \ +)) + +$(eval $(call gb_Library_add_libs,xsec_xmlsec,\ + $(call gb_UnpackedTarball_get_dir,xmlsec)/win32/binaries/libxmlsec-mscng.lib \ + $(call gb_UnpackedTarball_get_dir,xmlsec)/win32/binaries/libxmlsec.lib \ +)) + +$(eval $(call gb_Library_use_system_win32_libs,xsec_xmlsec,\ + crypt32 \ + advapi32 \ + ncrypt \ +)) + +$(eval $(call gb_Library_add_exception_objects,xsec_xmlsec,\ + xmlsecurity/source/xmlsec/mscrypt/akmngr \ + xmlsecurity/source/xmlsec/mscrypt/sanextension_mscryptimpl \ + xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl \ + xmlsecurity/source/xmlsec/mscrypt/seinitializer_mscryptimpl \ + xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl \ + xmlsecurity/source/xmlsec/mscrypt/xmlsecuritycontext_mscryptimpl \ + xmlsecurity/source/xmlsec/mscrypt/xmlsignature_mscryptimpl \ +)) + +ifeq ($(ENABLE_NSS),TRUE) + +$(eval $(call gb_Library_add_exception_objects,xsec_xmlsec,\ + xmlsecurity/source/xmlsec/nss/ciphercontext \ + xmlsecurity/source/xmlsec/nss/digestcontext \ + xmlsecurity/source/xmlsec/nss/nssinitializer \ +)) + +# nss3 after static libs to appease --as-needed linkers +$(eval $(call gb_Library_use_externals,xsec_xmlsec,\ + nss3 \ +)) + +endif + +else # !$(OS),WNT + +ifeq ($(SYSTEM_XMLSEC),) +$(eval $(call gb_Library_add_libs,xsec_xmlsec,\ + $(call gb_UnpackedTarball_get_dir,xmlsec)/src/.libs/libxmlsec1.a \ +)) +endif + +ifeq ($(ENABLE_NSS),TRUE) + +ifeq ($(SYSTEM_XMLSEC),) +$(eval $(call gb_Library_add_libs,xsec_xmlsec,\ + $(call gb_UnpackedTarball_get_dir,xmlsec)/src/nss/.libs/libxmlsec1-nss.a \ +)) +endif + +$(eval $(call gb_Library_add_exception_objects,xsec_xmlsec,\ + xmlsecurity/source/xmlsec/nss/ciphercontext \ + xmlsecurity/source/xmlsec/nss/digestcontext \ + xmlsecurity/source/xmlsec/nss/nssinitializer \ + xmlsecurity/source/xmlsec/nss/sanextension_nssimpl \ + xmlsecurity/source/xmlsec/nss/secerror \ + xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl \ + xmlsecurity/source/xmlsec/nss/seinitializer_nssimpl \ + xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl \ + xmlsecurity/source/xmlsec/nss/xmlsecuritycontext_nssimpl \ + xmlsecurity/source/xmlsec/nss/xmlsignature_nssimpl \ +)) + +$(eval $(call gb_Library_add_defs,xsec_xmlsec,\ + -DXMLSEC_CRYPTO_NSS \ +)) + +$(eval $(call gb_Library_use_externals,xsec_xmlsec,\ + plc4 \ +)) +# nss3 after static libs to appease --as-needed linkers +$(eval $(call gb_Library_use_externals,xsec_xmlsec,\ + nss3 \ +)) + +else # ! $(ENABLE_NSS) + +ifeq ($(ENABLE_OPENSSL),TRUE) +$(eval $(call gb_Library_use_external,xsec_xmlsec,openssl)) +endif + +endif # !$(ENABLE_NSS) + +ifeq ($(OS),SOLARIS) +$(eval $(call gb_Library_add_libs,xsec_xmlsec,\ + -ldl \ +)) +endif + +endif # !$(OS),WNT + +# vim: set noet sw=4 ts=4: diff --git a/xmlsecurity/Makefile b/xmlsecurity/Makefile new file mode 100644 index 0000000000..0997e62848 --- /dev/null +++ b/xmlsecurity/Makefile @@ -0,0 +1,14 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +module_directory:=$(dir $(realpath $(firstword $(MAKEFILE_LIST)))) + +include $(module_directory)/../solenv/gbuild/partial_build.mk + +# vim: set noet sw=4 ts=4: diff --git a/xmlsecurity/Module_xmlsecurity.mk b/xmlsecurity/Module_xmlsecurity.mk new file mode 100644 index 0000000000..f5b442683a --- /dev/null +++ b/xmlsecurity/Module_xmlsecurity.mk @@ -0,0 +1,53 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +$(eval $(call gb_Module_Module,xmlsecurity)) + +$(eval $(call gb_Module_add_targets,xmlsecurity,\ + Library_xmlsecurity \ + $(if $(ENABLE_NSS)$(ENABLE_OPENSSL),Library_xsec_xmlsec) \ + UIConfig_xmlsec \ +)) + +$(eval $(call gb_Library_use_custom_headers,xmlsecurity,\ + officecfg/registry \ +)) + +$(eval $(call gb_Module_add_slowcheck_targets,xmlsecurity,\ + CppunitTest_xmlsecurity_pdfsigning \ +)) + +$(eval $(call gb_Module_add_subsequentcheck_targets,xmlsecurity,\ + CppunitTest_xmlsecurity_signing \ + CppunitTest_xmlsecurity_signing2 \ +)) + +$(eval $(call gb_Module_add_l10n_targets,xmlsecurity,\ + AllLangMoTarget_xsc \ +)) + +# failing +#$(eval $(call gb_Module_add_check_targets,xmlsecurity,\ + CppunitTest_qa_certext \ +)) + +# screenshots +$(eval $(call gb_Module_add_screenshot_targets,xmlsecurity,\ + CppunitTest_xmlsecurity_dialogs_test \ +)) + +ifneq (,$(filter DESKTOP,$(BUILD_TYPE))) +ifneq (,$(or $(ENABLE_NSS),$(filter WNT,$(OS)))) +$(eval $(call gb_Module_add_targets,xmlsecurity,\ + $(if $(DISABLE_DYNLOADING),,Executable_pdfverify) \ +)) +endif +endif + +# vim: set noet sw=4 ts=4: diff --git a/xmlsecurity/README.md b/xmlsecurity/README.md new file mode 100644 index 0000000000..5d45e36119 --- /dev/null +++ b/xmlsecurity/README.md @@ -0,0 +1,59 @@ +# Document Signing + +## Introduction + +This code provides dialogs, and infrastructure wrapping `libxmlsec` and +`gpgme` that implements document signing. + +For signing a document, a personal key pair is used, which consists of a +private key and a public key, which is added to the document in addition +to the digital signature of the document, when signing it. + +The document signing can be done both for the source ODF/OOXML files and +the exported PDF files. It is also possible to sign existing PDF files. + +## Module Contents + + * `doc`: OpenDocument workflow legacy information with some illustrations to have an idea of the workflow, for starters check `doc/OpenDocumentSignatures-Workflow.odt`. + * `inc`: Headers to a subset of source files inside the module, parts like `source/framework` have headers inside the folder. + * `qa`: Unit tests for signing and shell scripts for certificates creation for testing. + * `test_docs`: Documents & certificates used for testing. + * `source`: More on that below. + * `uiconfig`: User interface configuration for different dialogs, it is recommended to navigate from relevant source file to the .ui file linked in the class which will be under `uiconfig/ui`. + * `util`: UNO passive registration config for GPG/ NSS. + +## Source Primary Contents + + * `component`: Main implementation of `DocumentDigitalSignatures` where the interaction with security environment and certificates occur. + * `dialogs`: Certificate & Signatures management dialogs. + * `certificatechooser`: Dialog that allows you to find and choose certificates or signatures for encryption. + * `certificateviewer`: More detailed information about each certificate. + * `digitalsignaturesdialog`: Main window for signatures of the documents and the start point of signing document. + * `framework`: Various elements for verifying signatures and running security engine. + * `gpg`: The implementation of encrypting with GPG and security environment initialization. + * `helper`: Some helper classes that include signatures manager and the helpers for PDF signing, UriBinding, and XML signatures. It also include helper tools for XSecurityEnvironment. + * `xmlsec`: XML, NSS, MSCrypt encryption/ signing tools, more on the low-level side of actual implementation of algorithms. + + +## PDF Testing + +To test the signed PDFs, one can use the `pdfverify` in this way: + + ./bin/run pdfverify $PWD/xmlsecurity/qa/unit/pdfsigning/data/2good.pdf + +The file parameter should be an absolute path. + +This is the output of `pdfverify` for `2good.pdf`: + +``` +verifying signatures +found 2 signatures +signature #0: digest match? 1 +signature #0: partial? 0 +signature #1: digest match? 1 +signature #1: partial? 0 +``` + +## References +* [Adobe: Digital Signatures in a PDF](https://www.adobe.com/devnet-docs/etk_deprecated/tools/DigSig/Acrobat\_DigitalSignatures_in_PDF.pdf) +* [Adobe: Acrobat DC Digital Signatures - Supported Standards](https://www.adobe.com/devnet-docs/acrobatetk/tools/DigSigDC/standards.html) diff --git a/xmlsecurity/UIConfig_xmlsec.mk b/xmlsecurity/UIConfig_xmlsec.mk new file mode 100644 index 0000000000..06482e2a29 --- /dev/null +++ b/xmlsecurity/UIConfig_xmlsec.mk @@ -0,0 +1,24 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +$(eval $(call gb_UIConfig_UIConfig,xmlsec)) + +$(eval $(call gb_UIConfig_add_uifiles,xmlsec,\ + xmlsecurity/uiconfig/ui/certpage \ + xmlsecurity/uiconfig/ui/certdetails \ + xmlsecurity/uiconfig/ui/certgeneral \ + xmlsecurity/uiconfig/ui/digitalsignaturesdialog \ + xmlsecurity/uiconfig/ui/securitylevelpage \ + xmlsecurity/uiconfig/ui/securitytrustpage \ + xmlsecurity/uiconfig/ui/selectcertificatedialog \ + xmlsecurity/uiconfig/ui/macrosecuritydialog \ + xmlsecurity/uiconfig/ui/viewcertdialog \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/xmlsecurity/doc/OpenDocumentSignatures-TestIntegration.odt b/xmlsecurity/doc/OpenDocumentSignatures-TestIntegration.odt new file mode 100644 index 0000000000..e90e4eaade Binary files /dev/null and b/xmlsecurity/doc/OpenDocumentSignatures-TestIntegration.odt differ diff --git a/xmlsecurity/doc/OpenDocumentSignatures-Workflow.odg b/xmlsecurity/doc/OpenDocumentSignatures-Workflow.odg new file mode 100644 index 0000000000..f7331f024a Binary files /dev/null and b/xmlsecurity/doc/OpenDocumentSignatures-Workflow.odg differ diff --git a/xmlsecurity/doc/OpenDocumentSignatures.odt b/xmlsecurity/doc/OpenDocumentSignatures.odt new file mode 100644 index 0000000000..78ac14fc0b Binary files /dev/null and b/xmlsecurity/doc/OpenDocumentSignatures.odt differ diff --git a/xmlsecurity/doc/XMLSecurityFramework.odt b/xmlsecurity/doc/XMLSecurityFramework.odt new file mode 100644 index 0000000000..b3f3a3549c Binary files /dev/null and b/xmlsecurity/doc/XMLSecurityFramework.odt differ diff --git a/xmlsecurity/inc/UriBindingHelper.hxx b/xmlsecurity/inc/UriBindingHelper.hxx new file mode 100644 index 0000000000..67c9ae69f8 --- /dev/null +++ b/xmlsecurity/inc/UriBindingHelper.hxx @@ -0,0 +1,51 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include + +#include + +#include + +namespace com::sun::star { + namespace io { class XInputStream; } + namespace embed { class XStorage; } +} + +// XUriBinding + +class UriBindingHelper final : public cppu::WeakImplHelper< css::xml::crypto::XUriBinding > +{ +private: + css::uno::Reference < css::embed::XStorage > mxStorage; + +public: + UriBindingHelper(); + explicit UriBindingHelper( const css::uno::Reference < css::embed::XStorage >& rxStorage ); + + void SAL_CALL setUriBinding( const OUString& uri, const css::uno::Reference< css::io::XInputStream >& aInputStream ) override; + + css::uno::Reference< css::io::XInputStream > SAL_CALL getUriBinding( const OUString& uri ) override; + + static css::uno::Reference < css::io::XInputStream > OpenInputStream( const css::uno::Reference < css::embed::XStorage >& rxStore, const OUString& rURI ); +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/biginteger.hxx b/xmlsecurity/inc/biginteger.hxx new file mode 100644 index 0000000000..fc99320c7e --- /dev/null +++ b/xmlsecurity/inc/biginteger.hxx @@ -0,0 +1,51 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include + +#include + +#include + +#include + +#include "xsecxmlsecdllapi.h" + +namespace xmlsecurity +{ +XSECXMLSEC_DLLPUBLIC OUString bigIntegerToNumericString(const css::uno::Sequence& serial); +XSECXMLSEC_DLLPUBLIC css::uno::Sequence +numericStringToBigInteger(std::u16string_view serialNumber); + +// DNs read as strings from XML files may need to be mangled for compatibility +// as NSS and MS CryptoAPI have different string serialisations; if the DN is +// from an XCertificate it's "native" already and doesn't need to be mangled. +enum EqualMode +{ + NOCOMPAT, + COMPAT_2ND, + COMPAT_BOTH +}; +XSECXMLSEC_DLLPUBLIC bool EqualDistinguishedNames(std::u16string_view rName1, + std::u16string_view rName2, EqualMode eMode); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/bitmaps.hlst b/xmlsecurity/inc/bitmaps.hlst new file mode 100644 index 0000000000..4224881839 --- /dev/null +++ b/xmlsecurity/inc/bitmaps.hlst @@ -0,0 +1,21 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +inline constexpr OUString BMP_STATE_NOT_VALIDATED = u"xmlecurity/res/notcertificate_40x56.png"_ustr; + +#define BMP_CERT_OK "xmlsecurity/res/certificate_16.png" +#define BMP_CERT_NOT_OK "xmlsecurity/res/notcertificate_16.png" + +inline constexpr OUString BMP_SIG_VALID = u"xmlsecurity/res/signet_11x16.png"_ustr; +inline constexpr OUString BMP_SIG_INVALID = u"svx/res/caution_11x16.png"_ustr; +inline constexpr OUString BMP_SIG_NOT_VALIDATED = u"xmlsecurity/res/notcertificate_16.png"_ustr; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/xmlsecurity/inc/certificate.hxx b/xmlsecurity/inc/certificate.hxx new file mode 100644 index 0000000000..8357f50651 --- /dev/null +++ b/xmlsecurity/inc/certificate.hxx @@ -0,0 +1,43 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include + +#include + +namespace svl +{ +namespace crypto +{ +enum class SignatureMethodAlgorithm; +} +} + +namespace xmlsecurity +{ +/// Extension of css::security::XCertificate for module-internal purposes. +class SAL_NO_VTABLE SAL_DLLPUBLIC_RTTI SAL_LOPLUGIN_ANNOTATE("crosscast") Certificate +{ +public: + /// Returns the SHA-256 thumbprint. + /// + /// @throws css::uno::RuntimeException + virtual css::uno::Sequence getSHA256Thumbprint() = 0; + + /// Same as getSubjectPublicKeyAlgorithm(), but returns an ID, not a string. + virtual svl::crypto::SignatureMethodAlgorithm getSignatureMethodAlgorithm() = 0; + +protected: + ~Certificate() noexcept = default; +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/certificatechooser.hxx b/xmlsecurity/inc/certificatechooser.hxx new file mode 100644 index 0000000000..12303fbf1c --- /dev/null +++ b/xmlsecurity/inc/certificatechooser.hxx @@ -0,0 +1,117 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include +#include +#include +#include +#include + +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 xCertificate; + css::uno::Reference xSecurityContext; + css::uno::Reference xSecurityEnvironment; +}; + +enum class UserAction +{ + Sign, + SelectSign, // Select signing certificate + Encrypt +}; + +class CertificateChooser final : public weld::GenericDialogController +{ +private: + static inline CertificateChooser* mxInstance = nullptr; + + std::vector< css::uno::Reference< css::xml::crypto::XXMLSecurityContext > > mxSecurityContexts; + std::vector> mvUserData; + + bool mbInitialized; + UserAction const meAction; + OUString msPreferredKey; + css::uno::Reference mxEncryptToSelf; + + std::unique_ptr m_xFTSign; + std::unique_ptr m_xFTEncrypt; + std::unique_ptr m_xCertLB; + std::unique_ptr m_xViewBtn; + std::unique_ptr m_xOKBtn; + std::unique_ptr m_xFTDescription; + std::unique_ptr m_xDescriptionED; + std::unique_ptr m_xSearchBox; + std::unique_ptr m_xReloadBtn; + + std::unordered_map, + css::uno::Sequence< css::uno::Reference< css::security::XCertificate > > > xMemCerts; + + DECL_LINK(ReloadButtonHdl, weld::Button&, void); + DECL_LINK(ViewButtonHdl, weld::Button&, void); + DECL_LINK(CertificateHighlightHdl, weld::TreeView&, void); + DECL_LINK(CertificateSelectHdl, weld::TreeView&, bool); + DECL_LINK(SearchModifyHdl, weld::Entry&, void); + + void ImplShowCertificateDetails(); + void ImplInitialize(bool mbSearch = false); + void ImplReloadCertificates(); + static void HandleOneUsageBit(OUString& string, int& bits, int bit, TranslateId name); + +public: + CertificateChooser(weld::Window* pParent, + std::vector< css::uno::Reference< css::xml::crypto::XXMLSecurityContext > > && rxSecurityContexts, + UserAction eAction); + virtual ~CertificateChooser() override; + + static CertificateChooser* getInstance(weld::Window* _pParent, + std::vector< css::uno::Reference< css::xml::crypto::XXMLSecurityContext > > && rxSecurityContexts, + UserAction eAction) { + if (!mxInstance) + { + mxInstance = new CertificateChooser(_pParent, std::move(rxSecurityContexts), eAction); + } + return mxInstance; + } + + short run() override; + + css::uno::Sequence > GetSelectedCertificates(); + css::uno::Reference< css::xml::crypto::XXMLSecurityContext > GetSelectedSecurityContext() const; + /// Gets the description string provided when selecting the certificate. + OUString GetDescription() const; + + /// Returns the usage string of the selected certificate, if any. + OUString GetUsageText(); + + static OUString UsageInClearText(int bits); +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/certificateviewer.hxx b/xmlsecurity/inc/certificateviewer.hxx new file mode 100644 index 0000000000..2db66ddba2 --- /dev/null +++ b/xmlsecurity/inc/certificateviewer.hxx @@ -0,0 +1,159 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include +#include + +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 mxTabCtrl; + + std::unique_ptr mxGeneralPage; + std::unique_ptr mxDetailsPage; + std::unique_ptr mxPathId; + + DECL_LINK(ActivatePageHdl, const OUString&, void); + +public: + CertificateViewer(weld::Window* pParent, const css::uno::Reference< css::xml::crypto::XSecurityEnvironment >& rxSecurityEnvironment, const css::uno::Reference< css::security::XCertificate >& rXCert, bool bCheckForPrivateKey, CertificateChooser* pParentChooser); + CertificateChooser* GetParentChooser() { return mpParentChooser; } +}; + +class CertificateViewerTP +{ +protected: + std::unique_ptr mxBuilder; + std::unique_ptr mxContainer; + CertificateViewer* mpDlg; + +public: + CertificateViewerTP(weld::Container* pParent, const OUString& rUIXMLDescription, + const OUString& rID, CertificateViewer* pDlg); +}; + +class CertificateViewerGeneralTP : public CertificateViewerTP +{ +private: + std::unique_ptr m_xCertImg; + std::unique_ptr m_xHintNotTrustedFT; + std::unique_ptr m_xIssuedToLabelFT; + std::unique_ptr m_xIssuedToFT; + std::unique_ptr m_xIssuedByLabelFT; + std::unique_ptr m_xIssuedByFT; + std::unique_ptr m_xValidFromDateFT; + std::unique_ptr m_xValidToDateFT; + std::unique_ptr m_xKeyImg; + std::unique_ptr m_xHintCorrespPrivKeyFT; + +public: + CertificateViewerGeneralTP(weld::Container* pParent, CertificateViewer* pDlg); +}; + +struct Details_UserDatat +{ + OUString const maTxt; + bool const mbFixedWidthFont; + + Details_UserDatat(OUString aTxt, bool bFixedWidthFont) + : maTxt(std::move(aTxt)) + , mbFixedWidthFont(bFixedWidthFont) + { + } +}; + +class CertificateViewerDetailsTP : public CertificateViewerTP +{ +private: + std::vector> m_aUserData; + + std::unique_ptr m_xElementsLB; + std::unique_ptr 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 xCert, bool bValid) + : mxCert(std::move(xCert)) + , mbValid(bValid) + { + } +}; + +class CertificateViewerCertPathTP : public CertificateViewerTP +{ +private: + CertificateViewer* mpParent; + bool mbFirstActivateDone; + + std::vector> maUserData; + std::shared_ptr mxCertificateViewer; + + std::unique_ptr mxCertPathLB; + std::unique_ptr mxScratchIter; + std::unique_ptr mxViewCertPB; + std::unique_ptr mxCertStatusML; + std::unique_ptr mxCertOK; + std::unique_ptr mxCertNotValidated; + + DECL_LINK(ViewCertHdl, weld::Button&, void); + DECL_LINK(CertSelectHdl, weld::TreeView&, void); + void InsertCert(const weld::TreeIter* pParent, const OUString& _rName, + const css::uno::Reference< css::security::XCertificate >& rxCert, + bool bValid); + +public: + CertificateViewerCertPathTP(weld::Container* pParent, CertificateViewer* pDlg); + ~CertificateViewerCertPathTP(); + void ActivatePage(); +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/digitalsignaturesdialog.hxx b/xmlsecurity/inc/digitalsignaturesdialog.hxx new file mode 100644 index 0000000000..08db226fb8 --- /dev/null +++ b/xmlsecurity/inc/digitalsignaturesdialog.hxx @@ -0,0 +1,124 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include +#include + +#include "documentsignaturehelper.hxx" +#include "xmlsignaturehelper.hxx" +#include "documentsignaturemanager.hxx" + +#include + +namespace com::sun::star { + namespace lang { class XMultiServiceFactory; } + namespace io { class XStream; } + namespace embed { class XStorage; } + namespace xml::dom { class XDocumentBuilder; } +} + + +class HeaderBar; +class CertificateViewer; + +class DigitalSignaturesDialog final : public weld::GenericDialogController +{ +private: + DocumentSignatureManager maSignatureManager; + bool mbVerifySignatures; + bool mbSignaturesChanged; + + OUString const m_sODFVersion; + //Signals if the document contains already a document signature. This is only + //important when we are signing macros and if the value is true. + bool const m_bHasDocumentSignature; + bool m_bWarningShowSignMacro; + + bool m_bAdESCompliant = true; + + std::unique_ptr m_xHintDocFT; + std::unique_ptr m_xHintBasicFT; + std::unique_ptr m_xHintPackageFT; + std::unique_ptr m_xSignaturesLB; + std::unique_ptr m_xSigsValidImg; + std::unique_ptr m_xSigsValidFI; + std::unique_ptr m_xSigsInvalidImg; + std::unique_ptr m_xSigsInvalidFI; + std::unique_ptr m_xSigsNotvalidatedImg; + std::unique_ptr m_xSigsNotvalidatedFI; + std::unique_ptr m_xSigsOldSignatureImg; + std::unique_ptr m_xSigsOldSignatureFI; + std::unique_ptr m_xViewBtn; + std::unique_ptr m_xAddBtn; + std::unique_ptr m_xRemoveBtn; + std::unique_ptr m_xStartCertMgrBtn; + std::unique_ptr m_xCloseBtn; + + std::shared_ptr m_xViewer; + std::shared_ptr m_xInfoBox; + + DECL_LINK(ViewButtonHdl, weld::Button&, void); + DECL_LINK(AddButtonHdl, weld::Button&, void); + DECL_LINK(RemoveButtonHdl, weld::Button&, void); + DECL_LINK(SignatureHighlightHdl, weld::TreeView&, void); + DECL_LINK(SignatureSelectHdl, weld::TreeView&, bool); + DECL_LINK(StartVerifySignatureHdl, LinkParamNone*, bool); + DECL_LINK(OKButtonHdl, weld::Button&, void); + DECL_LINK(CertMgrButtonHdl, weld::Button&, void); + + void ImplGetSignatureInformations(bool bUseTempStream, bool bCacheLastSignature); + void ImplFillSignaturesBox(); + void ImplShowSignaturesDetails(); + + css::uno::Reference getCertificate(const SignatureInformation& rInfo); + css::uno::Reference getSecurityEnvironmentForCertificate( + const css::uno::Reference& xCert); + + //Checks if adding is allowed. + //See the spec at specs/www/appwide/security/Electronic_Signatures_and_Security.sxw + //(6.6.2)Behaviour with regard to ODF 1.2 + bool canAdd(); + bool canRemove(); + + bool canAddRemove(); + +public: + DigitalSignaturesDialog(weld::Window* pParent, const css::uno::Reference< + css::uno::XComponentContext >& rxCtx, DocumentSignatureMode eMode, + bool bReadOnly, OUString sODFVersion, bool bHasDocumentSignature); + virtual ~DigitalSignaturesDialog() override; + + // Initialize the dialog and the security environment, returns TRUE on success + bool Init(); + + // Set the storage which should be signed or verified + void SetStorage( const css::uno::Reference < css::embed::XStorage >& rxStore ); + void SetSignatureStream( const css::uno::Reference < css::io::XStream >& rxStream ); + + // Execute the dialog... + void beforeRun(); + short run() override; + + // Did signatures change? + bool SignaturesChanged() const { return mbSignaturesChanged; } +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/documentsignaturehelper.hxx b/xmlsecurity/inc/documentsignaturehelper.hxx new file mode 100644 index 0000000000..eb50b37614 --- /dev/null +++ b/xmlsecurity/inc/documentsignaturehelper.hxx @@ -0,0 +1,104 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include +#include +#include + +#include + +namespace com::sun::star { + namespace io { class XStream; } + namespace embed { class XStorage; } +} + +namespace com::sun::star::xml::sax { class XDocumentHandler; } + +enum class DocumentSignatureMode +{ + Content, + Macros, + Package +}; + +enum class DocumentSignatureAlgorithm +{ + OOo2, + OOo3_0, + OOo3_2 +}; + +struct SignatureStreamHelper +{ + css::uno::Reference < css::embed::XStorage > xSignatureStorage; + css::uno::Reference < css::io::XStream > xSignatureStream; + /// If this is embed::StorageFormats::OFOPXML, then it's expected that xSignatureStream is an empty reference. + sal_Int32 nStorageFormat; + + SignatureStreamHelper() + : nStorageFormat(0) + { + } +}; + +namespace DocumentSignatureHelper +{ + SignatureStreamHelper OpenSignatureStream( + const css::uno::Reference < css::embed::XStorage >& rxStore, sal_Int32 nOpenMode, + DocumentSignatureMode eDocSigMode ); + + std::vector< OUString > CreateElementList( + const css::uno::Reference < css::embed::XStorage >& rxStore, + DocumentSignatureMode eMode, + const DocumentSignatureAlgorithm mode); + + bool isODFPre_1_2(std::u16string_view sODFVersion); + bool isOOo3_2_Signature(const SignatureInformation & sigInfo); + + DocumentSignatureAlgorithm getDocumentAlgorithm( + std::u16string_view sODFVersion, const SignatureInformation & sigInfo); + + bool CanSignWithGPG(const css::uno::Reference < css::embed::XStorage >& rxStore, + std::u16string_view sOdfVersion); + + bool checkIfAllFilesAreSigned( const ::std::vector< OUString > & sElementList, + const SignatureInformation & sigInfo, const DocumentSignatureAlgorithm alg); + + bool equalsReferenceUriManifestPath( + std::u16string_view rUri, std::u16string_view rPath); + + OUString GetDocumentContentSignatureDefaultStreamName(); + OUString GetScriptingContentSignatureDefaultStreamName(); + OUString GetPackageSignatureDefaultStreamName(); + + /// In case the storage is OOXML, prepend a leading '/' and append content type to the element URIs. + void AppendContentTypes(const css::uno::Reference& xStorage, std::vector& rElements); + + void writeDigestMethod( + const css::uno::Reference& xDocumentHandler); + void writeSignedProperties( + const css::uno::Reference& xDocumentHandler, + const SignatureInformation& signatureInfo, + const OUString& sDate, + const bool bWriteSignatureLineData); +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/documentsignaturemanager.hxx b/xmlsecurity/inc/documentsignaturemanager.hxx new file mode 100644 index 0000000000..ab89e5b966 --- /dev/null +++ b/xmlsecurity/inc/documentsignaturemanager.hxx @@ -0,0 +1,136 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include "xmlsecuritydllapi.h" + +#include + +#include +#include "xmlsignaturehelper.hxx" +#include "documentsignaturehelper.hxx" + +#include +#include + +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 mxContext; + css::uno::Reference mxStore; + XMLSignatureHelper maSignatureHelper; + std::unique_ptr mpPDFSignatureHelper; + SignatureInformations maCurrentSignatureInformations; + DocumentSignatureMode const meSignatureMode; + css::uno::Sequence> m_manifest; + css::uno::Reference mxSignatureStream; + css::uno::Reference mxModel; + rtl::Reference mxTempSignatureStream; + /// Storage containing all OOXML signatures, unused for ODF. + css::uno::Reference mxTempSignatureStorage; + css::uno::Reference mxSEInitializer; + css::uno::Reference mxSecurityContext; + css::uno::Reference mxGpgSEInitializer; + css::uno::Reference mxGpgSecurityContext; + +public: + DocumentSignatureManager(const css::uno::Reference& 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& xCert, + const css::uno::Reference& xSecurityContext, + const OUString& rDescription, sal_Int32& nSecurityId, bool bAdESCompliant, + const OUString& rSignatureLineId = OUString(), + const css::uno::Reference& xValidGraphic + = css::uno::Reference(), + const css::uno::Reference& xInvalidGraphic + = css::uno::Reference()); + /// 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 getSecurityEnvironment(); + css::uno::Reference getGpgSecurityEnvironment(); + css::uno::Reference const& getSecurityContext() const; + css::uno::Reference const& getGpgSecurityContext() const; + void setStore(const css::uno::Reference& xStore) { mxStore = xStore; } + XMLSignatureHelper& getSignatureHelper() { return maSignatureHelper; } + bool hasPDFSignatureHelper() const { return bool(mpPDFSignatureHelper); } + void setSignatureStream(const css::uno::Reference& xSignatureStream) + { + mxSignatureStream = xSignatureStream; + } + void setModel(const css::uno::Reference& xModel); + const css::uno::Reference& getStore() const { return mxStore; } + DocumentSignatureMode getSignatureMode() const { return meSignatureMode; } + SignatureInformations& getCurrentSignatureInformations() + { + return maCurrentSignatureInformations; + } +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/framework/saxeventkeeperimpl.hxx b/xmlsecurity/inc/framework/saxeventkeeperimpl.hxx new file mode 100644 index 0000000000..161b9a9361 --- /dev/null +++ b/xmlsecurity/inc/framework/saxeventkeeperimpl.hxx @@ -0,0 +1,290 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 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> m_vElementMarkBuffers; + + /* + * maintains a list of new ElementCollectors that will be created + * on the element represented by the next incoming startElement SAX + * event. + * The reason that such the m_vNewElementCollectors is necessary + * is: when an ElementCollector is asked to create, it can't be + * created completely at once, because the BufferNode it will be + * working on has not been created until the next startElement + * SAX event comes. + */ + std::vector< const ElementCollector* > m_vNewElementCollectors; + + /* + * maintains the new Blocker that will be created + * on the element represented by the next incoming startElement SAX + * event. + */ + ElementMark* m_pNewBlocker; + + /* + * the document handler to which all received SAX events will be + * forwarded. + */ + css::uno::Reference< css::xml::sax::XDocumentHandler > m_xNextHandler; + + /* + * the current BufferNode which prevents the SAX events to be + * forwarded to the m_xNextHandler. + */ + BufferNode* m_pCurrentBlockingBufferNode; + + /* + * maintains a list of ElementMark that has been asked to release. + * Because during processing a request of releasing an ElementMark, + * another releasing ElementMark request can be invoked. To avoid + * reentering the same method, a such request only add that ElementMark + * into this ElementMark list, then all ElementMarks will be processed in + * order. + */ + std::vector< sal_Int32 > m_vReleasedElementMarkBuffers; + + /* + * a flag to indicate whether the ElementMark releasing process is running. + * When a releasing request comes, the assigned ElementMark is added to + * the m_vReleasedElementMarkBuffers first, then this flag is checked. + * If the ElementMark releasing process is not running, then call that + * method. + */ + bool m_bIsReleasing; + + /* + * a flag to indicate whether it is the "Forwarding" mode now. + * A "Forwarding" mode means that all received SAX events are from the + * XMLDocumentWrapper component, instead of up-stream component in the + * SAX chain. + * The difference between "Forwarding" mode and normal mode is that: + * no SAX events need to be transferred to the XMLDocumentWrapper component + * again even if a buffer request happens. + */ + bool m_bIsForwarding; + + void setCurrentBufferNode(BufferNode* pBufferNode); + + BufferNode* addNewElementMarkBuffers(); + + ElementMark* findElementMarkBuffer(sal_Int32 nId) const; + + void removeElementMarkBuffer(sal_Int32 nId); + + OUString printBufferNode( + BufferNode const * pBufferNode, sal_Int32 nIndent) const; + + static css::uno::Sequence< css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > > + collectChildWorkingElement(BufferNode const * pBufferNode); + + void smashBufferNode( + BufferNode* pBufferNode, bool bClearRoot) const; + + static BufferNode* findNextBlockingBufferNode( + BufferNode* pStartBufferNode); + + static void diffuse(BufferNode* pBufferNode); + + void releaseElementMarkBuffer(); + + void markElementMarkBuffer(sal_Int32 nId); + + sal_Int32 createElementCollector( + css::xml::crypto::sax::ElementMarkPriority nPriority, + bool bModifyElement, + const css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener>& xReferenceResolvedListener); + + sal_Int32 createBlocker(); + +public: + SAXEventKeeperImpl(); + virtual ~SAXEventKeeperImpl() override; + + SAXEventKeeperImpl(const SAXEventKeeperImpl&) = delete; + SAXEventKeeperImpl& operator=(const SAXEventKeeperImpl&) = delete; + + /* XSAXEventKeeper */ + virtual sal_Int32 SAL_CALL addElementCollector( ) override; + virtual void SAL_CALL removeElementCollector( sal_Int32 id ) override; + virtual sal_Int32 SAL_CALL addBlocker( ) override; + virtual void SAL_CALL removeBlocker( sal_Int32 id ) override; + virtual sal_Bool SAL_CALL isBlocking( ) override; + virtual css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > SAL_CALL + getElement( sal_Int32 id ) override; + virtual void SAL_CALL setElement( + sal_Int32 id, + const css::uno::Reference< css::xml::wrapper::XXMLElementWrapper >& aElement ) override; + virtual css::uno::Reference< + css::xml::sax::XDocumentHandler > SAL_CALL + setNextHandler( const css::uno::Reference< + css::xml::sax::XDocumentHandler >& xNewHandler ) override; + virtual OUString SAL_CALL printBufferNodeTree() override; + virtual css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > SAL_CALL + getCurrentBlockingNode() override; + + /* XSecuritySAXEventKeeper */ + virtual sal_Int32 SAL_CALL addSecurityElementCollector( + css::xml::crypto::sax::ElementMarkPriority priority, + sal_Bool modifyElement ) override; + virtual void SAL_CALL setSecurityId( sal_Int32 id, sal_Int32 securityId ) override; + + /* XReferenceResolvedBroadcaster */ + virtual void SAL_CALL addReferenceResolvedListener( + sal_Int32 referenceId, + const css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener >& listener ) override; + virtual void SAL_CALL removeReferenceResolvedListener( + sal_Int32 referenceId, + const css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener >& listener ) override; + + /* XSAXEventKeeperStatusChangeBroadcaster */ + virtual void SAL_CALL addSAXEventKeeperStatusChangeListener( + const css::uno::Reference< css::xml::crypto::sax::XSAXEventKeeperStatusChangeListener >& listener ) override; + virtual void SAL_CALL removeSAXEventKeeperStatusChangeListener( + const css::uno::Reference< css::xml::crypto::sax::XSAXEventKeeperStatusChangeListener >& listener ) override; + + /* XDocumentHandler */ + virtual void SAL_CALL startDocument( ) override; + virtual void SAL_CALL endDocument( ) override; + virtual void SAL_CALL startElement( + const OUString& aName, + const css::uno::Reference< css::xml::sax::XAttributeList >& + xAttribs ) override; + virtual void SAL_CALL endElement( const OUString& aName ) override; + virtual void SAL_CALL characters( const OUString& aChars ) override; + virtual void SAL_CALL ignorableWhitespace( const OUString& aWhitespaces ) override; + virtual void SAL_CALL processingInstruction( + const OUString& aTarget, const OUString& aData ) override; + virtual void SAL_CALL setDocumentLocator( + const css::uno::Reference< css::xml::sax::XLocator >& xLocator ) override; + + /* XInitialization */ + virtual void SAL_CALL initialize( + const css::uno::Sequence< css::uno::Any >& aArguments ) override; + + /* XServiceInfo */ + virtual OUString SAL_CALL getImplementationName( ) override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; +}; + +/// @throws css::uno::RuntimeException +OUString SAXEventKeeperImpl_getImplementationName(); + +/// @throws css::uno::RuntimeException +css::uno::Sequence< OUString > SAXEventKeeperImpl_getSupportedServiceNames( ); + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/framework/securityengine.hxx b/xmlsecurity/inc/framework/securityengine.hxx new file mode 100644 index 0000000000..bebf07306b --- /dev/null +++ b/xmlsecurity/inc/framework/securityengine.hxx @@ -0,0 +1,142 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +#include + +#include + +class SAL_DLLPUBLIC_RTTI SecurityEngine : public cppu::WeakImplHelper +< + css::xml::crypto::sax::XReferenceResolvedListener, + css::xml::crypto::sax::XKeyCollector, + css::xml::crypto::sax::XMissionTaker +> +/****** securityengine.hxx/CLASS SecurityEngine ******************************* + * + * NAME + * SecurityEngine -- Base class of SignatureEngine and EncryptionEngine + * + * FUNCTION + * Maintains common members and methods related with security engine + * operation. + ******************************************************************************/ +{ +protected: + + /* + * A SAXEventKeeper internally maintains all resources that a security + * operation needs. The m_xSAXEventKeeper member is used to release + * those resources when the security operation finishes. + */ + css::uno::Reference< css::xml::crypto::sax::XSAXEventKeeper > m_xSAXEventKeeper; + + /* + * the id of ElementCollector of the template element. + * For a signature, the template element is the Signature element, + * for an encryption, the EncryptedData/EncryptedKey element is. + */ + sal_Int32 m_nIdOfTemplateEC; + + /* + * remembers how many referenced elements have been buffered completely, + * including the key element, template element, and referenced element of + * signature. + */ + sal_Int32 m_nNumOfResolvedReferences; + + /* + * the id of ElementCollector of the key element. + * If a Signature element or EncryptedData/EncryptedKey element has + * an internal key sub-element, then this member should be -1 + */ + sal_Int32 m_nIdOfKeyEC; + + /* + * remembers whether the current operation has finished. + */ + bool m_bMissionDone; + + /* + * the Id of the security entity, a signature or encryption, which is used for + * the result listener to identify the entity. + */ + sal_Int32 m_nSecurityId; + + /* + * the status of the operation + */ + css::xml::crypto::SecurityOperationStatus m_nStatus; + + /* + * the result listener, which will receives the security operation result. + */ + css::uno::Reference< css::uno::XInterface > m_xResultListener; + +protected: + explicit SecurityEngine(); + virtual ~SecurityEngine() override {}; + + /* + * perform the security operation. + * Any derived class will implement this method respectively. + */ + /// @throws css::uno::Exception + /// @throws css::uno::RuntimeException + virtual void tryToPerform( ){}; + + /* + * clear up all resources used by this operation. + * This method is called after the operation finishes, or a End-Your-Mission + * message is received. + * Any derived class will implement this method respectively. + */ + virtual void clearUp( ) const {}; + + /* + * notifies any possible result listener. + * When verify a signature or conduct a decryption, the operation result will + * be transferred to a listener by this method. + * Any derived class will implement this method respectively. + */ + /// @throws css::uno::Exception + /// @throws css::uno::RuntimeException + virtual void notifyResultListener() const + {}; + +public: + /* XReferenceResolvedListener */ + virtual void SAL_CALL referenceResolved( sal_Int32 referenceId ) override; + + /* XKeyCollector */ + virtual void SAL_CALL setKeyId( sal_Int32 id ) override; + + /* XMissionTaker */ + virtual sal_Bool SAL_CALL endMission( ) override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/framework/signaturecreatorimpl.hxx b/xmlsecurity/inc/framework/signaturecreatorimpl.hxx new file mode 100644 index 0000000000..d0fc1dc333 --- /dev/null +++ b/xmlsecurity/inc/framework/signaturecreatorimpl.hxx @@ -0,0 +1,96 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include +#include +#include +#include +#include + +#include + +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& xSignatureTemplate) override; + +public: + explicit SignatureCreatorImpl(); + virtual ~SignatureCreatorImpl() override; + + /* XBlockerMonitor */ + virtual void SAL_CALL setBlockerId( sal_Int32 id ) override; + + /* XSignatureCreationResultBroadcaster */ + void SAL_CALL addSignatureCreationResultListener( + const css::uno::Reference< css::xml::crypto::sax::XSignatureCreationResultListener >& listener ) override; + + void SAL_CALL removeSignatureCreationResultListener( + const css::uno::Reference< css::xml::crypto::sax::XSignatureCreationResultListener >& listener ) override; + + /* XInitialization */ + virtual void SAL_CALL initialize( + const css::uno::Sequence< css::uno::Any >& aArguments ) override; + + /* XServiceInfo */ + virtual OUString SAL_CALL getImplementationName( ) override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; +}; + +/// @throws css::uno::RuntimeException +OUString SignatureCreatorImpl_getImplementationName(); + +/// @throws css::uno::RuntimeException +css::uno::Sequence< OUString > SignatureCreatorImpl_getSupportedServiceNames( ); + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/framework/signatureengine.hxx b/xmlsecurity/inc/framework/signatureengine.hxx new file mode 100644 index 0000000000..6446c2f367 --- /dev/null +++ b/xmlsecurity/inc/framework/signatureengine.hxx @@ -0,0 +1,116 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include + +namespace com::sun::star::io { class XInputStream; } +namespace com::sun::star::xml::crypto { class XXMLSignature; } +namespace rtl { template 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&) + {}; + +public: + /* XReferenceCollector */ + virtual void SAL_CALL setReferenceCount( sal_Int32 count ) override; + + virtual void SAL_CALL setReferenceId( sal_Int32 id ) override; + + /* XUriBinding */ + virtual void SAL_CALL setUriBinding( + const OUString& uri, + const css::uno::Reference< css::io::XInputStream >& aInputStream ) override; + virtual css::uno::Reference< css::io::XInputStream > + SAL_CALL getUriBinding( const OUString& uri ) override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/framework/signatureverifierimpl.hxx b/xmlsecurity/inc/framework/signatureverifierimpl.hxx new file mode 100644 index 0000000000..15c79643e0 --- /dev/null +++ b/xmlsecurity/inc/framework/signatureverifierimpl.hxx @@ -0,0 +1,88 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include +#include +#include +#include + +#include +#include + +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& xSignatureTemplate) override; + +public: + explicit SignatureVerifierImpl(); + virtual ~SignatureVerifierImpl() override; + + /* XSignatureVerifyResultBroadcaster */ + virtual void SAL_CALL addSignatureVerifyResultListener( + const css::uno::Reference< css::xml::crypto::sax::XSignatureVerifyResultListener >& listener ) override; + virtual void SAL_CALL removeSignatureVerifyResultListener( + const css::uno::Reference< css::xml::crypto::sax::XSignatureVerifyResultListener >& listener ) override; + + /* XInitialization */ + virtual void SAL_CALL initialize( + const css::uno::Sequence< css::uno::Any >& aArguments ) override; + + /* XServiceInfo */ + virtual OUString SAL_CALL getImplementationName( ) override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; + + void updateSignature( const css::uno::Reference< css::xml::crypto::XXMLSignature >& xSignature, + const css::uno::Reference< css::xml::crypto::XXMLSecurityContext >& xContext ) { m_xXMLSignature = xSignature; m_xXMLSecurityContext = xContext; } +}; + +/// @throws css::uno::RuntimeException +OUString SignatureVerifierImpl_getImplementationName(); + +/// @throws css::uno::RuntimeException +css::uno::Sequence< OUString > SignatureVerifierImpl_getSupportedServiceNames( ); + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/framework/xmlsignaturetemplateimpl.hxx b/xmlsecurity/inc/framework/xmlsignaturetemplateimpl.hxx new file mode 100644 index 0000000000..c0dee1173b --- /dev/null +++ b/xmlsecurity/inc/framework/xmlsignaturetemplateimpl.hxx @@ -0,0 +1,95 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include +#include +#include + +#include + +#include +#include + +#include + +namespace com::sun::star::lang { class XMultiServiceFactory; } +namespace com::sun::star::xml::wrapper { class XXMLElementWrapper; } + +class XMLSignatureTemplateImpl final : public ::cppu::WeakImplHelper< + css::xml::crypto::XXMLSignatureTemplate , + css::lang::XServiceInfo > +{ + private: + css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > m_xTemplate ; + std::vector< css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > > targets; + css::uno::Reference< css::xml::crypto::XUriBinding > m_xUriBinding; + css::xml::crypto::SecurityOperationStatus m_nStatus; + + public: + explicit XMLSignatureTemplateImpl(); + virtual ~XMLSignatureTemplateImpl() override; + + //Methods from XXMLSignatureTemplate + virtual void SAL_CALL setTemplate( + const css::uno::Reference< css::xml::wrapper::XXMLElementWrapper >& aXmlElement + ) override; + + virtual css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > SAL_CALL getTemplate( + ) override; + + virtual void SAL_CALL setTarget( + const css::uno::Reference< css::xml::wrapper::XXMLElementWrapper >& aXmlElement + ) override; + + virtual css::uno::Sequence< css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > > SAL_CALL getTargets( + ) override; + + virtual void SAL_CALL setBinding( + const css::uno::Reference< css::xml::crypto::XUriBinding >& aUriBinding ) override; + virtual css::uno::Reference< css::xml::crypto::XUriBinding > + SAL_CALL getBinding( ) override; + + virtual void SAL_CALL setStatus( + css::xml::crypto::SecurityOperationStatus status ) override; + virtual css::xml::crypto::SecurityOperationStatus + SAL_CALL getStatus( ) override; + + //Methods from XServiceInfo + virtual OUString SAL_CALL getImplementationName() override ; + + virtual sal_Bool SAL_CALL supportsService( + const OUString& ServiceName + ) override ; + + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override ; + + //Helper for XServiceInfo + static css::uno::Sequence< OUString > impl_getSupportedServiceNames() ; + + /// @throws css::uno::RuntimeException + static OUString impl_getImplementationName() ; + + //Helper for registry + /// @throws css::uno::RuntimeException + static css::uno::Reference< css::uno::XInterface > impl_createInstance( const css::uno::Reference< css::lang::XMultiServiceFactory >& aServiceManager ) ; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/gpg/SEInitializer.hxx b/xmlsecurity/inc/gpg/SEInitializer.hxx new file mode 100644 index 0000000000..e4da22029c --- /dev/null +++ b/xmlsecurity/inc/gpg/SEInitializer.hxx @@ -0,0 +1,47 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include +#include +#include + +#include +#include + +namespace com::sun::star::xml::crypto { class XXMLSecurityContext; } + +class XSECXMLSEC_DLLPUBLIC SEInitializerGpg final : public cppu::WeakImplHelper +< + css::xml::crypto::XSEInitializer, + css::lang::XServiceInfo +> +{ +public: + SEInitializerGpg(); + virtual ~SEInitializerGpg() override; + + /* XSEInitializer */ + virtual css::uno::Reference< css::xml::crypto::XXMLSecurityContext > + SAL_CALL createSecurityContext( const OUString& ) override; + + virtual void SAL_CALL freeSecurityContext( const css::uno::Reference< + css::xml::crypto::XXMLSecurityContext >& securityContext ) override; + + /* XServiceInfo */ + virtual OUString SAL_CALL getImplementationName( ) override; + + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/gpg/xmlsignature_gpgimpl.hxx b/xmlsecurity/inc/gpg/xmlsignature_gpgimpl.hxx new file mode 100644 index 0000000000..906a51d19c --- /dev/null +++ b/xmlsecurity/inc/gpg/xmlsignature_gpgimpl.hxx @@ -0,0 +1,77 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include +#include +#include + +#include + +#include + +#include +#include + +namespace com::sun::star::xml::crypto { class XXMLSignatureTemplate; } +namespace com::sun::star::xml::crypto { class XXMLSecurityContext; } +namespace com::sun::star::lang { class XMultiServiceFactory; } + + +class XSECXMLSEC_DLLPUBLIC XMLSignature_GpgImpl final : public ::cppu::WeakImplHelper< + css::xml::crypto::XXMLSignature , + css::lang::XServiceInfo > +{ + public: + explicit XMLSignature_GpgImpl(); + virtual ~XMLSignature_GpgImpl() override ; + + //Methods from XXMLSignature + virtual css::uno::Reference< css::xml::crypto::XXMLSignatureTemplate > SAL_CALL generate( + const css::uno::Reference< css::xml::crypto::XXMLSignatureTemplate >& aTemplate , + const css::uno::Reference< css::xml::crypto::XSecurityEnvironment >& aEnvironment + ) override ; + + virtual css::uno::Reference< css::xml::crypto::XXMLSignatureTemplate > SAL_CALL validate( + const css::uno::Reference< css::xml::crypto::XXMLSignatureTemplate >& aTemplate , + const css::uno::Reference< css::xml::crypto::XXMLSecurityContext >& aContext + ) override; + + //Methods from XServiceInfo + virtual OUString SAL_CALL getImplementationName() override ; + + virtual sal_Bool SAL_CALL supportsService( + const OUString& ServiceName + ) override ; + + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override ; + + //Helper for XServiceInfo + static css::uno::Sequence< OUString > impl_getSupportedServiceNames() ; + + /// @throws css::uno::RuntimeException + static OUString impl_getImplementationName() ; + + //Helper for registry + /// @throws css::uno::RuntimeException + static css::uno::Reference< css::uno::XInterface > impl_createInstance( const css::uno::Reference< css::lang::XMultiServiceFactory >& aServiceManager ) ; +} ; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/macrosecurity.hxx b/xmlsecurity/inc/macrosecurity.hxx new file mode 100644 index 0000000000..5d9feb94c8 --- /dev/null +++ b/xmlsecurity/inc/macrosecurity.hxx @@ -0,0 +1,126 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include +#include + +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 m_xSecurityEnvironment; + + std::unique_ptr m_xTabCtrl; + std::unique_ptr m_xOkBtn; + std::unique_ptr m_xResetBtn; + + std::unique_ptr m_xLevelTP; + std::unique_ptr m_xTrustSrcTP; + + DECL_LINK(ActivatePageHdl, const OUString&, void); + DECL_LINK(OkBtnHdl, weld::Button&, void); +public: + MacroSecurity(weld::Window* pParent, + css::uno::Reference xSecurityEnvironment); + + void EnableReset(bool bEnable = true) + { + m_xResetBtn->set_sensitive(bEnable); + } +}; + +class MacroSecurityTP +{ +protected: + std::unique_ptr m_xBuilder; + std::unique_ptr m_xContainer; + + MacroSecurity* m_pDlg; +public: + MacroSecurityTP(weld::Container* pParent, const OUString& rUIXMLDescription, + const OUString& rID, MacroSecurity* pDlg); + virtual ~MacroSecurityTP(); + + virtual void ActivatePage(); + virtual void ClosePage() = 0; +}; + +class MacroSecurityLevelTP : public MacroSecurityTP +{ +private: + sal_uInt16 mnCurLevel; + + std::unique_ptr m_xVeryHighRB; + std::unique_ptr m_xHighRB; + std::unique_ptr m_xMediumRB; + std::unique_ptr m_xLowRB; + std::unique_ptr m_xVHighImg; + std::unique_ptr m_xHighImg; + std::unique_ptr m_xMedImg; + std::unique_ptr 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 m_xTrustCertROFI; + std::unique_ptr m_xTrustCertLB; + std::unique_ptr m_xViewCertPB; + std::unique_ptr m_xRemoveCertPB; + std::unique_ptr m_xTrustFileROFI; + std::unique_ptr m_xTrustFileLocLB; + std::unique_ptr m_xAddLocPB; + std::unique_ptr m_xRemoveLocPB; + + DECL_LINK(ViewCertPBHdl, weld::Button&, void); + DECL_LINK(RemoveCertPBHdl, weld::Button&, void); + DECL_LINK(AddLocPBHdl, weld::Button&, void); + DECL_LINK(RemoveLocPBHdl, weld::Button&, void); + DECL_LINK(TrustCertLBSelectHdl, weld::TreeView&, void); + DECL_LINK(TrustFileLocLBSelectHdl, weld::TreeView&, void); + + void FillCertLB(const bool bShowWarnings = false); + void ImplCheckButtons(); + void ShowBrokenCertificateError(std::u16string_view rData); + +public: + MacroSecurityTrustedSourcesTP(weld::Container* pParent, MacroSecurity* pDlg); + + virtual void ActivatePage() override; + virtual void ClosePage() override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/pch/precompiled_xmlsecurity.cxx b/xmlsecurity/inc/pch/precompiled_xmlsecurity.cxx new file mode 100644 index 0000000000..16ace305fc --- /dev/null +++ b/xmlsecurity/inc/pch/precompiled_xmlsecurity.cxx @@ -0,0 +1,12 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "precompiled_xmlsecurity.hxx" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/pch/precompiled_xmlsecurity.hxx b/xmlsecurity/inc/pch/precompiled_xmlsecurity.hxx new file mode 100644 index 0000000000..bf9c9025a7 --- /dev/null +++ b/xmlsecurity/inc/pch/precompiled_xmlsecurity.hxx @@ -0,0 +1,200 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +/* + This file has been autogenerated by update_pch.sh. It is possible to edit it + manually (such as when an include file has been moved/renamed/removed). All such + manual changes will be rewritten by the next run of update_pch.sh (which presumably + also fixes all possible problems, so it's usually better to use it). + + Generated on 2021-04-11 19:48:55 using: + ./bin/update_pch xmlsecurity xmlsecurity --cutoff=6 --exclude:system --include:module --include:local + + If after updating build fails, use the following command to locate conflicting headers: + ./bin/update_pch_bisect ./xmlsecurity/inc/pch/precompiled_xmlsecurity.hxx "make xmlsecurity.build" --find-conflicts +*/ + +#include +#if PCH_LEVEL >= 1 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif // PCH_LEVEL >= 1 +#if PCH_LEVEL >= 2 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif // PCH_LEVEL >= 2 +#if PCH_LEVEL >= 3 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif // PCH_LEVEL >= 3 +#if PCH_LEVEL >= 4 +#include +#include +#include +#endif // PCH_LEVEL >= 4 + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/pch/precompiled_xsec_xmlsec.cxx b/xmlsecurity/inc/pch/precompiled_xsec_xmlsec.cxx new file mode 100644 index 0000000000..74123c2f14 --- /dev/null +++ b/xmlsecurity/inc/pch/precompiled_xsec_xmlsec.cxx @@ -0,0 +1,12 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "precompiled_xsec_xmlsec.hxx" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/pch/precompiled_xsec_xmlsec.hxx b/xmlsecurity/inc/pch/precompiled_xsec_xmlsec.hxx new file mode 100644 index 0000000000..d69f3120e0 --- /dev/null +++ b/xmlsecurity/inc/pch/precompiled_xsec_xmlsec.hxx @@ -0,0 +1,149 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +/* + This file has been autogenerated by update_pch.sh. It is possible to edit it + manually (such as when an include file has been moved/renamed/removed). All such + manual changes will be rewritten by the next run of update_pch.sh (which presumably + also fixes all possible problems, so it's usually better to use it). + + Generated on 2021-04-08 13:57:49 using: + ./bin/update_pch xmlsecurity xsec_xmlsec --cutoff=2 --exclude:system --include:module --include:local + + If after updating build fails, use the following command to locate conflicting headers: + ./bin/update_pch_bisect ./xmlsecurity/inc/pch/precompiled_xsec_xmlsec.hxx "make xmlsecurity.build" --find-conflicts +*/ + +#include +#if PCH_LEVEL >= 1 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef XMLSEC_CRYPTO_NSS +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#endif // PCH_LEVEL >= 1 +#if PCH_LEVEL >= 2 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif // PCH_LEVEL >= 2 +#if PCH_LEVEL >= 3 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif // PCH_LEVEL >= 3 +#if PCH_LEVEL >= 4 +#include +#include +#endif // PCH_LEVEL >= 4 + +// Cleanup windows header macro pollution. +#if defined(_WIN32) && defined(WINAPI) +#include +#undef RGB +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/pdfsignaturehelper.hxx b/xmlsecurity/inc/pdfsignaturehelper.hxx new file mode 100644 index 0000000000..ea24685d2a --- /dev/null +++ b/xmlsecurity/inc/pdfsignaturehelper.hxx @@ -0,0 +1,73 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#pragma once + +#include "xmlsecuritydllapi.h" + +#include + +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 m_xCertificate; + OUString m_aDescription; + +public: + PDFSignatureHelper(); + bool ReadAndVerifySignature(const css::uno::Reference& xInputStream); + bool ReadAndVerifySignatureSvStream(SvStream& rStream); + css::uno::Sequence + GetDocumentSignatureInformations( + const css::uno::Reference& 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& 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& xModel, + const css::uno::Reference& xInputStream, bool bAdES); + /// Remove the signature at nPosition (and all dependent signatures) from xInputStream. + static bool RemoveSignature(const css::uno::Reference& xInputStream, + sal_uInt16 nPosition); +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/resourcemanager.hxx b/xmlsecurity/inc/resourcemanager.hxx new file mode 100644 index 0000000000..1dc5b29874 --- /dev/null +++ b/xmlsecurity/inc/resourcemanager.hxx @@ -0,0 +1,26 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include + +inline OUString XsResId(TranslateId aId) { return Translate::get(aId, Translate::Create("xsc")); } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/strings.hrc b/xmlsecurity/inc/strings.hrc new file mode 100644 index 0000000000..7e99a58d52 --- /dev/null +++ b/xmlsecurity/inc/strings.hrc @@ -0,0 +1,68 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#define NC_(Context, String) TranslateId(Context, u8##String) + +#define STR_CERTIFICATE_NOT_VALIDATED NC_("STR_CERTIFICATE_NOT_VALIDATED", "The certificate could not be validated.") +#define STR_VERSION NC_("STR_VERSION", "Version") +#define STR_SERIALNUM NC_("STR_SERIALNUM", "Serial Number") +#define STR_ISSUER NC_("STR_ISSUER", "Issuer") +#define STR_VALIDFROM NC_("STR_VALIDFROM", "Valid From") +#define STR_VALIDTO NC_("STR_VALIDTO", "Valid to") +#define STR_SUBJECT NC_("STR_SUBJECT", "Subject") +#define STR_SUBJECT_PUBKEY_ALGO NC_("STR_SUBJECT_PUBKEY_ALGO", "Subject Algorithm") +#define STR_SUBJECT_PUBKEY_VAL NC_("STR_SUBJECT_PUBKEY_VAL", "Public Key") +#define STR_SIGNATURE_ALGO NC_("STR_SIGNATURE_ALGO", "Signature Algorithm") +#define STR_USE NC_("STR_USE", "Certificate Use") +#define STR_THUMBPRINT_SHA1 NC_("STR_THUMBPRINT_SHA1", "Thumbprint SHA1") +#define STR_THUMBPRINT_MD5 NC_("STR_THUMBPRINT_MD5", "Thumbprint MD5") + +#define STR_XMLSECDLG_OPENED_CRTMGR NC_("STR_XMLSECDLG_OPENED_CRTMGR", "You have opened the certificate manager at\n") +#define STR_XMLSECDLG_OLD_ODF_FORMAT NC_("STR_XMLSECDLG_OLD_ODF_FORMAT", "This document contains signatures in ODF 1.1 (OpenOffice.org 2.x) format. " \ + "Signing documents in %PRODUCTNAME %PRODUCTVERSION requires ODF 1.2 format version. " \ + "Thus no signatures can be added or removed to this document.\n\n" \ + "Save document in ODF 1.2 format and add all desired signatures again.") +#define STR_XMLSECDLG_QUERY_REMOVEDOCSIGNBEFORESIGN NC_("STR_XMLSECDLG_QUERY_REMOVEDOCSIGNBEFORESIGN", "Adding or removing a macro signature will remove all document signatures.\n" \ + "Do you really want to continue?") +#define STR_XMLSECDLG_QUERY_REALLYREMOVE NC_("STR_XMLSECDLG_QUERY_REALLYREMOVE", "Document signature cannot be restored, once removed.\n" \ + "Do you really want to remove selected signature?") + +#define STR_XMLSECDLG_SIGNING_FAILED NC_("STR_XMLSECDLG_SIGNING_FAILED", "An error occurred while adding the signature.") +#define STR_XMLSECDLG_NO_CERT_MANAGER NC_("STR_XMLSECDLG_NO_CERT_MANAGER", "Could not find any certificate manager.") +#define STR_XMLSECDLG_NO_CERT_FOUND NC_("STR_XMLSECDLG_NO_CERT_FOUND", "Could not find the certificate.") + +#define RID_XMLSECWB_NO_MOZILLA_PROFILE NC_("RID_XMLSECWB_NO_MOZILLA_PROFILE", "Digital signatures functionality could not be used, because no Mozilla user profile was found. Please check the Mozilla installation.") + +#define STR_DIGITAL_SIGNATURE NC_("selectcertificatedialog|STR_DIGITAL_SIGNATURE", "Digital signature") +#define STR_NON_REPUDIATION NC_("selectcertificatedialog|STR_NON_REPUDIATION", "Non-repudiation") +#define STR_KEY_ENCIPHERMENT NC_("selectcertificatedialog|STR_KEY_ENCIPHERMENT", "Key encipherment") +#define STR_DATA_ENCIPHERMENT NC_("selectcertificatedialog|STR_DATA_ENCIPHERMENT", "Data encipherment") +#define STR_KEY_AGREEMENT NC_("selectcertificatedialog|STR_KEY_AGREEMENT", "Key Agreement") +#define STR_KEY_CERT_SIGN NC_("selectcertificatedialog|STR_KEY_CERT_SIGN", "Certificate signature verification") +#define STR_CRL_SIGN NC_("selectcertificatedialog|STR_CRL_SIGN", "CRL signature verification") +#define STR_ENCIPHER_ONLY NC_("selectcertificatedialog|STR_ENCIPHER_ONLY", "Only for encipherment") +#define STR_SIGN NC_("selectcertificatedialog|str_sign", "Sign") +#define STR_SELECTSIGN NC_("selectcertificatedialog|str_selectsign", "Select") +#define STR_ENCRYPT NC_("selectcertificatedialog|str_encrypt", "Encrypt") + +#define STR_BROKEN_MACRO_CERTIFICATE_DATA NC_("STR_BROKEN_MACRO_CERTIFICATE_DATA", "Macro security problem!\n\nBroken certificate data: %{data}") + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/xmlsec-wrapper.h b/xmlsecurity/inc/xmlsec-wrapper.h new file mode 100644 index 0000000000..3ad705400c --- /dev/null +++ b/xmlsecurity/inc/xmlsec-wrapper.h @@ -0,0 +1,43 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef XMLSEC_CRYPTO_NSS +#include +#include +#include +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/xmlsec/errorcallback.hxx b/xmlsecurity/inc/xmlsec/errorcallback.hxx new file mode 100644 index 0000000000..80ba564e9b --- /dev/null +++ b/xmlsecurity/inc/xmlsec/errorcallback.hxx @@ -0,0 +1,30 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include + +// Only used for logging +void setErrorRecorder(); +//ToDo +//void setErrorRecorder(const css::uno::Reference< css::xml::crypto::XXMLEncryptionTemplate >& xTemplate); +void clearErrorRecorder(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/xmlsec/saxhelper.hxx b/xmlsecurity/inc/xmlsec/saxhelper.hxx new file mode 100644 index 0000000000..a5863ffd0e --- /dev/null +++ b/xmlsecurity/inc/xmlsec/saxhelper.hxx @@ -0,0 +1,86 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include + +#include + +#include +#include + +#include + +namespace com::sun::star::xml::csax { struct XMLAttribute; } +namespace com::sun::star::uno { template class Sequence; } + +/** This class represents a SAX handler which simply forwards to + the corresponding libxml API and translates parameter if necessary. +*/ +class SAXHelper final +{ + private: + xmlParserCtxtPtr m_pParserCtxt ; + xmlSAXHandlerPtr m_pSaxHandler ; + + public: + SAXHelper( ) ; + ~SAXHelper() ; + + xmlNodePtr getCurrentNode() { return m_pParserCtxt->node;} + void setCurrentNode(const xmlNodePtr pNode); + xmlDocPtr getDocument() { return m_pParserCtxt->myDoc;} + + /// @throws css::xml::sax::SAXException + /// @throws css::uno::RuntimeException + void startDocument() ; + + /// @throws css::xml::sax::SAXException + /// @throws css::uno::RuntimeException + void endDocument() ; + + /// @throws css::xml::sax::SAXException + /// @throws css::uno::RuntimeException + void startElement( + std::u16string_view aName , + const css::uno::Sequence< + css::xml::csax::XMLAttribute >& aAttributes ) ; + + /// @throws css::xml::sax::SAXException + /// @throws css::uno::RuntimeException + void endElement( std::u16string_view aName ) ; + + /// @throws css::xml::sax::SAXException + /// @throws css::uno::RuntimeException + void characters( std::u16string_view aChars ) ; + + /// @throws css::xml::sax::SAXException + /// @throws css::uno::RuntimeException + void ignorableWhitespace( std::u16string_view aWhitespaces ) ; + + /// @throws css::xml::sax::SAXException + /// @throws css::uno::RuntimeException + void processingInstruction( + std::u16string_view aTarget , + std::u16string_view aData ) ; + +} ; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/xmlsec/xmldocumentwrapper_xmlsecimpl.hxx b/xmlsecurity/inc/xmlsec/xmldocumentwrapper_xmlsecimpl.hxx new file mode 100644 index 0000000000..8f5695d10d --- /dev/null +++ b/xmlsecurity/inc/xmlsec/xmldocumentwrapper_xmlsecimpl.hxx @@ -0,0 +1,208 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include +#include +#include +#include + +#include +#include + +#define NODEPOSITION_NORMAL 1 +#define NODEPOSITION_STARTELEMENT 2 +#define NODEPOSITION_ENDELEMENT 3 + +#include + +class XSECXMLSEC_DLLPUBLIC XMLDocumentWrapper_XmlSecImpl final : public cppu::WeakImplHelper +< + css::xml::wrapper::XXMLDocumentWrapper, + css::xml::sax::XDocumentHandler, + css::xml::csax::XCompressedDocumentHandler, + css::lang::XServiceInfo +> +/** + * NAME + * XMLDocumentWrapper_XmlSecImpl -- Class to manipulate a libxml2 + * document + * + * FUNCTION + * Converts SAX events into a libxml2 document, converts the document back + * into SAX event stream, and manipulate nodes in the document. + ******************************************************************************/ +{ +private: + /* the sax helper */ + SAXHelper saxHelper; + + /* the document used to convert SAX events to */ + xmlDocPtr m_pDocument; + + /* the root element */ + xmlNodePtr m_pRootElement; + + /* + * the current active element. The next incoming SAX event will be + * appended to this element + */ + xmlNodePtr m_pCurrentElement; + + /* + * This variable is used when converting the document or part of it into + * SAX events. See getNextSAXEvent method. + */ + sal_Int32 m_nCurrentPosition; + + /* + * used for recursive deletion. See recursiveDelete method + */ + xmlNodePtr m_pStopAtNode; + xmlNodePtr m_pCurrentReservedNode; + css::uno::Sequence< css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > > m_aReservedNodes; + sal_Int32 m_nReservedNodeIndex; + +private: + void getNextSAXEvent(); + + /// @throws css::xml::sax::SAXException + static void sendStartElement( + const css::uno::Reference< css::xml::sax::XDocumentHandler >& xHandler, + const css::uno::Reference< css::xml::sax::XDocumentHandler >& xHandler2, + const xmlNodePtr pNode); + + /// @throws css::xml::sax::SAXException + static void sendEndElement( + const css::uno::Reference< css::xml::sax::XDocumentHandler >& xHandler, + const css::uno::Reference< css::xml::sax::XDocumentHandler >& xHandler2, + const xmlNodePtr pNode); + + /// @throws css::xml::sax::SAXException + static void sendNode( + const css::uno::Reference< css::xml::sax::XDocumentHandler >& xHandler, + const css::uno::Reference< css::xml::sax::XDocumentHandler >& xHandler2, + const xmlNodePtr pNode); + + static OString getNodeQName(const xmlNodePtr pNode); + + sal_Int32 recursiveDelete( const xmlNodePtr pNode); + + void getNextReservedNode(); + + void removeNode( const xmlNodePtr pNode) const; + + static xmlNodePtr checkElement( + const css::uno::Reference< css::xml::wrapper::XXMLElementWrapper >& xXMLElement); + + void buildIDAttr( xmlNodePtr pNode ) const; + void rebuildIDLink( xmlNodePtr pNode ) const; + +public: + XMLDocumentWrapper_XmlSecImpl(); + virtual ~XMLDocumentWrapper_XmlSecImpl() override; + + /* css::xml::wrapper::XXMLDocumentWrapper */ + virtual css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > SAL_CALL getCurrentElement( ) override; + + virtual void SAL_CALL setCurrentElement( const css::uno::Reference< + css::xml::wrapper::XXMLElementWrapper >& element ) override; + + virtual void SAL_CALL removeCurrentElement( ) override; + + virtual sal_Bool SAL_CALL isCurrent( const css::uno::Reference< + css::xml::wrapper::XXMLElementWrapper >& node ) override; + + virtual sal_Bool SAL_CALL isCurrentElementEmpty( ) override; + + virtual OUString SAL_CALL getNodeName( const css::uno::Reference< + css::xml::wrapper::XXMLElementWrapper >& node ) override; + + virtual void SAL_CALL clearUselessData( + const css::uno::Reference< css::xml::wrapper::XXMLElementWrapper >& node, + const css::uno::Sequence< css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > >& reservedDescendants, + const css::uno::Reference< css::xml::wrapper::XXMLElementWrapper >& stopAtNode ) override; + + virtual void SAL_CALL collapse( const css::uno::Reference< + css::xml::wrapper::XXMLElementWrapper >& node ) override; + + virtual void SAL_CALL generateSAXEvents( + const css::uno::Reference< css::xml::sax::XDocumentHandler >& handler, + const css::uno::Reference< css::xml::sax::XDocumentHandler >& xEventKeeperHandler, + const css::uno::Reference< css::xml::wrapper::XXMLElementWrapper >& startNode, + const css::uno::Reference< css::xml::wrapper::XXMLElementWrapper >& endNode ) override; + + virtual void SAL_CALL getTree( + const css::uno::Reference< css::xml::sax::XDocumentHandler >& handler ) override; + + virtual void SAL_CALL rebuildIDLink( + const css::uno::Reference< css::xml::wrapper::XXMLElementWrapper >& node ) override; + + /* css::xml::sax::XDocumentHandler */ + virtual void SAL_CALL startDocument( ) override; + + virtual void SAL_CALL endDocument( ) override; + + virtual void SAL_CALL startElement( + const OUString& aName, + const css::uno::Reference< css::xml::sax::XAttributeList >& xAttribs ) override; + + virtual void SAL_CALL endElement( const OUString& aName ) override; + + virtual void SAL_CALL characters( const OUString& aChars ) override; + + virtual void SAL_CALL ignorableWhitespace( const OUString& aWhitespaces ) override; + + virtual void SAL_CALL processingInstruction( const OUString& aTarget, const OUString& aData ) override; + + virtual void SAL_CALL setDocumentLocator( const css::uno::Reference< css::xml::sax::XLocator >& xLocator ) override; + + /* css::xml::csax::XCompressedDocumentHandler */ + virtual void SAL_CALL compressedStartDocument( ) override; + + virtual void SAL_CALL compressedEndDocument( ) override; + + virtual void SAL_CALL compressedStartElement( + const OUString& aName, + const css::uno::Sequence< css::xml::csax::XMLAttribute >& aAttributes ) override; + + virtual void SAL_CALL compressedEndElement( const OUString& aName ) override; + + virtual void SAL_CALL compressedCharacters( const OUString& aChars ) override; + + virtual void SAL_CALL compressedIgnorableWhitespace( const OUString& aWhitespaces ) override; + + virtual void SAL_CALL compressedProcessingInstruction( const OUString& aTarget, const OUString& aData ) override; + + virtual void SAL_CALL compressedSetDocumentLocator( + sal_Int32 columnNumber, + sal_Int32 lineNumber, + const OUString& publicId, + const OUString& systemId ) override; + + /* css::lang::XServiceInfo */ + virtual OUString SAL_CALL getImplementationName( ) override; + + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/xmlsec/xmlsec_init.hxx b/xmlsecurity/inc/xmlsec/xmlsec_init.hxx new file mode 100644 index 0000000000..417acd288b --- /dev/null +++ b/xmlsecurity/inc/xmlsec/xmlsec_init.hxx @@ -0,0 +1,17 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include + +XSECXMLSEC_DLLPUBLIC void initXmlSec(); +XSECXMLSEC_DLLPUBLIC void deInitXmlSec(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/xmlsec/xmlstreamio.hxx b/xmlsecurity/inc/xmlsec/xmlstreamio.hxx new file mode 100644 index 0000000000..6e3d506a4d --- /dev/null +++ b/xmlsecurity/inc/xmlsec/xmlstreamio.hxx @@ -0,0 +1,39 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include + +namespace com::sun::star::xml::crypto +{ +class XUriBinding; +} +namespace com::sun::star::uno +{ +template class Reference; +} + +int xmlEnableStreamInputCallbacks(); +void xmlDisableStreamInputCallbacks(); +int xmlRegisterStreamInputCallbacks( + css::uno::Reference const& aUriBinding); +int xmlUnregisterStreamInputCallbacks(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/xmlsecuritydllapi.h b/xmlsecurity/inc/xmlsecuritydllapi.h new file mode 100644 index 0000000000..7f31e6f8f4 --- /dev/null +++ b/xmlsecurity/inc/xmlsecuritydllapi.h @@ -0,0 +1,20 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include + +#if defined(XMLSECURITY_DLLIMPLEMENTATION) +#define XMLSECURITY_DLLPUBLIC SAL_DLLPUBLIC_EXPORT +#else +#define XMLSECURITY_DLLPUBLIC SAL_DLLPUBLIC_IMPORT +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/xmlsignaturehelper.hxx b/xmlsecurity/inc/xmlsignaturehelper.hxx new file mode 100644 index 0000000000..d6e2b90eeb --- /dev/null +++ b/xmlsecurity/inc/xmlsignaturehelper.hxx @@ -0,0 +1,176 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include +#include +#include +#include +#include "xmlsecuritydllapi.h" +#include "xmlsignaturehelper.hxx" +#include "xsecctl.hxx" + +#include +#include + +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 mxUriBinding; + + rtl::Reference mpXSecController; + bool mbError; + bool mbODFPre1_2; + Link maStartVerifySignatureHdl; + +private: + XMLSignatureHelper(const XMLSignatureHelper&) = delete; + +public: + XMLSignatureHelper(const css::uno::Reference< css::uno::XComponentContext >& mrCtx ); + ~XMLSignatureHelper(); + + void StartVerifySignatureElement(); + + // Set the storage which should be used by the default UriBinding + // Must be set before StartMission(). + //sODFVersion indicates the ODF version + void SetStorage( const css::uno::Reference < css::embed::XStorage >& rxStorage, std::u16string_view sODFVersion ); + + // Argument for the Link is a uno::Reference< xml::sax::XAttributeList >* + // Return 1 to verify, 0 to skip. + // Default handler will verify all. + void SetStartVerifySignatureHdl( const Link& 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> + CheckAndUpdateSignatureInformation( + css::uno::Reference const& xSecEnv, + SignatureInformation const& rInfo); + + // See XSecController for documentation + void StartMission(const css::uno::Reference& 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& xValidGraphic); + void SetSignatureLineInvalidGraphic( + sal_Int32 nSecurityId, const css::uno::Reference& 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& xStorage, bool bCacheLastSignature = true); + /// Read and verify a single OOXML signature. + bool ReadAndVerifySignatureStorageStream(const css::uno::Reference& xInputStream); + /// Adds or removes an OOXML digital signature relation to _rels/.rels if there wasn't any before. + void EnsureSignaturesRelation(const css::uno::Reference& xStorage, bool bAdd); + /// Given that xStorage is an OOXML _xmlsignatures storage, create origin.sigs and its relations. + void ExportSignatureRelations(const css::uno::Reference& xStorage, int nSignatureCount); + /// Given that xSignatureStorage is an OOXML _xmlsignatures storage, create and write a new signature. + void CreateAndWriteOOXMLSignature(const css::uno::Reference& xRootStorage, const css::uno::Reference& 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& xRootStorage, const css::uno::Reference& 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& xStorage, int nSignatureCount); +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/xsecctl.hxx b/xmlsecurity/inc/xsecctl.hxx new file mode 100644 index 0000000000..558301a796 --- /dev/null +++ b/xmlsecurity/inc/xsecctl.hxx @@ -0,0 +1,408 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include + +#include +#include +#include + +#include +#include + +#include + +#include "UriBindingHelper.hxx" + +namespace com::sun::star::embed { class XStorage; } +namespace com::sun::star::graphic { class XGraphic; } +namespace com::sun::star::io { class XInputStream; } +namespace com::sun::star::lang { class XInitialization; } +namespace com::sun::star::uno { class XComponentContext; } +namespace com::sun::star::xml::crypto { class XXMLSecurityContext; } +namespace com::sun::star::xml::crypto { class XXMLSignature; } +namespace com::sun::star::xml::crypto:: sax { class XReferenceResolvedListener; } +namespace com::sun::star::xml::sax { class XDocumentHandler; } + +inline constexpr OUString NS_XMLDSIG = u"http://www.w3.org/2000/09/xmldsig#"_ustr; +inline constexpr OUString NS_DC = u"http://purl.org/dc/elements/1.1/"_ustr; +inline constexpr OUString NS_XD = u"http://uri.etsi.org/01903/v1.3.2#"_ustr; +inline constexpr OUString NS_MDSSI = u"http://schemas.openxmlformats.org/package/2006/digital-signature"_ustr; +inline constexpr OUString NS_LOEXT = u"urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0"_ustr; + +inline constexpr OUString ALGO_C14N = u"http://www.w3.org/TR/2001/REC-xml-c14n-20010315"_ustr; +inline constexpr OUString ALGO_RSASHA1 = u"http://www.w3.org/2000/09/xmldsig#rsa-sha1"_ustr; +inline constexpr OUString ALGO_RSASHA256 = u"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"_ustr; +inline constexpr OUString ALGO_RSASHA512 = u"http://www.w3.org/2001/04/xmldsig-more#rsa-sha512"_ustr; +inline constexpr OUString ALGO_ECDSASHA1 = u"http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1"_ustr; +inline constexpr OUString ALGO_ECDSASHA256 = u"http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256"_ustr; +inline constexpr OUString ALGO_ECDSASHA512 = u"http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512"_ustr; +inline constexpr OUString ALGO_XMLDSIGSHA1 = u"http://www.w3.org/2000/09/xmldsig#sha1"_ustr; +inline constexpr OUString ALGO_XMLDSIGSHA256 = u"http://www.w3.org/2001/04/xmlenc#sha256"_ustr; +inline constexpr OUString ALGO_XMLDSIGSHA512 = u"http://www.w3.org/2001/04/xmlenc#sha512"_ustr; +inline constexpr OUString ALGO_RELATIONSHIP = u"http://schemas.openxmlformats.org/package/2006/RelationshipTransform"_ustr; + +class XMLDocumentWrapper_XmlSecImpl; +class SAXEventKeeperImpl; +class XMLSignatureHelper; +namespace svl::crypto { enum class SignatureMethodAlgorithm; } + +class InternalSignatureInformation +{ +public: + SignatureInformation signatureInfor; + + css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > xReferenceResolvedListener; + + ::std::vector< sal_Int32 > vKeeperIds; + + InternalSignatureInformation( + sal_Int32 nId, + css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > const & xListener) + :signatureInfor(nId) + { + xReferenceResolvedListener = xListener; + } + + void addReference( SignatureReferenceType type, sal_Int32 digestID, const OUString& uri, sal_Int32 keeperId, const OUString& rType ) + { + signatureInfor.vSignatureReferenceInfors.push_back( + SignatureReferenceInformation(type, digestID, uri, rType)); + vKeeperIds.push_back( keeperId ); + } +}; + +class XSecController final : public cppu::WeakImplHelper +< + css::xml::crypto::sax::XSAXEventKeeperStatusChangeListener, + css::xml::crypto::sax::XSignatureCreationResultListener, + css::xml::crypto::sax::XSignatureVerifyResultListener +> +/****** XSecController.hxx/CLASS XSecController ******************************* + * + * NAME + * XSecController -- the xml security framework controller + * + * FUNCTION + * Controls the whole xml security framework to create signatures or to + * verify signatures. + * + ******************************************************************************/ +{ + friend class XSecParser; + friend class OOXMLSecParser; + +private: + css::uno::Reference< css::uno::XComponentContext> mxCtx; + + /* + * used to buffer SAX events + */ + rtl::Reference m_xXMLDocumentWrapper; + + /* + * the SAX events keeper + */ + rtl::Reference 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 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 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 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 . + 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> & rX509IssuerSerials, + std::vector 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& rBytes); + +private: + void setId( OUString const & ouId ); + + css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > prepareSignatureToRead( + sal_Int32 nSecurityId ); + +public: + explicit XSecController(css::uno::Reference xCtx); + virtual ~XSecController() override; + + sal_Int32 getNewSecurityId( ); + + void startMission(const rtl::Reference& xUriBinding, const css::uno::Reference& 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 && 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& xValidGraphic); + void setSignatureLineInvalidGraphic( + sal_Int32 nSecurityId, const css::uno::Reference& 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 element. + bool WriteOOXMLSignature(const css::uno::Reference& xRootStorage, const css::uno::Reference& xDocumentHandler); + /// Exports an OOXML signature, called by WriteOOXMLSignature(). + void exportOOXMLSignature(const css::uno::Reference& xRootStorage, const css::uno::Reference& xDocumentHandler, const SignatureInformation& rInformation); +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/xsecxmlsecdllapi.h b/xmlsecurity/inc/xsecxmlsecdllapi.h new file mode 100644 index 0000000000..36f8ad52ac --- /dev/null +++ b/xmlsecurity/inc/xsecxmlsecdllapi.h @@ -0,0 +1,20 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include + +#if defined(XSECXMLSEC_DLLIMPLEMENTATION) +#define XSECXMLSEC_DLLPUBLIC SAL_DLLPUBLIC_EXPORT +#else +#define XSECXMLSEC_DLLPUBLIC SAL_DLLPUBLIC_IMPORT +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/qa/certext/SanCertExt.cxx b/xmlsecurity/qa/certext/SanCertExt.cxx new file mode 100644 index 0000000000..c117f4c001 --- /dev/null +++ b/xmlsecurity/qa/certext/SanCertExt.cxx @@ -0,0 +1,260 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "cppunit/TestAssert.h" +#include "cppunit/TestFixture.h" +#include "cppunit/extensions/HelperMacros.h" +#include "cppunit/plugin/TestPlugIn.h" +#include +#include + +#include + +using namespace com::sun::star; + +#define OID_SUBJECT_ALTERNATIVE_NAME "2.5.29.17" + + +namespace { + + class Test: public CppUnit::TestFixture { + + private: + static uno::Sequence< security::CertAltNameEntry > altNames; + static bool runOnce; + + uno::Reference< xml::crypto::XSecurityEnvironment > initUno(); + void init(); + OString getB64CertFromFile(const char filename[]); + test::OfficeConnection connection_; + + public: + + Test(); + + ~Test(); + + void test_Others(); + + void test_RFC822(); + + void test_DNS(); + + void test_Directory(); + + void test_URI(); + + void test_IP(); + + void test_RID(); + + void test_EDI(); + + void test_X400(); + + CPPUNIT_TEST_SUITE(Test); + CPPUNIT_TEST(test_Others); + CPPUNIT_TEST(test_RFC822); + CPPUNIT_TEST(test_DNS); + CPPUNIT_TEST(test_Directory); + CPPUNIT_TEST(test_URI); + CPPUNIT_TEST(test_IP); + CPPUNIT_TEST(test_RID); + CPPUNIT_TEST(test_EDI); + CPPUNIT_TEST(test_X400); + CPPUNIT_TEST_SUITE_END(); + }; + + uno::Sequence< security::CertAltNameEntry > Test::altNames; + bool Test::runOnce = false; + + CPPUNIT_TEST_SUITE_REGISTRATION(Test); + + Test::Test() + { + if (runOnce) + return; + runOnce = true; + connection_.setUp(); + init(); + } + + Test::~Test() + { + if (runOnce) + { + connection_.tearDown(); + runOnce = false; + } + } + + + uno::Reference< xml::crypto::XSecurityEnvironment > Test::initUno() + { + uno::Reference< uno::XComponentContext > context(connection_.getComponentContext(), uno::UNO_QUERY_THROW); + uno::Reference< lang::XMultiServiceFactory > factory(context->getServiceManager(), uno::UNO_QUERY_THROW); + uno::Reference< xml::crypto::XSEInitializer > xSEInitializer = xml::crypto::SEInitializer::create(context); + uno::Reference< xml::crypto::XXMLSecurityContext > xSecurityContext( + xSEInitializer->createSecurityContext(OUString())); + return xSecurityContext->getSecurityEnvironment(); + } + + + void Test::init() + { + uno::Reference< xml::crypto::XSecurityEnvironment > xSecurityEnv = initUno(); + OString b64Cert(getB64CertFromFile("User_35_Root_11.crt")); + uno::Reference< security::XCertificate > xCert = xSecurityEnv->createCertificateFromAscii( + OStringToOUString( b64Cert, RTL_TEXTENCODING_ASCII_US ) ); + uno::Sequence< uno::Reference< security::XCertificateExtension > > extensions = xCert->getExtensions(); + for (sal_Int32 i = 0 ; i < extensions.getLength(); i++) + { + uno::Reference< security::XCertificateExtension >element = extensions[i]; + OString aId ( (const char *)element->getExtensionId().getArray(), element->getExtensionId().getLength()); + if (aId.equals(OID_SUBJECT_ALTERNATIVE_NAME)) + { + uno::Reference< security::XSanExtension > sanExtension ( element, uno::UNO_QUERY ); + altNames = sanExtension->getAlternativeNames(); + break; + } + } + } + + OString Test::getB64CertFromFile(const char filename[]) + { + ne_ssl_certificate* cert = ne_ssl_cert_read(filename); + char* certExportB64 = ne_ssl_cert_export(cert); + OString certB64( certExportB64 ); + return certB64; + } + + + void Test::test_Others() { + CPPUNIT_ASSERT_ASSERTION_PASS( CPPUNIT_ASSERT( altNames.getLength() > 0 ) ); + for(int n = 1; n < altNames.getLength(); n++) + { + if (altNames[n].Type == security::ExtAltNameType_OTHER_NAME) + { + css::beans::NamedValue otherNameProp; + if (altNames[n].Value >>= otherNameProp) + { + CPPUNIT_ASSERT_EQUAL( OUString("1.2.3.4"), otherNameProp.Name); + uno::Sequence< sal_Int8 > ipAddress; + otherNameProp.Value >>= ipAddress; + CPPUNIT_ASSERT_ASSERTION_PASS( CPPUNIT_ASSERT( ipAddress.getLength() > 0 ) ); + } + } + } + } + + void Test::test_RFC822() { + CPPUNIT_ASSERT_ASSERTION_PASS( CPPUNIT_ASSERT( altNames.getLength() > 0 ) ); + for(int n = 1; n < altNames.getLength(); n++) + { + if (altNames[n].Type == security::ExtAltNameType_RFC822_NAME) + { + OUString value; + altNames[n].Value >>= value; + CPPUNIT_ASSERT_EQUAL( OUString("my@other.address"), value); + } + } + } + + void Test::test_DNS() { + CPPUNIT_ASSERT_ASSERTION_PASS( CPPUNIT_ASSERT( altNames.getLength() > 0 ) ); + for(int n = 1; n < altNames.getLength(); n++) + { + if (altNames[n].Type == security::ExtAltNameType_DNS_NAME) + { + OUString value; + altNames[n].Value >>= value; + CPPUNIT_ASSERT_EQUAL( OUString("alt.openoffice.org"), value); + } + } + } + + void Test::test_Directory() { + // Not implemented + } + + void Test::test_URI() { + CPPUNIT_ASSERT_ASSERTION_PASS( CPPUNIT_ASSERT( altNames.getLength() > 0 ) ); + for(int n = 1; n < altNames.getLength(); n++) + { + if (altNames[n].Type == security::ExtAltNameType_URL) + { + OUString value; + altNames[n].Value >>= value; + CPPUNIT_ASSERT_EQUAL( OUString("http://my.url.here/"), value); + } + } + } + + void Test::test_IP() { + CPPUNIT_ASSERT_ASSERTION_PASS( CPPUNIT_ASSERT( altNames.getLength() > 0 ) ); + for(int n = 1; n < altNames.getLength(); n++) + { + if (altNames[n].Type == security::ExtAltNameType_IP_ADDRESS) + { + uno::Sequence< sal_Int8 > ipAddress; + altNames[n].Value >>= ipAddress; + CPPUNIT_ASSERT_ASSERTION_PASS( CPPUNIT_ASSERT( ipAddress.getLength() > 0 ) ); + } + } + + } + + void Test::test_RID() { + CPPUNIT_ASSERT_ASSERTION_PASS( CPPUNIT_ASSERT( altNames.getLength() > 0 ) ); + for(int n = 1; n < altNames.getLength(); n++) + { + if (altNames[n].Type == security::ExtAltNameType_REGISTERED_ID) + { + OUString value; + altNames[n].Value >>= value; + CPPUNIT_ASSERT( OUString("1.2.3.4").equals(value)); + } + } + } + + void Test::test_EDI() { + // Not implemented + } + + void Test::test_X400() { + // Not implemented + } +} +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/qa/certext/User_35_Root_11.crt b/xmlsecurity/qa/certext/User_35_Root_11.crt new file mode 100644 index 0000000000..0092d16c7a --- /dev/null +++ b/xmlsecurity/qa/certext/User_35_Root_11.crt @@ -0,0 +1,64 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4130 (0x1022) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Nov 8 10:51:39 2010 GMT + Not After : Nov 8 10:51:39 2011 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 35 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:9b:36:00:64:f3:ce:93:97:62:19:fa:78:d9:6f: + 92:6a:b9:d2:9a:4e:06:2c:02:52:cd:93:50:84:28: + 19:42:a2:4a:34:e2:cd:e6:b0:39:7a:c8:4d:84:bc: + 71:51:ed:5d:6c:7e:f9:cc:01:5a:4b:73:50:a9:3b: + 5d:ad:cc:89:f7:dc:e0:dd:0a:ff:48:01:a9:34:19: + c0:6a:ee:4b:20:f4:cf:3c:94:c1:ae:88:0f:c9:42: + 1a:a6:47:31:fe:37:04:00:bb:ec:07:5f:cb:ee:70: + c4:c7:7c:6f:ee:03:19:76:de:0b:df:d0:48:91:67: + 55:9b:90:91:f4:ce:56:04:d5 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 91:47:AC:29:95:5D:EF:72:14:8F:82:45:07:E2:94:49:75:C6:7D:73 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DNS:alt.openoffice.org, IP Address:192.168.7.1, IP Address:13:0:0:0:0:0:0:17, email:my@other.address, Registered ID:1.2.3.4, othername:, DirName:/C=DE/O=OpenOffice.org/OU=Development/CN=User 32 Root 11, URI:http://my.url.here/ + Signature Algorithm: sha1WithRSAEncryption + 6e:80:e6:1e:86:3d:d2:65:a6:17:fa:80:2d:2e:dc:85:32:05: + a1:69:82:e1:79:d1:dc:de:69:cd:9e:f0:cc:90:75:a9:45:ee: + 73:46:fe:29:69:c0:99:bb:fc:3a:db:c0:5f:69:c6:b7:ea:9a: + 63:b2:8e:29:2c:a5:5a:88:88:94:75:4b:ab:0a:72:f6:3a:aa: + 5d:6b:3a:5c:b6:9b:57:f5:c1:51:af:df:3c:a6:8a:a3:da:70: + 66:61:49:12:06:78:98:9f:bc:78:3c:43:6d:08:94:aa:32:b6: + f3:cc:af:0d:29:fe:96:47:7d:fe:4a:61:48:90:11:0b:bd:0f: + a0:fd +-----BEGIN CERTIFICATE----- +MIIDajCCAtOgAwIBAgICECIwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDExMDgxMDUx +MzlaFw0xMTExMDgxMDUxMzlaMGAxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxEDAOBgNVBAMTB1VzZXIgMzUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB +AJs2AGTzzpOXYhn6eNlvkmq50ppOBiwCUs2TUIQoGUKiSjTizeawOXrITYS8cVHt +XWx++cwBWktzUKk7Xa3Miffc4N0K/0gBqTQZwGruSyD0zzyUwa6ID8lCGqZHMf43 +BAC77Adfy+5wxMd8b+4DGXbeC9/QSJFnVZuQkfTOVgTVAgMBAAGjggExMIIBLTAL +BgNVHQ8EBAMCBeAwHQYDVR0OBBYEFJFHrCmVXe9yFI+CRQfilEl1xn1zMB8GA1Ud +IwQYMBaAFOhqu8KQ6mxwIj729kgbA+a+t6ZVMIHdBgNVHREEgdUwgdKCEmFsdC5v +cGVub2ZmaWNlLm9yZ4cEwKgHAYcQABMAAAAAAAAAAAAAAAAAF4EQbXlAb3RoZXIu +YWRkcmVzc4gDKgMEoB4GAyoDBKAXDBVzb21lIG90aGVyIGlkZW50aWZpZXKkWDBW +MQswCQYDVQQGEwJERTEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsT +C0RldmVsb3BtZW50MRgwFgYDVQQDEw9Vc2VyIDMyIFJvb3QgMTGGE2h0dHA6Ly9t +eS51cmwuaGVyZS8wDQYJKoZIhvcNAQEFBQADgYEAboDmHoY90mWmF/qALS7chTIF +oWmC4XnR3N5pzZ7wzJB1qUXuc0b+KWnAmbv8OtvAX2nGt+qaY7KOKSylWoiIlHVL +qwpy9jqqXWs6XLabV/XBUa/fPKaKo9pwZmFJEgZ4mJ+8eDxDbQiUqjK288yvDSn+ +lkd9/kphSJARC70PoP0= +-----END CERTIFICATE----- diff --git a/xmlsecurity/qa/create-certs/create-certs.sh b/xmlsecurity/qa/create-certs/create-certs.sh new file mode 100755 index 0000000000..5a4c244c6b --- /dev/null +++ b/xmlsecurity/qa/create-certs/create-certs.sh @@ -0,0 +1,187 @@ +#!/usr/bin/env bash +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# The purpose of this script is to create certificates to be able to test ODF signing code. +# +# What it does: +# +# 1) Create a test root CA. +# +# 2) Create an intermediate CA, as signing certificates with a root CA is +# considered unsafe. +# +# 3) Create two client certificates that can be used to sign ODF documents in +# LibreOffice. +# +# References: +# +# for most of the +# commands. +# +# for +# the PKCS#12 export of self-signed certificates +# + +set -e + +root="$PWD" +algo="RSA" + +if [ -n "$1" ]; then + algo="$1" +fi + +if [ -d "$root/ca" ]; then + echo "'ca' directory already exists in $root, please remove it before running this script." + exit 1 +fi + +if [ -z "$SSLPASS" ]; then + # Unless specified otherwise, we'll use this as a password everywhere. + export SSLPASS="xmlsecurity" +fi + +# 1) Create the root pair. + +mkdir "$root/ca" + +cd "$root/ca" +mkdir certs crl newcerts private +chmod 700 private +touch index.txt +echo 1000 > serial + +sed "s|@ROOT@|$root|g" "$root/templates/root.cnf" > "$root/ca/openssl.cnf" + +# Create the root key. +cd "$root/ca" +openssl genrsa -aes256 -out private/ca.key.pem -passout env:SSLPASS 4096 +chmod 400 private/ca.key.pem + +# Create the root certificate. +cd "$root/ca" +openssl req -config openssl.cnf \ + -key private/ca.key.pem \ + -new -x509 -days 36500 -sha256 -extensions v3_ca \ + -out certs/ca.cert.pem \ + -passin env:SSLPASS \ + -subj "/C=UK/ST=England/O=Xmlsecurity ${algo} Test/CN=Xmlsecurity ${algo} Test Root CA" +chmod 444 certs/ca.cert.pem + +# 2) Create the intermediate pair. + +# Prepare the directory. +mkdir "$root/ca/intermediate" +cd "$root/ca/intermediate" +mkdir certs crl csr newcerts private +chmod 700 private +touch index.txt +echo 1000 > serial + +# crlnumber is used to keep track of certificate revocation lists. +echo 1000 > "$root/ca/intermediate/crlnumber" + +# Copy the intermediate CA configuration file. +sed "s|@ROOT@|$root|g" "$root/templates/intermediate.cnf" > "$root/ca/intermediate/openssl.cnf" + +# Create the intermediate key. + +cd "$root/ca" +openssl genrsa -aes256 \ + -out intermediate/private/intermediate.key.pem \ + -passout env:SSLPASS 4096 +chmod 400 intermediate/private/intermediate.key.pem + +# Create the intermediate certificate. + +# Intermediate key. +cd "$root/ca" +openssl req -config intermediate/openssl.cnf -new -sha256 \ + -key intermediate/private/intermediate.key.pem \ + -out intermediate/csr/intermediate.csr.pem \ + -passin env:SSLPASS \ + -subj "/C=UK/ST=England/O=Xmlsecurity ${algo} Test/CN=Xmlsecurity Intermediate Root CA" + +# The certificate itself. +openssl ca -batch -config openssl.cnf -extensions v3_intermediate_ca \ + -days 36500 -notext -md sha256 \ + -in intermediate/csr/intermediate.csr.pem \ + -passin env:SSLPASS \ + -out intermediate/certs/intermediate.cert.pem +chmod 444 intermediate/certs/intermediate.cert.pem + +# Create the certificate chain file. +cat intermediate/certs/intermediate.cert.pem \ + certs/ca.cert.pem > intermediate/certs/ca-chain.cert.pem +chmod 444 intermediate/certs/ca-chain.cert.pem + +# 3) Create the real certificate. + +for i in Alice Bob +do + # Create a key. + cd "$root/ca" + if [ "$algo" == "ECDSA" ]; then + openssl ecparam -name secp256r1 -genkey \ + -out intermediate/private/example-xmlsecurity-${i}.key.pem + else + openssl genrsa -aes256 \ + -out intermediate/private/example-xmlsecurity-${i}.key.pem \ + -passout env:SSLPASS 2048 + fi + chmod 400 intermediate/private/example-xmlsecurity-${i}.key.pem + + # Create a certificate signing request (CSR). + + cd "$root/ca" + openssl req -config intermediate/openssl.cnf \ + -key intermediate/private/example-xmlsecurity-${i}.key.pem \ + -new -sha256 -out intermediate/csr/example-xmlsecurity-${i}.csr.pem \ + -passin env:SSLPASS \ + -subj "/C=UK/ST=England/O=Xmlsecurity ${algo} Test/CN=Xmlsecurity ${algo} Test example ${i}" + + # To create a certificate, use the intermediate CA to sign the CSR. + cd "$root/ca" + # usr_cert: the cert will be used for signing. + openssl ca -batch -config intermediate/openssl.cnf \ + -extensions usr_cert -days 36500 -notext -md sha256 \ + -in intermediate/csr/example-xmlsecurity-${i}.csr.pem \ + -passin env:SSLPASS \ + -out intermediate/certs/example-xmlsecurity-${i}.cert.pem + chmod 444 intermediate/certs/example-xmlsecurity-${i}.cert.pem + + # Export it in PKCS#12 format. + if [ "$algo" == "ECDSA" ]; then + openssl pkcs12 -export \ + -out ./intermediate/private/example-xmlsecurity-${i}.cert.p12 \ + -passout env:SSLPASS \ + -inkey intermediate/private/example-xmlsecurity-${i}.key.pem \ + -passin env:SSLPASS \ + -in intermediate/certs/example-xmlsecurity-${i}.cert.pem \ + -certfile intermediate/certs/ca-chain.cert.pem + else + openssl pkcs12 -export \ + -out ./intermediate/private/example-xmlsecurity-${i}.cert.p12 \ + -passout env:SSLPASS \ + -inkey intermediate/private/example-xmlsecurity-${i}.key.pem \ + -passin env:SSLPASS \ + -in intermediate/certs/example-xmlsecurity-${i}.cert.pem \ + -certfile intermediate/certs/ca-chain.cert.pem \ + -CSP "Microsoft Enhanced RSA and AES Cryptographic Provider" + fi +done + +echo +echo "Authority certificate is at: <$root/ca/intermediate/certs/ca-chain.cert.pem>." +echo "To be able to import it in Windows, rename the '.pem' extension to '.cer'." +for i in Alice Bob +do + echo "Signing certificate is at <$root/ca/intermediate/private/example-xmlsecurity-${i}.cert.p12>." +done + +# vim:set shiftwidth=4 expandtab: diff --git a/xmlsecurity/qa/create-certs/create-dump-certs.sh b/xmlsecurity/qa/create-certs/create-dump-certs.sh new file mode 100644 index 0000000000..95e8de9c6f --- /dev/null +++ b/xmlsecurity/qa/create-certs/create-dump-certs.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# This script generates 100 certificates (modifiable) for cases of testing UI latency for instance. +# +# Basically, it creates certificates with sender same as receiver following User [number] pattern. +# + +for ((i=1; i<=100; i++)) +do + gpg --batch --gen-key < user$i.asc + + echo "Generated certificate for User $i" +done diff --git a/xmlsecurity/qa/create-certs/templates/intermediate.cnf b/xmlsecurity/qa/create-certs/templates/intermediate.cnf new file mode 100644 index 0000000000..c6fd12d0a6 --- /dev/null +++ b/xmlsecurity/qa/create-certs/templates/intermediate.cnf @@ -0,0 +1,132 @@ +# OpenSSL intermediate CA configuration file. +# Copy to `$root/ca/intermediate/openssl.cnf`. + +[ ca ] +# `man ca` +default_ca = CA_default + +[ CA_default ] +# Directory and file locations. +dir = @ROOT@/ca/intermediate +certs = $dir/certs +crl_dir = $dir/crl +new_certs_dir = $dir/newcerts +database = $dir/index.txt +serial = $dir/serial +RANDFILE = $dir/private/.rand + +# The root key and root certificate. +private_key = $dir/private/intermediate.key.pem +certificate = $dir/certs/intermediate.cert.pem + +# For certificate revocation lists. +crlnumber = $dir/crlnumber +crl = $dir/crl/intermediate.crl.pem +crl_extensions = crl_ext +default_crl_days = 30 + +# SHA-1 is deprecated, so use SHA-2 instead. +default_md = sha256 + +name_opt = ca_default +cert_opt = ca_default +default_days = 375 +preserve = no +policy = policy_loose + +[ policy_strict ] +# The root CA should only sign intermediate certificates that match. +# See the POLICY FORMAT section of `man ca`. +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +[ policy_loose ] +# Allow the intermediate CA to sign a more diverse range of certificates. +# See the POLICY FORMAT section of the `ca` man page. +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +[ req ] +# Options for the `req` tool (`man req`). +default_bits = 2048 +distinguished_name = req_distinguished_name +string_mask = utf8only + +# SHA-1 is deprecated, so use SHA-2 instead. +default_md = sha256 + +# Extension to add when the -x509 option is used. +x509_extensions = v3_ca + +[ req_distinguished_name ] +# See . +countryName = Country Name (2 letter code) +stateOrProvinceName = State or Province Name +localityName = Locality Name +0.organizationName = Organization Name +organizationalUnitName = Organizational Unit Name +commonName = Common Name +emailAddress = Email Address + +# Optionally, specify some defaults. +countryName_default = GB +stateOrProvinceName_default = England +localityName_default = +0.organizationName_default = Xmlsecurity Test +organizationalUnitName_default = +emailAddress_default = + +[ v3_ca ] +# Extensions for a typical CA (`man x509v3_config`). +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer +basicConstraints = critical, CA:true +keyUsage = critical, digitalSignature, cRLSign, keyCertSign + +[ v3_intermediate_ca ] +# Extensions for a typical intermediate CA (`man x509v3_config`). +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer +basicConstraints = critical, CA:true, pathlen:0 +keyUsage = critical, digitalSignature, cRLSign, keyCertSign + +[ usr_cert ] +# Extensions for client certificates (`man x509v3_config`). +basicConstraints = CA:FALSE +nsCertType = client, email +nsComment = "OpenSSL Generated Client Certificate" +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer +keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment +extendedKeyUsage = clientAuth, emailProtection + +[ server_cert ] +# Extensions for server certificates (`man x509v3_config`). +basicConstraints = CA:FALSE +nsCertType = server +nsComment = "OpenSSL Generated Server Certificate" +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer:always +keyUsage = critical, digitalSignature, keyEncipherment +extendedKeyUsage = serverAuth + +[ crl_ext ] +# Extension for CRLs (`man x509v3_config`). +authorityKeyIdentifier=keyid:always + +[ ocsp ] +# Extension for OCSP signing certificates (`man ocsp`). +basicConstraints = CA:FALSE +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer +keyUsage = critical, digitalSignature +extendedKeyUsage = critical, OCSPSigning diff --git a/xmlsecurity/qa/create-certs/templates/root.cnf b/xmlsecurity/qa/create-certs/templates/root.cnf new file mode 100644 index 0000000000..1298d74d3a --- /dev/null +++ b/xmlsecurity/qa/create-certs/templates/root.cnf @@ -0,0 +1,132 @@ +# OpenSSL root CA configuration file. +# Copy to `$root/ca/openssl.cnf`. + +[ ca ] +# `man ca` +default_ca = CA_default + +[ CA_default ] +# Directory and file locations. +dir = @ROOT@/ca +certs = $dir/certs +crl_dir = $dir/crl +new_certs_dir = $dir/newcerts +database = $dir/index.txt +serial = $dir/serial +RANDFILE = $dir/private/.rand + +# The root key and root certificate. +private_key = $dir/private/ca.key.pem +certificate = $dir/certs/ca.cert.pem + +# For certificate revocation lists. +crlnumber = $dir/crlnumber +crl = $dir/crl/ca.crl.pem +crl_extensions = crl_ext +default_crl_days = 30 + +# SHA-1 is deprecated, so use SHA-2 instead. +default_md = sha256 + +name_opt = ca_default +cert_opt = ca_default +default_days = 375 +preserve = no +policy = policy_strict + +[ policy_strict ] +# The root CA should only sign intermediate certificates that match. +# See the POLICY FORMAT section of `man ca`. +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +[ policy_loose ] +# Allow the intermediate CA to sign a more diverse range of certificates. +# See the POLICY FORMAT section of the `ca` man page. +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +[ req ] +# Options for the `req` tool (`man req`). +default_bits = 2048 +distinguished_name = req_distinguished_name +string_mask = utf8only + +# SHA-1 is deprecated, so use SHA-2 instead. +default_md = sha256 + +# Extension to add when the -x509 option is used. +x509_extensions = v3_ca + +[ req_distinguished_name ] +# See . +countryName = Country Name (2 letter code) +stateOrProvinceName = State or Province Name +localityName = Locality Name +0.organizationName = Organization Name +organizationalUnitName = Organizational Unit Name +commonName = Common Name +emailAddress = Email Address + +# Optionally, specify some defaults. +countryName_default = GB +stateOrProvinceName_default = England +localityName_default = +0.organizationName_default = Xmlsecurity Test +organizationalUnitName_default = +emailAddress_default = + +[ v3_ca ] +# Extensions for a typical CA (`man x509v3_config`). +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer +basicConstraints = critical, CA:true +keyUsage = critical, digitalSignature, cRLSign, keyCertSign + +[ v3_intermediate_ca ] +# Extensions for a typical intermediate CA (`man x509v3_config`). +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer +basicConstraints = critical, CA:true, pathlen:0 +keyUsage = critical, digitalSignature, cRLSign, keyCertSign + +[ usr_cert ] +# Extensions for client certificates (`man x509v3_config`). +basicConstraints = CA:FALSE +nsCertType = client, email +nsComment = "OpenSSL Generated Client Certificate" +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer +keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment +extendedKeyUsage = clientAuth, emailProtection + +[ server_cert ] +# Extensions for server certificates (`man x509v3_config`). +basicConstraints = CA:FALSE +nsCertType = server +nsComment = "OpenSSL Generated Server Certificate" +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer:always +keyUsage = critical, digitalSignature, keyEncipherment +extendedKeyUsage = serverAuth + +[ crl_ext ] +# Extension for CRLs (`man x509v3_config`). +authorityKeyIdentifier=keyid:always + +[ ocsp ] +# Extension for OCSP signing certificates (`man ocsp`). +basicConstraints = CA:FALSE +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer +keyUsage = critical, digitalSignature +extendedKeyUsage = critical, OCSPSigning diff --git a/xmlsecurity/qa/unit/data/xmlsecurity-dialogs-test.txt b/xmlsecurity/qa/unit/data/xmlsecurity-dialogs-test.txt new file mode 100644 index 0000000000..1f8ee2b621 --- /dev/null +++ b/xmlsecurity/qa/unit/data/xmlsecurity-dialogs-test.txt @@ -0,0 +1,45 @@ +# -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +# This file contains all dialogs that the unit tests in the module +# will work on if it is in script mode. It will read one-by-one, +# try to open it and create a screenshot that will be saved in +# workdir/screenshots using the pattern of the ui-file name. +# +# Syntax: +# - empty lines are allowed +# - lines starting with '#' are treated as comment +# - all other lines should contain a *.ui filename in the same +# notation as in the dialog constructors (see code) + +# +# The 'known' dialogs which have a hard-coded representation +# in registerKnownDialogsByID/createDialogByID +# + +# No known dialogs in xmlsecurity for now + +# +# Dialogs without a hard-coded representation. These will +# be visualized using a fallback based on weld::Builder +# + +# currently deactivated, leads to problems and the test to not work +# This is typically a hint that these should be hard-coded in the +# test case since they need some document and model data to work + +xmlsec/ui/viewcertdialog.ui +xmlsec/ui/macrosecuritydialog.ui +xmlsec/ui/certgeneral.ui +xmlsec/ui/certdetails.ui +xmlsec/ui/certpage.ui +xmlsec/ui/securitylevelpage.ui +xmlsec/ui/securitytrustpage.ui +xmlsec/ui/selectcertificatedialog.ui +xmlsec/ui/digitalsignaturesdialog.ui diff --git a/xmlsecurity/qa/unit/pdfsigning/data/2good.pdf b/xmlsecurity/qa/unit/pdfsigning/data/2good.pdf new file mode 100644 index 0000000000..10528c57f7 Binary files /dev/null and b/xmlsecurity/qa/unit/pdfsigning/data/2good.pdf differ diff --git a/xmlsecurity/qa/unit/pdfsigning/data/bad-cert-p1.pdf b/xmlsecurity/qa/unit/pdfsigning/data/bad-cert-p1.pdf new file mode 100644 index 0000000000..04d9950582 Binary files /dev/null and b/xmlsecurity/qa/unit/pdfsigning/data/bad-cert-p1.pdf differ diff --git a/xmlsecurity/qa/unit/pdfsigning/data/bad-cert-p3-stamp.pdf b/xmlsecurity/qa/unit/pdfsigning/data/bad-cert-p3-stamp.pdf new file mode 100644 index 0000000000..b30f5b0386 Binary files /dev/null and b/xmlsecurity/qa/unit/pdfsigning/data/bad-cert-p3-stamp.pdf differ diff --git a/xmlsecurity/qa/unit/pdfsigning/data/cr-comment.pdf b/xmlsecurity/qa/unit/pdfsigning/data/cr-comment.pdf new file mode 100644 index 0000000000..b1aae07a21 --- /dev/null +++ b/xmlsecurity/qa/unit/pdfsigning/data/cr-comment.pdf @@ -0,0 +1,4480 @@ +%PDF-1.4 %âãÏÓ +1 0 obj <>>> endobj 2 0 obj <>stream + + + + + uuid:e7f483a2-dbf7-4046-8848-508b776dd738 + xmp.did:89321C534E266811A613EDAC20FB34D2 + adobe:docid:indd:924fbc79-cadb-11de-af61-e97e2740acd1 + proof:pdf + + xmp.iid:88321C534E266811A613EDAC20FB34D2 + adobe:docid:indd:924fbc79-cadb-11de-af61-e97e2740acd1 + adobe:docid:indd:924fbc79-cadb-11de-af61-e97e2740acd1 + default + + + + + saved + xmp.iid:E4B6ED806F256811A613EDAC20FB34D2 + 2010-06-27T11:39:47-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:E5B6ED806F256811A613EDAC20FB34D2 + 2010-06-27T11:39:47-07:00 + Adobe InDesign 6.0 + /metadata + + + saved + xmp.iid:E6B6ED806F256811A613EDAC20FB34D2 + 2010-06-27T11:44:22-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:80321C534E266811A613EDAC20FB34D2 + 2010-06-27T11:46:03-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:81321C534E266811A613EDAC20FB34D2 + 2010-06-27T11:48-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:82321C534E266811A613EDAC20FB34D2 + 2010-06-27T11:49:01-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:83321C534E266811A613EDAC20FB34D2 + 2010-06-27T11:52:39-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:84321C534E266811A613EDAC20FB34D2 + 2010-06-27T11:58:06-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:85321C534E266811A613EDAC20FB34D2 + 2010-06-27T11:59:50-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:88321C534E266811A613EDAC20FB34D2 + 2010-06-27T12:03:27-07:00 + Adobe InDesign 6.0 + /metadata + + + saved + xmp.iid:89321C534E266811A613EDAC20FB34D2 + 2010-06-27T12:03:27-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:4A27385D5F266811A613EDAC20FB34D2 + 2010-06-27T13:48:01-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:4B27385D5F266811A613EDAC20FB34D2 + 2010-06-27T13:50:54-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:4C27385D5F266811A613EDAC20FB34D2 + 2010-06-27T13:54-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:4D27385D5F266811A613EDAC20FB34D2 + 2010-06-27T13:55:16-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:4E27385D5F266811A613EDAC20FB34D2 + 2010-06-27T13:56:27-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:4F27385D5F266811A613EDAC20FB34D2 + 2010-06-27T13:58:44-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:5027385D5F266811A613EDAC20FB34D2 + 2010-06-27T14:05:30-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:5127385D5F266811A613EDAC20FB34D2 + 2010-06-27T14:07:25-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:5227385D5F266811A613EDAC20FB34D2 + 2010-06-27T14:12:43-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:5327385D5F266811A613EDAC20FB34D2 + 2010-06-27T14:13:56-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:5427385D5F266811A613EDAC20FB34D2 + 2010-06-27T14:16:22-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:DE855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:19:25-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:DF855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:27:07-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:E0855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:29:58-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:E1855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:32:34-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:E2855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:33:46-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:E3855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:40:42-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:E4855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:41:28-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:E5855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:42:42-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:E6855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:44:36-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:E7855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:47:08-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:E8855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:51:29-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:80C8B5F5A22068119109D8C24D4F5870 + 2010-06-29T10:49:23-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:81C8B5F5A22068119109D8C24D4F5870 + 2010-06-29T10:50:43-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:82C8B5F5A22068119109D8C24D4F5870 + 2010-06-29T10:52:12-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:00CECC59A92068119109D8C24D4F5870 + 2010-06-29T10:53:23-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:01CECC59A92068119109D8C24D4F5870 + 2010-06-29T10:53:56-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:02CECC59A92068119109D8C24D4F5870 + 2010-06-29T10:56:41-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:03CECC59A92068119109D8C24D4F5870 + 2010-06-29T11:03:21-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:04CECC59A92068119109D8C24D4F5870 + 2010-06-29T11:06:47-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:05CECC59A92068119109D8C24D4F5870 + 2010-06-29T11:09:26-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:06CECC59A92068119109D8C24D4F5870 + 2010-06-29T11:11:53-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:07CECC59A92068119109D8C24D4F5870 + 2010-06-29T11:13:29-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:999093B2AD2068119109D8C24D4F5870 + 2010-06-29T14:21:34-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:9A9093B2AD2068119109D8C24D4F5870 + 2010-06-29T14:27:38-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:9B9093B2AD2068119109D8C24D4F5870 + 2010-06-29T14:30:31-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:371C0BE61C2368119109D8C24D4F5870 + 2010-07-02T14:20:55-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:381C0BE61C2368119109D8C24D4F5870 + 2010-07-02T14:26:33-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:391C0BE61C2368119109D8C24D4F5870 + 2010-07-02T14:29:07-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:3A1C0BE61C2368119109D8C24D4F5870 + 2010-07-02T14:31:19-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:7A0142B9242368119109D8C24D4F5870 + 2010-07-02T14:41:33-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:7B0142B9242368119109D8C24D4F5870 + 2010-07-02T14:44:10-07:00 + Adobe InDesign 6.0 + / + + + + + + + ReferenceStream + 72.00 + 72.00 + Inches + + uuid:288c3c69-7dd6-7c4f-984d-b085b3307748 + uuid:93F9F49755C5DE1185BCB9A8461E73D9 + + + + + + + 2010-07-02T15:32:26-07:00 + 2010-07-02T15:32:26-07:00 + 2010-07-02T15:32:26-07:00 + Adobe InDesign CS4 (6.0.5) + + + + JPEG + 256 + 256 + /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 + + + + + + 244 + + + application/pdf + + + Adobe PDF Library 9.0 + False + + + + endstream endobj 3 0 obj <> endobj 5 0 obj <>/ExtGState<>/Font<>/ProcSet[/PDF/Text]/Properties<>>>/Shading<>/XObject<>>>/TrimBox[0.0 0.0 841.89 595.276]/Type/Page>> endobj 6 0 obj <>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*S­k@߃ŕ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 7±ÛGÆDT‘ˆ™À¢Ú‚°¸2’ñ´zt9f?’%äÁ5Ð&ê8!Vrê¤,mÀ¦,xöÎ"ç&¶HñnIC½ñù¢Í@jÔå è×ßteOh ŠÄíŠà"..n"”CLe)0ÚS”5ÇÀÆ'®¸ÂÉ«çö³ f?JsÀ§¢Wsȸëàݬ5UÃù¨;æºc{éÌžWò‚QB:YÒxV0oÌœ°ÌvCQäYÖœrÜŸ¤Wq˜©¬1(0#[Ž€!©rÛÀÖXNöµN¥.A…¤e8Ðe’”¶Ñô#+ìÊM¬*ÍH±:àUJV‹ŸÄ¤ƒ+ÐyÀ€ö«h#®ÞÀ¤gkàJª¦J·2´os 1{AUë|äÄ#\22¤Ç ÌL%m¦„_Žy{„ÌGÁ`¶EI#!+Eb#½6D^ø( ¦hóä®á®„Fþ"†‡q~(Æ w,°sù]i¹?(d‰ù'ú‹Ø±&"!3÷„(«ŸðX“àH@¸%Á-qOcÝl,HÓðàŠ,ØŠ†£Ö(™œÔ—÷ +Sö^ö¥é#ãT¤é÷Þ +½¡*Šƒ pæŒÎ¯l1l†'Ö†ÊíS'Ì™+½…æ š+ŽÂZž ¨Ü$½»X¹TxÞÙ-qh\ç|ÞÑ!Ëø¸CèßÙêu‰­IA•²Efuh¨‘pp9n!iñ¦ä+õÀmW<ž H!V…¶‚hÜŒØ9L "ÍÁñl÷Wì:'9õ˜|ƒâ (z6Iº=ïÉe­·œ¦$ÃÍD•µh¹xî[Nàâ½›€Q>î89žg³¤”\mIÑâ%ÁàtîŠÅgy¬6º‚ ¹Ô 'ó±6TÏU²EMDQ[Ìp“fì0à¤u³ªRIžC^‡Ó;e°2yýA|è€`I+·iHŒrk£ ÚMÇU``—AFäþ=¢,2>$5|uçÌ_†ÕÆrÛ"…ñHRÄuŽ G’\ĺ·Pâ÷‘&/M£øfÑÀx¶•!<ï¯/¿ÃÓå5/üȨ0¥¾ub{²ÜÞóåUæ¿ÌõÀ3°Lü\:Òßøsÿîä‘–"Ïg(ækºÛýãá/όɷ7Îàkœ~m¨_7}{>gôëëºú 8ŸùK•nëtãó•›ÄdÚ‹£­‹‘¯;¿î}¥ÓÞŒÎg«ÙvÒSÏù»ý·íC>…Ñ­çõ{»××ÜΉÛ>ï÷;npuäåÆ>7ô[ÅwòŽûø0ßh÷—¦ÞÍþØó~Îú\™òÓÌmú¦|Ìx0í{'{½ÿóáå=*ãKÑÏ·‹ý_j‡)›3ç°tøÚý¹§&çv +ï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^þ¸¼þ•[Ò‰ñ¶Û!&†áÇ^isC¤ài‚k®J ,åÝÓä“Ê?YwM/O.™J–GÕ«7$ ÛȲVŒbùÕGW@ áeÙfW»ªdmÞ3b- +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 uRÆ5{€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šý¦*Jm //+ ;5#&­MxŸ;y‚mÚßS‰oÙ^îìYKâ7u K?ÃXÞ_] LÁ$} ¥4ïµ6À¨‹Ï"èìtR?®ÿ[ÃÅÚáô¯?þò׿©Ó?ÿ#&Ü^ Në:½iðMÃf~ñg‰[{L×o±vòtáØ3 úq¥de6Ä€sºŸêžV‚˜îIІ2:ÏØC‘íÑ~n©-JÏŠí`öêú?KÎæw“sÊûÓÿ5?7醚·hýÜBM¹iØ$ˆìH\}ûŠ§Á:¢Ÿ¿Mò,AÈ–Çèý­ƒ»Fõm"’92ënÖ¾2_³™VO–“íÇ˭ÿZ3P(µm½>Ú£WÎ4$x‘{BpËŠe‡Ëá#jTÏÜ(k•LbþcvlÙs´pJÜ­æF_]HÀ(Ùb£$œ<š’ˆA=I-®p0Múµ­vDi}Q.‘ü—ÂÚþd´½˜ ÍéïÿþªìG–Õa™á¢mü8þƒ¾ÕÓx§iì~›’Óºoq|¦g¥XÀ:]ÆáôªO&Ä¿J!¯Õ˜|¥Ì=õ‚™æsÄ×õ¥õ¡ñŽ·£èøFbx›gMÑÂÀÜq1‘¿)y?ÔíÒ߸úÕè©ç¥JPZ‚ŽãêGÛ\ŸpÒu1¯Gß·a@<ÇßðÜ¥…GÒU×(HÑt³”±ßÚåTGJY•.*È |¤ÂM–yðê³ +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çæ°¸X l¢™ç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¹÷JÈüeä®V°lË —Ô€*«e,î`ºˆuP¨Uñ=FMÛXzÌ0û5?Ø +Ƶ„ñÀŒÀ‹&×åÔ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$Œçè?Zßfç(”vÛÞÀ³‡¢.Òõ¨Öß +Ÿá»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Ôf1Vè0_$¥cct=_€ïŸÊ ;Õ|9ËÞfk± 0n1 o€E»µû¼ ;A9•ƒruPyQå€ÚŤ¤•\è—™kÀÂ;—+J¿{£q¤+:ý[ói»ýÅ‘—Ça߯R)VÇ=mÅ¿ˆ{..!ð{yôú[j´ÌÖ¡ˆT +Ð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ôÅÖþ|hò,Ñê íÏÎÑ91±MÉèôñZ¦ªêÞÔ*¥Šj"Küd÷¸Í¢ëÚ;¯ƒWUî"”X54½9©Rn`¤^„¢›„ÖKSc¡ò¨2'CÎG|‡ôV6=|¶µ&±1ìc:Çîéœo÷öÃåIôJÝ'p4@|0Ñ(à_po4TOž2¸a…“Qﻄ_m”P+{›Ê¸:_&RÇ ˆÌ³sÌó6ñKxÍ÷Ä—ã5ãn¬CWÁ¨ÎQ°»h(v@Tœ8Ì«B²WÝ£ü¥¦cZç•Ý㨔ÝèGƒØV¸½Ö ÷Ç7"H«™ Ê’/…´\¢_¿ ^ÆÏ ë6{ülDBà +€u¥,¼ãXÄÖ×̸BñxDX”ì_Ðj,2’'3K~“,€ª.)¢ˆðÙÓ4c 5]Qõ£¶_u•Ú‘¢HÁcEI~b ” $ +îf@q½Ákš\Í­üØœŸŠ;Žòò9ø<ÁPëõj sAñ᜖¬6 +Ç †ª 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õ’%ÉÇlBìÚJ™ŽÙ:Gð E{·aU-Ób/zˆ\ÅHBkk>|¬&q“(ôkã“¿ZŒ²‹:}&³àQê$µj‰MÕµœ·¥I5&—\ÄSŒ*®DoŠãClÁó•²þË{•å6®ÄÀÿœÂ°§7m€a –ã9ÀÌæcð¾æþÀSsé&[-Y‰##HìØê…d±Xå†ËѺ3.Ì RÆf‰Šû;$5oy&á™S, Fù{ÞâÔúá`NMÿ47œü4²þ¾ýøùËþü“ý'cÝ-‡E‹?W:^)h.ó I:m¶¬G`,Ç]çCU¨¸`”›oÑ­´ú*MRâDói[­îÌÎV0·ºjP?9«f”¤§ÏFfÅ•[&HºY›o°F¸i¬ÞRúHV +u¢³v’ˆ:xgÛSÓ¤E|ë&âûïmy¾O€í&m«á -nÍÄÖÅÅ€5ý³*€‘vÏ|‹gçŒÐymÔ65Âû¥•ݵ‡ô’cšl/é’㊠Ñ{®jB¨•.wx}_Ì\uVÙ®´+Y/¤]EÓ:úöúa”P–:v³’%¡ñTÙjBl‡²Éìà¹ø>öq=EgînÏræîWá.rÑíÕGýÎaÝB œ_r—fÂùFzíñUìC󑾧ynúùÐÒº_=¹Ë—öÅ׶8¯Ù«”·”2ª°7œmžR®(1y(‹scSÓ}©m<ûŽ$A¿cŸL¨Ø¸úÔ| A\ºyÏJi±¤`¨–ló”ÙeDs|ì»V…I’âfûëu“™~°«ÞìLÜÑçs›$‰žR¶Pl>)cG.ÖµiÜâ”}õõþ]îu'‹Œ¸a–‘O²¶€¨ÈcÂ꘥³áû§±CžöNùñà™/z² 7±!XW+ð 6$û$«/=õŠ'÷È ÄtÄRÂ.D®¢ÄÅUO#>ŽWxV±x–X÷ÌXRVæIãÿšáˆ™ÈZˆßÓ.Oû„Z{<…U5è0Z(Î’·U/ÌnmŠÛåÔ^‚3ØÝ{ù± à/á—q»ŠžgÑ9 ù¶ðñ"1í÷v7u%º§•t…““ë©‘ò†@2+ÁaFÄ)B€e³ „6¯JD’ë=C*^ŽºŒ‰›ðÇ7)½Óš‹;›ì -Mñ¨nuÃìŠæˆ¦oú`øLj¨(º¢éâç×½€~} З¢sFG÷ +edñ` ¹ú +ÂâE¥÷J(IÅš1¬ÐÃxk3²’a2Vˆb…#¿ç–îrƒ6#Hì†E£â#¶<ìXxÙIÉ#ñ?÷º$¡¬™ø^ÿ¥WOÜé—Ÿïõú}íî;é–”ÒAyʵù~Á fx'oÇä®12wium¤ÆŸ&9Õ”‰,5Ó¨¢ÇX0÷Ïz¢©d«ÍY8vç‚›ëÚÛˆ<–t¾FÌÅeE׋W±Ó„Ç% +ܤóDiŠ féušêJʤˆìŠÙ•dVRÿo¾åf‚X<©\›‹ÁÏùÎ:ƒ}@˜.﬛¬bbϹ)‡nZë†ËѺ32ÂÄþƒEkŽ©¥ŒeÑ•n‘ÃBÑ`YQjÌ·Keñ'Ûµ’¬Dï±uKJé½|&æU@ºŒq”ÂÞ`Ý>_‰<ܶž{…Ü.sˆ¦Re$Ô3²Myo®çWÛlª%‘E c\šú«Ý¶uܺ‰cìZÙöi0=2톜h-x8¡+tI)€l!€X×Ð:W¬$˜š®ÕŸü”SÆ/vá?<ª|7¦8Çês>q}ï@Ÿ{³Æê.ᾞɘ=zvÄÄ[Ú„'¿z—”Öy¥¶”Q"Gc”LIZäAë-s„ž×¬é‚ëññÕimºü¤c)tÇ_wϱÒ Ž‘q/!þñ + ÃÁõ 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ŸàðV:@ÚLFxÜØ¥\hï»nØÇÞÅ>šnJKoxËs"Ž``ÒA(Çó Û5[°ã¿&†hà¬Ê®B·âÇï·ÿ+ø‚ endstream endobj 7 0 obj <> endobj 17 0 obj <>/ExtGState<>/Shading<>>>/Subtype/Form>>stream +H‰LŒ1 +Ã@ {½b?`ùN:ét­!¤6.â>„¸‰Áöÿ!&nÂÃÀ°™g‡ÕÂ!DbWt¹²jÁþ¢VÚ(áMý}:qÐIkYéÜ¿ÿ­…x…Yå-<Ï 3úiI8ÜfŒ4ÒW€ "æ endstream endobj 18 0 obj <>/ExtGState<>/Shading<>>>/Subtype/Form>>stream +H‰LŒ± +ƒ@DûùŠù×½½œ·Û +’Z,bBl"¨ÿ‘Ø„)³Á‹ŠÍ:IflÌCºÌ&UÉêÜ_xpÅåí}:qàŠ,"åL=÷ï¿CZµÐÔÅÓM­Ÿô3ÛiQ ‡™#F|¥/ì endstream endobj 19 0 obj <>/ExtGState<>/Shading<>>>/Subtype/Form>>stream +H‰LŒ± +Ã0Cw}…~ ÎùìØwk¡tš½„fi ÉÿCÝv)žíP“P³Õ VÙ©ùÇ»XC®‰Ç‚;7ì>Ñߦ†¿‘ºÇ”(-ÿþ=l]­0³èà|¼p™ÙO«ð\y9bÄ[€ªºý endstream endobj 20 0 obj <>/ExtGState<>/Shading<>>>/Subtype/Form>>stream +H‰LŒ± +ƒP E÷|Åýc|y1É*”ÎâP÷RêRAý¨Ô¥Üápàp7 +Ž„yå(M‰ä^ÑtΪû‹Xi#Á›Úûtâ +*™*äÜ¿ÿ#ÝÅ`æ\#£‚燆í´Ž·#ô`®7 endstream endobj 26 0 obj <> endobj 23 0 obj <> endobj 8 0 obj [/DeviceN[/Cyan/Magenta/Yellow]/DeviceCMYK 28 0 R 29 0 R] endobj 27 0 obj <> endobj 30 0 obj <> endobj 28 0 obj <>stream +H‰ª6RÈÌKI­P0Ô3…ä²"…ÔŠä …âÒ$C…¢üœ …O\‘ÆÁ¤A"\`!s]tI½æ0½f˜ +¹PTšÁTš0Òn¹ •p‡äÀq-@€ÌXô endstream endobj 29 0 obj <> endobj 31 0 obj <> endobj 9 0 obj <> endobj 21 0 obj /DeviceCMYK endobj 25 0 obj <> endobj 24 0 obj <> endobj 22 0 obj <> endobj 16 0 obj <> endobj 32 0 obj <> endobj 33 0 obj <> endobj 15 0 obj <>stream + + + + + application/pdf + + + MS_Logo_70% + + + + + Adobe Illustrator CS3 + 2009-10-28T13:10:30-07:00 + 2009-10-28T14:10:20-07:00 + 2009-10-28T14:10:20-07:00 + + + + 256 + 44 + JPEG + /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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 + + + + + + uuid:93F9F49755C5DE1185BCB9A8461E73D9 + uuid:288c3c69-7dd6-7c4f-984d-b085b3307748 + + + + 1 + False + False + + 6.000000 + 2.000000 + Inches + + + + Black + + + + + + Default Swatch Group + 0 + + + + K=100 + GRAY + PROCESS + 255 + + + C=0 M=0 Y=0 K=0 + CMYK + PROCESS + 0.000000 + 0.000000 + 0.000000 + 0.000000 + + + K=100 + GRAY + PROCESS + 255 + + + C=0 M=0 Y=0 K=0 + CMYK + PROCESS + 0.000000 + 0.000000 + 0.000000 + 0.000000 + + + + + + + + + Document + + + Adobe PDF library 8.00 + + + + endstream endobj 12 0 obj <> endobj 13 0 obj <> endobj 14 0 obj <> endobj 38 0 obj [40 0 R] endobj 39 0 obj <>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ò„> endobj 41 0 obj <> endobj 42 0 obj <> endobj 43 0 obj <>stream +H‰j0 endstream endobj 44 0 obj <>stream +H‰dV TT×½ç¾÷f?eÄ_T†FU„a˜RŠA~ŠŠø"hF¤MüEÄ&ŠhI4––QµJÁŠ4©µ#ÆO ±ËÅZM©œwè¹3C’Uyë2ï½{î9ûœ³ï¾cÌmac‰³ƒC v–åÑ›]4–dffŒ:ÓA÷Ïózžµ|iúýÀ{‹ó~Dï³腮Åý3Æ ¡gÿ¬œ¼‚ªŠ¦0zžÈ˜»[öš´¥ltÝœJÏýs–äJëXc¦$²÷]½4g¹úVÔLzÎeLÊf’\ϘÂd¥\1“E•ó—g<Ãó~n\æŒsÂʶ³ŸüÍHLHd¾lÀk®‘q«v+áѾŒs2SŠh48åɤ-¼‹²Õ2fÕta‹ÄÔ-œ!t©ú-Ð%,Øzù€Rʆ³QŒÖ¨5k’ÑË1¬f+ /³$†˜’˜ÎZ[Ç^M¸6ýIܵwê,×ýZâZâžÄ߈û÷wÖNylÝË:<)bÐ-¤c…u/É9;‚õü±RÎÜéÁÀtžŽü1"6Â`؆õ°œk Š1GâHZ£§5ó\k<ûVñyXßË ¿Sy€jǃPßÂCØE´ª‹¥Ë ²™õ‘tFÁbЙu¹‹®£ ¶^‡bx‚EP|¶¢M`3õr8Éì‚”;œ,{žaG ôÐ܇PÇky©˜òÄkÕn„º±.µ·Z!„õ§uÞ£Ÿ)ÐnõÖsÃÌ«’’²vO_3}ÁB²ïmíÕKÇ(á Scð[~F)U yŸú1­·SNVj ¹—ÈX«1úê<­á_ð4úé<Í¡rò®^#Û»ƒRïÆsç[š/ñ;¸÷b#oÛÅu8t«*Ø>%VXÈÕ.@T@ÑP ,ö|ƒ­<L¬G²E³½Ž%ë²"ëÁk·†[ÂŒ~Ze3Øg7À ƒ<ž‡ŠC‚oŸýCý³ÚÖá-lçÓØsø`Ó¬„ä+eàS¸auÝkìÆ`—‰|¦S¶LO€¨Ô jˆÙ  ³5ZÓkðú!Ok †Éš£±B +Ú,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™úƒ1µlêï6ÔOâK¬8Ê}v@;=5ÃFA´0)e{MI„=Dºlú¤ùs;UÃ~"3#o”äÊæEñêËæGïªí ¬WO…úÈn$y©z¯°¤¨åž-om¡‹·rƒC·u.½uô¨K7f_¹á·ø¼œÚÐÃG’+,*.µÝ*Ù‰z¢`PF9c¹±žœ%öïC-vñÿ¡.Xÿ%Tb*ÞÁgÏŸ» 0®± kþ\EÈW¤q"u¶6ŽŽî®A$$Þl¿r¶#ÁÿÚ–Oðè¿w臣»’Øm½Î%RXŸh|»Kc §a#}nyÌÿÕG›;îÛµjòDkëÔ¯)—V¤™äÑäSpm$½wœ”UÀ'‘)Ðä¯ ó7»Ž ‘—¸dü½øoö~3Û:njø^<#ºÚv–žMÍ?¶ø/³Ò ¬6wGLÞöGšml6¹Óƒ³©üÏ®—í|W,îÒzv™Œ>A8j™áömÒËÎwI ]¸X¯hq&xfFÑbo-¬·ˆŸ¥ ‚UTÞ½``WI mÀÒ‰ì s~+öÑ@ìBze rõ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 +ÿ­¯>¦“Ý?yÂI¼ªËXÇ`^Ô¢‘a’ýX Ñ}GÄ#몆ˆÎ¼òëãU†h›¢•v´ÊxÔšïºúUqÜ:ï©1ÿ¸•·ž]¸•¹wëÚÑ +ãh—zëÎÔ”ÿ‹Lút·%·¬Ùeµ¨§¾ +w~6ÖfžCa+6*×Å_ž§t5³©:þæÍ#’Ž•)5 rÙëž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÷ã]g 딶u²zÞš²‘„CýÈï„\G{ߎËǃԊÿxº»»[R++eµì8±´Ï¨jÆYü¤À½ŽŠM+—möq¹8‹ËIxòõ½ý Ï*'±>öeÍ$QVMl`çX?‰©œ ËÒÄÓdÎI•JE½münaõÂøFG#ÊÈ~;nÉ|¡Ö‘=}Í¡žËòR ¼*N^ÓÜ‘Äm$‰;æ?…NžvõNe_‘-Ÿj½©fúq +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óÒ}ÂËæèPïršœ³Õåé˜?!ïW~™Ü8 µâ38M/@0­ƒ=òSH•ºÁ*¬†á9œDøŠ+5È0f‰áp×4ñçMÜ‹h@ä!ª³ˆlD&‚HàûùY©™ü¾Š%`U5@¹t +Ô’Ï00ãÕHch”NƒYÆçB4Š‡A/ÍÃçS¡QÕ ²¡3r­>§f”ytRTK«@í¥_)dzcw hGŸˆ €+·å†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ç§ÂäæÐÔŸó–Û€çÍã,ÎïuŽçÇÂ#øt9-ÔX{?ñ¡÷yHnÓûrªåð0rünËUîndÌ÷ÉÝ:Ç›9jý6Ëëm©µÓc Ƀö=ÔÁ7ð/y¯ù£ßc_'÷GÞ•Vë{âtD¶Y'dʬ3Üy†<¦ó‘÷¥Eutlô^f>!¶5íÏ‹ŒË35攼™¥ÌÅЉêž0zG©CΛj+¿Oå¦ê<2SwK9¯¾¿ã?|§ç,¹Wf”t1çóžÌ3ß6ÙU¨ ê#ó^±ÆiÂßìáþ”?m=KÜtübüô•Ì0o•W¨ëά9^xç4.ÌžïQCy£œWÑ? Ã%ìY² ýJ©uÐ=kε²dóµRnòöˆ,³vRkbøáW©ÑœsöI 9»Ü¶‰ ;È‹q©rî€ Þ¥Á;Ù‰}âʹX~B,[õÆð:.¼}»Ìt6ö!Þr«á7ËÍ&Ï–™jÛì£qÆ›ã:ØúòÙØÖ˜U{ø)2(/NÆóT:ߦŽkí¢~Ówh?²Ý…"#çû,í¿x£ÊðÍ)Ɇ·JE龡O15p¯©…Cn·¬²Ê+aê¡þèS–„èBÔÈ!êç*hWÐ͹ ¶^ûÏ·ejËÀ“`ø€ÓóÏfx>Ø`œÓ׃·.Àº¬ý лqb³Þf½ÃžÎü=`#À–ËÜ(@Ïý‚—p çè´ÈJÏÒ²WYá_…;/BW€õ¶ƒDÊo[úWÇÀ(8&RÑö€"•Øªø¤ò7‘*lT±¦êdÕìQýøR¤†V¶?Õpæk®=a}ÿ9NQDEñ?-M¸EÚi+îKÂ`–>stream +H‰\”ÝŠÛ0FïýºÜ½Xü#´ Áu6‹þдàØJjhl£8yû*:a 5$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ˆË–> endobj 46 0 obj <> endobj 47 0 obj <> endobj 48 0 obj <>stream +H‰j0 endstream endobj 49 0 obj <>stream +H‰\V T”×~÷ýo–ÄmF˜AÔÃ8Vq”a­ (j­5Š8"¨ "à‚ˆâ†TÃ*ˆ„¨5#x)µV\ÚºÅå ±ÖX·$.1GKmVþgï›AbÊœÇ?oûîò}÷þC€¢&9D"dÖSàÆØcp¥GÜÒ•›’^V„H"±E°“(SÔ(ÌxÂázÒ$‰&©)í¥ ŒJÑW’OÞùûhÖÌY$”ôé¤JƽÈ!õv:É›OÄ#Šja Å8‰”CÛ1Z!V­Aë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'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ÇÅ$„Ž^%–Û_å_¾ óS²¿9röVð2 ¶Ùá3ÄÀ·TÝFþ"zz\ý´W‡Æ¦xŠ~ûôôd£Eª5;;±*È¥'!(g1Ø6fÝýj9³ÛÙ¦/¯^æØ›_>˶µÜ6zuÔØëw)žÊq­;n:»"~giæ¼…«ÒDf¢0²ùÎÈDOA‘wô*Ð¥¨ ŸÝÎÏÃó¼¥i[k—,=½/oƒiZyÉ·]äOY}âW¢ÐkÄbjôZ‹ïøw³$ÑsÉùBñQö8­¶³´öÓkÓ\ÿz1ú>'»²>:"·h^i¸˜Wð ÖÑM÷÷dØ¢nmNŠMŠwÙ‘®£Ï:òн^ é\¯AWµéu¢öДJº.°ÆšÃ;óî~‘[šwöʪeØÉÂ2ÖpƒõÇWW/É-Å˪’­÷,E3gÌY± éû•ÔÙ}G§3ëDÓ0ZÌÝõL÷_ÿ왽¡aùüm3†)º¹·°«PZ_X÷yÜœþB3QÜ‹©ÑË¢J}5ç[Õ[Û“'ŽÙò6-o¥ÃÔòƒ?—®… ¶þÉéu3³nµ%8“³yÏܨƒ; +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òÀWr GB´Ž„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  ¯Ãìg Wt3Ó:¼-|Û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³€Ú&)ã¨r­ty?Ç|~ÖÙ@ x€<{l)Åóy­Y`„²–²’Jœª3£)BUR“ºFYfd05Évj2‹ð5‰Hà4 Pô¡&g,ƺ¨É@YªÐ–;0vƒ +ÔXŠ67ÐÕIá΢U®Ê)v´ÈïÈxœá‚„ßD¹UPG5r¥«}€‹ÒE1Åëö&ª1®ÀÞ+Þ‰ÐÏíÇçTÃýjƱŽç‰¬wQ¶x—b0V.Û(Äl¡Á²Ž†È³"wêý3ªƒœŠý[Ùnm;ìf›{lÒç²ÏÕ úŒ®;3=óýø 8qël½sùÅ6÷¾ +÷Óäò}È$ò`¹*ƒ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&;©˜ã’9­mb›×ÑRÌÕ¶€;½%óNóé’cÑLÖr¨Žö‡ë›%Ç-Ï¿§DL3G!‡Bºà×ãàm#|Û’ýlA¶ãÿø4r¯BlÀåœ8u.@µí‘d‚ë y\n¦Tž£vÓB=o,½!»¼–Ú‰v<õ‘å4‹ÇcÂT-í–oÓUŠµhë4Kq³)ØA´Ý‘Où°ñ’Þ‹ï’ût¬¿Ÿ5‚WÁ{øŽÏé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çÇÿý‹~û endstream endobj 34 0 obj [50 0 R] endobj 35 0 obj <>stream +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ãZp­q-¸Ö¸\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ö(§ endstream endobj 50 0 obj <> endobj 51 0 obj <> endobj 52 0 obj <> endobj 53 0 obj <>stream +H‰j0 endstream endobj 54 0 obj <>stream +H‰dV XTÇž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»õ~lm r&î÷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†ÜŽ±ìYQrð¥™_ùt×oá§xs9¥…9S?X¿pÊÚׯ¢íÂwàË÷ñ:¾§I¶5åy«¶­›*´z¡?‘%ZÁ“„_0DD*­dbcV»Ï.ã.^ÔäžÓÝK£ñ=_B6ß&—9³Xº2bð¯Ý71:G‘ï¡_ôòÓ¬3©ÑÐqbŠ¤x£»æå(œ¿Þ\¸¸ü3n¿iß‘¿ÆU~± dk©\vdë‚¿D0Cí¦SX=_0f{?¾tzÖ"ôy +úh'úÈ@H¸F U]e4 Kˆ!}de;w?ãçx| +#n¬+?q›7üíµÊ!©°†ÃDø"îéÛü»vož¦zqËóTûýTÔ‚&’ Óå ‰ð‰¼òlŒÜÑ.—¹GòžËl.½Z[Êî  U‚ÁÔ9ŽJ^î&xλÓ8¹ÌÆg_á¶ÎÓ"/»!‰Ô“ +>¡ +žòžÉ‹ÙxšÍÕÂFµñ†?á·@ÿ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éøôÔ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´Ü?è̆ZW­4ª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¬“8 elµ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‘ÌX fò<ÒGyŒ<øŸlÒÃã÷tIÒ(†*§·_|úå(Æ&Q«³ôMÛ¬Xm³â´*w¾Z·nwÿ•ò\ËÝ[ñŽºõï¤æj>µ-ÐMK‰âÝèfà=·¹ü +ßh +Ùœªåãøµ¨Q²^«lFe[n’Rº„L§!àgpâ·¼L€8)n”žSEg|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+²9Â:56Öį’'Táþôä ±¢~o>êÙKõkÏl)×Ô—4ó'«- Ì»,¹¼‚°G“&1Y‘ÃFìâ­¦KñÚÐð“²''$L§×±Í…ÖÑ~å€Þ¦MèÇñSÆ®ý§jT3?Ç×.² {ÄNžMwø!²ƒÄÙɦì~ûSÛí©:zð7þ7»âÉ»8w9Ã×c w‰Ë5ü þ€ßãÍØÇ"y¾¼°ŒÄ:DRæ_*üèçohvbÕ`UZÕPaÆÿ©/Õ§+ E«V-Z\TÔ50¡¨ðÏ ²,+‹²Ì…¡—Q0ëðÀúÉ‹þ“Œ"ïÀßóƒ,1~´q‰…óéaü0Äž…B0/Áظ€?ôáÛ;ašžñ#F¡™:6B›´ β.H`Ûá¨Ò 6ÙÔ'é hAÄHÛ!_öÂ#rfJfhÁ±\²ÞÂù…ˆÓˆ*D "qQXƒ(C”ŠùBVö’h¡GŒÒqØcè€6y Y/øؔȗpLA„ƒ;±¹|t-ø¤T´mÇ{à3쟒P „uèã'(›˜åN8!'ÑÐ &6 á¬ãÖ èÇUÉ<úÇ…hC¯„A¥6Èõ¬¬¼ÒE°áhcf°ÑË`ÖøÓà¥IÐD“FË™U㽆éàeˆnm¾WÌ£Ã(Ÿet2ðÝ F%÷q H‡ën iÐ…c.®Qø­ùŽ~ ŸC> û5›žÍFóÓ ‰°‘&Ž>@\Gün̶‰vƒK$ +Œ±Gê„Ü“6\£µ¡Ÿ Ð* ¤A!u@Ô;ÃL`ÂN¥1˜!  » ÇY ¬)˜•™Ã4ôo;|€{S$µB¡b‚2å0úÒ ©ÿ"‘{š|&Ôà¼m_ÆÖ@®€² šBû$Ö4üQŽ¾`þŠ<Ƽ­@¸©‚ùª€[³ãú„{.âNFø0}rX?Æ!üùˆóËP¶,¬ó]Äc0ïèÚÑaÄä£5Ÿuh9¦÷ÿ8å°˜Þ†$ÚzÉ5¨Á³µ„tBíƒùÄ¥8'‡ÕC¾ÈS‘+Z^ +;1‡µü»"OE®Ú¡ÞÐõtöþû¥H n‘?úù¡´âpÏÜxf¢ÙaÌ<Ë"§µ­d‚9HÿCõ°Ž"ýi`<‘” ´œì$¿ —ÈM2D†h8Óh}•þ˜ž¡=R¸”%UK{‘ŽI×5êO,}Õ²ãìcö™œ,çÈä×åSr—|G‘”4eÒvå”rE0PC¦á‡†–o•þö<ÈÿüI»ãG  `†•À/Â:ÌþZ­ço#0Þ¡J°G¯.¢¦ÅâSgÈ¿¥ó +ò§tÞsá<Î$, ŸžÀC'0› è<…H­ó̦ªÎ3äót^AÞ£ópP¯ÕUéò¸v:ªÃï©‹9mnzz¦š]YaW ܵnOçºÔ]·Å]g÷¸ÜµsÔìêjµÎUYå©WëœõκmNǵØYévv¨®zÕ®zêìg½n³ê®PKªœÏÖ³zíêÜü’TM0­ØYãÚè®v|ý¿ù‚`T"<ˆàv°ã³¹÷= vi¸ãéH™ø[6ÊTh3 +À µ4À”Wa)>Õ!/þÛ5½bÆMªIÅßÅšUø®^{râèÄq›¶¾˜YŒ\%Ê9“’ñɥͫy4|[ƒclÆßÜh‰ +%¨ÏùìY k¹˜Ÿ%úÕŠèg±¦ßñ¹W³iï¶"/ÖüúrßÆÌç°3ÿ`ËO endstream endobj 10 0 obj <> endobj 11 0 obj <> endobj 55 0 obj <> endobj xref 0 56 0000000000 65535 f +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 <]>> startxref 89924 %%EOF 2 0 obj <>stream + + + + + uuid:7e7b597d-426f-3642-8dca-bcbf37236e1d + xmp.did:89321C534E266811A613EDAC20FB34D2 + adobe:docid:indd:924fbc79-cadb-11de-af61-e97e2740acd1 + proof:pdf + + xmp.iid:88321C534E266811A613EDAC20FB34D2 + adobe:docid:indd:924fbc79-cadb-11de-af61-e97e2740acd1 + adobe:docid:indd:924fbc79-cadb-11de-af61-e97e2740acd1 + default + + + + + saved + xmp.iid:E4B6ED806F256811A613EDAC20FB34D2 + 2010-06-27T11:39:47-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:E5B6ED806F256811A613EDAC20FB34D2 + 2010-06-27T11:39:47-07:00 + Adobe InDesign 6.0 + /metadata + + + saved + xmp.iid:E6B6ED806F256811A613EDAC20FB34D2 + 2010-06-27T11:44:22-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:80321C534E266811A613EDAC20FB34D2 + 2010-06-27T11:46:03-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:81321C534E266811A613EDAC20FB34D2 + 2010-06-27T11:48-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:82321C534E266811A613EDAC20FB34D2 + 2010-06-27T11:49:01-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:83321C534E266811A613EDAC20FB34D2 + 2010-06-27T11:52:39-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:84321C534E266811A613EDAC20FB34D2 + 2010-06-27T11:58:06-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:85321C534E266811A613EDAC20FB34D2 + 2010-06-27T11:59:50-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:88321C534E266811A613EDAC20FB34D2 + 2010-06-27T12:03:27-07:00 + Adobe InDesign 6.0 + /metadata + + + saved + xmp.iid:89321C534E266811A613EDAC20FB34D2 + 2010-06-27T12:03:27-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:4A27385D5F266811A613EDAC20FB34D2 + 2010-06-27T13:48:01-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:4B27385D5F266811A613EDAC20FB34D2 + 2010-06-27T13:50:54-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:4C27385D5F266811A613EDAC20FB34D2 + 2010-06-27T13:54-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:4D27385D5F266811A613EDAC20FB34D2 + 2010-06-27T13:55:16-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:4E27385D5F266811A613EDAC20FB34D2 + 2010-06-27T13:56:27-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:4F27385D5F266811A613EDAC20FB34D2 + 2010-06-27T13:58:44-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:5027385D5F266811A613EDAC20FB34D2 + 2010-06-27T14:05:30-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:5127385D5F266811A613EDAC20FB34D2 + 2010-06-27T14:07:25-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:5227385D5F266811A613EDAC20FB34D2 + 2010-06-27T14:12:43-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:5327385D5F266811A613EDAC20FB34D2 + 2010-06-27T14:13:56-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:5427385D5F266811A613EDAC20FB34D2 + 2010-06-27T14:16:22-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:DE855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:19:25-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:DF855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:27:07-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:E0855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:29:58-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:E1855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:32:34-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:E2855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:33:46-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:E3855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:40:42-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:E4855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:41:28-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:E5855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:42:42-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:E6855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:44:36-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:E7855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:47:08-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:E8855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:51:29-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:80C8B5F5A22068119109D8C24D4F5870 + 2010-06-29T10:49:23-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:81C8B5F5A22068119109D8C24D4F5870 + 2010-06-29T10:50:43-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:82C8B5F5A22068119109D8C24D4F5870 + 2010-06-29T10:52:12-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:00CECC59A92068119109D8C24D4F5870 + 2010-06-29T10:53:23-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:01CECC59A92068119109D8C24D4F5870 + 2010-06-29T10:53:56-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:02CECC59A92068119109D8C24D4F5870 + 2010-06-29T10:56:41-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:03CECC59A92068119109D8C24D4F5870 + 2010-06-29T11:03:21-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:04CECC59A92068119109D8C24D4F5870 + 2010-06-29T11:06:47-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:05CECC59A92068119109D8C24D4F5870 + 2010-06-29T11:09:26-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:06CECC59A92068119109D8C24D4F5870 + 2010-06-29T11:11:53-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:07CECC59A92068119109D8C24D4F5870 + 2010-06-29T11:13:29-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:999093B2AD2068119109D8C24D4F5870 + 2010-06-29T14:21:34-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:9A9093B2AD2068119109D8C24D4F5870 + 2010-06-29T14:27:38-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:9B9093B2AD2068119109D8C24D4F5870 + 2010-06-29T14:30:31-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:371C0BE61C2368119109D8C24D4F5870 + 2010-07-02T14:20:55-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:381C0BE61C2368119109D8C24D4F5870 + 2010-07-02T14:26:33-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:391C0BE61C2368119109D8C24D4F5870 + 2010-07-02T14:29:07-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:3A1C0BE61C2368119109D8C24D4F5870 + 2010-07-02T14:31:19-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:7A0142B9242368119109D8C24D4F5870 + 2010-07-02T14:41:33-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:7B0142B9242368119109D8C24D4F5870 + 2010-07-02T14:44:10-07:00 + Adobe InDesign 6.0 + / + + + + + + + ReferenceStream + 72.00 + 72.00 + Inches + + uuid:288c3c69-7dd6-7c4f-984d-b085b3307748 + uuid:93F9F49755C5DE1185BCB9A8461E73D9 + + + + + + + 2010-07-02T15:32:26-07:00 + 2010-07-02T15:32:59-07:00 + 2010-07-02T15:32:59-07:00 + Adobe InDesign CS4 (6.0.5) + + + + JPEG + 256 + 256 + /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 + + + + + + 244 + + + application/pdf + + + Adobe PDF Library 9.0 + False + + + + + + + + + + + + + + + + + + + + + + + + + endstream endobj 3 0 obj <> endobj 40 0 obj <> endobj 42 0 obj <> endobj 45 0 obj <> endobj 47 0 obj <> endobj 50 0 obj <> endobj 52 0 obj <> endobj 55 0 obj <> endobj 56 0 obj <> endobj 57 0 obj <> endobj 58 0 obj <> endobj 59 0 obj <>/ExtGState<>/Font<>/ProcSet[/PDF/Text]/Properties<>>>/Shading<>/XObject<>>>/TrimBox[0.0 0.0 841.89 595.276]/Type/Page>> endobj 60 0 obj <>stream +H‰dV PTçþÏ}ìâ³ì‚à#*˲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 ´F­Ek>ê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ÏWc 4[#"-á~иdÖô˲øøŒ±óÃC§ÄΛOò==zñÅÃmÄ#Ê|,œ–K^dk> zLíi—ä*BîÃ#ÖjŒ:o[¤!¼:oK¸”°ý×È>þˆBïÄsçê/ ·ñã‹g…Fp^¬U†A§¢à0Žíc’•lQîL<²ÎD9°ºÖÁ(l–ƒ™u‹Îh`Η1$½‚¤CHÚ_•†H[¤5¨ÕQ4þ~ƒ|¤á®xØŸzëÌjžþ͹ob³0•uÁ‡gLK¸R ~9ëWV¿ÄNìÖpʼnlÓƒ¯Vc4ëü,ádØl4Z-¯{ð–ùùûI¦]Åøâî¶]u›¶Î™¹3= ¾½»ðÓëOœK±mÿÜYPr%+'|–,—öïšãóA°¯^¸O•õ)ó(ƒfŠÃAîËôä•jOÕ'X º›Q£ÉQ÷•]B"Ø*0BÒ ü96@RëÅ2W6\üÕô ;ú#„~Yöèy^ „šìº‘K£>úŸ5mÛýEþ;Ñx3y§8TéœÙ¶ù=¸Ùôþ'a`bÔ¸Ô[zÑ@L Ù¸–÷ÃSç!/ø2εÐáþº`c FkQmË*Ðq¥&Ãoš¾ÃL<üpSNAnC‹3kuŽ§3¤Zugê<3^­5,RíïJ±«„ÊÐ-Œ S˜› ‚Øt³`ê‰ä!­8IEŒ%*b=3¸9ÀSÔ‹úõáA½ö+(Ã$¼÷Ïœ?w¦Á˜³uXñe9!_’zÐüÅ™ª8úT{·ï…kÿ£»J ¢ºÎð»ïÝ™œAPP)AÀ]`@‚ ² 4 +"›(KEœ(‚$„XêQA „Ã1ÔPk9Øq_jÝ©‰h —C qÁ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÷¤`œ?¢}"ŸB­l~DÇ2€'CB“¡ß*k…;/*lÞNZ_Ÿ‘–ß +³Èn¼ËÈ¿ënco…â[Ž¦·Ô^*¼C8‚ÇíÛ¤ÎtÊ¢:™'Ð#hF¢Lw A£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ôá²ÀdÔ!†ÿ +ø?—‡9¸'{‚Ì5~¬ +Ø´½—¡‰]Ÿ³a2ÛCº|mJHXšá­kxäp2®uøÙZ[Qµ¨1\õ˜]VåõÇ-ñ>ôæ^e×Kÿ4mÈõï¹,¢rŒÈRœûF ƒ„JË‘þNK-€c¹pDT6 ÷':p’V’K¸Ò¤¨.±w9ü@úNÞ‹§ådÊ“˜&ÓÓÙÎËG<,–4y/&-*®|›&Z›¢½ßG°,ÃzË2 —ù(ÝÇ› ×)w8Â3àâEÈ0úŽTc,°ÙA¤ÃÕcqÙâv›u$žãý?N1œ¢\ÓYH4V{®¶–îB +¦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=ƒÃÉ›÷Fü¡Ç°BMÙtD8â;Tž‰ˆcF|+ã~HÄTéˆjÄß9ÎìÄjÄV®5{ŽŠϼï[ÌGlC b‹áãð³qHû–3鈯9ÎÊ‘eD¥mF°ïñ}k´a}ãÆ[#pïñÿä8%ò±²þ«¦"6#ÐÕÿدþب²*üÍ}÷½7Ì"”²Ê®浬!•”6•  2ÔÒe¡ e$@;8ÓÒݶÓ,‘ÔI76J²A–P Ëöò› "’(j‰ˆˆ0ÁÝŠ¨!Z“úüÎ×+Üʨíäë9÷Þsûsïû PÈ1 ë ö;!ÇËùŸ¤?ž¬$¾BüžAE|xïC8þ߃¬ýÅ/†1Œa cÿÏàKñeó°‘¿mÁ#G^fcXÊëšú7Ý¡Þè.ß—ÇhÒ#Xz¿ ôJB×]aT¨?Ð-”¨‘®©O t‡úâ@w‘T™ÊƆÆlã–TÒK&² ï5oúÌ™3Ê>9mZ¹7·¡>á-J·¤³mëSÞ¼tf}:“È6¦[¦xs›š¼Lcúl«—Iµ¦2›RÉ)ÞÒTC:Õã5¶z /›I$S͉̋^ºÞ‹¯K=zœ%ñùÕձɦcY,Ý”||ÅŸ•hD‘%¶ …$<"Ár‚ÚkÄtÌäoÊèåiü•³n.ûÔ‹EH£…È¢ ëÙßÃ<–2ÔåÂŒ+SL¯&þ<ÖËœëØÖjJ)Êå&3¿X.¥ÖÀ~©â–Ì–5c&ÙÚL™Á‹¬Ks%â/õÖ³„}棚¿¿Pgä>c”Mœ¥ÖÔm¤.s=ÞþßañŸØ¹¥OªS°¡í}v9#æh^ª"Ô«ú°RO„•VPŠ_uØ…‡þ=_ó<ÇýÐß”£û£è çTŒŸ¯äƒÓþ6…‡ÁO”èêïô}qôì»( +›Þ'þQmäõÍOùNG +Â9ÚIlæã˜ÿù|ÇGÚü +r¤`0*ƾj´Š°×êÃ1} +×û°ÕùVÚ?C\-GºƒD¡Õ*û(n«É˜dÍB'å*«Ã¿@û*âÑLì!&ÝD’¨#j‰±—¾öÑ’qDZ;wa—}»˜}ú±À¥è¶aÃzµÝV'Ší鬇n÷(ºZ¢ ô­¼´Yϯ³¤>†¨}{ìeˆ„#(´çðƒì*={¥Üǯ,fEJÙË9«–z;fèÌÔ÷³® 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áy%&ªã(W?F¡rxæä}èÊ9_±*ÆZ¶“ÇŠÜ/œ%oV ? GÈÆôi®_x+{ Ç…gù¸AŸ5‰g5‹ç7 íî ¬u—yvŒKÃiٓ칕s.G¥Ù ¹3T +ï ŸÞ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ÎÊã¡¿ 0AwñÍ endstream endobj 61 0 obj <>stream +H‰tV{XTÇŸ3wöá{ØE#Ëò¨µBda×(h‰µºÁ ‚D|" +>   ‚Zå!"ˆ+¢U¢[>‚” +¨_+>ªUC‰6ñm4úÅ›SîØswÁ˜?úí7{ïÌœ9çwÎù3—!DI²‰@ȬÙþbv@ÈH/\]²2=q°Çw#ñ=§ˆ¥‹ãî(n;ã~®—â‚ê„r!ÎOãÜkiÒÚ´/ҧp~Ÿ~Ê•É‹âˆ×§ýñ¬4˜—¶ZH!õ„üâ)Ê{¬ŠKZ|üEòï þœ!ˆPÄA„lÚh„˜Ô:µ·N­Ëˆ˜M '„vˆNÙÐ/DG2X¾ÌJ†Ä + Ã¡wÖãЙtöa 8zÁÀòµ¼'܆󎨬È.Ë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ȨÎ×G­2 ‚Jç¡Æ!ôämºyy]îÎÌ;pÎÆïð«0FÑ6žÓ\SÙ+¡ðü QMÄ"ñ¢«D­hÑõ¹Øõ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Š±|Åþ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ˆC[c‰|R ,«|µ=àWËæe$‡#?Ú#ýGÛhó|OÇ7ïÕ;¿ÿËèé±Õ›ÑÞ1Ì´Eöq{¾½_õ$·Ú`¿UJD´—¯eæ»ÿXÆ*+Yú³+«—Ú*¶ï6ϲlÙc™CGvY+«‹eÏÅØ«{wÜ®j^¿»0sÎüU)Rd¢Ð³¹vϤ»Er*¼ÃsI»µþèíí9 ëܶ$eKù¢%gm[ᄃà~mæ¤ÕM¹…¨QS"j5~Ͻ%I!"ìžò· ••,¥ãLjöÏã»yvViutDNÞœRÓ²mç pŒ¦w?Ú—a‰úª¹11&1ÞaGhGÌé^VÒ¦q|Ò8ªT«‘jM)„vq «µ~º{ÛÝÏ3r +·5__µ{xèÿدö ¨®3þsï]ä¹QIÊ"!† Š""EðŠˆ‘Pdu—§º« >‚#1(&$>Æ*]dÇ$”¬8-u:h­5„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`ñ•£%ó[wrŸŸÅ›b‘ÛÅVcÃÈ©ûƒŽËn~Ó[¹µ¶ª¯‡†e©û÷fèÚÔ-I¦â÷ìïïTCFÕlg7Oç¬Ôü±õ|^61,@L‘­³‹1v“¼swßoš¬µÒÅÄî ²'xÈšP‡}\¸ÇFCÁw'M¥„vº¢’]KÒ³KßI[ÌheçÖÿ&”ãÁ?÷nYjzîš³§ Kòt¶5§QÃלÉrl.hwfÎñšU¯Öt¤–o™}æ×t†Š¤þë*"ÍÆäôÙ-+ª#ÂfF¾T´ùhð‘_&FÍÃ+RXDj ì£[¤)rÆÃÊÞCŽ03ÂäªXÞ[º%"‹ÝjiIH%”±I³‚œ|ÉdšYugÜÓìB•µ=g©/¿GbD¼†þç1wmÅÏDw¯™Åìn¶Û|»d¿Ï'ùoq±“Çjhòºâ)=‹¼÷UÂY–[ÇÊ?$¢·ƒäèEÁ‰ò,)ôa–äYÂÿ!yâ¡™Sè³Ë¬ëÞ4jŸLÈ9uè÷Â#pè!øíRÙG Ùˆ|ÄÄç‚Îø ¬P°ËŸá:Ä""ðâ&ŽAÄ Ì +ÚíðúÌÄvÈ«J@4a¥spÀBØ¿;ü@Œ@Õg~ŽÔãØà”†hC0tè ¤GÝpFûœ7"Þ^ƒ ® ÚëªF˜'ÜpmÜp]Ü0†º} àŽ<îx‰ô˜ð_ˆ/ÿ7¡Iz‚'x‚'x‚ÿg`ÕX‹5§íW Ð~/Whé7Z…ô» +íÓà0Ž$"VªpºšÀXrN¡)¸’…ðûw +-ÂX:J¡UHû)´èé‹óòròLy z­^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…ƒš¤ðkÁ"Þ‚Lé¶Î`zÁ"•ã{3X¨/â2ŒÆ[E8 ‡)Ø7•2Å2¥Ý‡}w Tœ +Ò&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ܤÈÙ½*ðõV1þ¬†,ïv÷¹þêU|¸U2óïr·˜Åx¹¨}¼¿ï±óðÞîÃî"C3ø÷žkI×°ûŒŸ ±gfwU3ã†[e9µ¹ít=Ÿ›ÑÛ©¾ÜiÝ´vål~U𸅸ž1ÎoŒŸÆãhöƒÄÇÙC pÜx–éfƒ»®Q·BîV4F.Fó»°Y™.Ó!&‹y˜^z]!¸SÆ»À§G i1î +Ø´`ù(ü7šnmý#MGÁf°@^oÀÛKäö)Ðò\ïð{”œ‚ç<Ú Ç­˜C-@Á¨ ¬;‘á„¡+­Ï»cì³–íW‡~9]ªC A#õhuÅ´]‡'k÷VVB £žu´ßAÓhîÿ¢Õ.«9ñã!OVˆ#»Ç G4•¹½v«·®C¿¸Žt™µO/ü'éåd{zÙ} ¦ ñé\2“.¸Öô¢­¡ÏG?k îðOjÞö‹/hÞ|»V~ŸæYƒ6ç·ÿò{“^ +:øžñ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-L3¾¨B|TXß—¼V©›¦óOùhÊüÏè9IŸ“·YÿÏØ;º gÙ/ú‰<ˆ+ãs=Öøê¸Õ®ÅPÇ? -ñ]½ã ßÍÖ£n‘˃šrS¼ó9¹¦=ù2õ¯L-¬ ›6}å5éðaÆx|'êÉmâ¿R3`»±nû2¢¯íå?ÇË|z9ì9íá WíãH¹ j^¥Ï endstream endobj 62 0 obj <>stream +H‰lV XTÇž3wvñ»°,DSX®@MMX–UÀÔX£©FD@>‰Ÿ"">¨ "¢5€"VÁB I!QãÛø¨1qµE%ÄGºJÍ*¨H–½CϽ ÑöëÞoîì½3sæÿÏùçœK€âFVIqÃB— *}…C +¾>{~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=‰)o^žTÄÞª¥ÃlèóZøÿìþÔN?È„$XïJ"/ãyôøƒN:!ݧFyÿ4ŒG›BLf7‡‹³ Õ€Þ¨Oƒú•+—ý¬ñî¹»Uuü4]|*×Èš“Wý¯‚KûKøϼ™}KdŒ ˆÑ€ö|I!³)TgÍjQ&GL¡ñAÞE­÷Æáps]þ–=g(ùõ—A{ñ~„·VPZ”žòÞú¬äÂ/Œ‡~´²óÌ÷àÁwñã<‹' +ÖÙ«·­CáèH2+añDƒfÐ+—NÈ•òiÕÍæ¯ø!Æ›¿"®¹)87Qžd³2_G ¤|!7å$ˆ Þ<ÁCÒd.nèåÔžFÖžQÀ ŒÁ!¢Z#Ùø5Ò‰<î¤þàFRF?7µÚã| sù6U¹#•%‰cFüVºŒ1ßGËE;èe<'&­Q‰±F셰Þ>Xܧ/¶-«ø˜Û.Ûvä¬uVœ-ØRVª*ß[¶øó`¦?¸éÈmÖÄ/šÓ(íæ£WÌN]‚‘ŒGÏïDÏë‘—Z PjУ£‰Þ=oa;kñS¼>‚1—ÖUºÆï€êÊ…ª‘ °FÃøkdûÛüû.;o¥Äq«*ü=Ô²ÖŒ2J‚¡D”‡§ðªÇ`àö.U¹ôoä™Ìê$àÛÑ€¨Ð†pmôU,è=mŸà&ÝǼT•[ùüs|ºµg¶|Úû` ”™"Þ¡Úù»àƬ<Ñ*Õãââ«Ò!_?™¯ñÿðÕÍF•î +¿Š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 àÛ£:&«Î]F 2ÎP$Nž¨±Ã¡Npãÿ|Ú°ckÝÎ÷)“œªò»MçùSj•œ…«sÖÈHy¥‚ty‚'wð/`é3°aThL~”ßAÈe ã!–tð·Î¶µýÆ~Ëo…?h "Ðá5<æ­ü=¶a?â7v7 ìE]…¨uXmð‹¢‚¼çœ¼ ½°v÷¸•vøîæÓêIc[$v0«´pTÖKUåß[zñ×, ”eÿà‘ëçÎ\€Ñ›ÛmN#“@̨ZÌ™h'$óé`“Kðr&5¸’I`pæ¨óÓï,ÚõáàqyÿªU{çåÇשã‰ç"Œiœ°üí)Ç74^·8RSb&ÎIœù·‚-&Ü«$«œw—ß±Rц‡¤fí21«UQl *ÀgõÇOÌ ¨W§r—NJ— _{@c¥2š(Lu6ð¥+ÌÂur65ôœ(9‘º”müøOœ‚fë5ª>^0Ïš;þú¨h ‹RÎæÍ\7PY§d_xn}o¯á6Þî©a}<øcþ#Ÿ úP«™Œt8À<:[ä;Ó"œ~¸I›95b&ëße‹ŠÍd±É{°µ®ü„éÇ ² Spëª|¤ö²ÕšÌæYåˆÁ¨T1?Ì·˜ÓfQ)qžAAaJý Çʬuo3ÓÃlÞ©?í†I0ôÄŠˆæ?B1}vÜ´·f–ÔÕÁKC†\XtNÎHË ©ÿ„èQ“7ÎM’÷©Ä¼^ º~xQ‰z9™°>ë°>‹BÏJA… Ìfc9-_ÿàl>œ¾q볳·àjiÁ~ÏÖÍ¿¥c×¥—Ú¿u—òõ‹*äšHÌøEñLR˜C……YŸÞâwa˜csjfÞ¦/>ÞºtùÐ1`¼ +¼Ö{¼úƒý 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ö¾—ðŽþ6EQFwÜhWŒŠaTËMzXMY0Ù½uÇLšÿêTú©;:xiÒDÚ)FäÒ}Aì•Dö !.,„D Y¸dò/&1ŸÑ?ðiÃ{â*ÞFüZBüبˆœR7VdÓè¤ñãÆùó+ä1U¸+vb¨™$¡~w>Ô/V/Õ·=“É«\SŸY˯0Ï2m1'óÂú}}™¬È>îmá þCªÑð—#Ç„††Ñk"*h«T…:GÖÝ\õtá~ÒË.—…>taÝ• a°G©ÒO 1ÏœA‡ñc‡JĈzVËOð,ÒJá9´…§âÕàßE6áПlæ;#·îÿ 3oÒ¿¶:Šöîü½ë­úâòöE>ä«ð˜x‘/—Kù[ü¿Ãkñè-nšŽ'g‘ÏÈ„‹é§½ÿ”E؉†iF…Iÿ§Ê<»¬:æ,[6gnFFkï3ˆ™6Ó¼4c¦)Ý»;‹ŸQ#˜†Tð?T;`/Òy¤Þá„÷ Af¤tÊÉûä/¤ŸhM¥VúšF;èÇô¯’#Y¥ÝÒ'R·ô `‹5úùªgçØ-¼›Í‘sä}òIùºJ˜2UÉV*•ß(×¾0„ær › G ÝFÉò=Ré ¡÷_g”èó¿MÛaÄOÂÝ6gÈïÖyùtÞÓá ö$ ³Ã}'0•ôê<?¨óL¥ªÎ3äSt^AÞ¡ó°RgRqa±£x³ÍªZóùê5Îl6ÅLW òÕ4{™ÝQ¹Î¦.´—¯³—ç;ŠíeÓÔÄ’µ¼¸°ÈQ¡–Û*lålÖiêr[¡ÝÖ¬W¨ùª£<ßj+Í/_«Ú ÔÌ"Ûóõ¬È^‘œš­ Æ,·•¯¶—X¿ýËï> $A1"ˆÍ`+æ»òñ9¹#ˆ80#™p·š±Hñø.e +´i`‡2„*aÊ«°ŸÊ‘ÿùš^Ñcš&U‚¤â{1f~«ÐžlØÚ°Ý /z.G®ålñ©Xë'Fsh:­øµÛrX‹ïìh‰ +™¨ÏöìYÙˆdHEÙèoFD?—kú‹a5>—àhíÛzäŘß^îûèù""#±•4 d`ržP{Z +´À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 ⢑…ÈA¬ý…¬ì$Bh¥ƒ°ÍÐ rY'´±G)_Ä61 +Úä|î6š mR4ÚöÛ;ÐfØmJBLÖ¬·Ÿ¢L¬aV—[ IŽ£¡üÙŒb ÙÊ~\‘LƒýØÎF:%,âÔ)8Vë§t,ØZ˜ ,ô˜4þ(8iÔЈÁ\–¤ñNC8Y ¢]ëïýèÊ/€úâð[󣄱D0(R3ã¸y4Z±MÆñ/¿5ßÑoá³×'a¿fÓs Ùh «iøà=Ä5Ĺ!Ûž…°k¤`˜'Q°âü¸Û¤¨Ä˜4âé¬ý …%Ò©J¥J°Š¹3Dv*Õž5áê0³Kp•Â™‚I‰Â9ŒAÿ6ÂIŒM†ÔéŠ?ä(õèK;Dãügˆµ§ÉÇC)öËÔâb…–ÉʨñÆIŒix ‘‹¾h‡!L­5P€°S׫vÍŽ³èÆ\Ì;yÄè{,ÀzpNÂo±±Êæøtázó€sàmpÝUÒìÁÄ-ä5ŸuhkLÆÿ å0—Þ„Zfº ÂÉU(ÅÜšGZ î¿bºÎ`ʸ! ¨Æ‰¥˜Á”NAiœ.Aî¦apú{ÉÀJ§ ´Â¾‚¡˜½’¡˜é C#ûm†Ff>0Î¥hþabŠc†Y>0ϱL¦`^¥ipŽÿ,'Ùu °d`Ðgˆ +ç{§ŒEO endstream endobj 63 0 obj <>stream +H‰ìWIŽ$Ǽ÷+òS«GÄU$¨“:è,´HÐP©ÿ²%2+kfø¼t§Ul¾˜[¤G>Ò#5þÁ×ñ¯·þk:þùß·ùQ?ÍüÈ¥½ÍGÍíøíÇ·ŸÞÊL¨LR=ØÇô`ò¢Ú>[ô«GZ~ÌuôÕeGþvü[cÿäÙ™güî—t|ûŸ·¾ü=ÿÎïåw~¯þýã÷Ÿþþþã?¾ÿö»ãã_¾IÇŸ¾ýæÐôš`N$X•<Êcõz\~ÍÓ:ÚŽ ïüzäý½àŸu¸ %,yÿEóô÷‘F>>à_Áw.EßÁïÞŽ÷7 ,ŸçÅ‘<ñYÒäw™cMkumøé„œ”‹qéý§yᤛÍ}cœtÀ„Óa#L»à'Ä}Ÿ”G;t l/mð_íZSKœèýfUí¯V^[G®_`NûÑï0ç¼!ŒL*tcšôX¡§ßèÈ,ÿÉ‹“³rŽë;•ìYöG +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Š&éHf X£æÓÌä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Ä@\‡à/bVL9ëoÍ4cóþwQÖ=cío·´¹žCtU%Ö’š7¨»¥ ìeËŽÃ’Vuô +€%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¤æ¯ù|Pnø|"×z}K¹+Ûëpc +ÕÔ)žÕ |£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ñŽq­Dµ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Á Ù¸™Æ¸vI·¯óTÏxEìºó‡…³Ì-ÐE&zf¥}N Å'É ]§.ª=6p€Êsˆ¤°üÈj_‹ÏÀ+±@|:ê¯ßßX „Ì´Á3¼kQezå]?d&Lá7žh½ú3Ð[É°s*»²‹?,$*àTkGB2œ*g ŽP »jñüAë)Ñ´€¤ƒd¼ÿ2lª°$½bF]¦ø¶¸ZCíAÑ!ŽBð÷øíGÆdÓãu;î}û!àZÀŽ¶Kˆ4¦—ÀD~×⇼B?$¨?îÒ)Bñt­‹ÄtALÇ.)îãy”½ºêÁ;|Û?¦WøÆÇQ$Œú4 W¾Aš®éþ¡c½¦{5=´ž»÷Íd×éJé² áB]¶jºï¶ÇÏ›ïÕ§g®ÝOÇíÓû«mý3ÛzU"P“°,¢ôªD$Š-r–›¸«rt·ûSºf©ÑÎZBÚ’RÓ(Ñu‚wfy]ÏAÜizárž +áÆ̳é´Ü’!£€°Q™" +*®5°˜‰n]MV©q¡¤®~SÝ¥hN°xáÑÞŠ&ùU¶î©î“²qXVÁRÞ‹:²*ž7,’¨î3sQ(×®ÊÁ!XZ†¯hÀp}¸F$PË'hŠ£ýØE‘,F$R‚êÝãdG¸ÄÏr‡ß¡ +¢¯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νäÀì§6 ‰x¥ä”X;bqÍ[²" e¹3ŠÒ‚±óbWîVÕ®4ZS²¨Ï`4ÒÜU?u¾¡`‚¹ý<÷t†YKˆ©iÛºêÔ’˜ð‡ñv!Lgx ½§.êYÖRÑ{$«ÙÃ3wýæ¦MFlþ!DEq½@&v~9Â,ÉcŒ}éø”Â&!ïö¬E€`i¶Gò:Ž’X¡²%} +’ÒâV½¶©E0[O5êmx§)‰°ˆìOOÜDuä#ƒf¨‹¬Oi0®K‹UÓÍ-kîVíyÖ•¼x¸b7Ë5b_å@~,3‰›ñªV +ö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á¬÷±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êN z…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´_’_FPi0³& +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æÅvD—ê¦qÖFŸèÓ|Ü6‡Ð)­‚GƒÇA7m¥v)q¥Â‰¥csDX–Ÿ÷ׂB@Ž)ñ]È›Y …Xy–wúƒ$ÏAR_ƒdËõÇF£kmn…ûÝ:gH“s36Œͤ$­ä:™^áluœjVŠŒÜÇOCÕZŸ¨Ïò °Ú‡;¦ífñ¡Â“‚擉M}…j›ãøsÿÑqç J>ŽU‚ärB }lhÚ:Z,G›ÝÁbê¢ÚB£èh“œo÷«ãø†£9~pÀ= Ø˜h8¾†ÏWï¡¿-Vk¨„;VåÔ +Ò°ü|ý)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Û8Ò¤NòÇÖIlàîXì›C‰ÃòÞnVUdŽ8Ô™÷¡4E¡¸ò¾:° œÐÁûBñ'%öS5ð*:úƒ¯±î®Õ݈~}Csƒ="4z~ý¬ŽIµ­ ÇÙÕ K€'î Ø‹ÅÅ.é«É¼9t¬: +Ç¢çä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“~ÐŒ)ÙÇM0ÜÙÿ!LZ^•(V+Bœc`utTÍbTî³·i2‘ɨ¯Ñ$’nŽƒëNdñÏ:ÿ\N„íùW¡áæYIÏ ÁìÁ_Ãq„©–ª³°Øtÿ«C÷oÅ?œ6†ìÏ« ¦5g5e˜ƒéê8èpÖVÄNÉŠ:fV^Ñ#‰Í´9:,ûH¬z”Žù@ÍAÇÅìf-Ù÷¯í +}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+ïÊì.ö!›Ë©ÞC˜U¢}8é“aPñúöÕ¡ýÕÅÉ-ÂO‹~ZôÓt6‡¶Gž‡Û&4’$†‹ òå¡×Pr­»ƒñýebO£k´È{’¡g(ûú^ÑÇMª &Í<ŠpæÊŒ!OÜ¿û`]ìcµ#vc'DÑ>sÙkÚ¼:´»õzutóH½œwt‡¿Ñç˜kS qòII¬ÄW‡([ +. {i¢\uRBôV™|²¥I¹‡ö×ä +rt‰ÿ+€Úôln]M‘­½-Rá‘„«EóFü¨è)ô“0½N˜²së”Ì7L+^¬qî~Ú¾Ùœþ$óåJ1M?k9Y™Û‡³­äy©M‰ŽL2ùÎË)ÎTTÄ}8íÐþP’®j,*‹Þ8n µrMŠóªÜÛÈë™®Z8£°˜¼”<“bD ºr.DMa&Š=õ¿öÝ{$¿IÁ”Ôظƒñ+ðØ÷èPè)Ú9âÅæÚ'im.ŽðKh®…þÓΡ4 u q:H,?2Ué‰Æ&Å™œP¸Èx·Ž7DŠaû,qƒéô‘XSŠ†âjb½Š²Êsgš(K¬ˆßêQ÷.Í]YÜ…{Ä;àjƒ~ÛýûÎò/K“lá Û’-ôæÓnU˜Ÿ (1€8x²Ï’@—å1äe·G¡Â¸Ž€Pp r¡ +þNüÉRé9-)‹‰öôˆšŠ—A²ãî†GN˜C(B H@pŒ´Ò3ëÃ+Obæ3kâ]1²Eðü!±7o “;ˆ"%:?ʖ쟗ÝÇFe¦Qz7ÀùáKµB!+® 8òV‚j3ƒY!´ Üâ™mRŽ,ŒΘ£©v ”ð  ð™7Gř̟¨ ÁD&60ïIÌBkIqÞP³_Æ&Xø:ˆ>è;×(œ¾Í ã2„jʇŒ]Ô4R‹öE<%fRœÉ·B…h+#ãˆë(+tUXSIÊ:À­ënbZLΚÈbχ^f‚t~–‘Z­Ôº¥.@ýº +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”º²D§ã‚$têð‚Yœç£‚KœLÏä‹JžKŒJ² ! +¹0eyÙMŠ³$~bEÂ¥HWX*ðŒÃ!^_râLŠ3e‚€0fªÈeR¬¬Ï…ELj‰í —ɨàÄq” ª ÑT=‰6§Eäõ½‚ÍÖ­ @[œìOSÏ=*;ª ©<(ÙL* &ë¯}÷Þ¢¶ + š>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"ü=™`D" 3Ø?©s)¾-E–_’=Ýáñð̳HâYää~¥?ÜYŽ$ý@ÇBý×¢¤AÊÞ=Úýr0Æ›£3x†“>“ ] +ÊS0æcʽ,7ž¿óDܸ—N¶ÕѶņ¢ú Ï§es~:ýΤÁ8Œ5VU?Ǹ`ÐBÓ–q•Ëzz³¦ŽV-Vªu1OV>}¿>ž¦÷qº½U9_Ðß/^¢[P*XMƒ8A~YÐfCÌØiFAáFt`¡Íic2VŸ–7~þ×ÝHf5þ±láh‚AciN™ö°–ÂAiCŽÐ¿Ù“¡tyÜ7«¤¾7l¼‘‚‡õb˲|ùð¨õ:ÑáÚ°²+€ +¦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Å-ú€süšo1Ï1¤4_?Î=lãϺs³¿¥ÿ“¦Ùé2ø¸Š¼|5}¯˜À¥õxtæ°ø§øƒøn¬{?º gÇ6á…Æ&7Œ‹ou„ã­Õsm¼›Àh#¼®¶-¹6<&}ßcwû¶tiM­÷žüØ7‚÷@âï»c¾Yb¾ªÁŸ‰ù5‰I_RPÙEÝNC2j²Íßrå—êTñ¡¥Ù­éyÕ€° öij+U‚´´/­t]ħñûe_?>—®“Q8îæ%|m0¥o8f<2´¶6¤½kwb›mëÙ›õ5ÐCôÉÌŽ@]|«l.ÔåºYÂ÷?ö«eÇm] îóþ+|êleœÈÙe{,‚³Êÿ—n²ù’h=™ \Y¶D6»««ªsŸ1½ w.Ùô®,x&äWC¸`ÕÞCŽŽ>ÖóÛ ôóá§@> ° À©Ï* ÉŠÝ{ÿxdYN\}ù Z\Q5_h &HRž¥À¤ÍaT40çunåMƼ…éýŸ$¯ ÀydCpmÖøLm>YYÃñØ€`)å뎇]©à»|d›ã3î^o,Oh•DÝÖª³!E-©•6ÍäÄÖÄ~ßÉR,.×Î, ï½`y—i2S¦Æȉqx™Ÿå^áÔ´‘#Æ€¸3ÔwÖ§2h"¸ƒ«§Õ—F8ýÏÙRù‚ï·D’o‚ê†Â½%uŒý¡0îI$“K´k6fË¥–%_Ä(þxd$%=> ¤wȨ̈E5åömår¿W„¼g6Šñz¨×üJ +þÏ„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‹Ì*ù¿¸ßè=Eºz;ù>žIÍjºcŽÜ0±¹Ÿcc€/¬ óŽÛ«:÷6p>&9ˆYoªÊt^Ø)v°ûkÌ>&~ tö!©s™É™íûÏ™v„r°ÇB}jæÛ4¥^<ฆ]l„ö+I]ר$4WÙÈR°J:æÁð’*Ö {0Ë—øzmæÐIúò£±k$_u‹SN( ‹eÐ1)>1ýçãt"çq“ÿ'IV\`7]Å7Q2LtÖx"ÍF FÐ÷àç³&L§k#¿Õä4™u¨žDz1®Z¤sç §oº9±8Ø<ý—J}O<9x A@ÿÝm;ùð¨GTØ +^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ì ÷F_¯—ŽH² ©‚å»ßÁdBëš…dÁy +Ÿ å½  ±‘ †‹mÓOš½Óý+SO­z`¯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'ˆbO»Ì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½­û*šq^F°:7àœêy‹-mlɞ͉‹39Œœið›RagÄR¹JOÖ›cIg¬ +?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ÚšÿÜ0Øá<ô̓e¿[÷žâÍ,FþìNw¹µ ¼zGd›”û&¥ü #I»¥2ã•)ûºSèç4ÿtrd’r'–Û:"<ÄÑпGצ€šc5èS¹H:æDÊU ²ê]Qõ"¸Cü^)Á +îœ3£4™ƒ½)$ýæ$¦¨Ï¢kOy°2®¦ã1ƒñ&£_fNaU€å–®¸B0‰ƒ(ÑýZ‹Ð2Üî(Nn~ÞÅ(˜ï‘%.–¥éô^ +IÅcôÃ)Ø性ïÛm(·ÆL·Bž†ã-àë"£ÒSGþ©»gþ^ØÏúžµ[8BõÕGû~lʜ՞éÓÉÊv QM,™@¸gV5?x¤±ç„‰{£ýmæUå¤o­„;§!–eéLl--WªI"5 la;p®  k©WAe¹Ù8N{é!)p®Ö¬90•ØÖ°ÔJ2mÕk?¹µ¸-S&™Ÿñfi¬r{V’)[ßá>tScPüa”Ë z¶ÿiÃlƒ”Óá÷—¯ß°Ã¯?™MpÕv±x»`ÿqÿ4ñqâGP9ÅÕ7ƒXÎG.Nž|›¤ë"Ü›özñg¹ \âŽwp<þHPÒÏ”¿¦_Æ¢œH[z‹h ØOĆŽ¤£Gu˜QV˜%½C«7ñÜtþI™6fšè–_ÒÇVo&9¨YÝm$b×¹ÑïumWä°3§¶ib¶0ÏÞ„7d`orèn¨MS\U° hÖ¥¡æ@höÈüvlÔùràÓÊãNs9+œ~D`ÊóQÎ8Ó=Uí¹Ðá 17’aìÉÓûD÷~7¤ùeOuÊA,"úÎa i­ÁÀ€áHÑá“Àê`3ïm+ ÎAvG?+‰Ïmu²¸°Šé—Ó™3Iò# T»ËÍÚ@7°!:|­NÀyƆùž½WüZ- åY2²ÜÄ6h !ßωôëëÞ9‡ýýÿ+èoŠ—¡^§Qð¦hì¡ßaÒç¯Ú_ÅÍ_M’ýõ-½Wx~…kö½˜á{ž­¿›Óøû5òo5ŠÅ ^·¯9íøIºâ» ì(ÎÜe!@:‡óäÀ„–>ñaDIyòOËÕÏîÍÙŸÑþj€bÌÏŽ~®}ØÅC +ÈQK8à‘šH8õ i>ã÷H­zÄ’Ò²—ëŸ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_&ÈÂJnnq­pE×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©Çä}ï -f/Ú$­•*”øN§oP#0&;ÐÇçË—|¥ endstream endobj 64 0 obj <> endobj 65 0 obj <>/ExtGState<>/Shading<>>>/Subtype/Form>>stream +H‰LŒ± +ƒ@DûùŠùÏÛ]ïÜmÁZ,bBl0þ?h’F^1<Þ +õœª±tžJïlÔãëôIkåçßX‘ùD;LÇløŸ4B̘Îþ jx¸°˜$ÑÎ÷.3ÛiÉÜ^gŽ± 0©Íó endstream endobj 66 0 obj <>/ExtGState<>/Shading<>>>/Subtype/Form>>stream +H‰LL; +Ã0Ûu +] Γc;öZ(™C†f/¥YZHsÈ£]Š}´#…X˜J eØÅj.Øi &ñóÀoì0>ÑO‹Ó_)¶&_˜ãßs«I)Ës–Äû —•ý²ו3fœ ™¨¾ endstream endobj 67 0 obj <>/ExtGState<>/Shading<>>>/Subtype/Form>>stream +H‰\’=n1 „{B-Rü‘ÚAjÃEÜ»ˆ‹uÃ÷2än‚÷¶ØO;âˆâgS#uﶄÆÖþÑTh²0¹[Ÿ›Œ¡1û bnXôþÖÀQÀä» v­‡”ôk5ìòßøÉ@žXšÕ]7ÔFÊèʤk•t›°?€#ÃËϼCКQ»Ip×M²³šÑ’ò߃#¦`IƒÇ>eDÊÒi¨žþ[p4cšâ l3—œ MUÒÚ¿Û‚ÿÀï´|UA]¾hzæŠYR4wÇév¤ÿ TÓÏÄ;o·—õõÊAcq]2ÿ€ßê#ÊÙ؉ãœ×èŸáÅóœ Lü÷ ú%7ª+Òm«ÙÊÍÔÑDù/ѽ{p$Ðœ¦t}^~+y;ªoíWÿÓ>Ûè¿ÛÓϼ¾š0¦'†bpžo7º&ÕCçªã²Ši`„?Ú÷×þôò>ú×{ÿñÚŸÛsû+Àr›g endstream endobj 68 0 obj <>/ExtGState<>/Shading<>>>/Subtype/Form>>stream +H‰\O»Ž1 ìýþL?·H'jDýG'!þ_ÂɧÝÊ™‰=7ˆ“zEs'/_ d`#)ŒÒI,‘Ré%rI +qt\`G +~øsÇ \à+Àó¯J‹ endstream endobj 69 0 obj <>>>/Subtype/Form>>stream +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ÝƼë>>>/Subtype/Form>>stream +H‰,RKn1 ÛûºÀ(–lýNÐuÑEðÐf¼¯äö¡üŠf@™Iic-Þ^d!¤›3dó– ¿¿Ç+}ŒÉk'MÎÂÏûxùñkÒÛ¿ñ 9! ž©¯³ë2ºÝGŸÜÇ%¼-IÙ|Óµ8\i³ ãå¼Z›§&ÝÆ Ð6¶ét—//£K„]hGÅXªÐ¥rá0y-XçšPøŒ€ÛiÒ\¶ Ö|vRåT@E8Ð…ÆÇÖ¬Ã^,브<äh¸Ù—Óçè‚míBeœsLé2EJqBåþ/¬Šw8•zÂä4¥¯Ñ¶E« sêI1§4½U F` Ýv"Ãf-í42¹´ƒuK*Ñ⤀!‹Æ3:K…6ÐUÛ{J ú鋲œ>²‚à ÀÌÒ s6u0»²Öß0•jχMôü·ñgüÄó-À\p‰ endstream endobj 71 0 obj <>>>/Subtype/Form>>stream +H‰4‘KN1 D÷9…/ÐÆŸØINÀ±à#`iàþåD(R+/.ÿª­6ééœÃI•¥ORã\A?ïí¾›°­A²& ÎW{z~úümÒý¢û˜I1’%fÐíÞ*ro—²'Ù-érÖp@Gù«s +Þ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~έ}´œ?϶Z endstream endobj 72 0 obj <>>>/Subtype/Form>>stream +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Ý,Sÿ endstream endobj 73 0 obj <>/ExtGState<>/Shading<>>>/Subtype/Form>>stream +H‰\;n1 D{ž‚M‘¢(µ‚Ô†‹¸ß"[¬¾?R[ÄëJz#ñ3ói$­¢y%)ï ªé.¸ 2‰I RuT¡R“┎ ¼ [ +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]Ÿ+~Þðø`¥òe endstream endobj 74 0 obj <>/ExtGState<>/Shading<>>>/Subtype/Form>>stream +H‰\“=n\1 „{BˆLRâÚAjÃEÜoÏ ßEÑX­«Ýož†”¨ÑGAi¦\Y{3’ú¾ÝBÇh‰˜4°ÞÊ#_ÛY.VK‡]‹÷jµ/÷!l»l»ÎÓ®Ó6f3дBØEFh}xˆ#µ1ÉïþS¸NA «´ ¼*(@ÐQQúˆXfë6VÁGáZ‚‚kÝoMÀý¢Í{Tœ'BØøZ,€›;Wò®Ý+¾ ïîˆS7ʲ®%ŽoÂøZ¡«IßhQŸÆ \Q¸•oBøÑr±ûFê}£&rîçÂ^g ¢²Ž?Ec8Hz¢g"¦qðuçÙ1¦1,PüŠâ¬WƒŠ¹ùCˆîF3Ò.µžI%«4ØÌ Ç0…k «»Ž}N«ûÂî±s7‰Ó}¾yk€>jeìw&ü +G5¶|s÷7AÕ.! ¤ýH5“Ï~ÃËû,‚Sëùn0ý§°ßÙ¹\E³X<“³Ù­ü©ÿÊGú·<ý~ñŸÏ­1UièËùø÷ãþ9ÄL™jOã4¿»Û{ùùZŸ^Þ ~¾Õ_¯õ¹<—ÿ (⤠endstream endobj 75 0 obj <>/ExtGState<>/Shading<>>>/Subtype/Form>>stream +H‰LŒ± +ƒP E÷|Åýc^Ò“UÎâP÷RêRAý¨Ô¥Üápàp7ª^XÚ‹8 a74¥c“Àþ¢VÚHð¦ö>8èŠ4³˜AÎýûï°fÜJBkeÏp‹ÄóCýŒvZÇ‚aÆH#}š¤Ù endstream endobj 76 0 obj <>/ExtGState<>/Shading<>>>/Subtype/Form>>stream +H‰LŒ1 +ÂPDû9Å\ÀÍß¿Éf· ˆuHazÓ(ÄÜüh#S<ÞÌŽÁUªSÕÅÌxªQÄuëï;®|aGáÝei8ð“j¦¶EiùïßÃ!£×d†ddØè¼=1­ì–­ðØx^9cÆG€/­ endstream endobj 77 0 obj <>>>/Subtype/Form>>stream +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ìý€>>>/Subtype/Form>>stream +H‰4RKr\1Ü¿Sèƒ 'ð:•E0•xᲫœ¬rû4è¥Þb¦ù´è†¯Kœb­aÄ"Ðs + ß?¯ãóbÒŒÁý½_/¯ßy¼ý¹¾†tDÆdZ‰. ñ^ãùqUæãz0Øs0™­ñ2ÙUûPRÏ!49ÆózLbŒ!ä`#*´ ,²i9³ +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úÊÒ U/G=Wç³ÇÚN ?³vÅ𣽖>#˾[ŽR,¨ž^Ø“à ŒW/e×uä:]"](‘½P®ÓÔÒÉ´ÁUçü¼~]ßðý`ª‰š¾ endstream endobj 79 0 obj <>/ExtGState<>/Shading<>>>/Subtype/Form>>stream +H‰\’½NC1 …÷ÆifG÷¯ÂBët7øiü…ÎO‡{J_ù']SÉßéðþéŸ[*~<^®P~¿ŸÒº_àãïýA,Ug•Ñ°xU—ôżÏsÉ·s~;æô‘~ì/¡j endstream endobj 80 0 obj <>>>/Subtype/Form>>stream +H‰,SAŽ1¼ûþ@Ì öå°mrˆ6Ò&ÿ—RØVKmUS†¢ ¿;M‘nΔSûÄ¡ÒeLë?Ú{ÿÓEFç>ðünßÞ~Œþë_ûº_¸[ÐX8\Ôúë³Uä³=LÓV2ŸýQ +—>‰çê“zv£!«¿ÚËmx’ÒÀÓúÃLÎ4£ˆlęȒK\¤Ê( {EôAø¸‚Š¹ Wxájù@^e²•U,R‹­J‰BKpä‰% +éкà²Ó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‡ËªaÆ^äÚT*:¤–/jJI¦µxÓð†§±Í4Šš<$•(,D³æãµj ú΋ϼó°â!ÙÝ!i®­w2)ËËbUb`|V?¦SÿÊ«ýlßñü`0<¬ˆ endstream endobj 81 0 obj <>/ExtGState<>/Shading<>>>/Subtype/Form>>stream +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‰8­p±æ€ûŒ{èá+Àˆç; endstream endobj 82 0 obj <>/ExtGState<>/Shading<>>>/Subtype/Form>>stream +H‰\Ž»ƒ0 Ew… &Ä$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`|g?C endstream endobj 83 0 obj <> endobj 84 0 obj <> endobj 85 0 obj [/DeviceN[/Cyan/Magenta]/DeviceCMYK 88 0 R 89 0 R] endobj 86 0 obj <> endobj 87 0 obj <> endobj 88 0 obj <>stream +H‰ª6TÈÌKI­P0Ô3…ä²"…ÔŠä …âÒ$cC…¢üœ¼Ê¸àêàòxDÌtÑå¸PŒ3ƒ©4ÅT‰¢Ð¨ ,oB@¥ ÌHcB–ÃY_ƵiPR endstream endobj 89 0 obj <> endobj 90 0 obj <> endobj 91 0 obj <> endobj 92 0 obj /DeviceCMYK endobj 93 0 obj <> endobj 94 0 obj <> endobj 95 0 obj <> endobj 96 0 obj <> endobj 97 0 obj <> endobj 98 0 obj <> endobj 99 0 obj <> endobj 100 0 obj [/DeviceN[/Cyan/Magenta/Black]/DeviceCMYK 103 0 R 104 0 R] endobj 101 0 obj <> endobj 102 0 obj <> endobj 103 0 obj <>stream +H‰ª6RÈÌKI­P0Ô3…ä²"…ÔŠä …âÒ$C…¢üœ …OBL.b@Ð.°:s]t3PTšÃ 4ÃTÈ…¢Ò ¦Ò”€‘¦pËM¨„û¦ ¿Žk ¢FXô endstream endobj 104 0 obj <> endobj 105 0 obj <> endobj 106 0 obj <> endobj 107 0 obj <> endobj 108 0 obj <> endobj 109 0 obj <> endobj 110 0 obj [/DeviceN[/Cyan/Magenta/Yellow]/DeviceCMYK 113 0 R 114 0 R] endobj 111 0 obj <> endobj 112 0 obj <> endobj 113 0 obj <>stream +H‰ª6RÈÌKI­P0Ô3…ä²"…ÔŠä …âÒ$C…¢üœ …O\‘ÆÁ¤A"\`!s]tI½æ0½f˜ +¹PTšÁTš0Òn¹ •p‡äÀq-@€ÌXô endstream endobj 114 0 obj <> endobj 115 0 obj <> endobj 116 0 obj <> endobj 117 0 obj <> endobj 118 0 obj <> endobj 119 0 obj <> endobj 120 0 obj <> endobj 121 0 obj <> endobj 122 0 obj <> endobj 123 0 obj <> endobj 124 0 obj <> endobj 125 0 obj <> endobj 126 0 obj <> endobj 127 0 obj <> endobj 128 0 obj <> endobj 129 0 obj <> endobj 130 0 obj <> endobj 131 0 obj <> endobj 132 0 obj <> endobj 133 0 obj <> endobj 134 0 obj <> endobj 135 0 obj <> endobj 136 0 obj <> endobj 137 0 obj <> endobj 138 0 obj <> endobj 139 0 obj <> endobj 140 0 obj <> endobj 141 0 obj <> endobj 142 0 obj <> endobj 143 0 obj <> endobj 144 0 obj <> endobj 145 0 obj <> endobj 146 0 obj <> endobj 147 0 obj <> endobj 148 0 obj <> endobj 149 0 obj <> endobj 150 0 obj <> endobj 151 0 obj <> endobj 152 0 obj <> endobj 153 0 obj <> endobj 154 0 obj <> endobj 155 0 obj <> endobj 156 0 obj <> endobj 157 0 obj <> endobj 158 0 obj <> endobj 159 0 obj <> endobj 160 0 obj <> endobj 161 0 obj <> endobj 162 0 obj <> endobj 163 0 obj <> endobj 164 0 obj <> endobj 165 0 obj <> endobj 166 0 obj <> endobj 167 0 obj <> endobj 168 0 obj <> endobj 169 0 obj <> endobj 170 0 obj <> endobj 171 0 obj <> endobj 172 0 obj <> endobj 173 0 obj <> endobj 174 0 obj <> endobj 175 0 obj <> endobj 176 0 obj <> endobj 177 0 obj <> endobj 178 0 obj <> endobj 179 0 obj <> endobj 180 0 obj <> endobj 181 0 obj <> endobj 182 0 obj <> endobj 183 0 obj <> endobj 184 0 obj <> endobj 185 0 obj <> endobj 186 0 obj <> endobj 187 0 obj <> endobj 188 0 obj <> endobj 189 0 obj <> endobj 190 0 obj <> endobj 191 0 obj <> endobj 192 0 obj <>stream + + + + + application/pdf + + + VS2010_h_c + + + + + Adobe Illustrator CS3 + 2009-03-04T14:21:57-08:00 + 2009-03-04T14:21:57-08:00 + 2009-03-04T14:21:57-08:00 + + + + 256 + 32 + JPEG + /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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 + + + + + + uuid:8CA472115A0ADE118D6EE84B58BD5EB4 + uuid:1c2d0ce0-ed76-de45-80b0-35352d7d0ef0 + + uuid:472287ec-7810-4a41-84bf-8a4190c7dbcd + uuid:5B20892493BFDB11914A8590D31508C8 + + + + Basic CMYK + Document + + + 1 + True + False + + 753.222900 + 198.807617 + Points + + + + Cyan + Magenta + Black + + + + + + Default Swatch Group + 0 + + + + White + CMYK + PROCESS + 0.000000 + 0.000000 + 0.000000 + 0.000000 + + + Black + CMYK + PROCESS + 0.000000 + 0.000000 + 0.000000 + 100.000000 + + + CMYK Red + CMYK + PROCESS + 0.000000 + 100.000000 + 100.000000 + 0.000000 + + + CMYK Yellow + CMYK + PROCESS + 0.000000 + 0.000000 + 100.000000 + 0.000000 + + + CMYK Green + CMYK + PROCESS + 100.000000 + 0.000000 + 100.000000 + 0.000000 + + + CMYK Cyan + CMYK + PROCESS + 100.000000 + 0.000000 + 0.000000 + 0.000000 + + + CMYK Blue + CMYK + PROCESS + 100.000000 + 100.000000 + 0.000000 + 0.000000 + + + CMYK Magenta + CMYK + PROCESS + 0.000000 + 100.000000 + 0.000000 + 0.000000 + + + C=15 M=100 Y=90 K=10 + CMYK + PROCESS + 14.999998 + 100.000000 + 90.000000 + 10.000002 + + + C=0 M=90 Y=85 K=0 + CMYK + PROCESS + 0.000000 + 90.000000 + 85.000000 + 0.000000 + + + C=0 M=80 Y=95 K=0 + CMYK + PROCESS + 0.000000 + 80.000000 + 95.000000 + 0.000000 + + + C=0 M=50 Y=100 K=0 + CMYK + PROCESS + 0.000000 + 50.000000 + 100.000000 + 0.000000 + + + C=0 M=35 Y=85 K=0 + CMYK + PROCESS + 0.000000 + 35.000004 + 85.000000 + 0.000000 + + + C=5 M=0 Y=90 K=0 + CMYK + PROCESS + 5.000001 + 0.000000 + 90.000000 + 0.000000 + + + C=20 M=0 Y=100 K=0 + CMYK + PROCESS + 19.999998 + 0.000000 + 100.000000 + 0.000000 + + + C=50 M=0 Y=100 K=0 + CMYK + PROCESS + 50.000000 + 0.000000 + 100.000000 + 0.000000 + + + C=75 M=0 Y=100 K=0 + CMYK + PROCESS + 75.000000 + 0.000000 + 100.000000 + 0.000000 + + + C=85 M=10 Y=100 K=10 + CMYK + PROCESS + 85.000000 + 10.000002 + 100.000000 + 10.000002 + + + C=90 M=30 Y=95 K=30 + CMYK + PROCESS + 90.000000 + 30.000002 + 95.000000 + 30.000002 + + + C=75 M=0 Y=75 K=0 + CMYK + PROCESS + 75.000000 + 0.000000 + 75.000000 + 0.000000 + + + C=80 M=10 Y=45 K=0 + CMYK + PROCESS + 80.000000 + 10.000002 + 45.000000 + 0.000000 + + + C=70 M=15 Y=0 K=0 + CMYK + PROCESS + 70.000000 + 14.999998 + 0.000000 + 0.000000 + + + C=85 M=50 Y=0 K=0 + CMYK + PROCESS + 85.000000 + 50.000000 + 0.000000 + 0.000000 + + + C=100 M=95 Y=5 K=0 + CMYK + PROCESS + 100.000000 + 95.000000 + 5.000001 + 0.000000 + + + C=100 M=100 Y=25 K=25 + CMYK + PROCESS + 100.000000 + 100.000000 + 25.000000 + 25.000000 + + + C=75 M=100 Y=0 K=0 + CMYK + PROCESS + 75.000000 + 100.000000 + 0.000000 + 0.000000 + + + C=50 M=100 Y=0 K=0 + CMYK + PROCESS + 50.000000 + 100.000000 + 0.000000 + 0.000000 + + + C=35 M=100 Y=35 K=10 + CMYK + PROCESS + 35.000004 + 100.000000 + 35.000004 + 10.000002 + + + C=10 M=100 Y=50 K=0 + CMYK + PROCESS + 10.000002 + 100.000000 + 50.000000 + 0.000000 + + + C=0 M=95 Y=20 K=0 + CMYK + PROCESS + 0.000000 + 95.000000 + 19.999998 + 0.000000 + + + C=25 M=25 Y=40 K=0 + CMYK + PROCESS + 25.000000 + 25.000000 + 39.999996 + 0.000000 + + + C=40 M=45 Y=50 K=5 + CMYK + PROCESS + 39.999996 + 45.000000 + 50.000000 + 5.000001 + + + C=50 M=50 Y=60 K=25 + CMYK + PROCESS + 50.000000 + 50.000000 + 60.000004 + 25.000000 + + + C=55 M=60 Y=65 K=40 + CMYK + PROCESS + 55.000000 + 60.000004 + 65.000000 + 39.999996 + + + C=25 M=40 Y=65 K=0 + CMYK + PROCESS + 25.000000 + 39.999996 + 65.000000 + 0.000000 + + + C=30 M=50 Y=75 K=10 + CMYK + PROCESS + 30.000002 + 50.000000 + 75.000000 + 10.000002 + + + C=35 M=60 Y=80 K=25 + CMYK + PROCESS + 35.000004 + 60.000004 + 80.000000 + 25.000000 + + + C=40 M=65 Y=90 K=35 + CMYK + PROCESS + 39.999996 + 65.000000 + 90.000000 + 35.000004 + + + C=40 M=70 Y=100 K=50 + CMYK + PROCESS + 39.999996 + 70.000000 + 100.000000 + 50.000000 + + + C=50 M=70 Y=80 K=70 + CMYK + PROCESS + 50.000000 + 70.000000 + 80.000000 + 70.000000 + + + + + + Grayscale + 1 + + + + K=100 + GRAY + PROCESS + 255 + + + K=90 + GRAY + PROCESS + 229 + + + K=80 + GRAY + PROCESS + 203 + + + K=70 + GRAY + PROCESS + 178 + + + K=60 + GRAY + PROCESS + 152 + + + K=50 + GRAY + PROCESS + 127 + + + K=40 + GRAY + PROCESS + 101 + + + K=30 + GRAY + PROCESS + 76 + + + K=20 + GRAY + PROCESS + 50 + + + K=10 + GRAY + PROCESS + 25 + + + K=5 + GRAY + PROCESS + 12 + + + + + + + + + Adobe PDF library 8.00 + + + + endstream endobj 193 0 obj [45 0 R] endobj 194 0 obj <>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>stream +H‰\”Íjã0F÷~ +-ÛEñt¥‚!IÈbÚ2™yÇV2†‰mg‘·E'´0†’üé|ä&_o_·C?«ü3ŒíÎÏêÐ]ðçñZ¯öþØYY©®oç;¥ïöÔLYï®çÙŸ¶ÃaÌ •ÿŒ‹ç9\Õò÷þ1Ë?BçC?ÕÃïõîQå»Ë4ýõ'?̪Pu­:ˆ/úÑLïÍÉ«<{Úvq½Ÿ¯OñÌ÷Ž_×É«*qÉeÚ±óç©i}h†£ÏE|jµØħÎüÐý·.šcûCû§ i»ŽÛ‹¢*êDh¨, W¨„Þ vjvV¬iÖ*“È”@d! 9È@Ï@/…–ƒVÐ3´†^ nf¸™ÆÁà ¹§ážº‚6MMhƒà q4‚ƒÆApÐ8ÁÁ`I0$X –C‚%Á`I0$X öž@K–– -YZŠ…$ZBoÐ +¢AKƒBƒ–…- + Zt4(9Œ#‡‘`ä0ŒF‚‘ÃH0r F#ÁÈa$9ŒVw#‹q…ûoþ6qvÕ×ĵ—â°¥OSv›¯~ð_ÿÓ8©xêöÉþ 0þ?þa endstream endobj 197 0 obj [40 0 R] endobj 198 0 obj <>stream +H‰\”ÍŠ£@F÷>E-»ZuoUB N ‹ùa2óF+a¢bÌ"o?OÓ#$pÐò~ço¾Ù¿ï»v2ù÷±¯q2§¶kÆxíocÍ1žÛ.+­iÚzú ù¿¾TC–§Ã‡ûuŠ—}wê³åÒä?ÒÍë4ÞÍÓºéñ9Ë¿MÛîlž~mÏ&?܆áO¼Än2…Y­LOéE_ªáku‰&Ÿ½ì›t¿î/éÌ¿'~Þ‡hìÌ%a꾉סªãXuç˜-‹t­Ìr—®U»æ¿û~Á±ã©þ]óã.=^¶XÍä!½A h½B[è ÚA›™Êz‡Jh Yh1Ý1½¨„²ÉÉÊ5 r:r–dqd±LwL·L&X&,„ 6@- …^!‘EÈbÉ"d±t&t– +™i ѠР%µÚѠРÃApp4(4èhPiÐá§ø9ü?‡ŸâçðSü~ŠŸÃOñsø)~?ÅÏá§ø ©•ÔBO!‹'‹Å“EÈâÉ"dñd²x²Y> endobj 200 0 obj <> endobj 201 0 obj <> endobj 202 0 obj <> endobj 203 0 obj <> endobj 204 0 obj <> endobj 205 0 obj <> endobj 206 0 obj <> endobj 207 0 obj <> endobj 208 0 obj <> endobj 209 0 obj <> endobj 210 0 obj <> endobj 211 0 obj <> endobj 212 0 obj <> endobj 213 0 obj <> endobj 214 0 obj <> endobj 215 0 obj <> endobj 216 0 obj [0.0] endobj 217 0 obj <>/XObject<>>>/Subtype/Form>>stream +H‰‹A +€0 ïyÅ~À˜Ö6õ¢gшzÑ +¾Þæ2#8©Á™©Sê5±†eMMäÐãÝé ‡„½FØâl¬*JÖ 'æÏÒ‹v¼ÃM3ý föb endstream endobj 218 0 obj <> endobj 219 0 obj <>/Shading<>>>/Subtype/Form>>stream +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Æçàß ûV endstream endobj 220 0 obj <> endobj 221 0 obj <> endobj 222 0 obj /DeviceCMYK endobj 223 0 obj <> endobj 224 0 obj <> endobj 225 0 obj <> endobj 226 0 obj /DeviceGray endobj 227 0 obj <> endobj 228 0 obj [0.0] endobj 229 0 obj <>/XObject<>>>/Subtype/Form>>stream +H‰<ÌA +ÂP Ðý?Å\Àt’ß6þ½èZ,xÑ®TlOo²‘À†ÇséNb^KuÑÞ1ìMª6˜J{ìÔÄÌ°ÜË£|þÈ)lžÈèæi®x…¢Ø8`CnknÓ [¦Êü߬tÇ'qx—sÜO€ <ö endstream endobj 230 0 obj <> endobj 231 0 obj <>/ExtGState<>/Shading<>>>/Subtype/Form>>stream +H‰\R»n1 ìõúÐ"Å—ZkÃEÜ»ˆ‹uÃÿd¨½8wW­f¸CŽFülj¤îÝRh,íM…&+&wës‘1Р1fŸA¬Ñ-EïoíŽ86ar!ÖØ¥²¡_ªaý}’ ø‰¤Ðšîº€\FW&ÍÜÐmB~GuN?ý +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 endstream endobj 232 0 obj <> endobj 233 0 obj <> endobj 234 0 obj [/DeviceN[/Black]/DeviceCMYK 237 0 R 238 0 R] endobj 235 0 obj <> endobj 236 0 obj <> endobj 237 0 obj <>stream +H‰ª6Ô3#C…¢üœbD 2óRR+2\ÉeE +©É +Å¥Iu¦ +ºèf (4*äË›Pi3ÒS!ªåÆ0•FŒ4‚[^_ P `.§G± endstream endobj 238 0 obj <> endobj 239 0 obj <> endobj 240 0 obj <> endobj 241 0 obj [0.0] endobj 242 0 obj <>/XObject<>>>/Subtype/Form>>stream +H‰ŒA +ƒP D÷9Å\ 1ÉÏÿè¾Øu©ÐuUKu!ôôMÌ0áñ+u·‡`=H—VQ{ã¢ÜX½ábÂî†}¦…¾ ¹jS¼À£Š!óšÌ[P1Ãt"ÝšnÁôBÄé€Jö/_;ºñ-¸~è÷`¡ù endstream endobj 243 0 obj <> endobj 244 0 obj <>/Shading<>>>/Subtype/Form>>stream +H‰\T;n1 ìu +] ´ø‘Hµ‚Ô†‹¸wëFîdÈ}ˆßÛjwf9"9äê³Ù$[«ÏÛúG3¦Á´†w òÉ}ú¦)Ñu‘ „û¢åÖßÚ…8š*IlJ6v— ØÚç + ˆ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ß> endobj 246 0 obj <> endobj 247 0 obj <> endobj 248 0 obj <> endobj 249 0 obj <> endobj 250 0 obj [0.0] endobj 251 0 obj <>/XObject<>>>/Subtype/Form>>stream +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î'À§£ endstream endobj 252 0 obj <> endobj 253 0 obj <>/Shading<>>>/Subtype/Form>>stream +H‰\’KN1 D÷9…/€Iü‰-bXÀÁŒDƒ4Ìý%ìdÓ¨ݯÔ*§"ÝÔ:VøL¡ÛAq˜A x_X)‘Mtbx-ÿ„­hÅ&id7TÏã­Ñ6¬#ì{Þ~¹;Vó,Ç.ŠÌÄj"£§{Ï[Ç¡<¹“f±®“ÔãMHíòs—¬½¢8£p A°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…óî_à±<–³å›B endstream endobj 254 0 obj <> endobj 255 0 obj <> endobj 256 0 obj <> endobj 257 0 obj <> endobj 258 0 obj <> endobj 259 0 obj <> endobj 260 0 obj [0.0] endobj 261 0 obj <>/XObject<>>>/Subtype/Form>>stream +H‰ŒÁ +Â@ DïùŠùÓdÝݬwѳ´Ð¶'ÛCÁ¯7)3ÌðÁBݽ,ieK(Ö¸eÃÑNªÜÎëD3}&g”j,ªÕKƒ3æÍ™o§„S-Ø××‚á ·Ý Ã•È_L+ºÛKpýÐÃõ`×Þ endstream endobj 262 0 obj <> endobj 263 0 obj <>/Shading<>>>/Subtype/Form>>stream +H‰d”MnÜ0 …÷:….E$%RÚ(º²höAÛõH³êíûH9íb€L¾7~üå×ÄT¦öÜm©3ß×¢ X³ešEFñÌ4J3j©6òsº[¢eëÖ ÌVZ@+*êHÃsI±ÑÜ}àVT3B 12ÐT€\¸5šŠÒtûY»1¸«ìÏO¯]g+» ¤6Vö£°y3TѺŽR¥y³cL •Ž8˜„ÙBbrÿYØ\} uÄ覗çØ,c°e’û/Âí~LÁ±Ê_"Ü^•þÀ‘}Nzçøu§)ùOºñ¼In m8¶Ó`ÒH®³äHw¢Ú‰ñÃññ²¶uÖ•Zæ^†R ÍðŸøG$rAT³T ßâè;R¸ÔÙ#:)Ã6z_Ë¡8L«­Õa§ÖxE›æö³võÓóÝœ3 #Š½$^M­¶êÅŸ¥cV=.£42}€VÕ‘%.TE{ÏéÌ0ãRè\7N2#&-ê¸`ÀZ9P[,ÉYØB Oe¸íh¾S}÷„ÍÏ¡ËJ¨˜'°Žß½`}þCøÏüàÐãkaG´óÛä¿òož>¶6ñô3ÞŽQÍ»_›­­9 +QþÕp wß×ü+Õ"X¸ã_Ê?Óý—Çš¼¥;ÂöHŽ/Æ Â&±i?ý§ù÷·ô=½&8ÜHnÄyÚdÅû­âs÷Ù°^)–Ó·QgqKŸžòýãKÍo/ùóS~Hé¯æÊž endstream endobj 264 0 obj <> endobj 265 0 obj <> endobj 266 0 obj <> endobj 267 0 obj <> endobj 268 0 obj <> endobj 269 0 obj [0.0] endobj 270 0 obj <>/XObject<>>>/Subtype/Form>>stream +H‰ŒM +ƒ` D÷9Å\ ñKüþº]K…@Ú®Ú¢.Oo"ÞËB’9¶HYøn­Â1WH`-ë‹žøQÀ‡šáaµ]¸ eÕ‹®7ÃÛ¨Ž¿i!ssÂwÄ€i†Åni³ïÞ‡O+šþÐýi´;F_ endstream endobj 271 0 obj <> endobj 272 0 obj <>/Shading<>>>/Subtype/Form>>stream +H‰\ÍjBA F÷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€€óIˆ endstream endobj 273 0 obj <> endobj 274 0 obj <> endobj 275 0 obj <> endobj 276 0 obj <> endobj 277 0 obj <> endobj 278 0 obj [0.0] endobj 279 0 obj <>/XObject<>>>/Subtype/Form>>stream +H‰ŒA +Ã@ ï~…>PÇ»‰½ë{IÎ¥> ¤9µ¥É!×w@i`¥nº Ö’q_¡E¹*gÇÅ9km¡ýb×!C͸؀Ângq âOc„³)ÄiŠSÁüD³£æI"Ϩ6tã[pýÒ­é/Àï8Ò endstream endobj 280 0 obj <> endobj 281 0 obj <>/XObject<>>>/Subtype/Form>>stream +H‰ˆÁ +€ ïûï ¶UqÓ{Ô9ú€ˆNæAèë3f`2eàUY¥G`Ùz‡g§e¶êQAÝ´ŽB‚´¡©6!ùûþëA7ž‚ᦹñ 0º‘ endstream endobj 282 0 obj <> endobj 283 0 obj <>/Shading<>>>/Subtype/Form>>stream +H‰\“ËN$1 E÷ùŠüÁÄN¶H#ֈŰG3ƒD¬øû± NµZê®s;×Øõ‘PJ×–›ré$ùm +:ÆØ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ÿyàÜ, endstream endobj 284 0 obj <> endobj 285 0 obj <> endobj 286 0 obj <> endobj 287 0 obj <> endobj 288 0 obj <> endobj 289 0 obj <> endobj 290 0 obj [0.0] endobj 291 0 obj <>/XObject<>>>/Subtype/Form>>stream +H‰‹Ë € ﯊m@xü)ÀèÙHF9#H¬^¸Ì&›F&¹îŒ\I{¡½… QX t4˜¼0F£œtÑK܇†‘¨‘0ÒŽÖT¡xì7®¹ÜŒù¡~c~V endstream endobj 292 0 obj <> endobj 293 0 obj <>/Shading<>>>/Subtype/Form>>stream +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€¢ydý endstream endobj 294 0 obj <> endobj 295 0 obj <> endobj 296 0 obj <> endobj 297 0 obj <> endobj 298 0 obj <> endobj 299 0 obj [0.0] endobj 300 0 obj <>/XObject<>>>/Subtype/Form>>stream +H‰‹1 +€0û{Å~ÀË]BíEk1?µQ Á×›kf``;¹qì…Ì)fÄ”9k5KP4žÛNq¯´ÑEÂ>E¼°Gí”oÊógé†AÒD¿yjŒ endstream endobj 301 0 obj <> endobj 302 0 obj <>/Shading<>>>/Subtype/Form>>stream +H‰\’1nÃ0 Ew‚¨"‘¢D®ŠÎA†f÷Ð N ÷J‘.jg²Þ“Iˆ_z$¹óî#32ܧ$­0¬.¨¹ í@šÑ±gÐ07ªF-+ +,é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ú`Í{‚z endstream endobj 303 0 obj <> endobj 304 0 obj <> endobj 305 0 obj <> endobj 306 0 obj <> endobj 307 0 obj <> endobj 308 0 obj [0.0] endobj 309 0 obj <>/XObject<>>>/Subtype/Form>>stream +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î'À§£ endstream endobj 310 0 obj <> endobj 311 0 obj <>/Shading<>>>/Subtype/Form>>stream +H‰\’ËjAE÷ýõ.u=»zY-⽈mÈ8 ûÿ!U=ÂÖÁÌœ‹nßzôµéÄ6»*¼•àc¦`8Ç€D ß±s!O^,piß„­YGÒ2(J H´¨ãñö™ö#oŸì}DÅIh¢¡ÈȽP0Ê}ä­ià4Yìlæ¶È"ߌL·?»VöQÈpAJA±GÖªès. ÉN iÕ¢å? +é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~íðñ +?Ÿà±=¶ÿ …û endstream endobj 312 0 obj <> endobj 313 0 obj <> endobj 314 0 obj <> endobj 315 0 obj <> endobj 316 0 obj <> endobj 317 0 obj [0.0] endobj 318 0 obj <>/XObject<>>>/Subtype/Form>>stream +H‰<ŒÁ +Â@ Dïûó¦I6ÙÝÞEÏbÁíIÅöPðëÍz70<†1§áxfÌkÊ™¬Œð¦”e„:±)vbäV±ÜÒ=½ÿR©T«@Zs„còs.x†Å¤Å±¡KÿfLW¶¦½?}Z0Œý+"_­à endstream endobj 319 0 obj <> endobj 320 0 obj <>/Shading<>>>/Subtype/Form>>stream +H‰lAj1 E÷:….Å’,ÙÚ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¨k O]sŸ™ÎÒbl$$wÁé/'Üç‚÷_Ox€ü0ïVS endstream endobj 321 0 obj <> endobj 322 0 obj <> endobj 323 0 obj <> endobj 324 0 obj <> endobj 325 0 obj <> endobj 326 0 obj [0.0] endobj 327 0 obj <>/XObject<>>>/Subtype/Form>>stream +H‰TŒÁ +ƒ0Dïûóën6‘ä^Ús1àˆõTKõ øõ&xQÞÀðÁDÍ«L+™ã"BÙ|‚SVï¡ÆÑ–‘>ô?twìâô˜‹%ìÚ€ õZëµ (Ø +W¨ÔÞë´ y~½K“Íï endstream endobj 328 0 obj <> endobj 329 0 obj <>/Shading<>>>/Subtype/Form>>stream +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ÈÊI­kIßµ›àÈêlf÷@»’|PR…ºùjù s^wM‹³©ƒ„ûè3OåTf†×0òØC¦6ÆuÈ>Û ÈaßaÁGp3Õ´ïá²ÏÀ– b¶÷óiüG(£žÊ¹üGHLI@Eäâ9åÒÑ}·ÕÝmw™¨{ÓU¼ŽüØ…”OBþ`bËè endstream endobj 330 0 obj <> endobj 331 0 obj <> endobj 332 0 obj <> endobj 333 0 obj <> endobj 334 0 obj <> endobj 335 0 obj <> endobj 336 0 obj <> endobj 337 0 obj <> endobj 338 0 obj <> endobj 339 0 obj <> endobj xref 0 1 0000000000 65535 f +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 <<8710EA5F576C4886B943D8D96EC67FE1>]/Prev 89924>> startxref 258944 %%EOF +342 0 obj +<>/T(Signature1)/Subtype/Widget/Rect[0 0 0 0]/FT/Sig/P 59 0 R/AP<>>> +endobj +340 0 obj +</ByteRange [0 265190 285672 47313 ] /SubFilter/ETSI.CAdES.detached/Filter/Adobe.PPKLite/M(D:20130409143422+02'00')>> +endobj +343 0 obj +<> +endobj +344 0 obj +<> +endobj +341 0 obj +<>/Filter/FlateDecode/Length 8/Matrix [1 0 0 1 0 0]>>stream +xœ +endstream +endobj +2 0 obj +<>stream + + + + + uuid:7e7b597d-426f-3642-8dca-bcbf37236e1d + xmp.did:89321C534E266811A613EDAC20FB34D2 + adobe:docid:indd:924fbc79-cadb-11de-af61-e97e2740acd1 + proof:pdf + + xmp.iid:88321C534E266811A613EDAC20FB34D2 + adobe:docid:indd:924fbc79-cadb-11de-af61-e97e2740acd1 + adobe:docid:indd:924fbc79-cadb-11de-af61-e97e2740acd1 + default + + + + + saved + xmp.iid:E4B6ED806F256811A613EDAC20FB34D2 + 2010-06-27T11:39:47-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:E5B6ED806F256811A613EDAC20FB34D2 + 2010-06-27T11:39:47-07:00 + Adobe InDesign 6.0 + /metadata + + + saved + xmp.iid:E6B6ED806F256811A613EDAC20FB34D2 + 2010-06-27T11:44:22-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:80321C534E266811A613EDAC20FB34D2 + 2010-06-27T11:46:03-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:81321C534E266811A613EDAC20FB34D2 + 2010-06-27T11:48-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:82321C534E266811A613EDAC20FB34D2 + 2010-06-27T11:49:01-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:83321C534E266811A613EDAC20FB34D2 + 2010-06-27T11:52:39-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:84321C534E266811A613EDAC20FB34D2 + 2010-06-27T11:58:06-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:85321C534E266811A613EDAC20FB34D2 + 2010-06-27T11:59:50-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:88321C534E266811A613EDAC20FB34D2 + 2010-06-27T12:03:27-07:00 + Adobe InDesign 6.0 + /metadata + + + saved + xmp.iid:89321C534E266811A613EDAC20FB34D2 + 2010-06-27T12:03:27-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:4A27385D5F266811A613EDAC20FB34D2 + 2010-06-27T13:48:01-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:4B27385D5F266811A613EDAC20FB34D2 + 2010-06-27T13:50:54-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:4C27385D5F266811A613EDAC20FB34D2 + 2010-06-27T13:54-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:4D27385D5F266811A613EDAC20FB34D2 + 2010-06-27T13:55:16-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:4E27385D5F266811A613EDAC20FB34D2 + 2010-06-27T13:56:27-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:4F27385D5F266811A613EDAC20FB34D2 + 2010-06-27T13:58:44-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:5027385D5F266811A613EDAC20FB34D2 + 2010-06-27T14:05:30-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:5127385D5F266811A613EDAC20FB34D2 + 2010-06-27T14:07:25-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:5227385D5F266811A613EDAC20FB34D2 + 2010-06-27T14:12:43-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:5327385D5F266811A613EDAC20FB34D2 + 2010-06-27T14:13:56-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:5427385D5F266811A613EDAC20FB34D2 + 2010-06-27T14:16:22-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:DE855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:19:25-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:DF855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:27:07-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:E0855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:29:58-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:E1855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:32:34-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:E2855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:33:46-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:E3855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:40:42-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:E4855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:41:28-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:E5855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:42:42-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:E6855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:44:36-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:E7855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:47:08-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:E8855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:51:29-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:80C8B5F5A22068119109D8C24D4F5870 + 2010-06-29T10:49:23-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:81C8B5F5A22068119109D8C24D4F5870 + 2010-06-29T10:50:43-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:82C8B5F5A22068119109D8C24D4F5870 + 2010-06-29T10:52:12-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:00CECC59A92068119109D8C24D4F5870 + 2010-06-29T10:53:23-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:01CECC59A92068119109D8C24D4F5870 + 2010-06-29T10:53:56-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:02CECC59A92068119109D8C24D4F5870 + 2010-06-29T10:56:41-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:03CECC59A92068119109D8C24D4F5870 + 2010-06-29T11:03:21-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:04CECC59A92068119109D8C24D4F5870 + 2010-06-29T11:06:47-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:05CECC59A92068119109D8C24D4F5870 + 2010-06-29T11:09:26-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:06CECC59A92068119109D8C24D4F5870 + 2010-06-29T11:11:53-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:07CECC59A92068119109D8C24D4F5870 + 2010-06-29T11:13:29-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:999093B2AD2068119109D8C24D4F5870 + 2010-06-29T14:21:34-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:9A9093B2AD2068119109D8C24D4F5870 + 2010-06-29T14:27:38-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:9B9093B2AD2068119109D8C24D4F5870 + 2010-06-29T14:30:31-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:371C0BE61C2368119109D8C24D4F5870 + 2010-07-02T14:20:55-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:381C0BE61C2368119109D8C24D4F5870 + 2010-07-02T14:26:33-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:391C0BE61C2368119109D8C24D4F5870 + 2010-07-02T14:29:07-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:3A1C0BE61C2368119109D8C24D4F5870 + 2010-07-02T14:31:19-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:7A0142B9242368119109D8C24D4F5870 + 2010-07-02T14:41:33-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:7B0142B9242368119109D8C24D4F5870 + 2010-07-02T14:44:10-07:00 + Adobe InDesign 6.0 + / + + + + + + + ReferenceStream + 72.00 + 72.00 + Inches + + uuid:288c3c69-7dd6-7c4f-984d-b085b3307748 + uuid:93F9F49755C5DE1185BCB9A8461E73D9 + + + + + + + 2010-07-02T15:32:26-07:00 + 2013-04-09T14:34:22+02:00 + 2013-04-09T14:34:22+02:00 + Adobe InDesign CS4 (6.0.5) + + + + JPEG + 256 + 256 + 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 +xV2KuxV2KpL5z/5Q/Xv+2bef8mJMVf/Z + + + + + + 244 + + + application/pdf + + + Adobe PDF Library 9.0; modified using iTextSharp 4.1.6 by 1T3XT + False + + + +endstream +endobj +59 0 obj +<>/Shading<>/ExtGState<>/ProcSet[/PDF/Text]/ColorSpace<>/Properties<>>>/XObject<>>>/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 +<> +endobj +1 0 obj +<>>>>>/ViewerPreferences<>>> +endobj +55 0 obj +<> +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 +<]/Info 55 0 R/Prev 258944/Root 1 0 R>> +startxref +332586 +%%EOF + +345 0 obj +<>stream +xœÝUkPWÍn6BTŠøXn|ð +¨ˆA!D| é’D’¨¥$ƒ´>bŽÔt@E«V-"¢ Q”G´ø„ZZ@™±T­õ5t”Ñ©ñwÿìÞsî9÷ÞýîùfÁ^ Ô…2 Á0‘Bh€Auð.\RøœAŽq•,@¨Î0?–ã ÆÀŽN‹Ô`:™VeaïH%ÓÊ6 [Ë挮éHgFp#X ˆåˆg,p"&Èt{n:lSÆ38þ püýÿŒÂ¹k3L1MÙ"*z%ª“huh ÊBWð£QËãVó><ëÛPœ™1Q\~,Ê_<Ç?( Ï÷?¢Èȉ„ó4ØA¤M[Ÿ÷T¼´%íì=x8¡ùþÑ ŒÒá¾iW‹Ë=²n2å.Ÿ%.àåM¬èÌMsð¤%ßÜêÎnG±Ú?´ŠXŠ)‘=Á¹E¦rʽ.Þe[Û˜€ýÂýU¶Ó'=Z:L7݈ýþÌL÷U­5û•žŸîC&š"jÅŒ{©Â_ÚòO5¼á‡fTx_;ŒÊÜÝ8©‘Óºv;£8Útx-Ķj¯s^8¸ÅæH o"쌓ñ ŸÌDÜ—G¤†g`Ù^²qs뤕3ër¯äm ú=ÄütD¿èù.®_ …ö2ïKj²õe|¯Ü(Ü÷f”ª@ú'„Þ #¡wÃ4*±2M•äª%"¥J«ÃA¦s˜€>Ò~Ldô +Ž+pI1=Ï~\¤å' ˜ôtX8Ù‚†I &0Š ?øà-ÃðÑO1™ ($ ïUœt£2 j×ï4œ!Ad‚ƒxW:róúXÑ…jñz?‘ZHTŽþÚ¨úzº¾6Q¢Ô©Py¦­—ÉUY˜ÒV‹å& ÍªCÓ$hVŽx˜Î²Õ*2/•T‰ w$.É$¨­æ¢Q¢ÈA1T~±Ž*\‰ªmV/¡”ëT§ªïVÂiIº­²±N‚¦æ4DÕªÌÆ:™árµJ¬¶Uh1%¾²Zc³fáûåâ/[i.nIQ±Jž™N; (‰ÊME6 àXü,¬Ñ}${Åû Â!¶Å·Ðû?C÷o“Øω¸9„ Sëçh»7àì©T„´}Ž ¿J¥øxÙ“í‘ÿAÁ?üc 0D2ßK +{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Šë°Ú»£ª½%~õõuÎ +endstream +endobj +346 0 obj +<>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†‚ü‡pÝÖ`ÐĤ„ Œ¬ ÌMLüÀpbâbjbbdØÇÊT¤³}鱈kn ù _*ûnÓû"<©ÀcÑ ÝgU O§ül˲ŒŒÿY8 Ø€#£A0HL$æiànàÊÆ«Ý(7qf +0›˜±qh³1²²²31Š©e””Xéë§èå%•égëg''ê§ä'ƒèøä‚b½‚”4'¡Š,Ö–âh&²±±0t-–C—@³”ÖeU@c5`n`¦iF˜SYš€"zö01¦6cÎKN-*)±ŒAXÊ8¾À™Å%Í ÔµÕ Â|\! +Y>1ÑúøxŽL­cÌ 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‹ÈÕœ ×ïqE­7kÛhà "–d +endstream +endobj +347 0 obj +<>stream +xœ3hâè4hb+\ÀÌÄÈÄÄÈhÀËÆ©ÕæÑö—‘‘›•Á ×Û€“9”…M˜)ØÛPØ@Äaçár*J,É,ÎI,K4T2P rñHú%å§äU*$¥V¤&çå—9¥E‰)†|< 5Ü<¬ÁžN®†¢ >3·³£‚ŸS¨Bp‚±œ8¯¥¡¡™¥©¥±e”8¯‘)˜kndi`Eoç41)!#+s?Pœ‹©‰‰‘áöª ýú^Ó…®î|]y§9¦ÛPüÓÓ¼¸s:—ŽªßIµ¹ïÃuVÅé—¦ð†xn”×~ûÄ`NoÂä"1}>I®íûþן”8ùÄAðldúæ¿–þçGÜîn~º[yg»û³3ÚJb8þ ½QžV·;y¥îfïS?dòSn(íZ>åàÕÏýÍ"ëwÝŽ‰Õ TÞÉ##ª”1ýÀŽ†Ìôï ;Š v<2¼V;Uh/ï{íÙb'ÕËnèN­w]õWNhbÂÇ9}ÛôÞõ:½Žšþ¤IaÅMƒ«®´m\8/ÆÉxÈÂDéÌejÇû²»OÄHÎú¡œÿîøCÑC÷f7íŒßÊôÒR°l­ CÙÝk5ßG2ÛœÖñsÈ^ñðzôuoܳӦœxDeòe—oMþ›Ü2ùÃ’ò+o—7'…7éŠl¿êë·ðyÿ‰†{b<ÍÖ78­Ÿ«zÌóš’·6/ñá‰ûû +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_’ÝɈ€¥…| ”ÉJ¬,ÀÊ„Í@Äçcc©ÿh«xhz”Þtv¾™ÍªÛìØÑ*fPqjvû§ÐËT§M‹wv¾«¾)W”Ÿ¿`ƒú¡E¯ºæ‰ Èn›u‚aG×é ÞqF÷¶NþàÚt#<ë}<;Ã_Îêí«Yoý?ÿ¤…tpØTw·ÿì:—ó25¯ïOuž²'æå­ƒú•¯7…™”õvŠîˆ¹\¹EhCûG¶¾ÐÍá[væ²e^9»$ÁXF)¢+#÷îóÝÁ·£Âø›t+ËY"=™ßsÅT&ìjûüîeÖµ3´mB﮳:÷.ìhÌ<õÊ©/~»n9W<ÑÐì÷‚­z_Êü ?îfyîlŽÁœ™Êa3f¹½mebWd­Ü°ö?Ûê?_ú%'4 9ó÷†ñÙã9f?J\3¥ï-Ú»5j¡ºÚ¶ ­ö _è̺zo²pÛ4¾g_KXèǘN[u O{¾}{[ãÎ4-qãX‘‰*êN®Ç^K;¼±Îó˜83tó®Y¢sþ[`éŽBKu-][C÷Ó£v.X½5ì1Ÿæ¦™î[سٞ«.Ÿ fü= *‘=*oo©XŒ’ÖŽsËðÂ{¬Ü¿¬Œ>Ÿµû*vΣ%üŽÂçìÍ۔̖D‰¶ó}:x#˦B±7E`Ç^_÷9Ûžvßð¸e6ßO­ìôÍÖC¡/×æ_¾’xÍíëJù Ox7œŠøµð÷ñh½yïx·3IÎ¼à•’÷ËÀÆøRBSšÐ¢×¶WYW>y8½Âm^Ä”ÉÇÞ\ìYuBÍ>¥ +endstream +endobj +348 0 obj +<>stream +xœZytVU’'!„ì!!_"ä#$Iî[¿÷Â’¢jkp1Y„°m1(vÒí2²(qDpnfB«´؃6¶}T8è8Ž Ú. b7ÂTÝ[·îëùgÆãÉ!¿ï澺U¿úUÕ}Ÿè>HtUg&'%‰ìÔôê5W¯ù>;))³W1ÃÊé©='¥¤öMn`õyøK﬌æ¥íËævÎo¿­]ƒYcçvν5Þ^ÛYk‰‚™Y9Mcšj‘¨±þ°òD.~Ð3+mLS\þAQ¶åˆPXžSéW›~]U7ŠXrJR^Éð‘€u®Ÿ8ÖT‚[%ìضåÂ8þG„Ⴤ½À4|§\m[!ü„‡jø ‚-Ë–Í›œS´m¸žËðê‘"°„m»Á©Yj°Ížj8O­†GÚVÂÀ%Ò@x åx¾Ãpœa×sNêuNX.߶} ßÀ‡wEdõd vÂr¬„Í{O§M|p”cñ&³è”àp¹öIê {`¤ëZæ”ËÙÀÀM˜MÖOÀãŽïò#תG‚%– +†5>²¿ÿ9Û‚ùXv[Ã/D`ÏbǾFv[–o{ƱG%ì£cmÛÀ§ˆ!° +œ¥á/4 ܵï}& +ÛÚß½ÇjBl丂'H8„½×ØÝûz²Âàú–öwﻉƒ¡åypz ¯¡ãð¶Ã«©ã »ÝÐÑö~'âßÓÑéý%ï-`½Þ;­ˆéã9‚›VB« oVW‘ÁnÏeÓê%ìÚà&;²I‹N):@ #xåyŽCÚÚÓè¦ák,3-ðttÒnT0Ð8p '4ÜM>qáŒ.Ó>m/mâƒÿBW»*í#­†€S*í?I}ÀrÇrù‘ŸŒž ,0e&½@=ÙàXœ éóÔ&øD$8 éÿ‰Nà0ü–Éb+ô´cÓÿ(iàZi»ÓÏ‘« –¶Ë)•š½! z“Œ–ls2TÎ{6FÇægÌ6°gq’dÌ1°k{šƒs l%8òó l»,Jk)òptð"[òåèrEÕOÀ«>øQ[’™C!ËÓ«3[#§t˜>™K"p‚s'óV{Ð5¶;ó9≋ŠÅ‘ÏÜϹþ³µÝ™ï)K°ÌÐð#¿R‡‡€Sœó™—é”ÒŽNV2W’è²Þ$+4´·-G[’Õ¤Äq•Êº1rÊõ$‹ÕëŽÅ«gÒ#¡6¸S3k%7èf§†×F²A05³6±Ý˜V¼z?©=ÐN©›õgEdÈKR“W_”°ƒyé"g÷¢G†ð¡Ëå(»ÔÈŒ0c³«8Ó| 8Ãq««àèdOÔéŠåœ ÌžOz„©Ò>É^Ä0h,36ûm%(3àv¶û(M–Q.GÙR«ÜÚãgŸ¡äDIŸ2§€`HnÈ4½:'Æêã€VéSæÔ‘š!·D9·%ŠŒÅ«—jX•`sžŒF‡“$çyÕC ƒàš–³—© !búä"ŸxX\†ójè|\íÁÜd½ÿg²å–éæ°ÚçV«~a¤ç“´‡ŒWüÈÜJðwDOro›`rƒ¨›½'Su A¦C–™\’0MÄAÃDÐ3ê“û3â7®6z’Û­ó*±m3ü¼¡|ÆÇ9¬²¨é{!·[¹ÿ!›‘™Ü?Oàðào>Ήhm`VåžT«¡ê„ŽêÜoiïp6²ÉwØ´D}’È'hu‚ÃÐg·[H8ýÈ>w(úXèt‡ßç0奋ŒåšÖçk‚ò”:–yƒTÐ0lŽaU^%ÑÞÁ*Å ˜WC0è·°(å ÒAÈKÏ6ð ¢=ônÂ<òH÷8ÄyoªVÞs|ÖÁ¼w"pÈŠœwBÙDvN©¼ï!0½Ñz‚ó} EdÖïü²›—…#2Áó®9eþ + +@Ð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Ó‰l 3Çæ5]l x\ŽÍ§ÕïP¾^§‰Œsš×,»öwl#ÃXdØ@¥ƒ!V7ä^3ö +©=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¥ ¨ÚÀÒ_ …ß–b/´%¥‡iê´%¥'Õ#Á`=¯¾"!7OC^š”ºâ!Kéo—»Çþ=)ò81†\¥ú/Q% Ä|Ðìÿ¸‚±÷Ýuúÿ+Ë#ÞüèMô¢Õl-tî h†òæÌÈ〵êðØ)A20¼³ˆG'Á„ð"Á(yÀ+ÔkbÃêKŽêÕÈc®iTsæË"°OÊú)ygAMãv«¬”²ANvìزT]]Y´«Ê–Œ•ÞÌ®e·ò‡÷ÞDôÁ¦Ò4~eݺ+ÀöžÇ 2ÊZ¢‰\vŽz6€,añ|î¿ñNIï´úï=w5 O9¥âwÑ&X.ºñ_ŒJ²cã›L#â +Ö“ø«ä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©M qbdÚ}R¯†^Ó\þW§ÊÃûHdÇã9­ZUÉ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%6­sÍ4ŒWd¼Im/uJ•ÉœRµ±œàêZ;|JŽk»k7H8Pïx8 µ/ª^S¾F¶¹M¬=fl]š~$Í\ðÔëäÆL曜º¼;%Þ¤Š`[Ç»'ÛÜCx{(:X]VMïuã؈<úB^¾ÇÀZ¯áQd SGÇOŽ…VÛñ9–þVò Þ˜FÄ?'=ˆs«¹ +RŠôädæL Rå&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Ø–>stream +xœ3hbæ5hüÆÄÈhÀËÆ©ÕæÑö—‘‘›•Á ×Û€“9”…M˜)ØÛPØ@Äaçár*J,É,ÎI,K4T2P rñHú%å§äU*$¥V¤&çå—9¥E‰)†|< 5Ü<¬ÁžN®†¢ >3·³£‚ŸS¨Bp‚±8¯¡±¥™¡‰©‰E”kå((211 +… Œ , 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•ÿ˜™íÑý¶5 Lî0º.çÃÊâܤ,ºþ«BŠžÅ¦MéOò¾cú²Ê¡ÐwþݵÓάÎÎþºŸ#4®,ôËòM~…]۾ؕîx1³Õ›÷ÆLëÇwwZñ½MM¡ë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=¹5F9› +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 +<> +endobj +353 0 obj +<> +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 +<> +endobj +2 0 obj +<>stream + + + + + uuid:7e7b597d-426f-3642-8dca-bcbf37236e1d + xmp.did:89321C534E266811A613EDAC20FB34D2 + adobe:docid:indd:924fbc79-cadb-11de-af61-e97e2740acd1 + proof:pdf + + xmp.iid:88321C534E266811A613EDAC20FB34D2 + adobe:docid:indd:924fbc79-cadb-11de-af61-e97e2740acd1 + adobe:docid:indd:924fbc79-cadb-11de-af61-e97e2740acd1 + default + + + + + saved + xmp.iid:E4B6ED806F256811A613EDAC20FB34D2 + 2010-06-27T11:39:47-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:E5B6ED806F256811A613EDAC20FB34D2 + 2010-06-27T11:39:47-07:00 + Adobe InDesign 6.0 + /metadata + + + saved + xmp.iid:E6B6ED806F256811A613EDAC20FB34D2 + 2010-06-27T11:44:22-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:80321C534E266811A613EDAC20FB34D2 + 2010-06-27T11:46:03-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:81321C534E266811A613EDAC20FB34D2 + 2010-06-27T11:48-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:82321C534E266811A613EDAC20FB34D2 + 2010-06-27T11:49:01-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:83321C534E266811A613EDAC20FB34D2 + 2010-06-27T11:52:39-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:84321C534E266811A613EDAC20FB34D2 + 2010-06-27T11:58:06-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:85321C534E266811A613EDAC20FB34D2 + 2010-06-27T11:59:50-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:88321C534E266811A613EDAC20FB34D2 + 2010-06-27T12:03:27-07:00 + Adobe InDesign 6.0 + /metadata + + + saved + xmp.iid:89321C534E266811A613EDAC20FB34D2 + 2010-06-27T12:03:27-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:4A27385D5F266811A613EDAC20FB34D2 + 2010-06-27T13:48:01-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:4B27385D5F266811A613EDAC20FB34D2 + 2010-06-27T13:50:54-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:4C27385D5F266811A613EDAC20FB34D2 + 2010-06-27T13:54-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:4D27385D5F266811A613EDAC20FB34D2 + 2010-06-27T13:55:16-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:4E27385D5F266811A613EDAC20FB34D2 + 2010-06-27T13:56:27-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:4F27385D5F266811A613EDAC20FB34D2 + 2010-06-27T13:58:44-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:5027385D5F266811A613EDAC20FB34D2 + 2010-06-27T14:05:30-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:5127385D5F266811A613EDAC20FB34D2 + 2010-06-27T14:07:25-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:5227385D5F266811A613EDAC20FB34D2 + 2010-06-27T14:12:43-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:5327385D5F266811A613EDAC20FB34D2 + 2010-06-27T14:13:56-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:5427385D5F266811A613EDAC20FB34D2 + 2010-06-27T14:16:22-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:DE855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:19:25-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:DF855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:27:07-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:E0855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:29:58-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:E1855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:32:34-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:E2855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:33:46-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:E3855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:40:42-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:E4855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:41:28-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:E5855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:42:42-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:E6855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:44:36-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:E7855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:47:08-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:E8855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:51:29-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:80C8B5F5A22068119109D8C24D4F5870 + 2010-06-29T10:49:23-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:81C8B5F5A22068119109D8C24D4F5870 + 2010-06-29T10:50:43-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:82C8B5F5A22068119109D8C24D4F5870 + 2010-06-29T10:52:12-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:00CECC59A92068119109D8C24D4F5870 + 2010-06-29T10:53:23-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:01CECC59A92068119109D8C24D4F5870 + 2010-06-29T10:53:56-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:02CECC59A92068119109D8C24D4F5870 + 2010-06-29T10:56:41-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:03CECC59A92068119109D8C24D4F5870 + 2010-06-29T11:03:21-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:04CECC59A92068119109D8C24D4F5870 + 2010-06-29T11:06:47-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:05CECC59A92068119109D8C24D4F5870 + 2010-06-29T11:09:26-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:06CECC59A92068119109D8C24D4F5870 + 2010-06-29T11:11:53-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:07CECC59A92068119109D8C24D4F5870 + 2010-06-29T11:13:29-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:999093B2AD2068119109D8C24D4F5870 + 2010-06-29T14:21:34-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:9A9093B2AD2068119109D8C24D4F5870 + 2010-06-29T14:27:38-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:9B9093B2AD2068119109D8C24D4F5870 + 2010-06-29T14:30:31-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:371C0BE61C2368119109D8C24D4F5870 + 2010-07-02T14:20:55-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:381C0BE61C2368119109D8C24D4F5870 + 2010-07-02T14:26:33-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:391C0BE61C2368119109D8C24D4F5870 + 2010-07-02T14:29:07-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:3A1C0BE61C2368119109D8C24D4F5870 + 2010-07-02T14:31:19-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:7A0142B9242368119109D8C24D4F5870 + 2010-07-02T14:41:33-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:7B0142B9242368119109D8C24D4F5870 + 2010-07-02T14:44:10-07:00 + Adobe InDesign 6.0 + / + + + + + + + ReferenceStream + 72.00 + 72.00 + Inches + + uuid:288c3c69-7dd6-7c4f-984d-b085b3307748 + uuid:93F9F49755C5DE1185BCB9A8461E73D9 + + + + + + + 2010-07-02T15:32:26-07:00 + 2013-09-06T16:23:05+02:00 + 2013-09-06T16:23:05+02:00 + Adobe InDesign CS4 (6.0.5) + + + + JPEG + 256 + 256 + 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 +xV2KuxV2KpL5z/5Q/Xv+2bef8mJMVf/Z + + + + + + 244 + + + application/pdf + + + Adobe PDF Library 9.0; modified using iTextSharp 4.1.6 by 1T3XT + False + + + +endstream +endobj +3 0 obj +<> +endobj +1 0 obj +<>>>>>/ViewerPreferences<>/Metadata 2 0 R>> +endobj +55 0 obj +<> +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 +<]/Info 55 0 R/Prev 332586/Root 1 0 R>> +startxref +389780 +%%EOF + +359 0 obj +<>/T(Signature2)/Subtype/Widget/Rect[0 0 0 0]/FT/Sig/P 59 0 R/AP<>>> +endobj +357 0 obj +<>> +endobj +358 0 obj +<>/Filter/FlateDecode/Length 8/Matrix [1 0 0 1 0 0]>>stream +xœ +endstream +endobj +2 0 obj +<>stream + + + + + uuid:7e7b597d-426f-3642-8dca-bcbf37236e1d + xmp.did:89321C534E266811A613EDAC20FB34D2 + adobe:docid:indd:924fbc79-cadb-11de-af61-e97e2740acd1 + proof:pdf + + xmp.iid:88321C534E266811A613EDAC20FB34D2 + adobe:docid:indd:924fbc79-cadb-11de-af61-e97e2740acd1 + adobe:docid:indd:924fbc79-cadb-11de-af61-e97e2740acd1 + default + + + + + saved + xmp.iid:E4B6ED806F256811A613EDAC20FB34D2 + 2010-06-27T11:39:47-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:E5B6ED806F256811A613EDAC20FB34D2 + 2010-06-27T11:39:47-07:00 + Adobe InDesign 6.0 + /metadata + + + saved + xmp.iid:E6B6ED806F256811A613EDAC20FB34D2 + 2010-06-27T11:44:22-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:80321C534E266811A613EDAC20FB34D2 + 2010-06-27T11:46:03-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:81321C534E266811A613EDAC20FB34D2 + 2010-06-27T11:48-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:82321C534E266811A613EDAC20FB34D2 + 2010-06-27T11:49:01-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:83321C534E266811A613EDAC20FB34D2 + 2010-06-27T11:52:39-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:84321C534E266811A613EDAC20FB34D2 + 2010-06-27T11:58:06-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:85321C534E266811A613EDAC20FB34D2 + 2010-06-27T11:59:50-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:88321C534E266811A613EDAC20FB34D2 + 2010-06-27T12:03:27-07:00 + Adobe InDesign 6.0 + /metadata + + + saved + xmp.iid:89321C534E266811A613EDAC20FB34D2 + 2010-06-27T12:03:27-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:4A27385D5F266811A613EDAC20FB34D2 + 2010-06-27T13:48:01-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:4B27385D5F266811A613EDAC20FB34D2 + 2010-06-27T13:50:54-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:4C27385D5F266811A613EDAC20FB34D2 + 2010-06-27T13:54-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:4D27385D5F266811A613EDAC20FB34D2 + 2010-06-27T13:55:16-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:4E27385D5F266811A613EDAC20FB34D2 + 2010-06-27T13:56:27-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:4F27385D5F266811A613EDAC20FB34D2 + 2010-06-27T13:58:44-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:5027385D5F266811A613EDAC20FB34D2 + 2010-06-27T14:05:30-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:5127385D5F266811A613EDAC20FB34D2 + 2010-06-27T14:07:25-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:5227385D5F266811A613EDAC20FB34D2 + 2010-06-27T14:12:43-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:5327385D5F266811A613EDAC20FB34D2 + 2010-06-27T14:13:56-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:5427385D5F266811A613EDAC20FB34D2 + 2010-06-27T14:16:22-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:DE855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:19:25-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:DF855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:27:07-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:E0855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:29:58-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:E1855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:32:34-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:E2855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:33:46-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:E3855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:40:42-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:E4855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:41:28-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:E5855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:42:42-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:E6855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:44:36-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:E7855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:47:08-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:E8855BC063266811A613EDAC20FB34D2 + 2010-06-27T14:51:29-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:80C8B5F5A22068119109D8C24D4F5870 + 2010-06-29T10:49:23-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:81C8B5F5A22068119109D8C24D4F5870 + 2010-06-29T10:50:43-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:82C8B5F5A22068119109D8C24D4F5870 + 2010-06-29T10:52:12-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:00CECC59A92068119109D8C24D4F5870 + 2010-06-29T10:53:23-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:01CECC59A92068119109D8C24D4F5870 + 2010-06-29T10:53:56-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:02CECC59A92068119109D8C24D4F5870 + 2010-06-29T10:56:41-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:03CECC59A92068119109D8C24D4F5870 + 2010-06-29T11:03:21-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:04CECC59A92068119109D8C24D4F5870 + 2010-06-29T11:06:47-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:05CECC59A92068119109D8C24D4F5870 + 2010-06-29T11:09:26-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:06CECC59A92068119109D8C24D4F5870 + 2010-06-29T11:11:53-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:07CECC59A92068119109D8C24D4F5870 + 2010-06-29T11:13:29-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:999093B2AD2068119109D8C24D4F5870 + 2010-06-29T14:21:34-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:9A9093B2AD2068119109D8C24D4F5870 + 2010-06-29T14:27:38-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:9B9093B2AD2068119109D8C24D4F5870 + 2010-06-29T14:30:31-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:371C0BE61C2368119109D8C24D4F5870 + 2010-07-02T14:20:55-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:381C0BE61C2368119109D8C24D4F5870 + 2010-07-02T14:26:33-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:391C0BE61C2368119109D8C24D4F5870 + 2010-07-02T14:29:07-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:3A1C0BE61C2368119109D8C24D4F5870 + 2010-07-02T14:31:19-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:7A0142B9242368119109D8C24D4F5870 + 2010-07-02T14:41:33-07:00 + Adobe InDesign 6.0 + / + + + saved + xmp.iid:7B0142B9242368119109D8C24D4F5870 + 2010-07-02T14:44:10-07:00 + Adobe InDesign 6.0 + / + + + + + + + ReferenceStream + 72.00 + 72.00 + Inches + + uuid:288c3c69-7dd6-7c4f-984d-b085b3307748 + uuid:93F9F49755C5DE1185BCB9A8461E73D9 + + + + + + + 2010-07-02T15:32:26-07:00 + 2013-09-06T16:23:05+02:00 + 2013-09-06T16:23:05+02:00 + Adobe InDesign CS4 (6.0.5) + + + + JPEG + 256 + 256 + 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 +xV2KuxV2KpL5z/5Q/Xv+2bef8mJMVf/Z + + + + + + 244 + + + application/pdf + + + Adobe PDF Library 9.0; modified using iTextSharp 4.1.6 by 1T3XT + False + + + +endstream +endobj +59 0 obj +<>/ExtGState<>/Shading<>/ProcSet[/PDF/Text]/ColorSpace<>/Properties<>>>/XObject<>>>/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 +<> +endobj +1 0 obj +<>>>>>/ViewerPreferences<>/Metadata 2 0 R>> +endobj +55 0 obj +<> +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 +<<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 new file mode 100644 index 0000000000..cd87f71ecf Binary files /dev/null and b/xmlsecurity/qa/unit/pdfsigning/data/dict-bool.pdf differ diff --git a/xmlsecurity/qa/unit/pdfsigning/data/forcepoint16.pdf b/xmlsecurity/qa/unit/pdfsigning/data/forcepoint16.pdf new file mode 100644 index 0000000000..9edccb47f4 Binary files /dev/null and b/xmlsecurity/qa/unit/pdfsigning/data/forcepoint16.pdf differ diff --git a/xmlsecurity/qa/unit/pdfsigning/data/good-custom-magic.pdf b/xmlsecurity/qa/unit/pdfsigning/data/good-custom-magic.pdf new file mode 100644 index 0000000000..2c532cbf6a Binary files /dev/null and b/xmlsecurity/qa/unit/pdfsigning/data/good-custom-magic.pdf differ diff --git a/xmlsecurity/qa/unit/pdfsigning/data/good-non-detached.pdf b/xmlsecurity/qa/unit/pdfsigning/data/good-non-detached.pdf new file mode 100644 index 0000000000..8e5b215115 Binary files /dev/null and b/xmlsecurity/qa/unit/pdfsigning/data/good-non-detached.pdf differ diff --git a/xmlsecurity/qa/unit/pdfsigning/data/good-pades.pdf b/xmlsecurity/qa/unit/pdfsigning/data/good-pades.pdf new file mode 100644 index 0000000000..987169eeee Binary files /dev/null and b/xmlsecurity/qa/unit/pdfsigning/data/good-pades.pdf differ diff --git a/xmlsecurity/qa/unit/pdfsigning/data/good.pdf b/xmlsecurity/qa/unit/pdfsigning/data/good.pdf new file mode 100644 index 0000000000..f28566442d Binary files /dev/null and b/xmlsecurity/qa/unit/pdfsigning/data/good.pdf differ diff --git a/xmlsecurity/qa/unit/pdfsigning/data/name-bracket.pdf b/xmlsecurity/qa/unit/pdfsigning/data/name-bracket.pdf new file mode 100644 index 0000000000..ac152793c1 --- /dev/null +++ b/xmlsecurity/qa/unit/pdfsigning/data/name-bracket.pdf @@ -0,0 +1,2241 @@ +%PDF-1.7 +%öäüß +1 0 obj +<< +/Metadata 2 0 R +/Outlines 3 0 R +/OutputIntents [4 0 R] +/PageLabels 5 0 R +/Pages 6 0 R +/Type /Catalog +/Extensions << +/ESIC << +/BaseVersion /1.7 +/ExtensionLevel 2 +>> +/LTUd << +/BaseVersion /1.7 +/ExtensionLevel 1 +>> +>> +>> +endobj +7 0 obj +<< +/Author (Petras) +/CreationDate (D:20120616164408+03'00') +/Creator (PScript5.dll Version 5.2.2) +/ModDate (D:20120616164534+03'00') +/Producer (Acrobat Distiller 10.1.3 \(Windows\)) +/Title (Untitled - Notepad) +>> +endobj +2 0 obj +<< +/Type /Metadata +/Subtype /XML +/Length 8 0 R +>> +stream + + + + + + + + PDF-LT-V1.0 elektroninio dokumento metaduomenų plÄ—tinio schema + http://archyvai.lt/pdf-ltud/2011/metadata/ + LTUd + + + + standardVersion + closed Choice of Text + internal + Elektroninio dokumento specifikacijos identifikatorius (pvz., PDF-LT-V1.0) + + + authors + seq Entity + external + Dokumento sudarytojas (-ai) + + + recipients + seq Entity + external + Dokumento adresatas (-ai) + + + instanceIdentifier + Text + external + Dokumento egzemplioriaus identifikatorius + + + originalRegistrations + seq Registration + external + Originalaus dokumento registracija (-os) kopijoje + + + originalReceptions + seq Registration + external + Gauto originalaus dokumento registracija (-os) kopijoje + + + originalReceivers + seq Entity + external + Originalaus dokumento gavÄ—jas (-ai) kopijoje + + + registration + Registration + external + Sudaryto dokumento registracija + + + reception + Registration + external + Gauto dokumento registracija + + + receiver + Entity + external + Dokumento gavÄ—jas + + + + + + + Asmuo (sudarytojas, adresatas, gavÄ—jas) + http://archyvai.lt/pdf-ltud/2011/metadata/Entity/ + LTUdEnt + Entity + + + + individual + Boolean + Požymis: fizinis (taip) ar juridinis (ne) asmuo + + + name + Text + Juridinio asmens pavadinimas arba fizinio asmens vardas ir pavardÄ— + + + code + Text + Juridinio ar fizinio asmens kodas + + + address + Text + Adresas + + + eMail + Text + El. paÅ¡to adresas + + + + + + Sudaryto ar gauto dokumento registracija + http://archyvai.lt/pdf-ltud/2011/metadata/Registration/ + LTUdReg + Registration + + + + date + Date + Registravimo data + + + number + Text + Registracijos numeris + + + code + Text + Juridinio ar fizinio asmens kodas + + + + + + + + + + + + PDF-LT-V1.0 + + + + +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ïïÝß½÷ó '¥ªµÕ0 Ö ÏJŒÅb¤  + 2y­.-;!à’ÆK°ZÜ ü‹ž^i½"LÊÀ0ðÿ‰-×é @8(”µrœ;q®ª7èLöœy¥•&†Qëñq¶4±jž½ç|æ9ÚÄ +V³)gB£0ñiœWו8#©8wÕ©•õ8_Å٥ʨQãüÜ«QÊj@é&»A)/ÇÙgº>'K‚óÈtÕ;\ú” Ó¥$ÕºF½ZUnÀÜå˜(4TŒ%)ë«”ƒ0C&¯”阤Z£“i˜¿óœ8¦Úbx‘ƒE¡ÁÁBÑ;…ú¯›¿P¦ÞÎӓ̹žAü om?çW= +€x¯Íú·¶Ò-Œ¯Àòæ[›Ëû0ñ¾¾øÎ}ø¦y)7ta¾¾õõõ>j¥ÜÇTÐ7úŸ¿@ï¼ÏÇtÜ›ò`qÊ2™±Ê€™ê&¯®ª6ê±ZL®Ä„?â_øóyxg)Ë”z¥ÈçL­UáíÖ*ÔuµSkÿSeØO4?׸¸c¯¯Ø°.òò· åÒR´ ßÞô-•’2ð5ßáÞüÜÏ ú÷Sá>Ó£V­š‹“då`r£¾n~ÏôY &à+`œ;ÂA4ˆÉ 䀰ÈA9Ð=¨- t°lÃ`;»Á~pŒƒÁ ðGp| ®[`Lƒ‡`<¯ "A ˆ YA+äùCb(Š‡R¡,¨*T2B-Ð +¨ꇆ¡Ðnè÷ÐQètº}MA ï —0Óal»Á¾°ŽSàx ¬‚kà&¸^Á£ð>ø0|>_ƒ'á‡ð,ÂG!"F$H:Rˆ”!z¤éF‘Qd?r 9‹\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=Ä•[=¾ô„=ƒ<Ë=GTB(É/Ù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¤[þ˜¸™$™™üšhšÕ›B›¯œœ‰œ÷dÒž@ž®ŸŸ‹Ÿú i Ø¡G¡¶¢&¢–££v£æ¤V¤Ç¥8¥©¦¦‹¦ý§n§à¨R¨Ä©7©©ªª««u«é¬\¬Ð­D­¸®-®¡¯¯‹°°u°ê±`±Ö²K²Â³8³®´%´œµµŠ¶¶y¶ð·h·à¸Y¸Ñ¹J¹Âº;ºµ».»§¼!¼›½½¾ +¾„¾ÿ¿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Áâä<.}w Hz1—~Hˆ‚¡BH—žNæ24г´«ƒ°LÍôÌÌÍŒôLL Œ*r¹4> +stream +H‰œ–yTSwÇoÉž•°Ãc [€°5la‘QIBHØADED„ª•2ÖmtFOE.®c­Ö}êÒõ0êè8´׎8GNg¦Óïï÷9÷wïïÝß½÷ó '¥ªµÕ0 Ö ÏJŒÅb¤  + 2y­.-;!à’ÆK°ZÜ ü‹ž^i½"LÊÀ0ðÿ‰-×é @8(”µrœ;q®ª7èLöœy¥•&†Qëñq¶4±jž½ç|æ9ÚÄ +V³)gB£0ñiœWו8#©8wÕ©•õ8_Å٥ʨQãüÜ«QÊj@é&»A)/ÇÙgº>'K‚óÈtÕ;\ú” Ó¥$ÕºF½ZUnÀÜå˜(4TŒ%)ë«”ƒ0C&¯”阤Z£“i˜¿óœ8¦Úbx‘ƒE¡ÁÁBÑ;…ú¯›¿P¦ÞÎӓ̹žAü om?çW= +€x¯Íú·¶Ò-Œ¯Àòæ[›Ëû0ñ¾¾øÎ}ø¦y)7ta¾¾õõõ>j¥ÜÇTÐ7úŸ¿@ï¼ÏÇtÜ›ò`qÊ2™±Ê€™ê&¯®ª6ê±ZL®Ä„?â_øóyxg)Ë”z¥ÈçL­UáíÖ*ÔuµSkÿSeØO4?׸¸c¯¯Ø°.òò· åÒR´ ßÞô-•’2ð5ßáÞüÜÏ ú÷Sá>Ó£V­š‹“då`r£¾n~ÏôY &à+`œ;ÂA4ˆÉ 䀰ÈA9Ð=¨- t°lÃ`;»Á~pŒƒÁ ðGp| ®[`Lƒ‡`<¯ "A ˆ YA+äùCb(Š‡R¡,¨*T2B-Ð +¨ꇆ¡Ðnè÷ÐQètº}MA ï —0Óal»Á¾°ŽSàx ¬‚kà&¸^Á£ð>ø0|>_ƒ'á‡ð,ÂG!"F$H:Rˆ”!z¤éF‘Qd?r 9‹\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=Ä•[=¾ô„=ƒ<Ë=GTB(É/Ù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¤[þ˜¸™$™™üšhšÕ›B›¯œœ‰œ÷dÒž@ž®ŸŸ‹Ÿú i Ø¡G¡¶¢&¢–££v£æ¤V¤Ç¥8¥©¦¦‹¦ý§n§à¨R¨Ä©7©©ªª««u«é¬\¬Ð­D­¸®-®¡¯¯‹°°u°ê±`±Ö²K²Â³8³®´%´œµµŠ¶¶y¶ð·h·à¸Y¸Ñ¹J¹Âº;ºµ».»§¼!¼›½½¾ +¾„¾ÿ¿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ÄõøþðuWYw¿‚î®$ï÷éž™¢~õï+ª»_ŸÕÕUÕU/1…Q3iT=arÞ€ðÜé¡æc`ýÜ%s–\ü@ñ´DAËæ®ZaªWc4»‰Ì._6Éÿ*û€Èò +Ú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ë_¡œˆ¾8™B‹óBOádöBzNÒß9Ž“¹?æ©\ËõÜÄKy_Á×ðµàꓼòIþˆÿ.t$zƒO.1WÜ îûÄ1qRœÖH›¬ÕjWh×h÷hû´·µ¯t›ž£÷×ÇéõúÕú™´ Ëb/,éhèx ã¥Î~‹:×w¾Øy²ó3#Ä8bœ¡ êëh>h¼û¿…@ã§ô%}3ÿðBã`NÅ)êÜÊA÷8P>ëør@/ÿ›y·ñ!>Ê/ò«ü:¿Ëó·‚A}?@1´`Š¸{x@ì^ñà¼ø·–¡åh´Z‰VÝܪ݆ýlÑ>ÖÎèBï­çë“õuúË&Í4Ï´Ù´ÍtÌôŠéoA¶ ~qÑ‚àÑÞ/ê%ÚbÚIÕBÓþ&Þn¾NüÈOˆ$~«%iÕZµ(Å$ø ¤| E›·9‚"šlæz9‡¸_äjÓô -”V@ßHL·ˆzzœÑb$m•v\ì³µmúÝz ¿Oë°&‰0þžÊ¨ŒKpv¦+pB¹ÚýM9£É¢]0-aÆ­ú—&¡½ ;8Œ…öOç³\-bÀ­bq'9ñnã³ÈGC?€äïçiT¨¢mcÄG¨[L÷ð‹ØãAZ,òÃ8—Bèã•\ÍÛµ|ZËW€Ci¡¸—RÅ2‘ +yžBßñ Üšû#Î&M\Nº&æÒ Q‡S›#E?^ 9]Bë¹…r¸ƒÒâ.ÌÚá ñY‚/œåVmµòú«ú«BÇL/‚›ýa=‰ ñ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Î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ó,ßñ^ô‰Pc­Zi2fº»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ô_…}Ž£äTaöÇáɧÑu'FK{ò,Â>hü'¶#aå­Ðð|jé<‘òh‘Æ϶òV”ªDš ©Þ*ÜÚzÄxo@¶DŒöíä«ûÝMM¼gµŽÂjÜ ý냸é(¸þúô0ýqƈp×ÐÍh=B?à|¿Bÿû”|"~¿$¾­ 0s#,íÅyoVsÊ»æã«p"ûPó´(ç pÒøe~1/” +qüàÇüð5þˆ?ày°lçx×ðD‚fΤÍèý…ÃïðwÆ™“½¨¯ Bã‡ùQD¢Kxê¶s×CöÒU— +R=m C>›ÀyM}Í$²äó,å?h ðèõ tJ¤öÕoáù=Pþ{~ ý“p®®Þtå=ŸP?ü9'à|»åÞBzOª|ô]¶[¡Ê¼ÛT}'¤Z¾Zåƒý¨½ +;øGHî~vA3âø2®Ð®£WÔøü?Æ/)w)ÈR`tÁ1p ûûEŽÞÀ®ûó·b÷»ãçð ¬’¼3·ÃoÅž7Gwœ«üJä¿0†ó8šÎa aŸ£aGW+\hÀx‰Õì¾°­ò¾š1äaÏàQ|0JÁUJ‹¤$¤±‡ýÖüµíW´ðgq p[7 ý%쩹¿¢Á?ÑØ_Ë¥FÐP~¹ßjúµü'yÀšþJÞe~!X‹_Ë»ø «¯ó;UF|¥ë\ á¥~kê?ÿUþ›`înòÆA4Q‹[å(ïVÜrÑd‰¢/BÍr~ƒWvS¾´ +"‘ö<…×aÉÛ÷4ÜôÛéù€ëŽ˜¯¾ÜÍ"R$‚†;éߦ|‘-ÊWé ?(ò6Þ‡”^t ZsÊ»àËšfzšz%–mF<ÒÚô¹òî +ö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œ%áù唶ãõ÷š&ø‰·ªì§ßÁ³kV-V?4t•žD4 X¹œ È¥¯p2|#DmÜ!z‰^ˆ·<* +\CkÄ`Ü(‡ºqO’wê±U›w"òÈ㸎 ؃w7¢?¤ˆdìV +Ý)f7F¿‡¼ ×H×âÕ\¾¾¼8›Ü«þŸPk:äljd–üÛµ/.ßž€× oOq2¿$ëY˜Ý"ÇAªÞÃŒ¾ûm!?ïW L¼õçjÎàXÊNâp¡7@o—à‘ðfIý=wîjyÖp;Dp+Ë“óÉÊJðz?"‘—TÌ~=¤æ*íø]ôoÈNÞ‹ ç›á—Uö3BF\°€}å_m_ LBD!WJÀéJL†ï¡ÙÊÑë0ç>pÙ-ÂD1 óN£Ë•æ¦Ó hè&usÅÂï—¹z4 ú-#¸°»¡y‹™`«$žéºïœˆ'ùAöˆ£.êÒ"©}Rpó©r—À¹¾Ä€F\+Z@9“À\+ 6ìHjõDØA«Ò×hÅ'Ð_¥Š?FÒßä/< éiàcÚhúŒ¢y*¯Å9¢†>…·õÞwám+Þ‰ÿ(% Ïø¿ù¿µØ0ŸÛ%#ýŸàÏy";`7/Fµ—¢ôP¤‘Ö'€Ý¿HŒƒT0ð ¡û·„î¸WÙÊÜ.KÔý;CO |wèùý¡;Ú 31²ôX$J+øN!q +Æ¢nöÚк=F¢‘ÈÝà`}è1N„ñX…Í +­=>ÅI¹½«È1ÛÇŒcênêd¬$BÇ.2¾1¦Ö ³¤]ÑZä_vÕ¼ÓT\¾ò×öøk{ù-kw©u2v€Ž —Ýæ~X¤|þ,XàhÅ]ù¹R~7@›¯¥‹¯d> G£uËêFO`N·È‚U¸²xä7Å Ø·"úB~@<û0ôæ4ìñ!Xâb¬œÿêiaGóiØÓ"D²WœèåŸGJi1âtH¢üŠ a=Ï =z VJÞ^ò7» mNNSÜœn¥“ˆ¾#8Ö8VEç—Ãÿ‘céýžR$,ÃXÌN¡ÿVZ®Ñ»ê—ýa¯ólylx1,º˜ÖbÌ5ò}#먞¹·\5ì|,êdM¾¬éöyØ¿ê¾›¯ÆØYˆ ‹øö¸6ðQìV2nü$ø:Éh;Em È•võŠ®“žïH@„²AÍÐÜ·ÀƒÕÚzœC"ïD/§ò²$l…Ôî‡-»Š·ÒLj?SQÅqȇ óÿ*Šè«ûýÊžñ÷/zõO½GˆÇ{Æå?ñ¬žxÏhƒpïF*oôm¸ïê ígi<ÇÃç$ø™§!}Si0Òµ8Ñð®¯ä¹J[!Kè?g²gPˆ¹Íêûc+Fo€t åpDÁù< ÁS¨ýy% Þ±çw žÕ{¨†ìDs WÒ3Š£­Ÿç+ âr)Yü $ì¸ò2 }8Sy/®Ã­ÐÃÊ`&„ú §ec {½ôØ_€vdÖ‡«»Hz5ÈÃQ’6|—‚ƒê‹]À¶Ë{77Oó½H/â|¡»Ø»ÔÕè¿ ¾I­òµ©ß÷Q·€/º½†ÿÄŸ òp+¯­÷T3¯ó}EçÕÜ[ºÐÌ鸱šÕ­²7rxn¢p"—?\øZ·õËüîñÕÐãÝðà`åÓðo®¦`êOá"šÿ…ç<,λðÎÞ|È_ðG|’?@ú¬ˆ„wùŸžrÛ%+›®¶h†ÃJßvE\=ó@T–Ùþd®@ˆ4GB£K(–«i|—lªnâøÿÐÉõÔ_X:Ü +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é_¶ ï³Ñ&°ž¬¯  ©L’5;§TÍl¤ë€o5Õ“µ +@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ήîîZ¨Ô×â ¥¢T› &h:¤»ï^·{€Êöå}’|yh€ð²+µ¾`S_ÚÔ@r_Ü[ ¼¥D'“ŽßžJ†g‚™`F&6˜‰ñ™ªWê÷-Ðj¢LÌi“Ìë6‹¬ÍBMÞ²0& }³P{ +)«²½¸xÄß–ª„9U g*æJµyHKU)iŠ–Ú&‚ÃÛÁ_. +/+ß'Ñ(î7ïßî¦DH%Wiž¿¼¥ ±¸¤íôd²©ÀÀ‰jÉ8ÍM€€;w6Öãt¢÷¸Ž¸Äì‚¥ë +6ì(ØSp¤À|PÌÔ‹z•bb`\##, e6¡ÓL +ãÿ¨t·J¯T©G¥±ž„™a§g†½23ìþ™a÷Í «6~f؈™ay3ÃÚ¹Áë +ûȶÉ6Õ6ØVà +è +ëë ++‹@? Îäa•W镦ª4‰§µ…Qð!žA 4€3÷9®O9ãh×¹-åFG»Ù ¾·¾¬XV>—Òß1?%ÇW“áËÒ/蘦ðÓdf—'Çüªy¶ÙcjîgÎ5g™3ÍNsŠ9Úi±YzYB-V‹ÅdÑ-ÂB–èvãKÆlÑA6™é2ÕUÙ&£’ÈèE *¡1äÒªDÕäá\å=:—ªìÞï';ÛÙ:qº×äÎÞÈ*ªªçâªj7“¼…®*opõŒÚVæ;ëðæ·µ3ÕÔ¶³!«nN”¿2ÛOÌ97ß‘èÏëêä˜ÚV︣ŽbV•Æ•F–D Qñ3I½?u]|â\Ý_@I’wsÕäZïSIuÞ²`$ÕUsòGiûE¡\Y±_ ‘Y]í~k³(¬œ$ë­Íuû‘õûÉ!3Õì²Ù{ôKCd¿t™ùú%«~É—ôk樬hu8}†©>Ã.í3ÿÒ>óUŸùþ>š¯£[ó'äP}æO~Ò'ù7ôIÿÙ>ݸÙ8Üõ¿<¼ŸÆðÉÖò5ò}õÎÊF`½wýª¦8osƒÝ¾ŸÊù¤ÿÇ~õ s›d>§±O:+¼åÎ +{ë˜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¤.ó ÉÉ.!ùºä„Þñ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ߟíÀí1P²…€#‡æÍ‚@È”¥Lø¥¢&·œc݃J²¨hpa{ú£4¼J6Kdõ²†fq´ŽRŒ@iØÀâ,:Ii~Y•ç"‰0‡gqX’(Sï,Še$Ôå© +JPbü‚â Þ§¨OLŸ^}ÜeÁ.1ˆŠ¹ mœ. ù¼Ÿ<{‚—ž?ïv»C”³ÝñzÎ/u®­¬]ò3—`éG˳¸£ýÊÓçÝ|5‚YøÒö£>F¸P9Ýv´ô$q xr-=¬Ñ•©€¥]û‡P¸Ž¥(`:r!fB}<ôd(”D€(WŽ’O¡¿éÝj,aNr„ÎiµQ¯×qNÑæ˜`ÓMeÛ&« ‡ÂFò¾8uà%Í'å©C¨£ÿ J”¶Ø ííZ)n„ÖzÈ»àÔlŽ)„B”;‹™­‚d¸xÎœ‹ ’`5GQá—K O‹˜\¼Ñüb¥ÿ+ý0#“šÂpJY S9J,«Ým‚!7Â!7…ï˜ôN‘ÓéÑÝè¦Ñý²ˆ¶Àí{`N­ßï×ø~÷£Ön÷˜»µ„¡žªB¡™ˆ)5(DbÙwÞíK*Õ'Âf ÝíàI<OzÝ-⥕íènÁ‡„ü?t·ج®°{¹ˆêýÊ}DÖuI«lËídÀO•É¤<×ò}ÛEòË·=‡d: “ n´[i{HH'c¬QGEA&#Ge{4*Ë“#²×c÷z=·Çë–m‚Ýfš–Þ.|&*G¼:wÛžÑYiL†Ñ~’TÞ ôÐ40ÈS=AáĬýp½ÊÒªgª4 ÷RßÄ!è‡EÕ4=¾(NÄ¥ìïGS°ZOJ]=‚buOµFk™ë$Ú\(] o3r.Þ]ùû£œÄ‹ŽGu8‰´ò¹Ä»X“\ ¸FV>˜­—xV¤gtZÉ÷É'>I°8žE;X^ÒãÏ:ÐE©©(ˆzÔ¼Ô@Ûæz¨‡i¶‡ahï{ ‡vö𼫇ãhØc0Ðï5˜¡Y +ÒÝ× —ƒ£ö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ð°/Rd›iõ¶I²^´ú«Šî`E•§ËmÝ3ZñðÅô¶qÓð7úÿ ŸA~ª»ÒEê8†¡Äm 9žÌô02—À˘è˜;à]̃ðQf;ØÿÀü€Ÿ0_Ã#ŒÓÄ@S?|aišz˜~¸ÝTýLŽ„ä[|?ÜõônM® ¡šS³K_¹ G ÓR­û†Îæ¹2÷›ìV^ÒÉÿ:3*±f‡î§UbM€>BŸû RÑŠˆ'¶„120ü% ‡oÎÐ D+¾ñáà 6üO ¢oÇð?·{­Œ•¶ÃGÓør³ÏšÁ¿‘þR$t^kÀ.¢ý^daLg G¬¡¢.êÎâ."ûòö¼\´J ÷ hL<]+žˆg!Þ… ¸–hí|{û¹:‹ÈrŠKrJ¢äì’Nïõø<~OÀCécJ\I(I…Ò›ÌF3c¦Í³NO*a^VAÐæVaJUA†Ê©0†Tè‘Р˜Ó*ÈheWIô•ºÔIlûÕuö™ªƒ÷Û¤’ÝÏ;K<D¿_(…û‡ÿ­ªh³{y4x84H,œÖR1»hA34vô>Ò/˜J#D<óÙ¥þ#Ÿ©N4aíÎþ­@‰0rü'àwtîðmφÎP¥ý˜Á8­˜!bïĤ­ª¤ DÌö›…yðšy맬ÈúN`hvʵYÿ$NœÙ•”âí“oÚÔ•rÅÛOZ³‰xwoå‹{¯_ÝRœµd/äð<|KǬe—¾RŒH‘ʾ=;/ýc1,É0´gÛ~ȃÔTõžÞ,Оþá#*ËëÍxTO·Ðí¡v€x˜áÝ*ÙÍ,÷,CxE‡V¨ÓðYºö¹Að؈·O\°èÚ,ö]HòÀIüQ5‚ x^8È=C,^¤åþX ÜÉéÐ$œV:«ÜŒ0¬¯?ÌE¾”5/×lßFù0±1n -Ô,XùÜΰ’‘–¨#ÿ>“—`sR ³0R[hÜÁyYâ-”K)ØPmoìð˜R: +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Œ‹ëøb´Ó‚ÔqéŽàGï74üi=C¹¯ã=Œå1²n Ùz?7k&ؤ(N‘UQ¶z²à£AÅr©ÀáUè ØU(Èh¨eÛ5×Tí¾@ìKÍn ÕEm¨ ·N +šî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“—*ˆz› rÔf§tÑ戊E¦ +å‚¢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Ϭ¢tðƒìQM( ¦(‡U¯×;äwôMúºÜ‡»}CfR˜‡rŸkÜJkÉuðí:D85ñ‡“ç«7:ê¯l¾¡† +°‰¯ó‹ú¤LM<$9ô:|ý©1E|Ñ3-]¥†Mo^5³Í%ò!QüMå9I¹Ñâ›æsVa[rñûÜñÍu7>ñÚ½×Ïß8/ÌJ‚Óh¯<ýqèÕí÷<µfÅ/¾×Š²òõá +ùg”•°üi†ÄÅ[ +Ièõ$ñ,c¶X.p»Ãˆ\˜&‡$.0y–3RœÙ4€2lu2’øÙ:½ªF„Jð ÜÑšOZ2!][m?S»‘|(„ê½âÖ¼fè!Œ%$Yy’­‚KO-T´´ØxÝ¿_pó.Î( þiˆ5 y¸J$<~|>7SnÊçHeÎHÍ#t&+åòXí®Õ®Ûàzz½éÖØÆÔ=™Gáý±mÄsÆó@êã‹)ÛåðÁ‘·gÓÙìøû‡ÿ²¹!’þ G¶òt<.ãµd<<0üˆº9aZ$¤â*)&z_ѦËõ–H?ü*—HˆœR$?pKât‘ûá jj +¹ÒEFj·{Ü' ï¾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€f E‹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í€1|@<šÓ€§{ ¾m`ìá;ø0ÂݨÂÞôñ〆»7ëwÂ~âqÏèoJ˜~«F½’rÐ¥•Üýƒƒè»% «èZǓκ´ þP6XCkÕï\rhâ¥ðѯI&,ñ&‘˜ ÿe–xÉVé®tÛÐÄŒøø<¸ššOš5¿·n6Èè^Ž¨‡Ìš$·š.@ôrBI É[;èQF$ï’ä_ÖvjÊ»*Ž¹¢òG5íMÞ†Ç1sbf^ZëñuÜTÔ‹܆¬z¡fÕëÔðsúWÍ_šÉc¬9ÖÊ=¼fYdáN²,¶*¶nͲ¨¬>®šÁÎœê‘a»¯D† 5ìÐþÿÁ°£ 9XËJê£K5Ë’Æ£ÿ¬Y¶¢×,  Y³,FNòoÔ/£ÌƒgÕÎI4Ü`½—',ÖÆ»-dŒ‰F®n ãýp¼jËý„¦›Ìé»ÉÖã’ïÇóï×Ꞇp¸èÆý`DÈñ<‡ÈZiP#âåÌù=A ïU8ŸCoñ¸­sò6-A6«¤ #¢\¸º•aW ü©éÅ1+Õt:6«ˆÛvq½Û¹ÿÚ‰?š‰ùÇ=ÙiÓ~éòÊË3ÓÅRrfª8 NÇÑpÓŒ™I‹7ú³´«̶îšóÓÊicÎÜ€·†¯&ßÒñ &ÃòNÀ ïÙâõ7 ø #ø›-*Jèj zµÕ^]Ú««¹ ¿Ë‰&ôn•¸œ%‘? ƒ>Xliï‡VÕØÒÒX„Ôä “|ý¤Ne¤|ÚúÞ„cïfðTzÒ$ɨ—Ó’)ødû„¤AOT-¢qB¡Ež0Y-‰þ›;Ó†~˜SM¢CΈr¦; Ó»áÇà$ð{¼•…›[ø¸É×C‡ËCX0uàà ‹F>²ùl¿Fð49Éu€²æ«ÓJ]Ñf+™J¤â©XJIéô6»`çíœÒ甦h‰éŒWTìlƒ£XMqØ¥Ck*=!)©سÖ^hn¶ÆáDý¤ú–thÔ™u}›º ¯ï×(3ªIÞ.45Žì´4,ùjÃRtðbuÿ’Ô×ëÙ#%…+7üæ±ëÏŸ\JyNØrç§ðïê˜{w÷ÊŒwç¼~ὧ­^`·[l®I?¹ý¢sù¨fMuçÂ+Ÿ>çâ5²$—ž^QÙöëÊ?'s..¨Ç7î7c1ì†àçמpßü¡=¢îîƒ×Î<õ|…Ÿ€zŽº$AnWS-<²¨gBº53Y8Ù}júÄL·Ð-öº{ÓÝ™#I6’ÉtDÆÈõ¨¢e­e£…xß- ÞbáxŸ‘" ü#«¢4%%‘ôE’i†Ô–ôú&èû"#Ù´%Qœ%ˆ¢MðIö⥓ °<°.@î À@Âx=¾°ÇíN'“~Ûîñ¸ž÷;º 91"”ƒþ› d‰l–‘2iÅmSÜá€g‚4œ Ú“ŠGe™à!ë xöyy($ìÒÛ…Ï(Âœxû¼±ÄãØçÐ{Y~:ÿw~˜§h¦·äNXˆ£ÚvíC±pX‹N<Òú¯¸ó¡‘ÐŽñ¡x]¥ÓÚ«4®úñ±[ßå¾ÜáçÛ ÿß/µß6 ™ƒ¿«›CäqX‹È<î$!É+‡ÞîÓNQU~‡ÇN¸äˆÖí}®ïÔ–,›n=ø®ª¼Ro¬Ÿâ’óï_4ZVç mÀ'Ï@14ÅÄ@#<_}æ©äã©ßkz˨[›\Ú¼;º1õdT¥¼,º$õ£ÌZãZûòÚ(}:7[f\Ì-æ ‹m†)Á©¡“åSR×Yuìøà¸Ð¸h)9>u;™£™œô†2†7j€Rs´-„ÐG+=!>ÔØRma† èÓ6*¹ ¿}pÅÝž3¤mbþ&z§'Ývie |tÆefß{cåµ™Uwo»b}oîž93o<»œh‰x´N_yTí4|~ÁSÙé ßWžwm¥¯Ü ó v–%y¢¼fFåOµ¤8³­wÁÔùK¯ùò¬‰8+VÿjÎÓŠ³»Ó'£|8ù#‡üQ€‚êî ,Ò/Ó“¼ÉšŸ)ì "Ÿ—dô˜k±þ~UÓ¬TÒÏ"PU´»)›ÍçnÎâ'ò©BÁ—epÏ‘H¦Å— ôÃ…j‡›€Š)"+îP¢~LnÂD‡Ö ÿîöÞNR ìf61{™}Ì!FÇ% 2\†Èô£Š(F£Hø™Ól9áïÂ!,UZ¦,rÕ<7ˆOðâ¯r’}54ª¶ôñ?„^ƒ€ûªüFÇȤ†hÚe*UÿÁÈ:Þ~„|}Ë‹éñ×½Ä×[q£ï©­ÀÓ‰ë°Ùžƒ=Ò§a¹¯ =µ~4æÎD¡ÐêXeëhµª¼W^©œÒ«ýäs<ö"/mD^ZŠ¼Ô ¾PçÌÕA–1§8ÎÇ„<þB8ìó4e؆@ÑjnöePiÁeD)ž÷IJ$¸‘HE£¾t8¢HÍ *+HÈ+ŒD0ts4U@šKw§É4¶wZ–#*\Xž ‡èölòìÕxˆÎsä à–së¸CÅI…¯wâ<))Èø\ÍxS78‡:F}q¼õÁX/”¿Ã °|üþoÍ­ÿÝ÷T7†+žºX“ŸÜ€ ?ôãcp _°¿ÛÈËQåX‰*GTÔ¶5ÁõA"Ç•¸éy²ùDy–©lž%?dzHÞ­03TÄQ̱ˆ"·Èúо´·_K!‡«‰m„-ÙÆÆ\ÖW0Ò—±A¿Ó…ÊS¦%ðqdÈÓ¡´ä”–ó ÊŠZIDÿæ«A»ÝF$£ã??›Íø!î 1…¥4AKÅU‹Ž++Úcœ&A4<Ãloÿhyi¯–ÒZÎÇÀ\¹ŠsÕ ,’ÇTžN#gŸÝðaþ$Ðw|øÓm²#âÈaVíhdäqeɵÂâl>ö tu[]R¸ÕLWÝC¦rsŸë]õÊÍÓoø|ÍKk ¸¯íx'Ô¿zåÒ]3Z øàÔkϨº +Þæ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ö„ýBFjTÒéTPqG•Tªª:Æ7"AÑä—›ýr—ê 4oìzª‹XÛõ~ÑÕOìR='þPˆ÷7*±Ž §{ ‚%z‰EIì&vIøñ²êc(s;´ç(úRZçglV +'ä´C²UŠx|¨|çÕ¾(ÿÏW‡«-­ýžÃÍÖ^U4äP!Úaµ¡ 4T[é¡omÇ֟Ѩo׆¾µr¼ÜX1ôºו÷´´oÆÂâ AˆÌb¿[ +|ƒWš{ëï‘‹‰–ŠÿXÉ¡ù©pk}~T¬ÿÅÜGH€|‚b.ÞR39*«‹˜ƒ– =èÈysþ º&sƒ½ÁQò–üÓt]fÕ®:NñN÷M÷;ð³À(rÌ-ÚñIíÚÛ¼ÞðIU.dBÈ_åB._Ç-¼Ã!ð>W@‘Er„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ã|„‰+T§ÚŸ›_œ'A^ÍwçÉ}ùCˆw¶î‚g‚ (Á•Ÿ +â¼<„S¯kÊœ9*B4IÞÑ!q‡ÝC.tÙçƇ†0èº% {]%÷ ËCš@ÑÎwàs,ZY_•MáSPý(š½­hÑàÌ Á/U[ƒ³Wé~\=4íÛ§ÉýwÄÛá)÷ýWÐ6X¹ŽŽêñº <¼o‹$7c%·½¢[˜aB“¨ÿ ²Cu€†Ç!6Äg'ëÏPD%gÝ­²Ù4ʵá\¼r71élíY&¼®4^p}Iž;_{Þî'[WÁ+«¿ 4Cÿ&t#~^òꥇ´ƒNóÿ”Ô ÊŽ3Qv„ÀBµ ‰¤I˜‚#lñ ‘ônM°&"“Ë–Œ±i¿MÂ^>æAÚeÄŽ«Ûl£ø[Ìð=ÒýÝv‚oYí¼Ý\üa_xA³ÂGu@…Óp¡ªÌ9T!p¡Ï³}ž6¢M-}è;à'NSÚö€½àuø¶÷ÿsî%RT×Ú÷Þªî®^¦»ººº»ª÷ê¥zé™éîÙ¡ F†ˆ’ÁY[P÷ D .I#.¸"c\àI\¢â à*ÆÅ}B\b$qy¢è?âÓóß[Õ³0¨ïO`úÞ[·ª—ª{ιß9ç;¯û‚£ð¨ßq< 7MöÍð=ØØ ö½þàþª™ØtZìÜÄé¯îf2°¨ŠèXK¼î öº“›sø-Aé° <-ŒÂI9ŽÉþ`VÅ:æú\C}}¡ÁŸ5ëÔc&G3ŒŽö›½NíÃh‚’¼ 8y¿·&¡€ô´4J'ãét"î¯é¼Mñù!ùüþD<$m  €€?Àã)¬¼~ňÉÁ` àóËOñù¼MˆrÊ^T“7ÈÙ¬Ùl¡²…‘ãMMþ@Àß؈+` ÆçÅ»âOÄwÄuq%žÌÇ®`‹¯Œ¿??‚çúÐ?§?çA´îBÚ磢ý}èÅåQ4O:{ûŸ:h‡Øü|Å…JtZ-‚°7gµ¿Ò|XJ§—ì!JK#³ÄŸÐTžtÅ­r•jÛ4”F¢¸7ÿLËpé~ÆîL ß´–ü{p ¿ÐHá1È_#0ò¸ ÂïdÊEÐóËÏ°÷ª;Ñ+¤\ í_àxØüdiä¹Ý/ÖeŽ°äÆBƒ Ú{"¾¢>ÂR]ƒ¥úz,ÕØ¥¸>ч^BÐ õ^/tyi³]•2k’³ZíXƒciMš0Of‰tÆ3Ñê%†e0ÐvxõØƺÃcåŽÈqXÊù%)à÷G½r0 UÔ@/p¤åX, G£x£ºv‹——±%ðá¡b‚f“ 2~_bgMñQb[¦33/Ó•Y™ÙŸÑg<5ˆ +p^r¹ƒ›çèr¬tqÐ6tˆÕ-—;yKHäƒÕ¢VzÒÀ[[¼iõ"ªWÙlÁ;äí>Ü°^•‰2K õÿË@ïd®šs)¿[Æšv]6°F³Ý»U²¤j»ßE—ÝK¬•†Q&ÓîããÆÄóߧ^Á…\„qáEØ+¯"<® ¾l{ADÜ!×!ákök®ßÕ/ê_r½Í¾ÍýÕõ¦ð!û!gð°Îér ôKÜ7¶£ê~ã˃èaÝÃÆ-¯è_a˜Ðíº;˜nË +Ç +ç]è^Ó¨odrÆ6K ›ãr®I¡´%ËƸ˜++´"ÃÓ¶l×ãèqntí¶‰Ìc¶ÇÙ Üï뺞™Ž3\%a-»Æ±ÚuŸpÈLrLrNrMNgÛf³grLRh±58ÍÂmSØIcÖ›¯ÞË$mqG܉ýdÒŒÃVEƒƒV{ÌDYc$´µ`Ð¥|Ì özÚ¯­”ÂÂ&!o WÀ’@|%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 Ž(í¡½†:¼\0æ-x'y·¦M).Þ7ø‰Â^åYîAq&Ŭö¬ ¢±øöÛ½³ºa¸šQ}³Ä8[´EѨ€]´d̆±'[!#+ÖI …«I´šx% jxTÁÏ>Š½dܘmÄ/ž¥¦÷F»ìÿ›ûFØþ$ ýa·!Viÿ±J®&"Ácãm|ðØß&ן6­åœò×ÐRZÚ#¿(ïƒÊWž¨Ñ¯®8ã±&ãì³®¿àM§íªN×€ø²2ïæôMµ·æïNß“(ñûÔƒ5 wIÝÅ9dŠSioœOóÕ2˜RÛžoo8µù´–Rtvìœx©ö¬ÜôüŒÆ9Ís[¦Ö]˜ŸßøxíúüºÆgj·äzò·¶¼˜~±6\kiÄÒ¾¥ÅTËDÉ°¿§ŽÉa•¶Ä™du²¹(¦Zª[šONNß½-~CzyÍòÚ ÷Fï¯N¯ªYS{OÃðûô雿©=š?ÚðM‹¯¡±¹…Îçj©Œ†DÂ|»‹°ŽbÃNy‘¡®PTÌÝ$c},éNR£uQôÁR<"ÛƒPÈÆHX6”©Í¬Ëè2K 1YlÅÞ7L…ÄZÎ8HÂ|Å,‰òatxŸë1²ùô¬ƒâ{žW±õg;G,Bi¤z +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ÖÛï.%Äú²¾ù¾=>Úæ+ú:}ó|‹±N=áÛïc|ƈ_Gb‚ý•:£¢ºIm”è:I¥áÂî¡ZõŽ9Ucï”Ryÿ‘§wbà´üw"Ûpiy…ÚGð}Ÿ…¥ò§ø¾kax;ðaüª'ÈúH‰°ã½ðRïAý!ßGÁ¯Ñú/¼_…ŒfDë¡×¼Ñ{¯^Ï šïdÈ™NAôsZÎ +ªauTW×ÊnÒ²'IcU•Éè·k‘¸Ér®«Åö)"'“‚Ì™dÎŽü͆¥„]xm t‚y¤(¼^ô¦Ó8ÏØe\f\iÔźQÞOI ¶©-„]‡Ýž+ ¡Ög«Æ¥©oÅO|8Õ8äȪ췆Âo†øø‹¿vrÀcµ4ßåÞgqÖŠ UW› ÇL|òÈù/]žUª ;ñ¶çO`:3•a+ûO^§Ä À Ô‚Ó…)éùþ;Ù×ü_ _§M‡ü(-Ù‰ÓÚì¼ÉhŸ8€êÍd`ᵜ›s²,ïô[œ®pŠLáM`±Œ€ÌÊóå×dZ–“iYN¥ýá40«É*¡Ëm† ¡Ë€}ß$2(ä7#(‰ää©~NðûEÁ/ n'‚0€o+ºÆ Ç-ðn·àv¥ä°(K¼l¡dsX’,3Á÷“–k…iÂFáˆ@ $Ílv#9ëœçÜᤜø¸wÐ ÝÛà À…^ëͨüµ…„Ú¨Ô_R+>Jª& …:Èÿlv(àñ-´µì·-¿w‚D6ÔØÆ’öe+Ô}u‘5¶Ræ¾mm¸ªƒ¿ŽþjV+Î Ÿã!/³:tº•º=:Z÷ >›“ÔœÁBÚy ñ'"{Ðä–ñ‰ìÀpX«A)Ägö0l+ù=’6P† á}ê° Fˆ øóÀØ$Á÷QCOžѪÓ6Êâ¥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ÖóÖ#ŒØYÙ&›2'KrHöL”Ûå¼\[ëäz9Ô‡®V|ñ›ÓŠRèÓ<ÌËííŦ¦b$RSo' Ÿ+Nб2„:‹Eç÷[\.?$Óv›.«+bÙš§Óé<“êåžÝ_äÇßDΛ:±Þuù)¿xÊv(«d9§¶÷ŠSûlI]ÙÅ©n(p-’e''Õ9 O–*àRœ‡G7D‰ó`IºŠ%é*–¤«Ø0(²Ö*n,üS9«bïUV7¸·¿‡ëÃ=~›Úãwr$Š„߬ã÷“¾çİ᪩W?'7ø™â°º‹v›ÝW´ëœ¤aE²¡*<% ød;iXÁÆkŸûzÜ?…{»{‡ptPjKf3Ñ€'Æf·ÆN {àJ-®ò9io*o(?|“zÜOH/9xkùUÆß#}.<N<—Œ‘¹š100Ì~~¶±ˆÍb ›Å^ Ø… +µ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êÍØkýïŒÙÄ2€Q#kª5M3Q&‘»àáÑÔžâ·å–‡äÈ>LÏyU50´€.}ç7;È/Ò}D~!Yõÿ<ƒz_w!°Ó7f1mä[J¢ñGðb†¶öÁ]›ôSá¦ö(0ÇøLÖ +­o²ú—¶Âݤr3K*7÷¤À°„%z¨®±R†[Ðz“h÷ÙJ¸óê&~3ÓebŘîa§™ÅÛ(l+ »Ôg1^ }¬™3š¢°¨Ö\jOáøÐSû t#œÞŠ6¡âîÑܤ't§æÕÃÆŸx >¤ÕÊÐÜEÌÕÌ- e4 æ9,À F³a‡ê ÐÏWÎxÄð`ð‘J6Ä‚­ô•Ž¥žŸx»ù=wòk<ÖñzÏn6ZóBݾº÷ê˜D¸=®xbY) Káçw¸“ hHB*g1fúàe6¼%L9‰2%†_œ¡2ÉV‹%ÁßÇJ~9QB!IÁøÂ&Á¬T”:¥yÒZé i‡´_b$O“{e­¤'ç»ôkõ;ôûõ´^lLmÙb`zêÀ¡ +LÏÃÅÃj{¶t˜Ä4úÕpêPø­ÙÞÿÉ‘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\%S²˜Þ9j±¶©y H5äa¢j‡V˜ñ#EWZ¬›D “ÏV¢ÝúÑÑn×èZªHò WO½ Ò0Õ:*ýwmþ¯œ¿ûL'kw_°~×îò1hÞý'ªÊG´äÙ ÇíÜýÑÝë÷þ`ﶧ'^ +©—vC Ñ…Ÿã§ý(Ö…~ÞÿØrjê¢"Øøqþ˜Uáq˜ dŠõfÝ^¯àL®pÂX2a5èMHøycu…%>,fÞ°íw¡nmBO&&u³íƒ·÷¦SÝCU£K*χ¤zÚÔò4Œâ¿~¢ßT­«=m£«¢½V†cˆ‰Ñ‹­ …ýû'gû&*Û¨a8)è‡mõî!QvŒei&æÎüøõk®yýŠw­/~kͯßzë×kÞ¢ß?v9±-ØuÍ¥Wï¿v|G“äuï¾»ŽH2R+:²X’E¯)›\÷8Q=šˆÎD ЋèEÇ+â;Ü;â»ÞÿÞ ~ãª})_5¦xOÎõÎvy/ þÜ{»÷ß=§t¶«\Û|;©Ü˾—zæ»'Â{¤Ý/¹ ´d7[Îö´®p1Ö >øžâ‡Zaë:vñ;ø=ØѼ(¥þ8JD§V v«‡‡Š3O02=.^MÂ&/  ¾Á‡M=v är)òÓ$´Ò ºúøC®÷>÷/VV`k¿¸þ­ò~hÛõhš!î[½z¯Þ¿þ¥ñ9›h·³õ3 ÷姰åø¿×ßöøï èáMì)ÎÆ’™»•˜b™¦ëÖÝ`¹¾n¥Ç²)ý|zoÚäflFË.– ó5 bWÞ@¸ƒ´>¨(ˆ%7šƒX))ùàBbMµ 72¦0–EÅÔ20äÙ£Šæ¥*ëTœ‹¯9i§X¸j+|µÂžª~µ±‡T­úƒênybíji ÛšJ{ñ‚f‚ íM! O_ýwVáªûÃY-UC˜9 U;:ÐEÚÝ[H»å¿\zsÎ)ðŒãî‹~´®P mÕÀä!Ï +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±^1·)T·£vO-ªíƒÿÓÛ<ù¼!«_ÒmC&_M¶Ø››ÿZà‰§†h)pð¹^o”xzìž ++$ëñê ú˜W'¡ÇàÓTëä(fÀV ìß²y ýÌÒrÐvµ°l£«®†c ßE€gN[=çüsÏÅŽM°ü©B»áª¹²—®ýS5ã¢c3&OZÙ9ðå°þRs®­-øxhBƒJX{ŸÁÒàÒÙ…ì2%ëEEŒî|WÚºA7ìFÝÔ›õ‡ÌJf-ó¨o›Oçc¼„ÐáÃÚ¬33}ð±-46k7¬XÍzÏÙbˆsX]«$½>O±#DQ ¥*ä÷wÒÛàfø:FR¿j)ÚPz}à`ñèÀHÝ.†kMx$w.TëŽSëê +hÿO¯/W‘Pš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ØÑtßù†ó}W®ôé õ¾I†I¾é]-Ó8NÕÏý-°¥c|K˸ñáF§LBœÆ½ÆàŽp4àXNá(®ÃÊq6kØ ª@„Ù0 +wÂá` k¨Õ&slå:²¹\m6ÜÐ¡É ö·ÃöŽb{»R Wgõ¹¦:á÷é¡!Õ¨´‚}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ˆò/ "i„ §Å"lΠ9;T¢X˜‹iµ-É +¬ÐÚQÙ•4LË‚Cc€mU¡C¶õ­Mz¸ !¸@qø%Ú€1.ÇÙMFSȳ_„"ÙPXÞ®ª]‡á­H°ídª [M8úñfñ¯W¨ÿ«¸–÷útŒÑ3HïÓaó2~ Û¦Tlëf½òø­ÿõ¤—×Äk ‰ì‘j èl¨8ž'IljRt¼1ó—³æw6ÍQåáj‘Í/.?ëÚ%£ÑmEV–Í:%¸íÔOGÐí¬ëÚoølŒ€` ø«Áýt–3pÃ(Mœ‹vñnõ2|Ù¼ýM÷wÃ>³þRÃÅvtº€¾øÿQî%ðm÷þ3»«kuí®VÇê\–,K¶dKò%ÙZǹ;&w—@ê8wBÛÊ‘mB¡M!…Ò&1( G Hmx4@¾ä(ôá’×þÀ¿ÔòfVRl'ðy/Žffwgö˜ßoæw~õ³ëÍ—òÚÖ:õö m h£Ag +¼^¬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¾"šh/1o‚×6ll2>¯ý5û–î-ÃÛ±·š?Ô~Àê%:I_«û½ÞEk^²d¥”O’¼¾C•RFáå)"©'”ªH#hŽ§¬y»78Õ’ +ÙxÞÍè@ _§­z¨wg’À"û­>5³„ñI-“ïDµ«ºÞÇ +Äp&ÿÁק’OvÕ›ÒØîh$‰äfbª7OüǯbáÍ Å±k×^1"‰ý+—Ô_ú‚]W\÷Úååñ§ßÿž3žäRàÛ¶=ºý‡Géó·¯>gÓ‘£å‰'ËZ5¡éy¢]¼õÈ«wm}õöF"Ú=Šh)¸ðHL|¶×ÚÇÌ×níØ ñ쮣ƒóÜ€oº×/×¹¯lú6¸Ý}SÓöèýÉ6ý"º+ùp¿3 L~,N«öƒe²HÝ›ö—+Û²º /ÆÛpÕ8îX£+/`EÞÒô²ì!ŠÁÝ!]JIÞÂB+û{‚¥YwsCpKà®ÀŽÀžs$ð^àD€Héªy²gˆ`\ÑÖ‹ˆŠaÅ™ÜBàëÜÊ“ ëÁÁ‰O@ +)Â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€¼§#ÛdT3С£è +§«»«ÓW@ºŒ;_h´€ØÃU+VjQI†#:N•úûób–õ>5ñàD«w&Z¶ÝbZ½ûBŽ‚÷”_—$9©iyíHÆÙ‘QÑŽ%®‹³£#TÌÄ"v¦ˆ„êLÑh-zñ}ÐÌàNObÅBÄÅ$‹¤ûT¬J¬ÉÆX•š__ÔNB«àk*^%D+h•ëTkÇõÚß|{~vú¦Çg~ã¼?¼ôÒf½ÝLð*’3¼}x玳—_ºeáÑ»wÓ âÔ»ün‡Tˆµw$r…z¯Õæ +_7÷’G. ‰·ÿ—ˆ}íMtñš™ý©”œ]W¸t3¶:¿´­Çþ‘=Îj®´Üd¹×ò°åEãF­SuxaàFÅ®g>9Ñ`ç­/ˆÉ/Á‡ÞŸDtyÖ”Œâ-L þB“I½AŽ_^Î+{7xŸõjðÁ¾Flè!&:NÂ,'I8ŠÀ,ÆÇÔ@)I‚›*„q|ÅíaF·!X)Ôø + 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œlƒâ/ëè ;Øë§;Ø þS«æV’Ðþ§â°ºÝ*,Tðf+Oq£ 6F«©³1|ZQyuÚ*Ëði`GËÏ”!aâX%bH@b“¦ŸÐ¦íÔa5ÿã¦]/_«,Q=Aëúÿ!çȸöþÞ•WP~BŒÛ¯Jmª~dLƒ<’†ßG4ÕÂcð1a—–YÙ(›d³l‘­2²Üò°]è´­¥.â//?Ž:=j” ŸwáªpÔ`9L&»˜9sÊL›ûy³™ãC,/¨"ÍENr’h¢iµçPZ-M… T¢E—êí¯9Ey +BYàEdeŠad›(Úl¢M€€­¸?=\ž¥ó¬A΋%¸^1Ú¨|Š/òó4®6hPÌŠÓ°°CxU`„§á㈣ê`°’ÇÔ¤ Æe LB1 _ o™žŠ†¼û¯ÈÃǾBß2Åí—™~†ÚsGù‘åÄ1–Çåm0[›¾GNpÌdmÆ&Ÿ£ZˆUoYûÄs¢u=ݯì©wÄœ7Ñ:~æ,Qûz@qÔfÇŽÇÏ8Þu”úÔêEë½ÝŸìõTœ©·ÇœíL»}.3×¾‚Y!®´¯”VÖ¯…—0ëì9/’.ª¿–¹Ê¾ÍñçÃÔcÌÏí;œ£Ô!¦dßã|Rz²þ°ã%ç;Ž£ÎÇ £ÃãHP GÂy³tsý.Ç!Ç‹šÅ?;>‚9¿ ¾t|áäO¹ðU ¯‚\vc8U5 IE¸ìV’"D䈡OàÖŽÈ«zCdK„Â*ÙNð.¡ +Þ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œd«™ÄÉñEàšŠ,+ž,pÇqã ‘9-H0882rú¹ÓONÂÉT½£õzIÏp§”"¸1¨£é=-·{2¦zŽ¾eÝÒºÝñZš÷%÷î» tçzìáþ+ÎõòŽ‡“ÖðZJÿ„ºoò:¾íÙëÑ:¯Üà%´ó+xʃý4мL‡‡zŸ‡Ïsþ|%üJËsÙçz­zàÛBô™à.â"«}‘Uè •‡ykm§¶¼æå¼»9ß’äÃù†ùÞ|.ŸÍç•*¼%ÖÔ+®ÒdK°i¿Ü{_‘Ã'†¹ƒ“IC]î³j†{¸gµ ëûÂ÷ÅÒ/x_l•Õ—ª¸"4>i&˺Ùm^ûáA¨SáÑ“”éãì"qS/ƒÚ‚a/Þ‚AXc.îxïR©ÝÀ5 íB +ÍÍMUËï¦XvU,Ÿí¸>†ýc¨þϽžB÷i%̵bÐL²šaÑ0Α*~Œœ ÕFÕ`/ªú0Ê»ÌÖlíq{Q­*j©‚ˆ9¦c‘÷…"êuL™<ëpvóH°v÷öø…"ÄEo›—/B\ô¶y8ÔBE/N‰‡¸²>¹;kEE‹(yº9¬»·`eÕB¥î-M¼°±÷üÅŒá*‚¸€‰ÓþšBU æ×AlÔ,²¯‚EhÃÔxcT´"KÿïxQÜV>P>DD\ùS¿Ûj‹ÂËFlèúXâ]=Ðw^Bà«øÛò:‡¹Òê(¿¤úKÍ2nçêÉìçùòêª29ôhUÝ[¾Ù†VU bÅp ®PÂtæ`Ž_dVœ_Úþ_Èh°-°Í­ƒëø«lW…n±Ý:À?m;z1ôfÈr¬3–…I ˆ¸²¨êb%§Z¾Å¦*F~³9UÓˆ‘h°ÿ€ŸÚàÏ¿ÙŒä4²fƒæ=Í V#e’ž8™ŽŽ|ùªc’UIæ¼YßD‚¹7«û¶ë¡6}Õåê!7½·NÏôx +H\a¸¯aÁiñÖ uiùÉï6Û3WÀÅ#”'6òmŸ^¢ˆéÐþ-˜í²/¢~¥²bÀSž)¼@ÿ qœ|¬°슆z K==ñ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Ä—„÷–ÇéNæ/ l}]x=DéÐFü¤?çyCY?j+"j„C‘&^àh«&¹Z)"c±D¹F¬_­XQK Ù bG›LGMYGÝ©¦H0(nÎM¹¥–€××òIZ )sÇ”J!ÅÅå“P5ˆjXISÆ©É8v98´(/F%91Çg±; }|[kk®5B6²±QO-ÕÚ"8g4X³[Z”›3#ãu8¼Ùž«–ºÜfƒÜÒSÿ 5v—·wÌÓÐÚÚZf­ëÚ0´C´9hfA\wîõ.A0±´f~[y[±@ +#r¶¢¹2ƒàÄOÅl0 ":½d© ‘ +}ãØ€HDWÀPäݨ­°hr1»ÿq3ž|ÍÕh;Fœ ï)ÿ“î x]±5„à5¡ß…þ¢ Ao²®1ëB‚S± †/„Š.œD…lÌÚypíÀd +¢†`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ô~{òê9€F5¡Q7jžG£šÉ¨7'ÊÐê|µr=ô¤{zèÀ£[§|;úxt‡uï2ëÈ,¶Tfq=WRL4ä(Ë*hÎⵧæÈS— 1ב1íê´Æ ¨p½;z©^ßMèq¥Lyž:– Â4i4v&™•ÛÁpï£`—¯4qÞþ¹1 +v¤¾Wu†½hDHA²,ŸÎ+ù<“÷=H »'ÌÕFúk#ßD;užMÍPÓãëÐà™SŸͼR}Ç¿O€˜â@ó2Ož—ž74oÏ<Í<ßzÂUSŸ}êK™'kãßDO)fjhÁ‰X , øJåWöãwW¦=þÔL-­oW<4è:¯‹ZÔõnÅuÉ]é®®¡® ]Z<ƒ…Ñ3¼ÎÈFÂ!~\@oA÷›­ò#ºŸk„ ´Ù~üæÈæȺê¼l…¦õŸ«R + ?I=›ˆQ14æòæ‘Óf}ú¸^ô¯b¢ö ¡ê¼©ÿŠ1þÚL)—b NB¦Éjý mÔþw0ˆ‹Ð3h*ã܆˜ˆ¦"Ó¸è Z)NÂE¯«_óØp¢¯€Rùýøë½ðÜÔú××ú÷îÿØu.Ü[>Co­÷»¹{iö·ì_‡úGOïOÞ_íÇ.ô6ho ¨СÛSÔÔ·!9=„—ΪñRTá èãúä¾tŸÒ7ЧícJåƒûñBŸQLf—ä{Š,®¬9BÉ¢ÂOù ¥‰¥„’ÞÓ¨2}\ï~ÅB¥½'¼”×ð(åÿŠQþÚ(•–,6?À:´¾ë¦Q†ô's¡ö¿­ï€b¡© °ÁðÂО3¬/uÜ“µqo¢· £ç` g:I' ¥òQòaÁ©ƒñXK _¶²ÆÛnD¯&±4¡rCB©¾åô½êWA˜wµsÆþþZÿ7`¥‹XÀü;S2 jÿ;þL8qB§ø áˆ)o„dý?'n _CZU,VlVƒi”ãZ É; +@‹$¦DEÑeX-I.N œp5¯ã$¹ªÅ‘T ¤Æ«ù}g@•W‘î•„ëŠz +cŽÍ’òçjÊ5 žë±ñM[ÿùsR¯$à9¸€DàGÕøÏ¢N_§ù#Î< #§ØY.ˆÂ‡j ªGQmEäƒÒ¨=I Im î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«T8­m|üäøøàØ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¥²ÒŠ]¥*¬mãǹNb|†‚vµ“dH " +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»—Ïë.`»|þ+}.½ íÆ-2göthÃêQ„#ZhÕ.Òk¢Ý¡Õh%ÓÜð†Šwc„äö¡©ªØ´x2ès¿¿víÖ­k/ÚJ]ÑÖ­¡6æŸÇÿ4`L’–ï+Ö™u³cÔE©+S¦hg*A‹RÇqiCÐãÿ{(”ö´·d^ý€t ¥Ç9o…0­wÛœ¸§h³¥Ý ]q*­×ÓÁN÷–hVq·`34ÝÒ‚- 4Çñ ‚-ÝB0T‚Ûs×o¸¸OÇéøG3רò™ûãj¿Œ·^œMŒ„!f‘TAu;ª XrÓÁ§ƒÓñ œÊ7#pjrok†óÓœÛ|4ÖDå*~€j6¨ÕÚ+),ôæo;›ýy‡Íhöج¬Í^þSöÍ+Ïk¿,–™ýWÀí›ÍQ^¾u‡§¹}þæÑ/yÌB¼EÏi™O¿äµœÞBÎPWëëì«û;¿Ñ“opGçàSæ{—ôµÕÏÔ°·`Ò9tˆ>sÀ ErÂóÅCCÙ##YMN?§gf +€PO§Òµ½£#¤4&êSb:Zç1hZÜ’Ç_ç4ÄÒ¹¦`,¦ä‚ pb„ºÛߣ°þ otƒ¢.Øò`0hµ@‹{žˆqbl{‡ 4wΖª'©ð¡êPGOM§àŽ¤ô„€ê6Š¶ÔŽÓa!H F3mÙÊQÚVº=²š– pÁl£r˜Ñ¢B¶úq +E¢"1D ÖÕn}ÖJ¥¬Eëf+mU –¬Õjb˜”¡h  ˆ{µ”MiÓ§&Údj™ êÕ̉ µ%³#óë ­d2C:“ioχBX¬!•FÃöò‰<ÜȬ›©tã@#Õ(¥G2Wj¼Âù™”ú¿…䌠ÆàÈ*Zð¹ÄààÆ1|jã˜ê7ï@öžºÉÕþÐÕAœfa¥$[°Ô_aZÇShûsv ç¦&ša«ƒ€ÀFœs‚•;ææ²x×BÍRpÕ +†é)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#žÚUÐNÔô¡©Ú­fRK‡‚ét0”†¿L‡B©R\™kC)|“¯?‰ë§Ðú›ú)b¯ïÏ„Ó‘ÌBæÎÀ2ûûú¨žöµS±€.Ø•këêjoóõàXÿNÅe5âù<ó³fÚlN¨¿Gýƒ¤¿ÕýËC~0äó`¤øNE´¦éTº˜fÒq‚÷5öÎ#}‹³áìÄüÙ³çÍ÷õâ„É8a2N&}ªO²¢vpÀó£àpØŸ$ðC¾S™âªÞÌÄãKîK +<ï§úDŠê£ø(Û'D¥~PÁûál¶5¼‹F·[šÙÛÖííe eÐ÷—¨JtÁ‚ùþt+lMaã‰ÖÖ»Â0ì_¸p`Q[»¿§çÄ 8£Çãq—¨çŸè£¢|_T(ÁV…¨ÆÓ¦°f]ðašZ[~gY+V2‰; Šß&¨ŠõØW¾þ!2Ç6þCp·†vêDŽïÆ=/]÷0¼µü»ª²Iÿ•ø÷^À—>*/ìÄn¼qÑQö=ç4j9Ú`“Ê%937SkÆH’Lìb®gŽƒ ˆƒf8C¹+à +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@¤&Ú:_lp…€„¨Ð˜a>ï¯ÆN3ƒ´KŤTšM RN RBd=b›…K%k¡w£ž¥8ž»é0õÛý7£3 geoº¾øòËøËË~¼û›óÒ—ýd׉Õk~Ê©yNoÞ9ú dàâb)ét÷çÅ‘É6_zïÐ]]—Áôû¿ü ÞѶ ­Uö{PR`تzDö5ؽüˆQ=HÓÌ#Æð Û,,kdUÜq ªà R©:‚„~ø´Q $wZ–(Lx£õxLBnæ¤ 8WZÛãLH1vª?Z˜á&O-Ñ(OT"ïÄV ºUÂ;¯Çe(áCZ'ZûU:d$«ú‰Ë%bGq™Ôn‡äÍ~Hè,Çå‰eiÑë-$ Ë[Ïg£ñXƒvøEðµ½ 11¯ jL‡%b^‚K¶às}&so6“iÉ&’ÙÜìùOÐz +jz{zæ÷&f÷öaê¨?,Ñ÷lc·ŠnŽÅ"áDc84« ·ZÝÑqokGG[kbVk®5—óõõûrÙ¾Þ,*‡ÂÆP®5ΆC¤'Ö×ÛJöP¹ä¢¾DŸJ%ô;cwÛI»õ-è[´¨¾/Ôçó±;{V²‘`©ÓÞòwÕ®wmµïz[ ÄÞ==×õbg¼;ë…½øÓ¥VS>¯ç=¨boVt§²¨©Èc{îºöXlEl(&Ã"ÆŸÑEÅet,?Â_¸lÕˇÆÆ%§)ÆÇ´·Kê ¶ãÆKv\4/Í\YpL…ùÿ‚‹Î¤^üß›JÛ²©â›1Íà¦*ó/%ÌØ®ÿ 6Ì[ņ[!-yn¾‘æÖlœŽ¿ÀþH—òŸLàj 5vÌÀÌé¸4†wÞXñ‰/q8y?£×±¯W¶ê×Yž¹© ,šhºJwþ¡Rž˜À °N$Þ&÷Ék@­à›v=Ñ<ó£Yfü~¡N«ŽA]ì„;“a¤1DV¨¬>'Ù°ÓíÓéê´ÉúdÝ -@¡»Dʺ3Vðé—–#3cù‰ccx!ƒ(¦ªåÇ‘±6Výœ3™F05Íù‚½¥Ø¬*ë{¥5^ÀÚ2 D²¸ˆ^|ÕëïØæ]s×´^dV1cv¨y貜ÍjµÝ += "ëÛ#³æ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-˪ŒZ­0åy ÖºyF Tµè©·BèV±F•Š…*¿†X-vU½Ëªg•A¯¬\¨±äí‚;‹ˆÈÖ—E +„[¤ýÐ 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ɹƒCj W‰§ÖÃ_©”ýÜÁqa5™ÜæfÂ,ÑÜc6'm‚Ý}-JF ð³} !»©”ÏÀ/@#ñ1ñI)°3Ž¼ª‘…˜Ç«XR'Ð÷˜8–onfñÂ-SXOÓdÅ»§PVBãÓjJM‰/ +µ¶ÕãdÖ%߈<|mç%‹ðzØÞ°`ÁÏ_¹Œx¤µ>‚t°H¶¸ñ ,´o8­aÖЃ5ÁYøìònñ7w/ß‚dÍgÅ+ˆÈï¡q«ý"õßïA"1¢eN¸Ÿ†k€Èà¤PŸP¬Ï0*€X4Òtl£µƒ%^/†þ"…t D%ŠÏ1)†ÍOÛ|Eó²e v ð‹÷ËÌgËTM*âv‰ýÒž«fu†Í ejo\šê.Õíß4O ZY…‰œŸ™Gj%&Àý`?Ϻ8‹Òœë[KÄqÝÞ›Ÿ±ÒNÎBÑÙ5Ø&[ ly`üK\kkStPèP¡Ã&†Ñy‡Ñ9.{|IN(œ¨p2  lY¿J¤úm¢C&8¼4ãä*èèóál}†#ÕǪ>xà±;—/q`¯Ø  Ÿˆ£öÇirøw ªd‰¨¤B%HÕ@ ÕÞ׺¥hò‰¾‰üq´bÇ™b~âøx•ò€VˆZS¥ò¨|ì8™N'2Àò¶ayÌO­YŸ·¡­ÏRü5l¶X9Îf*U˜q…WÀ=ð+ÚéøâCŇyµ…÷̬Ac¾ùÚò˜ÿ·¸t®ª›škëvÈ–«VPËm+×)®Ó^k½Ö¥ªªS+Z;lŽN×ëà õaêuî ÛöÃZð:,›Ž¥äP%°4ÖSà péˆj Õ´t/5‰Fîi4°v`@Õ¶I΋ªEÊ1iœ³ùo,­ãR u¨”ÿ_†Óņ!,‹ËóùÔâŽb;Ç s¤ðxñäEÑ6½`ñ<4¶,óp9/kñ¼™5HvŸ;ù‘l Ø%éÙ^°Zœ«ÞLš6ÓÂf»¦Iu³Ûc.Ñ5àÚäzÐõšKá:¢ÝìÆôk‘à6IlwlŽ*ÚýŠM%‚¯bnb1<, ½ÊÇüÿÆ¥{’{7‘«år¡ú¼§ø nÇ¥l(”›[ºTiRÍACž«bÈ»&÷C FY®Ë>˜%²¶Bñ×ñd v}.a¸}e ÷¨•Â5]Ñ.bE×PÑ…ú»¥þM3ðë Šá~±Šá~{rý‚c!œ ½Sn4ƒÙ²o:²à quRå´ÐhŸér9-Ñ::\&Âu±˜³ŽT+RáT{‚ÀÏø  8ƒB Ó¸.³‰hqQšº@,ˆ ŸºÝ50žuA@®õU ´t¨m­¿žÏ™jö…Ö)_ž©cÃX0—|³‡1^R¡c +›“Ÿç̨ȗãÿÁÆf­1•FÒYÁÐ,ÍÑZ¦h4f@³%i:Ñ›t- %©¾)álÂà +À"MXcœâm5)+d#¯GO˜Œ\c#qî”LêUÿдøô¶+ˆë$Ó•KxGl“Õuù-ß¿|©‹H]/H¦þg0 5¾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@h B³rÁxÞ³uum·éDÓ.)bk +‡œÐÉ· Jƒfʦ«‚óÐÔú8¦O_%’SJñL›(¹–ÊÐ< †–HȉÛÜ5»?âŽzA܆’WØ cŽDEÓƺö4Ãmocdü'?ÉÉ¿ì®7Wì1¤UÂ|\„Äp9É$S”u…’%&m;ÓŒrÅ“=:ñgÕ¢ÑÞ¡Åð®hç²îÞ»wö^¼ä’áÁá¾ûVÿì{¿š¸ëþý÷áƒ0ñ}YQléãá}ÈKñ¬ú/¿êš 붾ýÚÍC—nøÛWïìùío÷ ãØCguvœõ0Ò«¶5²Òåte¬ô–ñúkÊ\€† ‡Š·KRyd²¿Âó•Ì¢”¨©ø—Ж3ùá–½G\2ã×rñÿôksþ5Ùåø×Üxù”ëAšñ²Oê`³D§†°©ƒJv’¢ vРYO5¼k‚ëÁQu8:j„`Õ3e)mÇŽ•6j–XI†FCE/¨–FÞ}\í2;ø›Qî4;yÙ'ÅÓ,Z“+ß/Г¼G|$ãËOÒ.2*Êôø!¨õš£ì Zts‘6õð¨òâ]ô¿~¼ôBô¸„O˜zŒÆªL*my§øžÕer©‰eïðN³‹Bâ ºŒ: ÜU.àxéq+ù°ô$-¢)áuB™r€¿'^GÑ)îAjúAØYr+áÇÈ#óÃ¥*º«Py{8¹­¤×æ³Ë>™øJ«±z±è€~âVâ·å»XÂàJ4JÙ>¨~{àQš¨!¢¿7BA°ãt–o3‘/øxÙüª¯w²Å·íÞK¢Ûü!áå)-Ú㶀!Y«Ì‹ä¿"`‰ÈÇœÎåÜ&çç.î9n’SÑ\ÜIø×… +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=­g%’ý²'A´Š ·‰;D"*4wÌí O¯¯O— —{ˆK’£ÉÑЧõÍ®tRvNòñüŽIÙ¸k,1–$7g7çˆo\_ Äo\ï¸>È]Â.ÏSúçõ²8Fy±†$ÎE“Z“<‡^]îåJB)òBR‰¯øÐe½""*)LÛ b¾å´™ˆu™§2D7ŒYÉL£¿M]ãgÈH ž X›©ðÆêt >P£€·)>P¯*þ®˜TŠh~ø¢‰ææ\"Á¼ŸcÞ|sœyó—08þËÐpûïòy¬M„ЕÜáPè¢ßå˜\‰¤‰aùáa +a(ÁR¥,Ý%¨0aD ¯P +ö ˜J™”\k&£žÀž´kƒÁà" +º_zíÎúúúZRñî†v]ª!æÔ×Oì#"(=¬‚ʽ¿¹Ÿ3g_{×¢m»þÙåZêr½=?Ê65}Úܸ|ËšƒWIu»‹'ž5Õ²gÓ¸ùSla_€ ¥k$Û¢Kômש ZÙ +Ô$F‡5hEòœ‚ÖÖh ­Í€,©>É’:.E¿‘,ÏKËýT#è‚™FЩ6z‚EU §S¬YàÍè€?ƒ‚D; ƒžÁfУ bá÷ò’ï%‡¥ïôgØEyŠ%![;Ó’8Õn@cñM™ß׊^!U«„•3ò|‚ì®Q'a‡0ß%º\·‡DÛÓÅ"oDºžG¡NRI¬óy¯õªr_°Wbll¬D96~ +ÿ| ¦:%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 ‡qTŽ‘¾ ÊEMHZB!Y˲Ì‚=;³ #Ó‚Ks2ÖŒ —¸Œ†Î€qp¯)£â…ŒŽžÚ½$3‡ß¨p:<ýÏm™(:Ý3+“)öŸ»@Өр§À…’ nǪ2úãXR¸”R8šT9*É3€•"éßt/J•Ó]ZÓÃFry•Áî¯h¶ÿ¡¹ÿß_‚»¢íóç·G‡æ¡¤m‰Ç³d© ,%n8q\§¢8•Ì@R¥Bñ¼qþü¶j(6´.qggÇâ³:;;ïZ,v¦×¬Ig֬ɜZUµåÃU‹üðä‹P2¢ƒ@“žŽF£­AzŠèkÑ£ŸGUQ[aò⽘«š;Ù@¿H’è%vw]•Ý}X’èƒ3íN¯L¯K˜þ<­Hû +C¿a×4¢÷·xnµX#ØC¤Ð}S’c 1ý¾©Ê=%-"8M‹‰Åž{>ì!A»g ‡ìAwýɨ¤ÌžºmY™ÉKï’xé<ÒEÜ°Ó'ñÊ[g°Òÿù©Ô'\zÚɘË> +8`&/”HªÞoíUWíu¥‰EëF}Þ’X´‘jŸjé Ãå7Ä=\’Ž•D,•Þ*:íN©oy¾Ò;ùD=ÄÜQw8Ãò0ºiDzÐÚ“¿…äm‘z'ÊßßUò¶¸ë$o‹sÊÛRm_Wmxª}½Kj/|Kû©ßï’Ú»QûþÀÊÀº  +“Ý%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²â–×hdrä r«Ü8°\Ìi©à I½°R·N·IG£#tV*×)7)I df¼ ê£à¨›á ÁmÈþ‘@§Ñ<£Q+zvß71–³ëx>ÿp„ +Êˬ”ÚÚ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ƒŒ¶?Õ\H ¤]Y&­õMÇ`”ãUºð¿CGØ×Ο¿¹9‰Æî9‰ÄÙCsÏ?.>â³»c±îÙX;X!N²_/5&‹”ÃÁ©4£QÕgVØ ­—‰µQ¡]èH!£Ú•µ#ûl…L&£ ¿ÎŒf·J¥Ê ú1ø ±xÀË’*×Øi4*¤ŸæMäQÅ,#Æ%íJ^åõNQ*A(‰nè%æaÈOSÛüÙÑ u«£t³škìÅ÷ðݘ_¶RÕZŸå§5Z« øÍ='ÍíÏÑÜ6 ¹}ŽØ9ÜoâH’ꦈ5ê5šK©)Ùn£Ž u5ºÛt¤nÃr£’ •5ÊÛ”¤rõ‚H1À·Œ7€ò G¼2¿Ç¥ù]šàØ2†þ@ù±«Akbuñ‹“f8ù¹4Ãyö±Ò G;Ï´ó&´ó¤¥ç”¢IÒþþý‡úÉþ.ïY³OÙ³^ü€,Ê ¨ç™’=þÁ$@²Bú õý] Üë–“{½…dEQº_kù~$º’e+|Ð'ÇÄbÜÏ6C–£^“î•/Ý à5¶Â!ë!+aµà©§õ$û+N[‘åcD?yˆ–•Ïë°s,­W*´fu]­×a‘ûmFN¯$ä´Ü¶Ï_ ¾íò},ËÐÀœ4Á$&Ÿ›ÒÔ¸Õ|ý”Õ#cK; Ž>>^ÁÖUÖ3iT–ç›,y0-föÛ*‰­P¡7Oó|3Ïeo\L8­z¼´_¥åPéDªSØräVAï;9!1Âoõ |$Þ¬ÚWÔ‘®OÎkX]Uz,>Þïn´$ø”û¦èM©í ÷DïMß›ÙÕ°«éPá¦w£ï¦>kø¬é›&“*µZ'¬óêêë^½‘­ÓéœÆ\wG:›uv;{ì‘€·%`ìFˆ‘ðªÚ¾ËNÐv·°ÛzZ²aW½®~&‰ô#›Ÿs6c4p ÉXÃ6¸%"l»ÄŸÎýfd~`?DÕÕX‘BB‰yh’ÜRU¸¡ ­t:%qˆd|6V]WÞ·VU|T«º%Ëñŵ»úë\_¿êÚb+®é>ÆÏ?¸ÌêïðÝ:P|õ/¥Ï ê'’„ÌLëÍ2Žbîâ¦kûÎ_Í?–vJ€î‹îÍ/,¿kAë’ðÜâ|ÔXO£ÆÈ^¼fò²ÙGÈ&o‡ +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—òû.‹Ó–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‰#Ž^Î|@Õ¨Q J¥qxÄù¶ÃX Úßv¼@ATQ¿Mq(ߣy›*}{jÁÃàÖÃù(Žo•aÌ_)‚ÂcFm<6ÿ)¾"¥Ga²¸”¦&ØÔ´¤ty%ºŒ_arÄ9ƒ +Õ£¡†ŠSñ 3]ÉZ¤®}Më)Ž·@Eñk3ϱf¨„r ‹A5ß@%ªQ+(=¡CÍ”å«J3‹Ú£É¬Ú¿)~Úó2Fu±†^ùë}†ô‰ó Šò ` +ÉŠŽŽŠ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Ãq¸EÒ3×Ò7±„¹FÏ’Œ’aÂ’¢Â%K + _RK\í¼š:ðIT’YR’aQWY•*ì\,é%F•¨ï%}…aEKÔ;aý½ôg;ýEÀ¶7`ŸÂW¦:Àq H‚O™&E€K[b6± pµ'ÞÜøVÕ”e<ÖÍ3øPx]|:<úÅi@`{â[ å@PL*·Þ´c„ a&懱|øÛ@Ç®@gg ’yQÕ@ [,˼¸ã€´èaz¾ +ôaÿ³€d̶֑̯𩸠Äëi"0Œò<ôðpA9‡÷F°žÌ±Å:2x-óMàæfß²W¹i@þh  (dÛcŸŠÙ/ ë,eùq_(ï$êp2ÛžÊû§±ý'¦3ò€YÔÁ3³€g™÷ÓÏ ¨§y¾@õWFý–±ý²Oùlw~?bÁ¾Î§žÊ©¯rÖSÎ2åg€]ž/ l  ©·…QD±€¨!.‹:Ë-¢ž³­Å”yñx‚r-f{K˜·„v|a0PA¼ÈòK)÷ÒÕÀ2_¾¼Jý¬h ¬Ü¬âqÕŠz¬¡Ì•ëñÆìF¬ízw¬{x+§ëùVM]n`½'.Ôc“s#6Óîï¼¼KŽ¼K¶¸Ôù{Ôy 9ZCykȃ­äåVrpu»å·¯´‚×>l^Ž;ÈgññOõØIwÖ»y}7ù¼›úÛCžï¡M÷G{{9Û˶÷²O{iã½,¿¯A{í›IìöÓæhקoÅA^ÿtØM¨kÄ!ÚóÛ9Dþbž£´ÕQêöèà rïØÌzÔ¾¤ÝO°“´û)r䌜ÿ€`[_›4hРAƒ 4hРAÃÿçvjРAƒ 4hРAƒ 4hРAƒ 4hРAƒ 4hРAÃÏ:êz0蕔ζ:e±±5ûWýô0À¶°ƒ=à'8£ \à +#ÜàŽ¦lµšÃ^ðF øÀ~ðGD¢%‚ŒVh6h‹vh˜Š0„£:¢:#‘ˆB4º ]Ñ ±øâÐâ‘€è‰^è>è‹D$!)0£ú#0ƒ0C†¡†‡ð0†cFbÒ‘LöñV ¯cÞç؊ãØŒ7˜R•ð¯xëðžFÖâæâÞÁ›¼r +¹_Ž™xÊ‹E8YxÏâ%¬Â«¼2‡ú}åøßá9žÏÅ7XŠÕ¸„‹¸ŒW°bþ‚,<‚yÈÆv|„]ø;ñ ¾Böb7ö ¹¸€2À>ìGþ¯ñ +BŒAÆbŠñ…%‡RŒÇœÁD<ŽI˜Œ©˜‚õxÓ1 Oà÷8‹s؃!•<0²§v´˜reûL‰(ËÓ˜ÍæP¢¹”k>`!c ^@þˆ)ÇŸXßrÊúgjð5¬¤Ü«©Ç5ìëÔP•ª··Ùj5[Úˆ¿QÛ›©»w±…š~ŸzßJÙ·SQnE^Eν”ïÒ‡pŸásêìïøÇP‹/i›´Ë)êú+ʦèàÎS§ŠŽ/R«—ñ=~À¸‚â'\ÃuÔA +ƒ„ !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ü™õg"OÅü1S,µdŽÎ“i)‹sîÞ•ßÔ½‰x!R8¹Õ õæHå€ÂÌ>(÷æòj‘jˆû¿ï¿Sò7$Ž:hl2C?“~G~:ŽÂû¡?k3”¾T?Ö´ÝùId›ä¥é®±ßÛ;Ø«.º¼Õe¼…·˜Òd»Ÿæ®Ú‡ðTñQÕ‡ÿ%À§oÇ9 +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 +/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 [ ] +/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Ðz²²€,˶\Ûö\φÃ=™«@„>š '>Ú¨ïbènò ôíZ9. éx>†ÞP 8„v—ÃÅ­¤ø'e¥àì>1²á<íùàfš±b®•°,×BÃíùà.èÓ&Á‡ÓÒ{–çÁ)ØóiK‚S°çó>Áp-‹˜L<ÜçC  ª œ»Ó±|®Ýž@?þ/˜L×rl׉[q8™?®4€åÉŒ‹£b¹pÓí94ÝÚ@â ˆ=°ñŒÚylèß +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•·—¢Ø¾)ÇÒA  aåöu„HôâGÏSmâû.a‘$ÇÝ°·•_‚Blï°/ ~éŒW‚_J‘EGÓ@ç]Ç×­²ïáo:ïf›î²ér«ˆ–}ôAà­rÙ]™uº½c'ÉK‘ƧÓØ;Ó5ƒø ±#4[üK׌R üKóZñáLÒ×»PDïg@w=ÅGJ¨FŽ£ƒ6@[°ú/T#×qðVÙx¼Aíp_î¹UÄ¢$ÆÐË +‡Û׿}Z`ø¾sô/e1ä@ÃçÖ”çºpYö _n[È׆+&Ó?úÃy¸q+Þ-ûƇ×+‰ Û…âpßøÙ +ï–}×N“îæ$Vÿ÷]{·tãká 4À}7¾kM,“"Z˜n)×ò൱oâ9дsÓ׫eǼÀÓ.U ¼,wüÆ[E(!¾}´ªÍÐœªІf·˜ÎøÑBÏfBGÏ8CÿÛ%B°,® µž}ÿûQàݲï®Pˆù¤Öbåaß]eBGËL†æד*$ VÇÕLæü6 +äBhÁ+¬®‰ Èsüá >T x·ì[’”à {K\dGkö<Ü’>Ð2ys&ÅÁLˆ€r|ß²Ï  gþL;_\2ápÏV5€ÖlM«!Žícé»oÍw +„¥ïºÐL">¯²}ë¾T ¼UÖÿ S1)±çð¼”em9¯|apù®æFØ2Ràì¯y[¨øYž˜&ø×í¯¹ÀjÖC +1±,¾ à7íoVnÝûðâ–Ò.Ëþ{ŸW xÌ÷?ø–4–2»=|Zö?ø©´b:CB«÷4.¸ý+æ@O¿LøßÅÆs±»kÿÓŸ+ž§b-D†q0f1ô¬ÁÓ²ÿù|¤;á{G+Y!´T ˆÞÿÎÎÐà²ã®ÆæÜÿηÐûÂáÄU&L›ˆ8 ¡‹ÿÒ§Ò}š  H¬ŠZm}ѯ ×JøI,Uöq¢áÿBŠh—.j/‰]Kû¿ø] TÙ`3g‹+QãôÜ`‡Áaÿ¡õ¼ÀbX×/ð¡÷Ž h~? {1¡n„ÍŸ4€Z¼ÍnÁ¤Ó'ó@‹¯ÿRO¦ÐAââ(À#u àÁ>Ðî¹` +âM@Ê‚êÿvo+TF´¿þˆâ'Ä=þðö“.ð¢!lº‘ªÂ.“Eg+<ÁŽ‹/Å„Pµ5ÎáÇly/È)Ÿ.4º£!Î{M |:à}ÏƲbéð.ðö@§ðÍI7‡ça§ÂSÎW xZª”6Ý„øÁ.¸‡ê(¼ÍV:ƒ!_L¦¸¯14Ràö=XIsq8…¼O`½à`¥ï®ÝÁÊ¿*EÏÁʇ3!¬û¬²BºLÄ‘žñƒU6)œÌƒÕ^IOe§°°?Xm«ááªÿ&dÚ*~»àVß“ ýÂÅPFò§Êµ|,UÖh«@xÆsoʹ»<ÍKàÁÜiPí1¡±L*öj¬}“ ´€'3.Ät +«µk/Ï„°|°n{6I¼À»†×®n\ðÚ商Ž3ÛñX=˜wŠ ÄÎ<’ˆb™5Ð/PÛÁ|¤vJˆh¼ ÚS ¼ :]+?9¶æ­ì`§© +„‡ë¼€ØIäÊçî¼Dà-u°ó_|Q»VÊOà;ø UÁ:õkVIÕ ŒS÷@§IK1aÑ“¸ôãøé2 8~Ë?xnËXèŽw&vðÜã„ ŸI»–,ºáp®S |îFIŸ˜'>\sÍáµÒºl·Th¬”åzšçƒ—0€n¸[NØpq?cÞ°Tð¿÷Ƙ|4Ž £;yôCvÍ>6tè¼E¼}ÅX‘»%‹¡G„CãžeuMè–w´&B›  ?d^Ü+n?õºñGhêr¾€<ñÙ ¬Öšú”Áµ;4«R,ýP$†Ä>«¶tû!y•Ñ‡ûïÚ¡;j@Kob!F/ I¬þZ:Cð_·zO,tÇ»žÝñ‡žÊ2€þ:;TF…!ac_ô¡¿.V è>=ü‹|K8Bµ4Q‡¦@pÞ;C +1Z`¡<@ùtxïBò©¬B³}|•‘›ÊƒGª¬BóBßTVá´ni!§@)0` «Ä!q;ác'º€r3!¨†”U,¼‹¯|Ñ<º×jÿ¿XøPä»<º[Ð~*«Øa C]ŠðW@'*ºƒË*vº,ÆÏ;ò Ãï4Þê/Ý8¶ kjZn ¸Š +Ží{qx#èZˆuñÙI'q´Ó“§`À"hðM|Ì)˜ ÇahŠtÝE¬<ÐÃc. Ñ +„FYÅéÍxY¼@(Â=^qz Âó´ð¾¨!z’ÐnÐÊLÚ-em“|`,Ûš­²è=‚» Rq6/°g ¥úŸTÝù…¼6Èêv4Û·ÒÈo   :òV üÃ0dG@–ÁÃYéÒƒiÕȧ8N8ܘŠ +„ÿº ¶N¬‹Pà뤀<Bn¥¤ÁåA“ð^@ݯݤëc¡=!ÆÄ>i‚4Eºà(4áh. JSvgBP³/«tkK©øQä¥ÐìñŒßÚÖZp˜ . +•ó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Õ—¯WJÈH­øñpõ?2€Ü'îêÄŽf¡ÅPL¾& ƒ„œèX­ÍŠ½§@pûf5z—TôB€ô¡Ô¾exm˜†¾CµU (0²’ò¢j‘E%Ôz²’“9©Ê²zwâ÷“¾ƒFVo×:,ïal‘ºv´ªB U©±'>‰Sð;ÜtUjìS x¤ªÔž.‡³Iا U@3SÓ«ùŠ“÷ ëUš^¯@ø›ò»§eÛ‹¼md1Ô[àW)wf’\X>U)øÀ*œ ûâXAŸ½€¦(”™UÚ½#Ô\ +"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?žÏöU..3€ÆüÀƾÐEp‘€~Q <WæÉá(˜ÌMÁ(54€®jÏâô#üÎ) ã3!ì/È.>OsR!múŸ]<*¶Tviy¤,Š³OÂ7õS xZ²‡48n“Úî­ûf1Ô\ÐCQYöiïË­(5Þ*Ù§}¤@PWÉ>/!U#±ã^ËÙçu5€.¨:-1øHe_£@ø›Faȳ’B£W~ö¨±ÐEw¤UÈxÔ¢¡yÐÅSå²P¶Ÿ‰ë ¡[ÿu£Õ5ño +Û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û.áRO§‚­bÙ‰@…Äáén™Öz²wý›Þ*BÑÆÆMö® +‡«új'^'x‡ËRõUÇú½_ùh£ÑŸªþ^bý!wfŠÌIa&AÕ¨ê_@‡ ¤I">:áYXØW=Ü^à~:®âüJÚqzkÀšýq(œñãê7ee4E¹Bø½å¸ú-nßãœÒ‡“Òˆ¡[ð8gƒA²ZÖ.v0¦H‰Ä®¥jY_@U¾å#åÈÇlôáÕªü @píª5Ãæd„ ù¥&cÿRW™’rRGî‚j]ï4€ºÅä;â’öq˜£€@£›„up ˆ®6º¹A©RÝ•97Éàr±,¨îþª@p2«w}L.‹cÓ­z×'ÿR÷¹<™BAö#/Ë!4_à,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%^ã) 'qç’ÔL¼eý“Os a˜Æ5k—Øk¥® ¯WJùÄwKÍÔ¨‹ÌȦ‚qâHaçKM®ã÷ÿC=Z°[С0,¢köh£@PªYÌy@tmXûŽ¸¸§á]0@¦®ÄÅ6Ixþ©9àh7NJÁŒÔÆ ‡ûÙ* xz4v`TõÍ€\¬þ×,c9”˜‰(£ápƒ  sƒ8 ›Dgáª(º@ðÚ¸Š‡ Bø*«9â:Hnß•?r,˜‹+ É sqËj^ÀmÈ­o%5¿tÁ#P$|¡Ñ2¢#x¡Ø8£w@—M”æ¤ÒäĢ粩 +„ï–Ëô£ ä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†?œ‚]#·T­5€†ÈêÅäc¦Œü× ¹É:)Ì MY¾øp(ÄrOb>“?œÊýáÂ0šm)C +½ ¤´æ¾Ë=³Y¤¹ïrÏä +kŠ|Ê=ó6‚o@¹#ñA™°Kð²ŒXbÄ“éR¹ד;òDh”,=Âf}µÞ]À&.Yï üx•;º½a!vÙbbBEv4.¸ÜËT <ÜäS˜« Ƚb á­2¾(í2qÜV!sÇ[ +„×nüÈpƒÚlø˜e]s^Z­µ¢-CèB‚š}îÔ*¼Àôª[»©Õ¯Ý-² +½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½Ñ&Ýê'é¥4JÖ… +„g|«¬H2®.%wë» +y­‚¡é#åº5„†+\»Z“÷„J–mEsÝBh¿áá¦Ôfc9ˆ4Â×F­)õÿu³i“DˆU,kÍêb͞à ¶wR¸bD­Ùó +±ZwÜÊ[%)´‡HÃîŽ9ÐœëÂe×nd$  +7]­{ö.ê¤âáî9dÝ/ã0׋Q!y¸û‹o•EIv§¨d'6àk-ê¦@x¸e÷ÉcNE<\ÁM@(^»‡d{x ´kì»Z½ª@ðªõÈñ,ÄŒÃÕk=â@+ùqBÌuïæµV~¤@xžž|ŠCQÜ  žñ'×(þ¥Õ²6=a::ã¦Öêñ&Ð,¹U(ˆÓÇ]Æ4[ð~zú*‡^ ±èyú:¿ôLç¢ +šØB®Á ¨Öšñ,zBgKáµZk®6€ÖÅÉð¡.™Î"¨õÆ3¡9iÅ5Å·´Vðd~Ò'•PÕ»OÊ  OÓôÈ驹>}QðÎü±//K’‚±^PëÇþ™Ö jþ }8}/¥ч?R x‚kg‡µ»‚Æø-¿vv/¨º% +”mŒU!×*x$ IS2[@'*<œµ¿’æSäVðSøíµöWƒ  CȧàD,Ÿjÿx’ô{ÃXèD§BPŽ×þ½©´?Ì~NÙàA‡Ûÿ˜Aý©ö¡«Fž•ò“XÒÕ>ÔDðÚ–~›B4íbtÒ±¡:ž¥C/½^à:Ö*Ü*uZN§± { Ÿà:­OR üKN–µMÄöÔétºÁyª“¸<>ÓÓû\à:‰+Þæuºg‡ª‘M¡PÔé^] ,¨3è;v åÈ·±×¨Î ø¨‡x«$¨Ñ¾ïêŒzôØPÝŸÈáÄd +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ÜoM~=´9i‰ñ‘Ê›ü¶A=3ïVt—$‡¦g¨€6@3Þ`9N¢÷lÐÛÐü'ØwèPÃ#¼,yóŸR xÌóJ3)d«jô‚¼…žááîo˜a›ÛØ}šwSÂ˲è%©‰ö]$‘"„^1€–rC7Ð5±õš·t‰ôàbIª±Ý8y^a-6´òeÍ- ­3€–õŸ|ºƒßRyTT (zòá:4äÐÔe‰ç=ò’á¿îñ'B?Pèlœ>š÷øS +åSÞÓ2ð=¨”fᦰš¨@x<íËêò¨û¥gú)þ¥çÎ7vÂr<ï¹sL 7…³æòž{Xð‘zi#o_ŠZÒø3ó^Úbm–Ù;IòdEKChôZørãÝÄ¡‚œ÷Ú? +ä¼×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Õþ”«oi½kõj¡@ð6¯×¢ˆ—…ò[4þÌz-:g@šÌ«zÛbÅz€h\Kõ¶?¢@P/¨÷þR>œvà5‚[¥Þû@ eu-I6Ø–ª÷Áp‚[¥Þ§Ò¯"ëEkåë}zºÁ­RïS.ŠH¯æš¶„š¡@ðpÖû|(OKf5¾òë}>ÜÚ-¯¨ ½sâ]°{¦ôýW,0|R!ñf½ïw+Þ*?M MÊHÐLæOÓŸ»>bÞÊ¿&¥Þ?Ÿ*Þ*‡³jäP6˜f +/Ë„ð›býÊòU–¤ª(8¶¶~å‡nºú5‚¾nAð¿kiª^Ö¯±5Âr¼~­wb¡gÔ‹fÓópµ>0€êüÊNírâø*«_çO¿TWöç Lª ?¼în‚R¥~Þïòp:^Ч::êçýeÅdIŠý'¥/pì}¨U]vãPFv$·;„ê+”õ[sf(E*¸‘Ž^üá­Ÿ3€ +Ÿç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¸¯«!Ô ‹ou-äá( 3¡®k‘Á¡A× =P¶íhíÓp¸ÉP÷]Rýw“oºÝ¿4€z†w°øpGã÷mÐóOÂSзb,í>f€ðpAúñ A«ÓW~Ò‹”‚æá=§@ðni0øt6$Ü òö Ÿ¡@PyhpŠŒÏtƒî£I,Uœò­á¿îLù”âÉ.Xˆ58³£á)!£ONPÛ›$ FÜg]–;§îí‘Îg<Ü…½ï‚QÒFHR5¢h1RnÔLèÒmá1'q´Ìäá.}O kpÔU\ê!íøøYµÁ5ë  kËp*DÊá…Ð +„iêÁôd&­H!4†n®¤@xY^Á==jêg6Xxµ´HN§èqßÁý^´Úz&O*UÌ‹<†PÌzs}Z°úN$Ò“?üÍdžb¹ÃÙX¦N\Õ(–{–AË=ÌWU>Õèã±Z•ÞÁ±)ËYñKÑ»*~xŒMyTð7M“›êÐP=) uV xßŦŸÈ +2-q;bcÓOU <Ü­­YD»Tz¦±[ ŠÃØ\îÏIùwn ŒØÜ_  «ÒQº®¥ÑÇc žQ öÝûÐSx…2êk²zcL3€þüž +Ô¥US!öçÏÐ>)Åö¥ [@±}ÃÎõBW,L$u…?üpÝcC ·ÜÎ[ŧ:Yøni¸e®Á]ÐðÕóÙXNUáÎløêE +wfÃ7¸µ]£faAÃ7@ÛF³!A™Æš¾$ ·5€>|ŠUmÏv¢ <™>g}ò2+4TíPSm¶á'›  /ŽÔ·£w0÷Å;Ð×2ÛB˜ÝôЇ›†_÷3d¾$®.©á×'*Þßq5"aÆ­HÕZ©@ø—~º™§ÀŸí`ÑÓð§[^@ ËgµV\@¾ÅaÃßZ™@ò–¢Ú]Ô¡ÿu¿Í1€þQ&”cêéÕ6üc±ôïÂXèˆMé²Rþû€áý´7.ø'Ïäáö.3€­f÷©'®2Çj7<ô¬á_:,wE3S)üמ~l¨QEõ¢Œ"_Ób«QÅÐq½ÃÄ9BÕ¨Ñq}êtrÎçÉ ìiÚ 4ÊeÕ»dP¤nݨÆÂóÄoÔDjÑøúÿ‡êÈpùiÊÃÕyCà}×(«3P>§=!tŠá)¨—Šh1™6Žcm±;&Ô€¯Wê±kcaߨ^c‚zA£†ï³BÙϚdžF w@ÒR­¸NñkÔ(¦@x?5*‹…ÏT=x£A +uºFMdh“„ÜiJ6jržáojšîvä…öá7½G fߨÙÛ±0À-áEÚÎópÍÞU ¼ Z¦”'ÀF­z@m*†Æ …KâµFmª@mßaU›œÌš¬¹Fmß7€ÚÍJ›¸bãál‹FíîP , ŠÚ¥M·À!?¼¨È*‰¥]pÑZ!Tª@ø—:Íåe‰q¡ݨÓÝP×Æi¥‚•±`íÚ\°8ì^5ÃàÒÝ-Ýs  R;L’ZëG‚‚ùÃ{ô3€zŽaU;I}¤±qÓ¨çPñ ±0˜ŒÜÃx¸â‰ +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♂]º¯ýÒZ4Í$zPÓtÕl¼è¿Гm3TÈHØGµW 8ãMFKùIYšjiMF?¦@ðÚh2¶:o:Òý5õŸšŒ­iMÂ5TFr¼É„±7, ÀˆÀ•Ž¡ê +Op“Ùaøž'Ž”&P¹ÉìÐ}ÅÃižz›Ü×Oào²ú¾6è„ÆñmÞdõg +·J“ç_gÁJ}¸Rø¢nòüVhG™%í5º›lðOÁ{òI˦˜@·†×+=€`‡P³e³oßÕøpŠ‹CV¨±6;\åØPóÊ\H– %_Óp¼yåPöN>æA¨öͳ?3€rÚHÁ<ñh\•ÍsÚ@µV³±LAæšê Ík=k5; ?œª9zš'§æÍ@ù²õ&qGóüÜ<¿‡A'UóB)zÜ ìM$€$„Ö@íeˆ*¥D¦tIŸÍÛW5€Ž¯Ä.J”㛳ùñÙ +„É›È +ô,ÿäݬ@ø—NjQÀ3õ‡Ã¡¼ÍOØoõûœ› S +Î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éÖüúû  ‰²ê=ò¥œ86q›O|Hð/Mº’UÈ (:Žj>éèæ'¤™„}øø%°ùÍOeBš›sIoJÑÔÌk¾d°Aã&ÿ¬:Ri§2ž‡ç)ÿ¬ú +ÿºüó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§ee Vd <+[gB¸Fþã2iÂñ“¶¦T}þãóÏÓ\‚= ·p\tþ×(ÔŸòŸØÁ +2éºýôħÐê½i§B\×Å'õAÂ;óiYÓ%M›Ì\8\/„ðd®yQG5툃‡[ó²A!ÿÅ i‡0–ð³jþ‹“  —ª°Ë$”èÃ;ó¥ãïÌ—.gåÁ +Qj ñ +¤îi¾)Ü*®QC^Zcm”!ªA¼ƒ­y ÍßxŸá#µI>ÓS¦ã¹ØRÌßô™´ùqÞ¾äÕôê ¡ÕÐÛ[Ùà¢ÒŸŽÎ{»á¿nÛçlHˆ…q4á{ùÛ¾6€Þ—¥çJiõRÁúþí +„/ê¥,¢ãÈǾ³<Òè*ß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×·¾æÃßXomý!T²„ºל»­?+þëÞ³ÁâAÛüáo/6€Þ _']²¼±ÁÕâÝÆ +„·ÊÇ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(o­P <\ÎøôöµýÈÚ…Ð5 +„ÿºZC䲉¨ö®µ¬uªáoª{ Vzþð±زnoè¼´Áe9.ghY÷‚ÖF˺ÿÆÂÇJÞ×@  z=ÒÆ2õç„Ǽe½â ÈÃI-ëOg…F¦Ñn¶!4ËjÀÅè%ÉKh>¼ÁË +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Õ&§þð®%&,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@¨,;}¤R¹8¬a´x“4$/­Œ¦œÈó7$f²ŠM\ +'³4'8þ9tš gpµV' N{Tð~:óy‘ÁåjJ‚´:ówh?±V£{*–*WÕ‹-jcÁÐdèêÌÖ,ˆ·ïÕUM °ƒ%¦‘œåZiMÀ#A}±4—âÄA +„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‘òÖ׿bM\Æ&n|ÃE&Žµõ¦Â¦W5|Ú4ÁÚÙƒÕZjÖ¥yk½³øØP›™;YDÞ¬ ·™¹KàÎló°Ì¹¡b©h£ºÍz¡ oêÞ®).Òæ… +—¥ÍÖÕépÇ×ôi³õ9‚3ÞæãÒtƒbX°¶ùøBÂ3¾ã‹CÚxš›³ÍÎ +&Ðç¡Ù-î1Mƒè6;¿:¹#C»_b%˱¾¦uT›ÝzÚ|/Ë(‘°òá‡Èú¡Jz¸ h÷C5ÂþWÙ¡œ#[„Ðæ§- +„¯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²Í*mºLì„°Jð‡—æ@ÞãM—°…ꀽÿ>P <å²Ü¹O³,Mù²‚ò¡ +„÷Ó ^òp©¿I¬d *Q üKƒ¹úžXगÀ·yÁà¯3!ͦ²"}8}2(ápCžP <™C¥Á%Œ-j´†Ÿz †þlY9=\ó¹%ÁXš~Ôó?S 8ã…¥Ÿ3DEì"§%„¾Î„p¨\aùűб/60>-…åcL ca¶ï9xí +Ë_΄ðÚæ†ãôH@ÿóÂÁÿ(|++žÌ³}‚ò©pÄÝÒµdÒ¸' +ƒ>G ¼v#9IO˜IqGcÀŽüÔºè¥ÐÑAÅаÆZxÑFÂÝÅ+yÓQafM `áÅ«  1›bégU/M·Â1¯@ãd!`ùš>…㊠ +°°êš«)'\8¾‚ ô’Üt¶G“‰ƒ +Ço4€®^žV^¤X2øÕ)´ ¯íÆÛ—ÚPiÊç^ÛÓº®=+YVP./ðuÇ+´[ +¯—ËB àŽ—Âµ¾ ¯ï«@ø˜ß°Ÿ§@ºãñA¸áaYpãèôãþÄÝ—+þënú¯¼€¬À©€õÌ›f@“ÿ Å!µAÁU, +'ÿcMë* ‡ÆŠ<<òpÓNP |›ÏøOL†¥‘ÐДß(œqŽááfNge”œû‘cB3  ¹ó(Aa³¶¦XáÜ{Ÿ»yõB‡•/ÓÌÓ¼† +„çéž„öŽ|ïÅÒ÷ž. +„?üÞ¿ÒÛ7åDò[xïÝ«@ø´,›xÚTy».~UðiY*Û\&‚Bך‚–…KhÙíRD“ +éiJ.›k-¿(†ÇPÉs<Üò1 +„g|Å»òz%³ÛÒt®øÐz\ž`r2'|MðÂÇ÷(þëÖ4”×+9ËÅÙª…kš(>-k›±+€šrkÌîµ-  uoÅÂÀ-ÇÓô/\·]ð-µáqv㈶±‰[¸á)Âß´±r†°×˜Ý…«*^–ÿa· Œ¿Ä“¹ñÜL;ó +ß\ÍÛ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/_gmû½ºT<±k·ù6Â3¾µ¿œLJ\ѵj·µ\ð²l s¸ËT3™[/0€¶½*]p4¶¦,W»mo@ÛO`‡ñÖÇÛmï­@ø—Þå'ñ ™¶{÷[è}KšI™ÝšÀÒvï; +„eæG“å­Èð£L».R ¼3wÈr.¤®Qy ,3wdBØ»ÖnÇ%dNO¬Ð´Ûq›á#µël©Ö®oM%©v»FdBøæl÷ 7À ÄÑ´"k÷Í.è7~YL–¶ûí'hãpû†›vûó  Ã\æ͉۩h!~îðI +½!í‡Û—^U=\6°Ýá +ŒöU=^îñVi_5aÕìσ‚4nÁö5@Á+nPÆ}'y¸ú—@7/‰…A•ƒÀÐC™æ¯ûY.0%úžÆÓþçÖ +„¿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µúˆ—…^"ÉŒ<™­>Q ¼}ÛIõŸZ³Ä}ƒ±C»˜áoê$¯WŸ²"MOã¾4€œþ|Ì=¶‡s@‰êl&)ÕV³Ÿ¹P17£d(×Õl•â‡M Î7ZŽGò€x +úTV ¼À}wH!&Û@b‹ºCßO  þ/³aêõŸðdößd ¸¯ JŒ$‡ÐHFRyô˜"Ž¹f¸ý +„Åaù¢#Á¤òd–?¨@Pê0h1»»Hyд÷è0èAÂ3>äI©†zìj#: yJðpC–[ÅN…†ð_7t…á¿nØ+±0.3<™Ã6+^»ákøpR@’&Õ ÃðuЙòV±©@Ãîpæ%йÿ Õ*í„ÖÎ=×qZZÕöÜH¾y W x‚‹ì–¼Uh"UÃ+0ÔÖJvŽ…Oâ~ôpòpI×JՑùA»iìD/JÕ7[Š4q‡E©î‚¢YANRB¾ƒ‹zägBø.ê/ËålMÑŒ¢þS  “Ï`a§œ*|m|¶Äç.U×=^ Û’ic3˜Zli’ôŠÎb]ÔM*íNPñ¦EõÌ„°¤+ºä[)¢mrâh.ê¢K~P <Ü¥Òõ’)–XW)ºôyÂÃy’Um1™®¦FGј§ÞæEc øpR¢¼¦6NÑØ"è*nÀjŸŽóÊŠ®šm];?Tµ)J«ÚE×.P èñ+ºéŸô¦ó}݌ߴך$wA"(–ìb‹ºhÒ÷ÐLÇJ³©‰ =3·@wpª g!ÒŽ‡»cœ4GæsR8CRè¶xYæ<¬@xÓÍ“O)Iz Õ5ª-š7\ð7Ý&6{Ar,Þ÷¼kÝö¤$¶ˆˆ¡  ÅÃY¡ñ‚ƒ…çâ³OÁ’0íˆ.êÈdòpK^3€–ÞÉ!ðà,§¢¥ó  e_°£ƒ§&¤°hÙ7 +„ÿº²‹4 +~+Zq¯aù´2Áæ¤'fTS¤¼heèñ•¡âG X±!Qôø“ +„ií#¡úO­u°»«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=Æu×(|ÏÖ¤ûu|ì¯L‡^v\%íภÁÛ·ãª}Ðê¾iÅ&áÃcÇÕZ@Ÿ½/O÷ìbÂÝs2S&I%°t®€ŽÏÍ3€ÖO +?\ŸôÙqýÍÐkǧ'“¾ʧŽ¯ÙÐÛ²Æ>5/ª~¶èøöT‚·TÇ6ð1§‡>MÅÒŽl4€>/Š…Ï; WóÔÛñóN +oóŽ?žv™PÓj¨yüM/l6€Ö_('“ÊMÙ‘T(žÌõ+žñ 2‘Z{$\Mù2kChcÛ#¢ÇuŽvOðp;@›¹’‰Ca@ÕÈڥȺĚ3Ö‡w(¾[>š“VÚIB£õÑ<èã7Óî‰%¹Ãá>Þf} Xm +OÔ»ZŸ"â#Ä=#²>¿@°,ø&':®‡ÍIë›Ú +„‡ûæ>>$ 5yeÖ7(>Áß~$Õ5;x*Òûo?Q ¼évËÊÓ¹*í¸FWÙ}®áýôÏßá‡S¿L’õÏ^èÐœX躑‡ìºK vh×}ˆ…µ‘Ó<®ÛuW*œ'{k‚]&ÂPŽš“<ÜÖ® +„¿és®^L⮦«ýùè«Î,0< 4à !×ú†ÛÚT(b†ÐN‚»Àþá;žLzŸÓdÍÙ?ühý(_འܔ&ÊþñR‚‡Óþ‰k¢S¸¤£y"°zÑúåM¾ò)B# ì_¶)^»?f2”2ZÓtÑþc¶áÿ÷jV!]}5Gûßëÿuû6ðpqKè4ظ±÷mR ü×ü Vrœi\KöÁ»3!|ßÙ¹Î% ¹ÑÃGêà?džœŠ›XôBS.Á©øšAÝש¼„UH?hu ×ΩüÁµsª\—VC<'‰×Ω2ÁÊÞÂjH‹'ÓÉ~Sà;ÇíaÈ—=Ç1´O `uªq +qç‹-‡ /8ÕÞ7€j-…P+èœñ¬ÖÒã•Núžstžt*PP°£sé:çÝk*c%+E¥.4Ç|ÔàcCnË+ä‡éY),UÜ–W@­å-åilÞm½Ì*êɪQàÑÃ*¤[Tl9ìا¤;…/ ×Ùnuç +IT:…2½ÐVq»o3€†H ±¤)ËÅà lqf0œ¾kBžÝ3ÎU ¨†¸#zÆÂÀ­„QC¨4J&¢Òª¤üHo þðQCˆ$9Ž¤rǵŽ…nA*φ‡Wh]uƒÜtA˶H1îª +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Ýò¸nmJîê M +„?¼_ ¬>• Éò‰~µŠÃÄ`žqŠÁð#Ö<ÜàöÐI2Õ€\•v4R!„rÿu£–„ŽZoò‡Zf]Ámš(åS×’;qÅèÊ›ÓÃY~J3™Wþ÷ØP2k"«”*ñ´W`èfh¬Ôé‚2%®¦’yrlkhü¼ÐIeS«i¸ÀÉñ÷@×|”vé&Mò~òš +„ÿºë~qx1™IX5J^÷·tC©Ð8&¥éE¼¡“4Qž;±,Â*ñðAHN¬¥@P>%§ –¥Ûë²é“SN6€n¹‘•Q +EÑ-ð-“  i ÓF 0•ñ NNkfýÉ›.i‰áðÍ™œ¶Çš±•ŒÓTTNÎØnÍ䘬 Aš&(9³0Ânœä,™j¶ŽÂÇ|–£@PÏLÞ6Š·J<èÅaò¶K Ùi!¨ “Ð5OÎvOÁíNz2n¤æ0øíqhN÷Ðì¦YÒlß9½  {eT%…3Pr,þëî-3€î»‰e±íMñ£ä}“M …¼,^¬ þIÞ·(ÂÊhrÑRô+ÀÒ¤û%]eÉä3Z`zÀÄzfòÁ—ËÌeGš  ¿%—u2€K??ûšvêÉGg*ÞOOv«íD½øßìd½ÀFJW>TF“/¬R ,U6ɉ _³é6km~…Õ ß)6$’›·@oÜ“kj¨qt$߸Ïz[vŽu‚’)ÍûœLH³Çß› Ÿw¨š#Tµ“ïÝl}TÌÛ—ÔZM ›äG¥ +„÷ø'­ÙÑA 3ãš+ÿ“BèS¹}ý@ˆYظI~:Ûúf‹rĺ8ø'ùÍ%Ð/•Øµä’G¿#$ÉV |›ÿòÉ‘c.ÔH|•ýò¥áoÚ#osj¶'Ž~~NîÙfí Ìî@…Œûº#µwºá]°7ÌÛ §¢ˆC(„^P xR9¡Zk‹Á°òzÌW (ŸR/5–´PŽÔ§ ¡æÐ+Òÿä¹µ ÂëÔ+Mn•ÔÆ­lâ&©”!6IR·@›kÅÂÇÐ åCõÓæThNeP`¤6wS x‚S›KbnåÉGhÓ¥6—*¼ïR[dB*PáèR5S[š*þ¥­ò 3¨ÚIÍdn]Î3ž «E³Ÿ¶>jòK+ ~igX®3xÇaD©¿@»žg”ñÆwpj׋ÐWkBÁ*¶€F]K}õ¢ôC_¯ânøƒ  Ÿç±kɳ=7¥Jêç{K•ýõ¤òà$‚ÇP|öÇ/0·r¥p$Ú P°¦ö÷3€q=V* íÜÁÃzþØP—¬<‰ ´üð.U**œñ.9yÓÅmàØ!˺6ÜtvJœN¨Œv «¨þ¿Ps)é\'ðHui^Oàwa÷i’ÊS ÁŠ'³õ<¨Í­±ð‰ Až*øámf*Ü]ÚÄÂq»âçÂ.m‹*]Ú/äÃ)D§ ,íÒ~±T$í`7(èac¹K‘«@xžì—øHyÔ‹Ã.ö+ÐáJR]³ƒ_ø¡¨Ëá*™Ž/èš÷7«ÚTZ<"+0´Wà_×µ!§BQ¹"]Zd׆ëÞR]›ÈýD!¤Fâ_j2ÓJÞ-‡ žS4ÝÛ»&@=øÕRëtU/»r‰¾‚ç®k_îØL%Þ|MœX×¾7+^–Òu|8}Ô™‘?¼t½4 Y¸,Ô{'ïwÐ"Â¥Sºæð˜àA-…½µ]R (¢»ž(³Á¨ø«íEZi„Ð/ +„'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Ý"ËäÚÒ Ä!`Ýn¹L N×mú9¼,äûO`;¸Ûôó/ðì°èX"p0j Ëï‚;ÖódÊŠLøHݱÑZ| «kÉ ]¼»-¾ÜZ²‹7]RŒfi¦€“CÿuËo’ê¿cÉ´ M6¸+:âoZþƒáozx<æ”Úî;8{§ÛÃ@«¤éæÈ"%š]°ê>Âßôööâ¾÷"Ù…¼,ooT ¨EwÛÖBtU»šc¾­·´]&A6TB3Û{*>ÁþÄF Nk¶Ê‡¿:¡µÌ”!ÙD A5й +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“Ô$?Ðö\ºÇzf;:RAMO8O=Ÿ™¡@xžž;ÀGʧòøHõ\SQð_·Å’u¸å⦋=·x +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Ù¤´†Ðˆ)è*óü8Vz·~ÄjŸîªéPÍ8(¢{·ß­@ÐCÓ»S#6IðDÞy¸NMž–Þ§½ÉªvÊŠ{šX£Þ§mÏ„ðÐûvrzÚAY®„1nøÃoo¦@xÆ)æá(XCãêýK_ÂSð[5¹}éuÒ×dÓ÷þ­Æ±¡âJýY]£vêšP”âJƒ„â*Ç…Û—ŠJà)(®Rêúì㤴ãP”â:{ÿu °À -¬)²YÜ°±Ô”“H$ú ¬û7®@ðn)Ηj­K…Ù¢™ë<ù  öÍXDS“K‡¥·o©@xžŠžg³;˜\\´^ð/­Tk)$˜R#1t“Ôioº 0—fûv¨@ð˜[³‰KZV$ž.„ö*^»n7ð1÷É·†}öÅÝ&@½dÝ5ßq)™¦Å½F@Å;X’v¬iV\ü©áÉì;(TC„×ȧâ¾')”OÅý ·Š0'-¬þ÷ÿKð² ÜÀ&.õkÚ©ܤ@ø›?ņD <à ©âÁÏ@Cç²è·y‘àá†ÎS ¼ŸN/ãK1i'…uºâÓ@çÈ2JÃÚÒÔ8+>gL&¤ùðó8ÊĦK ×|)>o½aùtþ ¬ “[Pãf.>¿Xð‡Ÿ¿ Th,Êšƒ*dñù÷@HÓœTôx…ø‚}Ð¥kbáC6ÌøÃ/]g ÃúS¶ãGzƒñpc÷e@‘Þ` ]— ŸÁ^$º+„ª*^à©2kŽZˆåÅϪÅS§eB8×­øÞR`ˆB ÒðA¸÷3Â;ó öõÐû´§é‹[üÅI +7]ŸòϤÙMO´~$¾ „¾2€††+µÒ„ôÚL ÆÚç4Îᢧ+Ò%‹¡‡  áì‚ &3R‰‡¾Uð7ñ;CT’ÉÆþ‚>gü­@PØ÷9[ú})Ô±4õzúœ=Ä:‡ëj“Aéh¼ÿ}ÎyEàÍÙçÜӃᠡFÄpÓõ9÷?Ð(Ÿ?“N4~—‡“•-_³3'ýcMý'4“¨ˆæ˜OÝg݆öyq»Aý©ÏËùÃö8¡ÏË–áûnëËl,S £‹­ü>[7+Þ‡5óÄæu4¶yŸ0€vîg™´5G³Uv΀"u²úZÆB":ª…ЂcC%ÎÓ|•%‚Ì*øM%ÎèÖ³Yy „]2Zrëh–¬“ä­xGlɬW +Ö’Åls:¤†$°›¹dñ`hI]©þ‹HàÃ=^²¤¾A[ªdé:VµmJnÇZtÉÒ—  ò¤èâÀO)%Ë**ÞË?± Ž®|͇/ÿÚzbphp‰/×Ð)yâ$Â3¾J*£TÐ’jÞCqX²êlè)™À”t(YH# JžÊ7€Ö|ÈB,¨µŠJÖì0€^‘Žª„—ˆ¶¶ ¡“  Í»b¡›9éhK6¡@ðF(yíäÐL +Bž¡è)yí4‚PÉ;;C§‚¸Ê,œîWòÎgÐg%<Bº‘àŸêo}1œdRh4)c%_œm}=‚7GEÇðÍYòõ™¾9KþèÏÊCÐò¸•ü1ðØPßÊò¡È Š‘j +2õ­Ü\ ôí›õ /‹¸îíHîdC»  ãZʧâlº,̾ǵ5€ª·es’Ú1h’…úVooÕ˜‘>q'ŽAö­1ÛªYšÝÔÖ 'Áô­ÙAàÎìÛ@>6øbuÂê†r¼oƒW/p[®òLº¾‡T}Ûþky¯óA 4ÛH{Î{˺Y>Íùô­+çÒ÷æ: +„×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ÉjrYL>ï$åƒ(Ú*ýšŒË„p³Ó~M~?"0„7]¿&@?asÒÖ·Dê×ñs¨S5Vk©¿a¤ÆYÕP (ŸúÙríœàmÎÁš~ö>ÂÃ%&ðáÓI3á$¦(¼úuã"ÀB­õ,ÝÎì¶Õê+}ÑÔB™ªrA[ª_ß!PÿaáU&L·H? þðþg*ÞtdQÊÍJùº#5 ¯A­§ß€GÔ+Òº<î3ÂßtÒW¡™$¶¯æi®ßIßeBX§ëwrpZ§.5܃’®ßÉ@§4gqH×¾‡ŸUûÒÊ:M¶f šx:šÖ›ýN»C ÐoXPØ–åÎ-ì¤ê7¬@ð7 ¯ÃÇœÊME +‡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ÅÃ=¾ÂÚ!s“RA +b¤~&·£ƒôC¥#®%²ð0”mý(ç)$UiŠõÿñ?П5Ó& 5Çþg]‚B¬ÿ¾”üpºòé¾ÆP·cC²;…J;EÐà÷»ÙŽT7Ì£&g—&és@Ý‘ +§`ÀµcyÓ¥¨Í Vk\{•A=`;—;§+ÑÖÜw¶Ï0€>x—…“iJúøà#è›Î|• ÞMaßá€o\èÛwäØ´ƒ]¼U|ûÁ=>`wøš›àµ1`÷ +„—å÷P÷%\¤‚øï]ÿu{No:¡Aâê öþ®@Pª 8$›1§ä„Ÿ-zçØPYÖlHPŸƒýOeY?+œñ²j¿ÆÒO–&j©¬Ú +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¨€5 ngTYÁoP¡,Ý4ö¶8±¬p“áyêp‹CútM’²W)>-EOòdúÂLò°>^VôŒáy²šò$ÈÓ£™+ß²c<\2ð5à ¨Ìn¢@ðF(sj„[…´Llß•9µ/‹/c(Å'AIjh%ú±°§89 ¿â–%ʯ]b/«ÿA`lÀ—%@'äHã†R\`=¡¶áe9IvA °mMXÙI›ïñS~O¦V4Õ „þV ¼}Oe‡éY:Û¼ìÔ›êe§ÉÊ®dR ¼ƒËNkf ó¨]zÁÂ/eÃ@£ +Ô€{CÊFÿe]¾ëȲCOæå_*Üãå±Cȳ}/’MBÍn•ò”ŒJ]ìž(O Q üM© y«øŽ'³¨†”÷ÍV ¨?•zøÈöª”*åƒS ¼éKçKœCmðpƒ;@ÃJä´Aׄa¥ +„ø‚ ¡’4à |Á¿4:+}WSR­|ôq +„×nì VF)uEï[>v¶tźPy®!<Ü/@WVf÷ãÑ$Ç–_™­@xY®­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ýá=N*ÏÖè–_›(´UO³%æX+A›Ä/~bi<„MíÄ?¶°¤£H{X³}ÿØ®@XˆýÅw¯”{ê³4jã¯Q +„?ËÙl×£îÅ8k)ñìPÂã¬ÛÜ–úŒjû‰gÇ*Þÿ uí'çÅ=“ÏøqÿŒP lýó¥´}EŽ¦7Nâ?ß”µ¬$ïi–HÄ»U\è´á_Ú| [$ 4'¸åæK  |D–“;Zîi½;m•Ù*ØoiùnÁÙr÷#=ey¬C~Ü¾Ú +?pË.q}sòËð…ZË.3€>jÊþå«h¼²–=¨@ø¯;¸™ãOâþ;ð-n3€>îÆ/NÙÿšÊ«–÷V (zZÀQ#²ë-ˆmyh°tXÚãTOÑQhB¶<ü¤AÑòËÓ,0D ­mùåŸ +„wæ÷ÈÈÅÇË +Ö–ß?lý²†½WKÜÀâÅü¥4ÒüÒßnG1i[‡-ÿÞ¯@xÅÿ•Ž)Õ•Q#þ¥ÿP üKçî»ð8¿& »å¹‡îñ¤K¶Kq(ÚïE°Õ“tÉÐUÒ Q•¸_Ó¿ éªû  ê±ˆŽÒ\7|Ì“ªW6€j6‘ŸÊ‰4ÖaRÍûΤšìÜP^Åþ]RÍ +„éæ÷ÙŠ¦ƦQÒÍ)ܾI7KpoIÈÃJ1éæ  ºŸòV±œ‡il•¤º_(ÞOu9ÖCÑö &Ö“T÷ÂïtëvE('è‘*ü¸[w@·Õr= Ç„ÔTa&ÝvƒA2©^cþÀaº1År<©^3Âß®¾tIDiÐ3}”W?ÏòqË"êM bë0Iöª, +ĵó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›!ŽR j#’Þ`…ö°¢¦‰ ž¹$üâ¡}P¸»nRŸÁ#•¾-Ò$–&GÆÉí+ê±5vArd‚ $Op@$eq=9ò¹áýÔäCŽQë˜Gø—š|¬@ø—š³3,q@(¹éRèþv|8#~+¨ëœ|ºá#õÀ *Xä,ã|•äf+þëžÇN è¨ŒFò“O@-ïâíëÓÛñŠ·lhÙ„YB85¹eØ’­xhŠ4Mj…vfrËo  ¤ý.DSâp¸+9écÂR%¹Cü‹ã Æäät‡³uV@Ž«lkLíäÖ=  ”yRRœîR&9åù˜—Oáo¼ÇSšüÒƒ_ê(â™~2C‚>OÏþ¥Ž£ïñŽlФ[w¤:~®@øpvñËÇ…Ó…ƒèÉ]BPÆE±c.Ò0TE°ÌÌ°øpŠ +¤Ëˆ(^§^óV¡Š¢¾PKîõ˜áý”5 Á½á¢‚¬€²+´3“‡¦²iD³pæpòÐ4(OGEïø06ü’óÞU ,Uf|ÁjCÔh4猯â Fsέ mjîå÷Œúá%˜q\ ›”œÏ±Ô¥ÅÒ©üÂ’®`‡q""Ô— àhNgv»e7" ”a-¨),:)ÂÐu +„·ï;¦M;Â|òKðb.Þ&'†…= äů+Þ*ËFðbF)c_cû.m­îÌ/îØj0öƒ“Ww+j•ÏãbHZ=ø+0ô¨Ás×*_¶)‰è ‡±ß*¿“T¸.Á ÇûÈ+Ü @øÅÈtPDZ•Š0`ÝjÁ% +„×éùZüé‚@SÏÙêùîñV+[ó¶óX3ÿ®ÕÊ6Ъ2‡”‹®é_ÐjÕfhM¾4ÿ©²ÛÒô2iµf–á_Ú ‹­-Qu£© lµ±¢AµÑj³LŒ(§I´iµùwhg 阊¹¸‡‹·³–Ák‹V;ݾT!ìÇý3[í`½ãVaŠÎ8ØmõÎ} +„×é}nC i)>Í‘zÿè`‡qBb"*Þ¾‹Y­¹½ãC";–CË  #ò>Øò ý£Ù*G†+´0ZÙ+— H”§dÌ…>0€~”S¤E„€Gˆñ‹ÿ8Øúy4»Ýb>'6×Zý~­Îÿ¢@Pf¶~{X +5Îrë·G@û—±` ûmÝ„“ÖûWÄCø6©õwò";D‚•ª'14Ç:y0öâaÛ“ÔÂ/~ò3èß9|¤¨(ˆ­žÖÿ>§@Pú>uÅyVÔŽŠu„ÜOO]YIà¹{êViaP¥qÈ°v¡ ‚ã©»y2#Í\x´ye†ª)”¾Oµzƒ_<쳜%ÀkµKà¹{ê,Oi¥´pob„ ÝX>”Rã!6Ú#~ÇwÅ7\)5W ¸)5d;<š’FpÚGJ  »î‘Î sK’r—Oàb¦Ü%G—S¾MÏ‚¢'å® «>:Ât¬ð¦K±*ܾ)÷ËX6ùÀAO /æý3  ‡ +ÜËPê$…?ËCó  ‡o‘žÎTУ¨ùÅ®g=.;ŠžÞî1.”b%ÝçškÂÉÅ+žôáO’í7ÂMÒ¸“)IŸ(TÔ)O¥‘E—âM¿ž”§"PZ]‡$04…^)iõ¯SZ?0ÍuÓ½xZXð.èÄ!]JpóyÚoðã:uU |‚{>Îz0zÚ+ºÐ“ +µTJ7ߦy@º$Δ¬t¨¯;½=BõϚܷá_¸Sö öxÊÀí +í‚”œ'ù E«U¼â9I +„W|ÄcljS.ºçB¦ŒxÒÊ›ÈÂÞò‰9ˆšb=-Ó‹£aÔÕm¤<½GðŸò-»I"ÕQóKS~4€fH£¦Pu^Ì+ÿRÁO ±ÀY0¬ÑR¿(þÀ%ç¥ùÌžú`†VT4€V7r]( ÉJYm@¥<ƒVTÐjzX§”^i­_.?°ì‚¬ù,ëW”¥¶~Mn:òJ-ÏÌÐÊ í4€†~!C&¢Ã™§(Ý…Ž*ÔÁ©ce0/*¼å(ö9SÇÞh{Œ7E]C°°O÷¤A›.u| >R´–I—:>I ¤K_à^Ð:§6¥ŽŸkåE¥°“–-,ìSóš*T©S¥³¡ +€…[̤NmÍèÈF;…a=Áa~ñ  ÙÙußñ5Xêì)ñææöuÓñ#o¡@ø¾ä)Îqò< -]¨‹tÌM覾kžX´ ½ª@øÅ|Ä=R4-R³N?>¡@xŽ÷bs-(š*k >Ð ¹UèBÍÙšÅ<ÑÊ:•Ï/N}!5W›S³/Áï%¬òm +Xk~é÷•Ð_SÜ …¨p'Î6MW øNm+·å€èˆíñ¶•;@Uü ‰ +.œŒß¶ŠmU“ññ°Ÿ*Î5ª¬mµ&Ð\· ÇívwÖº¢FLQ®xÛ+j@Õ¯g£Ý1H-ÍØù¶ÕoT üíjíàcnû£ÞYüâµÞ2€jWãƒ@S$4é mk_¦@øÛÝT;&Xƒ>ÏÌuª£@ðN±mEnÈD-@}׶ÎR‚ú®ííòºÐˆ‚½¶·_¬@ÐÎl{÷±Å x{éò‹ßý¦A™ÙöQ™ˆ/„}©¶÷Ô1€ ج¥Ceã ¶ç/ATÎêõ‰î žg.´Ýj¶+švÂm›íU |šñDyJj hŒ‡¶ÍÎ@ÿÎæšc>nÕŸÛ*–Å£ÈÒêO5~fµaQ*/vIÒêŸT üÊ®(¥}ø43¯ÒŽQ ¨¥ÒüÒ%¡Õ¨_3›>Í_Ið‹7—¦vXYš,“´æ@)®Ï)bTØbMK­¤@P°¦¥òX1SFÓƒ1-õ*(GMS3ÝœÀ´´›M |ÃÖö4dâ­’v”.Ã!Jܲ¢8%-½ÿŸÓÒÌ~NKÏ6ù¥!Ê/á]Ðc•«òýV Š³ãÓz¬5€2¯&$½“O“»––yµáo—Ís»©ôÁÄé1iÙ_@CÝŽx¦>ø¸¡Û  ±?Jõê<.b{FÞºÐ/Ð\™dnQ«©@[‡is#åCíú^Ëβó‰-Oñ~†®S (zÚ áPM~hJÆÚ I6òø•ï¹Ëw¡Ï  áƒY†(ßßµ>Lð_7.†MŽ7¾”i7.Úà&à’s£éæØnÂCО&B Imöáã¦üWðL•‰TêvÁÔ +„ש@&'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ƒè¾`7ƒh·½,®Ûí‘Ñ Zã g»  ]ng×(í;Ü ¢Ý®³ +„wæÇðbÒ´HMÉX»?2€Ž¹#l"úÖ,æ±·nßöeËY°R'­(v'Û—½dízXškAJEÑôèh¿ëqèHs=4½ÅÓ0Î…ÊÌöG¤›DÓÛC:ÝþÈ9¿ôCi‚f¦æ P°¶ÿaƒôS*«¨s¤4£íÚÿÔVðŠŸ.Í5 +Ç£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ï½ÇzTîL[ô ×´ÏïøØE +„ßij «WŠ/y*e*3´Òš7ƒ? »<éVü¸yåCZ®JpƒTTŠ …}§–¥P‡/X°Úb"5\§N¾R ¸Nü̳¨':Žøup*¿Nƒ[¸˜.Âp¨²ÓàdhèÞ¾Ô˜K“9Üièg +Ï]§¼‹øpF(m k©NyUJºNSñA ÉÓK×…‚ +„—Ÿ!Mmj~äó\d3TpžµyX?@¬Ó¬Š +F§9iÒbuì‚€7Ç¿ÝœNP!§òR¸73Wx“ Äwùd©èº6u*LŽ‡p¶`§ç¾bL~°¦†«ÓsÇŠžNó'¹Ò—¬CÍŠÏŸj­hÅú.ì×v/î´"ÕjŸÀ?ŸžŠ×ÉÚ"{8Ú\T@ïӖ^ + ¿N¯ÊÊPªm ¦žø¿zÊÚ. Kd 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§Ïºçå ž¢7ïÐ…Ê ëW×{õ;†6NåíbR (Ÿº„Jõ]—ÐFèþµÒá¢ù-¶¦Š Ëýëí]žx—.Šúyê9ùqO|`=Yƒã*Q?Ðœ.táo÷d\‹>:ZÚ£@P>uIy—ݤu ׬SÊ +„שÃ˱cNí¢ñáìPfu’é Tkî[\訔.ÇíÑÝ%Rá#•¾Rð/õؘàæ<øu݈ºôØbõ|Bn_êëu¸\(ÑšÁ8B‰زï2´g<„-û.c®ãÏ"ªUqeC—1µïÌÉ ±{¯iäBO@2µÉ““49~] +ª+þ¥eòæÆ1ü·Ä-Œ.Ë:ÄCØÂèòMO6ÉMÒŒ³êòMŸxkó®aY¡&º†û5í_»†6€î} æÀ“º†aœ®÷>a5ÛÉBLôH¸k³w®x×6nFå±zf9ñãÚ<¦@PôtmÓËu–EE6=]ÛôQ hÖvm»ÑbÔíí]ÛnQ ü¸´µìâúD^§´u +„×)½:/¦ã.;.<þ¥ôšPÆÅ n€Ñ±èð¥L׌K  nC8‡†&zá&Q]» W ¼3»ÿÅ"šz*hæpuíþ¯Ô£«k†ˆ>;x zt7€x8€¸u j&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íã±óŽ£,,ÄöÕ7FÅŒvÛÛ Á…ò  ÷¹#çF³ÇßÁú`X‚{Éçìpþ`TùPFYJNU˜Q¿æ´dô¹Úš÷CꢊƒyóÞŠƒ4— Ï5—‹é)ÛÖ¤õg<—h-°è‰Ò ®lÈXV ¸}3Š³ é~ÏÌP:j-z]Šè ˜v¤Y‚Eo@%2Ù•d…Ÿ‚•è˜g”$(”kù’7o7l~ÜÚ'ÊÌŒ ­b!G/â´´Œ ©ÐƯøÅ…ï-úäßxL á—±s+›FÔwZ3À>cç«Ð[2OL^^5+þÖÓ +„_ü‰lЈ,Í‘zgª´ç~qÙ˜oß=‡ʧŒ}eüEV%62ömR üKÊÑÀ!¿X|—ñáHÂëtð‘˜ëFƒcñ;|ÂúR:7²®, ùv_öV üN_ÏKW½”m¤éã—ñu‘ômý7ÅgkJ¤3¾½'Âê5ã'×7‰à0>?m5€~m D}šž +¿¦(ô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¤`UžsÝ":ܽòl¨j Þ¾ÔsØSmQ¡dèŠaRmP¸Ë»3]h¤AùÔýê"w1}QÛ“ŠÂ/~õbèÆ/X•Q'sM®û_@·Êr?Ñwͯ©šë~ëgÐ]œbáè×O3f û]G ÿ÷¼}mJEÁŽîþã +B÷g*iŒ`©Ò=0ß +>Ñ"Ë C(Œæ´…5)=E¥qyÐG}y1E(«²že+”*=Jóß/zO5[å`è3Y)¦ ™®OVÏϪ@‡vH·ÛqÃAMæKÏCo@‡ËXQ;¼_“æØóð&蘨ê¥ÍâüÓ´Éíù]EèǽÒÈ +#¡™ÞóÇ} +„wÁé‹Ü '…öñÎ<}™ô»lO DEG@|¤~olýy;CÎüm¼]¨~ùP¯‹æ±¢¶©«¾4îuѨߕ‰žÃšÖN½*mQ ¸â½ª¯â ”gìÀ÷ª^ª@pz]_É5h† Öœ½®¿ØÉm¹œÅ¤4l(ézì¡@PÒõúéo6ÿE+R\¡Öë§s +OK¯ãÒM¢À¾c¸c·»×ñ… +]·^gú±8ŒPê4‡½Î *ê]©;ê ˆSvzWdUvûdE©×õ®œ¨@pz_ÒH>Ž†©Ðõ:|Ü%–ÁÅì]«²»ÎAÐäõô®u‰tã*~qš æq¸\èeèæocŠ:lG°¢î}ó÷ +÷xï{g±Àᇳ'zßûl<„cö½›È^p‚ ÃØáêÝ$ßjºÞ=Rb` +t¸z7Ýd=> |¡‚!ü×=>Øj.ÍZ +½ÐŽBºB½Ÿ¼ÙJ,âð„ó•½ÅŒ.T¬@ø—:ÉFüŽ¬ e†uïNW@éO³ÚSº:N±è>Ùêv3;Žj x:'òãºÕ5€zïw7èX +mºÞ½@Yì&"Ôï»n½³Z)bý¦±‘åˆ ÝÄÞýf@Ã䀞ÍX¶‚øF¢÷° +ufÃ[䦓|ø®,³áí +5B¦ÿl‚îrÜ$ÜL+Óÿ?‚]fãÿðP™­g"ª ]®@pgf6{†ö(íZÊl6C |Ê| ‡E4ÍáÒ\ƒe>0ÒzœST)ôbyÚ”Tfh€Ôü6µ£"@Œ¿]óšPK9A\cûlœ¸•Ùr”Aë0ó©& +pÌË£¥\è~‚Š:3mžkÖ’øÁÖafÚÂ]{Ù÷?D†vPÓ !³}¿ԡnlûჩC=¿Ô/à†Lõê™ôÉKÐ/¤@PßeàNæTkEq=s@ÔšrðÂø‚XØgNù,ÒxŠ™SwóApÜ@[·Sß3€f•¸.‰˜W†×iÖjhy,vèˆiMLjÌå»  _ンÄñiyq§A!sãUîãô-³37^c½>‚ ?ÛOå+X°¾ž«@X>íY纸ÔOL³{6–e==ꂳ¬›(Ÿõt®Á¿.kju~ñˆc„DðdM½Vð;M•ÃK"¤òkÜî¬g*@ûØ4 +ˆ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ýÐzW¶]f»®¯vŸw2€>“wŠ"‰º“a¨¥ô¹¼J‰2 j<ê>ŸU üY>ÿ1ÁM’¢±Ix >ÿE uØçó3¼˜ty¥)]éóùŸ +mº>ŸÿÏUeòJ ¾ø¡ +ñvàûy‰Gø˜÷9²ÚúZÆ}y–V@}¾Î6€~â; *Ìq>þ,?mR üK¿I» @AtËãܸÐþx;}~?™à¦hx†Î@g_ÂÞÔ¾ 麟/@çŸáðDÐqÝtët~FùPß«VºA$áB!Ö÷ªµе2»‹,¢ºæG}¯=®@ø—jò”û€˜‘ç}kf@µFñg ˆ[Z(0úÖ«@ø—nní>Î j¢Ú}onkÕ•FVP´)ÑD×úÖݪ@x1ëÉÖ½bÚ¶OS¶Ý·Þè>ÁÔˆÔ¯ Äö½cP¤éæØ÷Î1õ +.h+3´Úz˜ÛÐ$bK£ƒû>|³ tG‚›X¢)qøqw@Ê6J!qEÕ,æ£  Ç¾bc”ìlM |ßǾ3€ZLbÇ”zìkèôm1U ·Ñ÷©î¬Êl™ð +—à©ÞP×ñ,zhfƒ¦`·oקˇú…Ú²KB­E4r¼_¨c<„åx¿Ç«°B×…6–ý¯¦@øqÍïLpŒoxe†îR hj÷k%ûdÑtË[âãB7@™²7‡I5âÇež6€ú.dõjÓõ*ôë»ØR+ +ˆx…ðã†Ü¨@ø¯£iþ]ÀAv÷ž4J¸n27 Iví7ªŸôtxµ}Î~Oßjͱh¿c†øuiýf)\ñþÓäÌ+Q$oÙÿWWeèw +@hÙ_¢’Vr»à‘ê¿ì‚+Þ¿¤¹xñˆ?JÓDp¼ I¢á_Úx9Ÿx4üúo¬nmáqÅ z’‚+3T¬@вp;·) ßæÇ¢gÀí{  nY•Ñ÷Õ´¤ÐmˆA›nÀ;/(E]—Âïd(\ñGv³ÃEÛW“O7àÈ{ +w怣î-¥™kJ|f»D* j(@6 †.3€Nvt'„~ÜÉ. +·Ê€³·°£d MB÷€³·ÇCø†k`Å ¬ò)‰SSv4°â¨êŠ„¸+'|—?°êj‚›n`ÕslËõ¿*<œëúÙ‘ ‹ MÜÀº¶AY0°Þ VùG•k³¬—c5àAkäæZžÔ&^‚ah5s¿˜/…TƒR‚Á—>Yfel~èËU h« ô-e—#4EÄ}%PàÂEvÄïÙü¸À#Õ1fd-¾huU |Zîû4A†*£Ž¨÷\õò‹ßwXðÎ|âW©¨)øð„»\è´”x7+ ˆãLjúõ LôÅC8B30ñ•7Ììˆ0l® L|]ðOuã™~qч¥oj’Ô¥,¶þ@_†ì²¥|(»R:›kbª&VÔÙ•º*þ¥+¥Õ#§û5Æhö•{ÿR ™nÉ>›Ø Ì®ñŽÁœ}«ÛÄÎEŸø—n}ܺçnvà©!¸æ‚6û¿Ôp7›µô5ùtÙ ß5€”3in,}¨6²Üfµyv@^>Âí›Ýâ3ÂïÔò[Dý"½ >®åP+7ñ=ì×¢f·ªnµ¹›M£°ø8Pf·id¥ñP›\Mœ.;­X æÌn/먃Ž;Ióƒ¡*Ën?P ÊN/ãÇQƒ +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 +È^°ÊZ|ž :~Í‹/©¨@PQʺ—UÍ +â~=ƒ²îS ø× ê_? yïžÙô.tE<„Æ As.˜ÿÞÁX•*4€r×°s ?Ç@Æ/ž»ÎšÔÑ$S°F4©‹áÅ|F¦‡HL[šÜÚAÏÌV ¼˜Åíä¦#¥h°zTÜÑ*qûûúEI+þëJ®T üוÊlfJçvŒv,0•Þ®@pûÚÂé °¶4÷-ƒ¶ ‹ƒ4÷-ƒ¶Œf‡K4ù ™mg½9‹5…»ü¸—î 7 ÊñAoïI¸œ’¢:Ñ3èí} +„Oð^i ;2NÌG†ŠzÐÞè#®%qÄ…/¨û5è£&Ð&WØSÍ‘úh«A0èÀk ……`Å;°Ãúj:›AR¯šüUáÃùã,Ãú2¶A?<©@øŽs¬‡"º»üAÇ(Üx1›! +ðáÜÁ—@Ûþæ#%*qqÆþàmç®ÓàWÖñã"T0„S迲Ñ:ˇÓáoüN¯ükíz‹5†ÑŒˆ¼k·ôîͬ€õÔÌSüî­Ð{3bƒ#£ƒß›e}ºŒƒ/~aÐàÅüt…á¿îXG^LQLJåÓàcé&Ðr6Cèpdtð±— +ûÁ'>”Wžëg:hÞæ_¨dûƒO¿arðßõÜp¼£ðñ5ýà¿ë@ÿJǔڿú£Ý…¶@çör # †+á¿îܾx¯Óêw°Êè“]‡T¿[à.Rûq× ¤)´X婨@øqµ¥FRalÐ#ì+3´S ¤rÓ^Þ¾br,¾ ¹é¨î!7ŒCÉ?ØŠR÷K‚JqÈíwº[E(}hÖ¹ýnèîŸù D)¦‹÷ø»OŠ_Ù03äîS&¿ô»Á/ùæÊ­¥ušM盧@x«”þäJèÆ×`CJU ¸U†ÞÆ•|š¬©(z[ ¨þE±Ãiù<í_ùqõ«@.gƒ†š”kL£¡ª›@2„.eÈ„„›nh£)&ÐKîö¥8è9´Ñj‚:x¨=Ç5ü>ï=‚ =§@ø¾IÈTÜaišØ }¸®ôø Qs[sÉ7ôñÓPRÛ÷Ä1ÿq€qhR‚òihÛ_9ø"ʱA3´íi¨ÓOq#ˆK2†v:ýßè?C=ngEM)š>ÈC{4P ¼âÙKXÙŽ, âdסÙËïñ±ÿº¦9ñx¼ìÐqz@C‹ö]X‚€§¥¿ }h-榈þµ`Ç×C)Êé#sC,ºC°5•¡9}Z*Ô9}–³z¥áQ|Éé³Bà·Ë&+ÅõŽÁÄr†E  ±}Y`P b_†æŒ @x +>“®5HÕµÃË)øR Ë™õ²ÜtŽ³lÛšÔ¦œYë  Õ2C(HM—}š)c9«ÿQ ¼eÇå³Ðx¯9e'¯Ó†ž®AC. 6Ús6d™@%lø‰áÞ8Ñ&gÃ*‚LJ®Oˆ]øû=Ågü¸C7ÅCX#ä|³•·¯5åxÎ7¯)”9'd=g$¤Ê$ +È9±Ñ:ù 1Ñ'ÚäœÜ£@P· {uyìHùšÆ Ã^}Iài¶¯;ð–HÀ…ÒwؾÊЇ²¡@kУ€øq^­@ðÛ ûn/];zœ~Üw¯@çÜxfDD­á vî¶ò¡á e*Xš”çá ×*<æÃÉÖ¢ý«ÂA…á‹+ÜÃÿœÂO4Ћ9üÏéåC#*=“ÀWsÎÿ¢ø¨4êƕWò²=ñ'ú@à_7¢º{ëFƒÈ,ÜarDõ¨A6Fƒ¢yü,#\¢@PŽhö&›ÚŽ3i…tÐ;Ѓà.Á>°ñàk +¥ïˆ'd{ ¿Ÿ®Ä5å#ž˜m¥ÈNœT +ðÎáâÅL©gu”IâRÆï)ãÇulaueÓˆŠÛ×õ)¨§Û?,Æ\ÂèÚˆžÛJºÜÑ&HâÐöá·Y­  ArDÒ®ÇÙˆA‰Ð3©ÕP»¸#†ül ý„‡ÿÏMàˆ¡‡  ÜÇY`8´4‹™û¤4éEÞtÔÈÃs¤\h¥4¥™k†P¨R#0¦<¨@Ðö±àíØA n5x?-Øk®*EOP¦X@7iÄéÿ(Tù#ï/a—„\Êþ,#ï)ÂŽÄÈæÜ“B±O +½ ]nuK‹©ˆ÷¾¥2Cª‘=¹Õ* ~ó +{~\Ï"Âï4䫘H!Fü¸!ß@CÏ%¸×ªÑ`§9ŽÌ©¨@PŸ&> ý²,Í°Ó‘ã;)^‚ RßEÅpJMÑÈ —@Ó>æŤ¢Ù6rÚ!›®TÖ·Pj“#.4ß®ô]hý nòßòXö.t@ði)+aã!* dhÐŒ,[im[Ëfm”JÙ°…1rÛz‚*ä+_º*…Ò< +±‘ïð?ÝÛX°Ž|ç9‚q•‘{þÃ!D}Óq väž+Út#?®ÄWÄ1YðqUÂûÆíÿX5P¸|hÔܽ1ó?jk’FÍý@à¦UT'fÖ:N7NºUt›Á%µ°ÄuEë@¨6F-\m•ô`3$ìsd/¾JU’i•u䉉EϨ²Î +Åᨠ3Øðó‰öŠðpŽÚ0K èµ9vKB†‘æ³l>i½â^®[Žùïñïx ^yÑz}qÌ%‰XžÒZn½Ñƒ, +~k;Œz#Sð:íö1Dî&f?j·e}èö` Q_¨ú0ßúä±UdØÓóìG}’`ƒT¾nDé¨OÆ(>wŸÞÎ/N¹Óšî¨Oë@Gyä­ŸÜ<™yü¸£ +„_ü‚{­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ÔõÔ¬'ÚŒþªÈúeM‚ }G(‹¯0GÿRª@ø¯ûû^L1æ[ö£ÿþHðg9ßãÂãl6}>SàVSQöÖ¬ÆTœª@p?©ê&t‹p<Þ™cª^£@ø—.9& Ù^1„ÓÆ\ò“Á%Sm=;Ëty¥)Sm“ÁÏ2æ?ùÅ)À¨i_6æ?Sÿ’uHºÝ¤tÉc¬/  ¦Ò +¥ï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åvcƒÆ¦ œ®>&·—´l3 ±Í„Å©c–½¢@PúŽùN–´Ê º¦éý˜ïv–å¦Ü«ÈPæ¦ÜáËÐÜžnj¸,Ђ‹™Ûó¸Ô‹û “Rô‡ð1ÏíUà ™8&¶3s{ S ¸Ÿr³dþ“E!]ïxY:e¾6fŒ†,O=§ ]§@ÐÎÌͳø‹FÐø*%7/bMäNb@ȹÓÚ*¹sx?Ñ8« ¦â1wN³x‹žÜÜ«’ÒÒ|ž zÈ*Ïå8žK>š`-éÊ›ŽL[MIî’îЊë8øB-¥}¸{îŠ   ¸Û—Ìvœ*—»áo‚1ÖÜ7>w ¡€ ÚÈ}ã ÂRå£:èÞÞÝf}¿%Ú¹àÅüþC‚ßnìÂ'x ä<:¨€Æ.LT xÆ®¹-¦€¶§­© ÝiÝÛ*ÛѱküÐŽ–r ‚dŠ„±=vÇS +„igˆÓö[º&vcwF»d“rE渓Øê»ëMèÀæ˜z¥†qPfŽ=ðŠt“]eÙ6–¾cv1€¾¼™·/]ïx¢ÿüâ_Ö5€~¸Q~`QT¥‰ÙýሻaÓ 2Gá‹ÿi’ÅÖêäóLDåÇŠ*ÔÁãªÊ®rÔHÖ¶8`=®jm‚ÛwÜe®‡?nßqWäò1·hh¾ wEžtëdvÝDAö[ÆÝúŒÁ_e,»ÝT(¯ ¯2Áº†+eº6²Æ_³Õjàæ ûýŽC‚-ûñ >R ¸NãŸtÒQSZÍÜîñO.Q ¨¥Æwq/ùhüu‡™ÇwyÞ–ÂK`‰ÙóÐá?,Í:$k$(!d‡q1ãøCW™@ÿÆÌZ­ë6þp…ò¡<ëOV@Îö z’¤*3ôdÂÂÞù–ÇzòìC +Op^¤O‚›ÎvŽ'þ¥È¿ԴL†'èÕuIyM·@½å +V2k°W–÷Ðn(™- ?¹7š¨v^r¢”~± OœƒîÆìB—*ÔRy]d;ÑNØÒôÌëÒ@ TÉ빋?‹£^-Íø¼ž»àÌ Y•Ô2¿xæ‡ += ¼Søq>G‡­ž¼ÓZ=y£‹Ý­BA8ͽԚÄg$ìm¾Ë›tÈšÖPªWJ±°5-‹ò¦  T °§‡òfôT üKsʃ +N|X•åÍ]bÍˉhg×ዼy³úœyó¹¡eò¶¸þ.oþ‡P‰[þ@zQÓx!¯ä¼áo·úJ6kÃdhaµ‘·újhûå®ëF—ÙXmäm¯®@xÞÂá º‰âRò¼·F(Ôœy»eá`„’T-ÍuaÞîj +„÷ÓÑ\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Îú°Wbi¸’æØWð;ý”"©2+¬Ùã?¥•=]kVLQ‹²O ÍU ¸Ÿž¾n»$T%ïIWw¡bèŽØ qL?Û“Ê[™¡Ÿ  S9±0NØòã|•§O*šxÑ…~‡”Ü…ØÄ‹v+üë&V¾„!Ѫ‡*'V¾\àŠO¼’çshöƒæÒxâ•£  ;–ðP¡W_¥L¼ãEèκ¬6¨ÀC2™xg=Â+ÞXæaPГÊ|àžØ¸•t¯%Õ•d5fÈÄ{#Ðýî©cj[AìHL¼ÿˆ”Å}!©@ÏÖ4<™˜õjùФF²ÿ¸ã¸9N &Ì<©ÑP‚;sRHö§£duJ€*Rè˜Ô¬=_”@‚+ù&5KW ¨&µvçv“Ã¥1F'µbu~“MH*]ñ„–øÅ;ïV xZ&ep‹c +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Íy†·ŠßÑžÙ.4S ¤›\ÄS2hظ_Ó4crѨ8 vòáÏŒ³Ø6€ËÆÄv€ÌvMJáäÅ5oº-yòÅ)ÁÜÖd0NÞ2ÉÚ.· +5½×¿øö +åøä7ÆŽ©ùÀ;ë@oË * ŽXa¬[&”i”HEu¯x1W ¼˜ûØö¥>íž.Ï.d+Þ*GŽò ¦ˆ½æNqò‘o ±oϳn¡è¡çî•×éX%èD}ÖæT·¡ñÍ'Ÿ¸Çú舮Þ™¡ü¸ß~U (ì'ŸÙĶoXäœA}7ùÌ6诩üYÂ"‚Œwæ_3â!ܯgJQ$¤¯èSˆ¡Rèë[¢yŠšðÄ”¯ëÅCXLù¾WÌ~rÎ6k§|Ÿ¥@ø~‰dämq\™¡b‚xÊIQ°ë§™W¡€ffÃÙ~#á?û[¬=ôH:~ÜÙ +o$¦V©ÁúŽ¦·kzRM­rÁŸzIWŽÐP/GÏ¢ õ0Þy¯þ@§ÇL½ä}‚K0µúÍ®§HBØŸZ½®Áý45!Ÿý–0M‹Ä~ËÔ„ÙPí½¼é¨ÛlD³˜µ?P ¼N·ºŒ$|<³Ÿy nícùóXˆÙTå„NõO4€šò¹ P—!M‡î©Mû(þ,ÝäÈ6[ôñ6ó‹w+*z&“ Àý¢êßß=“ÙQ`4ä™aø ÅÀÏòÌ°ÁPþçyp|jÝ´ígò¿0€žç‚8šÒêפõ?ó|¾tHÈQÑÁÀÓgÔ…–•Mëÿh‚{öÎ(ªÌPs‚‚uÚ„š|(›9‚ó§M¸Aà~š6q¨k‰QM'X0mâðxË‚iÝc„Ô>–ãÓ&îQ ¸âÓf°WF3ŠtÝì¹ +„ÿºÙóÅbÒ ¨®üaÚì…&¡¤nŽM®ö´ÙË  …‘˜‘E‡Šèi ›(<œÓŠe@È/f€Dp‚Û´â·  eûùH mßiË(^ñÕò>8"ü„0¾Ÿ¶úKÂ+¾VÞp…}"ÕÇ0¦­ma•v`Á*"4¸Þ´ígØ. ¢Ay˜¶ý/‚Æè4á·Èw +4×`ÓvÞb} ʶIªP[S¬§}ÐÝúðæ˜-†`Àÿ°®Á Õ´#<"‚p½©—.´ Ân÷´_ª¹Ò— +qxbÚ/—™@©|Zèº0ˆ›ŽMû¥}ùÐô +OH;ÓÑ>;Œ]·é  J­ø³DE*´¢§WJU (}§_ÙGÚO$}½}\h ”uW‚ 扄$œ@2=ËgmkÌ2Ó/Ká~š¾­™Áý4ý™=!ÈÒL>›þÎ,èÃó,é,Ðñòñ|TÉ: ûjS vŸßsEàB-  Oå•“åX¬aKÓEuú§+Šžé‡ŸKp/׃tYwøyè·"Öœ6Õcc«gúoÅ +„·ïé¡ îå•ó;8£cúé +„·ÊÙ( jàÃIRÓÏ65Z»‘1檲égSM 7YƒŠ4©áÓÏÎ/šq;þšRÓ<Pe†þ0€xP--§Á½*g$Ì4€ê¸·¸ÔRMsK2£Îe +uËŒ[ºÅ¢!tIÆŒ[zÅCxÅgÜ"ã*â2Ôoc·{Æ- +„ßéNyÌ£ô>:3dÆ+þ¥²eX:÷$3|b5à +ÈïwÎ +ΛÑpœAõ:Ãïvþ¡¦ˆž¡.t…áÇÙr@H‡¬®4žaO0€B±¶74(O"žz9Âue3mäBþpÐ3\É…Ð2UÌ6וÙÎx"ÑJÞ‹«,O1#?.y³Aë0ÿʆ,ìiãy"~.P ¸˜ù×ð=i}çÃÏ¿ÆV h?å×–iý6%kl¬òókÏŒ‡°W–ÛhV@÷x¯.4ުߞ})Ûo4IÁùõÓ  É c¥K>üó<¥@xîúUYX ºÄŸå®¿  F°ñ¢ø8ö9ó=j=ô¯+z¨ôËñü‡/2€’Ú°8 §ˆSvò“Ú@mïg9Jƒ±RÌoû t’]7*ÐBgÿuí«$¸IAÝÀ‚üöÕ  tNÆwÓ¯QšŸþŠáwêþ;)š„£IèÎïþg<„mßüž²‹ã—‚–¦ßa~Ï6Po7k)$³àöíÝÚÊùM~`*"v\7¨6òsþ0€†ËÑvúÀÎfÁ¢gxh¤Ÿ— H£¦q( ¤­@øâp<µèóy.×y FíW ¼N£[ÅÄ!ÅŸetŠ4æf6,Ÿ¸éÄP]Â+>áùYÈm³5££ò'2€ž‘­V)võÆìy žyß*àú`*Œ Fð•S~Á_ +„W|Ö% ±Ø¡O3ì4Ö¥ +„Oð9k.$†—5Ç|Á +„åøÚñ ‘™¥ñÊò×>m­›ÄÆCÀO‘mla¬›ª@pÅg¶éÃ.‰ís\Ü­f› +„©óù8‘¬,:³ó×PŽluá˜}ÂЂßnfN=(Õݾ”ªŒÍÚ™9i&ÐY6²,™Š€¡ÿ@¹GجuPPÓ®sfî× +-Œ™c¯g³–Zy†—ðãÆÞdMËê5 \.xÌgN|:ÂÖáÌ|Kª JãôkZˆÎÌ@…2|¡0N2ŸYx»ÁÃ9ó9y$DO@Ó‚}æs³»ç󦳩u/¶Uf>ÔZ•Â^€5ŸeYS襛XFÔ^6Ì|©®´ö/V@!Ñi©µÿ@›¤#A…g¶Æ7¦37Í6€v—¸¦‘舷{µá_zOV‰fSÞäDfqÝ+…ó¼NÚWÁúP6‹PàÌÑgø¯û°ŸôñwRmÈV«8gæÇÇÿÒ7}øÅiüªc=3¿`ÅýÀ$]ñýÝÌão@çj°Ñî|˜€& 4ó\-‚š³ s%~\ж4)`/6€Ö?–à†*)Hm•‚õ-  7Å1w2m=—2ü¸7P ¸âoîbEM7¦šñoî1€ör?1úÈV_¥ì­ª@PªìmÄÂ>J64ÎÆ)ØëW hj• thlE8ÆùtG7€¾á –"¯Çó×¹Ðз;XåG(¿ß›|û–tÌÍbSë^œÖ_pì€ôë*PóHOÌž÷ë_Ð_óX½R+C°/ø«H ô-ø·O‚›Cã¨Ígùw€ ô:«2Û9Uš´´‚w–ͪ;œ¢K*†Z)Ü™³ª¹‘öˆ,üD/>«Ú¥ +ÿºY×?[LËù,PŽÏº~±ÁÏ2ë†ß¢¶Ëš†³nøCà·›U·#« ÑW‹èYu»(~ñ†îTr…¢)ŽÕp§á ”à^€P).þÀÜ«@ÐSœõˆ¨NI4¨i 3ë‘jP"·˜ Ò^+êY‰M  ŽßñP«UMÑ笎ǡf_ó5o:*©i»<ûšc +wæìz­Yå;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žÇ.´ÐÊ”7¦4Í1Bðg™“ù©4 ˆ3(bƒÐ ™3 Ø»›—€24ãbæŒ}ך Å¡s˜œíÀöøœ ?@Ïl¡%jàlyÊDøqÏlQ ‚›³NNi•m¹æѺJ}^>4·p»ÝA½Õ3·°H n™»,!¢Î½p æ.»ÞZÞ„xÇh·üØê™»ü~hu6:(;Fsá?wuŽ´~+»IÔæ:ŠÓúç®ß®@xÅ˸°ˆ.y/¸ÐM&ÐT†è’Ïsüæ–M7€Þ;ÇF;5ÙôdÄòì»È:p „ ŸF>A{|îۊùöK³V™=n·û¸ƒ +„¿ÝAÑa’ÃþùÞjl}*GŽÐÈÛ°·á ¿ø§=ÿu‡d³d+@)ªÍ_wèmÂÝçy1ÃÌÃ!¸¹?V2ÆÄŽ¹e…ñEÑÜÇÇAš_s,•¦‘<£¹™ûc™ô³[‹t>‹FQÏýy«A9>÷+v¤¢~O!þ,¿D  {ÜÏ¢v:÷Ä>Âßî÷æ1AZ‹Ãß[*Œ´?{µLÎЈRoæp†  k¥¤#ë1`i +<{í«P­‰ D'¡ ˜ž­5ź©„UYÄ1²Âø*åÙ›V@u–³z ‹äpx‚Ÿ­ó’Ôs!Îö hšo?Û°™áujø›Î–ów¸Ð£Pˆû«¨*]SÉ÷lh¹®(' io –pUÈ ™7×N>¾B èyö¾±¬¨#d ã Õ³÷M0€Š¹(’Þ»g‹ÿ1€NrœÎO#%-ÍãNž-*¼üEù┫¢kL\xùJHÎu³…¹­IH*¼ü„AYPxmM^¯™ÀTxíuÐMÓÜðUâèáM +„ßé–b":bk2ó +o9gÝ)ÛÂ[Bz2øqw>¨@PŽÖ…Õk€ZôaÇ´°þëÐÝ[Ù¹¡ÆzžÔp~ñ»_S ¼âÁlb!QrFap¨ÔxkÌÈ +ø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Ž~Óš|5›!µJÆMX +'_«@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ºÊÍÛñˆ´k VJW÷4jt¡qÐvqÉh÷á¿yæ(Þ¾Ÿòüjöa…þoÚ‡ Ýiý*‡—P“ßÒdÏûõò¡çÖr€P@žn.”nm_̲O ë‚Û÷9n7åBøöÄ,{YÛsÞúbŸÜ*TrâüÃ/þÅ~Â/~TþuÔàËQÓ8èùÜÑe +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‹Ú\geœã%pÁÖ¤6u«dåÜÁf­¿Š‹c‹rîV x‚‹†qCpJèv (3‹†íS (zŠF4–Å/lÍÔߢÍÿuc³XQצ¾”)Ûß?Ú5C(¡ëà¢ñc  <©9ƒ¨(`Â8¯¥AÑS4­I,øòpºzÑ´û  —¿âŤT9M•SÑËß)þ¥u?ÇAš™ëEëN*ÞÜ 5Ÿpà5Ы +µ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»:ž=¯@pg.üGNªò æIpãÇý³Ô:/§úéåusÝž÷•-ª&W‰£ßÓ-­2C‹ÚO‹®’þèê½áÇ]µ<ÂjcÑÕëÜëçˆ7å™wõÂïTãI^‚°¨ÑÃïT£¥” 'ˆd|ÛƦö¢„{  ÚW³sãY–¦teQíšñÎÒ]tÇ÷îátD½›Ú‹îøɪ_3ü,K“h³¨þ|(0Ž“Jˆ5££ž6€Âÿqv*ËÀ…9‹ÂW(‹šÈI¶H¶Ò ñ\Ô$U ,XÔi¸x\Dô‹j>p§1 +„©ó7Œ#–ï‚ÎoÅCš]0à°C ]P¼ÑmIÃÔ5ƒ ‹7.Q ,U¿!•¢;¯1hŠ¿U>´x˜Ð"üBEŸP.6U ¾[üŒÌ÷¥ä¡®1´M 6_<³o:ºæÓ”g-žy—´â +^LºxÕ$F,^qôREv'é¢7ŠCK‹_ª¢@x1×Ê\1ÀÞ{÷êBo@o–ê•Z ;Ÿº¸‹7Þª@ø¯ÛÌ}×âZ‹žÅ›ÿ4€¶îäà Ù–æo}Ûzý^LK8”ð/~ýa‚'xñ Ñ”·/ÞP (éï—~0¹$Ž¥¢y§ý~è£ó±êÊÛ¨¤@x¸tˆ\7 +ìÂ?²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·â%¨¿ÑŠÞÄ[Å9æ–föΠѺÐ#©nð…Úfà®ig=:ž…¥pzRÔîÜã·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ÛÇÀ¥á‡ã™KÇÕS xÌ—N¨Àn’%Ú‹CÁºtBEhòg n¢MÔyyüN“¿P è-šËóQƒT|Y:5Ïš{–u”Ì#lû.{Κÿ£Ôˆ_S¤·tþZ²` O 8›ÅÒ¤«/]’c½èv3uÐ0h.wó8,X5\ðÎ|u¿xÄYPѾôÕ…&;&\LÄóï–¾úž´Ý­o¡æ‘–æ˜o¯iíþF +{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“í-‘ìéXÊ;÷žAëpù×n÷â°,ÀÅ\þu;‚[eù/2Ì1}BHcè§ò¡+^Ë"ZTBáh틯S (3_¬q„å5gÃçîÅ_ÇCøܽø¨ÆlS1TP“hó⣖Áuz1Ù/Ó¬;Œ#4/&[åC%—¹é{TZ§¹)¹ì¨¾”¾ÑÔÇÓ+À…j*üëJü#—@„™Ãøš¾¤Áy‚‹Yr7×·ˆ“îjV™¡9ñ¾+ ¹sÝ(«Uj§@Pf–Ü·•MȨH·‚R¥ä¾Wnº’Ǹ³+'Ëc†ðãknµðÇÂ8A+€»¨–´°ʧ’äg]ÓÈoy' ñ‹'ÏS ü×%ÿÍfUkj$J’Ï)ÞO™²T3JCéPaè:(KN5°„âÐX–dݦ@xûf%Ç çHá+‚’¬‚¦vÉÄ‘ü8µ&àÇMÌU üâWó¦ zk„’‰/@“¤ ¥!TºXOɤQ +µTÉÔ7YôP Æ ,™ú¶”Ï–˜ºèþ$¿©áuš9ŽE]Ïi2ÑKfNT ¼3gÕd—D$Ëi–`Öu +„Ô³2õ2$’É4ñ§’g?1€–|Î ñãðiÉ’/  ’XQ »$%%¿(^Ì5ºG,MÆ~Éš]кÁü8*ñ±qyVɺá +„iËålÖF„!©®2€^‘<¨|ÔGù€p1_­T>´¢k„C”ìÄnÒŠ®M  LY$ʶ}ѳ"ó”AY°"W^aRÐÓ1ÿqrâŠÜ½ТÑüC²IZÌ‹Æ)O(€ó·›Ÿ–ßeÉ= äû5-‹Vüþ¸ôGÙ9 I´YñÇ–ò¡—*òl0 +äX~Ü&÷¥Š!‚rü¥=c9@·X¾´'ÏúL&™S»Ç.pöÒg šµ/ýR1ö¸pÐÓÏž÷KU裼˜ajFªY‚?Ž)LûXy‡LDƒ>Oc½ + U3€jö‰hY7ÝÊšÙÐÍ2SAˆŒ€§è“wsèÖŸ¥°§Ar>M€•·ž4€ ¹I6•6Ão0Bð_w× vq#28wWáwºk#‡–ÈêÓÄUVÞµU Ê_黃öˆ/d[8÷¥ï®xËÌ•¡#ìpE*/~§Ð7 +„ß©I÷7Ñƶ4CV6é­@øqÍK‹ÆŸPK­lvT –Zù° P¡¼ßÛöÆ…@É»\qHÑxœÚ´2y¯Ác¾êú+¥‘åH{›îüѬºþj¨öaþ,aÈð¯ª}Dð/ùßfc”VÀÆ÷-«ü{  C94 tV@Mdž}„ÒAí ¬jr½Á¹êÞO>9 Ê‚U1€ss¢â:Eõ4€ž¸œ•bD^8`¨ºAU¶ê‰ :ìš_*S xZVµt[ÌP¶§Ñ5/fË Â+žÌéV"aÒSHÁK¾2ÂñÌU­dH7Bfˆ®ÙߪVO˜@|›D.®ÕÎV-  Ô1ȶ<®]hÔßí=á ;ŠÍÿUýç)þÀƒþsqé^oºAW@#'±¢ó°nY5rš4e‚T¢¡Ê_5e²ô²;Ñ‹¶¯&/zÕË(ÞëÜb!jä¡i“»j]Õò¡ÕÙ²Â_´& Ù3:©@ø—ø³ø!Ñx þu«]cM³iŨ𳬞~¯4ïû„XH×òŒc¨ÌÐq‚Ç|õs²ø,"ŠÆ<9£.4ÝzM†™ƒ¢ÑÓ¦Ä…Ò  ·~‰ž¨w† ýWà/­Ù5ž7 åð\?W`h¢Á_³o»$!2Œ¥ïš}Kîñ5Ÿq»„ m‡ v×|ö‹Á¹æË*îö¥b +³_óå% +„_ü¸¨"ÊL7ŠlÍñw  _dúžH»¤«> -Ž‡pPaÍec=‹~ÀÓ-?ðŸQ A^ówÞ¾«ƒo×üÝ£|hmÕÃ1õêóÞºÐWñÎ÷]{ùä¦#'ÂÒtÜZ{ù• +›µõÄÜIz'üKõ@MeA%F8æ(¾lXÛ4l=%/ü)‰3êè3¨×>õAõúòõK‡ËYÇ°O3˜ýåë/‡pW”—;^žà&FÐfòË«@Ã*±sN~§a—@3ÝôbgÓù4rüå™sJºÒ62ÃÚÇÜÂíËJÛ\mµoï*jr½±#QÚ>] +í05fÖZ¶&7¤´Ãt(ýWiÐPQŽÁGª4ý´Ô…S´F±*+íRhõ¾Ÿø°h¶ +ÅaiàÒ>±AC­S<÷æ.ô¯4êziLˆì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ÖúºD*jç\†½#Gx ¾^Y>´þ²Ó¬§ÔÖ˜!ë/û¯tã@~q*‹à1Mëoª@pÖßôµ<œ¢LÄÍõ73€ê\£@pû®¯SÓ:'£kAQ’¢{ñsI +-±õçäM ãqSx_¯?—§@ðÛ•Uq' 9Ïói>•UùWà‹—±ÃEù’”T_¼¬ê· +mº²jr¦-FkZ–UûQ æ,»¦q,¨;+E›ŒQè(»¦·t§[GêÕsÌ/~ç­ +„—àîÚ œ$å9Æ(þ¥»ë˜@ñ‹SG³éÊî~Ìj4˜ÍÚrAª,k4Ì +÷¢‡.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ü~Â{bõ¤ÆéجÝpà“ò¡7çÅŒú¢–§/d†Z@ŸÖdw2L..Ámüôzè;9ÝO–ÙZøHmü.×ú•sÚiÜS@3¦iã¯c¿Óo²“9•ÖEl ;Ë»Ô:óCÔlÕ“ÔâB(Teÿ+c=$Ä,o«UºFð/ý)Œ¶Pûž 5^Ì?s +ûM—üÍjÃù,TÀ·é’óЕO¸‚Õqn4®Û¦+[*~§3ÜÜ–’/ƒ¿eÓ™æñö[6É”Æ(4Ž8„[eÓ™¾ÐÙåì&ÑÅ£…ÍMgW( Ó¸L‡q6לmÕzZšFÔÀ{›Ä/^kŠtÃ"V¯¢ç#ΈÝ|ÃRÂ]í«\7‰†ŽãÄ÷͵kÄCX·l¾ñvÝ¢bü5›o|Ôº³3oº¨hrùæ;»@wó¨a†x>0¿øÝ/Aô”kÖR?lømŽž1€ÄŒ¬¨å)ft¡… +„_¼ãì^…ÀÀ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?ÍZÃE TTey ~ñ5§ê»­¥.(jKã½n-íª@ÐáÚúŠÛË/ŒQü¸Wj)~ñ×ßvvj#Š š­¯ïQ ¼â‚1õêC¬€¶)b[¼Æ!ìw7œt·õÈ諵±M²-|­ºõ«2‚aëÏ·'p²«c´{Ú»PèϬò)jÄâp럻ʇ¶ý?ÆÎ;>«bé〡‡ä RŠzAÀ§§Ø*(ˆ±â…«¨€(Š]°DA)^¯]À‚•k¡—¡Jï„Þ{•ž÷ÌÙÙ‡ì{~{3úÑ¿¾Ÿçl¶ÌÎÌN)£jãxÅþ"ÖŸÆ•él@ð«Æ¯$a‡ý±ÀWm³jx›I¤<±ÿi\ÃÆ„¾ä +6IÈc©b1nIK´>‡¯Wz õÍ|}]‚;sÜ–0_Š@o‰|·%f@ðz·ƒKP˶°%jÜŽ¾èPyåžðÒ,ÇǪl@xU׫—Þôµ¹Ôоâö<Œ;;Ÿ•QŠÿ²dò;»È€àc®á_Êé`G,¹°µ1>ç ‚Bl|½¡)qt|jˆ†þm@píÆ7âàDz + ûªìð²4J7 ¼vëÚ‚îêSÚ5tŠþ¥Ôµ° +~Ç“]*€·ò¥¨h¬´OÜ^²LA¢{ʸ‰F|)÷zB]ªÛÅ„)YÛRã/íZ¶Ôø+«ñö¥‹Ã†=þÊšH½)ªÐ6Ç_Y·8dÙ¾­uו8é8Jw|ëÚEôøÛ´«2´¦g¿m“ê¬"¬©ñ ã#Õ9£dhB¸.Ž’c}ýïÒª/€Z4åcî¥Äa“dB‹á1Ýr,ÀÁ®ÔN_ùn9%€îZÊÇܽ4‚§Â„»V  ./j!æ•K€òiB—>åÓ„^Ïø™ž¥°ãlB¯—‹CØÇ:á)~¤§ê/‹¡ÎOË„gTö³WÉ1äë +¥¡}è-åc¥C1ù2žÌ·*žñwT;uJsm|ËÀßm@x âàJ… +ÛxÐmh„N§¡²\1Ë.1À€ðÚjÎnœDÈku‰¡á­2UE™$¨¡“ÀÕ÷&L½¡8„KÏM˜~X +žŽ$±ú?aúß%C{õäÃIy‹ž‰½ž@/\Å*$9b-ŽŽ‰/\'€úêûÎ5nÜ[^Ôû>a@PÒM|'S»'¨D5nî=ñ,4¨¹1W wÿ|÷ØáàéÉ£¨é•l&Ññ0ÙK(:¨Œ@/|Ï’3¹éQtéjÃ!õñÉ—ÔU&_¡š8ôäD3œ‚+&‡p ¡)7ÝÃ&.€ùBåJ1ÔIuT©+ ¯¬©¯˜–†ö + Ÿ±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¾2éÆ ÜÓæW4 ¼ V¨z¬ô”’ú@øs+ ´—%A‘°ûtÚŠCHGR‘ÙmQ¦­8%€6)ÑC½Ëà‚qÓ6 @[¿eq˜t‚¥%÷´­?‡päË´í'”™öj€áÛ|Úö3hÇKjY¸Ð›ê+€vÞÊ*d„(cÑ3mçí„wÁþ)Õ(Jb‡õ´ý× + ú椇G_J^–§ÐѱÒNMSC–}DýÍI0$è]3oº¿?@§UL•ÀòÂáÀO?h@ð¾›vz¼6'©t/ÖU¦žl@PW™vVuZðŠ„,u¦]!€Š.c‘$ÁŠÕiEW– M/7·oÒ+™ ·ïôrï  €ŽÌ yÁ‰PN¼-€rkC‚Bèq4óôœ ÎøôKUk;jâvü3ýÒÐ<ðˆ—ºbæÔ}§·æÂ0tkDlSÐúi‚çnzÛkYñs-ר¥5Ëô¶­ ·ñ1OzÉuø¯kÛÁ€ð_wÏŠ”Ò±eÓO¿gµAY_j*+YÞS/vå—š)€j sRág°üZC Nf~-ÕY(InاÐhè¬Ê{‹v8ˆåü¼wP}Î䣢÷KYÓüú¨AcV²Ü9 +ZZ¶å7h&€vbÕ(¢‹nßü†] ÿu>VËBÏDшe2}j@Pä_ð²V! ÂÁ®ù¼Z Šb'z~“y)—I"bÉÈÎo²P¹ø‘—šcQÚóƒ/^»àkJD{eo|1È<Á~è +]V‚ZˆÅ°µ‘Åc¨åÕ,]u͉a\~ËV„§ åyY¨½‡/©JC‡°_%¿åÞ@Ê}jKýÍoy@µböEp„u~«„~‹Ê1M„(5'ß9óoi.€Ú}ªÌn/åÞö‘ßîstgQJñ‹-Á®ùÒPÇö<™d†±!‘ßñN‚×F~Ç=¼éøŽ/êüŽû /Ëýé rw%°éVÐd–ºìc¾^©…²¥üFÁeŸ  ËodU›Ú_;x?\~‹á_ºbµžÌu‘ƒ¢§àŠu¨Õ½íã8ò¥ U'‚§¥ C˜?öÄ^–1Â{üÞ ,Xc®)Â7BÁ½[ Jº‚{9ÐÆkäÅ¡—÷  ·«óÀã!/‘ üí@ÉÐì:2/ä9ràáœÝ£œA-zöól·x뾄8 Ý"€úyà2qù²Ùý‚»`ö°†)…&éwœièwÁì ¤\pK·íÙÿb@ðn™ý¹j›JÎa÷·ÔìÏk + ïz±qã¹!_˜†zÔÇg/ÊUj¹KÉìÙ‹t¾Ì^>ŠÍîçÄŸ[þmÉÐœŸ è »¸­HùœŸÿ@ãU´ =îƒ —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˜Î»³™ê˜ÐÏô^Ëb8 + îSØ€§p«.k:¯{¾zš]ß”¤±”÷ôåèõïù˜»ÊQÐâë™÷úÏèmÝSÆÝqa_Ãq }(€ö«Ú]‰ˆÒ·ñ²ìo,€¨×I +å¥;/ËžUíyGžæÉ Ñ„Kçy®dh~kýÞ’´§dÌoýqqgdÏoÇ éÂ^«lÏo×Ê€àõ:ÿvöBzÁ‰–Þôóo  y<ð°À‡§ C#‚ÒwþÝY¬Ð8¤da›sþÝÙ•¬ùÏ«´È¸ã+œÎŸ{þ¨ês V•âeæü>”™óûç‹:áËð Ìï{Ê€ðôë®Aªdˆ÷S¿žhðn6q^N¼Uï@_¨}dLºj¾Íçñ‡úªt@)ž?€Ìÿ*M}}QJÉJ}Ej"€þûAê¢&A†wÁ‡  Éʸ¡Ç«¤¿ûƒ†Î7 ¼ÇçR²huà•?þ ÄÙè¶NŸ?ÿ´ZÓEM¦—–á‹ ÑP×’¡-×±`õœ/øáqAËè3~Å ’éÁæä‚϶\»?©Wܤ×Ð¥»à§¿ÐsØôÒ¡°;~ÁkøŒ;ÔÐSJÈR“jÁŒŽhÙB>æžç‚eKКvꘇ¨¸ˆ%wÁšÛ%ÐZ¡¡tüF½`ÍÏ„iï_lºÅ©„(NîX°w±áÏ™ÏPÌkå +‚# ÐÑKØXŽ¸ÇÜÁ…† ¢çÕöxŽtl·,(z©dè¯\~~¦Æ¢Q‹°ÿ+÷Q´æ9­†xé+pà­yÙ€ ôýëtV½G>¬ ÿuº¬* +ðV‰º§Ü—K¢¡Ú%C Ë*-šZ¼;¶Êø ËþX r°>¾°\M>œ®¾áÉ\X®–ªÚ^‰h÷H%lMaV½S&{“I˜t®à², L+Y*!,¬ÇmȈøŽTCw + Ü/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=xÃ9aŽb—î¢[ž'¯{;]ôØàà‡¢E]¯@õH-pÄVTzÑcO^–ñbêÜòK=.@}J¥. xÐÒòvQŸóÐÀ>¬®QB+ôšô/6à©Á¡ï©WC^àaªä#…IØTÈEÃT°;¥ ÇÖ€ÉEû ŠžE ¯fqHÏD!¬†,Zx½Ú§š+Åè(D,Ϫ‹öeÓâj1”¤x}ìyXüQ=‚Ÿ[üõÔd†lÏ;‹¿>"€ÆÏã­BÙ- +òâñ Ð~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ô¾º(K¦®ÁÁÆò’‹² ÊÌ%Çzó1§G±2ºäØs%CKË©ŠÊarxú›+ih¿ÊЪ¶ã_€ +ÍÒŒ^({Ë^Ó \Nxiö<tá%¬ÐP:c_eK/Œþ¥;”9I飶ð˜¥wÏÆM8w x<]_2 Ë/kò[Ú.ëº]=¢ËrQB‡.{$.€zSËâµcðÝ-š(€žQÂ>AÏ;!KwšeÏÜ%^`Gßð…¨jèeô|¯€ ‰F-½U—=ÿŒzùIeÜ„B^%x-{¹·Á»eÙëªEiÌk˜¶Œ×sSû)‰`oȲ×ó$¿ÔÐø%, †ìd!:QK/§eCö^»¡é<&ÇKÖÄ[ehUÂch"åè Ag|èåht6'Þ㤪o@Xªü¤¢L¼2«”p'ó§3„Ƽ[¢àۦㆾÂkwZçßy)ø©wÙéxÉÐòÃÕõñŠñcÕhùˆпUð4¹ƒÂ¶c¾üߟ  /îb¥ +À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$ê+ÌïÐNuü-r F|µ*ùsLJp°ÆÊǧDO,êjj@xž/ÞVÇ’·òñ@ÉЪ&/ðç¼6—8øgU“>§`UÓ‹ÔV¡ W±‡ÛwUÓ‹PH•/£V? Ç’)³*4O%8JW¨¼*ÑP]{SJ5Š:–¦«®½Yuü*¥Åþä3ž‚Ž£%ÐF¾€’ê…C[ŠCØ»¶ªë—<ð„÷X·ïª®# Þœ«º©ÃéÅ|D-ŽýUÝÞ@=ŸU‚Õ;T–DùU=_4 x·¬z¢‹¯ ºe«œ¤j[Ú ¬»°dhu¿Õ)7N,šÄzæê~…õÌÕïª|N/}ÔñµNcèˆÁ¹zGé’Ë3èë +ÅŸñ»ú\¥ûQ‰>ª² …Øê/JK Ó¼}]Þñ•žÓP‘áyúN´¤Ò –®Õß…Ð%Ä"äŒY +¤®3D½•]K1 +VÇfÒê±w IÓµB|X÷]=©@ͺRsr‡Ÿ-VÏjYÂúÓêE;Sâ0N`;xõ¢½h—, +…Qý µ@{uÿ`¯-î#±zïÅ!ì_}H¥’Ç(¿ÇŸŽ¬¡«ЩÇS¼û5,3WŸêU2´¦Ì }½Ar¬††H U¿€Dk‚§eýCSæ$5â…cýCƒÐ +Ö ¼Â aü(³~EZùn@;©baKo‹õ+¼×oW-"Ô³Eðë·$€öý— xJŽâä³õûÆ”tëoM‰hrøá¿îøN‚݆rcxûRà{;„6”ûÙ€à.ØPn›þœgâBumC¹]¨2±óR5}Q&d@P…ÜÙ]«käþÆ×ë†Ì'PÖßÊCEQKmæ Y§ŠCøÜmÈæ‡G¯ñ±%A`CöÔ@½H¸[—.2Ë7g@Pªl¸@øJxe¹nµá‚ãÅ¡ÿ›3Ô|,7Ô²Í"74ÿSÅîg—‰kງÿu±Î%Ckªº jƒâ$±N·±æ»¨þa6n¼Ð~¬dm¬ÿ·jªï) Ê‚Mo@—^2qCþ¤tþÜ¥Ð5\Í‘Œˆ ¯¾Š†¶ + V:»’c¬ olu§:›ΠåÅ¢gc«¿ ¾#ll[>¥jSª<ÁÛV@÷¨^)qOóóÕØç)¸§»ê^2´¥LÇ”éF"n•-eî@5˲°wM’¨¥Hù–šP½Sj­{ÅÚ _P.×…$U;’ÄoÔ[r{‡ð.ØráTvãPòh{C¶\8À I²%ù†6»I!ÅFà–ät…JÕ$s2n žÞrEm‚›në…*ýÁQí¬°ãlë…_ + Ž‹µ‰¢büpY¶v\f@PÏÜÚé(+ÈW ±äânítBuy[7á“Ä-"¶vd@ø¯{õ(_Š5¡ðs¯ž@ïÜÏF •Ì¶(~[ßyP ÓõŸ’^D7Ü™[‡EÐÿfÙñº³Ãc¾õ‹ÏJ†¶=W‡@¯åv*l{®‘Aù´í¥õ¬ÖR)hKìÿ¶—6  >*G‚ÒŽbT +¼Ï³èõ…¬´SDwqn{}©¡*µ„¼Æ,–¬Þm#4º_ŠôÃŽ³m£3 ŠÃm ®a…Æ5p_‡]ø‚ ¯Ý"e’P¢µ{8q.ɶEw<-Ûo¾]«µîF±„Xl¿ù^‚²`ûØ+XØ“qÁoÔÛÇ^m@pž¶ÿÞ‰9=€8¸XÍöß» ‰ªF¹'¢þ1¥1TGÍ™ÃâÒi"XnŸ3_­ùŽ§;™NÎík~”@«ù"1æ`×÷ö5ë n•íÇòdz‰zø¾Û¾ñO´g4‹Ã…7Y6ÝžïÐ^­õĽçx·lß[Ñ€àݲ}¿r¨`$NôÚ¾ÿ ”Ï ¬>‡·ïþt´!+4^£lml?Ú¤dhGékôµáEZ VÅ!\½xGù”†ô>Š¦`Gù¨ÂElNz.pÛQ¡‰A黣rªy z×Ð<Tå0oß$=ôbrG•c(ó«ÿ^¨²e +2OÔ3w4¿W«ÚTä ;öw4ï$€ÂüΆ¨ŒÞá?ÏA_s†®ù( Ÿ0ƒŽ¥XòŽkþc@ð´ì¬Üöœ'ä+VSŠ¡; |g^V×(}Ô÷ÊŸË + f³2špÍ$KñÎf§ ÿR—լи椓Àɱ;»¬@¦§”‡hÔâˆÝùh5ôË/èÙ¢ºó±ëP÷¢s×kÐbQïìqžzZEU&)ßVÀyçÓc‹CØﻳ÷ã©MG ×PñÛÙû)ôLSVkƒ”œ… ëí|æô\%¢½td_` •@/lP[…RB¾öÚ*€† Ñf’+Z-[;‡ @ߨsçx Ä|Ï;<™ß4/ÚÕöQVC’ž¾«m‚Òw×]wiW@ÐK‚ÀÐ}¨ÓduQ{—™/¶VCÓÐ#EZ ñÊÂM·ëÑrÕÿ]½¸MòˆZJcîz*Mõ×f7µiòõæÏõb@PŽïð&_ÔOèëªÉŸ0Ѐð\‘r-ÅÝ{ +ÏÓÀ5è}N ÚÔDzUÞ¿^ Ý¥•vºö-º_}¤ò€¨ßHÜo&ñÀ?:n@x|V_)È*U—WÜõÙ…¥ï®Ï8Ñ+ìU ÃNª]Ÿu6 ¨ïúü¸áæDðU¶ëó"4*Mð®Ñe顶kTÂ;sÌ@VFr}ãpõ]c^–_§Ü8.‚«ììúe¹[†Uí•ÇO)»Æ–@›§Œ›dÔ’ú»kbXMV-oca*\å{ÒÐG„g|Ï~žÌ¸§háí»çˆAu×Áÿ¤D´µ¤ î:øYÉÐî7UÃÌ()~A_êJC«ŠCØU¹ûÖéèÙ8lÑUvSXÂâp÷7[ø ƒÑìºû›äÝcžÕW>¥Ãa§Âî1/ + _Ú§&3éÏÔÐh,—âQ­ßp,äî±Ü»ÿT!`Ô͉Z. Ý@ÓÙë•ßðuîàO  ™ñÀãta'úî™  ¹£Ï©kAß3=nî´”»Óx…¼-%v/=m@xž +›ðdR§E Ù]Ø\mܧ.EjÓòõæo<(€¶µO)¡¨Ïù¢¡; ¯Ýö§SÆ2]ÔPØïÞþœÚ»* #ÜCŽŸ-vï]'€ö±Ùò†Ž]•»÷M2 <‡¸F‡—ªÃÙ» 4 <¦ÃªûhœJDQêüÜá-èX{>R$|,eÞvë €þÖÉQ/Ø‹ž¿?4 üKgTJ†×j:ÁE»Ïô@_ªÏQ®_ԗQ%C{2›³BãI_«Ä4†ÂèV\ÃÛ±TØ“9\ÕP<%Çzm1TNåLÐœT¸„ޜɨ®jv#çwÔÒÞcOÝß Ê‚=§åTa½`ÏÅï  ÉOj¥ÝUµ}Á?z΀à}·gž +ÜŠI¡ñ9:4ôšÚ¼ŠÕ5 +!ñ=¥h¨P½…§Àk,jøÙöioÚ@Þt*¼®ÝÞ´!¨ò^¥EwûnºË€à˜öuU=ùH¥¥Àpûîëz·zC¥‰xAÁaKñí}oÌ7 ¸Ç÷½Å‰ƒÔP%â+ Âk¯^GCž‚’nßð\¿ôÇBRÒgÈ’³ï£Jõ‚}ŸuãÉtшÅ=±ï³'ÐçúuÒkžkYàÏ?1 x·ìå%U…T›a»*÷Úi@ðÜíÿd«k! +jÁ û?™m@pLûg³K×Ýuî!·|nv´Wµ(¥0" +ü€ëþ½¹%Cq1/œÁ×kNCõЊ|)ºÿF,o¯V\#€Ö}¢„º†ÆÍu_ £o1DŠ_‡¥8úž:]EdŠãÃyàtÀ€àËòÁÒã”9IåË\Å~î`éI¨ìo©«,æn(Ÿ–'€*(2F-"B>73CK‡°¯ç`E.¼@-#1ü(s°âm„ÿºtÀ¥D/[)èƒéy(/[]@^N•/ÌQCç  æ×°ò)@?ÝÁæ7 + 'K\®™kqŸt² ž»ƒñ¯Ù¸ñJÏᦃñÑèÖÚ)×’k`/äÁ[¼¨ÞÞ†¯¤KúÔZ Ýf@P>ì°ŒÕÚˆ×2oßkнMÕ1÷ +5±çáབྷ” ºT_ŠžeŠŸœ]ZÅ€àjÙœ…½«Îø‹‹ðçZFP›!ìZ¢4K\Ï¡6#ÐíIv*P;©Ý~¥êR†dz±(~‡º”5 xîõ óǼò(&€^xMo_ +ÄÑ]‡^è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š7 (Ç6š’Þ“?†ò ÿÈå«ŒJ>úªj¨‘A™y´ÅàÔ碮ÖÂÑC -~cU;NÔXªm1N]H-0õ¤Ã¿úrt­.r Ê"Z “„×î– Cæ$TÿÞ²Õ€ ?zÇ´ÓdºŽéŽS„©Ã„”±LY½xঠÇ.R& 9у0yô±‹ oºgƱˆvÿüˆ¯¸ü™I¨ß§|m .Ÿ0öûª8„kékÖ< ŸŸÝ[;Ž5‹Ü*Ç"Ú¥› [Ç"ÇPëÛù¢¦`^Ë•¬õ}èÎZ)å!îN(TÚÝY߀ð˜îÓEU˜¼¨Ý·Ô€ âwìQŽ/;”roùÜ£ÓP7Õu…ü8 ÇR\äX·×P÷żÀqj-ŠŠŽu_i@PØ{ŠdÚ*dŒ¡&èÕaìT ,ù ~V=öêÇhÈ7êHÑó@(ß[Ž c@P?öÁa¬1÷ÂO`…æØ  Už"¹CQ_R•†~7 <ã#ûñDm,^Èc#ß2 üK‹TU^¯”{Ä’vtlÑËõ‚c›ð¦#'U›¸Ç6]XÂ>Ö¿ß¹5 Ã>œ¨ï*Kcèvô®z ô‚Q"aì¡ùûÝëÐGQ-ÄBq[cö¿?J߀ +ÑPÌßm[C  ½ª¬©jàÓU44¿dèxÝY ¡[¾Î¥!€ÜÏÛ7âµ ‡×Æñ Ê‚ãG¸°ž÷Hë;Áª"€þVARqº7le”ŽÿýÁ|üÔWlHÄ<n•ã§F• ¸(MôŒŸÄO\TAµUIé‰0µØ²to?Ñözt[N@?ƒE"¾^)i Õ@Œ`Ñ“ ”?ìž8ñÀ î‚Ó½2¹ôܤØR<™Ó?@ïø¹Ð=T>R' +>0 xZN&¸ñ ‹ [B +O&ÒÐåuYyˆÓ7q=Œ“—×/á°Ù“W~tNiXÂ>N^ù‚'øäÕJ>EU;¼À'¯¾Ð€ 8}¢KÉЙ2ªCœbµ´%R!¯Ì1žÌûï5 ¼ vrRÅp!þ³÷2 (ŸÎvº+ ûI*/‚¡ûпT‘Jc [×î_—”ãgÞʆ)kDqxñÙ‡w  GÎðAS„1¾€Î>ZÊ€ðVéV#åT w>wÝj¼^Ï>[ÈF`˜¼§X=ûì&ôbeö¤DZ’ϾXU½ÉÖkÄ+,a9Áo¾'€ÞMgµ–Ì7ßC6OÁ»U ÏøP• ðJÒúñ熖@_d!FíÃ,‘/g¿:+€Fõä#Emg|ÍNyࣞ2 8E¯ré92Jýñ™zFõ—ºÊ(J +NAQ¿IhÈ«Úµäð–êêECú  óXÉ¢ÔŸ|ÒPC4l>_”ÆæÓÇ5´Xø-µ,@`ðdŽ/€>ýš§k‘9–´È¢O¿1 xîŠ~úV œd‚–>E?ý €~î§ð6ËUVôs×âöaý^† xJÔ´º.ú½œ7€jHç+x¢¡wÐU+€"’aK»¢)ï  éÃøHѦ³Ôc-šþo‚÷]Ñ,Õt‘ +R?¼Í‹fý×€ vX4[y×bäôŒÆ°jT4»ššs/KÂÞH»hΕ„Ç4ç&-zH ÁEsn@+”ó +žñ¥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¸tr¸¡›³Mé–uÕVñºÎã®P.tê0R]@^â/®RèBc .p™–ꙞÂcb.RîBk‹CXô”¹®w@?Ó{Wðs×½`@pÆËüÛ+©FA¼3pÓ•ù÷4tv+4 ¯°\–2góK†Îë:›ð , Î뺠„߀ڜ×íeVÿݱ‡}©äzUõ¸LMe6‡|©šj!€zq´ ×ÂÆ"ìÏëuzº:O}'3ºP¶âú0•þ Aïš í@Ïqì¿W…=»®¸ÐIÂ3þ<Ǹ*d0ŠUmš-€^{š?/UÓ²é^{Þ€ð/½®ÚÅD¼Æθ ¥ Ýc@xžúo`×9p}_Úb@PÃ8o€Ò ’Äq™\:߀ ;ïMU?ì»â‡"j%€ÞV‘yqÏìÆEï]è4øT€ŸÄƒ Ç×,ž¡!¥ЇÛSê$„Ÿ0]húøo:W ãÀw:)€¾¥'5{Šø6/ð×ß¼ƒÏûö8/pœ–†»Ð)ô‹×·Û›Î„¿\§†.6 |Z~¢y0á+ÿ¼ß†2ÝÚœ7^ÝÁ”K½;ðÿ΀ðÚM¨©D4=©Eqi:_ÍRk§Ê”`¿¯ }k@ø¯Ú’:R‰hË.´C­}™Ín +´ñ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ÚЖ9†°B“¶á6Âk·ipÊò·ÑЇ„7ݦ‰lHx…%`J† M@›ŸàÉô +&[xóShKZjÓ9® éBåÐÖ<%ÄÂÔXÔÁ—bÚÖ /Ë6îúKaŽîþàB¿¨;˜¼OÑÖ}Ó¶5~ ^ùiÛ~üÒß{Ï™I¡°e«ü}À€°|:®Q£ê% Žéx# ô/ Åkø’ˆõç^@'ïe‡kD,†DÚÉNèTù”ÀˆE|’xà§*— •MÈ®%‡¶ w¡÷PÝ 'JFðqÝ…6 L†õÒu}RECŸ”™e³¸†«ÐPÕ@ôVæB£‹C0·»MÙZKÔ²x­È,^í²µV + óU1¥’“v„—åü¨.×' jq•­Û[ÕWj^ Íü\ý:¨Êo‰Ð£L÷—r¡Ç  +Œ² ¯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è´ÊìÃÂ>Fa€øA­\æk¨áo|Q“ůIåŽ+ážÆ.´·JÄ{.„¢§\Ãè‚|¾€(g!ˆ×®ÜsP=&*¿Û˺ÐnÔ¬ /K˜Ô#,Ë5k/€.Q“ÔÖÙ½ð±,(wÉ„wf°Gêzµ=‰»Ð(Ù¯$©ÿX”K^d@P/(wí7lR(YÒ²U®ý^µúV 1j¨â¯Œ¯¡PëÏùÚ s2ˆ½FåZ-€næÛœ±öån%€Ú²}GÍ¢–rm v*ZÐ5¸¨A)v¢—k@·/âcNAËdêDÔÿ ݵ4evƒQ†íB« „.¿ò¦KP¿egvùÀà-Uî__ôãŽjbåþ5º8„5±r¯h—n"dy,÷ðfô¨ê”žðÂXPÀ… +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樵ºK¿N&CNØçÒÐY‚ \þÞÙên¡nGŽ/wRC P×Ò¼Çãä;Ä~ßò]Ë  îª¸dÅm!å»#€zê:£îÝéàx_j+€zgÏC˜|F0Þ…>@Ï.UÒWu>à +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›úúò”®±½â–ÿº¥™©…X0ÅE](Ë€ðÿVåvÇÉ͉ZæéÛCÅ!Ë<ñƒ¿ÊŒYdÁ·§ Ë‚ï•·6áùXCø©·ü÷¯  1íXc%×JÖÆq¡ÛÐ*¶6éUÙÁÕ‹]h¬ú½x–SæºPšáÃ9^¥jª,_‚† + IºâÕ­Å!ô.”.€&Øÿä)¿kb“k  i[ùpƼ|)¬k@xg.+£?G¿»¹PY´|Ûæ^î$Ìár¡¡h­z ‘"êwzj¨CÉP…wt{YÚy­§Â;w”ãF©dFjqÇqø^…QÍ%Π¥x_v¡†è—[øŠQ6=þ©ðË­h÷—¢]t°TaÜ| ´„U£8©Û0ÇÔ…V + ñËY°RJJIU¿ZMzBoW5ÂÙª.ô´A™Ya²jõCuö‡ì +,Uþ7”ÿbJ…ŒF}W.¿šñjÊ$Iº¶þÜŒþF…ÙÍÏ <ŠóÍ](,€æ–Ój­û9œ÷êB•$Ð7lº)?,^à¹cÐüËØÊWÆ T!+Ìo!€þÊN™I^OTø¹¿jI Æúro|ÜYÈ…š>Á…y +"^'DËçb„åÓ_§”ÃSµ¸Uá¯"‚7g……[–~¶¨°p‚Z¡<£ûŸp|er5t¾á]°®+ÈT W2w¡l ¤ß©òO,ÇÁøÖµ@ºí|ÜÛ,X®{΀°Û¸œd/sÒ²vמÌÍñµ‘ |l¬WØÜSíО‡:cըŽ„wÁÉãýŠK‘ +xžNž.ªXV•Ã£Þô efŲ/J vXSåÇ×ÚNî[TñQVÿ]ñìÚ¹PɪX±‡A¥½bºŠ÷“à¡ŒU8ðôŸP5}î긎oΊÕÎ@5.ÒÆ úêk¨©ªùf1Èç‚ÓÐ@”]•vªYÁR¥bvÀ€ T©˜ÝI ª¬axö¿PNEVhBÖ +Ý.TÅ€à1¯X—«[QÅR×ìÆSP÷N§¥çå{uÃlmT¬w‘j¤µVCÕ%.î¸ÿ‹ÂÊ.TG5Ù•Z'ˆûâºÐ>Ô”ßÍCQÁ/•š~'¶§. °?/Ÿ§ é.ÄaJ5 +Ã.Ò.Ô®8+$¹î‹ë•žÀB¬R³i„OpPx ýS ¡Ï ÿR"•]Hê?Ñ•{ ÏøeSSS‰øjìkh¦j©Ž»éâQÜâÝ…ÂH½&Ñ |0ì /æ)h9UÝÈu"^íSì>­tãtÔN7]¤¾ ¸U¢ 5@·ïðeÂ6.´ß€ð”›´lºÅ? + ¥¥ô{¹WðJ_š&€–Wå‹š²n¢8€$}y T8È0'¡ +™^øZ¯œè^…X'f9Áëãh wî ¸hDZ©-oK Á|ÅÈû„Ýñé[>4 |Ì·%Îð6Ã4}Ûåh{‚˜êàšy.t™áµÛþOí¢·uls¦oHí¸…ûütü¹m$ÐKZºRÚ©¾£¯Ú£*kc?²THJßó@qÈrí­Ì ì„NÖýw¡ª„wÁ~Î%ñBÚ#øí5}EtXEĆIõ ;øÙ"ýðÃèÄ»¬†P¼oÐrQŸ,€Nþ[+4ô@`Ù™'?@§×¦ÌnŠeÅ“yzƒá|öwÞ*®( Æ-kwv¼áÏek¥ÝShðV):¿d¨J©a¬BzÕLð²T)õo”>‡·/]@–ÐË*éóP×­ Ž˜,x8«d} €j¨ÞÏI¯‘åm£J˜ªùE@?¨EÖø*5G  À»¬†xO2Ø'V%0XÕ땺¨cþ,Lþ\½g$Ð|èá×Òu¡_ ªFUê+Ç™×O1êËËçׯ)€Õ¼×}^U.8O5»PN×L²<©Ò¬©A+¿Ê°Wø*s¨ûVhª {CQŠ_Œ^üIŸ;Ò¶8„Ÿªœy$ÀÏ`A +Ćâ°Ê™îÅ KúhF™)ç\KŽ¯À|C3PêiŽªÇX‚‚3Êö@•9ÝËX¶TŒÈ¨<_UW-o©[¤W™Cc ÿRÖ +¢U â.c.4A¯ +]ÇéÊâ^âm2j—@uî`Õˆzùž-xYêÜ#€êÞÆWÌ^w-£nG”«ºm‡½\_/'þ\îhԀݧôD²¦ þë–Q‡3ìå·`‡uFò¨Igþå¥XBå2š<,€š…X5¢C‹ã,£™#€.ÙH8–¬ÞŒKö D©”BãŠCõ‘H3 (Ä2®Œ«ƒàõÃ]¡\èRÂcºú u½†ž» Ÿà«ß4 ,UZiÝ—:dž-“Ùª¢ºa)Jî°Ô­Í¸a˜ºQ'€Ç(èòén,'€ÚVÓ L•Ép}FÛ¨½®h¡°\{"£ý„Oðí7ª#Q©ÆxYn¿Ù€ðŒß•É‡“ÂÒ|€Ê2 üKusÊd0MbÇ~FÇZ„§à¥þSøõ„…uÆ=› j=÷USª6 Ã'ø}5P§-ýä û‚îøsv + ÇŸäÉt…j0Œ33ï-€zVåëÕ½\#V×2zÖ@:|/äŠËSJFϺè‰BVkî'}qöÚ$€^öUIÈâ‚Ëx9h@ø¯ëÛD‹*ˆÝÌ}›  !ÜzaF,®¥Œ!  ûÉ©pPjŽ†]K“«  Õ¬û’"J}1ÔÖ€à¹Ë¬?’ ®HЕØ›YŒÁÓ’yõH¸{m„-õ¢3¯þÖ€àkRæªtoÒË4¶”)ɼñtÛ>æÔÍ÷(r¡wÐC—*È3¸lSðЕèa-ÉXÆ=]¨ŽÁ]ùØVÿ£žéõ‚ÌÇ–K õ¬†xý¼°’ùØæâŽÕÎìV1å|!eÔU‘@ÕÚU™ g e‡°}—Ùí=t,Õ3»E$Ðýhw,Õ>2»u4 ¼ º©+ß«eoi‚îBÿ4 |ZºßÇ"šzÁàþæ.ô zˆ䤻À–2”™Ý•@:bŸlË“Sf÷7 Ÿ»Ý´IB"G¾döè)€zýÂÊ!XŠ2{ýf@ø—^앺€BQ›Ì|ñ‚·Tfߌ€v RÅ-x½föÍ*a_æ+‹ø˜{¥Z°+ ó•e„þª*=— kÃvQg¾zD½Þ‹ ‰˜û-‹™”ùú³„þƹ_ÑHOg¾Ñ[õãšT¡jvª¡Ñ¨ÿUJ]£ø˜néB×þëüšLJÌÁ»`À/hÐs,Äb®¸°8„2½d@xžæÏQ/Ì(6n2}'€ÞëÀ‡“œT¾`2>RïÝ+€†¨,•žÇ5„2‡1 <ð±R!²Ô +È;Ð€ðŒ ²ZK›ÅR/:s\T­äºôm2WÖ3 («öÁjH‚Œe\µ÷ Ž©ê êpR +ùìá1¯úÂôÖ8V²(ÑÀR§ê[“ ªkUßû˜]K!/x ï}&€Frœ9_"_Õ‘=Шٔs8ìÛt<ðQóÐw|(°4bÉ4®úÝKèõ€vRQŠ%Þßõ7 ¼ ~`wÕHŠX² «þp«A©RuìVV¨„C?6T»SýÑœ/ ‡¬@üü\õ°š¨ÊRo°°k‘àOÜ)€¦©‡ÔM$òk(Í€ òPuZE>œŽŽg|ZÂcš³C_Š!ëkRÕ9» iî^à•…ĆDÕ¹ Ð<~‘Q( ƒ Óªó6 , –Ìe#СÈ|•U]²@­èÄŸ£ËÌWÂ?·¢‹A/dÕB•ózÍYRëªV’@JúRéWÅaU ß@;jã&H?ž‚GÐβ)án;ìدº³¢JgÁJEbXA®º3S:Ë +WäW=\¦d¨ZÙb%¨¼†î6 8¦j•:¥Ô5w»àôÑj•ºÜtÕ*=­]Kô¶Ž‹”W«ôœª¬u‘ö…ìh¨ªª÷ðÔe,ŽC«Õ`@pWkÌíé©×I`¹Z㙨i˜•‡ˆ÷žñ¦1Â3~º¥Ô‹ÀIà›³Ú5» ÎSõÒ:É5q_I4†þ«,EϦŽcOVõ4vtè$°R=íy‚*dõ²ªÊNÈ«mñ«T/ÛPýƒ¯W +×°”•¨^¶©ªp&¥ÖºW>^àêKÔ ªWdA=€àÆêÿ#€Òñ{›q¸Uõô!(“[¼{]Æ|õÄx +2s nßêµÿ`È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]®*n9´ÀN«kY—Ç άk¸>«Bz±Ñdf]SÙ€à.Ⱥ¾Iʵä¹Ñ1t‰rRƒžz¡ˆÎº>!€ZéÔ_ÏìÆŽŽ¬VsP›;´ÙLFâX­ÍjÓQÝ\x8ê ÀåÏÝó^LCTc?öù04t¯Á=^ã—Ú,=…_Ô5~É@¿)w—Š°ð 1 e  ñIž‚8•åÂ*dñ—   劙“¾ôQ^– • Êñó{0÷Ê8X ^eA-øʧ‚q–·× ®@Íá)R!Cüh\ã¯hc딺Š$ñû]mÐî•‹xme°Rc÷C5Ö{·«cN‰ƒa_e5öî6 |ŠÚ§DtÔI`ÇY¢;J†j¦7äëÕ ÅI05Ó/4 (UjÖ»º˜‰k)Ä_³^+‚^ÈšOžka“ŒZºBÕ|r­Áµ«¹z4»B!oãaè;¿´¦K€Ã>(ÀçºÕ\ó°Z§ZþOcÍÂÒ]•5 '³™D“0>æ5 §   }”£’aKYøš^@£Z`„@û!þÜÆ„ÚtQJô¸Ž +¨¹é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²¥ú§ªX• +´”ÀÊ®XCUÒ•½nGXffWj €2UG¯{8©8\àìÌ ¯ì¬Ñ<Ëx«dg@çgœSC–ð˜ìó³P]º7éu›ÀËRçê⮩«ëÓEéI;‡³so-aC"»þj%¢Éù¶&ή_(€tàÉŒyæ)¼¨³Ü#Fñç"]ŒK`e7øÞ€ Ïnp’¯2W[u⸔avƒ3„ÿºÆ-Ú} [²R²_'€.¾•/ÅDÐ+à‹¡;PS•E÷ßcX;ÌnºÅ€ v˜Ýü6àÞ‘ÂËÒüzä¬æ) Ô:_ þœS(€.UEʽrSA_dîÒ ºl(«ÿ¤B'°[0û²¨·õN|]îyà­î@­ë§.EWÎáìÖ + 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ݹK_eTÔ;÷  Ž:¾ á‰h ÔÄ€ðïXÄS@ 㳨ºû<ÂGê"íTðB•á{K S‚ÆÀC\uÀ=œ,‡÷øCi¨ûDVk]9jIGtŸ&€z¼ËŸ£BõŽåÜõ"€žÐϨ=O·” uáÎw7Þ¾ƒhU;”t x|)>ZÂúx`èY-¢Ý#å`w|`XÂ3>LoºHˆŠÌ[~)&€†ÿ‡?çŠûHÂr· ÿÜ€ð/øŒ†Cup^Y`ÄW„¥ï§³!ANÁ Eyøô1¿ô% ±ˆ§ebçKàË®è×qí`Œ}ÝŽx +~$òú‘ÏÚ:ðk§šSF½ÒÄ–°À¸»дV綯²\¯Ón2 xZrj~Î LÉyΩùAù”¨¯ *tíoN©¡ Ћ/´ƒ‘š1ÃÙóbÔ÷|-ÄhûÚ z¨Ÿ’O´0‰¨EˆåôÛ`@PÊyëù€ 7<ãoõ@êX£ˆ— %]·sаûùp&BQ'†_nr†ýS çÆÇdÞ8¾wN @ÿÖMò(ÄØ×ðICŽúrž‡ª3,œ‚/”™9#±BCÅE,±µ9#¼r¾û3eÆýI š(€~T!…äø¦úx +~|Eýò*Ü=NŽ¥¹RÎ/ýÐï+xàdHøRÆ4´Ö€ðÎÏUT½Âév3çŒ?߀°|š0RAîsí¼é&|+€¦Ýï œŽ“kâ4¶œi–tÜ~È{´°¸ål@ /VTÿ¨/FC— E*1A!Ÿ8ÔÐ>´XYeQjÓdK”ÏY<Ä€à}—³¬K€BNÐv-ë*椔ö$ùãñç •Ÿ¤\ñˆïQFC_ Õ-ø ÐÝay ÍY}áÉ\û`JˆÑ¸ñçÖþË€ðá\wQ å¦|?8™ë.@ëÏg tF˲¬¯+ò1OÚ Z欿HmîǧÀ­0Ž>ÍÙü–Ú­‹PŠtÔrÌw·6 ,}÷¼2L)ð/ðžA„OË>ö±zw«%ð=gßÃUÈœ#õR*$%â›óH Ä€$žm;rŽ\\2T«©·Ç½”8 +…â°VÓ‡ÐK•ó… +Tû[¶¥1´N)­MÜöU/æÏ)+€~ù2åÆI„-©µ~m@ø—{ùZôEÔP¶Zû _ù1ŠG²LÁÚß%Ðrb™”xgÖZ»Ê€àάµyé¹#å. ¿Ü2‚ªvíœY`rÇÊhíœ_yíèn±ô ¬ó_@{ßÉÚ9Jª¨šy>íPnjJAŽú=£R¡MŽ+3[ÓÚ9ùü×Q“-µsV¦„møäT;g5Ÿ;ªùÅ2³vΚsG*ÃÙµsÖ¦´è„?çFŽkÄÒÀi'À_ªõ&C1/sOA­wPžªŠB^ÈD4‚£»jçí5 ¨ŒÖ¾ð*µ}½ZK~Û¨}ᵨ±r}G\ õ5ð‹DíÆGnvêž`käÚºÙ)CøH5znSì7†>’@Ÿ±Nço›Ýµ›}e@x„·Ô{‹×Þ²ÀáÝ(¡œèTÄUþ-ç.ñ•jÁ*¤wQEpŒ_íå ÈòKðVq51ÇWˆ_C#Ð5CSš}±DzÖ¾æ#tÝʾ£Ü¿·–?w]§åº!,ì]5ìë夡aèÆwÚÇ¥nâ,€nb‹šºÖE}z&OÁM‡°›¹v›óø–JxY.P/¨Ý¦¼áÜæ!µUHúšðÀÛ<*€:þÆw0uAô•/ÓÐ8twˆ-jêoÉÅ­}·#€î{= £à¢þš +zSÝߟNN(ßs¡†Þ@ 1t< @üÁ›.Fu:°NWû‘ èÉÅŽ”/"VCûÐË»S†k¡¨OW%¢)‡+l‰2©Ý§»zCÙæÔ=˽¦- +Í›Ð{§Ú'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Å€ð<­¾A VŠ¡Ážö:«Û 5=Ùœ¤ 5Û‘ZÓ»8„ýOu +있Qó,l’Ô)¬#€ÖW“éÕ2ñuˆÓдï2m©Ç#ÞOûZ cüVæõ¹±tÕ¬sl¤:aµ6ŠG-•É꜎  3»XD'½*ªð®sf¯á]PÔ‰Õ(Uô´,pÑ¿$ÛœFe{MªSôUÉPÝ©*U“z¨9¶n‘u§Î4 xîê.- èØ`$Ž/źK7þ¥Â)2è/©¡´¾1+4^‘¬õÔ]ß¼8„µžºë¥ÜÖí[wc‚2³îA]&7®Þ\àçV0 ¸3ëÑ…øi»Ä,“yä¥âþëê¥=Á"šÒÍ£X­­—ÖÛ€ ·¶^ÅXêp†#–xºz/@ê´xÇ€B0ÔEÕU…¢žÁe©IU¯n/‚Ǽ^ä#­Ö’í]•õ"Ÿ +TCï (è‹°ÖÐ?K†rËŽL-KбÄä–ýAUz*P¢›9·’ŽÌ#G¬ƒ¯üÜJúåFyÿá²äVú uZ¬®ïÜJßSlžöÜJS ‹ŠžÜJ³%>[äVq%º¾s«¨ûŽû–WáÖåÿëE"·ÊƒÝñ¹Ut¦Ìÿð´çVé(ñÙ"·Ê³â x2«¨â¶¯"`7°Ï­ò¦Á;8·Êˆ@‰îøÜ*çlNòþ[®ËJüw„Ü*º:ÃÿxMÊ­2ÿܵá…ä_ªÓ™5{*ÑÄÞÜ:] ^@¹,U÷sô’€g¼î³„gü傣υüµùsŒ—@ó”_ÅÕÄ¢T\C ÏøE=XJzKƒçé¢'%W›%;8dI˽hˆÁë5÷Oð¹Kzb/Ë?ž’@¯³ÖEE44@5n‘’* RÈ1t­bÅÏ…ôÂFã¯PSÎ “ð±¼åç6;Ï€ð˜šq÷v*¯èo[¡!Gé&½ šÜf#Pâ1–™^Û¯ÿÿ4Ç[%ñ¸aÁzéç|S1­öBæ^:R]1HAŠbk3{ÅèJåA¦ÂÅ^ýH8ð+?.á‰Üø•$èOã'ÌÜ>6 ¼v·Œa½€‚]ØU™{Ë/„Et»ŸRVU¾Çcj7Vݪ,ãžj§àÖfHÉo§ØZäÞú¦á)èüƒº¨½­â«bÁïü‹zXWÃöZ¼ãÄ܇'  ®]Sw\íßæ]»þ¥Ç®Tâ¼µaËû]îcW  \K—\¶Ô•Ü/²‰KÕ°-î‰ÜŒ_ÂwK’_ÚÇúuqpÑŒÜGŠC8ò%÷¹Vlm„‚^©! µ–@±&æ^‘„ežžûT½ÐZoWóHÕÐ-¨ï‹¬“’e©ï›Û·¯êWŸ¯ Z=Kí®Ü~ + þ\Y#LEìl +rÿ ụÿV6“è˜[Jcæöß%€ÞlÐáVaŽ„†®@¯çe¡\K¶EîÀÖèýbEïÖÂz¹ï_b@XcœÁ"šBym <¸¦aYðõKjY¼w’˜Åøú <ú²€öŒýß5ÔBýº]}Ü1 ß¥‚þN0ü¹ï3 <ðû±’£(Ëáüx€úlŠrOxíb|2SCÓ$‡XçþefÞgûЩºFž…•‡¼/ò‹CØLÊû²¾>RT$ûzò¾l(€¾nœò?¹Š;~¹Éûúb4’ ø‚>á.0¼¥òFö@£®d¯Q˜Þ·°Ï>oÔUhto¥BzïæIìZÊý\qȲv?o·gim—÷ÃÂ'øGö…^AKhåçý8Nýú7›ÝTæ „³Äó~=a@xL³æô;g”ô -0 Ë/-f¥]µä†ÊCÞ¬ehQ9>œ”Üañ†ä-ª$”jäµ|r,qby‹"(©‚×5‰cüò].RÙÞ„Eô¢{Ùkä.\Ägpé1Ý/:³&æYùØ»–·è! ô(ÏÕ>µxCòõ@Ï5–«nL ±°--oUtV\ô"ák‰¤¡/K†êåV‰4p[Šúc«TCêÿy‚?W>Û˜êÿyJMçz‡Ô%ì;Áü¹é…„Ç4O÷o¡ä3_( +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ÿ€ºó¾6È&±ntç]¨ƒ×\‰3À-©š:\&€îÕ>1 +÷õ9ÑÓzKÝ¿Ž øhÐKÓƒŸ»ƒêôª=t8±c¿Q§~¨s{6“¨-¡%ÿ®Qç; JßF]¶³ÀP á•ÿŒyœOåûÿ‡”$J¥wÒ¢†¼—sÞ‹=[–d«±f—-d—ìû¾ŽƒHEI}B¥’VIH‹´¡=íeI¿ssÝgæþ×ýëÑC=sÎû>÷}m÷µ¤÷øA ñŠ>ÝyWá¸áqC ‘;Cê +“r ðãF¾$€Æ/Ëw¤¢88œ>~…AŸ3}²7¢ÔÖeÅqÍrúä7дÍ!uE@M[¡©>í 4Wöi zwBHŸÓ üë§|«'l2×ÒW@K®eS;J¢ ±ô%eЊìºÅ#¶m謑¾b°ZÕ·E¹  Axg>æMsFß›§?f  ÍxBÌy ÂP_ ‚Â>}3;Ôº*jÈëIßÁ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’Ú¤ßmJMÄ026½*€ž8ÌBŒê{lìße”šŠë½ÐMüEXÔ[ƒðã6ªé~Œ4KVÐO„÷„×K× žF ­.*zj£è©Ûøqqê‰C&Ÿº]ƒð:½l«à M/Áç®âË) ‚nwÅ—Ÿ +©@,×ÁÃYñåm„ó@½| +(úVPCtг lJ2BNÔ üë>îoߤmð9+|BqÓ8 ­¦ð üÀ‡¿Ò hTüð+O`DãagÓát«Šž@?³‘eQD÷|©øá¯èh*ä_^Y¾ ­x´†úô6×¼b!¨6*~ú¼úü]6)910[UAïkô¨+~å) ¼ 2„TQ©6o¤Ê†o•¯  gCêš>eJë¯xâ_ô½gøQ<7E6)|Ü÷—  ŸŸf熲â89±âÏÛÐ/<@,F: £*þ²EýÊõwn/Ý”A)þú­ús"¿¸³u-C«°ŠN.ª”¦*© #‚SPeT¨sžÛMªCÝ5JßJ…y|cؼ‰öJ…- ÂïTÔkÅãöñ‹¶J¥¢ Kþў$3}–J—ÆòC¸¶»RɺÊu 'ƒ#‘øq%h~§kZ0DŽD;ð•®i­AШjÊ»¶0L…ªj¤APªTº!ÆŸÅrï{ñ;Ý× üNwŒ÷v»9⢪JwL@ß]ÍÆh̵ñ¯ûî:túIÏ‘p£Ì†Ä­J§·j^§ßùžÃÄ cP*ý>BýÍu¯Q·’§6Uú»ªúg+jêøÇ¢§Ò?cÐYuÕë†tqÎC¥³—  óerlöÓù²„÷Ó¿¯„TÀšfÞâÏòïëHùæ¶s ÝA+ýû±Á°`fZ’ÍÿuÅîdfZ ‚23³Ðj«8O4©2 @…y¹71CRKfáçóCØç̼H wÜeËPH‘yÑowAf‘Îl9DÄpm‘Y¤»R3@,Rù¸«\f‘gòC¸û^æÅ^ZšE…ŽˆÆ/~ñrtI6FiØOÇX3/¹AÝÂÎ2õŽ^ü’t ¤ºX¸õRØ̼dŒá­R´?Î5h°á—Y4KS}Sê0|àb]$7õ×í« l:õÕ ¼â—M÷g‡EÄ +š-€Š·á 97vÝ2‹·× , ŠŸðC)ÛÊ,þAY\` +X:!(èW Âéò†ì’P–²…¯ 3/o"<ËÞr[$ KpùT"ä}Jg°S8è™Y¢Œºòˆ2²hH4¶Ä2¯üHƒði)Í©MŽˆvü-ìNf–~Yƒð:…<õjQu@ÔÐWÛ1ÐõÞ½©|ê< ÍÌëk + ²%}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Ý1.¤B•Ôt¿ø4oºp–§ò)y:bH•Ë ·@Vs“4,¦u£J÷M£¨ùq¨úÍlŒÆ#ÔÆݪAX›×(ϦQ„ÆâDÀÌ$×ü(ê6Ù·p.³ÆϨæû†ƒž"/fͨVW~+C™Hf­„¥o-UQD¥ä¶agÖ¢AxgÖ)í97nhØPjY§ŒjØ*¤’Ìã±@KZÝ'€îòêSÞô, +ȼkžj¢J¤)ÁÍp]˜Ùd¨º{>~t§pL´H5û‹Ó°;¯ï‚fgPóGøÅISZúg6Ÿ&€Zz}²¨p¦á%hYJù2ÓÙ+Fh¼éZNÒ l ·ö.Šâ8ö*¾šËl½Jƒ°ÊZÇÛ RaÃ/k½á=žõNH¥6E£¶aûfí@mö²ágÓ$WžÈló†:㫲(‰|¸mÎi–m)G‚æâK¾Ì¶J OxÓQªr Y ¿xÛÏP;N Sh)a8í6  ®^Àšš¶Æƒm¹ÔSƒ°–ê?•*59¦ýgä‡p 6s€—:`»Œ¤Á~p‘ãeRQsÛx$Ðò‘7¦f~È/ë…à(0i¨’9ö& ”ΪŒ +, é1™c3ЄñJ•Q ÀàpM˜$€&¶ y!8*KÂÄ{%P[å:&r 0eNì ¼Ûn +.%/o߉Û4ï§I^v—;%Ð6Ü·dNZ+€¦,ä§dWÃدÌ)K5 ûé*¿€>†qV@æôÛ5j„Ê-ïó¬d$…ï[*·l§AðÅ+·¾Ñß¾±h©Ê­Ë  ¬ ù6¡©Oå¬MèyO‘ñœâ“ÆÐ ¨Ëãl®…Í3Š*wyJõ⎀nûWC%_å^}ЀÆÊh§c¬+¸G äöÔdc9®7~ñËÐ+üç›zøâCJiÞtC?`(Aë‰ÝÉÊC?ÌE°Ì¬üð—Þ¦#9œÀ•2•>¡Aøq“ÙÔöæsâ‰Ê“Û  )øÆ(ÍÜÀ‹9¥¯šýZÌpÜtRyöhÏ+£„$Ë0ÿ®òœâh¾w÷J);ä%áÏ2¿µá=¾æÆ +ìGƒÍÜùqkn•@B*› +'pêeå5]5ï‚u)SÛuKð_·Eƒð߬šiQVÀYVÐWhËGƱHÅâ0Nå-ÇÐÖý¼éî¼WhÓUÞzP=ó¨/ìILcýLŽAUVùe¿ÙMÅKðò{hçpZ±@¿Cý\0Te;PÅ]LrráA¨²`ºZò«¨—'…¡кU|nâ–Z'€rÛ° ™¢ö9Ø1­’Û^íΟ%âN‹„ç®ÊÎqÏ]•wxs·o Çzª¼;H½_“·o”ÒQpx¢Êûwjþv‡nòB®å_üЭèðËþŽØ)œÎPåð«èîXsÒâK™*ŸŒ@Ǽ&ËMW¸ÝüâÇ>@Ÿ±MGéű@“(m@ßÏå% (Ð9‘_üû…èG¯$ƒæÀÛaCòt•×  ¼» Õò¿ø?sÐ9u8㎊ Ümðãέ/ºã +ÎÒ¥´ÙX ±;®h,€®šë 1z\4‰C&w\µ@e\Í‹IeGüq…P¥!Z¢y¨¦> +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«ËŽ„ãNF“¸pä\} ”›ç’„ éV‘sÐù“2¡T^CEväü·ù!¼3£¥~ö> 5®²-ÒúE]íõ>¥ÂA7Ô¡)„ÿÒC^˜Ù­;ÂéÅÑ!¯  )c”pñEvtÄ?èSo«ð|sË+¤Ax Ny‘¬dÔmè‚S,¢§š  Óóý˜R裧ktI¢×W!“(N¸Ÿ¢7@çžÌ3×ì@å¿ø¹íC±4¯2”šÞ‡#)ìÜÄÒ^@Å2ý‰E™ª*¼‘·Tp’´¢ø˜Ç¼¼Ã‚ 5Õv#Ÿ0+ö º¢„w8)¡%–Ä]bW\%€Òy‰”¨¡t%–^Q•çFhîȶ86ÿcåÑ xîbusãˆC+ŠôÄ"hT¯±Ä41iDš!€žòL#wàSÀíVÐ÷¨›­çNÆ¿®[Rõè©D4]câëÂXÞefìA.§¡ááNûˆ=˜@y *^`Ððy$Òÿ Y74PFV8)© Fßɪ0‹°Nâ{N«Â\ ‚²ÀªXÌ{q*ð±8`mU,‘¾¹eñ59Þ1Ãu¡e­Ô ( ¬ºmøpZîÅ1~§ºPcÎ舤hŽ™XKiþuw«L¦¶ÝnëîG4ª2ë¯OVÌ1×¢V§[÷¼ €Zð;E(Œch‡gµ˜¤AxÅ[zMÊ“”`l.ü­–¯ + NìºQ¥³œx:õÓ ¼N]ßô¥3D±h~\×wPO¯N1Ê3ñ.èù­zà+ê¤ó,;V¯4Ô»-‡LR‘8U.`¨ƒÆáxM“xáb[¯Ax«d{³0³Öí ¥¯•ÝTƒ då¶f(ŽÛ)lY¹Y- ë¹Bù†¡­©õ\ ‚Ö¡õœjE¸0N°ž; Ax?íñ"qw\W — ?nOë|P —‰ٙܡ›ƒÃeg^)€ö2:ÜØp40¶‚÷p–A©bO?í»nᘅ¹=ý7 Âï4çev“¨MK`Ø©‚^@‹9Ã:ê,'X‚/¾ø´ÌË…t›;âÿºeCЊ¼}Ý)÷8^`¯xX娶\ÎÏ·âØ ±s®Õ (Çí\55æ&„âÏýAmã>4tA‰âû{[´ûlH]9>-öîóù @§†ö.â µv +´]VÐR ‚«}òɼŴXfÚ'ŸÖ üYÎþæm_¨5t#²ÏþU0/<ˆõ© +®A0®ïíÉL*Œ˜®⽋  ½ÇYôÄÅã{O Sù˜SY†a(GüÀ ôþe!•Ê›Œ¦°RŒ¿_BƒðŠóM + ©\‚CåÐ' üðö Ð"ôåOþg‰Z‡+þåi ‚Û7~ÞK´ñ.¯¢ø7~þc Âïôß½þ‹§¬5ÿ/Kƒ ¢N\Ô‰ j¼lw%.ê&€¸T“J¦a8‰KÆküu‰knôŽµrøq×”Ëá¾µ‰Ò^ìÂ]týŒÿRé)÷x¢2×&¹CƒC^ÔFUõ\ܤk®ŠˆUkh~§:ª‡PÂùŸ¡iF¢N ‚;3Q÷ˆ¹#00tTuŽù®yøÅ;ÛCÉ›neÃÏu¼qçÄäMP¹“ìpÅÜÏUY²Ü÷]²2'ãÓd+P À«¼Iƒ ý”¬R”95)c'0Y¥˜ªù‹ï:ÃÒ7YóÄõ”RèfLbhƒêêMDSs6S“¨d׳¨Ç.*Pc=Ãx´d—PÿžÀˆx­ ñgé_DM{U™Mã +°ñœö~ÁPjN~ñ¤[º eAjNÝ‚¡j%Rì,Óá [+¨ºúߨ¼‰e™Tûß ‚¾Úk^“šø¶’Ø%©öÚ ‚߮ھ/Øü{ + @ï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ÕæÁ}4˜=5­ ¿ÐÝ^x"厑‹a]ãî•ù!lgÖ¸{‡L(…>løÀw?*€ðšiÙº46 ­®ñ@Tƒà¦«1”#£nѧaÔO¡­4Šž£J³*sLd+†ÜjŒ*#€¦y]žSt‰T@ +z)dèŠRcöÞ*)j…PÙã †j¦ñˆwGµÆÃb5Óz ¬u!uÕKYið×TåYÿ'ô º(J˜G¶Õ|pŠ앱Y”ÓãèXxÌk®$€†y23ᶱ ¨ = €Æ{iDn8>jè¥[süÏh¾rqÉ\3´,ª9ÿ. ¿né ÙîU‘ºYƒ …Qse—ºP‹ÚÁì +ê¦Aø/­övA‚Œv@Øó¦[=E=ºÇ‡nãO‡àj>ºWƒðô„ÿ8Ǣå+5=åC”Š·á*¢úoT¨¹¡´z’ƒžÎf¡Á:PÕ|ò´ƒ—À1Õâ–¡%HÍûЋ e<¸ …QóÅ„÷ø‹ÍY&(!»Ý5_l%€¼²W1Hßš{¿@û–¨à‹›DEtÍ}+4ï‚ÃÍòîw P t,ÛW¯q2#áb{TƒðŠþ¿Ì£dWC¬§æç;ÐwªAŠÂñ†wúî¨:¯fÊDi00¶ jž¿Zƒà¦«U¼$+jç/üÓ*%€ž¾Ã[j~ä1¸éj=@ÏWôg„>K 'µÔz¾²Ú5ˆ  ͼâ%Ø5DƒàŠ×zYu/¦$Ç(ì×z9,€~¡«cj§p†P­ƒ'Ðae‰ÙÔê‡jI اTÞ$.…ªuø& ¤2bSnI4!k>#€ŽÞÎF;©E ökÍÐ (zj]­'}|o^ëè ‚æ­Ï/ ©K™”ã—B#«Öç%ÐwÍÙY¦cnp»k}×J}ïE!S‹VÉp8¿ÿ@ƒàÔ¾XùÁqzql®Õ¾¸»r«Ü‹ìp°U=î= ‚2³v±],¢cÎã"8¤v±—4ÚOµ/S-Õ’Tž…£ÿµ/»-?„ok_;›'ÝôÆ°ù_ûÚyèºÙÆ¡™1—ü¸ëæi”ãµËö qR0Í4ÃÎrí²ýÐíÏ+—„Š°8¬}û h³{•ât;†ã¾µ7Ÿ.ªSj—є̀±uJ½¢AðÜÕ¹ÊdDy®Ž5Ž?K«>@7®ô.ª¦Á»1Gƒ …Q§ÜټВ£6 Y[§Üytû/lQºY +§õ×¹ýwTQõ2IRܧ}Ô©ØNƒð;EÿãÐRØ;늖@½ù 8fHÔÐ?³N¬ŸŠWð.ÊH2@™¨vŽg Simãd×:µ7 + ¦·°©MM[ ƒŒê4½M º•GØ[q<Ç´Î Û †îœ:ÄwI"AO±C#5î‚;çð¦sÌã°ÄªìÎ9  8¨@%c)|Ìï\PI-üŸ'Ýà·aÈË w  çF„ÔÕ\ +4 +-€NñjãmQzç©•ù!\yU÷uNQFÜU(Xë¾ÞYXÆ¥IYØx¨{ W}£º†»¬u¿¹MýQ'¤.©¥Ütuÿ¨¯ApûÖËÞ˃Š; ¸õ²ß@©¼ž¸³} 'õþ:V0T¿èü©5ÀúEOkÜ*õ‹§±RtÄNÌP|V¿xbO‘®Œ¥FýÐUåSýë¼!/Þ(WC^týëªJ NmŠ&ÜP3^§ëÚj^§[÷±q‡¼Àí[ÿÖ·P•{3‡n*¥Að7|¾AÈOŠ`>ßDíù—kÜöP•5|%M½Õ6oû¯œx Þê¬AP4Üß–?0 ; ô­UP{ ‚vfÃÏžW.®óÄ@!ª‚^Ö ü—¾:Çn7uA6È ¿úOR-i# Ä}ùq§*i ÏroAJ* ®-ž]+€ÎÅ•‹Æ¢wRA©‚¡» +ÿÇ[…ˆšÞßuÑEmº».åñÎA Ú3x8ïºôTòw^ËUp î*ù—º¹à¨#  iiwÝ|ÁP£b]}ÃÌ(ì¹C¨ +‚BÓØ%¡2ù8ã4 +ÍÖ x•¹Á3Üi1†!ÃÊÜ,€Òׇüô½HÀuã%HLy¥uÔ$Š.1áVi”þ“º]¥€Ùn{ (}Ýþ¨Áܨá^åâjX̆oJ /‡†Ò÷¬˜a–x£†? 6ùfˆ£`±…ѨͧC+ÄüÇ%,'µ4®@až§H’-CàÆá×5Ú*m^B7N‘€%¦ Þ(^)Ä¥¤ñ.h¯,€:žòŒQh ´ßPÐw„ßi´×²ˆš%Ç£Ñå +zK-UíðnÃs(Ä/]§Að7^»ŸE44$¾7^{P­;ª5±Ã6]ãuŸ =Ü¡ÛYÛNá^K÷,@o½ÅâÐr[h†4~kÁP“Ù*íƒ õE“ÙÇ5ÿ¥ÇK°1Jƒ WNM/%€¶)>Nlp£ë&Û +k”MžõÖÉmk³°M×äÙwÐë¯óе…as“×ßÖ ¸}›^YG4ÔÚ/AÓ+ë  3kB\p±‰uÓ3 †î¾õ‚2ÿ©t{Šwß–¦Ap î®ïuþIÐUŠÉ¿»»~Bå´à§£n/{wN–Áܬ‚8Ky—|ئkVácTy9;¦”Ã"ºYåÕ¨þ„ + ¦"†¶ðÍêO@žáíë]€Ào׬ѳ¨é=Ê4¢1MøÜ5kÚJõòT¾#èà ÓeC³^?i=Í&Ôd9æ¤PQ7›P;?„讀M™ÍŠš.×!^Ì)sÐ45º–7û™®Š ,höØé‚¡{2¼^Knóí°¡Ö=/ 9\ôéÞ>§°|ºgÎ+h™w8#nn`È‹‚žÓ ¸3ïYΉÂñ–AˆÝ³ü9´µo•8-%ŸÞ³µ†Úµ\)Šv`;óž]«З;•ñà,ø¸/_@_ýÈ£ñ& <ƒöž¯N  ¯¯ ©0³óâX>ÝóuÙ‚¡æET×X`ãM×¼H9 ‚ïÔ¼øPuÌÍøKü¸âÃ5ž»æ×<ï g)±=Þüšåxó¯åÅtL‡˜!µ©ù×  Ÿæ‡TR µTƒ*¿ùO‹Ð?ûî$•·ã_÷Ï¥]‹´·Ù%¡‹”(nuÑ"í€A‹µEáÅìºQ»8N•kQx…*áµ|¤c<šÂ.n‹³PFIÏ ¤q·¶áþ®EÆU¨’ÚO ˆ„ï¥ZTÚ©Aøªö?‹EÕ:ªAð ´HW<ÍÅ—|-’%нé¾Ã1b[Ü{{ÁPKoÞ+Y4ŽGœ¥1”‘Ù%`¨–×*Œi´(|ñ–µ®@nû z\Êí3ƒW÷3Ô¬;T2f0üZ6ë§AP·´ìè÷¤d9œܲãƒwAË/ñá´#ÎÅ'¸eW$W›¤Ü„Iü{|#€úlâŤ!(F×¼˜}@x..¥[Å¢8›¹å€¡h‘ß;ž |·ÑrÑ”s|¡¥¶!|Ú2ç´Þ«Y¶Üa])|ñØr}—üNÃn¹ã—<5”’·Üñ[ÁP«wó‹{J†»Z h.€Æñ,LWQ[Øxh5îâüö€ZÍàÛn*ÕŒZf·šÑ\ƒðãf¾Æƨå–ÜãŸùºšåó¤{T« h¶w æµ7Œij5û5 ô†¿}$íáÌ~Kƒà nµ°­oþÇLcPZ-ì$€–ìó†[ÔjßØjÉ›ef«¥}Ù1Öp¸«ÕÒÍhÅ»J°RÚ¶[­x_ƒð‹?µ‰ƒ + ÷’Ïm@»Ø1¥€á@ò/æ®gÐîÖ¼¶;"/æî,ôÆ¥l®¥"4 :­Þ¸\½õ—¿U¨­t[½õgûºµ2© ³’¿tAð—ÞQ©ß®¡\«w¶iÔœ­Ž5ó¡DÔ0þºÕ±„ÿÒç†b]Ž…Øç–AqØúÒ|ÌÉ`‹áòöÖ—~+€>÷Æ'ܾ‡­?¿Xƒ |jýÓŸ!¾(¢ÁX¶þéœú™[>ºƒj ¥š­.®Að×Ý[ñ_؇ƒãÒú¬`è¾Ä0Ïð£è©m v_âaT½¼ïH8V¶ î«ž!€ºŽe™¢/ œùr_׉øû†ÅÙM¢á œvß°è…m!}»~<œ÷½°]ƒà¦Ëº<ÎÇœ’8ã8 ”uy ÔËŽhûF“8À˜Õ/W öLH‹ÒcLIÁYƒ— + êq4lÂàpeØ(¾æà‹;§e8%€f¶åcNíH-ìNfÍì AxÅç ðÍ5*Ö„‡3kÎ` ‚‚5kÁv¸h”†!’µà#”³$/$€¦<Ínõþ1tsl?e‡šÖÂa„ƒw¯ +j­Ap·ÏùÕ9æ®ÞiŸó§Ú°<¤n$bV +g0¶ß­AxÅߊ*#Ëù¾ ³oÿVJ½;._ÔÈ×ÓþÝ hÿ +p;“AK¬ýþ•uKûCoð¦£Å4\9µ?ô¶:ªnIhn’¡wWû£íÐIÕÖ”:µ¤p?Œö'»  ?/WK@ +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Ô±ÐvÝ<{ž–Ž…†hÜ/~‡G}Z 1ÖŽn‹¾‚ ÒÜYƒ²'L“Ï:–.*€n{Ç;¤ca2éxÛþüž Ð1½<‹h÷›kÝQÓA•êxKà* 8¾rêX©®âŽ”C ( ~ñJÏi^‚èQü;£›4óŽÖ_j«P<¾êh@õVnU«bEݱþè‚¡ûKíó55}‡ŸåþRo +  +éü¸8¹%8ãìþ +•4®Óý‹óÎ]ÊŠá,Ýû.êÔw=‡'Ü,]ìÀwêû˜Ê}S‰w¢î†×Po´åÎá²p( K…s¨ê ‡4#;‰g—ª³5¿Sø{¢5Ü™]Â?iÜ™]j«dêõmH½ìR{¤Á¿ÔµØ~OÐøVÔ]‹@—«ÜêÔæQ×Ë@¥z†Ÿ›µ”‘ö®¥–jÜã]¯áNRnc ÀRA+4ºI]+”fEíˆÕh +¿x…ë4*Å®™ÓØ4JQ„çEwÍœ©Aø›ó_ i]ÃOjÔÁ]mWL¡@ðqö7¨Æãþ‹[aC‹¾®5¶æ‡°ëÚÁ«Vu¾o8n% ‹Ù¡êù‡ÜÙ;ø"»kϯÐäÕ¾³œpì>¨ÊºN^[0ÔíU›ˆ$¢zó" 5’@ÞN¸}ÚúN=n«ÁM×mÈGÞDc H:@Ó¸l›Â̦IݦMÖ §ë6cŠ§Ê¨gÌ ïºÍ˜-€æ{æZÜëg+ºÍ*€²‹{zuÛàvwË.!€ö?RW½–¡ÌÛ¿M}æåGÜÌ<õj·Ï>(ê¾v²þ WâÝ׎Рøëºçvâ0¹“† î¹ÝòC8jÔ}Co^Ì”³é ¢§û†~hÓVÞ¾î4[ì¾é´óVo«¸Î Óýºï¬$€vÏäSÎ(>RÝwÏÑ ¨ïº¿âÝÛn2Y«×î¯\"TɘEÉ︡û+j”¾ÝßiËa*¾ 4Håç~ Â+þÎ~å˜RߎïþÎAt ´‚¨‡Lºi4²º0Ë3ÿ£n <–¾Ý?˜#€ßío_ÛQAx ß#€¾̪,E)`¸š¾ûW#Ð÷ÞmwÄMâ ãË«îß?%€~Üí½8¥¨Ú.ô +Ú#€.¨^p–{OÍÚîÎiܾ=.}!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«»ªv‹¿ISOÏžÕÒ5¯S-µ3Iå&éõ¬ÕCƒðÎl2Þ¬1G¶BÑÓ³É$ ‚¾gÓ‘ÊÔv'}Bç¦gÓÑkÏ{g±ˆ¶Ý‰Ôx1ï'€F«ÐuE $tó‹þOƒð¯›Ôu2·pêeÏIM †hßM_œ%0äÐ<о§šô%»“ÎÏ·…ü¸I§ +†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¡Ø~ §Íö¹¦½ºÖëRèºnÁü¸k/@åžâœtûaà_Wn›á_—ÑžMÈ”—·ƒ¡N(Â7ð4ëÕ6÷‰\*€ìƒþ‹§‚…ü8ûˆA¥Ø§ÕÓ¾iäˆiì’ôiµ]u(ÊBŒÊŽ “út¸LÝ_„Õ«‰Óh ]"€:?̇“úâÇq=gŸÎcÐXS* Ç!“>c³5j„¾Õ½ú`êÍL“>á·ë[ý + ‚ß®oý7}¥Ž*´_5)Â/îÖtâ_×·I1”u/&õT6˜ÿ}³.@mê0DÓw C«û¶©+€:ÞÍŠš¦j†P)¨¹êvBÈÔç;}»}£Aø÷*ÏÎM”:Iaë°o¯ ÂiÄ>œTjÇrß[5êà¾3/bao;æ Ö¾3/Ñ (éúÎäJ’Š¥p×¾3Ç + ÅÞˆ-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ð÷Ûÿ;¦ÔÄà’ôÛÿ™ú¤+E: œ0Ùï“„_ü×›y«Ð ZC’y¿_oÕ øNóZô%Üžžs­C;5ʧK|Ê +Èë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‡jõ+›F4=Ø0µ®«?5Ÿ»î •8t mCv|ÿîPO÷³D¨õxØÔO¬ÏûPï3¬€lÊÑÅ—¡ý{Ÿ/üF™µ^Oe ý$€Ú{ªŒz¥ÙƒA3 ý—¨—çQ»½à"†›å½®Ô (} ¨Çþ ãj°îÒ ¼NcÆxÁ-ñ )~ܘñhçKQOO³l€Æi´ ìÿÅaÌë˜_ü½BÆÀÙ óCïÓ³  •W³#Aá.C¨ràÊë$ñ‹p²üuW>­Aø×å*K,å€C£}`îg%ÝÀª&ÐM½Ä¶ÊÀïhþuÇ=ï•æQÄƈÇË /ýÞ]Ž»HKãÇ}¹©`è¡Ÿc¾5u&{èçjµùC§ÇòV‰SY$>R_04¨úÿqVÄÐ=fPõ‡4î‚A͆z‚• +2†ô½AÍFh”*ƒöÌõ5%šCa?hÏ¢‚¡Á¥§²À  q†0ÎàÒ³PÕ6l®ÑäØ0öïWm¯ApgŽ=REz±°…oIÇ^@ •€›p“ábN¬@µ”M³- e¶ƒký Aø×Õ®¯†#X -³×¾KÕyŸÍe«à+ñÁuI ;OÎ9Ÿpû®sZƒðܹ“·›ÿƒï|Q5ÝRáxjO‡ß©éKèÏ ‰Ä܇sÚ7/$>V¡%r½±zÜü˜jóoH%–RXoº¶…òCXm î©R娩O«²Á=j>œ=?fÃÏ¢iG8Ü5¸çq4Q¥«SX0úÿÑùqË + )܌ԭÈLZPÐÄwÁ¬ž¹Fýìƒ%cüâ³F  •ï…8G~ N&¼òZu¿2 Ç ³w¯ê,€rªð‘"Ç-ÐÊ—Sµ`hÈÄýÇQ¡TC&î@ ¹Ô€Œ¬¨!î;dá´¢‹ÑŽÉ˜H¡ ¾ù À(W†Ö瀵ˆ +l:}%€Ööå%p¨8T9dí”û«×T43Ü· É=/€6ð°x*‹™·¡žAKlȶßóT™mp¸†lûKƒ T²û³¼cn'ñlú!»?@‡ÎyÛ—L#g ðg9ôŸ:쥀ÑmD2è¸Å;|³áwúÜÏ` Sã@(ì‡|>GýÌuÔTf3Œáòóhô+o:j& :4HýÎÍ’IýÄ %­C~O  ?®g7F©D¸ôwÈ7h”tC/­R!]Ë +Œ¿Nc¨ªô,« Çm3U‰ô?´Í«çLEœOlò3ùqÛ6j”tC_›ï=ÎÕeE=ôµeho!å’8¦v_õÝ{±Á]0ô­ì’Ðö5ÌPúÎÓEôÐãÕCªÔ n*Øz¼¦á¿ôÕ +¥ò‡Å±úU¶A-5ô«”¢¦ƒnxñ?Ê +šÉÛ—Z5®-† zŸxÂ>ê~ßÿÿZ•Wï3Ôø2%¢£Ž8Än÷°Æ%4®Ó°æª—.:RØxÖüú‚¡áe^˷鳜Š0ô¦Áí;¼;\”RHe÷ú]ef)Ç4 +Ú—)¨ÁÅõÌZ›.x¨†nÒ èK ¯Å0ç:¬ã¿T«½j Itbj!:¼ÉDÔŽ#4nIk‹Ãáíâ¨ï"o«ÐöúŒòãú.Ó ¸Ç‡+Æn¥¡j–TR=ü‰rÝ"ÎQÀ’nøÃÇШÉl®Ùá¸c·Ca?|ÔT4‘{ÇSI\40«—sâP ‚šsø£S•Ñî6s‡jcø£ÓÐÚld¹}<ðµêðµ‡Ð."¦KËÐÔgø†m„—àÇOÙ\sÜ`wø_ hÑÔ7FæÒß-Z + i X)Rª†…CK#¦-Îá|•ÓÛ²*£y¨I1½£šs˜·/•èÒfGÌ9š²°/5"§Žzœ{Q7݈œ»4ʧÛùcjc~Äöã„ÝsU}Ȳ íF<Õ üâûyn7µ|´“8H5bÿãè½O}Ó(A2†>@»†8YÃùǽOGì.€Ýò )là Ú‡š + O±¹Fͦɉ +úN}ÚŒ¬˜kÆû´…Á¿4Ò +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¯ZàÅ34V'hþ+h´ÊÝÏj#Å ó9Gç@ßcÈBStH=ùu¾ B ›_üÉSè©2¾`¥IŸø?u£A›nôÖ¡* DsÏ°#1zëH ‚væèW‹ðöQ²+VŠ£_½TMòÝÈV›"€ö½Ç[%N¶vqGï;(€TGÊQ®†Æz£@GU#jã‘ÄQ£ÑG¯@ÿr#~w„˜…‹…Fÿ»£`hÌcX½ºíËð¥ñ˜'Æ  }*qË3F¡Ì³¯ˆA©2æ­›•ág¾VóVyôöeüâ1/wC%лwxæš7Q÷/ónDƒ |óþê<Ájj™=æýtð+†"î4[tRƒàóÑÓ9'kŒùh¯Á<æË^Êusœ@ƒW6æË5Ú*c~ôZÒº-fLãÆüø¾á=þÛƒ~x"fj6æ·aåøØ´nþ‹SÃh<ŒMë)øG(ñ=ŽÝØ´g4þº±—«"6ˆÐaèÊ|P BÃP‰«”¢´¸tel‰Ò¨t]Vv¤Çð‹—n €n¹ÝÉ(ØÂÝÆÞÒNƒ ³<övµ”FdOco¿Jƒð¯«Ð,”wilH[¡…ª¹‘M ÝøŠ`lÍ'$ÚOîà +ÃV©¹]ƒðŠÙÝwàc¶áîuì—hþ,xŠ:Fê%ˆü¸ ƒ †Æ¥}ïAnºzÇUÆ¥ý$€.ª¢œeºÁ©—ã. +k‡ã..Æ¡ÇQ[¸ä~ÜÅ—  k¼]qÇ ~ñk¶ ²-òF4…ûŒŽ+ÛZ¥—bÁJ:#ÐP@A¥5î§qöD†n5#´XÇÙÓPâi™ÐA04º—Ø!€jÿÂ":Je98¨0®öù!,¢Ç5Ë##+`ñã<"€šé‹>è„áýÔꊪ ÿ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Œù Vº7„'Æ<)€&ð@·­^ w—‚.@“„üði$‚SP#4ù_ß‘ C¼â“ÿ@˸ǾˆÅ·$ã—Õ@ëÛ*µA~.*Œ_ßA=û¿8™l ÿì_„¿Ý¥üP€c®aµ1þ«5Ú¾–|¨ù6Ôœ–|-€–»s¸è8Ži§ƒNX>-dQ:aËQ%XÝöùp &l9.€¶{rܦ‘#Ñ@cb~ñíÏ  ƒÞµEœ¥*cè ‚ReÂÇ7ðgq;cÑ3áãreÁ„¿ ©ëdðŠ€—àãSè“46ÝÜøpNø¤ˆú¢˜ï˜¦l·y›ðÅå„ßé”Íj#á™5p N%%ÆLCu FÖ„S­5Ÿ–?°¢¦™IÃbþùqÁÐÄKTù534¤òN¼d¼ZÈm9§3L¼d±*Γ;h¼lØÐKwbñ}¨änv'£î…^‚’/ Mºõ_6kiØi`0{†þ@åÿaÁšpK2àbN*NUñŽyŒ‚]á@:?®Êy ‚뤰j䑤ò,œ×3)|­j®šÐàcÃûIÍ?Ñ x‚'Ý;†µí^ÑÂ<éÞ h>7¨ t²`O*]\0ôHƒ„ïºQKèº=Ò †Áuz¤M'߬ ['ð‘6]P§o½Ð’` $tó‹wúAõʪÌq‘¢š@@Óú‡ÔUŠc‹õ‘iÐ2ïN‘Æü¸'CcÐföï¨ëBØÆíóy¼Ú¥R/ 1ôzd×p ‚aò‚|õJɼðq“ôÑ x‚'/ΛšˆÚØ1¼øL~çõL^¾”… ¸MÉäå+Ð&Õ˜8åz%И¼iA còÿ¾`9츓6ÿ'ÿï+ôB ßM¢#“_(%¼;Ũëvš°(èP~WøOÞSÆ;4Ô9ÅAôÉ{n@¯æUòÅ£‹l^ÌW_Ñ ¼â{;ú¡€0µw‚ÛÛY½Yƒy̽66@u4ÿºƒ‡X•¹¡ÜYcòÁ4Ÿ»ª£c²›úÑAƒðbžª Ž”£¬­{TQƒðã¾ñ4‚í í„'ÓUñýÛ€0†ÍÚÉßô@ߪ´~wÔ.ØümJƒ ›’ÆŌԧÒQ@ðOI» €.¾à¿¸{ ¡KÒPñ©ìHP+è0¾.œR|¦º<¥á„¸YVPMtÅnv“È„ UÐËèêzʧñ×8ú?åê„ÿÒ<ãÁq“aCKÚ)7@›ù—c¹ãpü”‰-ІÂ,ìÝ1r¸ˆxʆ"h_644:ÊÇ:eßôsSÞ*¤6¢8!iÊÏÍòC8óeÊ/1”¤x€áq¿\,Šû›.³ñ5ý”_J ³^C„×ßmL9;DWcS]—Ò°3Ï¿¤Axgž¿à+jÇèÁw@Sþ-,þô·JÌ4„jÊ¿g5þ¥©ýÇî¤{•‚UÙÔ"…5J•©ÅT25p6 ›˜Zì[tÕ,qêMŒuðÔ«æ  k¾`—Är6]ŸM½æk ‚ÆTk+4Q÷ +nß©Ö3(5–ƒ +n¯UÜxajj¼áÏRý~]§ÅpìpjõŸP-oÚ‘‹‚O­õ¤ª»$¤®œ‘‡‹Yw…áÏÒ¨-oß8-&tLmÔQƒ ÌœÚ^%OÓÃ(©íÿÒ ¼ º<¡>p$ljr0µËS¨{ó8%FàÖâS»·@½š°£P@‡™§öj¦AЛ:õ1VŽMâÊ«©Sß@‡óÓ¨©¶{êáÇ †¦Ý2ƒ3NáìÜL»e–Šßé‡ÜÂV 5@5óž8*{ŠÓjv@M=qózèàƒ0­éwæ´Îvqca*ŽÅ/ÞÙÊáñ²ÓzµQ!rà±Û=­W4FÕ,Ó iCÛ›icÚiþuó½À¾å¶ ÌÞQÐm„÷Óc*2JÃN ‰§mJÓ ¨¥¦í<â‹Ãˆ³–xÓí<*€vò•bÜ +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¸„3¶-Cûüé'.@ßóôÇxHÙ®¼ +ºY©ø8µ2„¦¿\ýð!»Ý4Â&†H¦ÿð‘:ýiÈ¿"ˆ:N?}\ýZ>¤‚y”Ü„wæ¯èÌÿ±¢†äÄégv + 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Ϻ·›êþIÈ ÁY44ßÏê~\õèÏ.‰øÄ‹9«ÇCh`¢IÁ0³‚zh¬³†y11w$79”p †u@3_ãM'LãŠgÍܧAÐöµF5âºÅòø×­©%€Ö~RW)¶éÂÖÚOÐS5=ç&FŠÃÐî|ÖSu4î§Ù“2äšq ÑÙ“ 5O³#‘"{;7³×<+€^WÉ?ÔšÍ0noöëjÜã³õŠ`’®@ ÎÔWƒð_úÝ3×(™Œê¼ ý4û÷j×iÎûW²›D[»nsÞ¿FñîRSø˜)?çÈB ‚;sΗ9¬¨)=ÆÂל/×  ï¿TŽ)e‡ã”9ߟ@?z¡*J§ v(0æüXVƒàžó«(-¦!d2积ÐÏ'ó ¿pàÒXAßjÔÁsþVÉH,ÁêuÎ?…4ž–9g¹!¸sÌãQƒÑ>çlt~¦Ì©æîñ9ççhþKÿ>å›k–5¬Ó¿O Í-ö,;\]úãT”¹î0Á‚ kòf9Y¦Æzs¯9/€ªUbaO ”®(¨ŠÁÃ9·טº¥P¬J~ñ:“5~–¹M½”¸›d‘ġʹM×kÔæsÛü¤Œ,Ç—04g›Ûæ´A™9·Sv¸Híd¦‚î@»y$’×PW€ÌÝ}·Á<ïâþêpFÜ.ìzHƒà;Í»ÕKëÿ?‡ Ï»u™Ê,ÇÆ(%ËÙ87d^æm(Ü–BÔê"‚’æ…; {•‡T‹•â<{µáuª_‘•¢ãØ'æðãêWÖ (Uæ5¬Ê +ˆRÀ î伆Q ÂëÔ8¬8º4VPa ´G„(÷[bóï@M2øÅÝF›80¯IeÔ"Ň“†¼ÌkQSuçÊj¬GeŸðqÝ?@ýUF¥XFJÎë¿Lƒð äùœ® 34óÕ ü—Fý§+ű Gjta4EÝÜÍf)9oÊÕhF¸)R†Ó²0o¨Y‚B4*#€r‡TV¥E÷Z!€ž§â*”-ˆÓúç=3Aƒ i4¿»w‚©uAØ‘šPsÎïn  AžÀ°(k)f˜7PT nîËG²` cþà–h¼7öËÍ +N­SÐN4ñ'þ,žwÏÝü‰¿ i³tÎ] ¿ +/Á´ÑhæJ¶Ÿânc2¨æÏ|Tƒ Rœ¿Buyv«$p~ÁüPŽÅç.éùÔJ + Üå¬ïè.ß0Çt~n¶zŒ å©£©iÆüÇîÖ ¼Ç÷fø«+ì0TYƒ M7ÿmî™ç¶K ÄÇy«¼=F½··JŒ¦‰à(äü÷¶  Çó `^´‚¾@ÇÎzš3ìúøvrþ±ó褷éèŽÚŠ ~ÜÉn„¿Ý·³è¡¾k†Ròùß>!€~ó Ê5ŠÙ†ÊÐù¿=¢Axg^¸™5§kÓáhíü · -è^ˆcnõ³ ºH­|>äÇÇ#†´´+w  -”#»[ ¶Ü/€vMæÈ9æ†f¤ 8“JAP).x­6‹ê@’ÂBlÁku5Èð—>âÃI@ÂXØ/xíSôÁC Qyšï€|0Tƒ …±àÐtÞt1R‹Ø.Xph–AY°à¨7H›âOTwtŠšåmÊ_´ }CÃû‰r#Â8B³àŽ«P¶`p6˜‚k”™ ~ûÀõ8çüvDÙÆ +ˆ*' Ùñ Î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%Õ¸ºëNà2¶EÉP“5,Ĩ=’¡_Ï¢&ë5ŠÃE]Ùçt«9 Æ袮­P¯¦y/N“Æ0ÔLq×KºHˆÄqVå¢^CШ¿Y°ÆÝŽïPô,uVÍþÝw“±@Gý©AxÌUÍH©G‡¡Ïè¢¹Û †÷[Êá R@†Žï‹û­Ð ¨ïËæÏ’pœ›8¾È^KÍ%¨®W™ˆ$Ý*ÜãËê¶@ÍR|q+¯peè²f5нìß…ÝYâ8¿`Ù½ÿiÞ*8…š Q%|ñs4»Á?zs±†~¬ËŸÎÙXQ/UʃÜ+ÃÄe£®@ãùŒêéâ .ÁøGÐ_ëCªþ.5´•Xö×cUÙòª^3÷¤#죱0vL—W}\µðÌSÀ:é˜p,oQBƒà.XÞ¡=;$z )ôË;Ü/€îçNæQ÷š[¬ËïŸ*€ºzéVn2Npâ ?®ëÔ½k>È_°¼{ÔGõcuœÀ˜¡–dyŸ/дGÕbÒD¡Y>mšu±oþ§Lc —Ï*ªAp/_Ò&¤ê9cV Ï[ÒAe{³0Io¤ì„a«dw@k¼vxuB ^YðÅ׌”@c•ï¦uà­²f‚Zû/ V=Ô&†r +  –ï,Ç­._¾1!€6{¥Pq/Œƒ ¿å›“ù!][þd•<õê<ÿ¥'Ãù $¾,ßVʇ,+ŽSå–o»Zƒ°ÛÕ‹Õ«M7Y¾«¯áo·»¸ç˜†ÝÃiøu»Kæƒ ¡¥åoV÷ƒ/)ÓÌ«åoÖ@ïÝͪŒ„}—¿×\ƒ ^~àV@îU¶Aˆø^ƒðã>àñ²Ñ„ãs¥pfÞòŠ ÃOå9\¦ ÿ凟@Ö©P¥›î _üúC+Ö,â§Îk«§CK4ÊÌÛ®W‡Ó9Qüâ+¶Ý(€ž­Æ#æNÒƒxų5ÐóÍ}'06Ta®x¾µA™¹â•}Ó(iûµâ•OÐá¾y*?èe¢ èÈÓ¼}©’/ŒÃ8+Žl@'w²cJ§‘v½$€þþS¹n‘”mh²âï3„×錷âäpѸ9¼éÎ|$€þåvxoÊ~ñ› ­¼l*Î8¥ì`µ±ò²±+K¤ñAˆP}?+KÖ xZV–ô +(ˆn[1yXYò;t7Ñ+åÖK*CW^SZƒð:U¨Î¢‡.üM‹Y¡¦ÊT?cnŸ,x8WfVÒ ¸éVFx€˜³IgÓá_Ù¤AøÖVUƃ{Dñ·[@gæ3DÓ["Ø@^yf±A»`U¡Þ|q»ƒâëU…úi\ÌU¥½lA×!û-ÁªÒ/ ëf3sûÁÁÅ\uݼüá/•SCa)´d¯*wR•÷ ä_¬ÀÄ~\ùQ(27ÄõRJn¿.²@-eƒÆíµ„¯-VE¼De/¿ úÿgŸª¿´\ò—²©Ž§Í©®Ô•ñ_ªs£ú-ßã »«êü)€ìWF™øòjUƒeÁª&wø®›´æÇ5‰ + Ö³ìV[àBùU­Ïj>œí¸dÌÖHåUÐW¨g Ve1 +žb•¿ªg- ‚Þ몎ñ¤(Í'n­zàs4𳋎xØpEÝ}˜áM×ý ß ¤éYxÓuÿZƒðŠ÷:îmJº³ “>³{}©AxÅ{«$·º¯xï§óCXe÷Þ‘wÈøÃÐÿ4?®ÏͼI7aÿ¥>· + þ9,Ĩ÷D '/Aÿõ„ÏÝ@Þt$ìƒ ü¸Õ4ԭ[‚údáúì‡ú  Aó”¢þTö ÍhØÿ|×-aÄ¡‚v  ‘KC*ÄÙxa?r¹šâÝ&%¹'þ,S&I >wî¬*C³ì)'ÐL5{‡máS~ÜÌŸ4ÚãÙ3•²(„Š;“eÏJËáMöœÞg¡ªÞ˜aæUöœÖ„¿Ýâfl ÇÝ vüë·Ò üëÖÝÈ.‰NXÅTP9ô¤WÉçÎÈ° W˜ÙO.@[UÆ™í&Gà%غF½È],£ÝYLìÀg»í_}'™g¿¢T]6\þÀ¯T@ûJx^Y$ ›ºÊeï»Bƒ°nùöb¶;  ±oÓ5>nõZUr£Žý¸–dõÚßкÏóÌS½ùêu_  ­Ø4¢ÉŒ††q«7Þ§A0°¿zû;ì{ø/mOƒð_ÚQ9õñ3” ®Þq—AóõKeý%ˆE“8̼ú¥›О[U ƒÊ³ð¦[½§¼zs±ojS²+b«ß\¦Aø/ðæR +XÌ +\<òbxSᦈԃюâ‹ÇÕGšhþvGŸSÛ—ßøªwõÑ4Ÿ–å”è‰P”*«OÜ&€¾­ÊKž6L‘^ýmXƒ ÚXýÝ-ž³L²RØ„\ý]yôC˜Å!ŃÂØ%Yýƒ%€N?Ã8âöT0@;$Ð þbÆ,ËíÖ ¸Nk +=ÍÇœºÊ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ƒ[[}®juÌ[‚)Cšµ­Ž  v÷±Ãe»5Lp«¬m×FuÚÉŽDŠ Hlg®íô¢zàr÷H‘ô±ƒÌt…êŸdc”îûÃXå¯í_]ø3¤Š©ïÔ-kGü#€Fe³–ÆÀظ´níÈâhÂ^ßLÄE0üY&ìËaE½v&óHÜ5m¡©½vf34gŠ=4 Æ°éæL× x‚×Î-ËÍ7 ŒoTÐÍh ϶ ’°!Euí’ÂhÇT^Ì$y“Ø4Z»c¦AKlí Y¾‘•vÃVP[ ¿îµl†hêŠA®}mzco®E‚¶¯‚^Ó ü—>Øâoº¸eèd¾öƒ'5?îP%6C(øbHž^{¨ŠAE½ö.cs§ÙܤµŸ<&€>È +ˆÞ>aøvŸÖ øír"^W^÷6Å +4NchZö ±õ/Æ×`9Ëö  å<²-æ~_lûæ¬H@+Uá`˜jwpô?gåÆ|! .çÑKÙ4JReæ僊z½=Qµ¬ÂÇœÖæ"ü¸–a ‚/¾¾µ'zRÔ”6¸ÈVPTƒà¹[¿—â¥L&ñUÊúû@}&òb:Ûβq'„õ}&k~ñQ^…<s2áÅU\Sñ°cùb›ný¸ÐÜ-|¤Ü¶¦Xú®Ÿ»5?„ÕÆúE^.dÌ-Žµð°‰õ‹ÖkþK«¼Ö½É(ÍçLâVëW=%€Öª~=1j?ˆkIÖ¯}Zƒ |Z¿e4o:š¶2l•-cÐS*ÜŽ$MÍ´ÖoMÓ üâÛO²sÄ£†1(ë·+€^xN©W²qòÏúv + ž&B—Æv,ŽBëw7× ,0öýRéÅŽcŠ[‚¬ß÷úk ©$™!†#õ×SC¸ =_ÐbGbw¡ÿ¿¡éSýMg ›ùqÓg ÅïñV±³/ÐÐRAïk<-¶{­ ÈÀ²Ã†9¶W× ¸37¼NAOÜic‘¨Ø4ÞtŽ™eE±i´±Ø Têbß4JÚ†+§¥ŠI ¦¬)õÒÐ*lc©{$Ðyر!¡ÊßXª·A?xãUc<'>‹Ñ +'€n¬ÌƒÚ¼FMóbÞx‡*ÇÓ³hz»ma/c¹ß%Ð߬¨ÉD6Ä7–;#€jÈÎ2]aÌo|¨‘Ô4¤Bº®@„ÔL}ì›kј¡ÅñÆAÇÐP¿5’Å6ÝÆ¡Å4ïñ¡<=+Js ã¬6í$¸Œ*U­gxñ^høxßu‹Å³Ÿ4INWŠ:lœ¼ñðíè#/úOeÛÇ„Äá£T~ß’l¨Ê6Û$€>ÿ‰·JÒ›‹¡_4ÿ¥N„T1c¨€~øFƒðiùñ&ß4Š˜’§7þXNƒ°Ì<§jLÉ%1¤9n<÷¯á¿t¡=oòÉ,¬¨7^¸¿`è±4nCéµå +è±´W5ú–“8ŠÒÓú^]q‰·UÜ!T6Ž?vE1 ‚»à±ú0Ds» .îc7ôÓ ¸âYWøF–£Ê°R|̺Zƒ ¬¥7Ô,á¶^4SPi ‚ÛTy6«²hÄQ®¸³Æ¦Êó4¾Ó&‹c‡‘8 WÂvæ&ë= ‚[eSCÏbS['ç™ø~+€ÚWæÇ¥hœÞ›ÚW@Óý#E•¿x :Þ®APúnꢚf{h–œÆÐ8ÔmgŠžM݆  ‡ý´4ç d~ñ‡7燰`Ý4—%]?;ºîÌMsoÑ üí–,Ë÷8ÃmÒ¦%+4J•Í×wô?KÌÔfóõ]Ш¥lBRqàH¥1´\?ÁŽDÊ<šeóøSã¾›Çÿüÿ;ó8Ÿëí QÒJßpCJiÿnŸïÒ^t) +QhSZˆ6¥Ÿ´Š•¥”¤TJ%û:öm,#Û0vÃ`c_‡™±ÿ>çó9ïÏ|ß÷óz_§îí¯çãûþÌ{9ïsÎû,l&YÎ× Cè3N#£;jh‰4ì³Ö¨·Û^6DåBaìªÖ»â¸hË !ñUºãáú\%€¾qËäRø¼Œb÷Ä°oî@?ÿÄ + 7tDöó/µÃaCÜŒQŠ  +5’@Ã^çcîØIØ6ì- ô•wÑ›1ž‚a}S!, † ›ÅÊC,”4y!‡ ›+€F­ö¶âŽõ§a£Ö + ´lâR*¹Á¥;,mŽâxJŽMÐáTÈ0O×z“™¤ò‘ºNýãÖy ð‘dÄ—D¬ ·5^ÔÃ=á]@ш!}Ø¢§в€kâ:AR¾@UÓ h’ Ë<Åâ0J—>~Þ–y&Jàü»aËGzU†Ç“¹|Œa©’õ«!T´Õà +–õ¥RþI' o•¬#„xmEåž°Ïy ;ö‡­½Lƒð7­í­„X(öÕ…äÉ\ûµÚ2ѧjQGÁ Û2Uƒð_—¯²Rœ"†_Êï)z³O‡ÓõÍžÿµÚ­²écòŒ‡í¾Bƒð•¿»Z€’¨0<6'‡í¾J ò̤D4f8R¿ + ãÓصäxì Ðñ™ç††—šÃ¼½U(¾Có5ÿRinI…‚†ÆXÃK?+€.8PWQË7\)†ŠЂ¯DØ)}'€2ª(uÍ–s†.Ã3hñåf™Ò؆/þX-;X"ì-CPËðeh¥[ó…ØØ÷&n8|åp´å”ºò6rP` ßrVmw; ‘(LF ÕÒ†oï¤AP ßëzk©ô†Eñ?j¨Ax?ú¢Ä©µpöá‡z  £¥•£#Dî¨d ?z¾:ËÛ×Þ* ãŸpnhÄE®÷ßIÙZx +F\ÔM9n׸±u,lHŒ¸¤¢A™9¢2ë*öÄɤÄP5 ‚Zψ/á‹:ì$…›nÄ¿—K î à¸ÎâØÍ<âß¹¨ÆÓ|ÌÉH`#pD6¨—7™‘pÎ5ú Úîk™€R•¬µÛkTµGÜ8‹¯H01$XŽ¸1]Å»ñ²DíENbÕhD¼»ºk´gÜDíëªÚ#î'€š¸)ö‘ˆš+hò›jÝÊÛtI“’5¢õç†F^Q“'“žg} étº‰¯ + ÷…}”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­êöBFw×È^Q ÂÒ·wYo +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óQ r5OfÆH¾^I§õ«áá2ÆjÔzF-É*v‡[²F-u—ÅI³,:0ji=´f +íIç5 /Ëš< ÂÒwm ïz¥öxû®}\ƒ°,X«"âöG cí³„x]À»6ìKÃU@9 y +¢´À8pkTN# ¾-WN +ÿÁÆͨmÛÐN•ÃE.tC†Ú¨a´ëµ€ +NŒ… ­íFízCâhfjÉ2ÝÁ‡>Ò ¸éFÏ»—%‚ÒýT_ÍÏVî JDŪÑèù9xôâÞÐCt¾Œ^ÜS­}¹DñóWKSЫ]º£×e–Œ¨¡ƒåèu+ÐÖ‰l’D(+££·N@ynÕR‘CÑ$öEÎ  ]|‚g C¦Ìè]Õ4¯Ý®J5r²Û¡ˆÍÕ°„¿i_†‚x2÷5@î+QM9¦£< €]É=Ê¢™Gª&€§±qc©¨ïÝ\ASP±:œñeÜÌ£‹@'ŸV׆S\J•Ñ'Ÿ× ,UNº!…1ç¡È<=úä'„¥ÊÙúžSÚ1@a?úl ‚ݘr‡<Õ(jêÃ5¦Ü ‚Ã)ïf[Äœ0Nƒé6¦ü t¡{'r㘠Ûh”tc*ŒežÒ¶CøH©0Aƒ Ý2¦¢[ó%NåâìkÊ‚1oÔ <™Uܧ^§•FÈ XÇTé!€*7‰þ5ä⎠”× üáµÛ²Z›¤À|¤ÆÔ~Q]¿H™IÔL'¢Ž¹~©á¿.ÊûÉ©èÇ{|Lô„º›gœ’5ME}ÆÜÝC5Èjm‚\pøpŽiü³úÕ[ÛLÂjí˜Æ¿  &j?9Os¸ð˜&=PsÕ:Ê6–#†TÍ1Í_@-±I¡7'œè5¦e“sCc/¾‡‹S¹ÜÔlìÅwkc¯qoó=RÒ†ªI ê ØÂÞ×IA»PÈ-íD qISÓ±¡ûP¬•§´;A$h«Œ=)ö²CˆDÁa=6¶_Å×±’#Ç(.š16¾Aݳ«Ä!d[oxYîÙ#€šîô”ј_Éâoº[µp·JÔ¹ò}1 +ºJƒð<µRËâ´>À.“±­žÑ ( Æ>§’­CÎ-Þ*Ï}-€Þº6 Ü’AŸaª ëP— qs`éØ.áTçºý°%o:z1™ýð ôQÐSBþØYåøØÏÚzÂ>Žã"vc?{I ^à@4R$lá˜ö±ƒ¦BX5;¹D]£Ü¤é¾Ðk4®›×v>ä<`¨œêÞ• +h°pâà¸îïi\»qŸ»/ËŽ .bH÷y'ôÊVµÿñYŠ¥zIý’­ÌIr¡cÇÙ¸_r4¯Ý´þ,z’Õƒ¥Ê¸i5ÿus_cMMIÂX]7÷ ´usÚs†2Jã¶î@ynx1Ý‘Cîñqy_jž§xÇŽ;ÞJƒðö=ã>®[NCCÒ縳¥Î oq–Ín*ãíÛ¾îdŽ¬Œî꤭QúüëÆ?¤Að¯?âþðõ+À~ßñ#Ô ¸3Çæ$˜°åd€àoý­áoš´••Ñ„ê/ ñ“òÐ4nÙF%DÃyü´jh¶ûH¶ m`>ã6ô'RQË6þŸ¶5±ñ+›¸Sv%ž‚•ÍІR>§`ÃËo„ñØ*sËØaé;~ô{y@9mã'æŒß½Zƒð<í}Úƒ(ŽZ@ã÷>'€-x‰!ß+‰‚þ@G?S„güè„g¼°F@$ýë<\áÕ¨¸›§<«ŠèñÅ=Щk*ð=öµ‹ááN]/Ü`ü9¬#†3ãOžšàôãŠEþÛ\AiH…a‡¹›†.Ñ ¸Ÿ&Tr£¾CŽajpÇO¨t±º"äm•X4Š·Ê„+, ‚õ„ÀžéFÑ?ðpN|,€þí:Ñg”¨/d‡?üß-%[Í‘R ‚VÜ0®® (0&ÔTmuⶈöÕªä¯9DƒàáœpíhÞ¾aJ‡Ã%Õ&\;Vƒ 3oBxžº€È±„]p¨Þ)ÞtÔ)Œ¿ õÏ@M¥¨k¦yj:Xƒð<8©.ER²pî„gÎ M,û ¦¶Ef®‰e@çók7ÕöDpèÀÄó[iÔ}'^úŸÑc%°Ós⥥B8ÛbbÕ9J¡!7NZ˜Xu¾á_ªÎ'Ø-ŽçÄêÝÐ}õxÓ‘kß O¼ï?wÁÄû2S†¡XÍÄûVhî~÷5‰’÷V›“ï6ÂÑ‚ëµó¶oÜ2¼HL¬×Qƒà}7±Þ~^`ºòãø=xb½Ã¨þž2š 0 8\ýèî FkS¥–‰ÌÓ ¨ûNüO]-Û0Å¿ôŸ›Pƒ‹Ø0%×°!UsbƒI Î%¢ÇJâx•‰ ºH ·£U›¢©ðšØ`jš®®W{ûÖ<\Óy¨yÞ*²ïx¸æmS ßmÎÐc¿°À Fá†úOû]µ›Àæd’Ì$ìÉšØn’áýÔá6n’Á¨ÁJÖÄM%ÐÏ厷ü*Ôpƒ%ПÍ$[¦`7ÎÄCS!l,Oì0‘˜^|&®‚&i‡¦•|85gÁÐLô&§ø +±pÉÄ7W ·¸¡ +¾û¯ ^–·î@]~ñ*(Œ‡ëò»úÄ=-1js1Ô +˜øI[4°¥çT°…Aô |RMæäX'Ä—°« &¨ÈUÚ)„ÞžKÓ>±(™ò¥Ò¬~ꢶ”!,Íê/€þ +¨çB +y†žöŸ¨áozè 7™±¡ÄqÚCè·LŒB,C/Ì´î@/¹žv' !hp-¥½T^½¢ª’qcHI{åô*×Æ¡´í¨Ïg¯ ·Ð•ù „BN!8o\.€:M (·`<Â2i¦K ¯C0iù¢L´\ƒ †‘öÖÁ€Jô +[†p«´·Ž wØ6§RËÐ)í‹лx¸$•vÂ)>iï^,€>¸ÆŽšQ 9†ê ï•¤sD4v0¦}ÿ„ð=””nxPKð A]%m k#DCT&Ž]ßiWiÔ}Ózo@¤á`²´9ï–´¿T5G*ïex\OûkŸéæ·P9p*ÚŠÅáÈá<æeåZ¢¢8i!mLG4ÙUµCΈÁ6¹’òŠÞ“jäs*ðdN%€ÒU%©X0‰á ó´ôº„FúQŽ’Gc8p+-½P-XÀ[%ŠÚ4)ha*„ŸwÒVŒf÷Ð14fO[1^­rc¢4`Ô̘¶ê Âaë26–é±!†ŸÁÒ¶fižñ]î²D©^4Ti»n@{Ÿ-9œVGì§ím+€ŽÌS":DÍKð‘:’qnhÒà2à ò9' ./€F©4‘5žÁî‰I£6 É<'zÄW‡›ÜHMqÝÔ,35´oœ4å¨Á5VvƒZ¨œe4æÛäÓ;Ï M©Ì½UÃbîÓéô¡Z£L7GiƒË2¥òz ¿T¥O}Ì). MÁ”*¯ + +®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—ÆœÒ~¥êœPFÛ´ÁÁdS:o@}cê ‚ŒMÜ)}ï<74õɼUœD6,ì§>yJ=5Ÿ'“ÂA“XšúÔBôÂTuœði(0¦¾0Cƒ ¤›úrõW€¡ÃÉÔ—kh´¥¦v˜Âª®2x!§v˜.€ÞvÞ[ìñèqÝ©À“ùö÷èÝQì|!…ÆŠ2õݱè Ÿ¥&žX­úÅ ÂÝ`5ã‘PÒ2´­˜:¸¦áü‹èx0ñm_ž‚Á_ + ªi5oŒbµvêÈR%ÝÔ1®ÀpÛ1øŠÕ(¨PÍr"‡ÝIšçNu«Zð'ç4ôÅ +òÔ  LUÈ#ä4øÀSÙZ-¯Í Lw¡øÑÔåu4Šè©yá€Jc³ïMœ‚85ÏÒ h˜NÝÑ* œy *­‡¡'Ï M[ãn•8'[aƒS0mMi´}†§ÐØš/ž§iÛçhœ§iÅüPd‹Â`ؼ?­¸’A½`Z1ߦ&JðÀPÕsCÓKwdㆊD…ñáœ^ú5 ‚ß4½ÌE|̃¶Šåsœ)è_¨zSŒ†bVçåOï³RíãNUö½A™ ›¾ïrtðaw +µÖwÈ~°™A3iz™Gé=”I?¼ *šÀjˆSÄÛÓ‹&  âûyYÎ4@›szñ4OÁ .LLOâþgUþðŸ + 3»Ôö¥P9ìØŸ~f﹡ç©[Ñû\•ešªApÆg”¾Z¹–h™±ò0£t ‚WÙŒ êxf7ýÿÒuPåk¼N˜*'Ψ|zÌUh"NC_låϨÜJU½O V2Þ°ú?£ê©ζ˜Q}<N§ÆŸQ}’ªÁ¸T/ä»Êôª¥R)ì#Œ/ µê + ë¾q‡£()Y.õ@Á{½#ò—â­¬'€B—ó¦³lÒPÄnF( €"ù,“¸…Ó"gDv  X?o¸Ãnæ±ïÐ7”[0ö?RЭè¡€ÙÛ?Ïx¨ºjÚÏ»¨©øž‚¦ýP‹t6»-'™Šè-ækÞã­'ΙÆ6£õd Â;³õlWôDœ¦8aFë¹è…¶ž ™*ÚÌxáEÔÝmNIÁ–1±î ÂB¬¯[.Á¢iˆêÐÌè»OíÇJV’¼]X›±wáoÚëÖŽÐ#¶é©wÆÞL ´Ús™„ýÏôj¸uç†fÆjðp¤aÅp8èÌXí(Ž#gÞÍùwôä +a¥}æÝ_ {Æyf¦ð˜Ï¼g‚Aõf½+y«P«é .©6³^5 ‚‡sfƒ¦ÏÝeùB +y¸jžÌ‡¾óØ> XØÏ|è ÂóÔd3»Lȱd0“f6ÉÕ ¨EÏ|TIJ8ñµ"ã)xt²áÉ|–û’Ø¢05”,šùl®ê˜ÇŠ¥/ùžÁøÃ;ækÞp'b§Nn¿QÏü`žú¼X V²»±8œùù) Â箧ëÃpš°épö¼Mƒð²|§^Lƒô²/Å™ßÓ <‰âs7kÜY4áNµé‚Iûv…GjÖ„»P†ê›¥ÜmVÆHuAtʼa…fVÆ< ÂÝ"K™¸t‡ÍîY‹’½³³“Ê>‘/êY‹§  íꉀ .C6جíeS!üÎ9koIo‹p0ˆŸégí½Eƒ ŸuP=¨…6áx.Ò ¼v‡¸•+}t8‰•‡YÜ“OAøÃSJ£àg‹YGŠPÁsžÙÇ ]Á èØ<I[]óµDRÐÝ„ÿº¢îl&QÆÖŸf}¦AXDŸªçðÉ°¡¹Ò¬SÿÑ üM§_R*¤“¶ / Y§;jž§3ÔVqÚYáí{æm ÂÃUõÄlMbÕhÖÙ÷Î Í.Ç…†è*££Ž¡ïPùV©n‚žÔ xÌgWØP¶]ŠÝ³+@Õ\g^0w¸ŸfW»YÅÜNP±NJúÃЫ„éÞtVC¨ ‡Ç̾w¾bëÕi öÉqžÌzÕЮ÷X…Œ9éPð ÌÞõÁ#5{ß*eHØ—¢á*›½oA}|öaŽ‹:îxœ`9ûðNT|˜!*ax%™]\ APfÎ)â‹:IÅ·±°ŸS**€Î©Tmrsàc>ç¼1¨Ì(Þ¾öØÒx™1ïà9 +½É$C ês*œ@•¿VÃ9µê/€.Ë(¹òýE¥y +.ûGƒ j4§ÊÃJ¥º>ø‘oN•f¨ª›rÊJš1Ï©:Gƒà-5§Úu<d¸…LЈ#Ç+Ëp½ÎáÆÿ …?çÃI->U[A_i<Ás³•°QEx#ÌIÌÕ x#̹ûî”ëÕçRн¨þu %œôüMõo@Ìæe!•&ŒEôœæj¼æ<ÄçÎ)mÄ®€9@ýé9:laÝ]s®Aø¯k=„9…6Å°a:§õPôò]•ô÷STнè-7Ùr‹#†ùV–ÊaC‚œßCš99hÜãé^¿W*‘Ãi"é^¿W‚Ã¥ßñ®‘ê`ù›V+èC ‚ œ~Cw2©QmØ—J^Š¡‡Pã=7N'3ík ÂÒwúy|QGè0à†™éÓËhþ¦ô±|mÐEÅÚazú´èRÞtög[†Bé‹.@‹¹&•“¨i0¸ÒÕ |寨Å[%ŠG å_ÓWÔ@G¿åcN÷†OÉâáŽ~¯AðÃç~¡B,"ä°Æ&îÜ/: ï¸Í¥½UHË2@õ5ÚRs¿kç‰C+lÈ ûÝ˨†"ŽB +¯×¹ý ¡Ü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/€ŠrJ SSëƒ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΂¦rx bSÐw³ºfÎp oßwÞ+€êýê G% TYPï7Tßk;LDcø/¨_(€öf7êT¨À ÜðëT[ù žr» ºQï ìîZðT 4< BT; CcP;wHGÓð¼ ]OÔ>=ED' SÐ~žáƒðòqvD)Åû ¼|J½ö0&-Cûë¯5@ïWËB ¸Ï‚Î Ðÿ©©QG±Å“ùs4ŠÃ]Ô£L,è4¢‚Ãu)@ï^XrÌmû)®ø¿¡/ždaŸ §Gü¸¾à‹6èÏʵ¢¶Õx«ü¹[ƒà-µà¯luÌm»ÔWçAA9hÊ u½Rˆö?-˜rZƒð‡Ï]Ã"Ú²E´/-’§`î†sCÕUEÀ•Á%ú2ªï@‚l&…ƒñH *gtŠ ®`…Æ^ËàîÊø¨ªúx852Šc#0ãã­è7U¨1á= œñÛ: ‚Â>cDrƒ§q‰¾Œßh¼ƒ3T"Çt38_2T¢ÿ M9À›ŽžR| –<—TS=³ëóµ‘ G:HʘÝ@ƒðŒÏáªF”¦iŠ¶fÌ#€– QS`ƒ,Ä2–ý%€2wxÆrÔÔŒ9#s—b÷D„žÁ"†ëŒ×I ýJñ£@eìÍXqHeñ{06_ó-Ö <ãëPJ»ã¬„WYÆúŸÐFŽ]sÂÕXÊØX:2|ø¦^<«7Äglâ81ªôA§ÿRÉ/}#ø¥í<>JNyøK;: =_±8tÄqgÆž>h¿ÛÓØù訯ö„‚k¼ƒ3Ž)/d‚Š.c“$ãØ Â’îØdµÀNgÃ/M@'\AÒiPê+ŸÏ~âˆAù´°ÌhV,ºò±|a™ñ¨œ +•³‚©ÖÒÂrP +üáŠb¾ kT@¡n•ôIJ2ž‚Ð'hÅ׬ŒÆ)™‡Ð/\ñ­Áµ[¸òþð‘àçç…+?@ëkz®€HØ U®¿6ÂReaÎeîá SáOƒZ»0§ŠÚ93 ‚ÌcŸ›YAsÐÎÂ$‡|4‚oó…{ª  3ª—58ô=a*(CíÉâТòò¸Ç³_iü¦*~POöTb'Õ?¿@Wñ”Ñ Í)†®Ô ¸}ÿ¹f°ç2 ›JÒþsÍ>¥L[c7”žû'|Vƒð7Õç÷;JFp€ê‡P“r®°wÚ „ð1ÿ§I ôw¤lɃEô?M@ÿæ)YÊÎÁПçiQ­o:*.bhQº¨ÖèúÇX/ ÷~ŸK·C­P]Î+£ô¬ˆ!ê{QÝcÏÝ¢Û?ô”z‡Êâۻ  ;(aO¥&èA ‚Æ¢;ÞãP8 +6“q4Cد²¨á=,ĨèM›I‹Þ¯Ax2 +«MLZaü¸è¡¨á]ðеéœv{ð¢^ôÐAÔLµ"s\yØæ\ÔìA “ÙZu8¡°R_ñH^–Ö–zñoû’+Öµ@¯œ¯ÌIûz â;xÑ+¤Bø^Ô…««SY‰H;óui«Aø´tsFœ²B£†ô‡E݆  ÍÔá S¤2Þ*=Zh–O=þæíKi¶qĹ¨ÇˆTÈ°}?ÝîªÚa§ŽÉZôé.Ôïå2!3[@‹úý,€¾w} '¤Ðwå+h»Á•])TÝ_þ•?|ī熿v+í‘PÌŸ|VŠ¡²è].OM1Dþ¾“ +zK}PŸ†±®²øƒЇ•=Á ú#,þ°ŠÁÓ²¸÷y¬<$葇3,î]VõUÝý¨%‡aû.î;_ üJ©F”°‹Eôâ½ÐPåˆM8« ï–Å—@ã"|èªöu³å)@Ó¨«,D Aá°xzc ‚cñÌoYˆ‘ÿÅПsñÌè/Vü¨ƒ¯«‚þ@é‡Y ±M·H¦‹6(ç‚xsìÃipÄ.^°Imä_ržœ’8yñÆ ÂËrPå):®3ü¿ø` ÂÃ~Æ;Æ–#‹?§Ax¸Âþl’XTï°é +h”ã‹Ï¨„T|ÛÂO½‹Ï<}nhÉWA¦ÇBRü °_²àI ‚Nª%«]©â¶(õÙ +š+€Ö¶fs2F¥x°º¶dí“÷Ó’ JÚ +²/MA‹ÐÎÖ¼U‚t™aÇÙ’O  ½³=u͉U†S°w®Ú_@&£†ç%ûë  £«ø˜Û õ]e +Z'€ŠŽ±èqbKŠN “n}:'4ì³[TWë™n´}ñV93!ÂÏ…KËgyÊCœE á––_%€.Ýè*~`5)_ziŽÁ›si/¬?jO,­’@5UÓ ÛT¦ââÚ¨Aðp.­õ/pˆ¶ +¶6–Öj +akci­!%Ã… "zi­¿PÜ+BnøZ + „«´ÇO³Ï£ ½ç†–EÜ4¶„S˜ËÂaYd£AnÙÜrÄ©Äohgµìb ‚WÙ²†{!f[Ip2—5l­Ap,{…K;9Mƒb8´iÙ+?jþ¦þ*k.²Õmì¡YÖÿ^ ‚wpf{U†Ú\”öÌöG5ZŠ™oŽåíKAf¾9A½ÇÖ«óæd(Y”ù^ Â݇;X&œKÎS懻Ð'ª|4”4=e~ÒMƒð/õööSȾ€ð~ÊìÝZƒà~ÊÊIUTU#âsOðdí¤AxƇÀêÌÉËÀ¿4¼›⌢l;¯ !dø&7Ÿšä%†>7™Ã‡i^– nÝ‹jDM æx2§¾"€¦s³SJ}09:2§×@3nv‡#m5b(„–9ã6 ‚ºJæü›Xñ :Ž÷ÓüÛPFaÀ èŽF±â—™Q,€–¸Å·cäZ2åâf.yC­Ø¨„½}bØ—¹b‹Êº.åÚˆâk#3«®ZãƉ9 z¬~¶È\sF­Í ¨°Y+l(š‘¹v¥Zï¹*©¬EÉ\ßRƒðŒo¸ÆSü(! Œ ×kž§§Y°†)ÊÞp¤6'€¶<P)Ò–½éðli'€vþP!Ë÷¬ª a„÷ø~( +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-éÆËB%} —âò%Ÿ + eùžºf‘ð¾l·ÊzˆBIRj°q³<ëa´ÑmHGUM­ A,ߘ-€6ñ)È‘(¬Ë7@9îËrœŠr…}I <\N¡á¿n3—ë¤bL‘(v3/ßO,ï»|KEu)ÒáÄÂ~ù–  ­¼k#hj¤½|ë(ï¨:œ$ð±þ´<¯HíøÜ5¸ÂQj܇ƒî–ïøRíw;wÐc¿­Fâ²\Ë÷_*€4bÁJÍâ#&¨‰r3Šœ–öVÐòÐÁ¡l˜Fè²ÆOËÓ ÎËB% WþŠ [  ‹T;PçîÀWþŠ‹ÒпÚ{†)Eõ[ñ¯WЕª¨4½4’ôV\¹[Õ¸€ ‰$)4Ø^Qã"TóJ¾©í—!ìcwÕüßÐÕTÒB(jècºâêFè–㞪MŽ}<·œÒ ¼éní«œ/”׌£tWÜÚOƒà‘Zqwwö±,‡¡ÏЃ-½ÃIýÔñ7=ø„áozÈâkà 0@·  O®P +²Ó´Ïø'U5ÎxV|8NAK(X³jü¬ApdÕ˜ä VêyViu߬«°`R9<œ’‘uõBtÍ&ϸ¡Ó EtÖ5[Ðõï𦣇Ç>œY׿'€nQéTôÑPÒ?ë–rƒ©áH„‚áp¡f(®<È1*R‚C,²â÷iÔé²n( +=Ðƃš}V¢œá¿.y‹hw•ñ‡'k¦BX³Ïºë™€ +þ¡˜BüKw=›*IeÝ¥ÒÛ©¨t ?øgÝõŠº¿ž2–ííkx4κ¿AÝ7ëÁ;Ù©àH ù{ðôˆëÏ´œB†ç¬Gî@Í_áíK!†¬æo  >œ)"†ïrPußÍ¡8}¸áné¾_}Õ‰·J®XìÊúêmôM}6àí­1dòe}Ó@ý|È3¸¢CŒ¬Ÿ¦@†œå¬_ܵK;/ÁºoÖ/c5ï‚?z³qC –¾˜vî¾è;ž‚¨ÓüOæ4‹ž?_c—žw •Ì³þì¤AX‹þK¥‰ØF`Èð$žõWS “9´ ¸û †EÏÐóШ7XÉr’ªð[~Ö¨Î(m±·UÂþ¶ó<\Z湡•Ï¼ÃÇ<ì<†B!¶ò™4.ËÊv-ÕÖÃÐ> ¿ԣ”RƒNmq8=ÊJ -|•EÝR<\®A9¾ò+·¸HÌq%pôéʯ  ¾î;gÂ1¸ ~º•}o@ߺÝN1÷°¯Á!÷í" ÂS0 ¡®|R´°Z»rÀ„ÂO·«cN ²80båO÷ ÁkKÌIª™‡¼^ýñ4)jèëkžËÃýñœúëF¶å‹ñSÐ-hø›vX“@4ìÌá5ïÌñaÏt³n\cåxKMËQJ;5­ÆíeWNÛ¢AÐù²2½“'0"á8~"X™þ¶ÊR±Ú–SÓ/pÖ³hÝ“¬Ñ!lvåºg4ÏS¶«d‘Ú +8ãÏ>¨Aø´ä Uʨ#2ð Î.€6ÏõAS'˜•›hѹ\!)d+£þ*ª +š£Að¾[Un>o:Ë=Xh2W•ûGµi¨DE=ã«lU›FO˪IçJŠA±‚¼jRy ÔØs¾ØW>.´jRS4•³0ƒn±?¸v«¦Þ/€fôVî ÇexÕŒ~hN/w +(dÇäô\5§š{-«kTŒÔ †¬š{½ZäVàÀR¬d­ZT[­põL'AÀÖiðp+Þ@ëݬ'\‚Ká¬ï-€²¯ö˜ä4þðì:5ûUÙܳÂ"†ŽÍ«²k>w[ªë•JÃãdžU[@;–¸ŽŽ “ÜEôª™„i×@v™Pê¯Á=±j× ´‡Ÿ(YÈ–ðFXµç7´7ƒ/jJŽ5ôê]ux1[Ô¶fï¥èØL¾¥Â4ã¸*ʪcé¨hŸ;Š`ŒcûnUQú¹¡Õ¥F²žéôYÆ¡Õ¥F  óË°ÝB9¦¾êV +:?ÂŽ³Õ5¸¢2õD š(¬®1PÕ|Yé*d-â=¾ºæ+ëê«Ÿâ)pžï°½úê6eÁê›Ü¸aðß2³C÷ + ð'žT‰[¾šÃ<œê½ó?¡Ä%üáögÊ ¯N\¦AxïïÇz&Eì'pÇæÕ÷@»1ÈÇ·µC¼vo@ͳ'Xß-«›g + 7©áìE± ûéÍ_5î§5—/ñ¤/ÕT6@™Oðš+ž` ˆì`_€R =-€jVRZù°[Só2 ‚k·¦Ö#)!M­f¨n]Ñ §ª®îM/Å57´âe¡~¾|NžÌž@7~äŠhǃÇ }×ÜØ]ƒð‡/QžŠËÃä5ÁÊ/Å5ÉBO;Œ}•ÉtBÝU+àEŸZq,zÖÜU[Ýç&ÁXŠföÍwß. ‚êÿšÆ½Xˆ%œÜx­iÜWƒð_×Ô g°èuÒ² Ã5­*€Ú´WW™SŸ^@kÚt@]©BñOÉ°iž:Ö üMdM5“Ø“µæÃèûñ}œ`è”Aq¸æ ·Ž )z„/Ú  ^•¥2º×ôúY ÙÎS Y‘0ŽZ3$ÿÜÐÚç¾á#åtÀVÙÚç¾@]•Ç†áÃ×v]ªAp¬ýjšwÌcÑ0v¬ýj–êç”KpìhÐ%¾¶ß÷èÇJ5rÒ0ñdþ¸JýÌ9¶^·EžÌŸo@½­BYlx +þŠh<-k‡³ÝQ …d×ߣAø—&Õð„˜­þ>|R-tJUߣ*`öø­=Ð xîÖMç(8Ê¡Ž:¥¯›þ½AGìºùcØkwbÿñpóÇ  %[ÔV¡HOìWY·$W-¿$ ¼k–å‹ÒUÐe©¡_·‚ ZR¤Q$SëÖ­h¨Ap¬[ÅÝlÉ3JÕZ0´Aƒàö]·*Õ(U Æ>Œu«v¤BØõ½.»¤Áa(œÄ‡s]vy´‘c×ÈಠoŠë6~ ¸ “ýÿ„_`(è§Tg«®Ë«È~ªŒùo«‚.@Û3Y:™WX]·=Kv³é-:äÑöŒ®;=\ƒðV9s«3ÆùwëÎT<7´þ¢›¼É ÛËTë/ºUUZÄJ{Ò‰ZÂÐ¥%í=’AC¹„õ—¾ +á‹z}À= ê—IM}áp¯²õÕݾ¸Ž“*”Àâp}õÕèß·³•Ÿ çgìD_ÿï»4îñõÿVý“îD`hˆºª ß-¡P"j¨*·þªó5ê*ëë¨Ç+[¦`wüúº£ÐíýÕLåç°óeýí?h”ãëï̵­HbÆú;ÿ@pAp*Á2Ù\ÿÀ2ÔÆÕX©ÝShð†lhÝQ=§ŠÕ$¨4<~4Þð\Ôö]b¶rdÊ.ÜÐöƒTÈ°}ÛÝËB,Aá{ØŸ¹¡Ýýˆ÷8=øSÏ<Ü_„güÍý|¤ì£`ùZ(+è á#õò:»?‰oø`ˆú’ktPbŽ?ZA§P/n ì$ÁŒz}+€¾?à œ …M¥ 7 (• +vA!»–œ „¸AØÞ¨AÐgŸýèe|¢¶ºfˆÌË~ôJ ‚Ò7»åYb¤øšäe·*­Apd·*Wòáá$Ž;ÌnujÑÃLæá*ÅÐùo©ìç7²ç½ G*ûùÍèå–êÃÉk„=íÙ/·@¯®óü*Nù# mÔ x̳ßhăC Mö 7U1w‹Zý`]%ûÍú¨k6¸"Ôb ûé²»^)€º}Ê LjŸ!Ý/»[ÏT?òeÌÏì&†ªI Õ_*h¦¾®¿<_+€zpÄ>Ý°–¯˜»‚Þ@Ÿ(Í>d‹Cë¿yüáŸ<¢AÐ’ýIÉÝ’ˆR5³?ªAxû~æEæ9 Pc Â{¼ç&×C­Ñèj„Þs‹úî)v™„©QˆA~÷œáïÆèË©,8†ºh>-?Üâ¹âaC ¬ìB„—e뎆¨ŠAWÉÔPqDG8ê&ÅaèËTßœÙÃ3Ø$¡`²ˆA` _$€F>¢Ôú¿,gl¦AxíÆìq·J˜Ú²›˜}hŽÅ‚•¾Þ×TA ´°tÀóŒF nœì…çkÞËb6KOXf.K + mþpr &±ï0{[5tà+~ôá¬õd(Ö ø×mì¯b"a§ †¾Ð (U6þújŠéfh··ñ×N÷øÆßJ{†DŒJÆa¨¬ú‰'LŠoüí ‚“¹q7žq’}Ï…¥úT±ÿÉ)óÄIz‡—@#—;G*ä„<ûRÆ”¥APÛ8RÕè ð _QDž‚‘§4OæØæ¼}©¼¢/R‡û¸š°Õ¨“|•‡6  ‰üÈG‹6Dœmœøá]æfÅWN»¾7¦Ý +á<Å“²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º´*çºb䪴M\8›Êm@å+±Zk Œhÿl*™ÁµÛT1ʢǪ¦²¦›*ÆS!ü4·ébwíbAÇ©€y›.î&€.éㄨézÝtÉ7o©M—ôçáœUÆçnÓ%4ž»M•Þf³›Ô õé6Uê¢AP;ÜTé}6ÝèpZXúnªô¡áá*»cA÷R„w˦ÊK €w8ƒAÓ_W¹ªªÁNj·g8æ›*×’@ªIž}MGƒølSåÆ„·JevuB¾¶_ +ê AxY*¨ä}Ê"À§¥òïȤò¡‰¨¡Õô¦Êk%÷!§BØ8O9èòK•+ D9ÄXª\Ð ,Uªf+åÁ>ä¾ö× +Ú¤AxÆ«ßê-°}‘a…fSõ ºJ¥’S¸F _Ô›®ºGÕÙ“²é"Ø_°©Î>t½[ÖÔ¢¤Oû¼,×J…ðÛë¦Û®ðg"lhK¸é¶jhÐ)>ŸÄ6¦ŸK  ‚/•ˆvªbqXÐWƒà•¿éDmÑö¿Ñ0¶¨7¸NƒðdžIy ºHo:sk*dø¥³°!Aé£ ƒè9{‘ÁÏ)ëºt)ʆr>áõšS¶®ºÜM­K‹†°C(çò٨꜔eñÚð‡W] Š•Iâ„ÊÁ]Sõ„Á]S«ƒR5› ¡ÙiNµ‹$ªR±¹!v-§Ú{èª>ž'FÕ’á‡_õµªÙ“¯„yM’œš_ + Z¥ÙìN†âÑ$NÏ©UNƒð/ÕQuü,wP uÐ è +ȹao:r-E± +™sÃ,tË:%É‹_¸rnÙ(€‚é’Tr ?åç  ;J®2jy eAÎ[4Ÿ–;]Õ(á” ôE¾ðpw^“ +dÁÝAÏ€[†«,çî°ªßË»6⦶ó9õû + ÆÓNnA{÷âyj¼C=Ü8nkk1Ãd>Ü]5¹Êû𿵂®@Í\½ ê6(Å>Öœfû5j=9r°• +ùú½ò?ú€zÒýël«-H%úðpOÖ@/»Ï;•¡ òƒs^n¤Ax?ujÊtgXàN-4¯]'•j@…‰ ¿œNëЛÿaqHî _³xžÌ7 + ·ï¨B‰°!D5çí»P׺ÊùB­Ë±9™ÓõfÔgrOØ›ÎPj5§Oö¹¡ÍÍÆñdÙÆ…Ÿw67K@-ÞákÃQÚ±aº¹Å{è~t5Åñ¹Ûü̃ÈÝãŽ<¤'L8™›_n,€:°[¼ì!CY®Í¾@±2JoW1¬U5šÝ¹ÙÓD±8’*7{Ö¹¡¼³øHÙ‹kþº¼éÿº¼kã|"Á˜åsñp×Þ.€B®2£Ðâp¿Kå…(æ¾,[ âM—ÇÂþC·såiêHòå&ñ‡ß~Ÿº'% &è˦çáî¹@5¼–UHò ûJcòp ëJ )/dGA{S!ì8Ë{Ðm¥á(ƒ+ ïÁQ©vä=ìöêu¢OÆ^)yÔ <ãüNgFqÌCÞ#ï æ,zœ Z_1®ùY ÂóôøJ¾€Bæ,‚¼Ç×  VnÓE'#Çâ0Oe^1µž¼§ïô„X(šÄå\òž¾Wƒð7µus»éqÒyžÄPK ‚÷]^[®“E™ QC8C^Û]èùýÞpÁˆ!&+ïùèýŸUÅ"jj˜™×~¨êÈÉBdÛE e%ò:^'ÜLa§Sº¡|Y^ÇÎèõžS¢–ðá|ý5ô·Û£ú*A_ƒCîA¨{ל+ßÐC-¯SYÔåÉ€òÚª6¶òº<£Aø´t™Ç׳ãwó¼.„¿é_Š¶Z6äHä½@]Ýî4TìÏÖ2±O,¯ëôžûKTÏ>ñõ UÐô~>+É eE±!‘÷þnôá.u)RwÕÿá>ôÑoû: x04Yƒð÷zÛ3$¢aCVJ^¯.¨÷kêR¤"X™Ù»“êsÊÛ*N¯t¸Uúœ@ßþʆ„“’`Xào@¿ªž½­×â‚y¿FÐo{JVÌJàjy¿}"€†ìôÔZÛžÆnÁ¼!»5ßq>§ûrcØO]¯Ax?ýÕÌ3IlõûìóþzLƒð.øëU¾€‚öª[åýõ†a©2t+o_ê&âswñpCó4Oæp•jŸ(+ŠTyÇi4àóFôõ®²¤eHýÍñ­U×3“¨ûž‚Q7  ÑGx +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Û :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]P]ANÉC¸ÀÛ/¨¡ApÓm¯ $™“†zbÛ+\’ +á:YÛ+\ɡ§ñö +W ‹_ä­%Å¿,o¿¸½ªÜÅ.hj߸½rW ÂßT«Ÿ·éâ–!ö{­þèÚ÷Ø=áœâ5ðpùj¼¶ï]Îqr$ðp{Wj>ÁûÇðµAaq|åoß?^æ"v”$a_ÔPˆm?\_·S +­@,ÅíÅ/  ã¥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îŽ{.Ô |î‰óAˆØꪡ"àŽ{îÐ ¼v÷óUFm+‚umÇý;P›UêR´·8Ž>ÝÑfzŽ=YtéÛ 4$v<×DuØïME€áïpPƒð_×q¬úp§õ3Þ™'hÞËÚzn›¸ûÃŽe/Ê«ú¾s/ñüø(1ŸÝÔ&ÝàØÏO,@·gðµAÙÖ+£ +Z¬AðnÉ¿ç€RmãÆÖŸÏa ‚ªvþîδÕ+{û¢OóX+€«¤<ıî›ßø ‚'8¿É쀪CcO&sÌo2Oµ¨ÎËBYâAlvç·¸JƒðŒ·¨Y2\4ŽT~‹«S!’ßâ:^`2¤â8Ä"¿E]ô¸ûxu‚§Cøç?ÞYƒà Îœ{ïPÖUÐ…™ÿxžá_j©^$âε7]Ëá©VÿóŸrï»(‰UÓU–ÿTWÔNU#JR§t¬ä·ûJƒð_÷òWndd›Ý¾μ,/÷@¯v÷BôH •¬üW?@¯wfÁjo¸ ¡9eþë]л3r*!à)x÷S “ùnŽwìí‚ëÓå¿»Uƒðïû€êú±|á1 +(€Þw&“NÍ—¨A¼ÿ—ê¡æÉ^z‚†SÐã3ô¹ûKnš(nÇÿyÔóq¥†Pkì§ËïÙZƒð}÷Å¥êr²×ñd~q¹úú!e’Ѐ8 &ÿëƨŸz¼¢ö²a¬Bæ÷¬Aønùɵ¨#ÎsŠ¡¯[þOõ47ˆ»d«Ë¶–ñTYýâ$æ8B:Žî–_Ö ?²x28ƒBóÇ ÂÝðJñ£®+Ø—?üU ‚kþŒÜ­âôböUååŸÑãÜÐÎîï(3ÉIƒ“¹³ûû¨Ç|6q©ÛFW›ÝÙãôÙnÏÑ‘´m 8™;?Û«ApYvöžËB,âôþÂSÐ{¾ê« +ëÅ©²±ØÙw@*„#Îvö›É¼c˜b#pg¿9„g¼?{ÃTÝ÷á<\ÿ«РOøz%h(kºsPOô‹[ÂÔ+â çá~雬üw ¨Œlû€âê1;ÿ~O Zrüµ–4LçW\§IÒ° Æ7M… »`Š›]H™-Äp`ÄÎ)+4ÓÔ6ʤŠí–SŸ@éüánó\T(€œŒNÛÜJ⢭;·Ô•@IÏÑ%3w§A%kgîw,ì­Sí—;@©G™0©k†í[T[ƒà.ØuÞíÞ¦ Z1üê¶ë¼»Po +(\Ý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+Û]唺 &#m†®X¼,W´@UsÜrBm >Œ=7Ò <™­+°#§‚!’jOë‹ÐSîó3uȈG Åþö‡þÖ ¼À'¯ô„=M&Þ¾'ÿ­APëÙW–¸Ïœ‚}e¯@/•/¹€¨F†*hœ‚}“§{Ærد?)h¦ÊpËx;Û#1œŽ¼/ã´° +©˜—eßÂ+Ð*×gq 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Ú±[ínœâ|1”º8´û ¿tôumP‚VC½Hƒàá<\¶]@¹O­ˆo—bèetáà€*eH-סÁuøÂ!åÓáÊ¥=ÁJz­*§APi?\­_Š¶hjŒu¸Ú¿ÐUªÖ7…ìâì_µFƒ ,8\‹›xº%6ñá<\« + `™ÂlâX5:úñÜБZVF#Á¤-{à_w¤VU ‚Ý‘kê•\ŠQ_™·R ýG…ÜÚ8I§µ¡vü‘ÐJtGÂ3¸bþì +º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«´úqoº(¹tqÒ‘Ó5îÌ‚–M½M6%€´l.€žbU›JDâx«<õ»Á¿®àYÎP£§9S'˜‚g³PÛ2U2;ê)TP9ô¼+ì)nÀF°+xþgôÊÊ@ËløðWª + Wznùå“‚I Ç”Zk+È–aY^m%€Þ<Ä›Ž"ø Õ° Þ<¢APA.è:ÍSFmõKß‚®é„÷¸[ßÉF ilne|‚wKA÷·x8+hïpœ2VÐým ÂSÐË + 4J‡‚VYA¯cèë›Ô¥h/‹!±¹àë[5ï§!µøR¤z «FC®@æ+×R(aŠ*øs—Á ¨`hÿeÔÖBð‘:@ý­úßQI5ƒ[°àïvÕµ‚¿_g7NÜž‚~ä+øûM4?[m{ +‚ø¾+˜Ÿ#€ÿ Ž”=œ¯¢‚~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¬Æ ¥ Œ•¬cèZÕÿ.ŒŠGòp×v@u¾óBÎc6®Î÷Èv:?D}ÏÔpc$òÐP¢¼¡…ͱ:3%·P¦È S›cuæI å¼,ô冖HÇê¬@×¹ßw|E4_ƒðŒ_¯Œå°Su OÁõi<ÁÇ®çø'*@2d9»~¬áýtý>T¨ÑPäØõÓ5ê*Çnâ Rý-C³øc7Ý©Aðn9þ# \•1j'3Ö`l*„;ìk|O@µ> ¶‹P];Öø~Ôù€WB4bx£>ÖùýsC…ç7ð„}Äop•e¨‘ÁƒPXáïJ† µ– ++Ü"€.ªâ„d$›—^t¥ª\M9„h™ñ•_Xù* ÂßT«©gºQŸKüKµš1DE Pa­Ú/ –©¿dX–Ú\žÚiƒbxÈ.¬ýŽAÑSXg–2–ÉÑa˜§:sÐíŸð'è‰û} oÿ\ƒ òPxO  B›¨Ht-ÞSU5º’…$ùvT]=Â}¸èÃÃVC +I fªLÈi[§ Yô¸Jow +ñc%«ðñ?5ï‚–KØ ð½8~o)l™©Ax´ärS$­®WØr›jõ·R×ìíkáK±°Õ( ÂÞz3 Œ„SÜ ×:W=U12¤’>u‰j·M‰[Þû¬|åk^»®c?B¡(aÓž#€¾ãdF§Y—¡ñLáwSÐ÷i,ÄbTÆÁ0™ßOÑ |sñ/QZU0UÈ¢)g¼¨%·šÓgQËVèIUìÏ åÅwpÑ“ÙèiN;r¶|‡EO_¨ApžŠÚ\à©F‰ ¯Ü¹‚.@Ïñá¤e‰Ä±éVôÜôW• 9… Ý ™©/.z± _¯TlÊ—³Ì üâóˆS l£Í)+§àÍë%«Ó%ò¶×RÑ›Í뮤£ð=Û˜À&IÑ»ûPwgo”ˆ!r¸¨ûô©û×Ũ‰gÄÐÕ èÓG5ÞEŸsÏ+Ò"¾ª(ü៷‘@ÜÎÊi9bh_ôy†áoêës‹\ßÑ2/êû¤áíûû[Õ‰²ý Ó³è÷·ÐHvzRºIÈUÉà  Ñª UÌ04ñ,ÝBƒàõZ4ݱ€œãt0TSƒðdÎø›…}š(`%«hÆ4G9_l±°BS4ço » }£·U¶nk€¶hþ¦ 7RÌûâ0lº…e?[T:%la…¦híׄåÓåñ‹R¹84Sƒðdf»ÃQJ[qÇïEÙß + Í*¨%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šü£š¯œT„œyÅó{  î+‰P¢Nª*^%€2TLj=†*;Å/ + …îpÔÊÕÑ àp W Ž`t݆ȗâÅ¿  Ì †hŸÀ‹3¥BX÷-Îú“m9Ë 0²þÖ ü×eK1–ƒø‰ 8«X­tu•DÄ­v ¯Ü¬Að=¸xí*O¡‰›.ÅâµkÐz÷Ú   bµ¶xýÝhëM<\Ò ´Á“¹õV´_õ µœÄm|öß)€ÆÙ$ ¹à‡¼Cƒ ÝR|DUt® ìú.>RAƒðŒWa#0îx2‹èÄ]JýEƒ¾Ö,<܉û4Ÿ»Óóö¥²ÙIœÒZ|zĹ¡ãç}ËnËQ× ±|ü¼¨¬ Òƒš¡¹Òñ²£$':Eü ]|Ž—!€.~¥Dˆ… E¥_üºªt‚•¬¤#¦áÎ<^éŒ'é¨(\àã•Î +~©rií—à.8^ÙËÅ¥ÒÛØqv¼òE„é²¥ 9],Ç_¶\zóõJOëqlK|£AøïáJwΣŒá1ôø5aìdž DŸÙ­ ï5ÿRÓ7X5ŠÛ#‰K>oÚYíë퉞©4Áñ}ý4Îø‰Rî3=™mäñƒÃ(õµò41'Ü +NÁ‰R? +  Ü䎕K\•'.è¬Ap +N\x«Ú§r +TµO\ø€ªÀyeôäñ•ÃSPUT‘«¥‘ÓÓäŽ?Qq±á¿t²R(ò'€Ÿ¸tZ*„#ÎN\­Z³8y‘¸†Ð‰«; ›Ýtš˜­ÖÚ‚›$'nÞ¢Axƒ®>¹å_a`ĉ`/ ‚wˉ;[+5ÄÖû ­7OÜù”º¼'ìi<4Qƒàpâ!ö?9 laé{¢Qi ‚Ò÷D£]A-%Ã’:Ѩ½zØ{Þ Åƒ¾ØZÍ@m¶TŠ´} °î{¢Í.Ô³¾wEm•sU‹!,éz­æ­¡©ÄÙ'z­=7tò 7bŸJ¹[CõÉ'–j<-'ŸüŽ¡„Sdž–“O~/€Ú©°þ$ÍN`:Ù®¬ê\!à%ÇFXžì|±zÏm†wš1ûÌnþð÷*  žf­Ç +Y´Æp¸žÓ x·œìÖ'ÂõÉný´_‚;óä×*Ä‚ššÅ°§ýä×ÃÐ÷ù*£¥q,UN~ÿšPI¡D$‰ÓDN¸LýÐŒ¯üpØ©Q§à‡hà¡€jñNI PôœX €†^Î&IØMAÃP@­áZg@C©°“k* + Í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Ì~&ÐYUç +Ýa+”Œž ÏT_— +aåáL Õõ—`$ÿŸ±3ó©þþøØf c²Ì Æ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‚*ñ¯|Ë+Yj¡Ì/™¨Axž"ª\BÒ½€ ŽEþ'€J¯âÏ%¨ävì+½FuïÁJVÒkËT÷Þ¨ß#|8STÜpZú=&€Î½‰/ zÃMàdžcçN@ƒØeâN&5HÃô‰áyºÌ+£FŽ“Äjȱ˺  Q~G*òFÍ&ðÀGÅÐu?G*iG GêºÝé<6n=C¾É…§`Ü»„ÂIJjŽîæÅjí±‰-Ðþ%¿ˆ¶ƒíh¡Axà;b¬y†Ã¹ÃÖ xQ慠oS0¾¡\çñ®gkbÇ»çÏ‘c?U£ã]/@ÝoT†„W¬n•ãÝ' “ýªMqÚx–¡ +Øñ“{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þã•×Ô™Þù0TOMz†E×vVQu¡¹„ÄaïŒû¶f5èAâÐ…¾Ñ tsöΘî‡úíeæB[4|f¬Lñ£ §`¦#€VOâ®áf¨«íBUУï.÷Ú7,Ë£jÚ*½3û&.]¯±PBž‚ÅÒ!ã×;㥴 N'Tð„?÷Ò–4ÇôÎXå×è ²)»]è>ô&§ÖQ¬J4aÓ›m%Ð~VÈu†µCúU­Ò"£N̆y@.TSÝƇ“|ñ¸… M@ŸôæÃi{í@‘âçBg  ãùHQ2c¨‰'nãD´EõxLE¨í>Á[ž@Û/S×F̽¡“Ê…®Ð <¦ï9Þ—’Ž¢¸Ô… u”@ •Sš @ÿ¸ -@?槫kP÷u¡&„wæn_ÃH’ÞMÁhAš AXDÿìÇÙ',¯O,1ãBsОLåÆqgg͹P¶¡Û¼wÆU‘Š¹Û0ÇÔ…N”@‡•ò@á1aàO Â3þg6à©ñW¾½ºPUt|­Ú¾t•Áw)z;‚ѽ+T¼„*Êjˆ Ô 8ã*o ’…\÷ßNà*W’@*‹ÀŠ&cqè8s¡Í×®Bí lâ¦<×œÌ +µo@ù•è‰Æc1ØáÄ…ò5^¯¶qO>* ãà˜,)€~P©È&.áBE„Θü¢ ¸,¼ í@{‡±éF¥’øʯ°÷R ›îÀÒžpUmdNºÐ4„ +G l…›äñÀ ?U3Òpù2ê¬AxLÇâl&YÔÖz²\¨£ÁÏU¬X—Åñ$4ðŠsPž§ˆ×nk‡«ä  ªª_ÍÁF¨Xõª¦ªõS…8ž§ŠÕ†kž§ê~Ò…òRA-üK9„)W½vÛž˜†â°bîb Ÿ«ÿ;¨t:®CãB‹4^@OøšNEMqƒÚ*€ø·y*š¢ô,|QWl0Gƒài©˜Wät¹Fñ“¸ µÒ (U*6='PÿV¨˜;¼é ô>«µ)/@„¦iT*ÿOm:w𡪼ü¹âm¨ýsÁA°œ¬0éBKPì³ÀtUd˜³ìBÑ y6·u¡ŠoóŠ¥ðV¡Çu«K@'Ÿ¸L\õKߊ'Ÿ'€Ny”Í$*h×z\ƒð >õ¾6ì(ÃâðÔPß'Ên' ïû´Á»¥âЪ ” Žœ&P‹®8´ºá)¸È;æžÈHÄâ°ð‚ -Ð , Fü®¶/Õ§†Ž3úSƒð¹»|fp@»=$~KƒBá{ +úC™É5ÒÆ•î\èa4¶­RÚ) ¦Ç–hþ¥q7°jD 8éÓ…Æ + É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 ÙL5ÏÅ[eÈ^ ‚F¥!ÒUmìf®4äW4¬1ŽŠ‹ØØ!TiXtyV!©9p™»P±Ó„·¯W´»'*)Ô ¨Ó»ÐQ´à\u)F©  ž‚CÐóAÀ¤»,¸B’ @KOæÏE½6žð®´ô4ô¢ÊÛ žP¤‚‚ºiþë^ã¸ê^Ã)c.ÔC­àNzQÇ«ŒOðŠk5ÿÒƒL®%;…­üJod  ü¾¸)r ‡Ãyû~t±ás÷‘rOxM†±?³ÒG#5 ŒO+ñØÞÍ?÷i¦Aé[y‚o&E݃`ÇBF @Sî`!Æ õÇ]hªz|P™âgGþí2áÏ=~žz®C”pzQP t/ =ùãðš¬Ap+¿È-%)íÈJa;ò‹£4ÿÒ+m•Bsme¬®U~¥Xƒ ,¨ü—ßð¢ñqÀ¤ U@oþÉjeï'aÔ· ý-€7PNtz_ÇÛ÷`‡ò¡*s‡î¤°IR%c§Ú¨":ê@‹Íî*W¤CX…¬²e%Oí¹ÖÇ«lY­Ap«|ýwNlŽ$ƒ‘§à› +ïà*[°éF—uïÌ*[Ï@;Ïò¿˜í©FpûVÙ9Pýì‹ž¤Yøu²ÊÏ  C\<’¢ˆ"¸|¾ =$€~›\Ô)—år¡ièo?8ÑkùåÞeð*«ò·¥A†_zÖ¬^ÓÅv}Wù{:ÎATþ5ü\˜ÉPíò¡ÌŠþ˜¼`H(Û¢2C P¥ý­âªX.‡Ý‚™•>Õ ¸v™•Uä°çŽÇ/¦™•' œÚ ‚ „h¨<.§~:„ch2süˆ³DŒh¨F‡‚¶jtÁeÖM4Ü‚N(}”^·“áϽ”·/)Y ¼}3s/“@¾g4I‹kzVÍÌÝ APÃȬל¹EÎ lHdÖk%€êûÞ¯‹žÉÄͬÿ‘á¿®~Y¥;W12LfýM¨Éúª¨eÙø*Ëlòž*íozO‹$`|¦ ]¯Ax +Š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¿WR¿LFC…?ÔH½å+4qï! gaºÐyéÞ™Y•½—eo:)n•¬*5êtYEEq YE' + Ö¾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³.Rs¶¤C8Æ/ë¹ýíKõÝ!á_zîátÈôKsƒ«Œ +‚cqøÜ Â;sasµ}©`œa,l™vÁ¢ÉJÉ¢L–µhªZÅÖ±=Òc\ÖªuåCUÏoæsrLJŸ0ÔR]î?¥P±”exrªzyt%‡Q³SÇðh\õÊg%Ðñ@y°-Üå¾wÕ«*K UÀ9î^Ö¡GcÕÔ ü×ÝÀÊ~KnœºRõ†½åxÕq~‚¥#cÂg_uÜ-È·9ã´,.OíBwkž‚‰=ÙL¢V‰q|½VØ[Ýò_@drá²7.ô¢AùTuÒ‰ìƉºædß-U'µ@Sú²+€’¶qê¯ ­AxL]¨kIÛ6|î¡K5îa?r8‹‘º†ÃA«>RAÍþ/NÇ+á€xö8 Â{|Þ…Ê$¡Zi8Žµê¼‹5iÁÍ 8ІŠfÃÒs.t«ZÂU›bTÒ?Ë”¸Ð6´¼9›Ý)¯,>-Ë[jžÌå~÷R ¶yÕåí5Ëñ½|(Fá’ƒèYÑW­Z̪…¥…Â>x +V½¨APi¯ú¦ê,D Cu×Ô_½ÅÝ‘½r¸‚› M@ë²KPÚvU]7Xƒðá|ß2¡‚àÑp¤üýÇ5ÏÓg*…†By±+ êgÐÖåÁ²$œP›p½¡AXún8:HñÃ{|Ûyˆ=4²K¶±ˆPQÿXÈ!¤ ™dÓËÁ•Šòƒ«n{M­fAe(SدRuÛôÝj2]å×/p¡3Ðöjj” )å ¹Ï …¹›ï§KЮ¥¼,d¼á2Þ.ô’aù´‡³z£T.Á6Ü-{nÑ ,U}ÍW¾{•¡­è ¿À¢3¼pU=tXW…«¨<á¬êñ½åCÙUïSŸó‚áöÍ®:CeoãÉô fXžÚ…¾@µžQ +kFñ”]ëY4âõJÄ .“ìo «ÔZrÂá)¸ú)ôÁ=lºÑƒ¡á,ûƒû5ÞÙ×Q‡Ó ÖÀSðq} Ä*(aײ`S3Ú*€>¯\ž9?÷éóè³x«Ð‹?.CéB7jÔIJ¿P‰òV$îJ]dqµáÓ²q/05ºÄŒ\è* ŸÛÄ6§ß² qfo®¤Axž6óc7;‹¡ „Ç´™ûsF)U>ýOÙ›7 + ­»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!.ôµúÃ[Ú&îA©Ú¼UþxSùo¯ ŠGBÕfô¡:ªžR¨8[»*³6@q8ƒ»s“VÌp8ÿzKë¡d*,ŽÓý²õ’@¯—ûÏ UŽ­@Ç›óöõšàgÕìã'¦C8¾ ZFÔ8qp_7²5J•j•}Ý7A+þo¿Š‚öjœ§jÙ§ñA ¥=¤aðÀ³Ï@Õöó²P ö›™?Wí ª3!¸€Œ5:ªÕ¹Eåú‡3EâÐŽcã¦ZîV ‚äjTôiÄk‘†×®Ñè¹dSYÓˆ!Ë©ZóéåSµ[F`ÒÐàÐ…Ú¥C†ÙV•ºHʼnkµ¶]4Êñj%,0¼'Lü¸^­¤’òCT-o + ¾ª•ä + Sg³éFQü”RíÔg5ÿuˇžêÈâeY>Lƒà\={±2“HÄÎáêÙKPŽÌó ,lÜTopƒjt,xÌдwõÆ$Ðe&¡g0´På±Ì¤OÑó†, to ì÷(ÀƒP=ï ‚ \½é‚ÀœLQEK =/€ +UXrGq‚eõ”jåík¹"ÚüS½“aYP½ —sñ‹¹ã ¨z›ÃefõâTä +V/î,”âGe¥“†MW¼^Eú׫«nc\õH{­j f[¡ )½.€œV>dyA“8½ºÓ62Ì“cWÊ +òà)p ‚’®º£JyÃöuJ5ÚœÕ;õŸê1á#åÜ#€m÷9—àµQ=Q"€’þVq)÷(Ä r|ô}„¥ïõ¼3ÝCž° ÉgÕ¯_!€ÆúSàPy[Û´ÇÇ®@ã9ïÕU±œp¹)U–@A…î¥ûáÃ9þ\4ûHøŽXÃ4a§º9©.j/ÍOæÍ4iÒ¢4¥ÝP£ú¤4Ë‚Û®aq˜òÚ”â1Ýv½º½+_¯^‚‡a«ÜÞ]ƒð_w7è¡ç~W­ÅÝ]Ÿ  ûÕPð´AŽß¿Rƒð˜âÛÜK[ÀÍâ](®Aø—ø9~‰¾$~«¾``ùPÎõËxà”¬œëWj9ï 6=dÃçLœ.€& Q®€h*f¨k”3éBtoYÛ +W=Æ‚5çÞí„é¡LÞ¾äŽc·`ÎCÙ„ÿºGÛ¤)ÃEóh;ô¸¿3¯åˆS5s_©APÊ™s7ôÂ>±œ9$Ð%¢#Žm(×™3gžZ0š•Q +3¤Üç,¸.ÂÊhÎ2¶è™ÈT+gY‰§\,‡_'s–MÐ ¼Ÿ–_í+4^ñ¹P)CžÌå£ÐÊ‚K154ÈY9N­R )X·Òp¡Û5ÏÓ¥þS(™Á»–³f›zë¸2Ýè©k¬9oWÒ <¦÷{³‹Q³.ì`Ìy¿ŸáÏmárdãZoHΖÐve·qŠ8ãÏmÏÔ ¼Çw\ÄÁ½4Leorv\¬Aøs;TÅR¯50ŽÃÈÙñ¼ú™C¼ZÃósÎÏ×j–O‡Ùz¥x'TRMAcʇj¼­N ô7Ô®ñöç©ÆÎ_ùsTN8$tDíÚ]æ|‰ÔÚ»ö + ŸýûŽš{SÑ(0jü¼=ÂÑñ5öÍ Ü8V ÷us¡ùwfÃuË®×(n±åBõÐïw*—I4Kà »¿ß­Ap?Õ8î§Ó$hûÚ>5+øA-Ô1i…¢àt…ÁÏÕÌô•öTÌq±ƒßÊjfv@9Þ÷$í'謙36ÂõXk6x’ï;Û\¸ªfƒÙ„§ 1çºE©†u(^AÃ4ÿR;àj‡1ÜÜ…ú ÿ N°eèJîB7jÜt5£ëØó@•‚ÿŽWáÉŒ¾+€ÕPþ¯? <-5Õ)ªUíôÀÚðê`èL ‚3^«æ>qŠÆÁïÁµjÞša_O­:y«$È]g¼VL ‚3^«¡Š÷¥®¿1ì¡©ÕðmÔ¨ ëOÔ+%Šß^k5þˆ!Ê`24éÕøST¨ª3PL+µ +O@í|™é?;z9ÕâŽ^ aï­­ýÓ<ÅlÃÁ’.Nª6T®uîShÐ6àÉ4¤®Ôt«yª%ýRaøy§ÖÈÓÐØ൛ÂyñCv­±ŽZ˼í‚J{­±ëÐͪù›íÊqÜHÛ…¾Ñ ,ìoÀSàPÛyƒ`½m ššb½€T–ÖšÚIƒði¹s/°kàÚ¶ Ú¢AШ5}`pÛ®®‚ÔôAhVÅ`à^U ej¾òŸ^ÎGŠª‡Ü‚ +Z©Axíæ Œ›dľWkÞP´ G™!1FÔZÐ[;?€hið²»Pƒ T©]Yu‚Iz XáÀkW~^ «ÎÚa<³mÜú ö°Zè’k”ÝâCªAíK®@£|3ÉñŠ8\ßµGM—@{ø P¡zC£µÚ£~Ñ ¸ŸjOTÙI¿V †JÐ- xÉ2<6Ô¾¥‘šÜ08RTr +OÁä| ‚›®ödv F<*>µ'ß*€f¶daïuÞÁŽØÚ3[K Ž„˜áR¬ÍmSÿè1Õ ‡’ ¾öcÛЬ¼À1zòÇžöÚ³,ôôc ÑdŒ¨ýô,ô|v*¸[%ŠýWÐ èåż,Tv9‚âj¿¼T½á‡^:ÔÞƒ:ªÀϽÑMƒ †Q{ÕSꢦcŽ3²k¯š-€Ö– Vw2qJkíµkÞoofõß]ÛÁîøÚo£Ax¬÷ëdy™Öƒ‡¦öú«%'zY”—JàeYÿ­zŸëõx`CEXøsï¡Ax?½ÿ?VרC¨IžúÜ6ôÑJ°zCŸûhŠÚ0½ ²SØCS{ÃL Â[å³Åef5ÀÐRô×;¤œªpÛ/M•@ yÓQÈsFÔþj‘ú¦›nz.Ä +Míoúhþ¥íªÔ*F¢koÿ,Â}$joß̦‰û(~rª½ýk ŸÛ5‚•÷Êpí|•í•’ôjº(m í@kº¸|¨Î`®qFÇ$€ŠTI5‹"±±òP·è2 Â]‡+)Rý°×¨nGƒ °¯{9¸¨Ý)0|.¶,ªv]'TŽ$-ƒ +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µmÁ":ê=ÓãoÛJù3îXQ*@hX»¶ vøpÒ1uîà­Ò®’*~©LôD ŽØÜâWPÉD¬E±bƒ+·ä6 ‚Pn‡ÙíªìX°ævøQƒð/%³ +é• +Ã¥xr/ižñ$»ã½V‰†&/¹É¦dø%nߣ))í +ºYREÕ‹ÅÓñŸRS–ÏʵúIáTƒÜÓš  3 +•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æØÙR$X +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]‡¯|Û3•ð_wv}tÞ?ÞÓ¶KšZD4<¿‚AU»áùÒ² UQž?Qƒ |j8t¨RC(+¿K5z‘>—…BîB±xàÃ’@þSoÜk|ªaÍŸQIƒà1o8âÙ`û&"¡*… +š/€®¸/E*,žÂÏô ¯˜ªAPWi8š- rÂÅ %³Žž§AxÆG¿ÄBŒZýJˆ6ýªºŽÔ¨ø‘ÉùÒðº«ЄŸ³›žéñ‘š°[ƒ°è™È1®@LÚ¡> +úTƒð˜nã˜, +Š°Lâ𶩄—åöø Ø ŠƒÞþ“š<‘7×jÚ z&O@ST€[,’² ½zNÙ,€îSµàbÔl;Þ÷ŽZ¤ºHǼb¤xí},€–ú3nyåB-G´[ƒðÚ½ø«ÿÔšÅzÙðÅhå³Á»‡Á0+ç¥CX;lø¦*¯è7XÕnøf\]\v½Z¡ N]ªAPo¸¦‹2q]…ÆñØpÍI„×n­_ÍÑkŒåº®]¨Aø*{Çÿ%‹¼fî„'ó…è½ TAÛä‚køÞ Âóô±_Ó“ÚËFbqƒB³¡‚Ú>M¹L\c2Š=í ·ßW>Ô(Y7ñp‰™ †Z + §êÇܦT/ø¹§hüëÍåŒ"*Ydšx6šÛYÍ»& 2¸ãÍ»^ÍWm ãîÈCBô®òo)Û»bSØ×Óhþçè9Ux!‰S} @ çÊhÔT̽ÑÂçÐ’AÁ“+OÁ’ó4Þw^Q½RÜe±B¥çô†zµˆE4)íQ,}½ÚJ­ø^ *‡•‡F+~Ô x5Z¹˜ÕÚˆ»,1œ8ØhåR´ªC)¯Iž‚UÐ[*S†Bv8Ö¨Ñ[кfÁGCa˜FëZjá—ü÷à¸å©kØÝhÝŸè]ÕKÜk4€Þí¢Ax¿—Ã!N†¿WSmð“Ò½–’Ñ6àm8Cƒ /ºÑ'ÿe7Ž?Xˆ}r£út±äªÄ×k£O_@ŸS[%Bñ‘â NaY°é%XÉg•¬F›>@ߪ?‡R¤ зï + ½u¨P^ﶆ˲·žÚï«!¤ùGÃϪ +Z¬AXìgûŽ¬›H ‡ò6ÚÿŠáMwh«ÚôÔÚ™<‡þ£Að˜7®|¦‚¼c7]ãʽP•l˜Òç åðW¢Ap?5δ•ÀˆÆ­Žyhœ@YðÀT˜_Š³†iž§œÉ<ð”×nºÆ9w  Úû•âç~Ìp5®}PÕy¼ì¢¶M“Yç) ÂóT¯N™oÚ©7®W_ƒð<Õ_Áw'Á² cª¿Z5Ø«š¨×ÊCûPÞ™,¢£ž + 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æUzBU®¥.ÅHÊIàç¼Êu5ú}ó²rÒ>g0Iò²jK Uæ>ÅplH^ÖA ¿T³o•9­ñóN^ÍSPí¯XÉ"#)†Í¤¼Úß ºÍ¢¼•$Vüòê¥CøzÍË ÒlÝ ?T†’ž»]åûV¾W:ŽZ ’—_*€ +}5$æ=Ón©¼Â…X^Ë"^`;æ%cèD Â[¥ø ^` +·2´ŽÊ+^+€RAx±;t ¿,ç¥þ@óX…ôÚËâ—å¼Î¨Ûÿøsþc¶J·mèô®l,{MU°Ÿwzw 4+0L혡 @ÞéOjþ¥ Œ˜»… mòzÄЙªU"5D2¼ºå¹Aõi¬.E¯Ì&>Á} +PßѬBÆÍJ{^ßë4©ÿL†(@Õ1ˆÃþ  óù!æ¹¾q᪼ó@ÿù¯|rèz€äýç/tÉ?ê ¸©k ]š!敦Ž!º+ïÒ…h +È1 +" y—¾¨AxLÃo dÒ²ðç†OÐ ¼ŸF]Ç‚5NbÚ°ŸFÝ AøsWªv1d™F GêÊ„?7FiÑ”²k(ž7æ<4±¬‚kµ`#0oâ‹èÕ`2“–é–š¸\­ð÷%éYVdžä­X AønùÁ×3)Q“RmñŒÿ°AƒàŒçGVW~*\Ä.ƒ¡·Pœk0zñ#ü.•o Aø—J'—m•˜áÊ/½KƒàŒçw»?p¸—ÖŸò»Í@'?(~Iº1ô„:%PC¨ê2NÉ?¥­Á™:ÇÑ1°COs<™§Ö ¨±æŸ¹X©Ú”ŽŒ¯²ü3_@ýëó“+Àð:™ß¿‘Ì!jÍBád:_ ÙÁÂÞ+ÓgØtCv  óŠÙàŠ{e%  +™^{ÄqÑÔ¼„B#ðŸÿˆºÄ¯×“ô®×$EÉ¿äj ‚úxþˆ[x©h†¡ eþˆIé~(ÊéNÂá$=þÜÈû$Ð_<™žãÓ Fþ£AøH]v 0\If˜ÌËf «¸¤?ʦ´Èü«¦¦CØ57f÷®âØ»–u¦ºöä2qè$pôDþµ§  1~|Ÿ(o°¨óÇ × <¦1?ò丮éfø¥Ÿ5ÈðK—]ÔN kùcŽ  ±~( +¥±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º—;Ï_}’Úé?®'¼TƘAëÙÙKíÚ˜n)S®[þ®ƒhwõ2(fKËß]SýùCI÷&3ÄEç­P>TPÁ¿S^ÉÇP7 + +*VÐ xK«v T2à X Š«k¼ƒ ŠÛ²À w|?«·× ¸Ç ¬Þ,ìÉk0 ¬~×®ÀRÔ"/ô¯  5ÿu“9ÿŽ\K1ƒ]0ù½tkÑÜÍ+üi2 îý^͸„¡5ØÂI 3F ™M²©=¾¨ f6Ó ¼vò/ѲX†'§‚ 5ʧ‚‡¾(SCb†µ‚‡6 + Çü«,å•6lºÇÎ@•°÷60^–Ǿ@ó-µP6µD*x|–áÉœu…2LÉT¢§`Ö5é¶[ +žòËS'hÝÉÄ»à©_5ÏÓ‚í|Qǽ-|¤ü €žO‹Ž· IŸÏo@/M ŒeÏÎ…âð¥IhÙ%<™®Ún:Ä,¡Ax2Wp“—ˆCIéØùR°bzcl™aêıvXðÆ„Åá›~JŠ¢øüKonÔ üKëü·²¤×Ã'Ýëþ@”ù)gÏøw  Ï`M­X;,øøL tÎÿ'¥µàãþhCS6'ɸqþí°æ)ØP¤AÐ-X°áüÀœtÓ´áB Â2ó»ßùpÒ“Z +W|/øî¨Ú¾†8â.o(åž¾ým´³+~”t’O +:Kí. +¶o„ÂñáÀw·Ò ,¢÷¼«Ìn1´.Øó¾Ú_Ö$϶ãØ$)Øÿ§:Æ!Aí + úÓ/å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¥÷t QSn<ðqs4Ï“j€A­˜mChx³‰]5ÞœÍîáz‡î•O· ˆnvÏ*ôÀµlpÑ1·q£µfÜ €ol:ꦇ?÷xcô‚2n’Ô Ú0™/\¬ApY +[½¨ÿNÄP4£°Õ2 ‚ËR8²3_Ô""Ž½!…#» + [ÿaÕ(E ++£…“2Ð'›Ž¢ºñçîh¤Aø—¦ú™2^¢cx+œºJÝù »L(-2†¯²Â;·iþ¥»^Tm*L ¥Já]¯iÞÓw×FÄT?³púÏ„'ó‘^ºf‡} +ê+€Ÿ THzÈÆ•§ ¿UÍÉS¢‡Ulξ\ù–zm¹ñç®@s"¼}©ü†¡¨táK=«ZÚž›¯Ý³_h^»ù3ƒŽZ†ðÂùi=…Ï©>7Ž×à +±Âç,´Äž¦ @js }Ñ…K¾Ò xß¾x«Ú~Iè8+|ñ?éî;YøÊUlpQÙÏPÀ$ü•Ñèµ+ù¢âe¡Â +ºF­äj³^ÂI(ݾò-´:ª?¯5 –O«m´æIV¼ Çi‘…kžÑ h•¾£zÅÉI…¯ +ß©'€ÞÈÛ×kâ‰m©Âwk>Ž Ôòéâ8^ƒðõúåÿøs®rMâ+¿ðËïÒ!ÃÀ¿ü•=¿‡KyY¾<,Ž²è¡ÂOVá—  A\BpÑû + ¯>QGÊQCI¯>@[}¿/…Ÿw +·~ AxûnS]ƈ2¤#n‹  ïçÊƒí¤ Wþ÷óÐÎoøR¤ðâP®‚¶  U­J*Ñ—4 üÇ΄×î§ùsŽ×GKߟ>@»? >ç›$…»¿Ô |sî™ÏfÎйãÏíY(TRºçœ0èO{>Ð <ð½L‹FÝEÁš}áÞ t”·ŠíUþÄ7çÞÐ!~¤ëÕ åÜðç= €Ž,cµ–&4d˜*h…áÉ<ꇃR)C'b°ò ¾ªAð—šçÝËâ0MØ)|šçM@×võ/E+êõ‡‡³¹ü@p?5ÿ¦R  »ª›mþMfdèßÒ|Ç/,X©˜°ÁeÒ|ǯ¯²æ¿.æe¡°4ëßËÂÿu©:¬ú)&)ÓÖ0¦ÃÛ5îñ¢ +gª) ×Pœ&RT¡—Á]PTé%0( ßÁE•žM‡ð\”é?[D©˜ÅÁ‰E™[P–ï£ 1îÚ6ðpe½ AP÷-ªª:ØT²‡^U­Ap튲»ñ1§„ƒó¥(ûTTƒÝ8îª |Õè®Ap«Õ +B›"TVÊ‚¢ZPƒ1J¡‰Æ,Ckà¢cPÃ%ü9’«)\…¾¨áK¨ç&Q‚OÄÐö«¨Ñ?¨ðÚ@…¤TyxŽ@­|½€Úí¹Æ$NÕ,jÕIqÃqréÆ Ù`E­n@mTô)=ïRZ‹Ú@íÚ°8Œzþ¨D•p=%Ê»r©’<Ôž3©•ƒ€Ÿk¿YƒðÚE©íëÊ1CpbQ¬‚êøªZr›NpÇ×ÐÉ'°³]c9†Ík´^‹ÎX{*÷‡§àŒ·5˧^쳧ÛÇUU°èéÕEÝÇ&.©F¦»¥×t4p:›“~iLô ÊÂ>ê¥þâTƒ¢¡×  [YØ{½Ë ñ]:„oι‹ùpÆ©•+vX·È]ªAp?µhQVË$sðԢŨÍ=eF m,mÑfºê0_]ed¾awW‹ Ó!|#´èô[ Œº›«-:ý!€:ŸÏW„’q¤g‹Îkþ¥RåÌKøî%8ðÒ„êÊ¡áî²P§¼,'U@g·áϹº?E¸a¨D•à&)ÇC tîUÁئ¢ˆ-Î-€)…&æ]j%€†õPŸ‹Ä]Ý|XotéƒÁD}PðA¸ô ÂÝHU¨1IÄ Í[Œ\(^àÏ9ômøÈ—ШSYD“IipRµu†á1]åÛœ º¡C¡ëWM@·sÅ-¯ü«![µÅí]%Ðh¥†k ×WiqûõhZ½´Mg(ÞbZ ”¯B®Ä4”ñn1­™ú>pODMJ{‹i;5ïÌieÅj,ËжŴ_Ó!üàßânÿ•Äñj¹‚ZÜm  é¾jDE[©Á’j¢Ax<ŵ»(96bp¢·xê= ô9«ÿ^)¬®µxj£áýô4¿•ù + ~jñ´-€æ)!–¤4TìØo1¯Ÿ:‡˜,c†e™w®zî1ž +p •îå?÷„zÞîŠS:m0[<Tƒð_·$hséNgÊ é–\!€–Vå)ðŠ‚`×R‹¥5вÊenÛЮŲ, 2üÒ_8ôÚbè¸úè^>1Ê-4 ü£Ðeïæô †'óÇ>÷S˼ÏÁêNÖh™·Qð…XŠ.ؘ…½F-G@7Ïf×=Ê„j+h®A÷iËIÁJAœpžZN:$€¦ÌHs¾ÞZNyDÝUV8âÊS·¼kºš¦ª¨zí¡q(oËi­4¯Ý½žNçµ­H™Ìî–÷ö–@œfKa禮:-ï}Xƒð˜fþ¢®2jñŽkË™¿jb-[¢ÌɈ1—¤åc/jþëž<_™n‘”e(ÚòÉ‹4^ù-çÌ¡„WðiÞé„Ç4N¥,Cñí–ó^Õ <¦%kY]KQ†4Àm¹dZZ10à)ÄniV:dX»å\SšP…Û*¨µás·üh`ÀGÂÁ? +úG½q‹‡Š>b5¤åãÐ*_°Rûx4@Z®Ú"€ÖûËâ¥iZ¡V® +zGƒ ÖÓòýóƒk#j*MÐòý‹4ÏÓCÙ¸±É™gø¥.@r÷v2oÂ.ø‡ÐæÕ¬þ'¨„ƒaY6¯@_]À ì%–å«‹Ð×ø˜S' ƒS¡å×ç + ï8 É+~j&ÈŸÛ~ ¸ƒSvç¶Üþ›:p +Ÿ`êÖkhìÐòÀé„Oð‘×Øz%¯vÌpåY.€Ž/âý” -Ú UŽ¿P>tâ§~•ºñN¨¹RCŸ  /ý×IÛËm0TB8ñË…؉›nL×Ä°-u⦛5Þ-'îäTMÚ*NH(¨DƒàŸøsõ4ÛWàyêV"€ú=¦<448Ưu¿§Ð §s1Ô­m=`°Á+¿õ@_Òy=LeZ4"€.h(4®*Šó^[_ÐLPþ‚ {Ãç  ÿl D´W[Cßj”ã­/ñ+¸Å£¶w•á_º¤‡º4ÁF ucK¤Ê¥Ò!ƒT©ÂÕI 1øUZ´4ÿu—©Ê‘0Ô2i}Ù»è&~í&mÌÉÖ7]¯AxLV׆«ÖFC™W +ºIÝÍwA,ìëQЇèU.I#܈—åÕGˇÚ<}©bä‹Ær¼ÍÓ#5.p›g[°Bã×{Ú<ÛJÝ\Ô¶cxxlóìT ‚óÔf—Nñú•z[´Y4K±[ÐrEO2\·VAÇÐ]õ?e…+¨»á)xÿj†¼þ&¸ÛQ›÷¯@_ÝÍ‚Õq·œA¡ióÕ}„Ç´#›F‚Áà¼ü6;rЮ>Á‘rLWmv¥AxL?³2êåñ’ÛüüÚ_æ/°¬6¸ÚìŸS>ÔvhfÙSx†ªiÜ™m‡áêî”@Úí¥ApžÚ.«Êª6EwBÃÛ.ËÑ è;l»Œƒñ½8*›$m—}§Að´´ýàiµ,Q+fÈJiûÁôavpQ'í¾òÛ~XC}Ä}“¢ÔG"TÏ^AÏj^à 'Â>nzáj»ád ‚Ò·í'=yà®âç*Èø—>é#€6ÍŸ#o—ᡨíæo5¯ÝVV£)ï¿´uŽá_úöª´ ÈÖßöÛÑèû†¬ {ýšq³¶ßçk^»}yàIª¯‚kÛgiÞO»T`ËWk0TUƒð_·û›@…´,Ë°Uv'€~ÉS<å­¦à—tpwà|IÆR¸nÛƒ{Ë Ëà i{PuññbÅp$UÛƒ¿ižñC~mŠf&Ï7žñC  Ã\eÇUû’NÌ éÿ£AxÄ&nŠÜú8Цí‘!é¶ÍÛþÁ^H2¹bq¬B¶ýã=tTõ{¥ü`ƒÃºíÑ¡åCí2'*!FQX5j—y[:„½µí2° +IõU’8~¼]æQ”ý+Èîµá$ñ}×.ûT«gp8ãQƒÙÝ®V_ ‚§¥]í}2JÅáoWû€ªW•,êl¨:Ю^- ‚îÓv'L +ÔW­ÅnÁv'Ü¡Að ´kìKߤ÷ÖÄÙ`íçI _`П«=áø‚v@MX…¤§X»ãÛ59Gƒ ,hwâ­aj‡ëÙ+èv ‚ò©]ë·ÔV‰x50´Nu(âí§R8‚±]‡Vè0Ž2 ݶÛuø=2œ`ç^vOÄ¢ISßÉvÎt “Ù1­­³©C\»Ž? + “ü''÷ìÒøÙ¢ÝIç îùâ÷×ý÷²(è ÂçnÑ/Ê=A5 ;sÑAtðÿ˜{â>hß;øX:dø_Õø¢Š¬†ú*íþª‘áâªJ–m[øR,>!G5º˜¯WÒ ãX*n4\5æ¨z4v •ÉŠ/@yõ•HOsX÷-Îk$€ +üws¯_YÄP̽¸ ¦Á ¨¸Mo:ºòC]Z3Ê@í†ú[ÅUk-JÃÐE¥Jq‡Qqã®2~x,îp•²üÌ+›ŒÛ¼_lm@ü~çxs³»8‘©AxY—2ä»ñVIŒ@É£Z›25‚,Nþ#€:«’dH؆)(Í@Ü^–æÈ +uÌQÐ#龊»©Ž¨ô,cpÇwûLò+Iª€ËPŸò’:5=Å`›ŸZW©š{S†Z¨VîÌWP/¿òï`LàŽ& + ÞKÓn¨CSÜûet¶ßDz?»¾Í‹Ïž¦Aø—.Ê+û\ÄQ|Q ¤±yA`X°^ÔJ];ŒEtÜóY KÐu*‘‚¨ Ñ]Å×ý%€ÆÎ .j“ÂعèöáÊ@ºMÐehúŸJ qU¨ü«‚þ@OuWÆr„Þdð Oƒ€‡³ä²ªhœÍ5åòÅp]È’q)tçå»Ã2YŠ%7U@Ïg4<™<ð‰Ó!ìè(¹«%)÷Z Ç+¨ºŸ ./bßPK·äþÉåSɃŸÁ‰…B›ô…AYPò0wô¢ÈáXèq]AU5OæÃlHУL4Ô†—åá÷ÐìSyÓE\³ÛEP2»‡áyz®_¯1ª@‚ ‰’çêj´€Jž»••’†ÆÏÝ®AP+Yø) Vªíj¨«]²ð ÂËòü ˆŽXC¢äù—4Oæ¢G”’£ª¼ø—ÍÒ üK‹Ç§]ÔßaÉâ[4îe_÷åîØ(y¹ŠáÍw ºz¡/1t‘á_ÃAw^vaÄ UÖô@k;³aš¢òVX]+Y{’á¯{J‰èHÜJ`Ý·dÝlôŽᇺ†ú,óAx'®AÐ*+yï e&¹×OÔ°}ßÛ¨AxLï×R›Ž¨A¾Ÿ«Ax|æG¾Ä©>‡c„ØgߥCØ“U²Éâ­õú˜â¿nSRƒðç6OeÈòÚ àÏmž–aÏCÉ·×ò§¨M†á˜{½áÉ<ìק£'qJKJVÉáÕ„·ïQ¿6NŠ”,jÜ ·ÊÑ74oºc·²BãP…$à >v{ùPû:³‰ëUÇ3Þ¾Î''³}ßj¬ÐPWòPƒÃ †jhÔéÚ÷-æKѦÚÔ¾o´€ 8SÔ–;áøs ®@kW²BãuÅwKûµ«5ÏÓ[»•BC=e ËòÖ^ô…zË÷.kÚÔþ‹í„þÕꢦ§|›·ÿêM´S= ï-Ñ[  {ždmӭ᯻ç4C½·Ä¼nGPôDgÔÕ ËØŠí>MíÂS ¢c8d'¶ÿ ÂkwøZþ•ý \Ac4ÞÁVõZ¼À^@7~¶°ª×Õ x#XÍUÆcÌëG •«ù^ ‚ºŠÕf)z”JàH*«Ítô§4CÂÐÂÆ:úsùÉõUüî…X/°3›i\`»*g^Ñó¬é1Ô®:@ÕW™WT–+ƒîìúwh<ÁvýÙJôD–á×®ÿ¬á15,kH± Ýì†ß  ¦þiñz•Y6®Î`7=_îã¦Äœ¤ :(~åeqÿ®»¦ ÃÈé\ÔÔhÌõÖ x#Ø'õ®Wê‘ …˜}ÒYè”7yYæŒö)kPßÚpeª×AJ»Ç! ÂS0à™`«PØÞ™æhÞ™Ò +ƙҎìÏk>-ç]]¦dY†· û¼Ñ„é‚xÚ|bö) ÂRå‚Ç!Få}ñV¹àItýÄŠÛ!%KA“ʇœîÊ$¡ÈP}Ïéþ´ê¥2שè£Á»æô:¦Aø—ú.ÌîHÔJîô]™a»ÅÈ¿äýNÒ­@ç«·|¯Ø9vO8ç¯@räpÌUlCÓ çÂ;е3‚k#f*eè\ûˆá_‹:œ”¸‚Å¡3~’št9O•M78“®Jƒ ­\»T±š„WNž`ç®yhšŠÉ¢ÀRCt¼3­©á_z@5…QÒ'vw9¼¨Aø—©¨L\êS…KGª GU+2¯ÆŽá´<ê¤C†=þ¸ªæÚ¸á } €ž8lºˆe–å‰ßÐÓŸW¾ejá<ý…áƒðLIšÙªB¯ ˆšsŒÕÚ¤§`Áúl ôŸàRL‘#CÃ5OÁ¼eJV4eØtójÞ*óý°YJñ¡Ô$xß9ó§ çÛjˆíZ:Ï—¤CØÝå¼ ÒQa½PŸe%5Îg²SÁòê"âϽøá=þr{u8cTÚ/ðË1ô +ws…=õG0@7H 5|½¦"¶cº6^y[ƒðd®¨¥®2*†‡m)gE´îÌ@D“CÀõ@ësƒ­bÙ†þÁÎú$oÙQ*j7\@ë·kÞ`(Bj†ûî£ËÓ C ²óÑo+€Ò" Ðï„ÇôñŸºF Lx«|ü—ú„«ïÑd†²tŸáý´ñ¾6º¦ Blã. äÇø9Ò5„¥9 -¯xa±L½œœ-Ë%Ð*¾ò¾¹Œ¡5h‡Bª¨WÜúXƒÊ‡â¹¢MÌòºÓÀŽwÌ@÷®d‡6…Kùs÷®Ò »ŸÉ%ié(X†éøÌß5Ê‚ø#Ü4(⹨ðä ‚7B|V·@y b¤èTôÄýþõJªÌÐg9þÄŒtKºøœÍ,ì^;¸éâsþ§AЙŸÿ¿@ñKF mâó¿Ó <¦…O¤©F)ü\_ø´za[™25øXã/l× ( ⯜ÉǜʗÜâ¯ôÖ ¼,ËÇ)(bô´Ç—O@+Ö+ÓR2°ò_ñžáeYû@àèp7aYÖ>¨Ax2×õI[ƒC(¾îl 2üÒ²àÚˆÛ¦µ[·R­W '1¯øž§õyè>,X©K(óJAg  ë§M¡ZüÃÆ„×îÓÖejˆex{Ú6ÂÊhüKßK ÒQSžbüËÐ×;X`P÷ÑÈ¿Õ_ÿ(€¶ÕæƒñzLáÉÜ–+€¾[ÉËBé4¡V?ü¹ïÞ@;â{‚Ž9^»5¯ÝO¥-p¿,ÇzRíÄ¢ŠÝ‚qõäôÿBUÕêëÁ&nü`kt¨C XÝ»›nñC1 ¤:€SÀº¡£WüPJƒð_wø·ô)0ˆÃÃG5îèe’Ñm8Gß@Mf!FªŸá)%þ×]„wÁßý‚cîPj†ú  cgªÃéþ/…Ë%Äõ)JTÈ ¶/­0<-‰ +5PV+£®ògÊ”$²š¦C8õ7‘Í-o)iÁ”GÈÎ’@—cœž‰ì+4îÌD5Õ£ˆœÌ_t¢ZëtËñD¶ü9j[a‰%¨¦¯û&È)N8áɬùŠÁèÓDÍwÊØNá0ÇDÍ÷Pîh5ð˜·Äº^åûÛ7AÏrŽ¡O"¿¿jÎÍè©×6<ò%š_)€ìC¬´G¼†OøHÙ‡5„»¸f^$n.µš¸«¦áí;m!o:Š´wp®[bÚb ¿´ÉS´é‰À2O'6½%€6¿ìs‹ AC1ˆÄæeéîy•8vu †$#¡Òâ +º¶|(™ÁG*šˆ¸_Ãî‰dFDeÄŸó²ýpã™dVw ‚» Yµ,VÛ €Ÿ«z³ªQG*âÞ›ø¢NÖ±P½iÇÜPX/YïGTß÷ÖR*”1x!“õ„g¼À7$ß +Æ:]²`•Aå!ÙTõ¼¢NËñdÓ_PaÍÀ=‹„ÌnÕÖ (3“E5”{" +BåT[ƒðÚmI3“"ØtKýOƒð²´ª¨kVÌPö&Ù*Gƒð<µ™LfÂäN¶yXµï¤>G-c ËÒ¾‹Š¶IS!S†­-Ñ <&û.VC,ò>aÕ(iß'€’YDSv {“É&èdõ¥b5†Óròlt:G*y545Kžþ¤áƒÐÖ%a‡*Ý)(!€zª1ÅÿŸM×ó Ô¯šZk>×o ð _Ô^ + V×’¶jÓß×÷ËÓáøÌä‡4î²ÙþõJ!®í Ý‚I?‡«èšíB“²C—‚vjT’ÿý21S¦qò¿[4ÏÓ̓ƒvåv-%o>OýϯæB³C™| +V>”êÑ™NΟ(qHφ1õù\ƒ ÌLõý#¸€’®=‰'³ï?åSê~êõÚ‚Rçt@çþLf2f(zŸ:÷¨áüPÙU19H ~T bÿ£)ÛÂPjh‰á]pÁ€4åÁPŠ'uÁ¹„?7Œ»ÓÐWNTP¾áñ+ÈÔ#”ÆÆ›nÄ3h¤ˆèX,…­üÔÈ„ºÂ×ìSQ¯$‡©+N@WÖd3)A 8A ue4f ûDÄ ™ó_ ‚235æså2qM·PËm@7}ÌG*N#ÂJVê¦OÐø9eÇÜTÈ#5~®á)¸}zÚEÁ~ºÔíkþ¥i•À Ë7©iCÐÝ»‚«ÌUü°þ”º{¯a©ò Êç$—®!0"õà+è‰ËBÔº’zâ4ëÖRX¿c蛚7Y-Ù¤ x*ðïÉä#µd‹ZM;æqìZJ-µ5ée¿¦'=‰ÓÓ#tO¤^>S-ó\ßÞÂØaKQA¥èõG•ˆ¦‡ ì‚K½þ„z[àhÔØs=õö'„·ï§KÒ¶ŠƒÕÚÔ§/ + Ï2X°&£I+ŠÝ©Ï*  ¯”]N¨01OæÆåéÎJImÞÉSà^Ô”¼?·yWùPÇTÉ"z"%Á(hzn¡2¸\ÒÁž‡ŽÏ-@/¼Z&XMò©ã Ë5ÿÒ+_j‚ž»Ž¯l@+OLƒ ýÊ:®l-€ÖÖJ?æØ©Ðqm®ÁƒÐñÕ*‘(;رßñƒùhÃçÊ!ä;á0´I}¹<8œ©˜¡ÇcÇ/ß@*Œ^dX­íøå?h/×­¥G>ÛéÙqïÝhŸz+£0ÇõtÜ×_ƒð¹Û¿¿ì2Útܨ|¨Ó¾®BÁ®TVÍÍ× ¸Ÿ:î•~°N×ép? ‚óÔ¹Â"߀§‚q‘'+ƒ¡¥(ëå¢r X뜵Låp;Jˆ³mÑ9çr ‚“Ù¹ƒoKQÞ¸eè§Ø¹Ã£¨—Q¢ôèáHuîvžAùÔùä¾êH¹“ias²óÉýÐE÷óVñ^×±Òù¢„çéJNØÒUžÂ +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•^òšî—pp(”×JâHÏÒáíЈÁUæ^‰Xª”Ž%®KWÚ k7b¬:|ÎÝvØ$)ñ‡Uȉ›‹–Žj)€F¯ 6ÝfPf–Ž^¯AXÒ{'€¬ˆ! ©tÜû„çéÖ9i#‰ÕÒ[ç  ©¾œ $SK¤Ò©¶švYúç°!Q:í +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|] +ôEŤ…•Q>æ»6h4¸ºìÛÄW>)Y†Ÿ.û¶ C~ÔRŠ +Ì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ŒŠ'qÂI×-ÓзüJBO˜á4þÜ·³Ð~½Ã¤WÐ2öï?÷Ã¥è`E>œ´*I¬ís†øñnÓß× ¼ fœšv ‘ÃÝfœ‘¦`ÆGeÃU1 ˆî6cƒZÄ­Yh +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½UûõRE!•ÄjH¿^¿ + ¿Îà›Ó‹ŒÀ±kýþêY>tÖù¾ß7MRâ'¶ÊÎ:ÿ¸Á|Ö6$(°ÉIb'ÕYS¾@OúÆžV.UŸÁЩåCgwùU¦dºáÏÝåp:„#öÏî›Á’.I–96ÝÎî[Eƒà-Õÿñ!ÆJzÜãý¿H-ç6ThÈ1Gƒà˜Wº+˜‚¸e(Ÿ?¸Ò=Æà‹×³MmxCE6ùs €ñU#réÚ×?÷È ‚ó4äfÎS$ÍÞ‰bïÚ›«  ]XD§¢Æ}Ct+ÚA¹t“ô¸Ž¥ïÐo  3ü­’ò‚fCAœ ^>tA³Ï¿JÊvþ­Ù+èK ‚kwÁ£Õ”ÝB…«°ké‚Gk _ &Ó뇃¡×5 +Œ ¾ò_]©ã.q(ÙZAo¤CØt»øì›X¡ñœyØ*»øì‰Eôųú0DšÂ1~Ï Apà—|9•/Ť«E†Rî3º·|èÒü |åǽfñð¯»4ÿ ‚Ýð¦/¥ƒZ;¼ékhH) 1zp +e€d0ÔMÝþF ŒÆÂþqþÜí«Ë‡Fp7rWÙÍ(º¬çý,X½‡÷Óe=ghü¥ËïîÆËBªQ +‡¥]~÷©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÷Ÿý£ºã•²‹ÚÔ@ìþ;–kœñéûü¿Îñ¶‹á Lßw¤|èu<™^ab·Û{`Ý tŒ+™S£˜¡QíÇvh”3_ÌfÓÊfD±a:óÅêgüÁá+yªí„Í)ztœ*„Fí¯£øR|t\n:„Ý‚ÎíÊË÷‚8ámþèÜS5NÁcÑXDS¥!Ãiy,Ú¨|hV߯Bn¥¸«×¿nV›÷P¯Xyp…½« CcyV¯ÆåCOV¸X‰CJ7ÁaDOV®AðR|òU ÂñƒáÎ|ò…fwæ3»#,Xm×ì¶pë3»m ‚çnöúçX`¤¨ÌVFg¯_¤Apžž­÷=O¦W'Ïrµ4Áý4·S[mÓÁ¿nn§öè%µéèúIbaîKm„¹Lã'©Q>œs?¸_ƒà/ˆLdç µ2 |Aä6Ä14) +”³Bí2ZX>´¨ôV¾^îUf(~´¨tŠÁÉ\Ì]îÝ  æÞX÷]<¶ªš +^s, uÑ ¨-yã»@­¥f‘h§Z{ +äÄ2KÖÐ (0–lø;€’V¨ñ CŸd ]‘ÀàŠ:œ˜³d—á4¶>âú*^lq¨ø‘‚Æi¼ï^>¡.œj—…DOC'”-?ãƒ@ª‘á–Z~$®Apà¯×ÜÊ!æ]ŠpÓ½^ó;”·Œ/ J¬3”8~=o¥š¸R {jˆ£'^Ÿ¸ZÍ(`q‹ÐdâÏÍhªAp«¬|ã&µé¼¶Îð˜¯|cbùÐê—³ã†pá˜V¿\Cƒà˜Vo›ˆž˜Éæ\½mAùÐÚv÷ñç(½Ýð´¶Ý ‚ûim»—yÓQ)Cƒûtm»×4Þou®Í׫+T-CÏ·:×@“âeJV8Y(ƒ¡Žè®±O’7jˆÆyëŽ4®Ý[³F +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œ±+2~)Ì.ÉâG;¦K7$žÚJT`ö­ºcæÿùQÁi:ðc4œ´AÇ +|™Ul+üG§+ѱJéThÌTÕê…©ÐsÿϪÛ®^¢RõœT¬´ôïR'EÒüŠ‡iÞìÌ<Š'À»2ÜŽL,o~åç…ñÿÆ}ðµ¥yÇÚ•©Ä'Á«0ÜÎûZþÖ9ÇQ</Cñxš¿ýZS†‡øÉO¸N縒â!x_Š§3m§{J^AðÔIë4ïCñô‡ëtï¹c(Gñt¦íôææÕvþ*ÍûS\þö·Ç]Oñ8ø0ŠËß>ïç ÷<ðY—Lûþñ3)ž™áRÓvZ’^ôUsü4ŠK¦ý!6›âIðW.5m^‘ÝG(ßS„âéL›×q —ø$øë Ó™6U)‚ŸHñt¦íp`ópåÉÖa¹é.‡.øŠKmS{Ý·jžHo+Nó-—§¯|—>ñé@Ii>âòô ƒO$xjÅ#ÍkS<]ÞóŠÚ]Ííïøe—L›s^ 5ÒKŒi^‹à1ùpyõÖ?E¼ºÔ`3ÍŸ¡¸tJ›üü_ávx– ·w2Çåo7|#Áò·wì‘,©ænzgXš—a8zÔ[Œ¡þöüNêo—WoÏ2&ñR×¾’âòôÛϺJÍí!x?ŠKßfÍ5ç«y&ƒxG†ãÕm¨õñêR{ÝÓ| Å¥ªÜÕM_dâéë˜Ó|3ÃѾ×ÿMÿÝíÎ…$ø5 —lÓÑùøcp7Kîa<ˆFq©ë–]ý¼–;É f$ÍgR\h×zuâí>|Å%×êôÂxS©…S”¸âOÉpþwªŒP'Þ\'~3Ã]yz¬¤>Û8ú´†¯¡¸¼º…ýï×8'µV›æ“(.݃Ü:Mˆ"ã¡c–[§9Å¥k´oF;âÕ%e®Òðó(žN|çž\¥O¼ƒ™RÃ?¡¸¼ºr»ÐÊxé­ø™‹ŒÝ_î„à[(.o¾þ\p·^@â=;¿-”áU).]£«k`¢Õ†T ídRFnF2édøz†cÒ©E/À½T¸·ŒÜOYƒÍpÔ6=‹ïWs{-`ü/‚£GÝé·p”šÇÝ„´°†¦¸tJLh¤æ®ùtxŠK®ë´tp»©"›lc/‰Œa,Óié7c,óã§ïªy,ˆa†üÇOQ\Ú÷/»W$¢Küe÷\ŠËÂÊ™kPd×ò 37=ÚÖ&Î\³â²6qö Æ ¨*Ó[„=ðU—\×±ÂFmâdw"þÅ1®û§þÕù¾?Èð@2í¤Oê¹È Ôð¡—ÄÿñÉzž™æÛ).õ¨Wªª¹ãÇüDŠKE½òÑô~áÔ®Š0u)ZÆl“ðS›ŒÒü]ŠËßþÅß…™sPd ÿ˜âÒ£Þ0ý:âÕ%0Ù0}Åeæäh%_]`ãNRÚ8Ãc—Å…R^×s{Q,ø[ we®2·þrõ«óÃ8Ú÷Üú+).]âÜsƨ¹ÝÝქ¸ôç[ž©Ïuv×L>œâòá‚>7E&.õ¼á7S\:ä;P]¤Î‚gÇã~LF†/¤¸T›Ïº­0^Pí¹nn›ÏMqùîejÆ”‰myéYž¤¸”÷ÊõîÒ¿:»= +|"ÅÓ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¾•áXÈíŠö=ÛiŸÐ·”¹ ÃWKØyW]¨ÎuöÒÉó†×§¸”¸Æ`0f¹Úã“Ž~=ÅeøÄœ³ +ã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öúü|ŠKâ¯øýy}uáFõ¿Ï¢¸Ô6æ!×%RË÷Ù|8Ó HÚ𥗪òƒÖØédõÙ,"§‚b1ñƒÖg2‹ K‡¶×r›m°:°tè¹—ù/÷Ó'ÞFBDqyúÁ÷–¨ãÒ%6|9ÅeZ¦ã\ðÔæÿoø_¼ Ä‡fÜâ2C^fVo‚£Cnx_ŠKž/ߧ +ÅãàÕ).{Λ.Ûu BqùÛ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Îô*;æ}3˜xužÌtì¼ã^æé¨i;ïxâ’i»ÞÅàýŽna×S<šâ’i/nø Å“à3.ÃÀŽ½®:LqI|¯«‹P\ßëÁB?Ü¿eZ³êµ–éYyØØkí"ŠK‰ФÃQUhBeZT•7L¤Š öÞ0±?ťĞð%Á}tJGOXGqùpVN ²ºîÞ¹¥™§£®»wn9ŠË›¿ïõBûóÿšxÉu5y:&ÜjÎŒe¢/‹v1ÕN.t\ô;S]ø¨ëýýÃÑ-\ô÷—·òó+ÔÎTŠ_MqùÛ?/±J|œËD!b~-ºŠâ>ø'—ÅÄR]0E;ZœØ’yzˆC':—¹‹W-)Œ0é”æ ðåBÄxGˉǺŒá).î’—“TâåÃ]öZQæé8­sÙk%).îòŸ™6N©áÌÄK u§«žK_ãzq7u3\–Üÿáÿðx–\þöµ¾P—¸ÔºøZŠËÓv9H½ºøß ÇÊÈ '. ¸~!Å¥Èܘ<âIð —z¾Ó][¿¥xÎŒaq¤´Óøê/13äã«¿Bqùp“î©E´2L>tzüÖO€ÿFðõüÓ# ­i äžý'ðS).ßý¹=…¶ïÿšø\_ÛX.Ùæùò?ª¹mœ0|Å%Û¼¶î2"×…xúkë +íUþ+—šö­ +#(‚ßLqÉ´óKÅŽnóKšiÿ•Ë›_õõ@ŠÇÀ‡R\jÚÕ<†Kd!ÃCŠK‘ù|oMŠÇÁk3\NçuújçGLÅ µõ Mü+—÷͘ÝTâ“à{Ž­ ›Ê>EñüYŠË‡ûî¿…ÿíÕá øÖNȧǰºµÓ—Õÿ"Ÿ¤xü†cƒ\ùc…vJÿe0“š6/§FâÍǤ¦Íkø(3Ù“šÖðBG‘ÿÆqZ§Ñ]…ömþ•ûàu).ä} óꤦÍk|”éÓÆíñÑÎOؼ3öÇ$çã>ü¤ÐAè¿q©i /Cq©iœ÷¶ðdꮃÌÜîùpлøqÞ<ŠËŒY­71?ŸtS7-dæ®ã#hƒá‹(.OÿèÃVzn£€»—Fj͵w¨¹}}>ø8ŠËÓ.©P/ ®³wÙÄ¢íyK*R\ÿŸqsÔÜÞŸñ7).}Ú:­¤•ñœÔÙÀ,¸=ú³uZÝÊpŒ¤*œÙÜžÊüáì-;aí{…3[©yÒqäÄJ^5µõ<ˆ‚¬ÖXS‡âòê–4¹ ÜË’»q/š)]Òd ÅeŠ»yõ„§#Èeæ6~]«BÍ« ¸T•MW•Ï.¦“ù“6¡éªŠËêÀ^…Âø?3­—º¿ »}>ð*Q\:'­v=¬N¼ïE³V»§¸T½¿¼FÍóפ @qyóµg<&<M+3÷ìÞSl¿¯=ãiŠKâg_SàèœÞˆá®úí[‚{²¿Îð(.+¡­ŠþîfÉíù{¬Iµ*ú+Åe9oÐËgh¹©ç1‚6ülŠKâG.˜¦æq?Ž§\ð<Å¥cöÂ}å îb¿Í ÷U¢¸™ù¥gªy2:­cølŠËú¸Ø +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øc G‡¼Þ¾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Î!Š#ö~_t S±û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øm Gh 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ÙÍÛ§2/&šöÍö]\óö£—ªòö ~Vs{» ¾“â˜æ]þ¥š;nÔ¾7Z¾–â2KÜrÖÛZn»Äù|>Å¥²êzÑWêÄ›ÁjÚ®­£¸<ýîW©3m"Œî‹¼{ã5G3qy_õ«‹‡Ø†mx?ŠËÓ¿\1Dýêl=k…W\GqÜn“3AŸøcXÃïe86ï/¿\_`C­û˯ ¸4R9#NÖgZWïîP\ºÄ-p+±&ñ~º¿E…(.‰¿ü©:jxØ,dx}ŠKwýÖ?õU¥ƒŠÚðÇÔÇ +ÙÉì§6f¬.|»=ÎCäÀ1+.§¸´qt½OÍçã ŸDqÜÜwN_"ñ lœØzΊK‰+òØÉwp½Èc.ÅåÕ}Úbxv j†'¢m™†ßAqYʬYg¥–›Î â×þ1ű{ÔO…ñ…üTo>µâòÝŸ:púÕÙô>øŠ§?\‡¿¯› ž:N›qÊË·Ëçqùp†¿Kq™êlðŸjn·Bà7Q\òüŽ‰ß©y"Ú¦eøŠË‚ÚÎOë_]ípÛy`*Å¥®tO\Ï]„ö5ü‚#´o§)W<¨æ±hYÇð‡).³éU~*ŒT`í‰PL:M¯²âòô/JQ'> 8‰üEéq—·ÿ¶³ô¯.Œ&ößÖžá¸Àýª÷cúÝNkx‚áÒ-ì\uû1ª²’Õÿª;ŠQ\*«eKÓ‡:íš½½ÎËÀíïlÀËø' Ç|]üÌ–jîæoÛˆKÄ -—"Ó嶤>ña“N]n;âRdîÙS¦0þkgoöqÁËS\è†]¿"^]èb®²ë:†ãŒXù.Oƒ»Yr7àL¨áÏR\úó5êŒVóxEþ¯Qg,úî’oÕÜü¢a×]²…á8>ߺ_?5·b]ðA—õwgûR}âmX&ð•—ï¾ý¶úçD×m¿íwŠKM»ûà*5Â8ŽÓî>ø Ã`öÆ"3õ¯ÎOäó—(.kRÓ–æQ¯.Þ…âÒ»XßëS}âM§Ô_MqùÛ7ŒÕ?ÝÞ €ëŸn¹¼ºÇïÖr'F‡û~ÿ'Å%ñû¿§u^SÜû¿ÏpÄh=®æ¾`¢õh|$ÅeòaïÌžÂS!b2vÌìïì^£øÕ G¦¸³Á£#fwV ¸$¾ò²1àv…2‹Wg'>B4•—£¸¼ù_¦Í)ŒÐ5²aðÝ ŸOqéUv_YV›x'‘¿úß}e†cqaøâwԯΠ¢›:‡/^Hq©.^}ÿˆúÕnç&^}ÿÅ¥ÀÎý:OŸm<Äê4¼+Ñø­ç¦æö}𶗵‰¢‡kª_$0†-z¸ñ´Q­ÇUjîú8hx?ŠËX¦­÷´ºÈ$ý¸ôë ŸFqé× /‰ö=´!›ªÒå_v9¼äç—§œöva¼ÀW—p¢ËïFN{—âRÓž5ép7»ÄûvšO?kÒÝ—ÞÅÈs7h¹í•â×Ès7Q\z•÷ìîeËýü ð÷컎âRY=_w š{A4áö|ÝÁ GïâÀœ j ¢iŸs¤¸ØçÆôUó e–Øpý« Â6Ì”û¹¡ðÔaÞ,ª‹À5ÜäUî禗ÞÅõÇíÓrÓ=ðëãúã2nîÀaêÄ;âY>’àѱ‹2MÎ*ŒPYn$^¦I{ŠK+Ó¢Tký‡ qðÁpâR×müõ<á©£ÄYp{¦ÒÅù÷¿v¤¸tŠ¼|PÉí™D÷ Èˇ).Ef]ë7ÀÝl÷ã¸~n]ë¹ Gž/;îd-7ÍDtà¥ì8—âòÝ+}SÍ•U§*›S\ö›šÛxøŠËÓ'½Rèw/ À¦^Æ2“^)ô»ÿ+Gó +ýîq;kƒmknpŽ-+5ŠU÷²}u~Úð—ý6/,úUÍc®‹¹ÊýÎp|¸"½©ç~nE>šGqéQÿkR±,—6Li p]…á­).u]…ÊåÕÜ´îí[¡rEŠË‡s>¸XÍMc†Lë|Ѓâ2èðÝý«ó£Óy¾[Bqi&ºÞõ,‘xTV†O§¸äºIŸVóD~ì¾I§R\*«š÷UVóüHà†W£¸ Äî®ß‘Ê´xg†£¶ÙÛ¯1“x B÷ökAqÙgÕ$O_Þãî7\_Þ-—lÓ±!Fб,§¸c®icp­pdž›).ö’Oâjžp/â§R\Êûøq=ÔÜWÜ;0~\OŠKâ­ÓLÍí±Ê¼ÅѾßßXÍc¦ªtÀ[P\zVå÷•UóÐOäóŠã¢ÏMcõÎObUè®MwS\ž¾æŒæú"ãG]£5gœLq©*÷·< æö½ þÅe}ܶ&…ñºÄ¦R3ç$x¡Eæß8vy-þ´6ñv‹ñûâO›R\Ú÷1ÛPÛ¤Àeõê’¦c… ðÛzR\&^f·½WÉm×ÄÁ¾ÊÙm x4 œßú%‚G#©ù­_a¸TVy§_»ZÍ·]þÅ¥[˜û6úuñÔâB¦«y,{Q+“ûö³—lÓÉ/§æ ­†W¢¸tJõY æÉ0ĹR}–Q\²Mûwi¹)­Ñ´Oûw†R\jÚWÄõ.ÿJåW$ ¢Ä~ò~ý«óq”ØðÉ—ºîÎæXPKiÉ¢¢Ž›Ê +×Uþ<Á=lŒ\=ba¼À—pp—á÷Çi;8ò ¸›OØ°2SjøvŠËìA“ë^ÓsA “â2{ðÌáâjó=|÷g—$x´{¿Gƒ£jžt¢Ýû=¥¸L°/í¶>ñŠŒáí).O__ana¼€"cîÅ1__áŠË‚ÚCKNT'>ÝJlxmŠ#Ð赘îK.È\Y%lDf B_¹vÅ¥gÕ´ÇV5·'Zà;ŽFªMÑ:jn7Bûàõ).EfÛ³Eõ‰7?‹ƒ— ¸¼ùǨ¹Ý냢¸T•uf®žÌr9Ï%ÆeX†DqTÔ›J¨¹d6¼4Åmí#jîÉ|þ8Åå»·Ÿò§š»vÏøŠK¶™r…S/ ª´¯.;å +ŸâÒ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¦òöwfüŒÙÂœ9S\ª‹uý«¹¢_gøPŠK‘©õi]5·UK¼Å¥¼×›9[Í훈¿Fp™¼Väx›¾^63÷RaâàëŽ)¯Ö%æÝBÃߣ¸tιÜ-€ÿ³ª´…&Œ–qÎéÁp¤šüJ¡O/(ñ®ojê$x¡Oÿ"{s}15wÜhöÍõÇQ\†*,Ör;)Š ð*,£8®dªªÿÛMÿƒÐšUõ»á8Z¸¸¢ôiÝôÕ{ÙðX~tÜÅc8ªÊnã5ÛýÀàqŠËwbêÛJn£´„˜-|bê|ŠK¯rGÿg +ãXÏqp»áÓ(.‰ßï§N¼›\wW| ű"öÝyD¶qœˆw ¸TÔåÿÔ>=uÕ&ÖãÊÿ©}zú¦Niãê½Ð˜âx3ŠË¾ ÷ÉžúW`¾Îð+).ÝÂ*õþO…·ÍÜ-ô¸‹Ëë ßOqÉó•‹>«æ¦KŠÚ¦òY9Znz¿Ñh¢òY¹ Çí6U6åQ‰—®QéE®þ鎇ËïJ/ò).‹ÈMn½TÏî3ürŠËX¦q9t Ó×fÃí~ÜøFŠ£c¶¦‡šÇüèðþÀ5=)Ž;R“[ÔÜ÷Ð)5ü'ŠË8îí·é_]ˆí÷†ßÎp”÷wNé¢O¼]ÅõÎ)Q\Êû–9£ +ã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®w³ ²j“´gÁ¯¢¸Œ¤¿ø•šÇ‚ó6‹_\Ïpt‰÷6Z©ånþÞBÃ?f8w%&{Ù}¸Ð9&^v%¡¸$¾LÍV…ñºFö˜Ut"µLM—â²Ëëš+ä—›ÝåwöwnïÂð?(.EfÙš2 G ·ekÊ31Ü6†àщ›ŠO'xúoéE§³F†ŸNqÉ´¿Ýü:/âû(.y¾A¯÷ ŽC†/f8•èüŽšÇíE)à ).EfÌnŒ¤Òÿe +¢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#ð¬.þ³Å¥ºx1÷/õ«KØà‡(.“ÌÅÊî×¾:{>M¶"^hâÿ•Ë@¬lÇõúk:V.øfŠc|Ÿ<ý« |ŒãÊö¹€âX‡íº@Ï}&2| ÅåéÍw½§~uqÇÃ8®ù®E—§·ÌQgZSÉ»øp-sŽQ\ +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ö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_±Eë\Ç#ÜŠ-ê\—â’iWl»˜â ðîÇò}§SVïÓgáq ÿ‹â²"väØêÄûQd`Ã?¤¸Œa+½«zÝø`8‘i£:–Z+^¼,UÚÇQÕRkgP\rÝ /×óèì€áWR\2íäŸâzîà‚WÃO£¸´°-â;Õ<áGgÿ[ÄwQOOÞEñ|Å¥À¾ôÑÕjn +,¦¸_ú¨Å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 ¾–â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¡ù×øw GÏ*¹«»ž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ðì¦Ü£¸tÈs†÷U'Þz† ¸¬M4ü]Ž›ÏŠ'S!b">šâÒÂÎœó Åãà›).ÍÄ«ÿ=Hpœ7ü0Åe4Qdó·XH-²ì[ŠK‰ûs~‚ûÈóÎ/Gñtžïp`j›,¯h±qƒ âë(.TÅV굆 Bt oEq™5:ôÍÇjn¯tÁ?£¸dÚc“Ç©¹)oÒ£6|Å%×=Ñÿ=Ï_ý¢ÿŠ#z^óù…ñ*êd*8þ.Åe$UdÑbuâC/º4¡È¢å—‘Tå2[õ¯.Àr÷S\æ¬ZÇWè‹ŒŸô"þ!Ãem"/ùît¢À†ˆ?Ÿ|wÅåÍ_¸r¶š{Ñ嶆¿Æp™öÉ;ø´ºÈ8I»²¾âéLÛù„~U©Ä{à'R\ªÊ…/?”æ~úPgÆc¾í™$1Yøò£—ê¢_×¾ ÇTg¿®ý).uÝ’sè¸yu‰( ´á‡(.y¾j£ö…ñ‚ªJ“g<ÌWmtÅ¥}¸õsà©…•Œ›…ìE!Nß>ƒâÒ¾þç»jnŠ R}þçû ǼÍÎÏ+h¹=Ô‰}•;?Ï¥¸,¤V»ÿFuâÍ°'ªÝ Å%Ï7»[x׉æiŽÝKq)ïÝ?˜£ÿpæ¿ãào0<ºnò©Oô<Ä¢’á«Ž§ont†þÙx~ÅåÕíí5]ÏÝh(´·—¾¼[.Oÿ«Ìh‚ûøÛÿ*sÅ¥¦-¾ôV}¦ °ÞðQ—-j‰&먺.â(.•ÕþÞ¿‚{Ù&Þ.„2üOŠË¸}ïAjø1ì9iß{(Å¥À¾ùÕoúÄû¸¶ÀðÝ—<¿ú£……ñ6І›f½‹Õ-¥¸4‘Ó¦H·ÐO§Í¸=ÏîÊ “X˜6¥ñ£5gÈ2ðÔÑŒ۴ÌïLqÅ2nΗWwáÓ½µ»ZKuâÝèRcÊËìÁº+ÏQóD˜ÀÞÂuWêß¼åR×½°å[5ù¸Èð(.=«&=fƒgî2ý/t0†mÒã5†c {uc·0^¢ Ë_D¾ºq@qyuí?»Bx7H"ÐhûÏúP\ž~áÁïÔ<ˆ.0| Å¥¢ûÇ'ÚWç9Q¨ÃWS\žþÐö‹õÙÆǵƒ†wg8:'3/]Íí11ð7).-ì—o¬æ~~®ûòíÏ).“!³ç¨yÒ‹au`Èlýßn¹lYùjÁ jnÃçÇÁ_¢¸d›WûÂýÔÕ{…oÃNÿ. ÛðâÒ·ù¡c5·“ÌIð3©§K#•³|xÛïÓ¿³we$Áw<=ýÐÇjn/ŒˆøjŠKWiP5·—vÅÁ‹S\^ÝÛO¾T/ ªô„‡ •âò·/ûr®6ñNÒ Ð³Zöå{—™“ÒÓOQ¿:'?®QéégP\©«îm£O¼ƒÐ†ŸMñh+ò ‚£?oøµ—z¾ü½µÙÆfZœÖ)ÿÇÕ —6¯ö_ Ô.æ¢{`øbŠK3În¨~u /j"ÃÙ).Mä¼s¨"〿EqùÛè_]Ïç Š§ó|ç*#×êy4SjøŠËj`ÝEO ²¸r1̓Y⺋ž¥¸Ôus¯Ðs?–ϯ¢¸äº’e+¹½VØGµ’e—S\Þ|ùö»Áíô~†Mbé߹Ѵáû(.-lÅòo«¹=ŸOqùÛû6x¸0^@UØ,º}<Æpl„ß M¼wÝ|¾™âÒ»ø´ÞûêÄ'Ü(&ó§õ–P\FÐÅZVÔg›AÔ ?â2èüÎ6mâí9Œa;¿³áÃŽ™:[ýêb6Þ%ø뗮њѨyþaà -ïÿÊåÕýþî©zD7´þþnŠK×hãøfê"‹Ê»á'36÷MLu^¶Ù&é‡(q¹o.ˆ©Q/°È$ÂhKjÜ“(.ß}W¢µ:ñamÙ•ð(ž~z‡¿ba%´mûA2qÏ.¤úà-).TµA€‡YæMÿÎOO§ùïÇ­cé¹Å%>iìPŠãÈÉ£‡ +㼺ÐÔÓ1=Øþè1ŠK¦ÝsÞruâC?€ï9o%Å¥²j¾»¦šÇ<ÜÜgøIG¸Œ{° ³ËçYq3Âð?çž?(.-ìÖÆû•Ü^ìmQÛÚøoŠãÎÄ+Ç빇ຆßCqI¤#Ãeõßð (.%®oIL¸ÅìBj†í¸iž “—Ñ·äŠKe5ùûaj÷XØð›(.Ù¦æµcµîQ\ŠÌÈákÀÝ,yêJ§ˆÅpô¬ÞéÚSÍãaí®½).‰_Ò³¹–›Œ…¯_Ò³%Å£«÷Ž+Œ—,(ñAů[ÑçxŠK‰«´ôrõ«3C …*-Õ¿yËe4á]#»yÓñ 37Ð6œ”éX!þü5y Gy/™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þÊ°GŽð¶'L®¯çÎÿðFOçºÎU‚ÞjîEÙÆð¾ Çå8·mDï"À6œ <°÷ˆaýý¶ME(.Ãœwj¹Ç¼MΈñ—l„rfÄ ³8ÿžþ]Ì.Z‚/¢¸ ×ÞV/ ™°gó¢›:×ÞNðŽ—ÖNŸx~Å¥¼Ÿ°Kv´º©]™Ïˆ™ßÙp.xuŠËÓÛ,Ôý;»ÕÊßOq)°Wö®¢æ~€(+†× ¸t =³H|t‹Ù g¾e8ö”¾uö…ZîÄ‚(¶Ï[gw£¸t~ô©:ñ¦CŽ·ð£Ï).ƒÐŸçvP'>áăˆw¦¸TÔ%¿¤N¼yïØéTrð«—ÛìÙPÏÍ< ž`8š‰‡sfª¹é=cŠû᜗ŽÎI…“—é‹Ltݤá+(.Ñ´j¬»ŠH¼‹ÙƒëúR\¦ûÎÑRÍ'­gŒhMqùÛ{þx>Û„Êdø0ŠK­üÐCÂÓ{2î«´A…£ƒ†ÿ‡à&^Î\ßQË]/3¿€âR]ô¹ãI5ùcøŠK¿îÕqý(žDpÜÞé£ ¿QòÔ½BXXùèÂo).ÃÿÜáÕ‰½hOiîð(.å½eç+Ô<z²÷Àð>—L[jº…én·¨™ßÙ©JüŠK÷ ÂðÛ´Ün¥ #>†âRÛtjSNŸø ÚgÕ©MÃÑ%xguuâc• ¯Iq9'UäãÃúWg>{ üűúó¯ÔÜT•ˆ_üóõ—>홫‚g·-Ó<&èÏŸ¹ú0ÃÑŸïöš¯çž‡ó2Ý^KP\º…¥úŽQó˜]ÉTªï ǵóÆtVsÓ¼c}Þ˜.—6nàqŸ.ºìràq«). ôÓk©¹½>âu(ŽØû±ª¥#Àgs'rš'üXñÉ—ê¢ÇK¨"ñå—L[ùÄ=ÂNv“ö.­hWùÄ}—÷x‘¿ÕÜNû$À0úUVs{z ^…áhãêŒÆÒFz#tæ…•„sCû^gô{—öýþ¿ª«¹ï"¸®áµ(.õì;/Ðó ê˜Í¾ó"ŠK·zM+âÕ%ó¹KqÉ´g×r'u×xiŠË¼;±:ña­„ºûR\ßg@'ý‡óXÆí3€È6>âYu¾¤­þÕÙ(ìàgSaRŠ©ŸîÚ»¸ðvÇù¸×ÎUsÇC3axG‚£{W}éT}‘ɾW}é󗊺e˧ÕÜž ôÁõ‰·\ÖßÞÕ<ð}Ü©äôîBqˆ »Ò,¼¸ö†¿è²a÷§¸™›÷\¡ä&Ë„>v>ܼ§Å¥‘*÷ vq'³ˆüŸþiÝqKi¹oÖQ\þö–/Ý¡å6†¼´|éNŠK¶izöAuâ}ó>øaŠKž¿é=ì)M=Èœi“æ—ÑRæMï]Gq鵘#“ž“EìýôïÑ«†çR\r]–yjþ?+b=Zva8ŽQ7òƒšÇÂ(WÓ!?Q\úuÕî? +îfÉÓÁ…?PŒâÒ-<¼ÝUóÀ‹n%>¼=¤8VÀ×ïVó¸þÇÀ÷Q\z•M¯{FËíÝ:Ø¢Öôºç)ŽÀÂS¯S'Þ §Ôða DZ‹Ò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»®ž¬åvI uÝ®«£¸üí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,Ø©çö"ótU™ûÌx}â£/†ßËpìx™t'¡éÈÀÙ$>4EÆŽâÖqF5ùA>¯Hqyu×M_¯æq?ºôðºé›).%®E5Y‡õ +ŒŠ\m—¹®EµãíêÚæ+5w«4|Ååo_rrw&ñ¸ätÉÉ—R\ºí6ìÏ.*²ÝÆ°&Õnß—Êêؼ]…ñ‚o^{´ùؼÝÇBêý¹jîFƒPëR\z•õRóÀt‰C𣗧»Oý¦çnûmܧ +Í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-‘áí(Ž#ä»/÷ü¬Ô’ö¾H„Çi¶ûBŠ£K|î15CÏï´ô¼¢—fâêß«yÜÃU\†/g8°W¼KÖßýôµŒM¤ï¤B 'ÁG0݃zË<&“̆W¤¸Ô6‰—»YM¼˜ßÅ£i^Ã{Q\†Ëƒ‹ÔÜwc8ð²<èNqIü7«ë¡¼ oHq)2¼OÔ<ô°]ÇðÏ).OÿáÁwÕ<’XþáÁ…—ª²A‰šúÄXX1¼ÅåéMNÐóÔŠx}ŠK¶©Ý@ö¦®÷΢{à§&yqÏHí§0ó´%ã/蹋ý´†Ï¢¸´ï¹¾Lñø†ËÊH§Ü)½Ž¹‹Ü)WRQÐ+mUri3Z[RégŠ#LÊ}"ñ8‰l8‘i]ÄŸïØo~+ðÔ¤SÆ®‘o·¨%q%S¿ùťȌ-RMÏ£†×¢¸tJo÷žÕòÔÁß|:űuaX5·>?‹âòô=¸RYÅq¶á‹ŽYâý=.Ñ¿:'@eµ¿Ç¥—"S²f/"ÛDÒ’5{SMä%¨o:X—ipÉŸ—¿½ñ®ÑDâãØ(Õx×—§÷»øý‡‹ŽYÞ•â2sÆñ."J¾œâRQךø“š›L‹í:µ&n£¸”÷Šê R¡3s'7uÞˆàØ¢ÖññÎÅÔÜõ¢c•w.Eq©mŽ¶»FÍöˆø‚ã&¯Nßí§ç>‰>â’çsÆ=©ç6Àþ4Ã:à ®O…ŒÈÜ%6cwñi FqéÛ´®ñ›š›¿±:[×ØCq©çŸù¶†–;I7‘Ô3ßÖ¤¸üí›*õQ'ÞÉ@·©R_ŠKeåŽrÕܳ‘ÈÁ}ŠË­Få.î©O|˜ñ»áÄ«3\Zعk§ euxßsì+ÑÙÀ¹k_ ¸´°Mo8žÕ¥‡öwN~ÔĦ7üEqɴクVËD€KN _ÇpL¼|òþ*}âÜBnø' Ç-f_U~Iø¸›À>ê¯*¿Bq©¨+.¥æv%Në,¿ƒâòô uq}âh ´.Eqi g>| ¸—Ý»½¶a ¿â’mr^}BÍMyìQΫSŽ™“Ç‹©y<ˆ¶m<þØ©—6»ª¹ëÇ0ñòÜßÝ(.•ÕŒCß«¹Ý¼€o¡¸|¸×vºúÄ1œym§OqYL\7äi5÷L…áƒO¥¸tÌ& ÈOmEÎtÄÌþ.øLKqùî_œ¤ºicßæ‹“*b;–‚ŽYÜÍfvê­‡Q|›’CNb86t9m¡–Û LØ[Øå´%—ï¾áÔïÕ‰wÂ8"Nl8õ'ŠËw?å·EjîÙkZÀ—R\êù3J_®~ufˆ° g”îMqIüä%wëïè]L^2âò·¯¸¸¼>Û.ÔV\\‰âòê¾¼ë7¢ÈDÁ:¾¼k7Ñø=eNÖóèrÊËÔÇ«Ìžp²›ö1ñB/âï1[Îv0W™p³Ùog¯âòÁ;Q\j›^#Û©¹›p²×H}â —!pÇŸ¼žZnïùÀûOÞ•÷1Žkøp5Qh ]Ãof8¦yÿ.]Iýêœ ŽµÈ¿KW¡xúoïp¸x<«c–@/Þ‘â².ó ÷€šû^´6ñ ÷Åe Vïâo÷Ñ@~ +Å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ÿê¼ +“º=Eq™³ú¡Ù|}âóW~höÅ¥¼ŸÖÄ%²MÑ6NkP\æmΪ{3xv‹ ©~Q #è³êÞNqiãz\w¿š»^F|Åe$µæy¼y/»é>{›‡óï†Ç¹·¿Rsk3 ¾Žáˆ8qÜæ¥ZnÃ×ãüûq›WP׌¾#Û2Ý,7»é{pÉé;qŠ#žU‹ÁJîÙÍ:Ø~z‹ë(.™6ïë]à© ·Ì™Ö^*ìâê½¼¯÷0#©.c*S<¯Fq©ç–>_Ëí¢*ê¥;Q\©µGêï»XÒÚQ{Å¥¼ÿºõ€:ñ®?Dq©.ºx'€§¶¤f\HMm‡u°1²‹W•âòæ§]ˆ¦}–½P‡â’øËöa –Þš˜¹™°I¬„^¶ïV†c%tÒÕÜô¢õßR\ªÊ)Sw‰b>L™ú+ñ!vCµžjøqÌÓn¨vÅåoÿãôżËç(.ã÷Ü[]5O„N>÷).Ó¼_ÿ‘–;æ/Çý°_ÿ Åe,sq õ|˜UXcû;׉I5¼/Å¥ÀßÖ[Íí§ Á¯¦¸Ô´îX®æ©ðùàR\æm^¦åN~ÐEÃW2we–l3@Í®‡¸F%Û b¸lÏû~ÇêWg'ðg(.¯®åãàYnA7ÜžñÀŸ£¸|÷.ŸWs3”Á…]¾Hp,ßw:öã -·ËiÈ´Ç~JqÙG]ï‰vêÄÇ‚V…ê=q.Å¥™xâ ‰,ä¦C>f®*cöJ¦0â½).•ÕGMDâÝì&^ì&p¬ŒþÅÓOïptfRb³èÇl×ÌÁý°Óž¤¸dÚ.Qs{;¿Œâ’ëJ3JÏ}s¥ÎCqi ÖÞ æ‰ÐÃ] kodxˆ‰—e õÎáHééË–0±öï-žÞŠœy8wb~4sÒþ½EÇÅ@Ý&ªùÿÄllÑí~ŠK¦ýfÊ)÷dnøé—ÊjÌÂÅà©° ™›È¸kÄ"¾ŒâR×=x’=7a““Š¬žEe·—]b$õàIS\J\õ»‡¨o÷eÆÁ¯§¸™pâ½Zî$Ì Ôâòá¦]óˆðôÖÄÌ<á:Q]gøc—<¿ášóÕÜ¢¨Þ‰âÒÊ쯑«O|¢Àî¯Q•â’mšÿöŒšÛÈøs—q\…~éì©Ø¥ÙTÔæwv쀷£¸¬MÜü¨æ6˜v|ÃÑ5j6«'•ø8xoâéÑÎÆb³J€g·|ïÙ(lÑôb³JS\ÞüÞöé¹ â~âRÛÔ]Ó@ÍÍÛÃt_Ý5).%.·ï‰Zn›R?ⵎ@£C^™¨N¼Dñ燼òÅÓå½Ãá.— +OoÛÈØ=0ÿ7fO‘ƒ_Cqùîá–Ë•<ðbÃ-WP\ž¾ô÷zn+Kð›).Ó}Eo'^]ˆÐ¾†d8®P¿þô_Àí00‹lc·màšQÃ¥¸TÔã†ü¨æq?Ú,4nÈÏ ÇÄKÛ.Vs»12ïAqi&¶ž}XËMEŸßzö1ŠË‚Ú¬ò5ô¨z£šûntÕfPõ†cÊëú½5ôÜOº¯Mqé]4=$p/|/S`aó;'Ý+døRŠË^£ýn×r{¥2‘öËpœDþvÞãêÄ›¡:ú´ßΛÂpôi+\üš:ñ1/À0°ÂÅoQ\Êû¬Ÿ«¹ãÅ0w1«ÃŠKâ?L>­ÿp¶¨>•àØš˜W¶Åƒú&qs_Ù1ËyuoR_dÂO¯{»>׎åû¶Í¯V¿:7ô½móþ—Äï¿ú$5÷¢ ê†7`82í_Åeƒœ—Þ¢–qqÁÞ\oF‘ ðSÔÜŽ"¥¶9kï\p7« 3Þÿn”2ü=ŠKeµá¾ÇµÜnÈÅ¡ ÷=Åpœ“ªÖû‚c–ØðÛ(.­L·Ï‚§uf Îc¸½xÚŸNq©ëÞ*û…šûÑrÿ¤¸tÌŽ Û®æöÚ‚|'Å1Ñzç¯úĸøÏðߎ€ï#r —Úª”Nj┾?n +Å¥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••àfÌJÞñ„š›±#%ï˜BqÄx¹ÙWs×ÁZ¤á Š£‘zñ Áqѧᇎ]>K¼º(HËOï¦8âYµþJÍÿg·ÏèÖ뉿»}ò˜Ã¼:¬E6>ð&Å¥[Þ±—*2?@qéÏ/½ím=Në>Ÿâ’i»Ã·T8¬,:¥I»ùqº;‹âòôÏWsß‹K#exÅ%Ï×ÉyNÍãNtÛEœ—ŽÙгúÜA‰zV?‚»Ø,ôHS_̓' Q\z•KŸy™ùp8à¶ô™×ŽÎÉOÐòÔeÖ ðj Ç¡ÎÍÝwéyÛÜ}7Å¥k´í‰ÚêWg;(Iðº G‘Ù×ø }uá…˜1Û×x.Ãqä¤Ü=ª¹Áh¤ÊݳŸâ2s’{Jý«3ÃtJOQç:˱¯òÄ£/è«‹è~Ã_¢¸t‰^µ@Ÿø Ú’ÚðªÅ ÇnŸÆënÒ'>ppƒ[ãu·Q\¦}:<9VÍ×ÏçwQ\z?® õU¥“îáI‚Gáï*¾•^ÂöôꙆBöwN"ÎIÅ·¦R\©;÷«yày˜x¸óÅ%ÓV¼£Œ>ñ~€NiÅ;ÊQ\>\lÉkjnþ/æ*cK^§¸äº3V•Us;çP\žþÝÜWÕÜü—ñ7Žªò÷—îÔ8{Í)øx†#ªR…K7 +÷œ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œ+<È*ŸºäÔ‘ž•áË).®ë'Æÿ±eÅþÎr À=ŠËÓ/ûä~uâmÌÆ|Å¥…_ýº «tö1ñ3¥†çP\rݘ.³ +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­ œ>‚á¸0béøÚúç ¶áõ(.S^Ën­¯çž}•ËnmHq©.Êκ^xÜÉn(³b±=¯ì¬)Ž@£ÝV€§‚°e:va“ˆnö1üc†c—sè$p/Kî¦:åàõ).oþƒäuj1œPû 9œâˆª´æW}â£}V†ÿNq)°§}~HÍcŽDüÅ%Ûl8ñá €$ãæ@û»Tp ð•—ö„UŸ§†À™#öÒÁhü~ª5—öìS.Wó˜Ƕ̳O¹‚âRÞ߸SÍçe ßÅp$þ›Õ«¹ ¢î‚ë?œå¸;oß zžǬ辙—FªâS'«¹ëÆУ®øTkŠËìA…þh “Nv“I{Ó.ˆ©ÐÿŠ£®›ú¾šÛ»"¾„àè”v¼ì>\2uœ6S€ËÍ‹Ãláeý^ÉkùÁçÕ<}wÃõ‰·\ +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«ž;Ñ|úŠ_(.ÝÂo»ÖUsÓ£Å(òÛ® È`¤ÃßÞ žÕr?uù.€3ü.†#v_É ×k¹“°wó€ßHql9ü°:ñv.ÚŒâRÓ6›ýžšù jÍf/d8Æqm¹Gÿêò7\´å>ŠK‰+;ìRuâ]›mÁ{Q\J\«›ô‰&^ ÿžâ².óéіć‹vïzÔ¡¸¬AWiè3mtôÀðÅ%ÓŽèÝGxÝ”—ù½†Ì@q™9i~K-p7«É{ ™ `Eó[êP\ž>aÔb5O]M¾œâR×ËKè–´ìcl ^šâÒ5þW$ÞËjÊË^½gŠLÄËS\Ê{ÛFÝÕ<ˆ6~ťȔôd=c²:`¸Kq`¿ÐeJ_LžÌfQÉ^?ç ¢”á‹Žèg¶Á00½A.s¶±ýyÃ/ ¸Ô6µæ KœÚ0“Å«³‹÷ÑôZsšP\Ú÷†/tWóÀq0ŠløBOŠËÓì-FpD +5¼$ñ¤µ¶Ýwjîº „ˆYÛî†ãTæÅ•¨¹Ýž‚¥¸´°Uçܪu.b°~;ÃQâ–îÞ!<–Ýa{Mà<†ÿÆpdÚ +ã*i¹½)ŸW§¸t K–¡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ñ!Ž~ÃÇìÕyeˆÄG·¿:¯<Å%Ûìýì>ñù»÷÷~v”âòôcËÿ&^]Ò8ñtÃ¥ª¼¶Ki=7ï./Kq)2ußE¥Ô 0‹ŠÚsLS܆7`8"»*Tr»32ð"~ +ÅÑÂÆ^`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Ÿ—Ú —ñªû;»’™œáØOû`»Cjnÿé?ؾÃQdNžò¼šÛÙ‡$øL†ãé/}~‰š›ÔcüKŸ_JpèÖçPó0ŒöÓ®ÏÕ8Ëåoß?ø5Ù;à?Q\æ¨GH(/µE-‹"cŠKˆ)/ÃQ\Ú<¶°0þÏ…TÏnD=oøRŠKâÇäÎÖ'Þ.áèÓÞ~œ¬ˆy1'»naÌêD‰»ý¸_ŽY£ç»OÏêŠUËã~ùÿùî3Ž…Ô=‡O‡ˆÉ¸´a~çD}ïc8ú6{Îÿ^Éc®]—qÀ¢¸¼ù)£:‰÷P]LÕ…â2G}ø¢Ne~§Ãq*³KÿÁ³ÛŠlçæCÌU~ÅåÍ¿zW5ODgB oFqþ¯˜q‘ž›6ÎïNqIüêÉ]ô<Š(ex7ŠËla¢ûmćK |}¢ûh†c {ÿ»Oƒ§§36qϱÅ|*Å¥²ÚòÞ¼ÂxA‰w=¡ â’ço.›¼t`¢ÌTÂØ(Vgó> G¦­±ÿb‚{˜·©±¿Á}òªTÿ3ðÔF©ÌM¤yŒ‡€“†IqM, ¿ÑòÔôü[ŠË««P¢¾š§Bƒ7f8ª‹ºêß¼]À—§×]s&Ñi;oë©N¼ëF—]vÞvÅö°Ü/ú`Kªá;).}Új-§Æ ¨¬¦´ØÍûÿ8»ð­¦õüT*ÍšëÓHó =>CI¨8šˆ4™ç‘’ ™iâ4Š¢4K(•dª*QhD$ 2•þk=ÏýÞ¿ë{þž}¿Ï¹œs®ïõ¼¾{ö^{÷ºW¥&SŽE¥î¤…gÂóbtÒ™ê" ~Á=Œ*×QÉÍbÝð‹).õüãã0o“ ׉±¤eƒÄ|Õñø¸ý—êbßðÅZnbaû¾áK)./î–ý3Ô< pÈ©ás(.WZ¶¢úÑ™"ŒRCËV¡¸ÜüìJ…õÎZØÙ•N¥¸Üüß ^Ò?º0…“ûþnð +ÅüÿN95O†8žÆpõ‹Ëp¹yÿ²uà™xm$¢,èþe).ÕÅáÍ Ô<ù¸‹Í‹(.7_¬„l£öc¦„ò³£ÿ4øu G¡-þÅ«G.nÃ_§x +½‹þÿßFÊü.‘¿˜Xk]5ŠË×|UwõÍ'äl4¼'Ååêó ÔÜü +«BókÉpôç·üÙBÍ~´½åϳ). ©õ–¶f +-ŽÖ­·ô†cuÛÛ®wc…çùöà=mo»ŽáÈß¿Ê 5·ãoéœô¯ZáÏ»óºþjî8)™£6|Åe$5fw5·ùy"~!Åeø¿òÞöú›÷£3VVÞ{1Å¥®+wMJϽЉøY Ǧ¼&×êyßóšÜHq©¬ªýQ„ød’èÏWû£8ÅåêuW"n9 ?•à6°w=1ŠødD:u=1–âró}:ž®çnÔ9éÓ±Å垥¥þŨi ?‡áˆ»ÿüÄ‹ ½ˆßEqia§ä½ª¿ùh»áó(.ÅfÁÓ¥ôÜIy/Cqì“ß–xtÈKl¸¾ž·ä¦M%xà?6ƒâ¸úŒæ Ý ¢ž¢X£M©Ç˜Ê +_ܦÔ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êý )ž_Bq©ç«,@p„.>˜â2õqw)xfI+Wð@æ2n”&å¯Á£D£3¾èÿoüÿL6™£´“XÖ™ñÅ@ŠË¼ÍŽ¿hoÞM!'vŒ8LqäµÿTÿèB…6¯ýzŠK]×reBÍSöÃOS³sf蹃ù:Ãg3‰ Þúà*õ‹sBñ6o}p-ÃqõÕ+Vª¹üƒBq™îkvûÂýXÉ6m:ÒdMó6»ýÅåƒmv×_ ÇôfwŸD]]©K‡|¨æ /‰ÌB—YMq,+?AËmE‰CR–•–âróßO¯¾ù´ƒ} ŠáØÔ9ù•Yà±ÇÉ\ƶO~å5ŠË|à°¦jnFŽÖaÅeòaý£Õõ7ïF':­´6Å¥~ú¦‡…Nœ£uíï2ÙyÀ£¸46UróGzÑ ù†Í%Ž·ŽóîZ¡¾ùÐ.'‚Ìptxî x¬£yìï\3f†¡¸ômõ{RÍ?‰d\‡úM¤¸”º_ï­ ¿y ^…â8ÙgÄX5O„Ñ2îðúG—ˆRu¬Üµ1qó8ÄÜðf —‰—ö5'4fþkòÁþαi™À›R\^ÜYcK‚ÇZnŒÁËP\Ýݶ«yÒ<ä4øN†£k4L6qkx*ŒN96¦Á£±9³¦©y:ôjάY²iuï´BËí$3†ÿÝ;}HqieÜv«š{>‚ Hq9(äXÃzâê†ÿLq)´Å硶IÄÚÈl¹c4Q|Þ™—^e•m—깩)ðn—«ÏhU^ËMß"Js:£U%ŠK§tÂIªyfv üoŠK™oÕà=÷=„a·jКâRêÚœ^QÉ6ñÞ{›Ó«R\þöUýµÅ&‘9ÊïIq©ëÊïE‡<k»å  ä ¯Kq阹%æky¦{_HqiaëŸS@ÍmŒ˜ ~ +Åea¥óí[Á½¸Üó¬Iu¾ýŠË“ß<ñy5‚i‘6OœLqéϧ?®¿zÂA0°á#).•Õ⣪¹ã!KªáQ\zÔy]ª¹éš`×åLŠËäCƒñÓô< ×`üLŠKUÙwF'57í+‚FúÎèLqytÛÎ-®/´.öE^ŠâòÅÝ}‡׉u@Œù“öÒß}ÇŠKùá7/j¹ýË1Áþá7S)._Üá/ßTs;Ëí€/¤¸›Y<¥tFR†?Cq)óoÍÛ®æ ßÁ²Î[óvP<[lÚý^æ\án6æ07÷¼(®Ò𗹋òƒ×)¹k;'˜1+?ø ŠKþúéÔ7o§}ÒàO{ÀÛßx%ʼ+UHfYÅ4SøBŠK¯²ùþ÷Õ<íGS^Í÷Dq„i]ÛžàÑ1âS¯íHp,¤v˜ïTUsÓJy¯NqÇÕ~g,õèÒàO¥®ãœA}ÔÜ4Qˆ!Ÿ3¨Ñ9°{½oÀ3S¹RFØËØŽ²iÕÛÉp\ýºß_Vs/ÊÝgøt‚Gë2ýÖèoÞ¢sû­ÙCqé]ôwN¨¹=F®Þß-Dq¹úôíoê¹bü>}û"†ã´Ê'ž­æA´ÙÇðs).•ÕkçW n>:äôµó+Q\ú´?Þušš»ùƒ‘ï*Gqé”~Ü¥‰ðL@lîiûŘBÜa8ö +µ{c²ž‡i …Ú½1•áè—ž=‰â!ø‹—ÕZK¾VrÏ.ìà4êZK¶Q\Ú÷‡+f8žüÕOe8Λ(Ôi¾ž»Ñv¡N ).{ã*ûÀ3iNsNû˜ßÙ…ÜüÅåÑ­^ÜUÍm’×$xw‚ã0ëŽEÎWó>ò˜¾‚âÒ³*[{’–;IÛç ™âÒ5z¨xQ5OùX1¼8Ã¥oÓîøy5„û™ã&s.*¹6gD€À‰ãç êº9—Üq"Þƒâ2ÚÝd—’›ö-ð±cew“ï).í{ïŽ À3©r7‘™Ý>IíÝq1ÑT¹ÒE}´Ü±G¬†àý(.µÍkg5Òsù* oJqyòmïj©ç>ʼáç0eþÊ…)‚o¦¸,¤ºG{ßAqi¤Î¹ÙUó„ã X蜛ŠË`Ä©}'x¼€X{™iN ¿‡â2©â|¦æ)Ç•&Òðõ G +÷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òüËÕ…¹‹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îú¨ë ŸMq uòÕÜŽ–“à †Ë£ëØhÝÍÄÍ»ÈCÞh]_†#«Rµ×$ÙKÆ;,Ã\ÆîÎóÁ—R\¾¸‹j|sâ%iÓe ÙE5~d8–6>}·¼–ÛÃ2P]|úneŠ#ÁìͽÕÜTÓ˜`Ÿsó-—wln}5·'‘¥À<šî;Ñ}‰úÅ¥¼”ñå—îAù!{ôÅ&L ü¾üï).m\ — O9±‘íeìü*ŠK¡íק”–›ÚC3ѯOY†c¶ðé!uÕÜdÕð† GzÛa·_¨ç!2ÄÞ‘âØ'u;–u2¡ ¹ÃuÌïìqÒ.ø~ŠËXf×{ãµÜÚ(~~×{OSñ´“¨oÞö O;i1Åe VøN̘ÅL{èÙ@dügøé—ªòÅóƨ¹äŽø8‚û˜æ}±m7æê¨i_lÛ“âRUÖ?çz=7lüfŠKuñNSLûdÐc<€N©áC).Åf\é²ÜÏ,aç^Lô¤E2ü'ŠË{´`5íÖðî—ÁȹûóÀÝ8G.fxèçó—FªÍªÔ<á§ýˆ¯b¸ Û~¸¾š§DyÞˆâRêÊŒö´Ü|2)dA/3:IqiãÊçézjž¿Úp}™ÏßÝaÁIµˆGb0²à¤3(._Üá‰+õ…ÖO£¦=<ñŠËÕvY¬æŽ‡CN _Êp¬Œµ…à>úuEGm§¸ŒãŠnï æ^´éÃð‹Ž›/sic¢Ø$¨¤Ì¥MŽ-fåû¼¯o¤ÌÓK‚M¤­l³¼ùG¾úÑÑÄ‹á Šã¨ÍÞÙÊ*t²aZ9§÷m~;9þÅ¥C~_ãžjžt£¤L÷5¾’âRÏ?øÁ(ðX©ÿìïlÞÃ$øX†cwÞa-áÙ£us½8û;3úGtßa]ŠcŠûЭà±&^ìïì0.>€âÒ-ìüÆh5Ï?[Çðñ—¿}Ü¥Ÿª¹ÝCž_ÇpLïÿ¸ûT5÷Gv"^’âRæÇ]]VËm¢Q”ùqWW`8Ž«ødÙ›jnºãŒüdÙ"†cKé†ooP?º„é–â¸Éoo¦¸ À‹÷¾K_lÌà(®ÞCŽÍ}ÍÞ ÿd|œ™hø&ŠKE]®Ë1á™ÀÈ<;—'_(.ŸÌg…pó~¬)/Ë“aìg…¶R\¡‡n¸AËmÔ0æiÝЋáèÛÜD}ói»±Ü¡¸›úݧæ '´þ Á£Zw/|Uýè\ûe ƒâróÕ×}îÅI“¹L˜ +p4ϺO).µûÕl5½d>•â8žæµ©Â³‡Ûææí•â‹ëðÚtŠcÚç±¹jnOêôÀ_§¸t‰ß/}¦š¦oqâÒ@yøV57BD6~yxÅq†Z¥QÄ£K!¹s¥1Ô“G0p£áJîÛ}ÌnÄg86´*± +²äŠKþõoõ{f ~ŒâòÞÞ\]Íí>æütŠË÷^ñšÏÔÜ ¼|¾á˜æ}éÅ;ô…ÖEþ:ÃS\z•kj÷Rs›LËïKq©¨×õxOÿèœèðúu=> ¸Ì×¹·OÒ3†M¿Èpɶѱ}!‡xq˜52< ¸ÌŒj\Ex6:÷pÀTUÓ¬F5®Nq©¬^H~©æ6¥t|3Ã1KÜdÁÛJžÙd†DdM,c8zV+~ý<Öqҙ߄8±ÑðýÇ0ðî_ôÜCgøaŠKuqþäMjnW°“àÛ b,óËmk¹“´áJÂû`8N)}|QáÙPä\á:ö }ÃûQ\VÄŽ¬ÅŒY¼ÀHû»„‚§Á‹<…á@ýYƒõ<ôWYÖ= G\å‹ ‚ÇJLd6u¾¸ðÃñÉTØÖAËt€]؆_Lqiß77Ÿ®¾yÏ‹–ó67ŸCq™l<üÙ5w£Äƒ†¢¸|°}ÇzjîѶʾc“ Ç0°ò…gÂób …Ìeì¼3Å¥ªÜZ¬”–ÿcc£áåŽÉ‡¼µkÁ3i‘r/¬Ø¤LQu‘·ösŠãðëžÔr'„n¾n"ÅeÞæÇÕÔ<D;Ô~xfÒ)w3‘2•Î0¼ÃñÞ_èÖ_Ím©‹ø@ŠKÏêë1ÍÔ<0­Iܧ¸4‘_ö«žÛ3•Áÿ ¸T•[Þ( t^WßòFaŠËռ߅¹y/âÝ)._\‰?±/–ý]N€_Eq¹ú¸2ÅÔÜvŠðÒ—îÁ‰Õú›ÏoaoL¬¥¸´ïÛ7VWó¤Ýr^‹â2.¹æ'5O…i$U.¹æÃosúokÔÜw}©¬ ÿœâÒ¯+¿ +#©xÁÀa& ZѼåWm¥¸\}ıjî{HÖax!ŠK‡ÜoŸ7£}p9ðíï‚ñu†ŸAq™)mÞì!5÷ƒ(ê£y³G 8èY-? <Þ ÔFõ¸Ñ·¼åçP\êºLVs7H!häÅS(.µÍK»fj¹“ð‘:Àð× žÄTçÔ'ÔÎV£ÃmŸhCq¹ùYe'ªï{XƒžUöYŠËšT×G«o>í¥°Ýõ‘%OK™ï0óK™|È©œ»ªÌèâoŸùeiŠKeõêú1öE¾ºþIŠKEýÑVŸáùhk‚º:†—ïUr»«†Ïp„e&· xÞŠâ2üoõÙ¹Zn‹@ìA«ÏÚR\b?œÔ<ÖæýÌe¬MÞŒáH›àŒºAÍíôC¼ÑκÆYÑ+y~æ2.*+Ã'P\ž|ó·©yÒÅ”—áwèy~¶Ìßþ¬æ©(1‘Ꭳ:¨¶KÍí~Øø>†KªN§Ž’ùy7{Äj nc÷e]¦Ó©£ 0óuuîÆã¶C Y‡ÆRÛëæ=¬æž)uøPŠK}ÊÞƒÄÍûØVyÊÞ_)._Ü›­>ž=,wuáÛ@h Àßlµšá˜úø¼é=jî›/.âP\©2{ +ê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é[-löØÁÜÒÀ Cdjß·àÉ ÇêÀ’²3ÔÜÆÛ„à³).ûÎ×Jé¹ÿ^–áè]̹’š;¶ª‘ਨ;ìíR^Í“QF)Ã+1¥JܶD_l|œ lør†#‰zÍÍã„gvrN6Ú€‘¨™0ü)†ãL¥F·–¦®î€—£¸´°nó(‚‡Ôß.ÝÂàŒç”<(…lÁ/ÜEç¤ï”)zn~˜ŸApÍĺ ´/.°MþöuT¢¸ …Š-üHÏÍ…àk(ž­*;U:¥(õä}ð—!p)o¸o‚=̤H¯extäâÛ´ÜÍle?Lqé˜]uï!õÍ'Ý(]ÆU÷e8öIíë’Pß¼]ÚðÁÓ—f¢@Éýê›7à â¿PÛ瞤¾y7L |™£…(ŽÎÉà„Ç;R9s™{Ä ßOpìë°¹Ù`%Oس*£µf÷P\è3k·wãr3@º3kŸKqŒe +Î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ÚóãåŒ:=Ž/¯Ð¿¸Û¬ ÿˆârów=>D}óI§Qþ ÅåÅ%ÏAÜE6 6wEÌí‚·¢¸Úô²†ànœTŸö2é ZLL/kÊð(ËJÞ~-7õ9fJ ?Dq©ëº~r„à)Ìwýä7ŠK—¸Ê}Õ.•¿¬SåÛ(.MäʳÞWß¼-¬þ!úðõ¤ŽjîzÑùï_Oº˜âÒ5ªþÒµúBë'Èß@p$mè8íöÞL¡Å±i·÷£Ê<ÒY=<^@¬½L”œÇð:—«¿7 +_\ÌÐ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žs²ÑüÎæ« ÁRñóóC!»,k·=bÕC>jÃQ\©…«ioÞ¼6”yÃ¥¸ôë*}R Ü‹$f.cnUe¥OêP±®Ws/Ñ%ž¾áfŠKmól£‹ÕÜ÷Dû<Û¨ Å¥Þ]ú5OF§×~ñúP¿*úGeA7¼Åe8Pø9™=ð²)s2ö$ï$VÄ +?w”âRU–[ö3ÁL¼”[ÆÜçл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¨æ®D›yÓG)Ž‰ÖËßÒòLºMümŠK31÷ý7Õ7XD6|Åå‹[ºãb5OzQºŒ¥;ºP\n~ûýMÕÜ·3p‡âR]üyˇúGgFÿ_IðAbů~AÏ=l§5üeŠK÷`UÍGˆG‡3ÇQ\Æï«Òˆ›÷£›OW¦¸TÔ ?–9j?f¢ÑÌyQþù†_Mqùâ];Œà”2|$Ã1WùEÙ¿˜›÷"~‚âRU^Üqxf3oÎp{M¤áQ*¦æ sñ$xiŠK§töâãǯíg¿}2Åeò¡ÖÆžjžŽJ~Åe–¸Ê·ïèy´ÍÊp}±±\©e-h¹ë¸ØnøbŠK3Qëɦjî»Q>êZOºzî98#µMñwÕ²Ú¯‹{dµ?JǬý;§ ïðzÓa‰Fß9}7ÃÕ¹eçojnº¥Ù²ó/ŠK§ôú%Ϫy*ÿÜÀë—¼@q)ó#6.Ñr»©ƒ‘ß¡¸Ôu‡VÒ?:/DÏjâЪ—®ÑÜc«y"ˆVç?‰áM|ëýöA¿õ~'ŠK [ä±*úOÆüw¼ÃqâCñ®Ósmœá7R\©TƒóôŸŒç!s`ªA[ŠË“¿³T!=÷ÑH^„ârõ_¾P2®ã…ù¼ÑeåâÇ÷bmt2<0³üWŠK3ÑëÚ{Õ<ô£‰Ö^×ÞÏpOóøÕÜwpL‰á—Q\*« Š>¡æ®Î‰á£).uÝë¯Öß|˜Ä†Ö×_-Jqùd‡ú­Œá·R\Z™3†f•lÐF2ÖØ.„FÄœ1ô.ŠcUèåƒ*n—ÒèW~ùÅq,ÑÕ[ÁÝ8[2—ñCDón¿z;Å¥{°ëÉßÕîg–ór…"ÛߥL¡Å®AŸ1[JO[°CÍ“ëG|7Åå{ïñI5ðXðöw^”âÕðÚw£™G\,ò€úæÓ~”íÓ)ÜC"²Ó¾]§æ)? +8íÛ—ªrO¡jnš)'â­(.àOíõ£þæCWº…† ¸4Ð3 ?f¦>rwN2‰‘EmÆ‚f Gj 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 ;àËn GÄË“]G¨¹ëD'><Ùõ ŠK©{ôñâz¤±wàÑÇK3;Ôªœó%ÑǬÊ9›õ<Äùï—:<æ‚ZÒ.eJ±1|0ÃñÅ™]@ÍCßÇBj‘Ù§03'ÍËÞ'<ksŸý]æ¼Ið‡(.ŸÌµ#kªyÒ|°.øé—›ßùÎ5·'¼úà»).mÜø¾ž»QE=~D‚âÒ!?z©þÅ¥<„¨þ(ÅåêUˆb“FýwPâ2Š¬îw!8à†wc86°w¹}:x¬-föwNà£Ðv¹}Å¥ºh8é2‚GÇÏ5œÔâÒÊLoÜE̓(ã„á]).Ãí÷´Qó„Ís +~!Å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ËâÒ¯»mß¹ZnšçèÐÃÛöµe8ryõ+»_Í/¥~e¡¸,".×^óviÞ‘àQ´ÏØ]ß«¹ï%½ˆÿHqY›¨:bšºØ$£lZ†Ï¦¸´2‰Cé_\˜D ›84œáˆ§}fßv57½g,ã>³o'Å¥‘úîMÙ¡æf·ÛÄá6¾/ây—Fêí].xfª3weÚ©Äœ¼½+¤¸›—5PsÛ§õÀQ\®þÔ›‡ô<:µÐðߎÔ[ƒÑjžôqT‡áã).ï}^%jžr¢³6æÕYFq©m.¾bªžçG°_|Å ŠËö—‡µÜF”bâå—G).½‹ë¶¾¨æ®=öüeŠK¡m·g"¸k»› —™RÃ'Q\æ.&_ý¼š‡~´ +<ùêÉ—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ÏÇ(.í{ƒ…#”âÒ¯Û;ê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=1 4¼Å¥?_üÚ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Î3¼-ų-l»c²+ÓüŸcmx±Ü Häo7üŠãà€¿«yÊÇ(Òðã—2¿sù•ú›2ÿ~Á±ˆÜ¡ô½ µÜŒþ£SNJßÛ”â2ktêtõÍÛ‰A|űÝæéD±‰ö +µ}zÅñ²s³ž‡!΃þjç6ŠK ûõüÕ/Î ¢eܯ篢¸4R¿ }VÍmSî?Oq™«,8ê þƒÍŸ«,8êW†£WYpü÷ÁTÔEÒ®þƒu£dÚEÒÑ9pÂSé¹]Þ×—:Ëq\ÅôçãWag§ØàÓ)Ž0ìV¥”™m•±^\è§0_LIP\©]éCj„i Fv¥e8b mÞCÍíîÿˆ_Aq)´yîkúGçF tžû&Áq8N‡½/¦„g·×åJf—Êßð²÷Åæ—ŠúĤ5౶Ùßå dø§—­í/éªæž…iµ¿¤'Å¥¶©½d¥šû’u®t–K3Qó¤óÔÜT˜æ­yR[ŠËß¾|{=ÏÏO»|{1ŠKºÀ›Ïêy˜Äµo¾ÀpÈM]ó‘š›.1&§®YEqé˜U(€øºx›}ìïìpøù—‰Ö‹N®Dpt ¯FqYÞ_ç:†#ÛÆþ:½(.Tùíå­„–ß^™áè”>x¬>Åà).ï½K·À3Ë:¹VXnI”º.ÝöS\æ.Ÿš§Ã$Þû}× 86:|^ËmÒÌÓî/øÅåê«ç¬%x”„mõœuOcêcÒÐjnÏêðÀ§¸ÚaKTsßnÛ„â2~¯=f0Á£ÅÄÚcîe8ú67Î<=ËÝìQ\¹—´ÒöÜ>T•7άÇp´qOlxEσR¼>±aÅ¥ÌO=k¸k’Ù^&H {0õ¬Ç).™FŠ•ùIÍ=7)ëq† ¸TV'KB* Âhqáä‡).ýùæ+§ªyʼ_ìÂ^9ƒâRY5®q£š›ª +µ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 ¸üí³»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øù|Å¥²zåójn°¼8Ã;Q\bê^¥æAþ.ìú…×R\¾÷†ïnÒs‡þ5Å¥w±íì‡ÕÜôl ¼íl}¡µ+bÁ‚G§× Q\¦}ÊÝÄ[ÒríÆF¬I¾”áX“{ÝzžÀëØëŽ3ò? +4×r×î>ðÁ[Q\ÞûžÛ©¹âø9Ãÿ¦¸ŒaûÜ=PÍ} ´áƒ)Žì±œÆJƒfÃãÌP(ˆøhŠËŒÙÅK¤“›=,gxž›Ùôˆ—‹/Aq霴©™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á÷ž—Ùâ–âòÁ>=w¤–;é{B ÿ/Á£ ryc=÷H›76 ¸4ÅZ,÷â>:ßKb5°X‹÷(.îOG"½LðŒªÒXSÙ¸àƒ).½‹½E§èyB<íÞ¢3Ž@©T­àn¬©Nó;'?Ö(UëÅ僭ýZ 5w£0lÃÏf8–2*r‰žûÈSjxWŠcgâÏW«¹ç¥1Å}êÏ×S\Ú÷¡Õ›ëyMó­~ÃåõsÇwô<Ä:¬á+(.ŸLÓ啕}x!ø]—XñYÿUóОÆ>–âOûnï~jn7"ÞŸáØÀþèk çeŽŸËŠla~~Š×G_+Nq¤ò:QÉ3ÿaÃK¡Ï1“%V6&8’¨~&ÅåƒÝvÍ{ Ç.ìm×|@qiany‹àѳ†[Þ¦¸tJOÅSà펙“ëôTs{r@į¤8‰ßˆ>mvÛEÎ`!Óö(oðŽ©Îëÿ¼CÍSQzÃ3ÇQ}7w½ž»8Ýð/).ußÕÕ< /±áµ).W¿`W}-· ”p÷»šP\ZØÎ9¦æ®ë æäsþ¦¸ô¬^íÕGσ(ùÕ^ýŽ¸‹êÏ^¬æv ; ~ ãSÌ–>¦æ~ŽIY:ŒâÒÂ>1Tÿè‚üSžz;ÅåÅ5yŸLæ¸X “ruÃßb8æi«—ÁH*³­2Æ'c¿·hïõ2wS\FRþ;PÏó3Àø/qóa…výð3ÕܶîR\è­§PsÏì‘áO0{§'«yšÝ•èDgevz2âRlÕÿ–àÔÕßCq ºøé•O€¯¡8âë +žAð$ä +¬Oq©iSwNÐsÙ6 †àB•Œ +žY\È]Y%ì‘ÊA1‚â2?ß`ý«ZžÙ¼ñ7Žùº1˶¨¹¤??fÙ7 —)îÇOºTÍí¶Êü2Š#ŸU“Âcn1óžDùç·6-@q™=(½û%OfB #þ)Å¥{ïþ% Ƕ‹÷î‡ârõ_ë­"¸ïE| Ã1[8¬ÅÈkñ%ÃÑÆÍ\„ɇìQ\qxD‡aÍ\t/Åe0r¢VZÍÓ"Z ?›âÒH üþb=] …~ß…âRh‡œ¤å6pÅfȉ»(.íûk­RsS[É'cøP†cŠ»ä»À½xKØ™´Lˆ³*ùÇ^ŠKïb~znªÊ$ø) —ÎIÇ"ªy"ˆÃ*Òi1Å‘Ó©}+-·AÈ_·­ýyG¯ò Œe²G°å^Â6—±}wðÁ—GWmÖP%O™\B¾wÃGP\¾÷‡o+ž Ïy,‘g€óQê¾­"ÃQêùFÍà µ†GvR\žüÏ75Tsóêp2ïÏ7IqytO,‘ ð^&:ÆâBÚ4©Ä,©Nqyï›»OÓòLî¦øLŠK‡¼[A?ËýLPhîÖÏôŒ°*Ô­`ŠáXÚTì$‚û~Ä Q§œœõ°ŽÛTÑA!†¥¸, ŸñáGÌÍ_EqéY¥ïI¨o>iƪ!xšâRlʽ2Üšh.“ˆv¬>˜âè­¿º=0"~'Å¥wqô¾)jžò£“}ŽÞ7âòâŠÎ-¯æi'X£¢s+3ÁÿµèOÜ<ò~ÃݤÖSZnƒ¦Õ¤Ö3—›÷ŽöÓ?:/D„›wTÿèÒv^3ûÉüpÆçà™Ô9› s/D”—á)Žd›ËoPóD€#Z ¿IÏÃhsߎº3ÕÜ÷t‰wÔÃpœðÒ¦“ähõcŽcc]¬E¾…âòâî8ãf5÷C'Ÿ÷¥¸Œ ‡l½NÍìp1Ëo¢¸Ô´%v?¡æn-i•Ø=šârõŠ•f7`9¯b¥y—›ÿüš• w#þ Ååoßòò"‚G›¼¶¼¼œâ8È{ÌB‚;8Ålï˜Å ÇùqUìÕ'ŒUü@qi&ª/÷¨OÆ).{»ô…ÖÞ|ÄßdxÔ-ün x¼ƒìe‚@Æ°†¦¸¬Çµ¨3LË]óÅ`A­E‘G†Ø¡ªoÞ A‘­÷ÐGŽð>Ó/Qó´‹ PûQ\þÐóY ×ÿí–K÷ ÄËõ/.Œ¶”–x9â2–©xö•jn“¸¥À¯a8n¾ÉÝÕÜó10ürŠK3‘ž8¸y$&2|ñ2Òö¥eúbã#¯‘áïP\†ƒ·6Tß|„¼µ ñ/ò¾– õÜ …Rào3Ó>ãj¿ æv³‘þ2Åe,3§þ}± “XDžS9Åå{ëë«ôÅÆÃѺ†_Gq¹úá§Ue‰ø©—öjuôÕ…­ÿQ­>Åeø_¬á—ú&ÒÅXÆðÍ—Ùƒ²õ/ÎÅBjÙzƒŽz>ïÉž²3q–ó2—Ic8÷d1†£{Ðåºúà™ÅÄ\Óûö2vŠg"_טáXH­(Õ…†§|œvaø4ŠËXfýú9Zn7÷aâeýú¹—÷Ûs³Õ7ÿ Ðßž{•âRæ.œBÜáh Ï>ñ-x¬í´–‡VÀ ßEqùÛ«ýÙDÍm²Í¼Åe~þx½ºÂ½XK™öwÿ˜·9^¯!Å¥ÔÕzö5‚ûXH­õì›—7õ©jž ¢zêS³).]£f|¨æ)ùi _Eq¹ùUÎa^êºUÎ¥¸4‘yuGëoÞObî"¯î8ŠË|Ç€[Á3›:s¥Ã²¿sì›0üv†£•¾§µš›á7úuÃ÷œOqyïãÏÿ@ÏÃ$FRãÏÿ˜áIm-õ™š;¡‡2¿µÔzŠKìAÞN%nÞñ"^’âÒH,ð³–g&RàŽbóÝœ5Âm#‘»[hç8he ÿ”âHcþ·Gp™KÿR\欆=õ +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Òüƒãi Kq€ýÏ•jn‹­~3ÅeªóÏù Ô< šá‹Ž€™åo$õ΋*êåo´ ¸Œß7|WOÍCóÁ:à ).7¿³ý ýÍQʈígS\j›£VóÌV'ðߎQäÔ6ÕÜ òÁ~„áòâÚ¯ø³FÙ©rWÔI×ñ†møC GÄË÷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ÍýÁB†w¥¸4RÆd•Ø”;É8Sܲ£Ô/BqyqÕ†žAð(Yµ¡ (.½ÊsÚŸ¦æ™Däà(.eþë.åÕw wcg—IÛ>„âRÓökÙJÏ=Û¬úµlÍpÜüú9}Àãmú°{>¤·5üV†Kºýñ%O«¹)ñÈŽ{|É‹ G‡|ñ‹2–q½XÇÙßÙÁD¼0Ã1ÉÜqÜ-Â3‹¸¹;ä® ÇÅd£áý žÀá8Gïþ„ài©ç ÿœâÒ)-Y5­+ ›ýÉäó<ŠË|ßÔ—õ܆jO£¸ŒaÃÏn×rÓ=ò0’ +?»“âÒ9I9_Í“¡‡)îôÇz‡6?%8¦y _Gq^íŸL±Á“ßyíß—z¾l»™jn!ÆÖvsÔš˜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òí{¬¯æ‰ý:ߢ¸¤Ã:ïgY¶™âLï›ß9!††ŸNq€Ïè°ZÏ„ç¾–âò½ïè>•á8–hG÷ G´ÏŽ+Þ"x€±ÌŽ+<ÚØøsÕÍÌÍc(ôsÕm—º®€s2ÁÝ0â§P\Z™‡~Oƒcq8·YVýˆŸEq©.^í5÷ýhÏÈë¯u xt†ÚÙjnYÅæýÓΣ8F‘ºëy¥»,Ûèr†ËâB»¿'Ws3 “¸áOR\Æ2e~¸HxfãCî57sœÜ¼á—P\j›ê«Ñ·É†"ç&lð¶œT_ýÅåUu‹–»^@ŽÖAU¿a8¢}f.^¯¾ù„b¿ÌÌÅ_R\†ÀK¯™¢t>&™ ŸNq™=¨íÑû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»õÅåêç®%8Ð ÿŒâRÓÖÏÛÆpä=¨Ÿ·ƒºº ÿ»îD™ÏÆh¤¼LÚïEqytE:>§ç¦…L€Of8¦¸'õúXÍM—›¼&õZEqyqêÕRó„ pÃO§¸´qc‘”P^ÌÀH/sÎ(2…Žýåc†#@®Â‘BjîûÑ,q…#EŽ…Ô£ Pl² 's7оMD†ö£ ¦R\n¾Ô)´Ü¦tƼM©SS\®þû‡=ÕÜ[löùýÃ+Ž/î”òc„g“mææÁ?f Ÿ@q)ó3‡Ú4ÞÑI†ï¡¸Ìq7&wí>ê$ø÷ Çß>àZŒã2 ©¹7´zf$¦pÜä€kÏ`8šÈ»›Þ îÅä6Äs•w7íCq©¨Wl@+“]TÊ=Î,e"\gņ + 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ß\-·)+Þ}ÿöµžkXã¹ÎEqéœ<ÿ€dM òÓae +å§ÂÚ¯R‘ÌwßÂp U2ü6ŠËWiþ¹à¹%¤2ÜTUèVšßŽâÒ£^¼óºãÅþOºcÈ ïGqùdJÛ«.|:ÀvÃc8Ò"õ<»¢žÛ\`à•).m\Í2ýµÜöæ±C­f™Ž~Ý'Wž¤çQ:vüdŠKÏêí“Nù ©rá¾i*BðÍ—Øåý†èyˆpä¸ÌYí½¿²šÇ‘;–hïýU(.ýºªØ‰f´²O>ä/ˆ¡‘ªŠÈ:Ž}‘Õ¯(Dð tõ+Š2+bõfÞž9F<ëÖžê㹃ÀêÍÊpŒã®|«Œ–Û#NÇËS\Þº¼Ä~5 +âëò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áÅ).]£Ä¦×Õ#<ï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¯Ws3 Dá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§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ç$¤ª>éÅe¢õ½ãõ»ÝV·§¸~yµÜ&.À²Îò:/S\jZHýƒ ×9ÒˆâRU¶ž~ƒšG¶×>ˆâòÁ{£‰ÌѶYð3Û<¬Ç^‚ᘫÜ5¤šÛ­)ð'Ž5©K¶Þ®/|”ƬÑ%[ï¤85~ñi¢ðˆx1üYŠ#táê]Ý‘ÊW隸4R­^ÿÜÏ‘Ûƒ…ÑL´’ 1-—Néñ§÷Qs›í2ÞáØB~Ëà:Zn—óþî–ÁõŽ×fîñ“Ô<"å£á¯P\f‰Ú¦¿ua_ÜÂB;(.…ßР‘ºðq„í´†7£¸\}Ë4õ·¯,f¶LSßyË1É<¿ó'ÂS^.Ûm2—ñÝió;¯¤¸´°-vÑóØC(r‹]OS\šÈÄþsõÒ9.ëØ),m^‹â2†ýqY57óu?.«Nq©¨sVóÐw›>swR\žû˜ÿ§ç‘; {Ì€G)Žü6·æ§öMgú;9JevÛ¸}Ð%o]Êp‰xi÷ÇE%À3Ó¼ÙŽ)±<!üÞðª—ÁÈ3‰ËÔÜnpK‚_IqˆýR´°šÇb‰ /Fqyëš/yNËMU™À~™æK^ ¸\ýŠoºèo]¡¢¾â› ). +ý®>QëB¤0¼!ÅåêË›ë_›¤ ïEq©ë–·þ¸u›öi}âÒ1ûüMâêê:É«{®®ûµN}5OÅ Éôk wç +ýü1xë'“ð0?oø'—ÊêîBÕÜðâø†c,Sí‡?ÔܦYM€¡¸ À'OÿŒàîÈÅÉÓWQ\®¾èƒCz^ð½/úàOŠË÷¾ç²mjž ‘òÑð—¹Ê]j¨yûXƒ®Ü¥Åe9¯Fܺü-'Y‡67rsV5ª¥¸´ï·Žo æ¡Ÿ.àMô<À¼ýý¿ÆjDiD¼Üÿë)—áÀþÝÔÜ †põý/¦¸Ì]Ô<½¹þÁÅ©Àñ–—¹÷l#^›”l-4|Åå‹kUašþÖy!2´ª0ƒâÒ¾ÿÕKëlRg< ¸+üçãd6ûdÝÀngJ9~űkãåµÜv¸`ÁËË(.ÍDéãZ© ïG ä]ú¸ˆâÒÆU¼án5"w¢SÅîe8v¨Mœ´VÍí‘‹!øzŠË'S¦ð§jD8#ÕðU—>íVÉ®£zp`à­‰—EäòÇð½¹-*ùÁ?RFP\Þº=«æö”dE>ôÅ¥Î{ax&ñ`Ö‰»}=L!s`Þ ã)Ž¤Ê?WTóЉ^…ârõ6}»«¹ï§Ð·iÓ÷2‚c·ýàqMµÜKG.ÇËàq­(.…_÷ýÝjžŠCܺußßGqyi«Ï™£æ ßíÖ©>gÅåƒ}éùÃú×&Š<Çÿ¦¸|ïG«_Z/“êüxŠËPhöð‡Õ…÷¢MäìáÛi;oùŠþ¥õз1|ÅeU¨ò‚áúÂÇ8éÃð‘——vp{ÙîçoæÍ…Çæß}ðï).¯ÍÌÆS”<ÌœzÏ ¸|2߬i§.¼Íw¤¸T•µ‹½îç´Ú\&á’.þ2Å¥‘º¶G¨æI/ŒR×öHR\¡7ìé«/¼ïNú¸aÏ@ŠK+³rj?âÖňê\9õŠK+Ó¥Õ5c¶Ñ¥•þê–KºH«Zž9Ì:ŸEqAoþ¥ºð¦k†YâñÍ×1³Äw ] žÛFf{™ä ÿ‚à $m8åã5ÔÕ#𯩫ËkópÉíj¹ Ã¡¸¼u%G}¤æ‰8‰ç^rÔ2†#¦ôò17ªyÒ¼]ið›Ža`û¼¹„æo%Î>ÊßFÿ’à>ÞºGËÜ æ‰(…-f–¹‰âÒ¯›õê&5b·+sÖ«ßS\zV%S/«yfc%øT†£‰<þxTVQN©>-7Ý´qÇ¿âÒÆ-?é|-·M4êºå'u x +ÝÂ"æ¨yÂЯ+Òh>Å¥…­YÝ.çÙ žPÉž+³¤`Ƭn™É Gø}ƒ9“˜;/®Áœi—>í µ£Ô<ŠÝÑ<ƒÖ>IqùÞï¿î5|—þîþë¶2IÒ½ë«?™d˜@=ŸîÝ€àÇm?ô3 Uò3›¸³§Œ°i\¢QÃwS\ž{ãg€û¹$˜µ\´O¿vg¨¹ ¥–ïýíVoQWÁçSW~dÎh-÷lÇ + +挥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ˆ0­WÌÑó‹È†Ïe8z•‡» Ï„agÝZhþ™ŒR’ÃÍðû)./íÆñuÕÜ¢¸Ô´‡/xHÍ£(™“Ãârõg¿î¤å6A 2J=ûuWŠË­;€-¥ŠÂ›Ÿ¡O{à×6 ÇaÖ¥·_£æqáLäÒÛûP\Þù¦%%ÇKcò|{Ž–‡hÃe¸Ì”¶;üì{à~NIZ ·"ð—ÎI1Ę)xÂG./Ã72\–uÚ¯¯S]ÍM×uÝú:5).Ïýû™Ïªy*ÂÖÃ_¤8r÷]õÁ]ÔÇ«†§QwX±ª‘–ÛtX¨mV¬jJqéÛ”ò®ºðq””—ÖðÅ— ‘;¿Û¢m¼u†o£¸|qoìþ¿Ò&üá¿m܃þ,Ååo/Qö•ãÿóÁ…ËSZ¢ìLŠK·pÔórHJ²’u×ü.å»D⣞oÎpD>\õîwÀ¤¸|°#Þž¤æ¦c„‰ÖoOe8¦ûV×¹LÍm¸N¼ÃquÉûG0Á%ïœànw^åM'ëo]à‚B+ojFq©ç?Ÿ{xŽS^6™¶‡^åçs¯¡¸|2u±¤d–”rþgR:ロûc‚âÒ§}uÝu Ç÷«ëúS\nÝ‘#C Ž…æ¸t:mžãÄK2³‰Û¿‰âÒ5Pf…ša:r|%ÅåÎ7ý{³š›7ÁMÿÞJq©¨O?ø†–ÛTâ”:ýà<ŠË­{£-æ¨3¡JÙC(àµy£í‰—;_qÈ\%·RîÔƒŠCæS\Ú¸Ëê\Ê‘—Õ¹‚âRÓÞÜa,ÁݪÐÍÆQ\šÈ 5Ž'8b ?ârç7]_…à!f‰7]_âÒ!/ý9suT•†3·.ÂÚDáúEÁ3AbÙ;¥)Ó#Ɔ—¤¸´°ß™®ævâÅñÙ GeÕtï*5·‰=ð/(.¯Í)GZë ï' +ø—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¡ÜÛ§1­L“ŸÑߺ‚9ê&? ¸ôç/þøÛ}wdÃÅ»=#žšz«šûžM<5õŠKá'ݼBÍ£»2 _Épœ8{bsýƒ ÜƇÙ†£K¼hV-=cLy-šU—á˜â^±ã-¢ð"ÜVìX@qéQ¯Né?™dœÄôþêÔ(†Ë÷Þ1}åÅú—6p]£ô•—1\bï|¬'ñàÐ%6üjŠK=ÿrÉád¶˜åÀÓ65ïøM—)¯UÞ¢æ‰!è†ßAqiß»\y6xniR‚L:m´ï]®<ŸâR×o:@Ë=ÛD§À1;•\ŸRódÁ¤Sƒë[•š{vs#x@q©ë†Ôí¡ææÆa9¤n/ŠKÞƒ"çÕU?8ó/éU^Ÿâ2Á^¶ß~ýKáƒ5üÃåÁµï?VÖãÂü nYälÚ¬8Æü|ÿ±s)./í½ë/SsÓ)ŴϽë{P\>ØݦåöÈ4Ð .º‹â2ùPâ³êÂÛ´Æ)ðŽò~C×€g‚…².¤ž\ò~C¿&8IéðÒõ¿¨yT0?ÿÒõû(.ã÷Fõè¹Ëù`ø"ŠK Û¯af1Ñ·aåéì<ó»T˜ô‘©a]†#táåú§«yžŽ~Å¥k´ùÌoõ…bŒß7Ÿ¹™âÒ»(2¶µšgŽ5×ÿí–K#uÉG÷èoi¤|ð!—ÊêšÕ³õ·Î 1 ¼fõ—ç^eóp?‡ãi2¿ b[Xeó3 GuQâÖMz^°s¡Ä­?P³ßoSsßw3使‡â2üŸ7cƒš{n’Ùðo).ŸÌæ{nUóØs#7ßsñ€¾óáÊÔƒ À«1û±i%´Ü¹ˆ®Ñ±ieŽYâzwmTÞ4RØ¡Vï.ý'c8zçÜ8Mxþ1Y:¥™ßÙ.ŸIq‰9y­éj‚GA¿Öt-ÅåÁ=uîB‚§±õà©sߣ¸T•=—=žË™ßy¾ Œì¹lÅåÖõûµšÛ£y"ðo(.ÃÓ®o«æ±ˆ?ŸârõwÖ«ï¼—ŽÉløã—NiÅ“w© opC÷0ÇM– {Ï?,#{÷ ÌdÏóÁ¯¢¸¼6•¾;žÙÈœ%Ýeæw^Ä’V¥ï 1‰ NÜV˽däŽê8að—/®i“¹êÂÛŒ“Ø×äm‚»CЦn¢.|AR&ä¸|qëë_äZøÈwýºõõ{R\^›æãÑ)ÍßJœ%ø?ó;ûÑ&ÀŸ§¸<¸S—#8Öß ¯Lqyë.©õÑ×è’Z?R\nÝ›M!¸;GìÍ‹¦Q\Ú÷Ovg +õ¸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‰2zä]Å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ŒœVb·šÛC™<ð}—O¦W·òàåÙ—´Ò6<Ïw¼2Å¥srÜÉ¿©yÂîê?@q©¬jû/äsû_ä2 ôm-ïa%´¶?‘ârõ+ïýÜ·öM^›ârë>ùš–{i—PÚð7Ží6koúR]øDä’*¯½iÅ¥¦]Ò¦„š'íÜxiŠË´ÏÖ2ÃÕÜ•€?Fq©i÷~x@ëügøaŠKuÑwνzîáo7üŠËPè‹"žšÛG—(.ŸL·Í²kÃeæÒ-´{>ìA£àwP\®¾¥B-p?Î¥¢¶Èc—›wK…ºÇ +øø®jžŠÓ¼;ÅqÌh¯IZîG‘›x9Ök*Å%l£å’]êÂ'C,a¾›âòÎ/þf¼ºð¡K“bøŠË'³îɱjn†BòÜ ŽâòÜ›]Ž/Îü·9q»é#)»2 ¿ƒâRU®Z‘àúó«‡Çpôç¿x¬3Å‘»ï±n—ÅÄÃÏ'Á}˳ ÙС †ŸÅplhm;a¹š'㸀JqŒD›¨y:r1fQçæ—×æǵc´ÜÆîŽc8‚Ž>|ÓDf œ0ÿJÆ^ìø'——¶æ¿ªyhgØÁ§¸\½s™‰jžˆÒè”v.3‰áH‹tùc²°’©~S^Ö n6°Åe¿7ü>ŠKç¤Ùä¥à~ŽÜ&¿Cç¤Ùä G]wFƒåjž´“áàú«Ž€ØGËߣå6åcèøŠKY!cØÈ .sG~Á~ÃR\Ü´ûÞ{¹u‰í±D '=í¾E—O&ï6Û9±;§2‹„AöÊ*¶áBhãòn›ôOfÿâò¹„iUìõ€ºð¦gãööúÃ1?_õãÕµ<3ñ’uIËüÎKZuŸÚOqé´r»šÛ•ünŠ#ÛÆê•jn7£!ÛÆê/(.û†é _pÛ†S\¾÷‰ oTs›8!~3ÃѧÛïG}áCwìàÜ~Û).ŸLó"M‰Âc·Žá-).ÍÄM#ÏÑr;íƒÊꦑçS\þöù%Æè?XßÕuóKŒ£¸üí-7žôr›tJþã¤NÃKRçÃÖ¨£ç.š×ðú——öõ3‡)yÂOFîü¸×ÏNq©¬Rñ°’ôí¤SÖÍ>¶¢rÛ¬ ¿„áˆâ¾£ÿ45]v\Ãg1KZÎ.Fñ¼ÅeÒ©ÛÀÏÔ<åà ÿ’Ⲭóþq×ê\`öý㮣8‘õiž™êÌ>üOÚpœÓ§Ååê—6£çv] ü-ŠËäÃSÏTSs3ˆÄûSÏÔ ¸Ô6›.l¦ç²mޒ᜘;C!»é#—¡PÊËT—à{).£‰÷O©¤ææ•ÅäÃû§T¡¸¼6¥ +Ç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#Øu+¨ Ÿ´‡´€Gqùâ/µC_øLjþ Å¥ðO l¥pQ€ö©ú—Ör¹ó+xzºÅÄ• "ŠK¯²D½úW°W¨D½F GªÏ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ŽÅ…¼àQx‚fø GBiï¥=๥1·‡þ¹4h†ÿFqé˜Ý?j³šGn×ð­—/n弧)€?ËpÌÏoûôžGÿàQ\>ؽOÔsÛR€7¤¸´°g÷Wó0t£‰‰³o$8Fæ½¼WÍ×D¾Ÿâ2gµè‚>jn79Þ—á˜Þ_³¼«¾ðq{B×,ïNqé]T|옖gŽ†DZã‘EŽTŸÇN*GÜ:wôÞ±“*Q\bÃK¯Êp?sÖRvžù$ÿ‚ârõ‰ýÌp¬ÃNük'Ååƒ]ðxJÅí­K„7üTŠK‡üƒ÷ǨyùȺðÁûã(.W?Ú½§šÛÄHø5—.q×ó§é oúóŽÏ¢¸ô*{þ´<§#ìeì¯)🎄T·7l£å™„“>øY—7þîψÂ'QÓŽ¿{5űûþh5O‡ºÄ¯­DqùdöxÝô·.ŒñÎïñ.¡¸ …R«Or¬¬ìÑm°þê†#DíÖwÿÿ¯`!ËÿqVæ­3Դ³×uT>ŠRø`g¯ëLq阽uÛ5·³^iðE Ç­[xee=7ß+R]Y•âò·þu)âµÁd£áe(Ž9êgÚè?Ø …•-ÏœÍpìßÝ8Ô¿6.‰ºá ŠË*p‰J…Õ<éŒ0¼ÅåÁ}³°¹ðÀËeËýï ÞŠá¸óûQó¤Í]~Œâ2õ±}ïsà™EälAà~&»ƒ;rqûÞ‰ Ç÷°ÅW¨¹!J‚_Ep7‚~ä“3ÔÜίûàçP\*êGVLWóØÔV ð™—Šzxï£ú['1–~uŠ# ú3調¹y’ÚðÅGó‹J0¯ïxŠK+ó^í?õ…b,e¾WûÅå¹/Y¬k¤–¬KR\®¾îíkÕÜ Ed¶Ðð¾GÞÂb—k¹=BíûïÅzR\f +½ñà\ÞƒBï÷ ¸ KvU¿u6Ý%²ç•ìª®.,Çr^zö§úÊÊÃÉ}†Îp̘½<çG5Oš®M¾â²:Ðaà¡ŸË6+»ž—Üu‡açR\*«°þ—Zn{¥ˆ%믥8®Þa”š^Qa‡1—ʪW¡Yê[—òݑʽ +½Fqéœ|ùÀeê›—™¿| ÅåÎw¼ì%𜀳ˆ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Èp lh¡/|Œ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§ÔÐ^Í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ÿœârçû÷ߧæaä΋ìßÿwŠKEÝqÄAáéL²Žì¡Èi/ˆ± Ûðà ÇhâéÓW©yhÓ?ƒ¯¦¸T•³¦tRsßs¡È³¦t£¸tJ W]¤æéÀ¥x-\õ}†£SúzðSx¬Ë¼è_¿ ×ÇÑo<öè7M(.ÁÏv¹MÍíl¡ãwQ\àGùú—Öw‡=– x~UÙîà˘hMgÂu²mBªX–q ¿‹âòÉœWi£šÛ£«à›(.•Õ •‘š›“ƒV¦îÂ6†UQs›…-žGqi kütŠþÖEn ºÆO­)Ž4hƒnUóT˜Ædã¢AwP\j›ý+¨y¢ ÞfÿÊC—¾MéO>Õ2~2püsŠKeuç¸îjn#óã.£¸|q;—Ë4¯©ûs9bÕþÎtÇ1[¸sùŠË;¿÷æmà9ðjyÒO!=ÎÞ›w2‰F·ž‘ xÒsrèÚ«Ä¡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Íï«ÞRߺ0H`žö÷U (.ßûŸýïÕóè|ñWÈ»4Rs›ÊOQ\*ê2½Ñ¾çoêÌÞ)µBìÖ)Ó» Åå¹·~¡©’'2Ue¼¹šÿcâå‹ŽÕ…#݃/:ÞDqùÛ×­.B> ^œáxmú¯.|"B·ÐðÅ ÇÁ¾VÅR¦Ýb–ËÂJ"“/ßMqMÌXÿ‘–{é(@¬ÑŒõËŽX£×Î-®æ¦…ÃvÚ×Î-Eqùd¶ô¯¨æfðð¶ô?ŽâÒ9™¸¤‡š§á– €ÇHªZ»Ú—^åÇó.Ws{ô`üJ†cwö¶¾j„&ÎÞÖŸâùw¾SÉ‘§«¹ï¥%¾Îð³(.ûç«%(ÔOåtÔ¦ýñCBéÕ1ì¦n 5Ï,쀧).ß{õV€g&³nâöm¸pê­¢¸4Яü[xŽa™~:³˜(5íÅ« +3õüÁ§kQ<¯Ap·K«Öß]Ô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Ë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Þ€âRÛ4Yö†š‡žûâš,›Ëp|qo|@ÏÍÂù2#ÿâÒÊŒÏ&xˆ¥Ñ¡þµ±\ZØ…§OÏ-AÍçä%³qáé“)Žf¢ÿ,5OÄgçõ•â2’:öàw^Ž=¸…âòΟru35OÄÛœruÈpô¨‹öEðÙóŠö{’â2É|o÷zã2ÃS1¥-eu ˆ2‹JÙ;¥‘ ÀÉ>ÍZ>ÏpLuv/ùùüƒB²°±—r{ /MqEž˜–LàAÂË)dÅ^&Â!h†_Oq™9ßóðÜf›º?…”Îã{>Kð4–°ßÙ•àn¢õ÷Q\þöÕÎÏ B³¿´ ;s‚½B«+´§¸T•ão¿\ÍMÏaZãoïAðaØKUóD€¸áÏRùm¾¬©ç.m‚áuŽ°ÌÃÑL$3Càì“É À ßJq)ü–e_ܤ¶,[Oq©i‹ÿ<áHñZüç—öÛžÇÔ< X üöª¢—~Ýw+ÿÒóYR ' +¹,©[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÷Ô³ÔK_‹(ž@á'Q\êºËžžÍpìP»ìé7(.±¯ß/ÏpÄÏý~eŠ#(ôÊ™GÜ…á¯Sð~ =wí»áÅ¥ºøáØ~5 +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)¡Z~ùÃå5?] <³œ—ýÁ…6ç$–uæ§ëQ<Æ;àXý7ü&ŠË¯õF%-7TŒº®ÖUž·®Ý‘^KÀsZL 2¡îÌÄ#½>¥¸4‘c澬æ)Ó/óÁ§P\©÷)¥/¼;bÕðrOãµY¥æÉ9™ ÿ‚âÒHU ÷©ya·á¿3ëq7UD§4· pû»dŒyZÃ÷Q\ZØoµd8bÌ6¾åS\è]»G¨y*Àɼ†¤¸<÷} žÏ)9ýiž‘Â}ß‚ç(.uÝ/óÏÐóЭþ'¶¯`8š‰Äö•Qøs(.ó6ë>¨¦ç¦_€× ¸ÌTZ~“žÇØ'eømÇY·ÿªæa„zÞðß)./mƒI#´ÜKGIym œâ2^»e²ºð /*àÓ(.u¥—OÓóÇÏÞ†âr몿÷§š'mêAð¿).ϽéÒ³…积ϖÖØþÎÙ<ðs).ÍDÅ»0í“¿Õ({ác{”7*«Šw- ¸tNŽk1]ËíqX„×b6Á,Ô¡éIW© Ÿˆ¤¯ozÒÕ—¿}Âm¯è oÏ=ŸAq¹ú¼7ת ŸŠÝÖƒyo®§¸¼óâ7Õ…ÏlqŸGqé]ÔzáW5ÏLÉ‚ÿNq©ëšW™ æAœÂRfó*/S\®þê½C‰‡­†£¸ìùmÈVáùÛë²…a6?kàv&þ6d'Åe‚ý§m;ôOœ¢æÉ‚1ɧQ\®^³ï@=bŒ¤jö½‘âÒÊÔnü«š§Â0püÅ¥ºxéÂmjžvyJ ßÁp|°ó^À(2Sgö‰Ö¤ñÂ~™y/Œd8º…_Ý;\Í£0õW÷>Nq„eæÝ¢çQÁ»ónc8Ð÷ÛOݺüÅ‘çäÔÎj¸¼F†_Hq™9ùæÌ“õ·ÎÇ7¼)Ã1ß{Nký­‹]šÓ½çœÅpY‹lßëæ¯Á3 jÙRFØß™NŒŒ& ÿ–ሣžõ ¯æAÀ,ñ¬CŠK¿nù‡yjFi¬„.ÿ°&Åe‚}Á{sÔ<Šp€»áoS\ +ß«ä45=—y WÉ Ç@¬U™×õሣ~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Òs Füü㨲."›Ÿ%]âû03f}?¨ æ)ßå5êûÁq DZ_ËÍ÷s9ŠË^ÆNzÅà (. tÉ>W©y:@6l,¬É$x#·!+Ø$O¥¸´q ›?®æ~ä6¼,l>ZÏcûYùnú›«ûàÝ)ŽÀÈ7$îÂN+äă̮Î|Å¥?_xß +‚»ð¼ÂûVR\¡÷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ÍÍÿ¡ç•½”âò½ÿ±ì*5·ñ÷iðkŽ³°K­ÑÿíQc\jÍe G§ty©%úÂÇ8vÐðŽÅÄf ‰5ò#/Ωºˆl‡»ï›%0/:á‹‹Ì«˜ÌaÙå<¼ó:í¡¸ÌÿÐ8-÷3»:ÁÇS\Âu¾®™RsSUaÂí뚧Q\>™þãv¨y"ͩỎ\^÷Üý¨šÛ´‡8ýî‘—eÜñ/•S¿6IÏ ÿÇ¿T‰âÒ«\Ñï+ý­‹Óˆ¯[ÑïkŠKï¢LÙ®ê§]Œ™á2ùçËÞWY]xÓApë2÷Oq©*+¶¥æ¦¢EržŠ­žd8b N<“(¼[“j8±-Å‘)tg1ý'ã!’ÙðÒ—Â'ìÓ¿61Ž—5üÅåê‹ÑWÔ^€cFâÒLT8M².ØV7?È7+OØôàe).ìgté¥æ©Gï~ Ãe¼ãðo©y2ÄøÝð÷).-ì}ÃÜßî[ž}º/6=Œ" ¿–áXÖ©rE?-7T +õ|•+n ¸4R§?{Á#tÈO¶Å¥›<éTõ­KÆ.Îjò¤Ö—º®lÂjžþÇêâ ÇP¯Ú<Èí¥ÿ±yßðF—;ÿóS'ªy"Â5Ãõ…·a—¯æI·ÍÊð ÇX渒˜æµ U‰ГÿÈ–ixŠâr몴½QËÿ™{¿JÛ[(.lÃÕçé oÃÐÁÛS\þöIÕ¾×>Šdmøf†#-ÒŽ +/«¹é`¶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Â"gø`ŠËïÒ¦)ÁcÜù.mZP\¾÷!·5!xÇ ¹­9Ååêã¯;KÍCÓ-ôÁÏ¡8¢:ÿ(¢æAœÀññ•þ(Nqyîu?&<éåo~Wpx½áO<Ä4oéÍ·¨yAŠWÃo£¸|2ìøÜ>ìÛiÍïìpücŠË tÕ§š{n/°áIŠË'ÓðíýjîÇ©Èñƒ—/nÚ÷'«yèjZÛ5m‡ öÓr› +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‹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ø —Îɱ—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êù£µ¶¨¹Š!’ùh­­Göë1_—ö²'ÎçI— ÆðÓ(.ò¦¿]¡æ)›Ð¼'ÅѯÛá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îÙáÂóæUy‹áÈGý™÷(xfi#k¨’o7ÎðÇžDÂÉRÏ<¥æé …ÔRÏ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â.¾ï}ŠËÕ¿ {]cI+“Z{… ÷Ž Ðã{wÜAºËã{d8Öã ;‡àØ/cx]†c¦´Ñ²jî)´u–]Fq¤5~·¼š›¡H>?â2gu}W_x/…þüýõO#hä}êê>8wuÙ^®dŠ'ÀP\^™Oï ãÀÇ,O‡°?½w>Åe²±áˆýZnàqVfÃŽý°ök¢æ®ð<Ã/¢¸ôi‹½æªo]*ÊkxÈpD>¬/_B]ø ŒÎ ]_¾Ã1wÑc^A5·ß÷y§P\ +~Ô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]®¿u–KKÛzÿRý­s°™×ðå—;_n FRɘË:I{:,¡å¶|ÀpŒeÞý®”š§íÖðr ÇÚDC«¹-;øá“(.o\ýSÚ½JÃ;P\ZÚ^<¡æ)Søød†cÆ,ÝeŒ¾Ú8VÓ]ÆQ\¡7ÇŠX2³œ—»{ÌdH€ ¸tÈ¿Yr’š¶É/Ìp¤¿^«”ž{É âe).»sÃ.5½M¥sà G´ÏÞ½Õ<áD÷®èÇpLq—­YZÍ“a€ÆªlÍò—AèÙÍeψ›Š—ˆÌüÎ BŒ¤În~-Ã1’ +‡•Ós?”€XÃ+R\F‘\†HæìfŸ8<FB]pÙK GÊÇGJÒr×7#ÁøQ†ãÎW>І)|ñv—¥ §ë»jž ]¸·ššÛ,j>øY—‰—ó .Ðó;Ð _LqÔºdzÜsâ%ç1ÿ6¥GcÎø‡áر╖Jëe¡ss×èŒ7Î+}'Ååo¯¼é„šg’O ÿ²Ã£!ðœ¿À3/9ƒ½Ì;—›[€âÒ¯Û0}³–g¦}’à[).£Èº¯Ü­ç6-øpŠËÕoŸ½WÍÝ0‰µÈÛgÿÂp¬EîYÞ]ÿàìÖFð GSÙ¼ÿJp/ÖÖ{ò]è"<¯yÿŽtX×~q\Í6€üŠËäCÝj©yà$ˆŸÃp„iu¹´‚šÛsÈ“à•ŽðûÄ_’ËËóâ%¤òl® 4V†Aqiiï~cžš›þ4æ*ï~ãMŠËDëàíÕÁã¥ò6¿K†>’u Þ^“âòÂ&Þ(¯ævD^‘âÒ!o²ö57CP|㚬íÃpÔù²-põlóÜÜ·ŸHäŸ/Ûâ&ŠË ;®ÄA‚û2š0ü0Å¥ÎW>ŠâIðûŽ¼Ûz=îæ>ô0û;'ÚViøŠKcUaKA5÷¢Ž™á…)Ž|V•v¨¹Ý-…¯qs†cÂíóS+©yh†BiðªGzÛýƒ_Ps›H< þ2ÑçäŒÓ¯×?8ó>x/Šc02¦–;i?@©pŒºÖe¸4•á¤+õ<ø¿Šàؕٮè#‡õ/lˆ7ÃS\š‹q·ÊN%/Ÿ»± +ì6jÍ3îÖznc³|iï»ÔÜt °´±´÷0ŠË+sÛŠ§Á½XÁÿæ2¦sFüY‚G'¼¼ôÒl=±ÉËð¹—ÞEâP5OøQòüÄ¡b—ÏÄ]%0Òˆ*å Ç5¿Ë$n¯Lqi¬JÝy‰šûnÔ%.uçe—XW‹è¹ýÌ€£¸TÚmƒÚ<‰ ·mƒÚQ\–6~Xö€šÛØ$øh‚GéïöïúGÍ>Îh»wAŠKáo-Œv>®“›'ÌèÛÁ´Ï­…S\zV;×d8‚Àw?‡âòÊ”^3WÏ£c‰ _@qyp›½ÈptJ'6{…áÈÍû݆^jî>–q¿ÛЇâRø«ÕÕrÓ9ñp’×Õ‡R\î|¹þ-À½¸…}±jøe—Z×xø/jžt¢ñ{ãáû(.mÝÅûd+±—]¾Ï™´Áü.sÞ$øŠËPhkYÖñR1»…v7ú@o½ü$ŠK[·­ëŸjžŽ–° ?BqšÞ£å6•æik…£ŽQäÕµwéo)>Þ¸Ú?R\ú6N¼¯.¼3jøJ†K€\룣ÕÎfæ•ÆªõчOe8âçn“Ó.¼ì"rî ö”]PCKÛpÛrŠKK»ab%OgÖ¤|ðŽ—¡Ð »·‘ÙKg"^<ðÇ).o\»÷57U³ÄíÞ÷).Ñ>wÜÔàÆ°wÜÄ>=ÖUËÝÌ9äà×Rûefcz?ï` »í ŒÎÒ*6û+ŠK;ÿHáKÔÜ·©FÁ[Q\#“ÿ™«æ%”žüÏŠË ûÀ²Ýjn7÷¥Á"¸‡EäsœWÕ<å#»Žá¯1Ë÷?­îÇ 0ÿk:XLüiõLŠË¯³¨¤ž›WÇŒ.*Kñ4øZ=wÑÚ¾ârõzŽUs7 +3|"ť𛞭惸JÃk31äE·®RsÏOaÊ«èÖŽSJuܧæ~~oø†#¢uû×2[ègCVrFl§ÎÁvZÃçS\&Ø›ÓZͽQ†·£¸ÔùIµº…2BOªÕâòÊ|¾¥¸ùlÆØJìgiÁ‘ Ÿoq(.£Èa¿xjžŠúó†‡ Gµ"÷5Uó´]HoNqùÛ Í¼PÏ}¤I1ü"†cŠ»V‹zúXªÕâF‚G#q¯ú_üäÿƒÛe7â).•6èÖZ[xS爫 ºåQ\\³Uÿ·Á-“VßwçP\Z›Ý;ÔÜ“2Okø]Ç.ìg²qžm~c íïLß±ð™Þ—t©å5õÜ‹ˆ)µü\ŠËg"q´ãx›£gS3Ï xTmê~8ƒáÑVâgQ:ù|>Åå}/{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‰%Ϋ=åÁñÂ~â2{дâ57¿B·°iÅÇ®±?‚Ç:fÔËžì‹1ì ±?3\šÊ¶ 6ީ禃Bð(ía‘ÆÔÜô«°Z¤ñ… G,q‘]Ï©¹¹ï˜ò*²ë†#¶ðÀש¹é  Szà‡^—vÞûëá^¬äºöwv«Q¾šâRmº~Ÿâ2íSë<ýÕ]?‰Ü}µÎ›Kqië^]Lx6`&ç´á)»¨^‚áxî»oÿFÉí~û wß¾•à> +¿ûŽî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Ýé³…†?EqyãÊ5_¡æö Ïø*ŠËp ÄW;Ô<ˆ`/ñÕ.ŠËú™³£;ïÆšp³ûFÙ°ÛVþ½ž›>½ B W/¢æ¦W‡¿ýÏ?Ë«¹Ý‚W¢¸ÔùÇŽÖ×ÞM ¥}ìèy÷pëôwÞÜ:L¸Uþ½õàT›ÉTµ‘Z7hU75OúÈocxŠK—ø¶žÝ熱’¨g~ç`¯á{).Ÿ‰‡†ÍÓs9 _Hpäll3¡ù%ÏdDŒÙ„æŸQ\þöÕë–3·NF‘†¯¤¸ô.êm]Añ4ø —¶]…w}/SÞμ¸àí(.íü³óòÀc–áaÝÂgç]NqéþóEåÿÅÿ{c£=ø/ˆŽ“þç‹j—ÎÉ9nR>b Úð~Çt»ŠÛŠé¹‡¼Ä†—¢¸ •¼Nvm¸6L+Ît_Ú|ˆ¶äuí žF`d«ç¯ÖscXûPû¤:þ¬æ¾‹©Ã÷S\ê¾Ã€g¦>r"ÓnÂs%¶ÐðA Ç~Ø[‹ÖUs/Äáõ†7 ¸´6·•^«æN´‰Ûð).Cà=›ïSsÓX ©òžÍ£Ž8«C]5ÝD´‘¹cŠâò¾wú`ŽþÁI|";}°€âÒ\lés¾šÛC¡\pâ2 ¬òûíZî¤íªøÝÇÖÂùµô.t¢È‡ùçó6yÎÙ\žý?ÆéØ{IÈ97¾Fq¹ó‡ÓÔÜ1‚~#Å¥wñ÷õËÀ½¸< ±Øð(._™n%÷ê¹ï†ßGqyã>ûþr¢ðÈ‚nxGŠgo]ëgJF)/›˜(ç'Òü.áùÒÒ¾†áhiߟuBÍ=›ëSøì—7uå15O{)¬ÇM]ù7Å¥±ª=²’š'í‘ÒàUŽôószè oº¥xoŠKïâ¯/wc¥Ãò2»ß1oóÀ×-(Žy›&Ô<°ûëÀ7R\*í¶fÓ…{ñ¶UfÚJ¬Œ>‹áØ Ü·ÆIà™`¡œ)û»(ÝðS(._Øâw­åN*Úrbx-ŠË+SgJ7=¢óeêL¹Žâò…õOŒTß:ÇÇøÝð(.­ÍJé ož[|Å¥Ò~ü™tìQŠq†Àöð;/Ä +øÇŸÕ§8Nê»QË3ià_03¥×7ÙîÅ +”²‡:HÆeøfŠKC4‘ÈÏ.eƛߙO4¢¼‚&Å¥cv~Ï~ànœCíï\/Aèù=o¡¸Ôºí¾¡åö¸ +œø°ýÁ·)Ž ð•ÒÞVë¢y ÷ŽAè]¥Ô<éciÃð& Ç+óW£à1‡Bv6|5zŸá²ÞúØjIà%bv‰Ž=ýÎßBq4Vsú¨¹eU2üfŠãð»¶_©¹ýD'Á¿f¸|"ó÷”ž2B?2îYŠËÚÄWßWVó”—Ìçg2ûþG檹ÝLœ_@qùÂ|{x¼ô8Ù‘ߦàÛ£ŽMÜ&oWs3dCšÓ“wS\Æq{oRó„~cïÍ—ï{ᾇÕ<ÈOùX¸ï †#y™ë å=0üRŠKáß{$¥pžƒµ÷¹€â˜¯›ÙIÍC; ïJq¹úÖR¯¨¹ ³Â‰¥^£¸tê}ÒW_mLÏ(â73 ¥û=a`6!Unž´Sèö{â<ŠËX¦pÏÀc“¶¡Æwá_2û"ló¦–»¾ŸÄXæÇ6oS\ÚùÛþTs'Ú¥eø1ŠKkãmRÍÍ?˜æõ¶O&x +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õÙ(.-í”!›´Ü.â¢KR%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ŠÛ%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¼'Å¥±:æf5 Od8&^þøî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¿ÍM Gö§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ÌàÎ ¼L QNn»ó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\–2 WNé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·‡ yHsj¸Gq¹óåוÏtÌr7vA-Ê‚^~]YŠKϪÁÛ«yÂtÒàŸ0\BÔòÎm°]Ͻ§×Û`7Ã%p"oÔ°ájž2 +|$Åe8P¸JUáÙD%9ÃïÍï<;å^ƒáIUzô"-7È4¦y+=z ÃQi·¿®æ®ï¥£¡Ðë-).u~wßqjnžf w÷È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ð³G{®ÑóýyÃ×Q\^™KfRóÀMcMê’™GŽùù"?PóÐK¡kTdàjŠK[÷Þé Õ<ábÝð%—ÂO¹U´¼ìò}îæ"e“2áÀÇ)·g8>•—½Çpd”ª¼l5Åeöü†ÕÜ&YM€W¦¸¬Œ”Ý°NÏ]gø§—øºâ_¡o“]@ÏÝ)MeRyàã).ÍÅìmÃÔÜñ£3f#@NÉ¥¹XÚîc-ÏdôÁ7R\¢>VÚP]øÐ pâç.ÃÑŸß°î!5‚Û*7¬{„áÈzú jî8ÌðÏ).ŸÈ-õ¶¨\Êtð­—îAŸFËd–ïcpœ—ÄœUŸF—1sVJ½ îÅå¾/¬áËŽçÞ¦ŒÌûN¼©ß.ãâ4jÃS\æi½2‹Á3Øs~"}'sÆ +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-ôi uáÝ …ðûBŸ¶¤¸|eÂ%#ÔÜ3ƒÈ$ø(‚£µi»¡ßß±¥2—±Gu +¿¹ÅåûÞshw5OºÈ{`xŠKßæ­NVsÓZäó¢—WfSs¼q‰Xìeì¡Liðá Ç–“é0ÁžˆµõÀ^Æ毋øQŠËZäŸåÎQsSk1û³\ŠË­;6ÐÓs?åGÅ¥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¾§ºðŽÍ»~#Å¥¥=±ï<}µñ¢y›û\ŠËû>vý-jziD´Ž];ÅåÁ½0$›:ÀÃÄá6)‘…¬¼0äI†£µ©6Ï ÿsBÝ̿È;—·¹ÌCzDIØ6—y„á˜`/´bŠš;æ* žâÒ·¹ -‹ n680çô¾½ŒÈ]žÏp^ÿÝáÛ´<3ÁžÌp<÷–¿_¢.|hJŸoMqië¾»ýt¦ðˆ}w{eŠKΏㆣ¡þîŽiÔÕå•ù~ï9Ôs÷ÀëSÏ]þö#óÆËy†?Fqé˜zçoõ ºˆ-Ì+´´ÅåÎÿÓõ)>Ž›s(dópû)œèôO×g(.{щEÔ<åp3¼ÅåÖ• +®×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ëæ¼}£š{.Öß ïÇp FJÔ¾<Þ&/ÃC~Å%L«LïBjž4Ñx=N|hów>ZîÚu™ˆßBqypáèºÄߎ€Ã<‰ r|žÙ-LeÒe$À1RÇÆ” x´#õؘ2ÇdcÑ[…g—ïsBÓvËs>LpÍӦƦÁ3‹‰¹§>²ÇØDüŠËûž·7Ts?L ¾.oo#ŠËWfi«BjžðÑÎ^„âÒÒ¶îZXËí÷ß÷Ö]‹Q\ªM¯oVÞôêäûnø~Šg[ÚvdÇ ¼ì"rÎ.±ý)~Ä<–öñ—Þ·°bËð£cé}ŠË¢Ò‡¤©ôÜX©ÿ›9ÀK¡Súá€ó(.Ãÿ"ŸîÅJ@g/ã‡(¼áÏQ\®^©ñiJn~ç ïá¥).¯L­¡GÔ܆χàÇ(.݃ç;Ü+…»å)ßÃGêùQ\Ö&–.xAËÍ0i •á¿ÿáä¹jî¹é0â (.¯ÌòsßVߺ´«þ.ÅåêƒåêÂÛ0êøû G·=Õ/ž™ÞÏÝ13¿sÃ6ûì©Þ–áñÒ®bÁ®z$$®Òðk).Ýg5^X?^0°áù)Ü ÿ›áˆhíÑi—–ÛÌÀÈùУÓ—÷=õUEðxR{\Etî€á•).߸Y]ÿ£æ¦G‹€™Y]§0ÒÛ7öÄë›ß92ÄÞ—âÒ³Ú1ìq5OEA¡†O¤¸TÚ’MN€ÇJŽ-¸ný›—ÏÄОEôÜO#ßÅОÅ(.«‹.¹QÍæÉ%ÀûP›û®¼Pÿàò—66]y1Ñ2¢ÄŠ9ú[`g¢áóŽNé ÑËÕ<ô¢¯ƒF¯¤¸4OØÁ¼2˜«|òÀnŠË ;~‰ä|ð²Kعyøï–vü’+).Ò’W£Ö…±ZžôSQSyõÅ Ç„[ceõBqœ;p_+ý­ BÉ’jx[ŠKCÝòÒFjúÑÑ<-/mNqùÊÜÓ¥»úÖ9A±…÷t¹žá(üöÛ{¨¹g×6À{Q\îüUŽ,&zÙ ì9'ìe¢Ü>†/ ¸¼qËkt·Ý\&å ?oxŠË:ìw½©æI›ùü-ŠË {æ4V1·Û#™|·îÌU(.݃B7¿¢æ‰(ë‚áÓ(.+#'¿¹HÍÍ7›>N~óMŠË÷}iënjšÿ–¿žáÒÚäMm‡[—]DÎýÊ$íAŸHÆ5µÝë—îÁÒ©øÊ$ã…ez™TÚX \:uÅ¥ÖUüššÛîQÄgR\ÜÉ¿Kd£—]TÊ=ü·[‰},çüûŠgï|»b{ª¹)ºTZÃߤ¸tNÖíGß&³¤•{‹™ý]~çdÝþ9—™“CþEð$ºÄ‡Æ ¸ômª'{)y*3Áî÷¡¸ÌUþ³à}áíÙ¾à£).ï{ÍÁèg•rO°§´=æüRŠËƒ{ìœPËÝdˆ¬‰†7¢¸Œe&mï¦/¼½2“¶_OüíÖßÿjö¶ºðæëŽ5[Fqé”îùæj5w|ÌޅⲬSïèâÖ%ÑÒÖ;úÅeM*Y·¯ºð¦g„Í>ɺŽ#š…3Ôü_'ó6 gR\ +ÿÑÅ_©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Ã¥±Ê«_þ€š§ü•¶~ùƒ G tã™wƒ{q¦}ìe¨[høpŠËäCõË««yâPcÃk1Ï}íœÎjž4ãP¼Åå}Ÿ}S áÉXZíï¼ iŸÙ7Õ¢¸Lu.˜Z“ᘳZ0µ6Ãñ‘únFG%Oü{ü»](.Ÿ‰®OPÞn2KƒÿÍpìÆ=oÍéà±Ô„™C‘ˆ³:oMUŠKcõJñ¿´ÜuØWJœDqé]|µþ[=w06üŠK:Y¢“úÖÙ¨$xg†K—¸M—onžŠ9íc.:ˆlìòÍ@†#òáÆÛÔ< Aá;).ÍEí/¾wã$&²—IzÈ løVŠ#Áì_W«¹éLwe8Vÿ³-¸“»^€0-Ã/g8:¥í_§æ~æó(.Càç~Ý /¼ @î¹_?§¸¬AÞÖTx¼£yìï^Ô)½­Å¥oÓê’FjžŒâë oBqémØ?EÍó‘þÅ¥©,Þ¨€¾ð!ö^ˆáˆx©´èy%Ï„a#h¤Ò¢).µîßO•œÇþÎ £øù7~?âÒPoêö šÛ«!øŠK­»g`!5·}ð—¾ÍÊ‹OÖr3ŠFÐ+/V_=Ã¥wQ`n=ÏÏéT`nŠËRo-™¬çö4mðg).3ä{Û¿¦æ~´jøë ÇJh‰Ç—…¢}J<þ>ťηðžÓrÓ5Â<­á/S\ +?³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 >ñ©£æ6ÛfP\Þ¸)WsÇÃrß x±ÄmÊIŒ™G•søo»¤n”«M¹ƒ—†úžz[ÁÝ8©Àìïì ñm—ná×—ìÕrSiq|¼áû(.•vÖ9§ª oZÌÍ:ç4ŠË tE¿ê§L÷$/Mqùƾò:5OFK†÷¢¸ô¨{®½_x"Ö¯ö2a#>šâRmžûC¡làDî”éŽÛ·à(.#©©¡jžrÓèÏïL 8–q+¾«å™i',"W\Að(£ÔÆÄ©êÂ'ƒd”Ò9Q‚âÒ=xö½SÀ½8‰ÈÂL*í$Rû>ûÞ©—Âö¢š'LÏПFq¹úk®RsÏÎÂ~­ÀÕ—j³úûoˆÂG§Y­þ~+Å¥cvþÊÞÂc.ßg%Šà+o&xtÆÊda5·ò¼Åe$5oÅ­ZnÞöÓ>óV f¸xÚ5Õ<“|ü\ŠK­ûºÊ4ý­ ÓøÆ}]e:ÅeæĹZýÜ]{`…®~î.‹J[^ª¤æ6¿l +¼Á±['ïÐÙ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¦:c fNhÁÞ@ß%8ÖeÚte:¸ç@gËm—<>“áˆòöy¨æ©›} OS\n]«[–k¹©6Ñ‚Z«[VS\¾2¥¿ØÄUé/¶P»TÚ²gŽWó¤­»à).{³•ê;oêÔlå—¶îý%†Ü‹™6ÁsMçÄÁæ¾÷¬Åp,"÷Ÿ·OÍÓnt¬pÿy).“ÌwìZ¦æž‹L#†¿OqéQ—/^<^Ò»*b—rÁO§¸\}r§EjîùXÚ0üM†ãxšrkež=)F¥5>@¶á¥). õ· Qó„M9 ~Åe(Ô¦ãt5ÏœÚ>“âÒΟVµƒšÛÃ>SàŽ>íË¥ßÕ?8×S\&¶ÖÿB_øY‘ ÿšârçë·/%Üu´®åI'u^Žâxeöu×%¶Ñ2ö“Þ…âÒ\ÔøªŽš'C B ¯Oq¹ó¿}ÛGÍ6C øÍ—±Ìyg«¹8àçPûã®j îÅÚva/­ŒÞŽâ2ü?ùgôˆá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£Å¥­»çÖ[Ô<íGQ÷Ü:ˆâ2‚ž¿óI5OE§ÓþŠK÷`õÁ-jnû¥ið­ G"²z‹7h¹­sX“ª·øsŠKǬAíÎjns2¥Á»1§ÓŽ|í&ê•I‚`8r6Noz Qi£Óë¦7½ŽáØ>ÿ›˜-LÅþ§Lc…”áïS\šÊ¦…¶©¹Ÿ¿€Þ´Ð†£Îï¿óoêêRi÷ßUˆºº´ußüƒÙƒìA`9·z™Íû^ÄÏ£¸Üº†7<¦ä™íóQ¢Ñ§¸4•õ»a~>/ ›=*?Žº~·Y—«û úhyfc£Þâ²´Ñâ?UžÆ²N‹ÿT£¸¼ïƒƒ•j.C¦,_Ãp»|©š‡æ}M€¿Gqé.íZ[_m|øhø¹—«ü®ºð¾`’ùøà—ñû?¿×>D­3|'Åå•yxëmYž= +÷G*“Š9™ ¿“áÈÉÜgü5·û¤p8Îø žÂž‘Óu<àg6°£G}Z£î—¶®úC塀ë#Ýðå—¶®ßãô…‚0â ŽŒRm~iØTÍ}/‰ùº_6g8f‰'V¹PÍ0ò‰U.¢¸4V“‡žª/|탞<´8Åe5p¦ó––›xˆE䙎ºÒf¸üíËöü©¯´N´WhÙž£—ŽÙ?ÃeçBf+Vsášf‘ÿ /Jqyp…Ï,­æ‰0‘Ï+P\šÊT›—õÜ óùT†£[Øöòº†»6Á—“^²á>øE—:ßií¯OƒÿÆp̘(èk¹ë˜®YÄ“—v¾ñàÕà^¬­Fö܇۾†âò™hõá5O˜îQ~ârõ§w:jî»0<`¸Ä¶ùúé'ÔÜ‹–° ŸÌp$˜-4÷E=÷ž9F‘Û*2Û.æÕ¬äöP¤jݼÚwR<[ëÚU¸b¨š'CD2>œâ2ï|ÅÝàvÚ'çæýDfa»6 Fqi¬6ürš{Q,±á÷Q\–u¾=ø}áÍŸîƒO¡xöη>¶º°ð 3é”û•±‡ãøÒ»0üL†c(Ôq~M‚{ùü‚G'°ÿZ«/Ã݈`8’ï=P{#¸“Ûœ ¨uÔþ‚ârë^®ÚZÍ=Ã]ð<ŠË ´X…)jî8~íSáE‚ã3Ѷîô_´Ü6V²6aø>†cmâ-Õ…÷m’ð6 G@ìWkÏW>?±°áÅåÖ¾j¥¾ÒúÑA!‡¯úâÒ·©s—ú¹gº…ø~ŠK¿îÖŸÔwÞŒˆ=¸õ'Ÿá8賩ÛEx˜9Ð9פ“å64¡‰n7ŠËr^—{?Qó„—@î¾.÷~FqiiWÿÒRÍ“~ÂxŠËŠØ–5x¬I§D&…|”jËŸâRmjµNh¹M4æµZ§)Ž¼Fçã ½8ÇQY8üÎðß(.]â —ÿ®æa€[gø!†#0ò«¯J鹓Èçå(.ÕæÈŸ3ô·Î‹*í‘?g2<Àé´“5wMc•÷ŽÐ…ã}· +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ÃçAŸöü$ŠËlaÞ½˜³JÅJgùÍÛäÝ{Åeø¿ïÒ/Ácm-´¿³¥)ð¯Ž#ØV4LËí¶J|"W4ŸÀp¬·½ôÞ,7Ÿž8 j »F±m/}€âÒÎ7yµ±š§Í`kR¯6£¸\ýÃCwê¹ÝŽ>”âÒP¿½}¯š§ÄTœÿ^÷àŠËß~žwªžû!¦¸ÏóJP\¦¸ÏŸïͲaž ¸\Ý™rõ‘ +ÀϤ¸ƒâ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½J3 Dv·^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€Ô¯ "&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çÄÚ„ë¸ìï°úoø ŠKÔÇ­Å_Ss›90þ:Ú8¤©«æa ŸÕ¦Å%ÖhÈ‘vúÂççârä +ŠË­û¢É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’2­V_É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€p7|Á“²”Ùvñ×ÕécS§áU(.]£{[Ÿ¢.|ÒöKÁ‹Q\ºF7SYÍÓ6û^âÈéTqšžÛø@ð—¿}o秴ÜnmÄ'roçgŽÝ:'QUÍ :Ôø¤3jPg¬L–ä{öÇXÝ°`Îê¾ÉÇ(.èQò¤ÿ£¡ÞxÑ †£[Xèã‹À3]£Ü/lÒ›Ï/¡¸|¤æ>qµ–› +ÄD†_CqdÇýx›š».²¬¾‡âÒ·yúÚjê[çQkóôµgQ\–° ¼ô—š'Mµ¹Ãq|üœ]w©y¸HT2g×0ŠK¥-sÎðL˜V"7·8è³Ì9‹).߸‰†h¹F¥ Aqù¾Oë/‹È^6P*NáíºŒ¾–â²22fz%·AbXD6¼ÅeZféYDá‘tÑðZ —iÞÖÇîYnCab RvUFªáßP\šÊªïÖrdž Eü.ŠË¶nÙKÔ…7¯,Vê–mEqi¨ïœRGÍMÑ1Szç”ú—Qd©調¾œâòÆí­ŠžUv ;÷ðßøNÄkP\:fOß²PËm§‰‰ž¾å ŠKzœŠ[^¡x>áXÞtR6Y‡éne†B¹:föwŽƒŒ‘†_Eq™!wO¼kÛ…åéh‡šáK).WïÖô®ÿÅÿkqÁþ.£‰ÖnM‡R\ +Oïÿ¨¹`QéžÞÏ:õ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’ßÂp|ß«T?ÜþŸc¼2¡=3çMT©^—áHÊ”øyªšûAthBâç Ç+ÓþÒ/„g—ïs¿°fš?jéf†c:}S15·Ï-/Eñlá[ÿU݃ìRfî[—4bœ¥Õú¯2%(.-í¸Äz-7}“@æç ÿ”âÒ!ŸÕ}Úì‚Z®e\û;'?Ù欧S\j]Á×+«yÂ|P’àÕŽÙ“7 ÏtÈsÿͯ‚(WçÉî$xtFê°á«„g7´æn¬ÒöSŠÝyÆÈpz˜ªZMÍM3%­”¬Ii¹,ev™z¹’g·ûàWQ\ªMýÎX—±‹Jq¦yÓ6q´´†/e8‚»|ó‘š»A +½‹.߬£¸üí‡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\‚âò·ï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…Œ·!{×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ü˜„£û߮Ƨ\®lÃg‰8çÿ­'?ñz øc"N•Ô[m¦±÷môaßÙUGpwYU<.àf:o@£ýü'¯ò§áÜAó ìçÇÙx9G%5 ¸(ñT¿ïr™¸> !JA­®3ë.šîšEÄéÑ»ËbsÝ ¤÷~þå¯wGtÅ׈8ÔWmà'Þ pèá¹»Ño§ïýòW øÜl)U|±ˆøík%¿ûaÓnÇ#5NbzÐ ;RÓ!âÔý¿ÔöN.W´æ Ú}Äç.N»P|Š„c˜÷õgØ<<Û'>UÂ1µñÅ´cü'¯gbÁOˆ8õßn8Ãæ–é„*~AÄ]d›ÛEÙ†Ú´…w|@\u3’±ÙRp}HŠ™L,¼ãc§l³v½Çæ®…u•ŠÇDœ¾¸mfò¹ç †ÝVa¶„cÈ«ÜÖ\nÅ\œ+ÔlUé÷Ø<®['àDÜE⛊O‘æ¿œ'è#õ¼Ô]`ÕƒÔËÿÁψ8-Çý»úq:ÀWÜK9…­ƒçÛ}—p|ï]ÁæžEàM Ÿ_À¿»ƒé<Å—ˆ8Õ2åïé(H<"B+ÞY±[çÒÖîn»´µ§ˆSãdêà<Žƒ>§Î/âqd›/EÙ†Þ{éÓ´TÉN„18#|2aüy|£ˆSY·ëôe‡}V JZ¼ŒˆSYW¥Õ6Oøeø1§<Ÿ§Ú¯\®cÅZâ<Õv‰8•i¯4ð û(Þ\Ä©‚½çw>wM°ÍÑ{I8­1k:àÖV|îÇlÃïq=Hß\H’mptúæEQš=ÉN¼m#ð âƒ$uÉØV>wiDñŽt¡ÒÉÃqTF‡y£ð˜9sAñ±"NŸLFé¾àá°OÊ¢RÝFÁˆ8 ¼ÔîIÜtðÐ(Õ„“ñ +ÀŸ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¶ÏÙ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×¹Ÿ1xBÄ©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îÜþ“×ÜC¶9.Ê6TI*Y܉´ñÁÕG*ãÈEÅoqQ/Ó€Íc®Y¢VªL# G¨Û&Ð,°«—¹Fh˜¹z³‹mÔ3ʯäsÏdÚå¿”pÌþWêp†ÍuËÊ¿ â4Ø蹿°yÌÆ€›â¿Š¸ƒ×VòâÌbàg—G넪ëbžƒhÛž].âáþ\œÍu 4$þ¹ZN³ù–eás‡*~½ˆcRéƒ#\®’náîÅWtbßÝ·Lôâ+:Š85Nê´½‰ÍU\øàeE<À£; ztÔ.ýarà%Ч¶D(*õu–>x|¡„cñ@•sÏGZ‚„ɘ]™UÎ pD]h–þñï\®’n"ÀW­ÖÏmœ±¢x'7'¼Ôªùû·Ç=KÔjÕœ â4à6ö—.lžp°ZñEœÊºâ›:°]8SÎòšÓÝË^(|-þžTx…XŠq™v¯(ÓR¼AÈ;á‚™T+úº˜ãa6°AÃÍ"NîV²y£øj Çîû»ö^nGäú Ëðì"N5ìÌ´/ÙÜwâ¨ãf¦­q§m³ô  ñb}´YzTÂqÂË[O6gsuF ßz²•ˆSa5§@6wôã@Ä)ñ[¯des½‡ÛÏ)âÔ¶ÉÕã&wÑ<ÈÕ£¬ˆS·`»MÜ ‡¼RVzƬw<¶ÞºŸ‰{N”Eàõ® +÷Š8ÍË\¬üoâ~8…ji¢¾Î²Lis±òh§Ò¦×›Ø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Êæ1 VÄ<ºÛ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Ù×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À ¥ð“-õïpsÀë–úDÜE¶É.Ê64ðÒ7ø€¸iëA`'£¬Xà‹8Õ2ž] àêT|‰ˆSI{ÓoÙÜ÷1…Qqã6Wß =:ÅwJ8¦ó^«ü¡ ñˆ©øG"ãë(zt”ø“uÐ0 —.DèþûªmƒÖ…â/Š8½÷å; ±yààÉ+^DÂñɼ4è.ÇcàÓDœ~ûŸié‚‹¶ [_—tñÏíEœšÄ›:wcs=ÔJO¾û}Ÿ°¹¥ªhü# ǦÎÆ÷?Ææÿµµ°ñý}DœfîÂN¼˜!nÅÙ.äæÅu½8ªeZä1¹.RÀ +Í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ÑÀÛÉž\~¯„£EÝáê£lîº>¢¨u¸ÚKÂ}ÌÇíšÈæ–æÎ\»&‰8MZu–<:×ð‡D/Žæe¦èî>x§æÁ¯c/J8Ø{EÄ©Qº¶È<â‰H¡ûõu–9+SñE"N5l«øÞ“ 'R°:²P n5®.qªãfvü–ËUëûß›»“w|›ˆÓØE‡+k؉׫‰ðu"îãÑ}-ytXÍ{uÌ,p'J¸ }Ç„öU|®ˆSìÌFÚÔé„ fRgÚðX ñëÊlü]ÂqæÂù‡ØܱMwàü‚£"NõûëO­;b)fú:ÇÑ‹¯?õµˆS%õ{Åúl³bØJü{ÅFŽù¸ŒÝ?är+°pj¡âÓ$¥^ØGkNœä’•”K•ÛÒ‡¼bñ¿s’Í}MbÅ‹8}qµªdsÕ¢õ /*âq<º9¢GGyþ•ÝKÀ£uFÔm<×Dye÷r§O¦ø(šw".qœ0ô!µm¶<ò$›«ïÝ1¼Ÿˆ›Ä7%žø´ìÃÀ#]Ô×éíBqð—$±}¶÷ÛËæž7FGß&¸{ Á:6Œ®-âTI•ZÜ—Í]U½ÇÁˆ8Öä{šÍ3بø³"žÀ‹Û-zqt÷y³QÒ&¤..Ôwb˜™7{‘ˆS'ôH÷YlnežÐz¤ûç"N¿ýôÁí(Çj8&Üù•CÙPÄiè#ߥŽ\®×6º†wqúd*¬ËæzÙ†^OÄi¬ò¯»ó¹‹1Åñ²Í9Q¶¡Âê®)h]$'‘Snp O91ñmîšrJÄ©aVkkQ.×»60ÔYkk §ßž?˜ÀN¼>õ SÄ)Û\úx´° Žž!DÌÅ¡k$Ñ2ƒB¸{2t@êÂJ]ç%°æ$(´Zć|U5ðHÁ¸4|ìV¼¦ˆSó ø(ÚðâDœ\ÐAÔ=!KæÊÊåzk!È•Ì•EÄ-$>Ÿ(ñ4/óÅŒÁ£mêtt1Êû‹?‹8õe~íF­Nrx?u¦[ªûOÍÂæ…¾ÜÍæ®…õóŠïpÔ°¹ŠÁõñ2 ðÒŽpÖÕŠ=,àØ«ë-áâÞ‘Ÿÿèâ™=©ùw‰xÙ¦¥$Û` úuiýÁÃÉ…Ô…UÜ< }(>PÂi§R“K¿MfsËÄÞW|‘ˆSis౯Ù\=yt…<¶VÂqj¡]¿.Ÿ[fwž]ÿN G¹ƒ+²¹j ¨<¸±ŠˆS5Q>ûT6w=©ÊgŸ&âôè~©„ï=ÜJ¡#†"Cƒü—JýDœÚu‹»ŸÍ]ÓžW¼³„㸊û¦JOæľi"NeÝ—ï4tøæ1—Xñ&"N¹®^)”´ÉiÔt`‡Í(ð="NEå†bh%'Rs}Ú…‹X^ŠåqÚûøÔí\®ÿ`Äìñ©»Dœê÷ãm±yÂÁÞÿŒÍás3j¤øl§Nè鱗yÌFw@ñé"îâÑÕ=:zïóûÐj79±’r˜W_ç&çd~Ÿö"N‘SZó¹mÆç Li'â4jÔ|ú@6WÍqŒ×ÍÎËÿí: ~¯ˆÛH|QâéƒÝþ¡I|Ø LYTêë +^¶ØQ±âe‡_–ͽÌh;ü[$ß{®¡ÕÙÜõT‘¹†Z"N£¥ß®Åæªi„™ÐÒo×qúdòþø6—ë9)´çÓgs½æÅNÄiåCÖÙ Ù¿ÝÉ ²šuöRwðè^=:*ërhá„Nç¥n¹:J©å¾GÄ©°Ve—ëÎXk”sÜ`6W]),ËÌ9î) Çä°*³E‰Ç’ÔÜ«Á¨\a¼÷¹×Š8I96–Í= #/âTË|¹!9 œÐÑÍ#, ¯sl<ù/7|)áØ7Q¸Æ6ëÈFàÇDœÊºN‹sw"M*éëT%‰y™N‹s‹8=ºyõ¾qÌÇÕ[/áôÞ›Þ”·x¤ LÉë|”67åí&â4ô1ã¦6lîùâ×͸é~§6m­Kß]‹ÿc‡š¾N@d órï®ÏMÄ`ã/ s‰8Õqe¾,Ïþíªi‚°He¾¬,à6Ö¶-ó?ñžùdÚ–ùYÄi.²o•Mlž°Ìɼ}«lñ8²ÍZQ¶A®;[•¸vÿSM&&’áëp²ÖÙ"N‰o™m8xxWªjBßFýÁÜDËl#Dœßµe p'J'TßFçü^§vg‘Ílî»æt›Eþ#á4N›ñÞ‡·÷"m¯Ó×ù¶¡Î÷>¬-∖¹:'¸ea¤æêà”ÒÕyDœ^\{¹\½¸Öœ(pPÄéîý'¼Îæ¾CÝÂÛŽJª|b›Û6V÷)¾HÄ©A¾ü0ÿÉûb}(~@Ä© .—ŸÛØ­ø GúÝÆÄ}+ÊÂÈDòØôeJ¿ÛTÂ÷ ×y4N|'J¶„žo'|Ã;‹8Ôµ/csÏ2‡ãÔZ¼BÂ1Vùð݉îîƒ÷q³:Õ ?ñX¤©Ìð:3À®xš„›ã&Kdó¸‹SNEÄ©¬;8® +Ÿ[ˆÑš‘ó•×âÿ£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<)¾Nõ¥°øþ|÷K8Ì œµ‚Ï+“-âÔºp ¢aØÑ:bɘÐ.ø§÷¾ý;t‘™õuªm‚¨JÛ¿Û"ât÷%u°M;¹ï-ÙRNÅõ„‰ï(yHÄ©m“knâuãÞAÄ©¸höüþ£óc˜köü÷ŽæÁÕ™Ÿ±¹o™­WgÎq5zbçI6w\|ø|î9&‚Üð7þq‰?&J¯"âôäæ Ø\Gˆ×qª¤ŠZ +nGä:J*ÞûŽ²×³¹>üŽú°;Ê\q ‰Ÿ/J< ´>øMmØ'Ôl½'Ôv ß,âTÎÏky<ÒÒD}—¹éc^˃"Në¨ÏíšÀåú‡ÈB»>qZO;fà#ìÄë‰xO§vÝëo~ÅO¼ $žQ==+ÿÉëXààYDœ~ûÎ7²¯wê'ÀŸ–p y½þærÉ££Öf_®ØJÜÖÒ×9˜›P|›ˆS9·íÏl®ä8r1סÝ\®zræX¢\‡vŠ¸Iü&Qâ©q’vµ¸%P‰æž‡pŠq§]<°#›Çõ© àDœrÝ] N¨Eàú:Ë2ÿ³èo§ú½þìýàÿ«3òÏî€,¬£Bƒqjœtš›ÿZü%>lž^PÄé·¯Úƒ»û‘|L„±óÐýW<ˆSaõÙõÀ#m¯Ó\EöÀë‹85Ìê¯CQqYöÕ¡ØÀ¿’p 6æè~\,bÓHꃃçqúâÊÎXÀ澋0§Í®öoÅæŽgŽ\¼Ú¿¹ˆÓ‹kÙò›{–9C­eËÓ"NM£%Y +H8^–d),áXCžóé¹ü÷î:L”óé…"n² ÿî:ÛP-Óí_—ˆÇ#ø˜ƒr&°æ¤Û3׉8•uÖ1tãaÓ(Õ6êð:×w VÄéÉ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ºÊÿ`-³70­rV§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žÓØ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Ÿ[m³,ìâô:Å¿’p¬âÞûzV>·1šñZëûùÜDYQ¼­ˆÓô}ÎO¿esW5Ì|ðïDœ:b_<ÖžÍíyÅ;Š8Ý}ùšÓln¹A[¾æŒˆ;È6YDÙ††¸œÝC<m9®Þ/â ›âûEœî~ÜmÅæ–…ð8Šß+ᘾÆæai ^HÄ)Ïé÷›{f'²âŠ85JëŒnqØ'®ëwœ;Pgts Ç:«…i‚»Û1üö…i‚»›ÀÂ9ìÖ×âÿ\¨#{h)~ˆÓ÷^dgVvâ¾Y½_dg§¶gí\nëC|ðÝ"N-«%O²·b8f4GÉ3"N/®âgÕøÙFµÇ}ð[Eœª‰+i¯DêŒë€Î4ze`I§öîs=À£-œÐá¬3©Ôã…nlîøhU*ÞYÄ-$þaQ⩸Hœmþ¿¶þ/n;–‰cv{ë’l®¾·L^\Ä$¾™(ñÔ$îÑf1ñät^êá>“;ÔÿRÂѦ-܈ö +¹É)¹>Êò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ÅÅ#ý'ž\Àç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ï-á˜ÚÈ_t xÄf¡ºÎÃò<Å׉8UcnâòdÐq*iGáßÝ5¡û;Œ<(âôÛ‹äìÍN|ÜÅ:jÅûŠ¸‡G÷ƒèÑÑ{â$*è b“XoÚ´ÏùƒÍ½ÌrÏ9,âÔi¿í ŸûqDÓj¿í¨„cñÀ‰“O‹Õ2û-%i+qxccccƾáEEÜ/,â”ëöoxÍ]3ÿ®ø["žÀ£[,J<½¸·Ö Ø8Ièƒÿaæ­5Oˆ8Û¼Y¶5—ëPÞ¶áíDœ +«= ¸Ù¼¿§Á§Ò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 ø§ÎHŽú/ƒGÙø@×Y8Ñ)Gý‘ŽLûÉþB\®šfXŠœÑÊ[ÍæqßŘU+o¥ˆS-óìºl®ß¼ ^PÄ©mÿ}#Ÿ{V°Ûñ8^\~Ñ‹£÷^ç¶ÜàQ¶œ„·‰¹8W(#ËòõlîëÐàkEÜAâsˆOÙæQß{¤@âáu– ¢øS"Nï}d÷nîaŒzd÷î"NìÏ…Z³¹úå8KëçBíDœZ;‹lñøN§©æ+àsUÚÄÁ7‹8Õ°+Žäcó¸…•Šß âôâÊWÎæY¨øH Ç”ÖЃ&ÓFÙð^gû DÛz°‡ˆSýþì¼çÙ\Ÿ8î‚¿ âô½?á°yLO¢'Ÿü ã–ð¹ÀLè ãˆx€Ä×%>ùÛ›\nˆ\)PIxíÇÐßÔ¦4ŸëÝ à%DÜBâû‰OÙ¦}¯!Ä“‹Ródwü§ÞÄ«O_Çåú 4¬â~õél"Žekð¹ ¡¸%â”ø½Ô£0æ)– ÓuˆÑªøt ÇjÞ£{¿dò0d‚m*WP±º¯P¹4§Äo«WýÛ}s`„â5EÜÅ£[*ztÔ¶É5~x”ámô¾ šTÚ}æ—‡µ¡~PÄƼWg~âý8Vqçèõ„c|¾]Ïû؉÷õZ'ðö"N‰ŸVúvâ–i)~£ˆS-sqÎvâ]•þøew°$õµi=ÙÜsÒYñÞ"Ç'³FòÉ`ú-Yn")XGxã¡a¦x9 ÇyÉëØÜÖ™²›^$)@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÷-ÌA—øvªˆÓ'sÃσˆ‡S©—¬8:ÒÆçZÄé“iÕ¿–€£=¯xLÄ©°ZÓ%mr yê*2aÇlsVæšEœš…¹/p3©”ëðbÑÝ)וûôQ6·<fq¾Wu6·m3Ôy¾W§\·|ÉÏ\®#áà½/_²UÄ]<º‡E.Ù¶iòw~jœÐa)¹KA^‰¸NÂE­T“t6·§Ï—jRMÄ©–¹iJ>7ë*Ï&â4JÜ4í_àÑ–"‡×™–UÓ´çDœN\:±€Íõæ¾ø §®ÐÅ‘¯€;Q¹..<ð‹8´h™ñà}~ÉàÿqJ¼»ý&6w½À5¼¬ˆSžoòì}|îþD7$wÇêO'J<5Ìêܵ…ÍË´¨ëÜõ‹ˆSAýlë=lîÛfvàÙÖ¿‹85^ ›[¾Y¢öêøŠ"N…Õ¬ÓÝ/ÎÄ%žuº»ˆSâ÷ç+ÅÿâL›Vñ›EÜÅ'sè“¡JÊŸšÜŽp¼lx`ÖŸšKÄiädð;ÛØ\ïˆ ÀwI8}qM‡kËæŽç!îÁðc÷‹86ï?ôÿÑY>ÊùMý âˆþø}l®F&Àù¿]Ÿ‘Jy¾í‘ëùÜGý®8?Ó*ŽmWÜÃÏ6z”¼ˆÓ“¿:e» Ób]¥â;D]¡iŸómâÛäš6WÄ©¸(”¥#ÿ“q2BñÎ"Nw/•¾ˆŸxÏ/•¾DÂD½ÃùÇCn[v¤3ú:½DÎBÄ)Û|?±>Ÿ«÷€7qöIO›y¥š¾‡ +]«ûÒÓ‰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?Ÿ+âôÁþúÍN>w,tÄ~ýf·ˆÈ6EÙ†òü¡§ot,‘¾.îc¹y‘Ù§Ø\Ÿ>oƒÿ)áôä›N>ÕžÍë¿øŽÕûǺ}ËæªU‡6í±n߉8}qé¯ÝÆæ1×,ˆMí.§O¦‡ÝƒÍ==ÿÞ[ÂéÉgŒì𠛇{(Á7Š¸‹O&MôÉPӨج3Äcº Çô(1Š‹b³.ˆ8UR}rÎq|ž„cfä«ŽƒÛ¹þ‹Ä.½r™Íu«2¿(â4È|²Vn6·2£ëœ¬•_Äé{÷sÿÑépsà…Dœ:b?ý2œÿèlÌ*þ’ˆSý~å®®üG§Ú`.øƒ"î#Ó^eZzò{^xŒx\/”ŠÄÑqï#âôÅ¥½þ›«O+^Ò^?!àê¸éöÛQ‰…×9Ž›œ~ဈӲ µÛp¹^ +Œ—¯ú]`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ýó3­oâÛºžýÞ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žÚ}÷¸>ï"âTÚÔ^ÕƒÍ=Ñ°ï-âTI5ØWSòä·°Á>WÄ©¬;2{›Ç\w?2{‹ˆÓ4î÷ë—°³^_.âTÒn©Ñ„Ï}ô¤o&âæ“ás•zl=hßÝXÊóïçüxrvÊI%}F¨*,ðCŽ£6‡_:)ˆzxžY¿ â”ç{-û͇ß5[“ñ3Ÿ[£ø"Nt»ž«ü¿9ýVÄ©A>æÉ{Ù<ŒFÞNÄ©~Ï1­>Ÿg†³Î1­±ˆ{È6{EÙ†Æ*[x“À¨\^€(ápëØe›{®9Š«c—ïEqÌŠwcs½›6HÄ©ûŸ¾¬(?ñ™uú²R"NƒÌ“»ÒÆF;¹<åð~8‡uV?½ÛŽÍcæ€WÅ[‹8½¸¾§ê²¹ë[XOÛ÷Ô"îàÑÍ=:zò²ŒtX€Ý2«÷[Ÿ›Ïæz¢ásDœZ•m±OŠÁ= þœ„cJë†W{²¹ŽMá‚?.âôâÆ7*ÂæqÇœø0¾QqwmFŠ² ½¸GM'‹tœ\”‰/š!â4x<[3 ÇâãÙZˆ8%>cŒI|8N›ºû¯ƒ˜c=­â³Eœ'ý?›Æå¶cB)ÎN|ÈѺ(øŸ;žmx/§öüø€ö +ÙñH!5ëí¼àÅD.˜A,¯s^p9i6s÷m|îz¶áõDœšñ´·Ù<< ;É/ö>+à–gø) Gt}6wìV÷õè\KÄ©U¹ú¥…ü'¯ž]|‰ˆSyôB 6Wù±£î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”ø|½„c\Ö5˜ˆîR_ç˜ÆIÖ5çEœžüæ_ë±¹Þ±B.GÍnü»{Ø+¤xG„Ø;³¹­—Ä‚7•pLa?}ñAâÇðWEœV>Ìÿømþ‹óÌfÞùOqâ^Yªµ€#è¢âm%ßûæ_oeZzt ¡ÀÂNradꦑº.3XƒGò‰8Õq9íN|n–"+ÞUÄé½h쀇Ã>©‡ûâZc€ý@ãš"NQþ®ø>Ÿ»87PñÏ%tõ {¹\˜á€×ê~qªaGm˜ÏO¼ƒó _,âôâöŸ_ÏO¼gFöŸÿ^Ä)Ó¾·¨›;^ #fïáp&§r>– `ÚNl3BqèÎj™Xâe G5ñÞÁÙà‘ŽÒN^gÚ6ïœ#âôÞ þ‹Í=;CN ¾(âTT6\}þZüŸÁ6Õuº‚ƒ_óîÿ_N­‹,G泯zÀ8¡õ\ž"€÷qê¯ëõ ›«ŽjØu½fJ8Æ.²áç:x=˜›ŸÂ 9ÉE¡)·(¨J»ïó¿*â”m¦LÊä‰p• þ¬ˆSƒ|\1ô¤º“å¤`××arAñn"ŽG×z›[N@%­â£Eœ¾¸ÊÌãr=‡/îØØ<ðÌ„û#·ˆHü¢ÄÓ'ÓdÁ~pGq7uÎÿ@Ä)×½:a6›ë,oƒÏqjÏ­÷-¸­yÊÉ}ßÂÝÇÖûNÄ© \lg6OX&r`±ýEœrÝ’1 $œ>Å‹8 ufÛÔœËu,-TÐÙ6µp3 \vzo>·1z x?§l³|}k6÷^Ä©´)öQ 6×a o-âTE^ê3„Ï=³(ôRŸA"N]¡1Ž‚;Q¹çžá'DœºB'%Ø\uB1ÿ~qR] ÇuÑÊ°yÌ6­Ê¢”qztû«t$îè®ÝÿÓþÇÀ‹¾.pL@éýU:‹8=ºCéw²yÜc˜÷PzC§r~Öê;®ÅÿÇ£Ó×™­F³V7ñäoožeìp;¡y ¯ ,Ì +)>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¦Nê!ztÔ¶)¾ò{â¾eàE]§eB¶Z[ ñ¹cbq×ÚZ@ |òÀØ<ð¬1›<ð'DZƒ[Žp¹zA&,RÙ-xcVµþ:Àæª#…L[ë¯Ã"N¿ý£½ØÜò}„·ýè@o Çâå+.³¹í˜=#ËW^'àˆñÒlÿïùÙÆT‘Š?(â>ØïD,Ôyæ¶'®ãù§öÑ·ÑÇM&À;J8ºÝ?ð˜<N"à„cbåĹ>àáÀKêf¡>´ÀB܃lüÄæá*3ðMŽÈÀM›_ìÎO¼9WHñž"NwoÙòw6ll·Qü°ˆS{~n‰ÎlžpslA‰n"Nnûå=\®¥bÔhûå"NÐ6Ãòð³c£´i3¬€ˆÓ7sC%É'ƒò37Tñ>ØÇ$çŒZ܉úäõ9` ð2Ž¥ 9j]ÏæzC5JóÖp×å§ã$Cö¦¾»ú]ñ×ÜE¹}oþowã¶á•%Ó¸§û–ç?:G´(^IÄ©†Í‘¸,zq”øû£׃Nä걩?6x/§†Ù±úeØ\5ŒPÒÞzsG6W¹kNn½¹­ˆÓÛ"ûh6W¹›Â¤(>FÄ© >™˜$á˜@?™ø@Ä6¶×q¸>Ýß+âqd›R¢lCõûöC¹ˆá`cj®£¤úé¼ýP>§ß~ËÈvÄáp_ê².\šˆL{ËÈûEãóßÞ-áX_ç›!º;5NÛ ƒÛц:õub}$¶qªßßv/›[~¹îíamDœ*èûäsýoðþ"Nß{×ñ¨¤Âå::b ;æ"2°âe$«÷;çÏæzoø›"N-êS]es½³ªÈÏædesÏ¡UùÙœ,"Nï}Èkåø‰÷EMñŠ"žÀ£{PòèpÕu9~Ir;\(•º¸ÐaeÎŒ\—〈SI» w‚Ï}Ô2Š×qú훞í+á‡uË–Ý"îƒoq‰LÄ©¸ÈñÞðhÃ>ÉØ ?«ˆÓ£;\¸!›«ÒKÐn*áhv©Z–Ÿx7*²KÕŠ"Nì'»>cs_%>>[Ä©yðyÁ?ùÎÆQ›ŠŸqj=rŒúq¶¸¥ +¶™¼Î¶ ¯&â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èÅcŽ-ä?fàÑ%—¨¥æžª"qþ{F…šø\òþ„ˆÓ£Ë·ö66OdnhÍ·¶žˆÓ“/Ü£Àµø?WïëHZž /…{q/®œäÅ!ÜeÛ1z.Y‰PTú¶Ÿ¹_¦Îíw‹8=º·* ærVì¼Ç®²ïž]GñËŽE¡Eó­æ'Þ °Æ¬h¾µn✼Ui€èÑ™Ø}—ë¤`·“Ëu<ð«"NôMÕk¸‹ l7Uw$K‘{¤£a.]ˆPPÇ’E5x-§v]í;ods]ÁÆÁoqº{â‡R\®Ê:3ø¡ŒˆS½ùÉìć{’ülÛmln;ص¡øVÇö7Þ%žFË‘“péB„Ž˜º‡ú]ñCŽíó¥»fsOq¼¨ˆS5±º¾÷¸i +[]ø˜VÜqª&Ž¼×NÀÍšÒ#ïuqjÛX³o»B©+è¸sÂ(ñüµØ\¥Èæψ‰8Ë:]âr+¡*xüªˆc·NûìÄǼ8"…Îk?PÄ)Ó^ÉÓ‚ÿâ, ÙæJžV"n²ÍÍ’lƒi¹h'²„]à”[NÂ)äíù¹Ž‹8•´ ~˜mш>ÄÛu±saߌ߸\}qˆÅ­ø§<ýG9Ù<¡†çqªßÓÏNæsÏ'~vª„ã¤Î½?5à¿8ß,AßûÓÝŽEà¹N÷gsÛEh_ʼn¸LûŽ(Ó"òÀ“kˆ'—¬¤òJ Ã–äkEgçýµšÍõ±8ÿîŠc]庌áŽ}-v?ÂåªmPA­øC"Ž»Ÿ`sÕƒÆ's±û_"Nm›™{²yÂñ°íbæÆÞîš÷œèÅQI[â‡làŽ©ªnãî+ñC. G%•ka:›»>ÂY+^I‘isÖþ–Íõ¹6øz§æAþÕ3ø‰·p<â³D¡_YÆçæ`_ÅWŠ8U‘8Àæ^æúºñdâ›\~óE>·‘ëMÄ©E}57Më8è@ú(0âyrˆxòÑ5¿Á­Âå¶å¡ V¼ºˆcĬQg6ëó2Á”pìHµú#6wõP-ø"N̓ß[-aóÌ•Š/qºû»“}ÇT¦âˆSG¬j‘WùÜ°ºj‘ñ"Ž:nóbGÄ Å¿qztÛ÷ÒP§.”JÝ(U',Ï5<&âÔ²ú×áqàv¤%+úsQ…ºnË).×QAèÅ)~\Ä©¨¼%ïy~âA™nÉ{YÄéîËûÕds½–ØwEÜÅ‹#zqTÃŽ¯ù)¸i¨SïJôp²â³DœF‰Ï/YËæáH-øw"N-«{åä'Þ2‹ }ŠÍã~<“÷ñŸU”xzï“^CY—\,”r·¾Î2G2Mzm™ˆÓ{¯Sí0x´E#úœPß7S™ÕŽ‰8˜Ï»ln¹æ”ع lîûÌÄÎý-âo‰OÍÂÖ³©êD\º ú´°@NñÞ"Ny>÷±JlîúXSªxºˆÓ{÷Æ®$>†^¤7v£ˆÓ‹ëÔ¡—[qý÷Œ}oæfó„k¦uö½™MÄ)ÛtŸw†ÿäõpàDœ—=Ÿ—ÿämgç-{þ§»ŸÜWFðèÌúù“û*‹85‰›?_›øÿZåÕüùz"N%í³­Öñoa +[ñ "Nl¶1ÃÙ§lsãØÕlnù„²úœâß]U˜Dîs\Ä-$þ+Q⩨üàšs".˜Ñ§UzØ ¬øÓ"NÙæ•Å¿r¹•ð°•Xñ]"ŽsBò»e"Èe”nóÿ·gÖq¥Û<$âTËì[ñDÄé“ÉÛu\rq`j®®³ÍѺy|$áèM\Gu;˜rÈK_gÙX½uÞ§–UÑIÃÁ£m¯ ¯Ã^!ÅGˆ8Õq…;Œäs+FwW|Œˆ#:n¬›;6Úu-ŒbsÏ3§´lð²ˆÓ[°Ø|.·k_,âTÒ–c&;ñ¶Ã0où7æˆ8õe¬Ÿv³Ÿ°L|ë§}"Ne]³×ßåg×DËlöúû"NlË®Ïñ_\æ†Ö–]_q*¨‹æ»*yq†çÏ*âTÖ5ùtÿ“ÑAÁ÷‹8µ*_Ê^Í}´â5EC^¯ç?:ÇÏ)žMÄ©]÷éUvIFUJ€¿*á¨",nÍN¼ªÝqÖÅmEœžüLã2÷c˜ ¼Òj£ˆc€=VYTIQI›ö÷tâv´-ä®F6ü3§ï½ýãuÀíHË2ÝðŒ±ÚþñÛDœÞû¦“E­ÊDœjØ^GobsÛ7Ë2{-+âÔ<±3›ëÞ€^@Ä©ŽÛ]k!Ÿ{–ií®µTÄ)×ý¸©—[ ×w Oqš ôwLågs&rÆŸYˉ~{~³ˆSâ •}–Ÿë<sR…Êp³Vó9ì'¨×Ÿ/â ¼¸)‚gvm¬¾U˜õtìÒp¸ïÚÝÀäu¾‡eŠgˆ8õa³}÷q'ÂrºÎ6ó°Ù¾›,âÔ—É}˜Ï=ßô¤rþPÄiäž×ØÜ1Gï)þ–ˆS‹ºûœ2lngÆ`ï>§¼ˆÓùóWÒù‰wX¦õü•jŽ¹‰)¿}Àq&&³âK8¶o+p¹.¨mÃk‹85N²uØKܵR/UJÞF¼P«2[ói"nƒÏq‰ß.âTX,õ›Çü8ŽP/Xê§Ò&×”+àBÑu¶Õ>¹>¸^Ä)ñ+›wærÕžãdÿóïÙ\™|ƒˆ'«È&羓ÍcŽŸÉ›ˆ8]ÔÌtƒs…ï&âôÁV+7†ýÞ­Ì9©jå^ñ8²Í¢lCÅ»ˆ8•6¿{ëØ<\w¾QÄ©’j—¨JÜ ;à×n&¯³2 µKÔqÊ´ßÝ^„ÍÃYhðâ"Nü Óãlî¹æƒ]˜îˆ85ÞzˆÍm'@|›7‡q XÏ]Ó¯=Ðqš¹Tº‚ˆà•ECE>‘p4^*2CÄ)Óvo=†Ï=³º¯{ëqŽvH×›;®‡ù¸!]ëŠ8}qéç¿  ·¦n”Æô¶ Ä|H??OÄi̪Nß·Ø\eYtÄêô}WÄ©ÿžkzQ6yØJܼà’~üßná7Å{‹8¥Ó I¦QϽ¯€Gƒ–¼Îõb˜¾ï¹wœˆS-³èñ©l®ªgL¤æÞø*›;™qJsoäÿvÍ©jïm)øíÄÚ{ïq”uÕ—°¹¯þeø +áÅ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ݘ¶:ü²ˆc +»èe>·bˆé´»Øõ"NõæOÞesßr°Åló'ï‹8•6>~”x"6Wå´mxA§/.çC·±y\Oeƒ×q|øfiS6w|Ú÷›¥Dœ>Ø÷.QQ©2ð¢gÐ]´*3´|„ÍõFfÃñ‰¿G”xª"ÿ¹/xxäbÊG/ëà½?þóc"NU¤—íO>·b8+seçl®¾8 ó®ì|³ˆÓw¤Dy69föH‰Ê"îâÑý!ztÔ¶™9¹ÎŽˆ,yzp¸ûÌyˆ8ÝýÒ;ÙÜuâUñ½"NóqŽþnGävÌDþW|ŸˆS%µòÆ‘lî{fÙÊG‹8eÚ]=Ÿàs½Û| ˆÓ‹+v€Ö]Øáô}„L«®³HñÛ%óï;«ì'RS6l=kÆçwVùMÄQÃf˜»;‘:#á†óÅåÌØ&âTÒN½•¨?‘&l}À +V(þ©ˆSA½ºJ'ðaR’\7Kðn"NcÔî ¸ÜŽYh](ÞXÄéƒ Ê5gsßÁö:Å[‰8•6‹gìcsÏ„öUü€ˆSëâöü ÙÜñLôÛó/qŒœLÌÆæªXÃBèš³H8FÈÿåö!î[©ÌÒu:Ä,øŽ–Õá,¿‚‡ÍÂÔ…•ºNÇÛÿM±½.­Ù6W,ÇMkvHÄ)Ûäëù.›Ûfõ¾âï xŒºÀͳïä?:Ç#€|öûEœæaßzi:¸•ÇDIUüCÇÎKiQ¨NeFà1=(Šio–Ö”p ´Þ~j›~<“ÿ(âôèV4BÓ(±iÓ…ÖÓ¾¸t›ë˜Ì ðßDœŠÊ¯{l®Êy¬=ÈñzBÀÍ9à+õ=:ZÁîï¦uVvr€ýÚ[ÂëþëD§Œ‡þÓ•ÍÕ?™¼“„ã8ªê?öâò0.±á}ÜšppÁ þ£sM@ªƒ f‰85‰+ßÒŽÏýæe*ßÒAÂñ½×˜Z›ýèËÁÈI©·‹8öŒì®"É´È6×½˜•x8µ¡A×Wº†ç’p4¦~5–Íõ™‰.øhO޽Ʌ²ŸƒGd¶õ»ë¾\Ä“‰o^¸Ñ=lî›=¡Šß'âTÒžø)›«ö4JÚ³g‰8õ&â?:ß2ámZ%âTÚ̽)Ææª Œ]Øsoª%áØzp¦âZ6·3ï~¦â ÇwzÑ“ÄII^§˜uÀ‹8ÏwlyW’;–•:äcò:ÛìýW¼‘ˆÓ{?ðÆfp;õVbº.3ìá7¶ˆ8½÷c·4ær+ð°sAñ"NŸÌ”7—G¶™¼ç8¶á+Dœ*©A_ÓL¨“hM¹ÝF]w\tÄ}ý²ˆS£ôéB³ÁíÔÇ +'¯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"ÿPÂ1NÛÔ*ÅåªánV¸5µŠJ8žüUžw"Mm„ÇU hƒâÏŠ8½¸iZljElÅT'ë.š-t+›Çl“m– ª&âˆ~¿h*›ëé |šˆSÓhF…Ë¢GGÕÄá´éà ‡¼"tFôê}¬5jv2ûj6×ça¹à«DÜ$¾‰(ñôÅÉÓ–xr)rj„]`¼ƒˆSw vŸßÜÃo¯Ýg¿ˆSýþø‹›E‰À·H8•u͆UÅ‹ ¢mŸ¯Ã"pÅ[ˆ85NÞùµ3—ë «ˆéTýÊÃŽÉDÅ»Š¸ƒÄß/à˜ÈÈ¿  x´íóN¸æÇ +ç?WÍã¾9W(ÿ¹t§õ¹Ø\õe,ÃqÊóÃœÊt6zЊOq/®”èÅQ«ò£1hF\†­®SìøhÌ §Z¦yÑ,ùÜ3ªxg§ZæÁ}¨ß#´†!ÍžÐ÷Ý*âTÚ,_”‡Íõ,p^@±ÕèàÙcln™Z?,ât÷ÖõÎó‡ÐMÝ;ßgsÏœ«øŽ˜Ì­ëý%J< 6öœL›û\+Â!æÉëìÌо='oqšÒÊ—m+›gYUüW§nà݃ +‚‡‘”ƒ:&³ºŒ¦ïûîœÄå: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œ>™7¡$âôÛûemÊå:þ¼cx#§G·)Ñ<îK5®oãøfáĦÄý"N‰¿ÿÈân¸Í*õ'ã†Ç”àßK86ó>œ­!›»™çE>œín GùÅѹ< qà‚¿,â”ç+<_ŽxÏóу®ð|§’¶ðð©Ä=+J7P_§C^&À§K8:àO Lgrõ#}lúP¼ºˆÓ‹+õö½à‘…êÛÄ]³#µÔÛ-Dœr]‰¿>årݬCŒÖÍqj”+ÿ6;ñ ÛA-“V?+ûÅô´»®Š¸…Ä¿!J<"À÷mîDêÔ· <äùf§fs× 07qúØH§O¦ró¾Çq•›qºûÔéKøÎ6ÇQM¾BÄu¡ï¢G+‡¼ƒ*Ò·¦..|=n‚²nÈ;%+ZÞ±úÿ‘v'P[MíÿÀKó Aó¤yNñ>÷­A¥H=OR¤y¢y.Š Ñ R*ÍшDˆDIŠÒœ&Q4‘BiÒðßûÜ×÷<þ¿×rÎuùýÖò®õº?ïÙÏ>ûìy_ÜŒ`VÿNï§y›ŸŸdsÕ1~\Âßfäî~üÄÛ¸àUñ"N9ôY“ÍõÖwEœªÊÇÞ9Ìæ1Ä(~DÄM›u’b\­Û~*ñ˜ÞºANÿ.mQIñ"Žh>ÿ7žñoùÛÐÁ7Š8%~b³WÁº5,ñ¦m¸TQ7-0û›;: àgEœ*êA¿å'ÞƆXÅJ8ZØûîïÆçfEí¾û{ˆx/n¦èÅQ·ð×2 ‰{F”1ÉÇ$pjã×2‹EœúóÍšþÄ枃 rŠŸqj"wçµÀÍ(‡:õcfpZgw^WÄiîÂZS™Í=+¸ÚZSMÄ©…½~{ðÞ­(¥ôcÔQÐg\oÃ涃½Š? âÔ9i¸ïy6ׇ}ðÑ"N3f/~Ü•Í]}z¼§„£CþTáÃlspðAñ£"î ØÌ•âî4øIâq#ü‚×äïT·3¥?-âô½—J‡Y£x¤ð8úw–“À¹ÈR´M‹Éº¿ËgUØ\_ðj"Nï}y«÷Ù\¯æ¹à«Eœ>ØöwárU×àÒÅq*6ƒÚf'žˆ"FýNß„éýAms‰8 ¿XRÍý&™óßN+ÄçªGî€çñ ñ•E‰§÷~W‰dÐKG‰ŠR]¨ßy6&Ø›L˜³šÍUU…ô„9ˆ¸‰Äg%žžÞ¹Ý)ðH—œú¿34šPüW§ÕÿåE÷±¹úëißEÓlã7±¹mÅÒø§ù“úýÿß±ŒúJ:JÝ“Š85R‹' àgÃ`dñ¤GDÜ‹Û-zq¸µ°äÄMÜàÂUïÑÆ]ŠOqª¬Îô¤ž•™\P O¼åÏyàãDœèïýîQ€ë­:ziüŒˆÓzùGØ<žv¤tùÇEœFg{£¦µ¢uÌL}< B)žAÄiò¡jN|2v´Ž™¿µ!#DÄé½÷ê×<ÒVdý;ÛBÖ)ÞUÄ©Ìoò±¹L>(ÞDÄéoß߬Կñ¨ëlsÁ½ÀÍÊŠ8ÍÏ_ÈÕŸx½¼“ˆSuqiÝÝ\®ƒ÷£O{i]c§B[øÉ’ìÄ».–ó/'â4†m5¡ ›ëxÚTlre;ÃÏy{NÿYÄ©WÙì¾µüœ7âèY5»ïsw‘uùDYG½‹nÛÐÆ9‘6ÿ'‡ûß'âôÉ ¸0†ÍýMfàcEœ>™Ùë®3¹±javöúô"NmÜ›äg‰ó°Š·qJüšâÜg›qÇCHç5Ź/.É©¢žÝ¢x´e\ÓI^ÊLKZËW±¹éw.”X¾RÄé‹«tòs~âæç+üRÄ©?_oÏ..7\+Ž±z{¾qú`sïhÅÏ:qJo'âTÏ·~VÀm“ÖÏvñ +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˜¯Û\·ƒCóFÖqê”Æv|Î殓À.î­÷|Í涧¿]ñîáÞê;SÜDd¡ê;›I8öÓÆv|&Ê:zï—ÒNf+¹:õ¡~癸SIñu"NÍD…î…Ø î/¤†=ÓˆðõŠ?#âÔHíE[užDYÆUܳçDñÛEœ^\õ{÷‚G;ܧóNu ~PÄé½' +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œè«n|P¼‚ˆSmón“\nØÁ¦Ð” 9òñŸnÄŒ€çq‰/"J<ýíGk¢Gí/&†/ß[úT¦C³Ä)çf¶p!bÎÍl-â´ +\*ÝÛ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¹¡oÌz‚ýt#mýýYCëï)Åg½ÉçFã¥ø¬wDœž>x×@AÖè”Þ5XÄé“qŸ(Ãç¢*)^N±÷ Ã²¢bC=«Vź€G:ØhûaÐ⨨[ë(âTUvjûq׈¸@ÿN_ì?"â”óño±¹*ô8/¸RÄiÞ©ÿTp3Ê%§úwz3¯ ž›Ëÿv¹­â9$gÀ;õY”xúÛ;¶¬Ë~zÂL \Ç– $:wNtäs;5I8vûìèu–Ÿu6®Lù5ý#lK‹økú"NY÷pŸ•¢÷ð÷Eœæ.FÍÅçJ+þ¢ˆÓ7väÑðÃ"î¡Øœ–œ¯|| +ñ˜ec¤íßÃ&pŧ‹8½¸=/}nE¹^ÖÖAØ\DˆU|•ˆS]7tM{âže£”þ]Ì Ž ]ÓEÄéÅUÌ1ÜŸÞï”êt0ùP1ǧɇÉ-Ƴ¹Žñ’Ÿ Ḋ+_>׌*>IÄi [æp^AÖá3Å ˆ8=½÷êÖlîÙÁz\ïÕíEœZØ& ³¹¾ÀžzVÍÌl®ÆÐfÀ«Šxø¢Ä_{i!ñ¸åb_ý»´8'Š/–pl˜¹¸¤¸%Ì©?ôÚ¸”kù;ñ¹»óo/âXXy×ð8æ¬ò¼qªmVõ|–Í ŸŒâÏ‹¸—Oôâ¨oÓk:â‰H[Ôtà~ËƵŠgqj&ú:uÙ\ÇâòÀŠ8¤j?í²¹g™nÀn¡sR¥ ¤t€±(¬ù÷»2Ÿ!âT×5ü¤ x¤íyúw13ì ?i)âTl +®èÎæ¶j mð>"N]£ZÏ$ØÜ1‚P!µž©#â4 LsÍM3Ž¬K›^Ä-<=“„#ëRçdqš-,vK.7⪪ ¶aOe?ݲ|°eÓOqjeªfxGxZÅW‰8}ïO}Fx‘žþúG@ªŒgÙ‰OXÁLéþŒçD–ƒ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ˆÇü5á“11{J'UñDœ>™Õß,csõ3ìp[ýÍÇ}×s€GºrÑŒþð<"NOŸ½h.›Çl|&â4g5<õ?ñ.ŽY)~VÂqf¤Á‹˜9‰:íãéiÜ7ÑàÅãŽpXMÉù*ñäzø´ç_vIûõÛßfs×Á™PÅ—‰¸‡ÄÏ$›…š^¿ÜŒÈÿ¶§´Éo»±¹^»ŠwqªçSß›ÂçvH<õ½é"î!늲ŽÿÈMõˆ'—óÂ+jõ;ÃÃÅÜÔ@Ä)ÒÈŸ;–pê×)ÞS±ïâµûŽq¹áÇÏKò‹îa?]7ÁïqD˜Yÿ;ñ #¸ž&±~˜„£ž¿çÌ*vâ ÛÀÓï9³ZÂñ·ÿv¢™¨Ôyàˆ8Í4xòyvÖyn°|ßàÉ‘Žb“nû‹ó ­ÞHÄéƒÍvü~±±ƒ b²¯/â¸,cKKþ'ã"¾â­Eœ¶*ÕÍÇÎ:ÿJMF¥™ˆû‹BØü?#—„ã´Î'Ÿíâr#îᬯ]êϺ…>­â½DÜDâ·‰Ÿ|zã‹»ú€ë[ªÃ·¤êð8vœúóŠqzqCj•eó¸j!cà%EœZ™™é—O^$žÐá2p[åÌôËEœ†ÿSFî’p7à{ç¤R¿_R›ÏÍ ¦Ó÷KêŠ85RO¹îw C·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ÓÜ¥•î¬„ã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·’U x Ç´Ïøý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%{RO hÆ玃/'¤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ˆx Y×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ü>§Õÿâ^Ä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ëý`Ídy|¯ˆSE}g©OÁ͈ÜÔû"Mðõ"N­Ì°åMØ< F¿WÄéoŸð*?ñf°"¦øF§ºnâøYçzè”®{&=Ÿ›XXIY÷ô5 G€ÙÕË +ðÿvñ ¼ˆˆY×W”uTYe™ú.|´„#ìaûe#À#mŒL.h[VÚ/)áôô”N¼Ë榪¨ãà«$Û°÷ÅåFÌE:Å7ˆ8UVÍê¾m ¦ã +m³º‹Eœ¶&N¹¾‹ÍãFЩ%–7bs]>ÞPÂi¢U%~›$ñØWi_Ç›<ä:ñbê+#âØõñÓÁúl®ªiì«üé`mÇ}‘CÖòyÚÕ{C†¬qêœÜ”i¾ ñ6®âº)Ók"Ç‹ë%yqTQ7¾Vi3x¤ƒÌúw1 gF_Äé‹ËÕ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Ü.>Öô·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ÑÉ +>OèàùåÝpWS§1ì£ÅÛ€›QBéßyª³À;ˆ8Vÿ­dsÇ ¶ã>¶h•ˆÓß^×*Ææz“M¸ýÜ–ÍU·Ð£R§xa§ø©Ò¿²ÿ·0§§Jÿ!âÔŸ¿´}›Çìî»´}ˆ/®èÅÑ6­ìÕizßJ« =ø`éJÞ uXÅÇJ8F‘u¶æ7£&ògb¾Nñ[$œŸzóÁ¼\nx®M‹‰©å‡UdsUl1É\~X9§2ŸRû6~â­ NiJmCÄi02ªE3Aâ1ɬxs§6îûU³ß»e¸hã¾_5LÄ›\¢bC/.ýHÚSjE;Rª£g+cà×Dœ–óŠ}tŠÏÝ`4Qì£_EœÚ÷©);ùÜÁ½Šïqj"Ó{žÍ= '‘-â4ÈýÓàf¤cz]ÂFø;Å?qE^ÿú.6·L1S«ð$6·í [8«ðT§B»æñÙàfT®¯«0Àçˆ8ß¿«ó"—›úBf|¼ˆÓ‹s:bsGýÌ?,â4 ìöÜN~ÖØž§ø·"NÅ&ç‘lžpƒ£…9Ü-áÁ¡ÎîppS¼¹ˆSU9x­ +Ùf´0§:–ÞÆ žQÄ©Ìg®¿ÜŒr¸~LÜ ¶ef®¿_Äiž÷´Áç¦íÜqËd+ÓÜŠtÔHG³6‚8äÙÊôq*´™6ÝÁæ:^¦^_Ä)ñ©/$£¬Ä 3Ò<æ[ã|\ê ¿Š8µïëÝYÄ-#J§TsÏ n|XïÎqš·‰­<)™~L¶i'sêûîbóxÓIñú"N½‹‹oþ,àhe?-áènž•ËMUBp;máæ9DÜË;+zqôôOoŒ"nQº…úwžþ'øX§/îFW$Þö;¥a+ôïÒ.ÇI¹Ñ±¿€Çq&ôFÇÁ¢§[Hüi§>í}F²¹Ê=|q÷U+ài7}Ì,OÜñè°fÂÿ…n¡â•EœFЃÏ?Ëå:@"¦:Ÿ)âÔ»¨öN‚¸i{žÿ;wàuDœúó¼,L®ƒû&6xÙ$‡:·m&J||¸„cõ¿~žà‘¶¨iwb8•Y?ϽŽyÚ f€«í¯l‡q5 +‹£²Ê±`®ˆSÖÕmqƒÍÿvALÝûoqª*çO}…ÏMÔ6)ïÍMð¹…ûãwE<†Ä¿,J<¶ 1‚¸>"l᳘ÞÃ#䣾xZÄ©…Ñy ¸©yx­cÇm>Íö—ë3b¸[çÓlCEœ*êÍÇÏñ¹‹§+~QÄ©ØŒ4 ²¹‘Ö-iqjß'׬Éæz³Q ¼¶ˆS©Ûû~y6×{Ü\ðJ"NOÿePs6×a‰]ðEÜÃ'³YôÉP©ûóìÄ=Õðû½†îù[Ðð\"Ž•‘>KÁMÍÃ++O>Ä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×|+âÔºO­f'^oø6À׈8µ2½ºÜÂ/uf“½ºqúÛ÷·kÆæq'ØÁ¾¿Ý"Nß{–.­Ù<¦².Þ^ă¶èƒEØ„oѺFž¾‡÷+çX!â4 Lyj3›ÇllÊS[%{Ú7ÊÎæ®\WѾQ.§Aèä'ïds'-þü¦ú=ø»ôi7Õï*á8÷DÎuü¿ÝŠáòú'rnñ8²îQÖÑÔdž\¿Ç“‹¡<TÙß)âôÉÜøì>6»&º…7>{@Äcàø\Guï"áh"³<úŸÛ.úÌò賎كããŸas}J aRwå¿w{Ìçg]"íÎ…ã㇠Íÿ/•ž îC7NèpÖ–A‹ ŠÏ—pÌ”fN9Ïæúþxü’ˆÓ8.Çæê{¥f"uçšæl®Zœ ܹ¦©ˆÓüâ ×ù‰7‚C-qÚ•õ$ïWód]Ù@Äãxq£%/‹J™+büžÜ4þÉèM#qT™+Nqê¿ö>™äò}èÑÓßù€þü›£z°¹êYaYçÍQK8¡-7`ó„ŽþÞHÄcȺ¹¢¬£Ä¯¾J[¬ä"rh±ñc2#@âoŠ8½÷Û~šÍ]ÇÀìÁ¸ÿéf,Û"n#ñÃD‰§º.ÿ3AâýEäÐgéÎ.îL¬¾¡ Ÿ[ „ú¬¾!¿ˆÓPháäVln»·Q¼½ˆSÎjÕšÍ-78ìS¨ÿéš;X~‹ÏõVI^2ËuO ØØ¢bCmÜ“V,Óߺ¬£/º´ANñoDœž¾ïøç|nà{Wü §þ|G^7#r½‚ÁHG&‰8ÍÓ6ùê667v>4ùÊqj&þ‘Êæ–åábßÙÓ7°¹¾ËËÿTÄé{¼šu†¾ïÂ7DÜDÖ5–d†#WÒ\¥q]‡·5ƒ`Ú#Wqª¬f¥«@<¹€^]èÛ"0†U¼’„#çKîÄB'ÜÔcÁí´Š?+â´°R¨ùOÄ“ +aGÈc~°M„9Uü„ˆÓü¼9h+›{.Ž+¾SÄé{/Xñ.ðˆÍ„¾w/†ùº‚‹8Õó†ÐNf+yÌ*t8 ~gYÁ=¡†ôqjßç ßÀæ::® ¾NÄ©Kœ· ^\rI+ +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ß!â”ó_ÃÄKĉVõ;õÉ`ø«q1 G€Yc­MØÉÉÆСúì9Q|™ˆSM»sàQ.7bÁÍ>©{îjÁ~ºêÐ"²âM%«;%žJ]íþÕÀ­HÛóüÇ«B‹oÈ涃«:ï-⸶à“ZlîÙ6#™?©+âT]d˜»œÍõÎÊø[ŽØû©ŽÄØ\_µ™Oð¹‰X©·½‹ÿâlÃÿÛÆ6ñ ÐVZ„Ié˜\HUyiD Ú çÙˆ?¯ø§³ÖŸ 4Ñ¿3Òn«lýÉc"N]â÷ËÊ榅uÅsI8f̆mêËåªs‚Ž™âDœªÊܯ'ž<äÖ=пóCÌ‚—ñd#Õøê_ãÁÍ(Á:ümÈ.fÈŸ#â4¿çé_¹\¿9LóÞóôïŽ÷¾üÕl®> ˆú«+EœÞûƃ]DÜXÄ©[èÔíÌæªk‚cÔN]þÓ5§6®L㛈ë)nÓ ›hÕÜs,œ+Ó8³ˆS±Rkø¿ñÿ¹0Âçúb$ðçDœÞû‘Šë$‰GІ#7ˆ8õ¨Ï´JÇçiaÐδ¼8× +NmÌÀ殂*Ï,â¸|Ë]lîXØ«ø="N¥nj¦+à‘Vôcb*ñ6ø5§ï½/Å%ær¼¯ˆSYyË0p^]è`›Á©ÌÊ[†‹8M¼ÌØÍuü¼x! Çö¼õï`óX0g¥ø"N=«ÌþExQü]§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ù›/=.â4ÕYüÁÙlsƒH#Åœ+á÷I7þÓãª=‹ÏqL}ÜŒz>阕þ]ÚµDŠÏqªç_¯¸Üï„."ëPŽ(þ­ˆÓ÷Þ3ßy6÷¥®g¾¿Dœ:ä#ÞýËuz|2#ÞýC±½ÂéÀæq#¿¯p:‹8%þìÇ«ù/κÄg?^#âTUV«w›;¶‹nÕê5‘ptÌâ×O^SÞ)õô²¡ñ‰ëEœºFõ°¬Ca‘Â6Fj®D›F¿KÄé‹[S¶›ÇÜ`ËÊš²Dœž~ôÅ?ùÜ +¢"}ñ¢ˆÓÓüá—«—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‘q­4~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$Õ|âvÖ®I»¼,âôÉ\Ýi‚û“°©¸ŒÚŶ«;]§¬Ûÿ³ÁçªspGÄiΪuÛÚÄ]ÿc èßYV°M«uÛú"NŸÌšá°yÌED)Åÿq\Ž³îm~âƒ6Nñ•nbŽÚûµ›ëëïbàEEœþöËYòïâÊEŇˆx2ñ¯l¹ÜŒŒKÿδpé¡âDœJÝžQíØÜ2‚+÷Œâ?Ý +b¸¥83•ÍUožŽÛ(>SÄi>¥_6ׇ^ÞYÄiêcU½Å‚Ä'‚8¥õ–I8ÖasmÃ/6N»¼råÍ郭Ը—ëŽâÓVjœ"âÉbÓô¦ë¹D9ï‚ß"âÔ9ùåÝÄcF”%lý;Ã&~y÷u§ùù¯7£r}uUü= Ç·+kîárÿúzÅwŠ8¤:^|ÍcVÿ_-âôÁölSÍUûŠ§÷lSYÄq9Ó³|îÓ¼E2½ âôÉÌÌmñ¹™Àø}fnWÄ©ÌÊXš_l‚k‰/ÿx“/v´¤¥ãØB|±³°ˆS·<õžãÿ³ý>îwǃ{B—§¦Š8ÕuWϼ&H|aæê™Å\±Zs +›«ÎFR;kNp¤J]Ñ“q#ÊÖý;Û *êÇŠ8 BÇí)nF¹fTÿÎqƒÕÿq{*H8ÎÇjŽÍ]Ç@Y¨u&§áÀ•¬Yٖ㧿½X34R‰H‹‰ú1ž…pŠ×qjeR†WOrf*Ê·jÊâ–ƒï=e¸-á8È|õäf.×Ç?ÑD^=¹EÂéé/úŽxra%t¢U¯êظNZñŸE<¸}q+Z÷@%²c¨.²^&â4Ïß»<›ë|Ü‘Ú»¢„#´ïÙ~f󸜾8Ó¯"N…vÍš©à‘®)ñc¹M¬Y3SÄ)ûµ³¹J>M}(>æ?ð&™'·ås{ï(âÔŸÏ•·›ÛAüyÅ;‰8õm¦_9ÎæºKlŸú<õû¦·ýŽYh3‘¼9-ì÷MÛ8æ盌\3ŽPî¹è(>DÄigã¥I…øÜtñ·_šTLÄé{ÿñÇë\®/CùãOé%+¡£>­Ïæú¢ü.Çpó²¹m%ðÁ›Ï~ïç[êÔæsÇÁ÷¾¥N=§1l†Í=ÙÜÞWÂqä¤g7Ú0ãw"lœðC–žÝò‹8½÷ÖMòÑ?Ϊh¼›ˆS]·ß. â.xáÿÀ›lu<Ú"²zŒsjƒq€§;·Í-7ØžîÜN§¬ËúÒv6wm\ì«ønǼÍ{ˆ'V ­«ºFq쯻J»¸¹œêùŠO4#®'™£|21Ý9±ÞBÂñÉœ?u˜Í`§“âGDœ*«I÷Ö%îE:ب~§Ã?»¯/àØ_פÒ×Ë$§¼"p +“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ûþÞéEtb§Š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¯§çh(tK |œÎS|ˆc›VÉj’Ä£ØL¹ +<ÒµƒþcÒFÓF~(â”øνRÜÃÑÂν‰8UÔ%?Éæz«”þ‹ˆS¡í^<ñÄ?mû‡&R_¤í ºè^ü§—«V p‚=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§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ÙÚª¦ˆS]áûs‚Ä›ˆ[XáûK¢¿ÝDÖÍqªmÎœîwÌB§>,'/ˆ²rnäK"Neþ¥Õ´uÁrüê"t®C9qöyiµ)⸂­ðZ6××]Ò,qÉìcEœž¾éÞqüÄ»AXãM÷Ž‘pÌYe/ÝÜŠTYYŽþ=ÞIÄ)ëš?·ŽÍ]+„ŒxnƒˆSçäñé´ªÃ)º´¡~g™Aԅǧqja7·hÎæú؇ÞRÄ©Oû]¢àþ”Wè4o28zßõ(!âÔ)Ýôé67‚x•©e»YÿÆÿwÇ‹Žªì`WOï#zº‡§»¢§S÷ Ûº}ܧû{0k´îˆÓvÜnGóÿv3h¤ºùQÄ©{pxæAâÉ©ÎðÊÊÊdü Ç@¬jÆÃ'S5co§RwøÖÃln™A4­Ã·qú`‹%–‚û“¡Û2­˜3‚³Åoˆ8uN† qÙÜ5±E-µöŒnlîA™ï!âØ(5Ä%ž¾÷ñÓY`+9Õþâ<õââ¸[güÃ-DœÆï±ïïds}}<•¾¯'⸎êË]Ä“ðÐa ú¡8ö×}¹]ÄéÅÍlO3fVr ÞDê Ûˆ?¯ø"·PU–(‡yr(ëk³ÒøOPâS2žÏæ:® >YÄ©Ì·ÜKTfÆ¢|2¶î»¡ÿZî]$âThÎÀæ:u‰/Oˆñyp߄ⶈÓf¡[>zÍ] ]#ÅùYçKZ©Ùö½/É:lÏ˶oµˆSuqð»¢G9_þàap¿s:°uŒ .ðˆˆÓ8çÕlî$?­$ß+á8B~,Ó.>·‚ÃûÇ2 žnÛó®.jÎ庙ÀTçÕE-Eœj›óÙŠ³yܰѾŸÏVJÄiò¡û•}|î$ðôîW‰8õç··gÿíjìRŸ¶ñÕŠgÜÆeÖW+^q‰/,J<•ùY­ýÕ}È)ÊÆ ÿwz‚Ýo!âô½¿ùèóàþƉ r>OAØÃ9{gs¹¾fK™söNq”ºu Ù‰÷¬ Ðh÷uEœÞû„Q»ø‰¢m(þ­ˆc(TøcAâM¼÷’ÙW‹8M÷U{õ6!_'âA¡}FThé½ÿu¸aê?Æ1ƒ3bc:asõ]â¶Ê1^q‰_.J<›?‹}IÜŸ`7ë‹äVdüs§§Ÿ…69Á›1c™”Zíʱ¹aâVbÅK‰8}ïÏíÿŒÍ=ÕŒƒoqÄ«ÌчÏM\ä­xwñâê +^œ…“ ßüà·£,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Úú¿GÄ©¦Ò®››vó6CÚ5qª¨3L©@\ H"Û?ìƒ b¦T‘pDÏ›Ÿw ¸>_í„ÀuÆbïüþ›ë± õë–ìYÀçÁt_Ê_Ë2°¹ƒæáoÿPô·S=?z´Ç冗]gôèÛEÜEÎÿ$Êy 9?G”ór>“(çqĬسì¿]%õÀ_qzz±úûùÜÄÝ:Š’plþ/<˜‘M=¥¢v’ó•I^äÒF.7búà$‡¼–ïûˆŸx+ظ|ßZ§O&CŸólnZAÕ }.Š8Õ6Ʀçg]ڌل±D·0õ¡øPǦÐòíÙ\_­ï+Ⲏý½ûYGµÍ´<´ÓIÿoF +Å 5øGM;-OY§Fja*².f:É#Âa\7åØ»0µ³ˆÓ'S¯ÑÃl®×RiüÞ}ð-\nè_zà¹Eœ +íÐÍ=Ø\÷ÞGÄ©Øïõ›'‚àùŠŸqzúÐñÃØܳƒ¨ÈCÇ?%â.ŠM'Q±¡¿½X±ÝÄ=#ÚÔ‡÷÷ ÊÅŠíq …¾ßÊäúpŽÓ*¾]Ä©Wyùy B=ý¯"TVžá.ªÊËÏÏqM¼tWC>w9åHí3\nê¬÷ÀqšŸ¿vs#ÉßNcXÅqšæíõQNAâQÓ*žGÄ-¼¸ú¢~w p+êÓuð|¬ŒÜ=ˆÏ]Äîk|-ss6·]\S¢ÿ€(ñÿ°(ñ´u¡Ëâ>ln¸ L}tYÜ_©Цœy´››6ö*~§ˆc†.×Áqêð‹ß‰8%þJ»gØ\Õ³ÔÊ(>MÄ©SÚì¦òì¬ÓbàUEœ¾÷ ãèÄŠé_åa7®>.G&ŒóDœ†B|®§¸#,¬$ôEŸfÀ7Š8ýíç7öås3A9¯ø@§³ÿ¬Äå¦*¼¼ˆÓ´ÏµÜ¨mtp·(C!?Ô¦ê"÷Ý"NÅflkÚ<`%7 …rËð¯4À_qêQOì–Êæº?oƒß+âô·?~¶9¸?å:×ÿ´Ð§Uü~§®ÑÍ{?esO/ƒ¯qÚcVhóY67Ü`¯Ñ¨ 6¥ G-p$œö]4þ«T67ƒ[LÀ-DŒ,´ùgQÖ¿óMïës$QÔôeTFçÎ#ÇK)…*Ö”pTÔ…*Þ!â”øf½¯€›‘¦yWC5jÖûšˆÓ„Û;鰕ܦÚ@ëǸ¸_FñÜ"N_\ÎÛÁýɇÐå<}%¦‰(+ŠïqúÛs׫®¿¥ð‘:Ш™ÒÔbÝS˜ï]ßË\øX¬û="î ñqQâ)ç T§£…Vr›Vh×Ȳÿ6Õ©øp§‰—S±ýln™¸ÝFñC"N݃«U‚ûfÂsÞþÿFRUN‹8ö_,áž~ùE VÄ.Oq<ýês¢ÄcºïZCÑÓà-%{.ø”Ï]‡&ØS§|ær¹I™XÚ˜ò™%âØÉ\}›ÇmDIU|—ˆÓÌIŸj›ÙYg¸ DÏëSm«ˆS ûüÏéøYg'pŒúùŸ3Š8uÈÞhÊN¼i ÂŒâ÷‰¸B»FThiÂm×qtÈõæ©hܳ±³QñV"NýùjOÕ`rÇ¿ÙÇ·Dœ>™oþh îoQ l³qBñnb˜:|—ë3Ö‘:ü€€›‚qÝ(nE€ë»¤ 7hãnTq¬Ëd©!â¿g©%âÔÊ\_^‡ÍÕ¯°=ïúòû%qÜ×ù<íºÉ³¦óÿvsÔŠOñ8ÿ—(ñT]”šM[•¬äö¼ðBëžlI-5û'§úÿ•vïQUUiÀáª\A®¤8iFø¸“¼Îó>t4 ¬«bM‰3E!ø‚Ê_˜¦0‘†VêäŸPf&5Š¬!ÉWeXš©5f€,…I­|d9û\¾ïÜf­Y‹û}µÖüQÃo}ÏÙïýí½[¤¹èWamÓ:`"‡ã +¸òÍäÞ!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 ¢®³fo[ƒnwø¯¶Ým‹»6¬O³8´qÍÒ2—}‹ÈÍR)‡C§tô/¡ÛË~Mû¨ÆvV<¾^ð ,Ž••µšÎe<ãEðoYvçu¿S¥rÉeŽ"×9OY®Å1ïÀ€™ášÌá +å]?‡Î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_îeq¨.Â&ËŒÄ;ñÃ…MÖ9ëù°Œ+ ŽÇÛ +~Å¡™°¬ÀÚF•ýYÆm8ñV#ËŠl‡iŸð7ߣrïñ82òÝ,¿86ˆ‘xŒöñü¤aýv y ‡ãœ•gY_òowkN<°Â³l‹Cy8ÑEç’ Ï%~8q0‹Cy?Jÿî*Þð"øm,CàÔüt2wéfDk*¬€S9<}vòçäl#iN3Jæ’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³8 J,!ô<ï;m£ÄbãpìYUÕž g ï—ü‹»±È4±Š <½0 ôœ’?GB'*œ¯+ +apó|ZëRœpsúu¤³÷ï$î÷ð–í‡ܼ¶ 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øàÊÿá?9 FÚ^¦'^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ôØ«T$¿&™§˜çÏ ¾’Åõ‰[¦IS¤.Æÿ{{ÇŽË°Rénã_úvì)…/º½·õꆋúgþsצ¨»ïþÇÈ^r–KNãzÞê+Eo¹w‹=¿ÿÔììƒâãçÌ™—•—ž?iffV|ú´4ãFK'þƒd +˜?2¿ÅØ©S@‡ÜÀÀ€¨ªÏ¿V^±L[PSýhQÝé3Jï}Dz*>³·¼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 âp K:+§•d¦e–§¦eæfg§g— +ðÔ0 ³{•–é{‹óšXšXšZF¸††FÆP.ÐIÊL,Ö}! â¼Æ@)CKc3cƒ(. Q²¢,Ì\Œ¬ E®³g?*270*42´0BSÄQ´æT‘©¡‘©¡Ev–: HŠÌLL°(²Ù˜±¨ÈÒÐÈÀÐÐè* ,n²Ù¢|¡¨Ì«"UIdE†fX9ÌXŠ¬È]ÑkKn_„……‰‰ÑÆ@ÄQfF_ƒ˪*÷ÅO:×KçrX.aŸÿþeí>päÉÊ°00 E:s##ƒß‚} ÉçÿÝhøºðÔ/«¨Î[‚⦘¥/ð]“c|þyÉœu!, /1ùó±~8qíʧ™kʺºY„vºÔn¾›Ûõø›çÏÖ%­R«ÖL¶-ø`åkótªf]œ×Ù÷Ë;~hÚ!œëü7àº_éÃuƒ{'?‹¸þÑ»MK²îSxp²v¹ÁáKÑì½·³Ýê~Ëü»]ÿGÀ›s›ÿ—Vëgß‚Öìs æô9ºRoGjó¶§ œ'Kçê1ºîÐL[~çÒõÅÇWYEXõ,ÉÞé{ÅÐ2£€)î_Ì´sûw¶}}T®ø€¹ë«O’Ëô»Ißœ ×q2êÿ\[uæ{²”„å×’ŽÞ³¢¦ÜÏv±&BéF +endstream +endobj +28 0 obj +<< +/Filter [/FlateDecode] +/DL 1258 +/Length 33 0 R +>> +stream +xœ3hbyfÐÄ|n3#‹uŸ÷^6N­6¶ï¼ŒŒ¬¬ ±†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–11–UUî‹Ÿt®—:Ïå°\Â>ÿýËÚ}ò ie`FhÀ®”ªeùAñÂÌÈÏв03(!W”˜¼ˆóó?µôYO³êk›VLô©Y!(Xéã¹æÄ÷ÖÔ·ÝÖ ˜ÖŸõßzÆLëMì¿÷ &žÜ69¿¦!äÍqŽÞ¾ßMo´*2ÍÌ.Ó¹ÕáÄ”ÔòOáŠiÖçZ¶'Kí¯”û#{Yv²t7OlëÞ™Fœƒ^Ö,Üõ?eÒ¬7ÿLßõè¯û£ÐöÆëžt…‘ù²ÆKs×G ‰šý'?—ï蹶“/ÄÌhŠOæéŠZ}cê²3§»®íOñî;ÕµiÃKE£y«V´Î0i´T´^addû-Û¼-JtÆ‚iÿL¶3q¨µl©œV”¼mÓÓìk%}ws¹mvZkN,D¤ +endstream +endobj +29 0 obj +<< +/Filter [/FlateDecode] +/DL 998 +/Length 34 0 R +>> +stream +xœ3hb~dÐÄtj3#‹ë<õU¼lœZmmßyYY b % ÄàBœŒbœÙ™ÅÙz©©†ÜœlÌ¡,lÂL®®†J + —°¤c°BpjQIfZfIqjjQfnfqvjqvi±¡€H ³0»Wii‘n°·œ8¯¹¡©¡‘©‰Y”8¯¡™…‘™¡‰‘±a”Aé–(ȃÔp K +(IMÍ+-NM11‚¸ƒÛÕÓè # +š•}ÏÈÊÀÜÄÈÏçbjbddxT'({ê÷ÂÉ/«8ö¨G»¤¼V>[d´ø˜dY¿l“úöçEµÎמ°nâöù»JûžÃ«^½–Çîäw·H¬ÿ²×û¦Ó§6ì•øκ}ɵϼoH&‡øæ%÷6Ô¾:§©Úç÷ìŵ?ÙÞß„—¥Þ±œ<»Vî¾|CÉó’¬ëÅ6ý} °„Õdåš«\¿þì75[òHA¢«t­öê@™²¯õ"9º®x¶ô=NÚükû¶“¦õ{“ç?¼Ì™xoºÚ‘ ¥ª üÞLJ/.Õu1OÊû`4ÿ)kuÿ¾¸²³'¥˜N߸Diþú õsžÏ¾Pok?´—µàýŽW ~O·Å)/È“éÆž÷k+3#ãâÆ93Áá'+ÌÈøŸ…À H112€ãV–$ÆLOÿ ŒA|y-j TÚ”2JJ +¬ôõËËËõÀ)H?¹(§X? ˜@,= Ǭ2 0Ñ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+µ‡w· +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 new file mode 100644 index 0000000000..9ae7e23bb0 Binary files /dev/null and b/xmlsecurity/qa/unit/pdfsigning/data/no-eof.pdf differ diff --git a/xmlsecurity/qa/unit/pdfsigning/data/no.pdf b/xmlsecurity/qa/unit/pdfsigning/data/no.pdf new file mode 100644 index 0000000000..5d552421a4 Binary files /dev/null and b/xmlsecurity/qa/unit/pdfsigning/data/no.pdf differ diff --git a/xmlsecurity/qa/unit/pdfsigning/data/noeol.pdf b/xmlsecurity/qa/unit/pdfsigning/data/noeol.pdf new file mode 100644 index 0000000000..d870f896ca Binary files /dev/null and b/xmlsecurity/qa/unit/pdfsigning/data/noeol.pdf differ diff --git a/xmlsecurity/qa/unit/pdfsigning/data/partial-in-between.pdf b/xmlsecurity/qa/unit/pdfsigning/data/partial-in-between.pdf new file mode 100644 index 0000000000..211a111cb3 Binary files /dev/null and b/xmlsecurity/qa/unit/pdfsigning/data/partial-in-between.pdf differ diff --git a/xmlsecurity/qa/unit/pdfsigning/data/partial.pdf b/xmlsecurity/qa/unit/pdfsigning/data/partial.pdf new file mode 100644 index 0000000000..890f56217d Binary files /dev/null and b/xmlsecurity/qa/unit/pdfsigning/data/partial.pdf differ diff --git a/xmlsecurity/qa/unit/pdfsigning/data/pdf14adobe.pdf b/xmlsecurity/qa/unit/pdfsigning/data/pdf14adobe.pdf new file mode 100644 index 0000000000..58aadb492c Binary files /dev/null and b/xmlsecurity/qa/unit/pdfsigning/data/pdf14adobe.pdf differ diff --git a/xmlsecurity/qa/unit/pdfsigning/data/pdf14lowin.pdf b/xmlsecurity/qa/unit/pdfsigning/data/pdf14lowin.pdf new file mode 100644 index 0000000000..5270151ebc Binary files /dev/null and b/xmlsecurity/qa/unit/pdfsigning/data/pdf14lowin.pdf differ diff --git a/xmlsecurity/qa/unit/pdfsigning/data/pdf16adobe.pdf b/xmlsecurity/qa/unit/pdfsigning/data/pdf16adobe.pdf new file mode 100644 index 0000000000..ac1c5f37b9 Binary files /dev/null and b/xmlsecurity/qa/unit/pdfsigning/data/pdf16adobe.pdf differ diff --git a/xmlsecurity/qa/unit/pdfsigning/data/small.pdf b/xmlsecurity/qa/unit/pdfsigning/data/small.pdf new file mode 100644 index 0000000000..60675454f9 Binary files /dev/null and b/xmlsecurity/qa/unit/pdfsigning/data/small.pdf differ diff --git a/xmlsecurity/qa/unit/pdfsigning/data/tdf107149.pdf b/xmlsecurity/qa/unit/pdfsigning/data/tdf107149.pdf new file mode 100644 index 0000000000..db063f366a --- /dev/null +++ b/xmlsecurity/qa/unit/pdfsigning/data/tdf107149.pdf @@ -0,0 +1,97 @@ +%PDF-1.2 +%âãÏÓ +3 0 obj +<< +/Length 61 +>> +stream + BT + /F1 24 Tf + 1 0 0 1 260 254 Tm + (Hello Worl2)Tj + ET + +endstream +endobj xref +0 7 +0000000000 65535 f +0000000312 00000 n +0000000532 00000 n +0000000015 00000 n +0000000660 00000 n +0000000578 00000 n +0000000743 00000 n +trailer + +<< +/Root 6 0 R +/Size 7 +>> +1 0 obj +<< +/Resources 2 0 R +/Contents 3 0 R +/Parent 4 0 R +/Type /Page +/MediaBox [0 0 612 446] +>> +endobj +3 0 obj +<< +/Length 61 +>> +stream + BT + /F1 24 Tf + 1 0 0 1 260 254 Tm + (Hello World)Tj + ET + +endstream +endobj +2 0 obj +<< +/Font +<< +/F1 5 0 R +>> +>> +endobj +5 0 obj +<< +/Subtype /Type1 +/Name /F1 +/Type /Font +/BaseFont /Helvetica +>> +endobj +4 0 obj +<< +/Kids [1 0 R] +/Type /Pages +/MediaBox [0 0 612 446] +/Count 1 +>> +endobj +6 0 obj +<< +/Type /Catalog +/Pages 4 0 R +>> +endobj xref +0 7 +0000000000 65535 f +0000000015 00000 n +0000000235 00000 n +0000000121 00000 n +0000000363 00000 n +0000000281 00000 n +0000000446 00000 n +trailer + +<< +/Size 7 +>> +startxref +128 +%%EOF diff --git a/xmlsecurity/qa/unit/pdfsigning/data/tdf107782.pdf b/xmlsecurity/qa/unit/pdfsigning/data/tdf107782.pdf new file mode 100644 index 0000000000..086e18eedc Binary files /dev/null and b/xmlsecurity/qa/unit/pdfsigning/data/tdf107782.pdf differ diff --git a/xmlsecurity/qa/unit/pdfsigning/data/tdf114460.pdf b/xmlsecurity/qa/unit/pdfsigning/data/tdf114460.pdf new file mode 100644 index 0000000000..a736e5bb90 Binary files /dev/null and b/xmlsecurity/qa/unit/pdfsigning/data/tdf114460.pdf differ diff --git a/xmlsecurity/qa/unit/pdfsigning/data/tdf145312.pdf b/xmlsecurity/qa/unit/pdfsigning/data/tdf145312.pdf new file mode 100644 index 0000000000..6ff43f87e7 Binary files /dev/null and b/xmlsecurity/qa/unit/pdfsigning/data/tdf145312.pdf differ diff --git a/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx b/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx new file mode 100644 index 0000000000..0196a4707b --- /dev/null +++ b/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx @@ -0,0 +1,646 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include + +#if USE_CRYPTO_NSS +#include +#endif + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#endif + +using namespace com::sun::star; + +namespace +{ +constexpr OUString DATA_DIRECTORY = u"/xmlsecurity/qa/unit/pdfsigning/data/"_ustr; +} + +/// Testsuite for the PDF signing feature. +class PDFSigningTest : public test::BootstrapFixture, public unotest::MacrosTest +{ +protected: + /** + * Sign rInURL once and save the result as rOutURL, asserting that rInURL + * had nOriginalSignatureCount signatures. + */ + bool sign(const OUString& rInURL, const OUString& rOutURL, size_t nOriginalSignatureCount); + /** + * Read a pdf and make sure that it has the expected number of valid + * signatures. + */ + std::vector 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 xSEInitializer + = xml::crypto::SEInitializer::create(mxComponentContext); + uno::Reference 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 PDFSigningTest::verify(const OUString& rURL, size_t nCount) +{ + uno::Reference xSEInitializer + = xml::crypto::SEInitializer::create(mxComponentContext); + uno::Reference xSecurityContext + = xSEInitializer->createSecurityContext(OUString()); + std::vector aRet; + + SvFileStream aStream(rURL, StreamMode::READ); + PDFSignatureHelper aHelper; + CPPUNIT_ASSERT(aHelper.ReadAndVerifySignatureSvStream(aStream)); + + std::shared_ptr 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 xSEInitializer + = xml::crypto::SEInitializer::create(mxComponentContext); + uno::Reference xSecurityContext + = xSEInitializer->createSecurityContext(OUString()); + vcl::filter::PDFDocument aDocument; + { + SvFileStream aStream(rInURL, StreamMode::READ); + CPPUNIT_ASSERT(aDocument.Read(aStream)); + std::vector aSignatures = aDocument.GetSignatureWidgets(); + CPPUNIT_ASSERT_EQUAL(nOriginalSignatureCount, aSignatures.size()); + } + + bool bSignSuccessful = false; + // Sign it and write out the result. + { + uno::Reference xSecurityEnvironment + = xSecurityContext->getSecurityEnvironment(); + uno::Sequence> 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 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 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 pPDFium = vcl::pdf::PDFiumLibrary::get(); + if (!pPDFium) + { + return; + } + + // Make sure that good.pdf has 1 valid signature. + uno::Reference xSEInitializer + = xml::crypto::SEInitializer::create(mxComponentContext); + uno::Reference 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(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 xInputStream; + std::unique_ptr pStream + = utl::UcbStreamHelper::CreateStream(aOutURL, StreamMode::READWRITE); + uno::Reference 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 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 xSEInitializer + = xml::crypto::SEInitializer::create(mxComponentContext); + uno::Reference 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 pStream + = utl::UcbStreamHelper::CreateStream(aOutURL, StreamMode::READ | StreamMode::WRITE); + uno::Reference xStream(new utl::OStreamWrapper(std::move(pStream))); + aManager.setSignatureStream(xStream); + aManager.read(/*bUseTempStream=*/false); + std::vector& 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(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(0), rInformations.size()); +} + +CPPUNIT_TEST_FIXTURE(PDFSigningTest, testTdf107782) +{ + uno::Reference xSEInitializer + = xml::crypto::SEInitializer::create(mxComponentContext); + uno::Reference 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 pStream + = utl::UcbStreamHelper::CreateStream(aURL, StreamMode::READ | StreamMode::WRITE); + uno::Reference 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 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 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(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 pPDFium = vcl::pdf::PDFiumLibrary::get(); + if (!pPDFium) + { + return; + } + + std::vector 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 pPDFium = vcl::pdf::PDFiumLibrary::get(); + if (!pPDFium) + { + return; + } + + std::vector 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 pPDFium = vcl::pdf::PDFiumLibrary::get(); + if (!pPDFium) + { + return; + } + + std::vector 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 pPDFium = vcl::pdf::PDFiumLibrary::get(); + if (!pPDFium) + { + return; + } + + std::vector 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 pPDFium = vcl::pdf::PDFiumLibrary::get(); + if (!pPDFium) + { + return; + } + + std::vector 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 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 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 pPDFium = vcl::pdf::PDFiumLibrary::get(); + if (!pPDFium) + { + return; + } + + const std::initializer_list 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 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(rInformation.nStatus)); + } +} + +/// Test that we don't crash / loop while tokenizing these files. +CPPUNIT_TEST_FIXTURE(PDFSigningTest, testTokenize) +{ + const std::initializer_list 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(1), aDocument.GetPages().size()); + } +} + +/// Test handling of unknown SubFilter values. +CPPUNIT_TEST_FIXTURE(PDFSigningTest, testUnknownSubFilter) +{ + std::shared_ptr pPDFium = vcl::pdf::PDFiumLibrary::get(); + if (!pPDFium) + { + return; + } + + // Tokenize the bugdoc. + uno::Reference xSEInitializer + = xml::crypto::SEInitializer::create(mxComponentContext); + uno::Reference xSecurityContext + = xSEInitializer->createSecurityContext(OUString()); + std::unique_ptr pStream = utl::UcbStreamHelper::CreateStream( + m_directories.getURLFromSrc(DATA_DIRECTORY) + "cr-comment.pdf", StreamMode::STD_READ); + uno::Reference 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& rInformations = aManager.getCurrentSignatureInformations(); + CPPUNIT_ASSERT_EQUAL(static_cast(2), rInformations.size()); +} + +CPPUNIT_TEST_FIXTURE(PDFSigningTest, testGoodCustomMagic) +{ + std::shared_ptr pPDFium = vcl::pdf::PDFiumLibrary::get(); + if (!pPDFium) + { + return; + } + + // Tokenize the bugdoc. + uno::Reference xSEInitializer + = xml::crypto::SEInitializer::create(mxComponentContext); + uno::Reference xSecurityContext + = xSEInitializer->createSecurityContext(OUString()); + std::unique_ptr pStream = utl::UcbStreamHelper::CreateStream( + m_directories.getURLFromSrc(DATA_DIRECTORY) + "good-custom-magic.pdf", + StreamMode::STD_READ); + uno::Reference 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& rInformations = aManager.getCurrentSignatureInformations(); + CPPUNIT_ASSERT_EQUAL(static_cast(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 new file mode 100644 index 0000000000..d63e4b6b7b Binary files /dev/null and b/xmlsecurity/qa/unit/signing/data/02_doc_macros_signed_by_attacker_manipulated.odt differ 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 new file mode 100644 index 0000000000..0190abb00f Binary files /dev/null and b/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_attacker_manipulated.odt differ 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 new file mode 100644 index 0000000000..f4b4198f94 Binary files /dev/null and b/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_attacker_manipulated2.odt differ 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 new file mode 100644 index 0000000000..558bdee47e Binary files /dev/null and b/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_attacker_manipulated_triple.odt differ 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 new file mode 100644 index 0000000000..4136b32e56 Binary files /dev/null and b/xmlsecurity/qa/unit/signing/data/02_doc_signed_by_trusted_person_manipulated.odt differ diff --git a/xmlsecurity/qa/unit/signing/data/add-visible-signature.pdf b/xmlsecurity/qa/unit/signing/data/add-visible-signature.pdf new file mode 100644 index 0000000000..8dedb6998b Binary files /dev/null and b/xmlsecurity/qa/unit/signing/data/add-visible-signature.pdf differ diff --git a/xmlsecurity/qa/unit/signing/data/bad.docx b/xmlsecurity/qa/unit/signing/data/bad.docx new file mode 100644 index 0000000000..86d0eda49b Binary files /dev/null and b/xmlsecurity/qa/unit/signing/data/bad.docx differ diff --git a/xmlsecurity/qa/unit/signing/data/bad.odt b/xmlsecurity/qa/unit/signing/data/bad.odt new file mode 100644 index 0000000000..75c39d5d83 Binary files /dev/null and b/xmlsecurity/qa/unit/signing/data/bad.odt differ diff --git a/xmlsecurity/qa/unit/signing/data/bad.pdf b/xmlsecurity/qa/unit/signing/data/bad.pdf new file mode 100644 index 0000000000..f3f056f2bf Binary files /dev/null and b/xmlsecurity/qa/unit/signing/data/bad.pdf differ diff --git a/xmlsecurity/qa/unit/signing/data/badDsigGPG.odt b/xmlsecurity/qa/unit/signing/data/badDsigGPG.odt new file mode 100644 index 0000000000..032ddbf7a2 Binary files /dev/null and b/xmlsecurity/qa/unit/signing/data/badDsigGPG.odt differ diff --git a/xmlsecurity/qa/unit/signing/data/badStreamGPG.odt b/xmlsecurity/qa/unit/signing/data/badStreamGPG.odt new file mode 100644 index 0000000000..252ea26b00 Binary files /dev/null and b/xmlsecurity/qa/unit/signing/data/badStreamGPG.odt differ diff --git a/xmlsecurity/qa/unit/signing/data/encryptedGPG.odt b/xmlsecurity/qa/unit/signing/data/encryptedGPG.odt new file mode 100644 index 0000000000..9490a0ce58 Binary files /dev/null and b/xmlsecurity/qa/unit/signing/data/encryptedGPG.odt differ diff --git a/xmlsecurity/qa/unit/signing/data/encryptedGPG_odf13.odt b/xmlsecurity/qa/unit/signing/data/encryptedGPG_odf13.odt new file mode 100644 index 0000000000..e738c2f6df Binary files /dev/null and b/xmlsecurity/qa/unit/signing/data/encryptedGPG_odf13.odt differ diff --git a/xmlsecurity/qa/unit/signing/data/good-xades.odt b/xmlsecurity/qa/unit/signing/data/good-xades.odt new file mode 100644 index 0000000000..4f96d4bd89 Binary files /dev/null and b/xmlsecurity/qa/unit/signing/data/good-xades.odt differ diff --git a/xmlsecurity/qa/unit/signing/data/good.odt b/xmlsecurity/qa/unit/signing/data/good.odt new file mode 100644 index 0000000000..8c6019d0ac Binary files /dev/null and b/xmlsecurity/qa/unit/signing/data/good.odt differ diff --git a/xmlsecurity/qa/unit/signing/data/good.pdf b/xmlsecurity/qa/unit/signing/data/good.pdf new file mode 100644 index 0000000000..4a506c1e11 Binary files /dev/null and b/xmlsecurity/qa/unit/signing/data/good.pdf differ diff --git a/xmlsecurity/qa/unit/signing/data/goodGPG.odt b/xmlsecurity/qa/unit/signing/data/goodGPG.odt new file mode 100644 index 0000000000..a02af30169 Binary files /dev/null and b/xmlsecurity/qa/unit/signing/data/goodGPG.odt differ 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 new file mode 100644 index 0000000000..f2b1a71096 Binary files /dev/null and b/xmlsecurity/qa/unit/signing/data/hide-and-replace-shadow-file-signed-2.pdf differ diff --git a/xmlsecurity/qa/unit/signing/data/multi.docx b/xmlsecurity/qa/unit/signing/data/multi.docx new file mode 100644 index 0000000000..aba69508e2 Binary files /dev/null and b/xmlsecurity/qa/unit/signing/data/multi.docx differ diff --git a/xmlsecurity/qa/unit/signing/data/no.odt b/xmlsecurity/qa/unit/signing/data/no.odt new file mode 100644 index 0000000000..22cf7683a0 Binary files /dev/null and b/xmlsecurity/qa/unit/signing/data/no.odt differ diff --git a/xmlsecurity/qa/unit/signing/data/no.pdf b/xmlsecurity/qa/unit/signing/data/no.pdf new file mode 100644 index 0000000000..5d552421a4 Binary files /dev/null and b/xmlsecurity/qa/unit/signing/data/no.pdf differ diff --git a/xmlsecurity/qa/unit/signing/data/notype-xades.odt b/xmlsecurity/qa/unit/signing/data/notype-xades.odt new file mode 100644 index 0000000000..4f96d4bd89 Binary files /dev/null and b/xmlsecurity/qa/unit/signing/data/notype-xades.odt differ diff --git a/xmlsecurity/qa/unit/signing/data/odb_signed_macros.odb b/xmlsecurity/qa/unit/signing/data/odb_signed_macros.odb new file mode 100644 index 0000000000..3e90f45145 Binary files /dev/null and b/xmlsecurity/qa/unit/signing/data/odb_signed_macros.odb differ diff --git a/xmlsecurity/qa/unit/signing/data/partial.docx b/xmlsecurity/qa/unit/signing/data/partial.docx new file mode 100644 index 0000000000..3d6ca46851 Binary files /dev/null and b/xmlsecurity/qa/unit/signing/data/partial.docx differ diff --git a/xmlsecurity/qa/unit/signing/data/signatureline.docx b/xmlsecurity/qa/unit/signing/data/signatureline.docx new file mode 100644 index 0000000000..e1dae66989 Binary files /dev/null and b/xmlsecurity/qa/unit/signing/data/signatureline.docx differ diff --git a/xmlsecurity/qa/unit/signing/data/signatureline.odt b/xmlsecurity/qa/unit/signing/data/signatureline.odt new file mode 100644 index 0000000000..d3a3e4671e Binary files /dev/null and b/xmlsecurity/qa/unit/signing/data/signatureline.odt differ diff --git a/xmlsecurity/qa/unit/signing/data/signed_with_x509certificate_chain.odt b/xmlsecurity/qa/unit/signing/data/signed_with_x509certificate_chain.odt new file mode 100644 index 0000000000..5e519dd8b7 Binary files /dev/null and b/xmlsecurity/qa/unit/signing/data/signed_with_x509certificate_chain.odt differ diff --git a/xmlsecurity/qa/unit/signing/data/tdf42316.ott b/xmlsecurity/qa/unit/signing/data/tdf42316.ott new file mode 100644 index 0000000000..95162a6271 Binary files /dev/null and b/xmlsecurity/qa/unit/signing/data/tdf42316.ott differ diff --git a/xmlsecurity/qa/unit/signing/data/tdf42316_odt12.ott b/xmlsecurity/qa/unit/signing/data/tdf42316_odt12.ott new file mode 100644 index 0000000000..ecff487091 Binary files /dev/null and b/xmlsecurity/qa/unit/signing/data/tdf42316_odt12.ott differ diff --git a/xmlsecurity/qa/unit/signing/data/tdf96097.ods b/xmlsecurity/qa/unit/signing/data/tdf96097.ods new file mode 100644 index 0000000000..58d1b2c771 Binary files /dev/null and b/xmlsecurity/qa/unit/signing/data/tdf96097.ods differ diff --git a/xmlsecurity/qa/unit/signing/data/tdf96097.odt b/xmlsecurity/qa/unit/signing/data/tdf96097.odt new file mode 100644 index 0000000000..f0356513c3 Binary files /dev/null and b/xmlsecurity/qa/unit/signing/data/tdf96097.odt differ diff --git a/xmlsecurity/qa/unit/signing/data/untrustedGoodGPG.odt b/xmlsecurity/qa/unit/signing/data/untrustedGoodGPG.odt new file mode 100644 index 0000000000..e1b36d5441 Binary files /dev/null and b/xmlsecurity/qa/unit/signing/data/untrustedGoodGPG.odt differ diff --git a/xmlsecurity/qa/unit/signing/signing.cxx b/xmlsecurity/qa/unit/signing/signing.cxx new file mode 100644 index 0000000000..9f449d26d6 --- /dev/null +++ b/xmlsecurity/qa/unit/signing/signing.cxx @@ -0,0 +1,1473 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include + +#include + +#if USE_CRYPTO_NSS +#include +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace com::sun::star; + +/// Testsuite for the document signing feature. +class SigningTest : public UnoApiXmlTest +{ +protected: + uno::Reference mxSEInitializer; + uno::Reference mxSecurityContext; + +public: + SigningTest(); + virtual void setUp() override; + virtual void tearDown() override; + void registerNamespaces(xmlXPathContextPtr& pXmlXpathCtx) override; + +protected: + uno::Reference + getCertificate(DocumentSignatureManager& rSignatureManager, + svl::crypto::SignatureMethodAlgorithm eAlgo); +#if HAVE_FEATURE_GPGVERIFY + SfxObjectShell* assertDocument(const ::CppUnit::SourceLine aSrcLine, + const OUString& rFilterName, const SignatureState nDocSign, + const SignatureState nMacroSign, const OUString& sVersion); +#endif +}; + +SigningTest::SigningTest() + : UnoApiXmlTest("/xmlsecurity/qa/unit/signing/data/") +{ +} + +void SigningTest::setUp() +{ + UnoApiXmlTest::setUp(); + + MacrosTest::setUpNssGpg(m_directories, "xmlsecurity_signing"); + + // Initialize crypto after setting up the environment variables. + mxSEInitializer = xml::crypto::SEInitializer::create(mxComponentContext); + mxSecurityContext = mxSEInitializer->createSecurityContext(OUString()); +#if USE_CRYPTO_NSS +#ifdef NSS_USE_ALG_IN_ANY_SIGNATURE + // policy may disallow using SHA1 for signatures but unit test documents + // have such existing signatures (call this after createSecurityContext!) + NSS_SetAlgorithmPolicy(SEC_OID_SHA1, NSS_USE_ALG_IN_ANY_SIGNATURE, 0); +#endif +#endif +} + +void SigningTest::tearDown() +{ + MacrosTest::tearDownNssGpg(); + + UnoApiXmlTest::tearDown(); +} + +uno::Reference +SigningTest::getCertificate(DocumentSignatureManager& rSignatureManager, + svl::crypto::SignatureMethodAlgorithm eAlgo) +{ + uno::Reference xSecurityEnvironment + = rSignatureManager.getSecurityEnvironment(); + const uno::Sequence> aCertificates + = xSecurityEnvironment->getPersonalCertificates(); + + for (const auto& xCertificate : aCertificates) + { + auto pCertificate = dynamic_cast(xCertificate.get()); + CPPUNIT_ASSERT(pCertificate); + if (pCertificate->getSignatureMethodAlgorithm() == eAlgo + && IsValid(xCertificate, xSecurityEnvironment)) + return xCertificate; + } + return uno::Reference(); +} + +CPPUNIT_TEST_FIXTURE(SigningTest, testDescription) +{ + // Create an empty document and store it to a tempfile, finally load it as a storage. + load("private:factory/swriter"); + + save("writer8"); + + DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content); + CPPUNIT_ASSERT(aManager.init()); + uno::Reference xStorage + = comphelper::OStorageHelper::GetStorageOfFormatFromURL( + ZIP_STORAGE_FORMAT_STRING, maTempFile.GetURL(), embed::ElementModes::READWRITE); + CPPUNIT_ASSERT(xStorage.is()); + aManager.setStore(xStorage); + aManager.getSignatureHelper().SetStorage(xStorage, u"1.2"); + + // Then add a signature document. + uno::Reference 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& rInformations = aManager.getCurrentSignatureInformations(); + CPPUNIT_ASSERT_EQUAL(static_cast(1), rInformations.size()); + CPPUNIT_ASSERT_EQUAL(aDescription, rInformations[0].ouDescription); +} + +CPPUNIT_TEST_FIXTURE(SigningTest, testECDSA) +{ + // Create an empty document and store it to a tempfile, finally load it as a storage. + load("private:factory/swriter"); + + save("writer8"); + + DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content); + CPPUNIT_ASSERT(aManager.init()); + uno::Reference xStorage + = comphelper::OStorageHelper::GetStorageOfFormatFromURL( + ZIP_STORAGE_FORMAT_STRING, maTempFile.GetURL(), embed::ElementModes::READWRITE); + CPPUNIT_ASSERT(xStorage.is()); + aManager.setStore(xStorage); + aManager.getSignatureHelper().SetStorage(xStorage, u"1.2"); + + // Then add a signature. + uno::Reference 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& rInformations = aManager.getCurrentSignatureInformations(); + CPPUNIT_ASSERT_EQUAL(static_cast(1), rInformations.size()); + // This was SecurityOperationStatus_UNKNOWN, signing with an ECDSA key was + // broken. + CPPUNIT_ASSERT_EQUAL(css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED, + rInformations[0].nStatus); +} + +CPPUNIT_TEST_FIXTURE(SigningTest, testECDSAOOXML) +{ + // Create an empty document and store it to a tempfile, finally load it as a storage. + load("private:factory/swriter"); + + save("MS Word 2007 XML"); + + DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content); + CPPUNIT_ASSERT(aManager.init()); + uno::Reference xStorage + = comphelper::OStorageHelper::GetStorageOfFormatFromURL( + ZIP_STORAGE_FORMAT_STRING, maTempFile.GetURL(), embed::ElementModes::READWRITE); + CPPUNIT_ASSERT(xStorage.is()); + aManager.setStore(xStorage); + aManager.getSignatureHelper().SetStorage(xStorage, u"1.2"); + + // Then add a document signature. + uno::Reference 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& rInformations = aManager.getCurrentSignatureInformations(); + CPPUNIT_ASSERT_EQUAL(static_cast(1), rInformations.size()); + // This was SecurityOperationStatus_UNKNOWN, signing with an ECDSA key was + // broken. + CPPUNIT_ASSERT_EQUAL(css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED, + rInformations[0].nStatus); +} + +CPPUNIT_TEST_FIXTURE(SigningTest, testECDSAPDF) +{ + // Create an empty document and store it to a tempfile, finally load it as + // a stream. + load("private:factory/swriter"); + + save("writer_pdf_Export"); + + DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content); + CPPUNIT_ASSERT(aManager.init()); + std::unique_ptr pStream(utl::UcbStreamHelper::CreateStream( + maTempFile.GetURL(), StreamMode::READ | StreamMode::WRITE)); + uno::Reference xStream(new utl::OStreamWrapper(*pStream)); + CPPUNIT_ASSERT(xStream.is()); + aManager.setSignatureStream(xStream); + + // Then add a document signature. + uno::Reference 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& rInformations = aManager.getCurrentSignatureInformations(); + std::shared_ptr pPDFium = vcl::pdf::PDFiumLibrary::get(); + if (!pPDFium) + { + return; + } + + CPPUNIT_ASSERT_EQUAL(static_cast(1), rInformations.size()); + // This was SecurityOperationStatus_UNKNOWN, signing with an ECDSA key was + // broken. + CPPUNIT_ASSERT_EQUAL(css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED, + rInformations[0].nStatus); +} + +CPPUNIT_TEST_FIXTURE(SigningTest, testOOXMLDescription) +{ + // Create an empty document and store it to a tempfile, finally load it as a storage. + load("private:factory/swriter"); + + save("MS Word 2007 XML"); + + DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content); + CPPUNIT_ASSERT(aManager.init()); + uno::Reference xStorage + = comphelper::OStorageHelper::GetStorageOfFormatFromURL( + ZIP_STORAGE_FORMAT_STRING, maTempFile.GetURL(), embed::ElementModes::READWRITE); + CPPUNIT_ASSERT(xStorage.is()); + aManager.setStore(xStorage); + aManager.getSignatureHelper().SetStorage(xStorage, u"1.2"); + + // Then add a document signature. + uno::Reference 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& rInformations = aManager.getCurrentSignatureInformations(); + CPPUNIT_ASSERT_EQUAL(static_cast(1), rInformations.size()); + CPPUNIT_ASSERT_EQUAL(aDescription, rInformations[0].ouDescription); +} + +/// Test appending a new signature next to an existing one. +CPPUNIT_TEST_FIXTURE(SigningTest, testOOXMLAppend) +{ + // Copy the test document to a temporary file, as it'll be modified. + createTempCopy(u"partial.docx"); + // Load the test document as a storage and read its single signature. + DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content); + CPPUNIT_ASSERT(aManager.init()); + uno::Reference xStorage + = comphelper::OStorageHelper::GetStorageOfFormatFromURL( + ZIP_STORAGE_FORMAT_STRING, maTempFile.GetURL(), embed::ElementModes::READWRITE); + CPPUNIT_ASSERT(xStorage.is()); + aManager.setStore(xStorage); + aManager.getSignatureHelper().SetStorage(xStorage, u"1.2"); + aManager.read(/*bUseTempStream=*/false); + std::vector& rInformations = aManager.getCurrentSignatureInformations(); + CPPUNIT_ASSERT_EQUAL(static_cast(1), rInformations.size()); + + // Then add a second document signature. + uno::Reference 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(2), rInformations.size()); +} + +/// Test removing a signature from existing ones. +CPPUNIT_TEST_FIXTURE(SigningTest, testOOXMLRemove) +{ + // Load the test document as a storage and read its signatures: purpose1 and purpose2. + DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content); + CPPUNIT_ASSERT(aManager.init()); + createTempCopy(u"multi.docx"); + uno::Reference xStorage + = comphelper::OStorageHelper::GetStorageOfFormatFromURL( + ZIP_STORAGE_FORMAT_STRING, maTempFile.GetURL(), embed::ElementModes::READWRITE); + CPPUNIT_ASSERT(xStorage.is()); + aManager.setStore(xStorage); + aManager.getSignatureHelper().SetStorage(xStorage, u"1.2"); + aManager.read(/*bUseTempStream=*/false); + std::vector& rInformations = aManager.getCurrentSignatureInformations(); + CPPUNIT_ASSERT_EQUAL(static_cast(2), rInformations.size()); + + // Then remove the last added signature. + uno::Reference 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(1), rInformations.size()); + CPPUNIT_ASSERT_EQUAL(OUString("purpose1"), rInformations[0].ouDescription); +} + +/// Test removing all signatures from a document. +CPPUNIT_TEST_FIXTURE(SigningTest, testOOXMLRemoveAll) +{ + // Copy the test document to a temporary file, as it'll be modified. + createTempCopy(u"partial.docx"); + // Load the test document as a storage and read its single signature. + DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content); + CPPUNIT_ASSERT(aManager.init()); + uno::Reference xStorage + = comphelper::OStorageHelper::GetStorageOfFormatFromURL( + ZIP_STORAGE_FORMAT_STRING, maTempFile.GetURL(), embed::ElementModes::READWRITE); + CPPUNIT_ASSERT(xStorage.is()); + aManager.setStore(xStorage); + aManager.getSignatureHelper().SetStorage(xStorage, u"1.2"); + aManager.read(/*bUseTempStream=*/false); + std::vector& rInformations = aManager.getCurrentSignatureInformations(); + CPPUNIT_ASSERT_EQUAL(static_cast(1), rInformations.size()); + + // Then remove the only signature in the document. + uno::Reference 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(0), rInformations.size()); + CPPUNIT_ASSERT(!xStorage->hasByName("_xmlsignatures")); + + // And that content types no longer contains signature types. + uno::Reference xStream + = xStorage->openStreamElement("[Content_Types].xml", embed::ElementModes::READWRITE); + uno::Reference xInputStream = xStream->getInputStream(); + uno::Sequence> aContentTypeInfo + = comphelper::OFOPXMLHelper::ReadContentTypeSequence(xInputStream, mxComponentContext); + const uno::Sequence& rOverrides = aContentTypeInfo[1]; + CPPUNIT_ASSERT( + std::none_of(rOverrides.begin(), rOverrides.end(), [](const beans::StringPair& rPair) { + return rPair.First.startsWith("/_xmlsignatures/sig"); + })); +} + +/// Test a typical ODF where all streams are signed. +CPPUNIT_TEST_FIXTURE(SigningTest, testODFGood) +{ + loadFromFile(u"good.odt"); + SfxBaseModel* pBaseModel = dynamic_cast(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + // We expect NOTVALIDATED in case the root CA is not imported on the system, and OK otherwise, so accept both. + SignatureState nActual = pObjectShell->GetDocumentSignatureState(); + CPPUNIT_ASSERT_MESSAGE( + (OString::number(o3tl::to_underlying(nActual)).getStr()), + (nActual == SignatureState::NOTVALIDATED || nActual == SignatureState::OK)); +} + +/// Test a typical broken ODF signature where one stream is corrupted. +CPPUNIT_TEST_FIXTURE(SigningTest, testODFBroken) +{ + loadFromFile(u"bad.odt"); + SfxBaseModel* pBaseModel = dynamic_cast(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + CPPUNIT_ASSERT_EQUAL(static_cast(SignatureState::BROKEN), + static_cast(pObjectShell->GetDocumentSignatureState())); +} + +// Document has a signature stream, but no actual signatures. +CPPUNIT_TEST_FIXTURE(SigningTest, testODFNo) +{ + loadFromFile(u"no.odt"); + SfxBaseModel* pBaseModel = dynamic_cast(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + CPPUNIT_ASSERT_EQUAL(static_cast(SignatureState::NOSIGNATURES), + static_cast(pObjectShell->GetDocumentSignatureState())); +} + +// document has one signed timestamp and one unsigned timestamp +CPPUNIT_TEST_FIXTURE(SigningTest, testODFUnsignedTimestamp) +{ + loadFromFile(u"02_doc_signed_by_trusted_person_manipulated.odt"); + SfxBaseModel* pBaseModel = dynamic_cast(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 const infos( + pObjectShell->GetDocumentSignatureInformation(false)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), infos.getLength()); + // was: 66666666 + CPPUNIT_ASSERT_EQUAL(sal_Int32(20210126), infos[0].SignatureDate); + // was: 0 + CPPUNIT_ASSERT_EQUAL(sal_Int32(18183742), infos[0].SignatureTime); +} + +// FIXME: For some unknown reason, this test fails on tml's Mac unless it is the only or the first +// test that is run in this CppunitTest program. When using our patched bundled cppunit library (as +// we obviously always do on macOS), the CPPUNIT_TEST_FIXTUREs are run in lexicographical order so +// use a name for this test that makes it the first one to run. + +CPPUNIT_TEST_FIXTURE(SigningTest, aaa_testODFX509CertificateChain) +{ + loadFromFile(u"signed_with_x509certificate_chain.odt"); + SfxBaseModel* pBaseModel = dynamic_cast(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 const infos( + pObjectShell->GetDocumentSignatureInformation(false)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), infos.getLength()); + // check that the signing certificate was picked, not one of the 2 CA ones + CPPUNIT_ASSERT_EQUAL(security::CertificateValidity::VALID, infos[0].CertificateStatus); + CPPUNIT_ASSERT(infos[0].Signer.is()); + CPPUNIT_ASSERT_EQUAL( + OUString("CN=Xmlsecurity RSA Test example Alice,O=Xmlsecurity RSA Test,ST=England,C=UK"), + // CryptoAPI puts a space after comma, NSS does not... + infos[0].Signer->getSubjectName().replaceAll(", ", ",")); +} + +CPPUNIT_TEST_FIXTURE(SigningTest, testODFDoubleX509Data) +{ + loadFromFile(u"02_doc_signed_by_attacker_manipulated.odt"); + SfxBaseModel* pBaseModel = dynamic_cast(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 const infos( + pObjectShell->GetDocumentSignatureInformation(false)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), infos.getLength()); + // the signature in this manipulated document is technically valid but we can't tell who signed + // it, so make sure no misleading info is shown to the user + CPPUNIT_ASSERT_EQUAL(security::CertificateValidity::INVALID, infos[0].CertificateStatus); + CPPUNIT_ASSERT(!infos[0].Signer.is()); +} + +CPPUNIT_TEST_FIXTURE(SigningTest, testODFTripleX509Data) +{ + loadFromFile(u"02_doc_signed_by_attacker_manipulated_triple.odt"); + SfxBaseModel* pBaseModel = dynamic_cast(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 const infos( + pObjectShell->GetDocumentSignatureInformation(false)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), infos.getLength()); + // the signature in this manipulated document is technically valid but we can't tell who signed + // it, so make sure no misleading info is shown to the user + CPPUNIT_ASSERT_EQUAL(security::CertificateValidity::INVALID, infos[0].CertificateStatus); + CPPUNIT_ASSERT(!infos[0].Signer.is()); +} + +CPPUNIT_TEST_FIXTURE(SigningTest, testODFMacroDoubleX509Data) +{ + loadFromFile(u"02_doc_macros_signed_by_attacker_manipulated.odt"); + SfxBaseModel* pBaseModel = dynamic_cast(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 const infos( + pObjectShell->GetDocumentSignatureInformation(true)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), infos.getLength()); + // the signature in this manipulated document is technically valid but we can't tell who signed + // it, so make sure no misleading info is shown to the user + CPPUNIT_ASSERT_EQUAL(security::CertificateValidity::INVALID, infos[0].CertificateStatus); + CPPUNIT_ASSERT(!infos[0].Signer.is()); +} + +CPPUNIT_TEST_FIXTURE(SigningTest, testODFDoubleX509Certificate) +{ + loadFromFile(u"02_doc_signed_by_attacker_manipulated2.odt"); + SfxBaseModel* pBaseModel = dynamic_cast(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 const infos( + pObjectShell->GetDocumentSignatureInformation(false)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), infos.getLength()); + // the signature in this manipulated document is technically valid but we can't tell who signed + // it, so make sure no misleading info is shown to the user + CPPUNIT_ASSERT_EQUAL(security::CertificateValidity::INVALID, infos[0].CertificateStatus); + CPPUNIT_ASSERT(!infos[0].Signer.is()); +} + +CPPUNIT_TEST_FIXTURE(SigningTest, testDNCompatibility) +{ + OUString constexpr msDN(u"CN=\"\"\"ABC\"\".\", O=\"Enterprise \"\"ABC\"\"\""_ustr); + OUString constexpr nssDN(u"CN=\\\"ABC\\\".,O=Enterprise \\\"ABC\\\""_ustr); + // this is just the status quo, possibly either NSS or CryptoAPI might change + CPPUNIT_ASSERT(!xmlsecurity::EqualDistinguishedNames(msDN, nssDN, xmlsecurity::NOCOMPAT)); + CPPUNIT_ASSERT(!xmlsecurity::EqualDistinguishedNames(nssDN, msDN, xmlsecurity::NOCOMPAT)); + // with compat flag it should work, with the string one 2nd and the native one 1st +#ifdef _WIN32 + CPPUNIT_ASSERT(xmlsecurity::EqualDistinguishedNames(msDN, nssDN, xmlsecurity::COMPAT_2ND)); +#else + CPPUNIT_ASSERT(xmlsecurity::EqualDistinguishedNames(nssDN, msDN, xmlsecurity::COMPAT_2ND)); +#endif +} + +/// Test a typical OOXML where a number of (but not all) streams are signed. +CPPUNIT_TEST_FIXTURE(SigningTest, testOOXMLPartial) +{ + loadFromFile(u"partial.docx"); + SfxBaseModel* pBaseModel = dynamic_cast(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + // This was SignatureState::BROKEN due to missing RelationshipTransform and SHA-256 support. + // We expect NOTVALIDATED_PARTIAL_OK in case the root CA is not imported on the system, and PARTIAL_OK otherwise, so accept both. + // But reject NOTVALIDATED, hiding incompleteness is not OK. + SignatureState nActual = pObjectShell->GetDocumentSignatureState(); + CPPUNIT_ASSERT_MESSAGE((OString::number(o3tl::to_underlying(nActual)).getStr()), + (nActual == SignatureState::NOTVALIDATED_PARTIAL_OK + || nActual == SignatureState::PARTIAL_OK)); +} + +/// Test a typical broken OOXML signature where one stream is corrupted. +CPPUNIT_TEST_FIXTURE(SigningTest, testOOXMLBroken) +{ + loadFromFile(u"bad.docx"); + SfxBaseModel* pBaseModel = dynamic_cast(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(SignatureState::BROKEN), + static_cast(pObjectShell->GetDocumentSignatureState())); +} + +#if HAVE_FEATURE_PDFIMPORT + +/// Test a typical PDF where the signature is good. +CPPUNIT_TEST_FIXTURE(SigningTest, testPDFGood) +{ + loadFromFile(u"good.pdf"); + SfxBaseModel* pBaseModel = dynamic_cast(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 pPDFium = vcl::pdf::PDFiumLibrary::get(); + if (!pPDFium) + { + return; + } + + CPPUNIT_ASSERT_MESSAGE( + (OString::number(o3tl::to_underlying(nActual)).getStr()), + (nActual == SignatureState::NOTVALIDATED || nActual == SignatureState::OK)); +} + +/// Test a typical PDF where the signature is bad. +CPPUNIT_TEST_FIXTURE(SigningTest, testPDFBad) +{ + loadFromFile(u"bad.pdf"); + SfxBaseModel* pBaseModel = dynamic_cast(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + std::shared_ptr pPDFium = vcl::pdf::PDFiumLibrary::get(); + if (!pPDFium) + { + return; + } + + CPPUNIT_ASSERT_EQUAL(static_cast(SignatureState::BROKEN), + static_cast(pObjectShell->GetDocumentSignatureState())); +} + +CPPUNIT_TEST_FIXTURE(SigningTest, testPDFHideAndReplace) +{ + loadFromFile(u"hide-and-replace-shadow-file-signed-2.pdf"); + SfxBaseModel* pBaseModel = dynamic_cast(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + std::shared_ptr 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(SignatureState::BROKEN), + static_cast(pObjectShell->GetDocumentSignatureState())); +} + +/// Test a typical PDF which is not signed. +CPPUNIT_TEST_FIXTURE(SigningTest, testPDFNo) +{ + loadFromFile(u"no.pdf"); + SfxBaseModel* pBaseModel = dynamic_cast(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + CPPUNIT_ASSERT_EQUAL(static_cast(SignatureState::NOSIGNATURES), + static_cast(pObjectShell->GetDocumentSignatureState())); +} + +#endif + +CPPUNIT_TEST_FIXTURE(SigningTest, testPDFAddVisibleSignature) +{ + std::shared_ptr pPDFium = vcl::pdf::PDFiumLibrary::get(); + if (!pPDFium) + { + return; + } + + // FIXME: the DPI check should be removed when either (1) the test is fixed to work with + // non-default DPI; or (2) unit tests on Windows are made to use svp VCL plugin. + if (!IsDefaultDPI()) + return; + // Given: copy the test document to a temporary file, as it'll be modified. + createTempCopy(u"add-visible-signature.pdf"); + + // Open it. + uno::Sequence aArgs = { comphelper::makePropertyValue("ReadOnly", true) }; + mxComponent + = loadFromDesktop(maTempFile.GetURL(), "com.sun.star.drawing.DrawingDocument", aArgs); + SfxBaseModel* pBaseModel = dynamic_cast(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + + // Add a signature line. + uno::Reference xFactory(mxComponent, uno::UNO_QUERY); + uno::Reference 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 xSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xDrawPages = xSupplier->getDrawPages(); + uno::Reference xDrawPage(xDrawPages->getByIndex(0), uno::UNO_QUERY); + xDrawPage->add(xShape); + + // Select it and assign a certificate. + uno::Reference xSelectionSupplier(pBaseModel->getCurrentController(), + uno::UNO_QUERY); + xSelectionSupplier->select(uno::Any(xShape)); + uno::Sequence> aCertificates + = mxSecurityContext->getSecurityEnvironment()->getPersonalCertificates(); + if (!aCertificates.hasElements()) + { + return; + } + SdrView* pView = SfxViewShell::Current()->GetDrawView(); + svx::SignatureLineHelper::setShapeCertificate(pView, aCertificates[0]); + + // the document is modified now, but Sign function can't show SaveAs dialog + // in unit test, so just clear the modified + pObjectShell->SetModified(false); + + // When: do the actual signing. + pObjectShell->SignDocumentContentUsingCertificate(aCertificates[0]); + + // Then: count the # of shapes on the signature widget/annotation. + std::unique_ptr pPdfDocument = parsePDFExport(); + + std::unique_ptr pPdfPage = pPdfDocument->openPage(/*nIndex=*/0); + CPPUNIT_ASSERT_EQUAL(1, pPdfPage->getAnnotationCount()); + std::unique_ptr pAnnot = pPdfPage->getAnnotation(/*nIndex=*/0); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 4 + // - Actual : 0 + // i.e. the signature was there, but it was empty / not visible. + CPPUNIT_ASSERT_EQUAL(4, pAnnot->getObjectCount()); +} + +CPPUNIT_TEST_FIXTURE(SigningTest, test96097Calc) +{ + loadFromFile(u"tdf96097.ods"); + SfxBaseModel* pBaseModel = dynamic_cast(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 xDocStorable(mxComponent, uno::UNO_QUERY_THROW); + + // Save a copy + uno::Sequence descSaveACopy(comphelper::InitPropertySequence( + { { "SaveACopy", uno::Any(true) }, { "FilterName", uno::Any(OUString("calc8")) } })); + xDocStorable->storeToURL(maTempFile.GetURL(), descSaveACopy); + + // FIXME: Error: element "document-signatures" is missing "version" attribute + skipValidation(); + + // Save As + save("calc8"); +} + +CPPUNIT_TEST_FIXTURE(SigningTest, test96097Doc) +{ + loadFromFile(u"tdf96097.odt"); + SfxBaseModel* pBaseModel = dynamic_cast(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 xDocStorable(mxComponent, uno::UNO_QUERY_THROW); + + // Save a copy + uno::Sequence descSaveACopy(comphelper::InitPropertySequence( + { { "SaveACopy", uno::Any(true) }, { "FilterName", uno::Any(OUString("writer8")) } })); + xDocStorable->storeToURL(maTempFile.GetURL(), descSaveACopy); + + // FIXME: Error: element "document-signatures" is missing "version" attribute + skipValidation(); + + // Save As + save("writer8"); +} + +CPPUNIT_TEST_FIXTURE(SigningTest, testXAdESNotype) +{ + // Create a working copy. + createTempCopy(u"notype-xades.odt"); + + // Read existing signature. + DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content); + CPPUNIT_ASSERT(aManager.init()); + uno::Reference xStorage + = comphelper::OStorageHelper::GetStorageOfFormatFromURL( + ZIP_STORAGE_FORMAT_STRING, maTempFile.GetURL(), embed::ElementModes::READWRITE); + CPPUNIT_ASSERT(xStorage.is()); + aManager.setStore(xStorage); + aManager.getSignatureHelper().SetStorage(xStorage, u"1.2"); + aManager.read(/*bUseTempStream=*/false); + + // Create a new signature. + uno::Reference 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 xTransactedObject(xStorage, uno::UNO_QUERY); + xTransactedObject->commit(); + + // Parse the resulting XML. + uno::Reference xMetaInf + = xStorage->openStorageElement("META-INF", embed::ElementModes::READ); + uno::Reference xInputStream( + xMetaInf->openStreamElement("documentsignatures.xml", embed::ElementModes::READ), + uno::UNO_QUERY); + std::unique_ptr pStream(utl::UcbStreamHelper::CreateStream(xInputStream, true)); + xmlDocUniquePtr pXmlDoc = parseXmlStream(pStream.get()); + + // Without the accompanying fix in place, this test would have failed with "unexpected 'Type' + // attribute", i.e. the signature without such an attribute was not preserved correctly. + assertXPathNoAttribute(pXmlDoc, + "/odfds:document-signatures/dsig:Signature[1]/dsig:SignedInfo/" + "dsig:Reference[starts-with(@URI, '#idSignedProperties')]"_ostr, + "Type"_ostr); + + // New signature always has the Type attribute. + assertXPath(pXmlDoc, + "/odfds:document-signatures/dsig:Signature[2]/dsig:SignedInfo/" + "dsig:Reference[starts-with(@URI, '#idSignedProperties')]"_ostr, + "Type"_ostr, "http://uri.etsi.org/01903#SignedProperties"); +} + +/// Creates a XAdES signature from scratch. +CPPUNIT_TEST_FIXTURE(SigningTest, testXAdES) +{ + // Create an empty document, store it to a tempfile and load it as a storage. + load("private:factory/swriter"); + + save("writer8"); + + DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content); + CPPUNIT_ASSERT(aManager.init()); + uno::Reference xStorage + = comphelper::OStorageHelper::GetStorageOfFormatFromURL( + ZIP_STORAGE_FORMAT_STRING, maTempFile.GetURL(), embed::ElementModes::READWRITE); + CPPUNIT_ASSERT(xStorage.is()); + aManager.setStore(xStorage); + aManager.getSignatureHelper().SetStorage(xStorage, u"1.2"); + + // Create a signature. + uno::Reference 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 xTransactedObject(xStorage, uno::UNO_QUERY); + xTransactedObject->commit(); + + // Parse the resulting XML. + uno::Reference xMetaInf + = xStorage->openStorageElement("META-INF", embed::ElementModes::READ); + uno::Reference xInputStream( + xMetaInf->openStreamElement("documentsignatures.xml", embed::ElementModes::READ), + uno::UNO_QUERY); + std::unique_ptr pStream(utl::UcbStreamHelper::CreateStream(xInputStream, true)); + xmlDocUniquePtr pXmlDoc = parseXmlStream(pStream.get()); + + // Assert that the digest algorithm is SHA-256 in the bAdESCompliant case, not SHA-1. + assertXPath(pXmlDoc, + "/odfds:document-signatures/dsig:Signature/dsig:SignedInfo/" + "dsig:Reference[@URI='content.xml']/dsig:DigestMethod"_ostr, + "Algorithm"_ostr, ALGO_XMLDSIGSHA256); + + // Assert that the digest of the signing certificate is included. + assertXPath(pXmlDoc, "//xd:CertDigest"_ostr, 1); + + // Assert that the Type attribute is set on all URI's that start with #idSignedProperties + assertXPath(pXmlDoc, "//dsig:Reference[starts-with(@URI, '#idSignedProperties')]"_ostr, + "Type"_ostr, "http://uri.etsi.org/01903#SignedProperties"); +} + +CPPUNIT_TEST_FIXTURE(SigningTest, testSigningMultipleTimes_ODT) +{ + load("private:factory/swriter"); + + save("writer8"); + { + DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content); + CPPUNIT_ASSERT(aManager.init()); + uno::Reference xStorage + = comphelper::OStorageHelper::GetStorageOfFormatFromURL( + ZIP_STORAGE_FORMAT_STRING, maTempFile.GetURL(), embed::ElementModes::READWRITE); + CPPUNIT_ASSERT(xStorage.is()); + aManager.setStore(xStorage); + aManager.getSignatureHelper().SetStorage(xStorage, u"1.2"); + + // Create a signature. + uno::Reference 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& rInformations + = aManager.getCurrentSignatureInformations(); + CPPUNIT_ASSERT_EQUAL(static_cast(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& rInformations + = aManager.getCurrentSignatureInformations(); + CPPUNIT_ASSERT_EQUAL(static_cast(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& rInformations + = aManager.getCurrentSignatureInformations(); + CPPUNIT_ASSERT_EQUAL(static_cast(3), rInformations.size()); + CPPUNIT_ASSERT_EQUAL(css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED, + rInformations[2].nStatus); + } + + aManager.write(/*bXAdESCompliantIfODF=*/true); + uno::Reference xTransactedObject(xStorage, uno::UNO_QUERY); + xTransactedObject->commit(); + } + + Scheduler::ProcessEventsToIdle(); + + load(maTempFile.GetURL()); + + SfxBaseModel* pBaseModel = dynamic_cast(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + CPPUNIT_ASSERT_EQUAL(SignatureState::OK, pObjectShell->GetDocumentSignatureState()); +} + +CPPUNIT_TEST_FIXTURE(SigningTest, testSigningMultipleTimes_OOXML) +{ + load("private:factory/swriter"); + + save("MS Word 2007 XML"); + { + DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content); + CPPUNIT_ASSERT(aManager.init()); + uno::Reference xStorage + = comphelper::OStorageHelper::GetStorageOfFormatFromURL( + ZIP_STORAGE_FORMAT_STRING, maTempFile.GetURL(), embed::ElementModes::READWRITE); + CPPUNIT_ASSERT(xStorage.is()); + aManager.setStore(xStorage); + aManager.getSignatureHelper().SetStorage(xStorage, u"1.2"); + + // Create a signature. + uno::Reference 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& rInformations + = aManager.getCurrentSignatureInformations(); + CPPUNIT_ASSERT_EQUAL(static_cast(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& rInformations + = aManager.getCurrentSignatureInformations(); + CPPUNIT_ASSERT_EQUAL(static_cast(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& rInformations + = aManager.getCurrentSignatureInformations(); + CPPUNIT_ASSERT_EQUAL(static_cast(3), rInformations.size()); + CPPUNIT_ASSERT_EQUAL(css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED, + rInformations[2].nStatus); + } + + aManager.write(/*bXAdESCompliantIfODF=*/true); + uno::Reference xTransactedObject(xStorage, uno::UNO_QUERY); + xTransactedObject->commit(); + } + + Scheduler::ProcessEventsToIdle(); + + load(maTempFile.GetURL()); + + SfxBaseModel* pBaseModel = dynamic_cast(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + CPPUNIT_ASSERT_EQUAL(SignatureState::PARTIAL_OK, pObjectShell->GetDocumentSignatureState()); +} + +/// Works with an existing good XAdES signature. +CPPUNIT_TEST_FIXTURE(SigningTest, testXAdESGood) +{ + loadFromFile(u"good-xades.odt"); + SfxBaseModel* pBaseModel = dynamic_cast(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 xSignatures( + security::DocumentDigitalSignatures::createDefault( + comphelper::getProcessComponentContext())); + + uno::Reference xStorage + = comphelper::OStorageHelper::GetStorageOfFormatFromURL( + ZIP_STORAGE_FORMAT_STRING, createFileURL(u"signatureline.docx"), + embed::ElementModes::READ); + CPPUNIT_ASSERT(xStorage.is()); + + uno::Sequence xSignatureInfo + = xSignatures->verifyScriptingContentSignatures(xStorage, + uno::Reference()); + + CPPUNIT_ASSERT(xSignatureInfo.getLength()); + + // The signature should have a valid signature, and signature line with two valid images + CPPUNIT_ASSERT(xSignatureInfo[0].SignatureIsValid); + CPPUNIT_ASSERT_EQUAL(OUString("{DEE0514B-13E8-4674-A831-46E3CDB18BB4}"), + xSignatureInfo[0].SignatureLineId); + CPPUNIT_ASSERT(xSignatureInfo[0].ValidSignatureLineImage.is()); + CPPUNIT_ASSERT(xSignatureInfo[0].InvalidSignatureLineImage.is()); +} + +CPPUNIT_TEST_FIXTURE(SigningTest, testSignatureLineODF) +{ + loadFromFile(u"signatureline.odt"); + SfxBaseModel* pBaseModel = dynamic_cast(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + + uno::Sequence xSignatureInfo + = pObjectShell->GetDocumentSignatureInformation(false); + + CPPUNIT_ASSERT(xSignatureInfo.getLength()); + + CPPUNIT_ASSERT(xSignatureInfo[0].SignatureIsValid); + CPPUNIT_ASSERT_EQUAL(OUString("{41CF56EE-331B-4125-97D8-2F5669DD3AAC}"), + xSignatureInfo[0].SignatureLineId); + CPPUNIT_ASSERT(xSignatureInfo[0].ValidSignatureLineImage.is()); + CPPUNIT_ASSERT(xSignatureInfo[0].InvalidSignatureLineImage.is()); +} + +#if HAVE_FEATURE_GPGVERIFY +/// Test a typical ODF where all streams are GPG-signed. +CPPUNIT_TEST_FIXTURE(SigningTest, testODFGoodGPG) +{ + loadFromFile(u"goodGPG.odt"); + SfxBaseModel* pBaseModel = dynamic_cast(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + // Our local gpg config fully trusts the signing cert, so in + // contrast to the X509 test we can fail on NOTVALIDATED here + SignatureState nActual = pObjectShell->GetDocumentSignatureState(); + CPPUNIT_ASSERT_EQUAL_MESSAGE((OString::number(o3tl::to_underlying(nActual)).getStr()), + SignatureState::OK, nActual); +} + +/// Test a typical ODF where all streams are GPG-signed, but we don't trust the signature. +CPPUNIT_TEST_FIXTURE(SigningTest, testODFUntrustedGoodGPG) +{ + loadFromFile(u"untrustedGoodGPG.odt"); + SfxBaseModel* pBaseModel = dynamic_cast(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + // Our local gpg config does _not_ trust the signing cert, so in + // contrast to the X509 test we can fail everything but + // NOTVALIDATED here + SignatureState nActual = pObjectShell->GetDocumentSignatureState(); + CPPUNIT_ASSERT_EQUAL_MESSAGE((OString::number(o3tl::to_underlying(nActual)).getStr()), + SignatureState::NOTVALIDATED, nActual); +} + +/// Test a typical broken ODF signature where one stream is corrupted. +CPPUNIT_TEST_FIXTURE(SigningTest, testODFBrokenStreamGPG) +{ + loadFromFile(u"badStreamGPG.odt"); + SfxBaseModel* pBaseModel = dynamic_cast(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + CPPUNIT_ASSERT_EQUAL(static_cast(SignatureState::BROKEN), + static_cast(pObjectShell->GetDocumentSignatureState())); +} + +/// Test a typical broken ODF signature where the XML dsig hash is corrupted. +CPPUNIT_TEST_FIXTURE(SigningTest, testODFBrokenDsigGPG) +{ + loadFromFile(u"badDsigGPG.odt"); + SfxBaseModel* pBaseModel = dynamic_cast(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + CPPUNIT_ASSERT_EQUAL(static_cast(SignatureState::BROKEN), + static_cast(pObjectShell->GetDocumentSignatureState())); +} + +#if HAVE_GPGCONF_SOCKETDIR + +/// Test loading an encrypted ODF document +CPPUNIT_TEST_FIXTURE(SigningTest, testODFEncryptedGPG) +{ + // ODF1.2 + loext flavour + loadFromFile(u"encryptedGPG.odt"); + SfxBaseModel* pBaseModel = dynamic_cast(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + + // ODF1.3 flavour + loadFromFile(u"encryptedGPG_odf13.odt"); + pBaseModel = dynamic_cast(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + + // export and import again + saveAndReload("writer8"); + + pBaseModel = dynamic_cast(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); +} + +#endif + +SfxObjectShell* SigningTest::assertDocument(const ::CppUnit::SourceLine aSrcLine, + const OUString& rFilterName, + const SignatureState nDocSign, + const SignatureState nMacroSign, + const OUString& sVersion) +{ + std::string sPos = aSrcLine.fileName() + ":" + OString::number(aSrcLine.lineNumber()).getStr(); + + SfxBaseModel* pBaseModel = dynamic_cast(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 xPropSet(pObjectShell->GetStorage(), uno::UNO_QUERY_THROW); + xPropSet->getPropertyValue("Version") >>= aODFVersion; + CPPUNIT_ASSERT_EQUAL(sVersion, aODFVersion); + + return pObjectShell; +} + +/// Test if a macro signature from a OTT 1.2 template is preserved for ODT 1.2 +CPPUNIT_TEST_FIXTURE(SigningTest, testPreserveMacroTemplateSignature12_ODF) +{ + const OUString aFormats[] = { "writer8", "writer8_template" }; + + for (OUString const& sFormat : aFormats) + { + const OUString aURL(createFileURL(u"tdf42316_odt12.ott")); + const OUString sLoadMessage = "loading failed: " + aURL; + + // load the template as-is to validate signatures + mxComponent = loadFromDesktop( + aURL, OUString(), + comphelper::InitPropertySequence({ { "AsTemplate", uno::Any(false) } })); + + // we are a template, and have a valid document and macro signature + assertDocument(CPPUNIT_SOURCELINE(), "writer8_template", SignatureState::OK, + SignatureState::OK, ODFVER_012_TEXT); + + // create new document from template + load(aURL); + CPPUNIT_ASSERT_MESSAGE(OUStringToOString(sLoadMessage, RTL_TEXTENCODING_UTF8).getStr(), + mxComponent.is()); + + // we are somehow a template (?), and have just a valid macro signature + assertDocument(CPPUNIT_SOURCELINE(), "writer8_template", SignatureState::NOSIGNATURES, + SignatureState::OK, ODFVER_012_TEXT); + + // FIXME: Error: element "document-signatures" is missing "version" attribute + skipValidation(); + + if (sFormat == "writer8") + // save as new ODT document + saveAndReload(sFormat); + else + { + // save as new OTT template + save("writer8_template"); + + // load the saved OTT template as-is to validate signatures + mxComponent->dispose(); + mxComponent = loadFromDesktop( + maTempFile.GetURL(), OUString(), + comphelper::InitPropertySequence({ { "AsTemplate", uno::Any(false) } })); + } + + // the loaded document is a OTT/ODT with a macro signature + assertDocument(CPPUNIT_SOURCELINE(), sFormat, SignatureState::NOSIGNATURES, + SignatureState::OK, ODFVER_013_TEXT); + + // save as new OTT template + save("writer8_template"); + + // load the template as-is to validate signatures + mxComponent->dispose(); + mxComponent = loadFromDesktop( + maTempFile.GetURL(), OUString(), + comphelper::InitPropertySequence({ { "AsTemplate", uno::Any(false) } })); + + // the loaded document is a OTT with a valid macro signature + assertDocument(CPPUNIT_SOURCELINE(), "writer8_template", SignatureState::NOSIGNATURES, + SignatureState::OK, ODFVER_013_TEXT); + + mxComponent->dispose(); + mxComponent.clear(); + } +} + +/// Test if a macro signature from an OTT 1.0 is dropped for ODT 1.2 +CPPUNIT_TEST_FIXTURE(SigningTest, testDropMacroTemplateSignature) +{ + const OUString aURL(createFileURL(u"tdf42316.ott")); + const OUString sLoadMessage = "loading failed: " + aURL; + + // load the template as-is to validate signatures + mxComponent = loadFromDesktop( + aURL, OUString(), comphelper::InitPropertySequence({ { "AsTemplate", uno::Any(false) } })); + + // we are a template, and have a non-invalid macro signature + assertDocument(CPPUNIT_SOURCELINE(), "writer8_template", SignatureState::NOSIGNATURES, + SignatureState::NOTVALIDATED, OUString()); + + // create new document from template + load(aURL); + CPPUNIT_ASSERT_MESSAGE(OUStringToOString(sLoadMessage, RTL_TEXTENCODING_UTF8).getStr(), + mxComponent.is()); + + // we are somehow a template (?), and have just a valid macro signature + assertDocument(CPPUNIT_SOURCELINE(), "writer8_template", SignatureState::NOSIGNATURES, + SignatureState::NOTVALIDATED, OUString()); + + // save as new ODT document + saveAndReload("writer8"); + + // the loaded document is a 1.2 ODT without any signatures + assertDocument(CPPUNIT_SOURCELINE(), "writer8", SignatureState::NOSIGNATURES, + SignatureState::NOSIGNATURES, ODFVER_013_TEXT); + + // load the template as-is to validate signatures + mxComponent->dispose(); + mxComponent = loadFromDesktop( + aURL, OUString(), comphelper::InitPropertySequence({ { "AsTemplate", uno::Any(false) } })); + + // we are a template, and have a non-invalid macro signature + assertDocument(CPPUNIT_SOURCELINE(), "writer8_template", SignatureState::NOSIGNATURES, + SignatureState::NOTVALIDATED, OUString()); + + // save as new OTT template + save("writer8_template"); + + // load the template as-is to validate signatures + mxComponent->dispose(); + mxComponent + = loadFromDesktop(maTempFile.GetURL(), OUString(), + comphelper::InitPropertySequence({ { "AsTemplate", uno::Any(false) } })); + + // the loaded document is a 1.2 OTT without any signatures + assertDocument(CPPUNIT_SOURCELINE(), "writer8_template", SignatureState::NOSIGNATURES, + SignatureState::NOSIGNATURES, ODFVER_013_TEXT); +} + +/// Test if a macro signature from a OTT 1.0 template is preserved for ODT 1.0 +CPPUNIT_TEST_FIXTURE(SigningTest, testPreserveMacroTemplateSignature10) +{ + // set ODF version 1.0 / 1.1 as default + Resetter _([]() { + std::shared_ptr pBatch( + comphelper::ConfigurationChanges::create()); + officecfg::Office::Common::Save::ODF::DefaultVersion::set(3, pBatch); + return pBatch->commit(); + }); + std::shared_ptr pBatch( + comphelper::ConfigurationChanges::create()); + officecfg::Office::Common::Save::ODF::DefaultVersion::set(2, pBatch); + pBatch->commit(); + + const OUString aFormats[] = { "writer8", "writer8_template" }; + + for (OUString const& sFormat : aFormats) + { + const OUString aURL(createFileURL(u"tdf42316.ott")); + const OUString sLoadMessage = "loading failed: " + aURL; + + // load the template as-is to validate signatures + mxComponent = loadFromDesktop( + aURL, OUString(), + comphelper::InitPropertySequence({ { "AsTemplate", uno::Any(false) } })); + + // we are a template, and have a non-invalid macro signature + assertDocument(CPPUNIT_SOURCELINE(), "writer8_template", SignatureState::NOSIGNATURES, + SignatureState::NOTVALIDATED, OUString()); + + // create new document from template + load(aURL); + CPPUNIT_ASSERT_MESSAGE(OUStringToOString(sLoadMessage, RTL_TEXTENCODING_UTF8).getStr(), + mxComponent.is()); + + // we are somehow a template (?), and have just a valid macro signature + assertDocument(CPPUNIT_SOURCELINE(), "writer8_template", SignatureState::NOSIGNATURES, + SignatureState::NOTVALIDATED, OUString()); + + // FIXME: Error: element "manifest:manifest" is missing "version" attribute + skipValidation(); + + if (sFormat == "writer8") + // save as new ODT document + saveAndReload(sFormat); + else + { + // save as new OTT template + save("writer8_template"); + + // load the saved OTT template as-is to validate signatures + mxComponent->dispose(); + mxComponent = loadFromDesktop( + maTempFile.GetURL(), OUString(), + comphelper::InitPropertySequence({ { "AsTemplate", uno::Any(false) } })); + } + + assertDocument(CPPUNIT_SOURCELINE(), sFormat, SignatureState::NOSIGNATURES, + SignatureState::NOTVALIDATED, OUString()); + + save("writer8_template"); + + // load the template as-is to validate signatures + mxComponent->dispose(); + mxComponent = loadFromDesktop( + maTempFile.GetURL(), OUString(), + comphelper::InitPropertySequence({ { "AsTemplate", uno::Any(false) } })); + + // the loaded document is a OTT with a non-invalid macro signature + assertDocument(CPPUNIT_SOURCELINE(), "writer8_template", SignatureState::NOSIGNATURES, + SignatureState::NOTVALIDATED, OUString()); + + mxComponent->dispose(); + mxComponent.clear(); + } +} + +#endif + +void SigningTest::registerNamespaces(xmlXPathContextPtr& pXmlXpathCtx) +{ + xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("odfds"), + BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:digitalsignature:1.0")); + xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("dsig"), + BAD_CAST("http://www.w3.org/2000/09/xmldsig#")); + xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("xd"), BAD_CAST("http://uri.etsi.org/01903/v1.3.2#")); +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/qa/unit/signing/signing2.cxx b/xmlsecurity/qa/unit/signing/signing2.cxx new file mode 100644 index 0000000000..aef3c7f088 --- /dev/null +++ b/xmlsecurity/qa/unit/signing/signing2.cxx @@ -0,0 +1,80 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +using namespace css; + +/// Testsuite for the document signing feature. +class SigningTest2 : public UnoApiXmlTest +{ +public: + SigningTest2(); + void registerNamespaces(xmlXPathContextPtr& pXmlXpathCtx) override; +}; + +SigningTest2::SigningTest2() + : UnoApiXmlTest("/xmlsecurity/qa/unit/signing/data/") +{ +} + +/// Test if a macro signature from a ODF Database is preserved when saving +CPPUNIT_TEST_FIXTURE(SigningTest2, testPreserveMacroSignatureODB) +{ + loadFromFile(u"odb_signed_macros.odb"); + + // save as ODB + save("StarOffice XML (Base)"); + + // Parse the resulting XML. + uno::Reference xStorage + = comphelper::OStorageHelper::GetStorageOfFormatFromURL( + ZIP_STORAGE_FORMAT_STRING, maTempFile.GetURL(), embed::ElementModes::READ); + CPPUNIT_ASSERT(xStorage.is()); + uno::Reference xMetaInf + = xStorage->openStorageElement("META-INF", embed::ElementModes::READ); + uno::Reference xInputStream( + xMetaInf->openStreamElement("macrosignatures.xml", embed::ElementModes::READ), + uno::UNO_QUERY); + std::unique_ptr pStream(utl::UcbStreamHelper::CreateStream(xInputStream, true)); + xmlDocUniquePtr pXmlDoc = parseXmlStream(pStream.get()); + + // Make sure the signature is still there + assertXPath(pXmlDoc, "//dsig:Signature"_ostr, "Id"_ostr, + "ID_00a7002f009000bc00ce00f7004400460080002f002e00e400e0003700df00e8"); +} + +void SigningTest2::registerNamespaces(xmlXPathContextPtr& pXmlXpathCtx) +{ + xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("odfds"), + BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:digitalsignature:1.0")); + xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("dsig"), + BAD_CAST("http://www.w3.org/2000/09/xmldsig#")); + xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("xd"), BAD_CAST("http://uri.etsi.org/01903/v1.3.2#")); +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/qa/unit/xmlsecurity-dialogs-test.cxx b/xmlsecurity/qa/unit/xmlsecurity-dialogs-test.cxx new file mode 100644 index 0000000000..b5b16c3a72 --- /dev/null +++ b/xmlsecurity/qa/unit/xmlsecurity-dialogs-test.cxx @@ -0,0 +1,61 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include + +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 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 XmlsecurityDialogsTest::createDialogByID(sal_uInt32 /*nID*/) +{ + return nullptr; +} + +void XmlsecurityDialogsTest::openAnyDialog() +{ + /// process input file containing the UXMLDescriptions of the dialogs to dump + processDialogBatchFile(u"xmlsecurity/qa/unit/data/xmlsecurity-dialogs-test.txt"); +} + +CPPUNIT_TEST_SUITE_REGISTRATION(XmlsecurityDialogsTest); + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/component/certificatecontainer.cxx b/xmlsecurity/source/component/certificatecontainer.cxx new file mode 100644 index 0000000000..e230c7b2ce --- /dev/null +++ b/xmlsecurity/source/component/certificatecontainer.cxx @@ -0,0 +1,152 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include +#include +#include + +#include +#include + +#include + +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 +{ +private: + typedef std::map 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&) {} + 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 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 const&) +{ + static rtl::Reference gContainer = new CertificateContainer(context); + return cppu::acquire(gContainer.get()); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/component/documentdigitalsignatures.cxx b/xmlsecurity/source/component/documentdigitalsignatures.cxx new file mode 100644 index 0000000000..4ad63b36ed --- /dev/null +++ b/xmlsecurity/source/component/documentdigitalsignatures.cxx @@ -0,0 +1,906 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +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, + public sfx2::DigitalSignatures +{ +private: + css::uno::Reference mxCtx; + css::uno::Reference 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& rxStorage, + const css::uno::Reference& xSignStream, + DocumentSignatureMode eMode, bool bReadOnly); + /// @throws css::uno::RuntimeException + void ImplViewSignatures(const css::uno::Reference& rxStorage, + const css::uno::Reference& xSignStream, + DocumentSignatureMode eMode, bool bReadOnly); + /// @throws css::uno::RuntimeException + css::uno::Sequence + ImplVerifySignatures(const css::uno::Reference& rxStorage, + const ::com::sun::star::uno::Reference& xSignStream, + DocumentSignatureMode eMode); + + css::uno::Sequence> + chooseCertificatesImpl(std::map& rProperties, const UserAction eAction, + const CertificateKind certificateKind=CertificateKind_NONE); + + bool + signWithCertificateImpl(const uno::Reference& /*xModel*/, + css::uno::Reference const& xCertificate, + css::uno::Reference const& xStorage, + css::uno::Reference const& xStream, + DocumentSignatureMode eMode); + +public: + explicit DocumentDigitalSignatures( + const css::uno::Reference& rxCtx); + + //XInitialization + void SAL_CALL initialize(const css::uno::Sequence& aArguments) override; + + OUString SAL_CALL getImplementationName() override; + + sal_Bool SAL_CALL supportsService(OUString const& ServiceName) override; + + css::uno::Sequence SAL_CALL getSupportedServiceNames() override; + + // XDocumentDigitalSignatures + sal_Bool SAL_CALL + signDocumentContent(const css::uno::Reference& xStorage, + const css::uno::Reference& xSignStream) override; + sal_Bool SAL_CALL signSignatureLine( + const css::uno::Reference& Storage, + const css::uno::Reference& xSignStream, const OUString& aSignatureLineId, + const Reference& xCertificate, + const Reference& xValidGraphic, + const Reference& xInvalidGraphic, + const OUString& aComment) override; + css::uno::Sequence + SAL_CALL verifyDocumentContentSignatures( + const css::uno::Reference& xStorage, + const css::uno::Reference& xSignInStream) override; + void SAL_CALL showDocumentContentSignatures( + const css::uno::Reference& xStorage, + const css::uno::Reference& xSignInStream) override; + OUString SAL_CALL getDocumentContentSignatureDefaultStreamName() override; + sal_Bool SAL_CALL + signScriptingContent(const css::uno::Reference& xStorage, + const css::uno::Reference& xSignStream) override; + css::uno::Sequence + SAL_CALL verifyScriptingContentSignatures( + const css::uno::Reference& xStorage, + const css::uno::Reference& xSignInStream) override; + void SAL_CALL showScriptingContentSignatures( + const css::uno::Reference& xStorage, + const css::uno::Reference& xSignInStream) override; + OUString SAL_CALL getScriptingContentSignatureDefaultStreamName() override; + sal_Bool SAL_CALL + signPackage(const css::uno::Reference& Storage, + const css::uno::Reference& xSignStream) override; + css::uno::Sequence + SAL_CALL verifyPackageSignatures( + const css::uno::Reference& Storage, + const css::uno::Reference& xSignInStream) override; + void SAL_CALL + showPackageSignatures(const css::uno::Reference& xStorage, + const css::uno::Reference& xSignInStream) override; + OUString SAL_CALL getPackageSignatureDefaultStreamName() override; + void SAL_CALL + showCertificate(const css::uno::Reference& Certificate) override; + void SAL_CALL manageTrustedSources() override; + sal_Bool SAL_CALL + isAuthorTrusted(const css::uno::Reference& Author) override; + sal_Bool SAL_CALL isLocationTrusted(const OUString& Location) override; + void SAL_CALL addAuthorToTrustedSources( + const css::uno::Reference& Author) override; + void SAL_CALL addLocationToTrustedSources(const OUString& Location) override; + + css::uno::Reference + SAL_CALL chooseCertificate(OUString& rDescription) override; + css::uno::Reference + SAL_CALL chooseSigningCertificate(OUString& rDescription) override; + css::uno::Reference + SAL_CALL selectSigningCertificate(OUString& rDescription) override; + css::uno::Reference + SAL_CALL selectSigningCertificateWithType(const CertificateKind certificateKind, + OUString& rDescription) override; + css::uno::Sequence> + SAL_CALL chooseEncryptionCertificate() override; + css::uno::Reference SAL_CALL chooseCertificateWithProps( + css::uno::Sequence<::com::sun::star::beans::PropertyValue>& Properties) override; + + sal_Bool SAL_CALL signDocumentWithCertificate( + css::uno::Reference const & xCertificate, + css::uno::Reference const & xStoragexStorage, + css::uno::Reference const & xStream) override; + + sal_Bool SAL_CALL signPackageWithCertificate( + css::uno::Reference const& xCertificate, + css::uno::Reference const& xStoragexStorage, + css::uno::Reference const& xStream) override; + + sal_Bool SAL_CALL signScriptingContentWithCertificate( + css::uno::Reference const& xCertificate, + css::uno::Reference const& xStoragexStorage, + css::uno::Reference const& xStream) override; + + void SAL_CALL setParentWindow(const css::uno::Reference& rParentwindow) override + { + mxParentWindow = rParentwindow; + } + + /// See sfx2::DigitalSignatures::SignModelWithCertificate(). + bool + SignModelWithCertificate(const css::uno::Reference& xModel, + const css::uno::Reference& xCertificate, + const css::uno::Reference& xStorage, + const css::uno::Reference& 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(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(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(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 +DocumentDigitalSignatures::getSupportedServiceNames() +{ + Sequence 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& rxStorage, + const Reference& xSignStream, + const OUString& aSignatureLineId, + const Reference& xCertificate, + const Reference& xValidGraphic, + const Reference& 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 xSecurityContext; + Reference 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 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( + 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 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(); + } + // 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 xSecEnv = aSignatureManager.getSecurityEnvironment(); + uno::Reference 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 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> 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>()); + } + + // 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& 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 xCert = aSignatureManager.getSecurityEnvironment()->createCertificateFromAscii(rAuthor.RawData); + + auto pAuthor = dynamic_cast(xAuthor.get()); + auto pCert = dynamic_cast(xCert.get()); + if (pAuthor && pCert) + return pCert->getSHA256Thumbprint() == pAuthor->getSHA256Thumbprint(); + + return xCert->getSHA1Thumbprint() == xAuthor->getSHA1Thumbprint(); + }); +} + +uno::Sequence> +DocumentDigitalSignatures::chooseCertificatesImpl(std::map& rProperties, + const UserAction eAction, + const CertificateKind certificateKind) +{ + std::vector< Reference< css::xml::crypto::XXMLSecurityContext > > xSecContexts; + + DocumentSignatureManager aSignatureManager(mxCtx, {}); + if (aSignatureManager.init()) { + xSecContexts.push_back(aSignatureManager.getSecurityContext()); + // Don't include OpenPGP if only X.509 certs are requested + if (certificateKind == CertificateKind_NONE || certificateKind == CertificateKind_OPENPGP) + xSecContexts.push_back(aSignatureManager.getGpgSecurityContext()); + } + + CertificateChooser* aChooser = CertificateChooser::getInstance(Application::GetFrameWeld(mxParentWindow), std::move(xSecContexts), eAction); + + if (aChooser->run() != RET_OK) + return { Reference< css::security::XCertificate >(nullptr) }; + + uno::Sequence< Reference< css::security::XCertificate > > xCerts = aChooser->GetSelectedCertificates(); + rProperties["Description"] = aChooser->GetDescription(); + rProperties["Usage"] = aChooser->GetUsageText(); + + return xCerts; +} + +Reference< css::security::XCertificate > DocumentDigitalSignatures::chooseCertificate(OUString& rDescription) +{ + return chooseSigningCertificate( rDescription ); +} + +Reference< css::security::XCertificate > DocumentDigitalSignatures::chooseSigningCertificate(OUString& rDescription) +{ + std::map 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 aProperties; + Reference< css::security::XCertificate > xCert = chooseCertificatesImpl( aProperties, UserAction::SelectSign )[0]; + rDescription = aProperties["Description"]; + return xCert; +} + +Reference +DocumentDigitalSignatures::selectSigningCertificateWithType(const CertificateKind certificateKind, + OUString& rDescription) +{ + std::map aProperties; + Reference xCert + = chooseCertificatesImpl(aProperties, UserAction::SelectSign, certificateKind)[0]; + rDescription = aProperties["Description"]; + return xCert; +} + +css::uno::Sequence< Reference< css::security::XCertificate > > DocumentDigitalSignatures::chooseEncryptionCertificate() +{ + std::map 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 aProperties; + auto xCert = chooseCertificatesImpl( aProperties, UserAction::Sign )[0]; + + std::vector 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 const & xCertificate, + css::uno::Reference const & xStorage, + css::uno::Reference const & xStream) +{ + uno::Reference xModel; + return signWithCertificateImpl(xModel, xCertificate, xStorage, xStream, + DocumentSignatureMode::Content); +} + +bool DocumentDigitalSignatures::SignModelWithCertificate( + const uno::Reference& xModel, + const css::uno::Reference& xCertificate, + const css::uno::Reference& xStorage, + const css::uno::Reference& xStream) +{ + return signWithCertificateImpl(xModel, xCertificate, xStorage, xStream, + DocumentSignatureMode::Content); +} + +sal_Bool DocumentDigitalSignatures::signPackageWithCertificate( + css::uno::Reference const& xCertificate, + css::uno::Reference const& xStorage, + css::uno::Reference const& xStream) +{ + uno::Reference xModel; + return signWithCertificateImpl(xModel, xCertificate, xStorage, xStream, + DocumentSignatureMode::Package); +} + +sal_Bool DocumentDigitalSignatures::signScriptingContentWithCertificate( + css::uno::Reference const& xCertificate, + css::uno::Reference const& xStorage, + css::uno::Reference const& xStream) +{ + uno::Reference xModel; + return signWithCertificateImpl(xModel, xCertificate, xStorage, xStream, + DocumentSignatureMode::Macros); +} + +bool DocumentDigitalSignatures::signWithCertificateImpl( + const uno::Reference& xModel, + css::uno::Reference const& xCertificate, + css::uno::Reference const& xStorage, + css::uno::Reference 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 xSecurityContext; + Reference xServiceInfo(xCertificate, UNO_QUERY); + if (xServiceInfo->getImplementationName() + == "com.sun.star.xml.security.gpg.XCertificate_GpgImpl") + xSecurityContext = aSignatureManager.getGpgSecurityContext(); + else + xSecurityContext = aSignatureManager.getSecurityContext(); + + sal_Int32 nSecurityId; + + bool bSuccess = aSignatureManager.add(xCertificate, xSecurityContext, "", nSecurityId, true); + if (!bSuccess) + return false; + + aSignatureManager.read(/*bUseTempStream=*/true, /*bCacheLastSignature=*/false); + aSignatureManager.write(true); + + if (xStorage.is() && !xStream.is()) + { + uno::Reference 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 const& /*rSeq*/) +{ + return cppu::acquire( + new DocumentDigitalSignatures(uno::Reference(pCtx))); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/dialogs/certificatechooser.cxx b/xmlsecurity/source/dialogs/certificatechooser.cxx new file mode 100644 index 0000000000..9dba3e9e90 --- /dev/null +++ b/xmlsecurity/source/dialogs/certificatechooser.cxx @@ -0,0 +1,377 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + + +#include +#include + +using namespace comphelper; +using namespace css; + +CertificateChooser::CertificateChooser(weld::Window* _pParent, + std::vector< css::uno::Reference< css::xml::crypto::XXMLSecurityContext > > && rxSecurityContexts, + UserAction eAction) + : GenericDialogController(_pParent, "xmlsec/ui/selectcertificatedialog.ui", "SelectCertificateDialog") + , meAction(eAction) + , m_xFTSign(m_xBuilder->weld_label("sign")) + , m_xFTEncrypt(m_xBuilder->weld_label("encrypt")) + , m_xCertLB(m_xBuilder->weld_tree_view("signatures")) + , m_xViewBtn(m_xBuilder->weld_button("viewcert")) + , m_xOKBtn(m_xBuilder->weld_button("ok")) + , m_xFTDescription(m_xBuilder->weld_label("description-label")) + , m_xDescriptionED(m_xBuilder->weld_entry("description")) + , m_xSearchBox(m_xBuilder->weld_entry("searchbox")) + , m_xReloadBtn(m_xBuilder->weld_button("reloadcert")) +{ + auto nControlWidth = m_xCertLB->get_approximate_digit_width() * 105; + m_xCertLB->set_size_request(nControlWidth, m_xCertLB->get_height_rows(12)); + m_xCertLB->make_sorted(); + + m_xCertLB->connect_changed( LINK( this, CertificateChooser, CertificateHighlightHdl ) ); + m_xCertLB->connect_row_activated( LINK( this, CertificateChooser, CertificateSelectHdl ) ); + m_xViewBtn->connect_clicked( LINK( this, CertificateChooser, ViewButtonHdl ) ); + m_xSearchBox->connect_changed(LINK(this, CertificateChooser, SearchModifyHdl)); + m_xReloadBtn->connect_clicked( LINK( this, CertificateChooser, ReloadButtonHdl ) ); + + mxSecurityContexts = std::move(rxSecurityContexts); + mbInitialized = false; + + // disable buttons + CertificateHighlightHdl(*m_xCertLB); +} + +CertificateChooser::~CertificateChooser() +{ +} + +short CertificateChooser::run() +{ + // #i48432# + // We can't check for personal certificates before raising this dialog, + // because the mozilla implementation throws a NoPassword exception, + // if the user pressed cancel, and also if the database does not exist! + // But in the later case, the is no password query, and the user is confused + // that nothing happens when pressing "Add..." in the SignatureDialog. + + // PostUserEvent( LINK( this, CertificateChooser, Initialize ) ); + + // PostUserLink behavior is too slow, so do it directly before Execute(). + // Problem: This Dialog should be visible right now, and the parent should not be accessible. + // Show, Update, DisableInput... + + m_xDialog->show(); + ImplInitialize(); + return GenericDialogController::run(); +} + +void CertificateChooser::HandleOneUsageBit(OUString& string, int& bits, int bit, TranslateId pResId) +{ + if (bits & bit) + { + if (!string.isEmpty()) + string += ", "; + string += XsResId(pResId); + bits &= ~bit; + } +} + +OUString CertificateChooser::UsageInClearText(int bits) +{ + OUString result; + + HandleOneUsageBit(result, bits, 0x80, STR_DIGITAL_SIGNATURE); + HandleOneUsageBit(result, bits, 0x40, STR_NON_REPUDIATION); + HandleOneUsageBit(result, bits, 0x20, STR_KEY_ENCIPHERMENT); + HandleOneUsageBit(result, bits, 0x10, STR_DATA_ENCIPHERMENT); + HandleOneUsageBit(result, bits, 0x08, STR_KEY_AGREEMENT); + HandleOneUsageBit(result, bits, 0x04, STR_KEY_CERT_SIGN); + HandleOneUsageBit(result, bits, 0x02, STR_CRL_SIGN); + HandleOneUsageBit(result, bits, 0x01, STR_ENCIPHER_ONLY); + + // Check for mystery leftover bits + if (bits != 0) + { + if (!result.isEmpty()) + result += ", "; + result += "0x" + OUString::number(bits, 16); + } + + return result; +} + +void CertificateChooser::ImplInitialize(bool mbSearch) +{ + if (mbInitialized && !mbSearch) + return; + + m_xCertLB->clear(); + m_xCertLB->freeze(); + + SvtUserOptions aUserOpts; + + SvtSysLocale aSysLocale; + const CharClass& rCharClass = aSysLocale.GetCharClass(); + const OUString aSearchStr(rCharClass.uppercase(m_xSearchBox->get_text())); + + switch (meAction) + { + case UserAction::Sign: + m_xFTSign->show(); + m_xOKBtn->set_label(XsResId(STR_SIGN)); + msPreferredKey = aUserOpts.GetSigningKey(); + break; + + case UserAction::SelectSign: + m_xFTSign->show(); + m_xOKBtn->set_label(XsResId(STR_SELECTSIGN)); + msPreferredKey = aUserOpts.GetSigningKey(); + break; + + case UserAction::Encrypt: + m_xFTEncrypt->show(); + m_xFTDescription->hide(); + m_xDescriptionED->hide(); + m_xCertLB->set_selection_mode(SelectionMode::Multiple); + m_xOKBtn->set_label(XsResId(STR_ENCRYPT)); + msPreferredKey = aUserOpts.GetEncryptionKey(); + break; + + } + + ::std::optional oSelectRow; + uno::Sequence> xCerts; + for (auto& secContext : mxSecurityContexts) + { + if (!secContext.is()) + continue; + auto secEnvironment = secContext->getSecurityEnvironment(); + if (!secEnvironment.is()) + continue; + + try + { + if (xMemCerts.count(secContext)) + { + xCerts = xMemCerts[secContext]; + } + else + { + if (meAction == UserAction::Sign || meAction == UserAction::SelectSign) + xCerts = secEnvironment->getPersonalCertificates(); + else + xCerts = secEnvironment->getAllCertificates(); + + for (sal_Int32 nCert = xCerts.getLength(); nCert;) + { + uno::Reference< security::XCertificate > xCert = xCerts[ --nCert ]; + // Check if we have a private key for this... + tools::Long nCertificateCharacters = secEnvironment->getCertificateCharacters(xCert); + + if (!(nCertificateCharacters & security::CertificateCharacters::HAS_PRIVATE_KEY)) + { + ::comphelper::removeElementAt( xCerts, nCert ); + } + } + xMemCerts[secContext] = xCerts; + } + } + catch (security::NoPasswordException&) + { + } + + // fill list of certificates; the first entry will be selected + for (const auto& xCert : std::as_const(xCerts)) + { + std::shared_ptr userData = std::make_shared(); + userData->xCertificate = xCert; + userData->xSecurityContext = secContext; + userData->xSecurityEnvironment = secEnvironment; + mvUserData.push_back(userData); + + OUString sIssuer = xmlsec::GetContentPart( xCert->getIssuerName(), xCert->getCertificateKind()); + OUString sExpDate = utl::GetDateString(xCert->getNotValidAfter()); + + // If we are searching and there is no match skip + if (mbSearch + && rCharClass.uppercase(sIssuer).indexOf(aSearchStr) < 0 + && rCharClass.uppercase(sIssuer).indexOf(aSearchStr) < 0 + && !aSearchStr.isEmpty()) + continue; + + m_xCertLB->append(); + int nRow = m_xCertLB->n_children() - 1; + OUString sId(weld::toId(userData.get())); + m_xCertLB->set_id(nRow, sId); + m_xCertLB->set_text(nRow, xmlsec::GetContentPart(xCert->getSubjectName(), xCert->getCertificateKind()), 0); + m_xCertLB->set_text(nRow, sIssuer, 1); + m_xCertLB->set_text(nRow, sExpDate, 2); + +#if HAVE_FEATURE_GPGME + // only GPG has preferred keys + if ( !sIssuer.isEmpty() && !msPreferredKey.isEmpty() ) { + if ( sIssuer == msPreferredKey ) + { + if ( meAction == UserAction::Sign || meAction == UserAction::SelectSign ) + { + oSelectRow.emplace(nRow); + } + else if ( meAction == UserAction::Encrypt && + aUserOpts.GetEncryptToSelf() ) + mxEncryptToSelf = xCert; + } + } +#endif + } + } + + m_xCertLB->thaw(); + m_xCertLB->unselect_all(); + + if (oSelectRow) + { + m_xCertLB->select(*oSelectRow); + } + + CertificateHighlightHdl(*m_xCertLB); + mbInitialized = true; +} + +uno::Sequence > 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(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(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 CertificateChooser::GetSelectedSecurityContext() const +{ + int nSel = m_xCertLB->get_selected_index(); + if (nSel == -1) + return uno::Reference(); + + UserData* userData = weld::fromId(m_xCertLB->get_id(nSel)); + uno::Reference xCert = userData->xSecurityContext; + return xCert; +} + +OUString CertificateChooser::GetDescription() const +{ + return m_xDescriptionED->get_text(); +} + +OUString CertificateChooser::GetUsageText() +{ + uno::Sequence< uno::Reference > xCerts = + GetSelectedCertificates(); + return (xCerts.hasElements() && xCerts[0].is()) ? + UsageInClearText(xCerts[0]->getCertificateUsage()) : OUString(); +} + +void CertificateChooser::ImplReloadCertificates() +{ + xMemCerts.clear(); +} + +IMPL_LINK_NOARG(CertificateChooser, ReloadButtonHdl, weld::Button&, void) +{ + ImplReloadCertificates(); + mbInitialized = false; + ImplInitialize(); +} + +IMPL_LINK_NOARG(CertificateChooser, SearchModifyHdl, weld::Entry&, void) +{ + ImplInitialize(true); +} + +IMPL_LINK_NOARG(CertificateChooser, CertificateHighlightHdl, weld::TreeView&, void) +{ + bool bEnable = m_xCertLB->get_selected_index() != -1; + m_xViewBtn->set_sensitive(bEnable); + m_xOKBtn->set_sensitive(bEnable); + m_xDescriptionED->set_sensitive(bEnable); +} + +IMPL_LINK_NOARG(CertificateChooser, CertificateSelectHdl, weld::TreeView&, bool) +{ + m_xDialog->response(RET_OK); + return true; +} + +IMPL_LINK_NOARG(CertificateChooser, ViewButtonHdl, weld::Button&, void) +{ + ImplShowCertificateDetails(); +} + +void CertificateChooser::ImplShowCertificateDetails() +{ + int nSel = m_xCertLB->get_selected_index(); + if (nSel == -1) + return; + + UserData* userData = weld::fromId(m_xCertLB->get_id(nSel)); + + if (!userData->xSecurityEnvironment.is() || !userData->xCertificate.is()) + return; + + CertificateViewer aViewer(m_xDialog.get(), userData->xSecurityEnvironment, userData->xCertificate, true, this); + aViewer.run(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/dialogs/certificateviewer.cxx b/xmlsecurity/source/dialogs/certificateviewer.cxx new file mode 100644 index 0000000000..62de673c00 --- /dev/null +++ b/xmlsecurity/source/dialogs/certificateviewer.cxx @@ -0,0 +1,377 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +using namespace comphelper; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + +CertificateViewer::CertificateViewer(weld::Window* _pParent, + const css::uno::Reference< css::xml::crypto::XSecurityEnvironment >& _rxSecurityEnvironment, + const css::uno::Reference< css::security::XCertificate >& _rXCert, bool bCheckForPrivateKey, + CertificateChooser* pParentChooser) + : GenericDialogController(_pParent, "xmlsec/ui/viewcertdialog.ui", "ViewCertDialog") + , mbCheckForPrivateKey(bCheckForPrivateKey) + , mpParentChooser(pParentChooser) + , mxTabCtrl(m_xBuilder->weld_notebook("tabcontrol")) +{ + mxTabCtrl->connect_enter_page(LINK(this, CertificateViewer, ActivatePageHdl)); + + mxSecurityEnvironment = _rxSecurityEnvironment; + mxCert = _rXCert; + + mxGeneralPage.reset(new CertificateViewerGeneralTP(mxTabCtrl->get_page("general"), this)); + mxDetailsPage.reset(new CertificateViewerDetailsTP(mxTabCtrl->get_page("details"), this)); + if (!mxSecurityEnvironment->buildCertificatePath(mxCert).hasElements()) + mxTabCtrl->remove_page("path"); + else + mxPathId.reset(new CertificateViewerCertPathTP(mxTabCtrl->get_page("path"), this)); + mxTabCtrl->set_current_page("general"); +} + +IMPL_LINK(CertificateViewer, ActivatePageHdl, const OUString&, rPage, void) +{ + if (rPage == "path") + mxPathId->ActivatePage(); +} + +CertificateViewerTP::CertificateViewerTP(weld::Container* pParent, const OUString& rUIXMLDescription, + const OUString& rID, CertificateViewer* pDlg) + : mxBuilder(Application::CreateBuilder(pParent, rUIXMLDescription)) + , mxContainer(mxBuilder->weld_container(rID)) + , mpDlg(pDlg) +{ +} + +CertificateViewerGeneralTP::CertificateViewerGeneralTP(weld::Container* pParent, CertificateViewer* pDlg) + : CertificateViewerTP(pParent, "xmlsec/ui/certgeneral.ui", "CertGeneral", pDlg) + , m_xCertImg(mxBuilder->weld_image("certimage")) + , m_xHintNotTrustedFT(mxBuilder->weld_label("hintnotrust")) + , m_xIssuedToLabelFT(mxBuilder->weld_label("issued_to")) + , m_xIssuedToFT(mxBuilder->weld_label("issued_to_value")) + , m_xIssuedByLabelFT(mxBuilder->weld_label("issued_by")) + , m_xIssuedByFT(mxBuilder->weld_label("issued_by_value")) + , m_xValidFromDateFT(mxBuilder->weld_label("valid_from_value")) + , m_xValidToDateFT(mxBuilder->weld_label("valid_to_value")) + , m_xKeyImg(mxBuilder->weld_image("keyimage")) + , m_xHintCorrespPrivKeyFT(mxBuilder->weld_label("privatekey")) +{ + //Verify the certificate + sal_Int32 certStatus = mpDlg->mxSecurityEnvironment->verifyCertificate(mpDlg->mxCert, + Sequence >()); + + 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(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(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 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 >()); + 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 xIter = mxCertPathLB->make_iterator(); + if (mxCertPathLB->get_selected(xIter.get())) + { + if (mxCertificateViewer) + mxCertificateViewer->response(RET_OK); + + CertPath_UserData* pData = weld::fromId(mxCertPathLB->get_id(*xIter)); + mxCertificateViewer = std::make_shared(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 xIter = mxCertPathLB->make_iterator(); + bool bEntry = mxCertPathLB->get_selected(xIter.get()); + if (bEntry) + { + CertPath_UserData* pData = weld::fromId(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(rxCert, bValid)); + OUString sId(weld::toId(maUserData.back().get())); + mxCertPathLB->insert(pParent, -1, &rName, &sId, nullptr, nullptr, false, mxScratchIter.get()); + mxCertPathLB->set_image(*mxScratchIter, OUString(sImage)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx b/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx new file mode 100644 index 0000000000..3cd13c6060 --- /dev/null +++ b/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx @@ -0,0 +1,826 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#ifdef _WIN32 +#include +#include +#include +#endif + +using namespace comphelper; +using namespace css::security; +using namespace css::uno; +using namespace css; + +namespace +{ + class SaveODFItem: public utl::ConfigItem + { + private: + virtual void ImplCommit() override; + + public: + virtual void Notify( const css::uno::Sequence< OUString >& aPropertyNames ) override; + SaveODFItem(); + }; + + void SaveODFItem::ImplCommit() {} + void SaveODFItem::Notify( const css::uno::Sequence< OUString >& ) {} + + SaveODFItem::SaveODFItem(): utl::ConfigItem("Office.Common/Save") + { + OUString sDef("ODF/DefaultVersion"); + Sequence< css::uno::Any > aValues = GetProperties( Sequence(&sDef,1) ); + if ( aValues.getLength() != 1) + throw uno::RuntimeException( + "[xmlsecurity] Could not open property Office.Common/Save/ODF/DefaultVersion", + nullptr); + + sal_Int16 nTmp = 0; + if ( !(aValues[0] >>= nTmp) ) + throw uno::RuntimeException( + "[xmlsecurity]SaveODFItem::SaveODFItem(): Wrong Type!", + nullptr ); + } + +#ifdef _WIN32 + constexpr std::u16string_view aGUIServers[] + = { u"Gpg4win\\kleopatra.exe", + u"Gpg4win\\bin\\kleopatra.exe", + u"GNU\\GnuPG\\kleopatra.exe", + u"GNU\\GnuPG\\launch-gpa.exe", + u"GNU\\GnuPG\\gpa.exe", + u"GnuPG\\bin\\gpa.exe", + u"GNU\\GnuPG\\bin\\kleopatra.exe", + u"GNU\\GnuPG\\bin\\launch-gpa.exe", + u"GNU\\GnuPG\\bin\\gpa.exe"}; +#else + constexpr std::u16string_view aGUIServers[] + = { u"kleopatra", u"seahorse", u"gpa", u"kgpg"}; +#endif + +bool GetPathAllOS(OUString& aPath) +{ +#ifdef _WIN32 + sal::systools::CoTaskMemAllocated sPath; + HRESULT hr + = SHGetKnownFolderPath(FOLDERID_ProgramFilesX86, KF_FLAG_DEFAULT, nullptr, &sPath); + + if (FAILED(hr)) + return false; + aPath = o3tl::toU(sPath); +#else + const char* cPath = getenv("PATH"); + if (!cPath) + return false; + aPath = OUString(cPath, strlen(cPath), osl_getThreadTextEncoding()); +#endif + return (!aPath.isEmpty()); +} + +void GetCertificateManager(OUString& sExecutable) +{ + OUString aPath, aFoundGUIServer; + if (!GetPathAllOS(aPath)) + return; + + OUString aCetMgrConfig = officecfg::Office::Common::Security::Scripting::CertMgrPath::get(); + if (!aCetMgrConfig.isEmpty()) + { +#ifdef _WIN32 + sal_Int32 nLastBackslashIndex = aCetMgrConfig.lastIndexOf('\\'); +#else + sal_Int32 nLastBackslashIndex = aCetMgrConfig.lastIndexOf('/'); +#endif + osl::FileBase::RC searchError = osl::File::searchFileURL( + aCetMgrConfig.copy(0, nLastBackslashIndex + 1), aPath, + aFoundGUIServer); + if (searchError == osl::FileBase::E_None) + return; + } + + for (const auto& rServer: aGUIServers) + { + osl::FileBase::RC searchError = osl::File::searchFileURL( + OUString(rServer), aPath, + aFoundGUIServer); + if (searchError == osl::FileBase::E_None) + { + osl::File::getSystemPathFromFileURL(aFoundGUIServer, sExecutable); + std::shared_ptr pBatch( + comphelper::ConfigurationChanges::create()); + officecfg::Office::Common::Security::Scripting::CertMgrPath::set(sExecutable, + pBatch); + pBatch->commit(); + + return; + } + } +} + +bool IsThereCertificateMgr() +{ + OUString sExecutable; + GetCertificateManager(sExecutable); + return (!sExecutable.isEmpty()); +} +}//anonymous namespace + +DigitalSignaturesDialog::DigitalSignaturesDialog( + weld::Window* pParent, + const uno::Reference< uno::XComponentContext >& rxCtx, DocumentSignatureMode eMode, + bool bReadOnly, OUString sODFVersion, bool bHasDocumentSignature) + : GenericDialogController(pParent, "xmlsec/ui/digitalsignaturesdialog.ui", "DigitalSignaturesDialog") + , maSignatureManager(rxCtx, eMode) + , m_sODFVersion (std::move(sODFVersion)) + , m_bHasDocumentSignature(bHasDocumentSignature) + , m_bWarningShowSignMacro(false) + , m_xHintDocFT(m_xBuilder->weld_label("dochint")) + , m_xHintBasicFT(m_xBuilder->weld_label("macrohint")) + , m_xHintPackageFT(m_xBuilder->weld_label("packagehint")) + , m_xSignaturesLB(m_xBuilder->weld_tree_view("signatures")) + , m_xSigsValidImg(m_xBuilder->weld_image("validimg")) + , m_xSigsValidFI(m_xBuilder->weld_label("validft")) + , m_xSigsInvalidImg(m_xBuilder->weld_image("invalidimg")) + , m_xSigsInvalidFI(m_xBuilder->weld_label("invalidft")) + , m_xSigsNotvalidatedImg(m_xBuilder->weld_image("notvalidatedimg")) + , m_xSigsNotvalidatedFI(m_xBuilder->weld_label("notvalidatedft")) + , m_xSigsOldSignatureImg(m_xBuilder->weld_image("oldsignatureimg")) + , m_xSigsOldSignatureFI(m_xBuilder->weld_label("oldsignatureft")) + , m_xViewBtn(m_xBuilder->weld_button("view")) + , m_xAddBtn(m_xBuilder->weld_button("sign")) + , m_xRemoveBtn(m_xBuilder->weld_button("remove")) + , m_xStartCertMgrBtn(m_xBuilder->weld_button("start_certmanager")) + , m_xCloseBtn(m_xBuilder->weld_button("close")) +{ + auto nControlWidth = m_xSignaturesLB->get_approximate_digit_width() * 105; + m_xSignaturesLB->set_size_request(nControlWidth, m_xSignaturesLB->get_height_rows(10)); + + // Give the first column 6 percent, try to distribute the rest equally. + std::vector aWidths; + aWidths.push_back(6*nControlWidth/100); + auto nColWidth = (nControlWidth - aWidths[0]) / 4; + aWidths.push_back(nColWidth); + aWidths.push_back(nColWidth); + aWidths.push_back(nColWidth); + m_xSignaturesLB->set_column_fixed_widths(aWidths); + + mbVerifySignatures = true; + mbSignaturesChanged = false; + + m_xSignaturesLB->connect_changed( LINK( this, DigitalSignaturesDialog, SignatureHighlightHdl ) ); + m_xSignaturesLB->connect_row_activated( LINK( this, DigitalSignaturesDialog, SignatureSelectHdl ) ); + + m_xViewBtn->connect_clicked( LINK( this, DigitalSignaturesDialog, ViewButtonHdl ) ); + m_xViewBtn->set_sensitive(false); + + m_xAddBtn->connect_clicked( LINK( this, DigitalSignaturesDialog, AddButtonHdl ) ); + if ( bReadOnly ) + m_xAddBtn->set_sensitive(false); + + m_xRemoveBtn->connect_clicked( LINK( this, DigitalSignaturesDialog, RemoveButtonHdl ) ); + m_xRemoveBtn->set_sensitive(false); + + m_xStartCertMgrBtn->connect_clicked( LINK( this, DigitalSignaturesDialog, CertMgrButtonHdl ) ); + + m_xCloseBtn->connect_clicked( LINK( this, DigitalSignaturesDialog, OKButtonHdl) ); + + switch( maSignatureManager.getSignatureMode() ) + { + case DocumentSignatureMode::Content: + m_xHintDocFT->show(); + break; + case DocumentSignatureMode::Macros: + m_xHintBasicFT->show(); + break; + case DocumentSignatureMode::Package: + m_xHintPackageFT->show(); + break; + } + + if (comphelper::LibreOfficeKit::isActive()) + { + m_xAddBtn->hide(); + m_xRemoveBtn->hide(); + m_xStartCertMgrBtn->hide(); + } + + if (!IsThereCertificateMgr()) + { + m_xStartCertMgrBtn->set_sensitive(false); + } +} + +DigitalSignaturesDialog::~DigitalSignaturesDialog() +{ + if (m_xViewer) + m_xViewer->response(RET_OK); + + if (m_xInfoBox) + m_xInfoBox->response(RET_OK); +} + +bool DigitalSignaturesDialog::Init() +{ + bool bInit = maSignatureManager.init(); + + SAL_WARN_IF( !bInit, "xmlsecurity.dialogs", "Error initializing security context!" ); + + if ( bInit ) + { + maSignatureManager.getSignatureHelper().SetStartVerifySignatureHdl( LINK( this, DigitalSignaturesDialog, StartVerifySignatureHdl ) ); + } + + return bInit; +} + +void DigitalSignaturesDialog::SetStorage( const css::uno::Reference < css::embed::XStorage >& rxStore ) +{ + if (!rxStore.is()) + { + // PDF supports AdES. + m_bAdESCompliant = true; + return; + } + + // only ODF 1.1 wants to be non-XAdES (m_sODFVersion="1.0" for OOXML somehow?) + m_bAdESCompliant = !rxStore->hasByName("META-INF") // it's a Zip storage + || !DocumentSignatureHelper::isODFPre_1_2(m_sODFVersion); + + maSignatureManager.setStore(rxStore); + maSignatureManager.getSignatureHelper().SetStorage( maSignatureManager.getStore(), m_sODFVersion); +} + +void DigitalSignaturesDialog::SetSignatureStream( const css::uno::Reference < css::io::XStream >& rxStream ) +{ + maSignatureManager.setSignatureStream(rxStream); +} + +bool DigitalSignaturesDialog::canAddRemove() +{ + //FIXME: this func needs some cleanup, such as real split between + //'canAdd' and 'canRemove' case + uno::Reference xNameAccess = maSignatureManager.getStore(); + if (xNameAccess.is() && xNameAccess->hasByName("[Content_Types].xml")) + // It's always possible to append an OOXML signature. + return true; + + if (!maSignatureManager.getStore().is()) + // It's always possible to append a PDF signature. + return true; + + OSL_ASSERT(maSignatureManager.getStore().is()); + bool bDoc1_1 = DocumentSignatureHelper::isODFPre_1_2(m_sODFVersion); + SaveODFItem item; + + // see specification + //cvs: specs/www/appwide/security/Electronic_Signatures_and_Security.sxw + //Paragraph 'Behavior with regard to ODF 1.2' + //For both, macro and document + if ( bDoc1_1 ) + { + //#4 + std::unique_ptr xBox(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Warning, VclButtonsType::Ok, + XsResId(STR_XMLSECDLG_OLD_ODF_FORMAT))); + xBox->run(); + return false; + } + + //As of OOo 3.2 the document signature includes in macrosignatures.xml. That is + //adding a macro signature will break an existing document signature. + //The sfx2 will remove the documentsignature when the user adds a macro signature + if (maSignatureManager.getSignatureMode() == DocumentSignatureMode::Macros) + { + if (m_bHasDocumentSignature && !m_bWarningShowSignMacro) + { + //The warning says that the document signatures will be removed if the user + //continues. He can then either press 'OK' or 'NO' + //It the user presses 'Add' or 'Remove' several times then, then the warning + //is shown every time until the user presses 'OK'. From then on, the warning + //is not displayed anymore as long as the signatures dialog is alive. + std::unique_ptr xBox(Application::CreateMessageDialog( + m_xDialog.get(), VclMessageType::Question, VclButtonsType::YesNo, + XsResId(STR_XMLSECDLG_QUERY_REMOVEDOCSIGNBEFORESIGN))); + if (xBox->run() == RET_NO) + return false; + + m_bWarningShowSignMacro = true; + } + } + return true; +} + +bool DigitalSignaturesDialog::canAdd() { return canAddRemove(); } + +bool DigitalSignaturesDialog::canRemove() +{ + bool bRet = true; + + if ( maSignatureManager.getSignatureMode() == DocumentSignatureMode::Content ) + { + std::unique_ptr xBox(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Question, VclButtonsType::YesNo, + XsResId(STR_XMLSECDLG_QUERY_REALLYREMOVE))); + short nDlgRet = xBox->run(); + bRet = ( nDlgRet == RET_YES ); + } + + return (bRet && canAddRemove()); +} + +void DigitalSignaturesDialog::beforeRun() +{ + // Verify Signatures and add certificates to ListBox... + mbVerifySignatures = true; + ImplGetSignatureInformations(/*bUseTempStream=*/false, /*bCacheLastSignature=*/true); + ImplFillSignaturesBox(); + + // FIXME: Disable the "Use XAdES compliant signatures" checkbox if it is irrelevant. If it is + // enabled, set its initial state based on existing signatures, if any. + + // If it is OOXML, the checkbox is irrelevant. + + // How to find out here whether it is OOXML? I don't want to create a SignatureStreamHelper and + // check its nStorageFormat as that seems overly complicated and seems to have weird indirect + // consequences, as I noticed when I tried to use DocumentSignatureManager::IsXAdESRelevant() + // (which now is in #if 0). + + if (!maSignatureManager.getCurrentSignatureInformations().empty()) + { + // If the document has only SHA-1 signatures we probably want it to stay that way? + } + + // Only verify once, content will not change. + // But for refreshing signature information, StartVerifySignatureHdl will be called after each add/remove + mbVerifySignatures = false; +} + +short DigitalSignaturesDialog::run() +{ + beforeRun(); + return GenericDialogController::run(); +} + +IMPL_LINK_NOARG(DigitalSignaturesDialog, SignatureHighlightHdl, weld::TreeView&, void) +{ + bool bSel = m_xSignaturesLB->get_selected_index() != -1; + m_xViewBtn->set_sensitive( bSel ); + if ( m_xAddBtn->get_sensitive() ) // not read only + m_xRemoveBtn->set_sensitive( bSel ); +} + +IMPL_LINK_NOARG(DigitalSignaturesDialog, OKButtonHdl, weld::Button&, void) +{ + if (mbSignaturesChanged) + maSignatureManager.write(m_bAdESCompliant); + + m_xDialog->response(RET_OK); +} + +IMPL_LINK_NOARG(DigitalSignaturesDialog, SignatureSelectHdl, weld::TreeView&, bool) +{ + ImplShowSignaturesDetails(); + return true; +} + +IMPL_LINK_NOARG(DigitalSignaturesDialog, ViewButtonHdl, weld::Button&, void) +{ + ImplShowSignaturesDetails(); +} + +IMPL_LINK_NOARG(DigitalSignaturesDialog, AddButtonHdl, weld::Button&, void) +{ + if( ! canAdd()) + return; + try + { + std::vector> xSecContexts + { + maSignatureManager.getSecurityContext() + }; + // Gpg signing is only possible with ODF >= 1.2 documents + if (DocumentSignatureHelper::CanSignWithGPG(maSignatureManager.getStore(), m_sODFVersion)) + xSecContexts.push_back(maSignatureManager.getGpgSecurityContext()); + + CertificateChooser* aChooser = CertificateChooser::getInstance(m_xDialog.get(), std::move(xSecContexts), UserAction::Sign); + if (aChooser->run() == RET_OK) + { + sal_Int32 nSecurityId; + if (!maSignatureManager.add(aChooser->GetSelectedCertificates()[0], aChooser->GetSelectedSecurityContext(), + aChooser->GetDescription(), nSecurityId, m_bAdESCompliant)) + return; + mbSignaturesChanged = true; + + xml::crypto::SecurityOperationStatus nStatus = xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED; + + if (maSignatureManager.getStore().is()) + // In the PDF case the signature information is only available after parsing. + nStatus = maSignatureManager.getSignatureHelper().GetSignatureInformation( nSecurityId ).nStatus; + + if ( nStatus == css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED ) + { + mbSignaturesChanged = true; + + // Can't simply remember current information, need parsing for getting full information :( + // We need to verify the signatures again, otherwise the status in the signature information + // will not contain + // SecurityOperationStatus_OPERATION_SUCCEEDED + mbVerifySignatures = true; + ImplGetSignatureInformations(/*bUseTempStream=*/true, /*bCacheLastSignature=*/false); + ImplFillSignaturesBox(); + } + } + } + catch ( uno::Exception& ) + { + TOOLS_WARN_EXCEPTION( "xmlsecurity.dialogs", "adding a signature!" ); + std::unique_ptr xBox(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Error, VclButtonsType::Ok, + XsResId(STR_XMLSECDLG_SIGNING_FAILED))); + xBox->run(); + // Don't keep invalid entries... + ImplGetSignatureInformations(/*bUseTempStream=*/true, /*bCacheLastSignature=*/false); + ImplFillSignaturesBox(); + } +} + +IMPL_LINK_NOARG(DigitalSignaturesDialog, RemoveButtonHdl, weld::Button&, void) +{ + if (!canRemove()) + return; + int nEntry = m_xSignaturesLB->get_selected_index(); + if (nEntry == -1) + return; + + try + { + sal_uInt16 nSelected = m_xSignaturesLB->get_id(nEntry).toUInt32(); + maSignatureManager.remove(nSelected); + + mbSignaturesChanged = true; + + ImplFillSignaturesBox(); + } + catch ( uno::Exception& ) + { + TOOLS_WARN_EXCEPTION( "xmlsecurity.dialogs", "Exception while removing a signature!" ); + // Don't keep invalid entries... + ImplGetSignatureInformations(/*bUseTempStream=*/true, /*bCacheLastSignature=*/true); + ImplFillSignaturesBox(); + } +} + + +IMPL_LINK_NOARG(DigitalSignaturesDialog, CertMgrButtonHdl, weld::Button&, void) +{ + OUString sExecutable; + GetCertificateManager(sExecutable); + + if (!sExecutable.isEmpty()) + { + uno::Reference xContext + = ::comphelper::getProcessComponentContext(); + uno::Reference xSystemShell( + css::system::SystemShellExecute::create(xContext)); + + xSystemShell->execute(sExecutable, OUString(), + css::system::SystemShellExecuteFlags::DEFAULTS); + } + + OUString sDialogText = (sExecutable.isEmpty() ? + XsResId(STR_XMLSECDLG_NO_CERT_MANAGER) : XsResId(STR_XMLSECDLG_OPENED_CRTMGR) + sExecutable); + + std::unique_ptr xInfoBox(Application::CreateMessageDialog( + m_xDialog.get(), VclMessageType::Info, VclButtonsType::Ok, + sDialogText)); + xInfoBox->run(); +} + +IMPL_LINK_NOARG(DigitalSignaturesDialog, StartVerifySignatureHdl, LinkParamNone*, bool) +{ + return mbVerifySignatures; +} + +void DigitalSignaturesDialog::ImplFillSignaturesBox() +{ + m_xSignaturesLB->clear(); + + size_t nInfos = maSignatureManager.getCurrentSignatureInformations().size(); + size_t nValidSigs = 0, nValidCerts = 0; + bool bAllNewSignatures = true; + bool bSomePartial = false; + + if( nInfos ) + { + for( size_t n = 0; n < nInfos; ++n ) + { + DocumentSignatureAlgorithm mode = DocumentSignatureHelper::getDocumentAlgorithm( + m_sODFVersion, maSignatureManager.getCurrentSignatureInformations()[n]); + std::vector< OUString > aElementsToBeVerified; + if (maSignatureManager.getStore().is()) + aElementsToBeVerified = DocumentSignatureHelper::CreateElementList(maSignatureManager.getStore(), maSignatureManager.getSignatureMode(), mode); + + const SignatureInformation& rInfo = maSignatureManager.getCurrentSignatureInformations()[n]; + uno::Reference< css::security::XCertificate > xCert = getCertificate(rInfo); + + OUString aSubject; + OUString aIssuer; + OUString aDateTimeStr; + OUString aDescription; + OUString aType; + + bool bCertValid = false; + if( xCert.is() ) + { + //check the validity of the cert + try { + sal_Int32 certResult = getSecurityEnvironmentForCertificate(xCert)->verifyCertificate(xCert, + Sequence >()); + + 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 DigitalSignaturesDialog::getCertificate(const SignatureInformation& rInfo) +{ + uno::Reference xSecEnv = maSignatureManager.getSecurityEnvironment(); + uno::Reference xGpgSecEnv = maSignatureManager.getGpgSecurityEnvironment(); + uno::Reference 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 DigitalSignaturesDialog::getSecurityEnvironmentForCertificate(const uno::Reference& xCert) +{ + switch(xCert->getCertificateKind()) + { + case CertificateKind_OPENPGP: + return maSignatureManager.getGpgSecurityEnvironment(); + case CertificateKind_X509: + return maSignatureManager.getSecurityEnvironment(); + default: + throw RuntimeException("Unknown certificate kind"); + } +} + +//If bUseTempStream is true then the temporary signature stream is used. +//Otherwise the real signature stream is used. +void DigitalSignaturesDialog::ImplGetSignatureInformations(bool bUseTempStream, bool bCacheLastSignature) +{ + maSignatureManager.read(bUseTempStream, bCacheLastSignature); + mbVerifySignatures = false; +} + +void DigitalSignaturesDialog::ImplShowSignaturesDetails() +{ + int nEntry = m_xSignaturesLB->get_selected_index(); + if (nEntry == -1) + return; + + sal_uInt16 nSelected = m_xSignaturesLB->get_id(nEntry).toUInt32(); + const SignatureInformation& rInfo = maSignatureManager.getCurrentSignatureInformations()[ nSelected ]; + uno::Reference xCert = getCertificate(rInfo); + + if ( xCert.is() ) + { + if (m_xViewer) + m_xViewer->response(RET_OK); + + uno::Reference xSecEnv = getSecurityEnvironmentForCertificate(xCert); + m_xViewer = std::make_shared(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(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Info, VclButtonsType::Ok, + XsResId(STR_XMLSECDLG_NO_CERT_FOUND))); + m_xInfoBox->runAsync(m_xInfoBox, [this] (sal_Int32) { m_xInfoBox = nullptr; }); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/dialogs/macrosecurity.cxx b/xmlsecurity/source/dialogs/macrosecurity.cxx new file mode 100644 index 0000000000..ca4df4e64c --- /dev/null +++ b/xmlsecurity/source/dialogs/macrosecurity.cxx @@ -0,0 +1,447 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +using namespace comphelper; +using namespace ::com::sun::star; + + +IMPL_LINK_NOARG(MacroSecurity, OkBtnHdl, weld::Button&, void) +{ + m_xLevelTP->ClosePage(); + m_xTrustSrcTP->ClosePage(); + m_xDialog->response(RET_OK); +} + +MacroSecurity::MacroSecurity(weld::Window* pParent, + css::uno::Reference xSecurityEnvironment) + : GenericDialogController(pParent, "xmlsec/ui/macrosecuritydialog.ui", "MacroSecurityDialog") + , m_xSecurityEnvironment(std::move(xSecurityEnvironment)) + , m_xTabCtrl(m_xBuilder->weld_notebook("tabcontrol")) + , m_xOkBtn(m_xBuilder->weld_button("ok")) + , m_xResetBtn(m_xBuilder->weld_button("reset")) +{ + m_xTabCtrl->connect_enter_page(LINK(this, MacroSecurity, ActivatePageHdl)); + + m_xLevelTP.reset(new MacroSecurityLevelTP(m_xTabCtrl->get_page("SecurityLevelPage"), this)); + m_xTrustSrcTP.reset(new MacroSecurityTrustedSourcesTP(m_xTabCtrl->get_page("SecurityTrustPage"), this)); + + m_xTabCtrl->set_current_page("SecurityLevelPage"); + m_xOkBtn->connect_clicked(LINK(this, MacroSecurity, OkBtnHdl)); +} + +IMPL_LINK(MacroSecurity, ActivatePageHdl, const OUString&, rPage, void) +{ + if (rPage == "SecurityLevelPage") + m_xLevelTP->ActivatePage(); + else if (rPage == "SecurityTrustPage") + m_xTrustSrcTP->ActivatePage(); +} + +MacroSecurityTP::MacroSecurityTP(weld::Container* pParent, const OUString& rUIXMLDescription, + const OUString& rID, MacroSecurity* pDlg) + : m_xBuilder(Application::CreateBuilder(pParent, rUIXMLDescription)) + , m_xContainer(m_xBuilder->weld_container(rID)) + , m_pDlg(pDlg) +{ +} + +void MacroSecurityTP::ActivatePage() +{ +} + +MacroSecurityTP::~MacroSecurityTP() +{ +} + +MacroSecurityLevelTP::MacroSecurityLevelTP(weld::Container* pParent, MacroSecurity* pDlg) + : MacroSecurityTP(pParent, "xmlsec/ui/securitylevelpage.ui", "SecurityLevelPage", pDlg) + , m_xVeryHighRB(m_xBuilder->weld_radio_button("vhigh")) + , m_xHighRB(m_xBuilder->weld_radio_button("high")) + , m_xMediumRB(m_xBuilder->weld_radio_button("med")) + , m_xLowRB(m_xBuilder->weld_radio_button("low")) + , m_xVHighImg(m_xBuilder->weld_widget("vhighimg")) + , m_xHighImg(m_xBuilder->weld_widget("highimg")) + , m_xMedImg(m_xBuilder->weld_widget("medimg")) + , m_xLowImg(m_xBuilder->weld_widget("lowimg")) +{ + m_xLowRB->connect_toggled( LINK( this, MacroSecurityLevelTP, RadioButtonHdl ) ); + m_xMediumRB->connect_toggled( LINK( this, MacroSecurityLevelTP, RadioButtonHdl ) ); + m_xHighRB->connect_toggled( LINK( this, MacroSecurityLevelTP, RadioButtonHdl ) ); + m_xVeryHighRB->connect_toggled( LINK( this, MacroSecurityLevelTP, RadioButtonHdl ) ); + + int nPrefWidth(std::max({m_xVeryHighRB->get_preferred_size().Width(), + m_xHighRB->get_preferred_size().Width(), + m_xMediumRB->get_preferred_size().Width(), + m_xLowRB->get_preferred_size().Width()})); + int nMaxWidth = m_xLowRB->get_approximate_digit_width() * 60; + if (nPrefWidth > nMaxWidth) + { + m_xLowRB->set_label_wrap(true); + m_xLowRB->set_size_request(nMaxWidth, -1); + m_xMediumRB->set_label_wrap(true); + m_xMediumRB->set_size_request(nMaxWidth, -1); + m_xHighRB->set_label_wrap(true); + m_xHighRB->set_size_request(nMaxWidth, -1); + m_xVeryHighRB->set_label_wrap(true); + m_xVeryHighRB->set_size_request(nMaxWidth, -1); + } + + mnCurLevel = static_cast(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 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 aWidths + { + o3tl::narrowing(nColWidth * 2), + o3tl::narrowing(nColWidth * 2) + }; + m_xTrustCertLB->set_column_fixed_widths(aWidths); + m_xTrustCertLB->set_size_request(nColWidth * 5.5, m_xTrustCertLB->get_height_rows(5)); + + m_xTrustCertLB->connect_changed( LINK( this, MacroSecurityTrustedSourcesTP, TrustCertLBSelectHdl ) ); + m_xViewCertPB->connect_clicked( LINK( this, MacroSecurityTrustedSourcesTP, ViewCertPBHdl ) ); + m_xViewCertPB->set_sensitive(false); + m_xRemoveCertPB->connect_clicked( LINK( this, MacroSecurityTrustedSourcesTP, RemoveCertPBHdl ) ); + m_xRemoveCertPB->set_sensitive(false); + + m_xTrustFileLocLB->connect_changed( LINK( this, MacroSecurityTrustedSourcesTP, TrustFileLocLBSelectHdl ) ); + m_xTrustFileLocLB->set_size_request(nColWidth * 5, m_xTrustFileLocLB->get_height_rows(5)); + m_xAddLocPB->connect_clicked( LINK( this, MacroSecurityTrustedSourcesTP, AddLocPBHdl ) ); + m_xRemoveLocPB->connect_clicked( LINK( this, MacroSecurityTrustedSourcesTP, RemoveLocPBHdl ) ); + m_xRemoveLocPB->set_sensitive(false); + + m_aTrustedAuthors = SvtSecurityOptions::GetTrustedAuthors(); + mbAuthorsReadonly = SvtSecurityOptions::IsReadOnly( SvtSecurityOptions::EOption::MacroTrustedAuthors ); + m_xTrustCertROFI->set_visible(mbAuthorsReadonly); + + FillCertLB(true); + + std::vector< OUString > aSecureURLs = SvtSecurityOptions::GetSecureURLs(); + mbURLsReadonly = SvtSecurityOptions::IsReadOnly( SvtSecurityOptions::EOption::SecureUrls ); + m_xTrustFileROFI->set_visible(mbURLsReadonly); + m_xAddLocPB->set_sensitive(!mbURLsReadonly); + + for (const auto& rSecureURL : aSecureURLs) + { + OUString aSystemFileURL( rSecureURL ); + osl::FileBase::getSystemPathFromFileURL( aSystemFileURL, aSystemFileURL ); + m_xTrustFileLocLB->append_text(aSystemFileURL); + } +} + +void MacroSecurityTrustedSourcesTP::ActivatePage() +{ + m_pDlg->EnableReset( false ); + FillCertLB(); +} + +void MacroSecurityTrustedSourcesTP::ClosePage() +{ + sal_Int32 nEntryCnt = m_xTrustFileLocLB->n_children(); + if( nEntryCnt ) + { + std::vector< OUString > aSecureURLs; + for (sal_Int32 i = 0; i < nEntryCnt; ++i) + { + OUString aURL(m_xTrustFileLocLB->get_text(i)); + osl::FileBase::getFileURLFromSystemPath( aURL, aURL ); + aSecureURLs.push_back(aURL); + } + + SvtSecurityOptions::SetSecureURLs( std::move(aSecureURLs) ); + } + // Trusted Path could not be removed (#i33584#) + // don't forget to remove the old saved SecureURLs + else + SvtSecurityOptions::SetSecureURLs( std::vector< OUString >() ); + + SvtSecurityOptions::SetTrustedAuthors( m_aTrustedAuthors ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/framework/buffernode.cxx b/xmlsecurity/source/framework/buffernode.cxx new file mode 100644 index 0000000000..4dfa9fbfe2 --- /dev/null +++ b/xmlsecurity/source/framework/buffernode.cxx @@ -0,0 +1,887 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "elementmark.hxx" +#include "elementcollector.hxx" +#include "buffernode.hxx" +#include +#include +#include +#include + +BufferNode::BufferNode( css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > xXMLElement ) + :m_pParent(nullptr), + m_pBlocker(nullptr), + m_bAllReceived(false), + m_xXMLElement(std::move(xXMLElement)) +{ +} + +bool BufferNode::isECOfBeforeModifyIncluded(sal_Int32 nIgnoredSecurityId) const +/****** BufferNode/isECOfBeforeModifyIncluded ******************************** + * + * NAME + * isECOfBeforeModifyIncluded -- checks whether there is some + * ElementCollector on this BufferNode, that has BEFORE-MODIFY priority. + * + * SYNOPSIS + * bExist = isECOfBeforeModifyIncluded(nIgnoredSecurityId); + * + * FUNCTION + * checks each ElementCollector on this BufferNode, if all following + * conditions are satisfied, then returns true: + * 1. the ElementCollector's priority is BEFOREMODIFY; + * 2. the ElementCollector's securityId can't be ignored. + * otherwise, returns false. + * + * INPUTS + * nIgnoredSecurityId - the security Id to be ignored. If it equals + * to UNDEFINEDSECURITYID, then no security Id + * will be ignored. + * + * RESULT + * bExist - true if a match found, false otherwise + ******************************************************************************/ +{ + return std::any_of(m_vElementCollectors.cbegin(), m_vElementCollectors.cend(), + [nIgnoredSecurityId](const ElementCollector* pElementCollector) { + return (nIgnoredSecurityId == css::xml::crypto::sax::ConstOfSecurityId::UNDEFINEDSECURITYID || + pElementCollector->getSecurityId() != nIgnoredSecurityId) && + (pElementCollector->getPriority() == css::xml::crypto::sax::ElementMarkPriority_BEFOREMODIFY); + }); +} + +void BufferNode::setReceivedAll() +/****** BufferNode/setReceiveAll ********************************************* + * + * NAME + * setReceivedAll -- indicates that the element in this BufferNode has + * been completely buffered. + * + * SYNOPSIS + * setReceivedAll(); + * + * FUNCTION + * sets the all-received flag and launches ElementCollector's notify + * process. + * + * INPUTS + * empty + * + * RESULT + * empty + ******************************************************************************/ +{ + m_bAllReceived = true; + elementCollectorNotify(); +} + + +void BufferNode::addElementCollector(const ElementCollector* pElementCollector) +/****** BufferNode/addElementCollector *************************************** + * + * NAME + * addElementCollector -- adds a new ElementCollector to this BufferNode. + * + * SYNOPSIS + * addElementCollector(pElementCollector); + * + * FUNCTION + * see NAME + * + * INPUTS + * pElementCollector - the ElementCollector to be added + * + * RESULT + * empty + ******************************************************************************/ +{ + m_vElementCollectors.push_back( pElementCollector ); + const_cast(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(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(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 > const & BufferNode::getChildren() const +{ + return m_vChildren; +} + +std::vector< std::unique_ptr > 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 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 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& 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& 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(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(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& 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(getNextNodeByTreeOrder()); + while (pNextBufferNode != nullptr) + { + if (pNextBufferNode == pFollowing) + { + rc = true; + break; + } + + pNextBufferNode = const_cast(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(getNextSibling()); + if (pNextSibling != nullptr) + { + return pNextSibling; + } + + /* + * Otherwise, it this buffer node has parent, then return + * its parent's following sibling. + */ + BufferNode* pNode = const_cast(this); + BufferNode* pParent; + BufferNode* pNextSiblingParent = nullptr; + + do + { + if (pNode == nullptr) + { + break; + } + + pParent = const_cast(pNode->getParent()); + if (pParent != nullptr) + { + pNextSiblingParent = const_cast(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& 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(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& 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(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& 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 const & i : m_vChildren ) + { + if (bChildFound) + { + rc = i.get(); + break; + } + + if( i.get() == pChild ) + { + bChildFound = true; + } + } + + return rc; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/framework/buffernode.hxx b/xmlsecurity/source/framework/buffernode.hxx new file mode 100644 index 0000000000..f59ae2f816 --- /dev/null +++ b/xmlsecurity/source/framework/buffernode.hxx @@ -0,0 +1,118 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include + +#include +#include + +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> m_vChildren; + + /* all ElementCollector holding this BufferNode */ + std::vector 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 m_xXMLElement; + +private: + bool isECInSubTreeIncluded(sal_Int32 nIgnoredSecurityId) const; + bool isECOfBeforeModifyInAncestorIncluded(sal_Int32 nIgnoredSecurityId) const; + bool isBlockerInSubTreeIncluded(sal_Int32 nIgnoredSecurityId) const; + const BufferNode* getNextChild(const BufferNode* pChild) const; + +public: + explicit BufferNode(css::uno::Reference 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> const& getChildren() const; + std::vector> releaseChildren(); + const BufferNode* getFirstChild() const; + void addChild(std::unique_ptr pChild, sal_Int32 nPosition); + void addChild(std::unique_ptr 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& getXMLElement() const + { + return m_xXMLElement; + } + void + setXMLElement(const css::uno::Reference& xXMLElement); + void notifyBranch(); + void elementCollectorNotify(); +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/framework/elementcollector.cxx b/xmlsecurity/source/framework/elementcollector.cxx new file mode 100644 index 0000000000..d8f7fb04e7 --- /dev/null +++ b/xmlsecurity/source/framework/elementcollector.cxx @@ -0,0 +1,138 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "elementmark.hxx" +#include "elementcollector.hxx" +#include +#include +#include + +ElementCollector::ElementCollector( + sal_Int32 nBufferId, + css::xml::crypto::sax::ElementMarkPriority nPriority, + bool bToModify, + css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > xReferenceResolvedListener) + :ElementMark(css::xml::crypto::sax::ConstOfSecurityId::UNDEFINEDSECURITYID, nBufferId), + m_nPriority(nPriority), + m_bToModify(bToModify), + m_bAbleToNotify(false), + m_bNotified(false), + m_xReferenceResolvedListener(std::move(xReferenceResolvedListener)) +/****** ElementCollector/ElementCollector ************************************* + * + * NAME + * ElementCollector -- constructor method + * + * SYNOPSIS + * ElementCollector(nSecurityId, nBufferId, nPriority, bToModify + * xReferenceResolvedListener); + * + * FUNCTION + * construct an ElementCollector object. + * + * INPUTS + * nSecurityId - represents which security entity the buffer node is + * related with. Either a signature or an encryption is + * a security entity. + * nBufferId - the id of the element buffered in the document + * wrapper component. The document wrapper component + * uses this id to search the particular buffered + * element. + * nPriority - the priority value. ElementCollector with lower + * priority value can't notify until all ElementCollectors + * with higher priority value have notified. + * bToModify - A flag representing whether this ElementCollector + * notification will cause the modification of its working + * element. + * xReferenceResolvedListener + * - the listener that this ElementCollector notifies to. + ******************************************************************************/ +{ + m_type = css::xml::crypto::sax::ElementMarkType_ELEMENTCOLLECTOR; +} + + +void ElementCollector::notifyListener() +/****** ElementCollector/notifyListener *************************************** + * + * NAME + * notifyListener -- enable the ability to notify the listener + * + * SYNOPSIS + * notifyListener(); + * + * FUNCTION + * enable the ability to notify the listener and try to notify then. + ******************************************************************************/ +{ + m_bAbleToNotify = true; + doNotify(); +} + +void ElementCollector::setReferenceResolvedListener( + const css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener >& xReferenceResolvedListener) +/****** ElementCollector/setReferenceResolvedListener ************************* + * + * NAME + * setReferenceResolvedListener -- configures a listener for the buffer + * node in this object + * + * SYNOPSIS + * setReferenceResolvedListener(xReferenceResolvedListener); + * + * FUNCTION + * configures a new listener and try to notify then. + * + * INPUTS + * xReferenceResolvedListener - the new listener + ******************************************************************************/ +{ + m_xReferenceResolvedListener = xReferenceResolvedListener; + doNotify(); +} + +void ElementCollector::doNotify() +/****** ElementCollector/doNotify ********************************************* + * + * NAME + * doNotify -- tries to notify the listener + * + * SYNOPSIS + * doNotify(); + * + * FUNCTION + * notifies the listener when all below conditions are satisfied: + * the listener has not been notified; + * the notify right is granted; + * the listener has already been configured; + * the security id has already been configure + ******************************************************************************/ +{ + if (!m_bNotified && + m_bAbleToNotify && + m_xReferenceResolvedListener.is() && + m_nSecurityId != css::xml::crypto::sax::ConstOfSecurityId::UNDEFINEDSECURITYID) + { + m_bNotified = true; + m_xReferenceResolvedListener->referenceResolved(m_nBufferId); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/framework/elementcollector.hxx b/xmlsecurity/source/framework/elementcollector.hxx new file mode 100644 index 0000000000..29447e882b --- /dev/null +++ b/xmlsecurity/source/framework/elementcollector.hxx @@ -0,0 +1,80 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include "elementmark.hxx" +#include +#include + +namespace com::sun::star::xml::crypto::sax { class XReferenceResolvedListener; } + +class ElementCollector : public ElementMark +/****** elementcollector.hxx/CLASS ElementCollector *************************** + * + * NAME + * ElementCollector -- Class to manipulate an element collector + * + * FUNCTION + * This class is derived from the ElementMark class. Beyond the function + * of the ElementMark class, this class also maintains the priority, and + * manages the notify process + ******************************************************************************/ +{ +private: + /* + * the notify priority, is one of following values: + * AFTERMODIFY - this ElementCollector will notify after all + * internal modifications have finished. + * BEFOREMODIFY - this ElementCollector must notify before any + * internal modification happens. + */ + css::xml::crypto::sax::ElementMarkPriority const m_nPriority; + + /* + * the modify flag, representing whether which elementcollector will + * modify its data. + */ + bool const m_bToModify; + + /* the notify enable flag, see notifyListener method */ + bool m_bAbleToNotify; + + /* whether the listener has been notified */ + bool m_bNotified; + + /* the listener to be notified */ + css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > m_xReferenceResolvedListener; + +public: + ElementCollector( + sal_Int32 nBufferId, + css::xml::crypto::sax::ElementMarkPriority nPriority, + bool bToModify, + css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > xReferenceResolvedListener); + + css::xml::crypto::sax::ElementMarkPriority getPriority() const { return m_nPriority;} + bool getModify() const { return m_bToModify;} + void notifyListener(); + void setReferenceResolvedListener( + const css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener >& referenceResolvedListener); + void doNotify(); +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/framework/elementmark.cxx b/xmlsecurity/source/framework/elementmark.cxx new file mode 100644 index 0000000000..71444d7cd3 --- /dev/null +++ b/xmlsecurity/source/framework/elementmark.cxx @@ -0,0 +1,64 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "elementmark.hxx" + +ElementMark::ElementMark(sal_Int32 nSecurityId, sal_Int32 nBufferId) + :m_pBufferNode(nullptr), + m_nSecurityId(nSecurityId), + m_nBufferId(nBufferId), + m_type(css::xml::crypto::sax::ElementMarkType_ELEMENTMARK) +/****** ElementMark/ElementMark *********************************************** + * + * NAME + * ElementMark -- constructor method + * + * SYNOPSIS + * ElementMark(nSecurityId, nBufferId); + * + * FUNCTION + * construct an ElementMark object. + * + * INPUTS + * nSecurityId - represents which security entity the buffer node is + * related with. Either a signature or an encryption is + * a security entity. + * nBufferId - the id of the element buffered in the document + * wrapper component. The document wrapper component + * uses this id to search the particular buffered + * element. + ******************************************************************************/ +{ +} + + +void ElementMark::setBufferNode(const BufferNode* pBufferNode) +{ + m_pBufferNode = const_cast(pBufferNode); +} + + +void ElementMark::setSecurityId(sal_Int32 nSecurityId) +{ + m_nSecurityId = nSecurityId; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/framework/elementmark.hxx b/xmlsecurity/source/framework/elementmark.hxx new file mode 100644 index 0000000000..94ca71fdfb --- /dev/null +++ b/xmlsecurity/source/framework/elementmark.hxx @@ -0,0 +1,67 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include + +class BufferNode; + +class ElementMark +/****** elementmark.hxx/CLASS ElementMark ************************************* + * + * NAME + * ElementMark -- Class to manipulate an element mark + * + * FUNCTION + * This class maintains the security id, buffer id and its type for a + * buffer node. + ******************************************************************************/ +{ +protected: + /* the BufferNode maintained by this object */ + BufferNode* m_pBufferNode; + + /* the security Id */ + sal_Int32 m_nSecurityId; + + /* the buffer Id */ + sal_Int32 const m_nBufferId; + + /* + * the type value, is one of following values: + * TYPEOFELEMENTMARK - the default value, represents a blocker if + * not changed + * TYPEOFELEMENTCOLLECTOR - represents an ElementCollector + */ + css::xml::crypto::sax::ElementMarkType m_type; + +public: + ElementMark(sal_Int32 nSecurityId, sal_Int32 nBufferId); + virtual ~ElementMark(){}; + + BufferNode* getBufferNode() const { return m_pBufferNode; } + void setBufferNode(const BufferNode* pBufferNode); + sal_Int32 getSecurityId() const { return m_nSecurityId; } + void setSecurityId(sal_Int32 nSecurityId); + css::xml::crypto::sax::ElementMarkType getType() const { return m_type; } + sal_Int32 getBufferId() const { return m_nBufferId; } +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/framework/saxeventkeeperimpl.cxx b/xmlsecurity/source/framework/saxeventkeeperimpl.cxx new file mode 100644 index 0000000000..b5a7f02728 --- /dev/null +++ b/xmlsecurity/source/framework/saxeventkeeperimpl.cxx @@ -0,0 +1,1152 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include +#include "buffernode.hxx" +#include "elementmark.hxx" +#include "elementcollector.hxx" +#include +#include +#include +#include +#include +#include +#include + +#include + +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(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(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& 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; igetNodeName(pBufferNode->getXMLElement())); + + BufferNode* pParent = const_cast(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 > 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 > 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(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 > 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(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(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(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(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(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(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; igetNameByIndex(static_cast(i)); + aAttributesRange[i].sValue =xAttribs->getValueByIndex(static_cast(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(m_pCurrentBufferNode->getParent()); + + pOldCurrentBufferNode->setReceivedAll(); + + if ((m_pCurrentBufferNode == m_pRootBufferNode.get()) && + m_xSAXEventKeeperStatusChangeListener.is()) + { + m_xSAXEventKeeperStatusChangeListener->collectionStatusChanged(false); + } + } + } + else + { + if (!m_bIsForwarding) + { + m_xXMLDocument->removeCurrentElement(); + } + } +} + +void SAL_CALL SAXEventKeeperImpl::characters( const OUString& aChars ) +{ + if (m_bIsForwarding) + return; + + if ((m_pCurrentBlockingBufferNode == nullptr) && m_xNextHandler.is()) + { + m_xNextHandler->characters(aChars); + } + + if ((m_pCurrentBlockingBufferNode != nullptr) || + (m_pCurrentBufferNode != m_pRootBufferNode.get())) + { + m_xCompressedDocumentHandler->compressedCharacters(aChars); + } +} + +void SAL_CALL SAXEventKeeperImpl::ignorableWhitespace( const OUString& aWhitespaces ) +{ + characters( aWhitespaces ); +} + +void SAL_CALL SAXEventKeeperImpl::processingInstruction( + const OUString& aTarget, const OUString& aData ) +{ + if (m_bIsForwarding) + return; + + if ((m_pCurrentBlockingBufferNode == nullptr) && m_xNextHandler.is()) + { + m_xNextHandler->processingInstruction(aTarget, aData); + } + + if ((m_pCurrentBlockingBufferNode != nullptr) || + (m_pCurrentBufferNode != m_pRootBufferNode.get())) + { + m_xCompressedDocumentHandler->compressedProcessingInstruction(aTarget, aData); + } +} + +void SAL_CALL SAXEventKeeperImpl::setDocumentLocator( const css::uno::Reference< css::xml::sax::XLocator >&) +{ +} + +/* XInitialization */ +void SAL_CALL SAXEventKeeperImpl::initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) +{ + OSL_ASSERT(aArguments.getLength() == 1); + + aArguments[0] >>= m_xXMLDocument; + m_xDocumentHandler.set( m_xXMLDocument, css::uno::UNO_QUERY ); + m_xCompressedDocumentHandler.set( m_xXMLDocument, css::uno::UNO_QUERY ); + + m_pRootBufferNode.reset( new BufferNode(m_xXMLDocument->getCurrentElement()) ); + m_pCurrentBufferNode = m_pRootBufferNode.get(); +} + +OUString SAXEventKeeperImpl_getImplementationName () +{ + return "com.sun.star.xml.security.framework.SAXEventKeeperImpl"; +} + +css::uno::Sequence< OUString > SAXEventKeeperImpl_getSupportedServiceNames( ) +{ + return { "com.sun.star.xml.crypto.sax.SAXEventKeeper" }; +} + +/* XServiceInfo */ +OUString SAL_CALL SAXEventKeeperImpl::getImplementationName( ) +{ + return SAXEventKeeperImpl_getImplementationName(); +} + +sal_Bool SAL_CALL SAXEventKeeperImpl::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL SAXEventKeeperImpl::getSupportedServiceNames( ) +{ + return SAXEventKeeperImpl_getSupportedServiceNames(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/framework/securityengine.cxx b/xmlsecurity/source/framework/securityengine.cxx new file mode 100644 index 0000000000..e276163d41 --- /dev/null +++ b/xmlsecurity/source/framework/securityengine.cxx @@ -0,0 +1,67 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include + + +SecurityEngine::SecurityEngine() + :m_nIdOfTemplateEC(-1), + m_nNumOfResolvedReferences(0), + m_nIdOfKeyEC(-1), + m_bMissionDone(false), + m_nSecurityId(-1), + m_nStatus(css::xml::crypto::SecurityOperationStatus_UNKNOWN) +{ +} + +/* XReferenceResolvedListener */ +void SAL_CALL SecurityEngine::referenceResolved( sal_Int32 /*referenceId*/) +{ + m_nNumOfResolvedReferences++; + tryToPerform(); +} + +/* XKeyCollector */ +void SAL_CALL SecurityEngine::setKeyId( sal_Int32 id ) +{ + m_nIdOfKeyEC = id; + tryToPerform(); +} + +/* XMissionTaker */ +sal_Bool SAL_CALL SecurityEngine::endMission( ) +{ + bool rc = m_bMissionDone; + + if (!rc) + { + clearUp( ); + + notifyResultListener(); + m_bMissionDone = true; + } + + m_xResultListener = nullptr; + m_xSAXEventKeeper = nullptr; + + return rc; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/framework/signaturecreatorimpl.cxx b/xmlsecurity/source/framework/signaturecreatorimpl.cxx new file mode 100644 index 0000000000..4371b7ae69 --- /dev/null +++ b/xmlsecurity/source/framework/signaturecreatorimpl.cxx @@ -0,0 +1,175 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include +#include +#include +#include +#include +#include + +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& 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(xSignatureTemplate), m_xSecurityEnvironment); + m_nStatus = xResultTemplate->getStatus(); + } + catch( css::uno::Exception& ) + { + m_nStatus = css::xml::crypto::SecurityOperationStatus_RUNTIMEERROR_FAILED; + } + + if (m_nStatus == css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED) + { + css::uno::Reference < css::xml::wrapper::XXMLElementWrapper > xResultSignature = xResultTemplate->getTemplate(); + m_xSAXEventKeeper->setElement(m_nIdOfTemplateEC, xResultSignature); + } +} + +void SignatureCreatorImpl::clearUp() const +/****** SignatureCreatorImpl/clearUp ***************************************** + * + * NAME + * clearUp -- clear up all resources used by the signature generation. + * + * SYNOPSIS + * clearUp( ); + * + * FUNCTION + * cleaning resources up includes: + * 1. SignatureEngine's clearing up; + * 2. releases the Blocker for the signature template element. + ******************************************************************************/ +{ + SignatureEngine::clearUp(); + + if (m_nIdOfBlocker != -1) + { + m_xSAXEventKeeper->removeBlocker(m_nIdOfBlocker); + } +} + +/* XBlockerMonitor */ +void SAL_CALL SignatureCreatorImpl::setBlockerId( sal_Int32 id ) +{ + m_nIdOfBlocker = id; + tryToPerform(); +} + +/* XSignatureCreationResultBroadcaster */ +void SAL_CALL SignatureCreatorImpl::addSignatureCreationResultListener( + const css::uno::Reference< css::xml::crypto::sax::XSignatureCreationResultListener >& listener ) +{ + m_xResultListener = listener; + tryToPerform(); +} + +void SAL_CALL SignatureCreatorImpl::removeSignatureCreationResultListener( + const css::uno::Reference< css::xml::crypto::sax::XSignatureCreationResultListener >&) +{ +} + +/* XInitialization */ +void SAL_CALL SignatureCreatorImpl::initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) +{ + OSL_ASSERT(aArguments.getLength() == 5); + + OUString ouTempString; + + aArguments[0] >>= ouTempString; + m_nSecurityId = ouTempString.toInt32(); + aArguments[1] >>= m_xSAXEventKeeper; + aArguments[2] >>= ouTempString; + m_nIdOfTemplateEC = ouTempString.toInt32(); + aArguments[3] >>= m_xSecurityEnvironment; + aArguments[4] >>= m_xXMLSignature; +} + + +OUString SignatureCreatorImpl_getImplementationName () +{ + return "com.sun.star.xml.security.framework.SignatureCreatorImpl"; +} + +css::uno::Sequence< OUString > SignatureCreatorImpl_getSupportedServiceNames( ) +{ + return { "com.sun.star.xml.crypto.sax.SignatureCreator" }; +} + +/* XServiceInfo */ +OUString SAL_CALL SignatureCreatorImpl::getImplementationName( ) +{ + return SignatureCreatorImpl_getImplementationName(); +} + +sal_Bool SAL_CALL SignatureCreatorImpl::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL SignatureCreatorImpl::getSupportedServiceNames( ) +{ + return SignatureCreatorImpl_getSupportedServiceNames(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/framework/signatureengine.cxx b/xmlsecurity/source/framework/signatureengine.cxx new file mode 100644 index 0000000000..0390ea7e61 --- /dev/null +++ b/xmlsecurity/source/framework/signatureengine.cxx @@ -0,0 +1,197 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include +#include +#include + +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 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 >(static_cast(const_cast(this)))); + + m_xSAXEventKeeper->removeElementCollector(m_nIdOfTemplateEC); + + for( const auto& i : m_vReferenceIds ) + { + xReferenceResolvedBroadcaster->removeReferenceResolvedListener( + i, + static_cast >(static_cast(const_cast(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 +#include +#include +#include +#include +#include + + +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& 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(xSignatureTemplate), m_xXMLSecurityContext); + m_nStatus = xResultTemplate->getStatus(); + } + catch( css::uno::Exception& ) + { + m_nStatus = css::xml::crypto::SecurityOperationStatus_RUNTIMEERROR_FAILED; + } +} + +/* XSignatureVerifyResultBroadcaster */ +void SAL_CALL SignatureVerifierImpl::addSignatureVerifyResultListener( + const css::uno::Reference< css::xml::crypto::sax::XSignatureVerifyResultListener >& listener ) +{ + m_xResultListener = listener; + tryToPerform(); +} + +void SAL_CALL SignatureVerifierImpl::removeSignatureVerifyResultListener( + const css::uno::Reference< css::xml::crypto::sax::XSignatureVerifyResultListener >&) +{ +} + +/* XInitialization */ +void SAL_CALL SignatureVerifierImpl::initialize( + const css::uno::Sequence< css::uno::Any >& aArguments ) +{ + OSL_ASSERT(aArguments.getLength() == 5); + + OUString ouTempString; + + aArguments[0] >>= ouTempString; + m_nSecurityId = ouTempString.toInt32(); + aArguments[1] >>= m_xSAXEventKeeper; + aArguments[2] >>= ouTempString; + m_nIdOfTemplateEC = ouTempString.toInt32(); + aArguments[3] >>= m_xXMLSecurityContext; + aArguments[4] >>= m_xXMLSignature; +} + + +OUString SignatureVerifierImpl_getImplementationName () +{ + return "com.sun.star.xml.security.framework.SignatureVerifierImpl"; +} + +css::uno::Sequence< OUString > SignatureVerifierImpl_getSupportedServiceNames( ) +{ + return { "com.sun.star.xml.crypto.sax.SignatureVerifier" }; +} + +/* XServiceInfo */ +OUString SAL_CALL SignatureVerifierImpl::getImplementationName( ) +{ + return SignatureVerifierImpl_getImplementationName(); +} + +sal_Bool SAL_CALL SignatureVerifierImpl::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL SignatureVerifierImpl::getSupportedServiceNames( ) +{ + return SignatureVerifierImpl_getSupportedServiceNames(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/framework/xmlsignaturetemplateimpl.cxx b/xmlsecurity/source/framework/xmlsignaturetemplateimpl.cxx new file mode 100644 index 0000000000..203f0fea20 --- /dev/null +++ b/xmlsecurity/source/framework/xmlsignaturetemplateimpl.cxx @@ -0,0 +1,113 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include + +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 seqServiceNames { "com.sun.star.xml.crypto.XMLSignatureTemplate" }; + return seqServiceNames ; +} + +OUString XMLSignatureTemplateImpl::impl_getImplementationName() { + return "com.sun.star.xml.security.framework.XMLSignatureTemplateImpl" ; +} + +//Helper for registry +Reference< XInterface > XMLSignatureTemplateImpl::impl_createInstance( const Reference< XMultiServiceFactory >& ) { + return Reference< XInterface >( *new XMLSignatureTemplateImpl ) ; +} +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/gpg/CertificateImpl.cxx b/xmlsecurity/source/gpg/CertificateImpl.cxx new file mode 100644 index 0000000000..b771c1282f --- /dev/null +++ b/xmlsecurity/source/gpg/CertificateImpl.cxx @@ -0,0 +1,248 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include "CertificateImpl.hxx" + +#include +#include +#include + +#include +#include +#include + +#include +#include + +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( + keyId, strlen(keyId)+1); +} + +Sequence 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( + 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( + keyId, strlen(keyId)+1); +} + +CertificateKind SAL_CALL CertificateImpl::getCertificateKind() +{ + return CertificateKind_OPENPGP; +} + +sal_Int32 SAL_CALL CertificateImpl::getCertificateUsage() +{ + return KeyUsage::DIGITAL_SIGNATURE | KeyUsage::NON_REPUDIATION | KeyUsage::KEY_ENCIPHERMENT | KeyUsage::DATA_ENCIPHERMENT; +} + +void CertificateImpl::setCertificate(GpgME::Context* ctx, const GpgME::Key& key) +{ + m_pKey = key; + + // extract key data, store into m_aBits + GpgME::Data data_out; + ctx->setArmor(false); // caller will base64-encode anyway + GpgME::Error err = ctx->exportPublicKeys( + key.primaryFingerprint(), + data_out, + officecfg::Office::Common::Security::OpenPGP::MinimalKeyExport::get() + ? GpgME::Context::ExportMinimal : 0 + ); + + if (err) + throw RuntimeException("The GpgME library failed to retrieve the public key"); + + off_t result = data_out.seek(0,SEEK_SET); + (void) result; + assert(result == 0); + int len=0, curr=0; char buf; + while( (curr=data_out.read(&buf, 1)) ) + len += curr; + + // write bits to sequence of bytes + m_aBits.realloc(len); + result = data_out.seek(0,SEEK_SET); + assert(result == 0); + if( data_out.read(m_aBits.getArray(), len) != len ) + throw RuntimeException("The GpgME library failed to read the key"); +} + +const GpgME::Key* CertificateImpl::getCertificate() const +{ + return &m_pKey; +} + +/* XServiceInfo */ +OUString SAL_CALL CertificateImpl::getImplementationName() +{ + return "com.sun.star.xml.security.gpg.XCertificate_GpgImpl"; +} + +/* XServiceInfo */ +sal_Bool SAL_CALL CertificateImpl::supportsService(const OUString& serviceName) +{ + return cppu::supportsService(this, serviceName); +} + +/* XServiceInfo */ +Sequence SAL_CALL CertificateImpl::getSupportedServiceNames() { return { OUString() }; } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/gpg/CertificateImpl.hxx b/xmlsecurity/source/gpg/CertificateImpl.hxx new file mode 100644 index 0000000000..b0856ca010 --- /dev/null +++ b/xmlsecurity/source/gpg/CertificateImpl.hxx @@ -0,0 +1,93 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#if defined _MSC_VER && defined __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wundef" +#endif +#include +#if defined _MSC_VER && defined __clang__ +#pragma clang diagnostic pop +#endif + +class CertificateImpl : public cppu::WeakImplHelper< css::security::XCertificate, + css::lang::XServiceInfo >, + public xmlsecurity::Certificate +{ +private: + GpgME::Key m_pKey; + css::uno::Sequence< sal_Int8 > m_aBits; + +public: + CertificateImpl(); + virtual ~CertificateImpl() override; + + //Methods from XCertificate + virtual sal_Int16 SAL_CALL getVersion() override; + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSerialNumber() override; + + virtual OUString SAL_CALL getIssuerName() override; + virtual OUString SAL_CALL getSubjectName() override; + + virtual css::util::DateTime SAL_CALL getNotValidBefore() override; + virtual css::util::DateTime SAL_CALL getNotValidAfter() override; + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getIssuerUniqueID() override; + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSubjectUniqueID() override; + + virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificateExtension > > SAL_CALL getExtensions() override; + + virtual css::uno::Reference< css::security::XCertificateExtension > SAL_CALL findCertificateExtension(const css::uno::Sequence< sal_Int8 >& oid) override; + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getEncoded() override; + + virtual OUString SAL_CALL getSubjectPublicKeyAlgorithm() override; + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSubjectPublicKeyValue() override; + + virtual OUString SAL_CALL getSignatureAlgorithm() override; + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSHA1Thumbprint() override; + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getMD5Thumbprint() override; + + virtual sal_Int32 SAL_CALL getCertificateUsage() override; + + /// @see xmlsecurity::Certificate::getSHA256Thumbprint(). + virtual css::uno::Sequence 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 SAL_CALL getSupportedServiceNames() override; +} ; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/gpg/CipherContext.cxx b/xmlsecurity/source/gpg/CipherContext.cxx new file mode 100644 index 0000000000..291db0ba66 --- /dev/null +++ b/xmlsecurity/source/gpg/CipherContext.cxx @@ -0,0 +1,27 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "CipherContext.hxx" + +using namespace css; +using namespace css::uno; +using namespace css::lang; + +Sequence + SAL_CALL CipherContext::convertWithCipherContext(const Sequence& /*aData*/) +{ + return Sequence(); +} + +uno::Sequence SAL_CALL CipherContext::finalizeCipherContextAndDispose() +{ + return Sequence(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/gpg/CipherContext.hxx b/xmlsecurity/source/gpg/CipherContext.hxx new file mode 100644 index 0000000000..2c0ffcdc9b --- /dev/null +++ b/xmlsecurity/source/gpg/CipherContext.hxx @@ -0,0 +1,26 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include + +#include + +class CipherContext : public cppu::WeakImplHelper +{ +private: +public: + // XCipherContext + virtual css::uno::Sequence<::sal_Int8> + SAL_CALL convertWithCipherContext(const css::uno::Sequence<::sal_Int8>& aData) override; + virtual css::uno::Sequence<::sal_Int8> SAL_CALL finalizeCipherContextAndDispose() override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/gpg/DigestContext.cxx b/xmlsecurity/source/gpg/DigestContext.cxx new file mode 100644 index 0000000000..4864191bb8 --- /dev/null +++ b/xmlsecurity/source/gpg/DigestContext.cxx @@ -0,0 +1,23 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "DigestContext.hxx" + +using namespace css; +using namespace css::uno; +using namespace css::lang; + +void SAL_CALL DigestContext::updateDigest(const Sequence& /*aData*/) {} + +uno::Sequence SAL_CALL DigestContext::finalizeDigestAndDispose() +{ + return Sequence(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/gpg/DigestContext.hxx b/xmlsecurity/source/gpg/DigestContext.hxx new file mode 100644 index 0000000000..2d48daf344 --- /dev/null +++ b/xmlsecurity/source/gpg/DigestContext.hxx @@ -0,0 +1,24 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include + +#include + +class DigestContext : public cppu::WeakImplHelper +{ +public: + // XDigestContext + virtual void SAL_CALL updateDigest(const css::uno::Sequence<::sal_Int8>& aData) override; + virtual css::uno::Sequence<::sal_Int8> SAL_CALL finalizeDigestAndDispose() override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/gpg/SEInitializer.cxx b/xmlsecurity/source/gpg/SEInitializer.cxx new file mode 100644 index 0000000000..5cfe325aa8 --- /dev/null +++ b/xmlsecurity/source/gpg/SEInitializer.cxx @@ -0,0 +1,80 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include "SecurityEnvironment.hxx" +#include "XMLSecurityContext.hxx" + +#include + +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 SAL_CALL SEInitializerGpg::createSecurityContext(const OUString&) +{ + try + { + /* Build XML Security Context */ + Reference xSecCtx(new XMLSecurityContextGpg()); + + Reference 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&) {} + +/* XServiceInfo */ +sal_Bool SAL_CALL SEInitializerGpg::supportsService(const OUString& rServiceName) +{ + return cppu::supportsService(this, rServiceName); +} + +uno::Sequence 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 const& /*rSeq*/) +{ + return cppu::acquire(new SEInitializerGpg()); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/gpg/SecurityEnvironment.cxx b/xmlsecurity/source/gpg/SecurityEnvironment.cxx new file mode 100644 index 0000000000..e6813228a4 --- /dev/null +++ b/xmlsecurity/source/gpg/SecurityEnvironment.cxx @@ -0,0 +1,217 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "SecurityEnvironment.hxx" +#include "CertificateImpl.hxx" + +#include +#include + +#include +#include +#include + +#ifdef _WIN32 +#include +#include +#include +#include +#include +#endif + +#include +#include +#include + +#if defined _MSC_VER && defined __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wundef" +#endif +#include +#if defined _MSC_VER && defined __clang__ +#pragma clang diagnostic pop +#endif +#include + +using namespace css; +using namespace css::security; +using namespace css::uno; +using namespace css::lang; + +SecurityEnvironmentGpg::SecurityEnvironmentGpg() +{ +#ifdef _WIN32 + // On Windows, gpgme expects gpgme-w32spawn.exe to be in the same directory as the current + // process executable. This assumption might be wrong, e.g., for bundled python, which is + // in instdir/program/python-core-x.y.z/bin, while gpgme-w32spawn.exe is in instdir/program. + // If we can't find gpgme-w32spawn.exe in the current executable location, then try to find + // the spawn executable, and inform gpgme about actual location using gpgme_set_global_flag. + [[maybe_unused]] static bool bSpawnPathInitialized = [] { + auto accessUrl = [](const INetURLObject& url) { + osl::File file(url.GetMainURL(INetURLObject::DecodeMechanism::NONE)); + return file.open(osl_File_OpenFlag_Read) == osl::FileBase::E_None; + }; + OUString sPath; + osl_getExecutableFile(&sPath.pData); + INetURLObject aPathUrl(sPath); + aPathUrl.setName(u"gpgme-w32spawn.exe"); + if (!accessUrl(aPathUrl)) + { + sPath = "$BRAND_BASE_DIR/" LIBO_LIBEXEC_FOLDER "/gpgme-w32spawn.exe"; + rtl::Bootstrap::expandMacros(sPath); + aPathUrl.SetURL(sPath); + if (accessUrl(aPathUrl)) + { + aPathUrl.removeSegment(); + GpgME::setGlobalFlag("w32-inst-dir", + aPathUrl.getFSysPath(FSysStyle::Dos).toUtf8().getStr()); + } + } + return true; + }(); +#endif + GpgME::Error err = GpgME::checkEngine(GpgME::OpenPGP); + if (err) + throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol."); + + m_ctx.reset( GpgME::Context::createForProtocol(GpgME::OpenPGP) ); + if (m_ctx == nullptr) + throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol."); + m_ctx->setArmor(false); +} + +SecurityEnvironmentGpg::~SecurityEnvironmentGpg() +{ +} + +OUString SecurityEnvironmentGpg::getSecurityEnvironmentInformation() +{ + return OUString(); +} + +Sequence< Reference < XCertificate > > SecurityEnvironmentGpg::getCertificatesImpl( bool bPrivateOnly ) +{ + std::vector< GpgME::Key > keyList; + std::vector< rtl::Reference > 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 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(ostr.getStr()); + xmlSecSize nWritten; + int nRet = xmlSecBase64Decode_ex(strKeyId, const_cast(strKeyId), xmlStrlen(strKeyId), &nWritten); + if(nRet < 0) + throw RuntimeException("Base64 decode failed"); + + m_ctx->setKeyListMode(GPGME_KEYLIST_MODE_LOCAL); + GpgME::Error err = m_ctx->startKeyListing("", false); + while (!err) { + GpgME::Key k = m_ctx->nextKey(err); + if (err) + break; + if (!k.isInvalid() && strcmp(k.primaryFingerprint(), reinterpret_cast(strKeyId)) == 0) { + rtl::Reference 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(aCert.get()); + if (xCert == nullptr) { + // Can't find the key locally -> unknown owner + return security::CertificateValidity::ISSUER_UNKNOWN; + } + + const GpgME::Key* key = xCert->getCertificate(); + if (key->ownerTrust() == GpgME::Key::OwnerTrust::Marginal || + key->ownerTrust() == GpgME::Key::OwnerTrust::Full || + key->ownerTrust() == GpgME::Key::OwnerTrust::Ultimate) + { + return security::CertificateValidity::VALID; + } + + return security::CertificateValidity::ISSUER_UNTRUSTED; +} + +sal_Int32 SecurityEnvironmentGpg::getCertificateCharacters( + const Reference< XCertificate >& aCert) +{ + if (dynamic_cast(aCert.get()) == nullptr) + throw RuntimeException(); + + // we only listed private keys anyway, up in + // SecurityEnvironmentGpg::getPersonalCertificates + return CertificateCharacters::HAS_PRIVATE_KEY; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/gpg/SecurityEnvironment.hxx b/xmlsecurity/source/gpg/SecurityEnvironment.hxx new file mode 100644 index 0000000000..0c530c6715 --- /dev/null +++ b/xmlsecurity/source/gpg/SecurityEnvironment.hxx @@ -0,0 +1,65 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include + +#include + +#include +#include + +#include +#include + +namespace com::sun::star::security { class XCertificate; } +namespace GpgME { class Context; } + +class SecurityEnvironmentGpg : public cppu::WeakImplHelper< css::xml::crypto::XSecurityEnvironment > +{ + std::unique_ptr m_ctx; + +public: + SecurityEnvironmentGpg(); + virtual ~SecurityEnvironmentGpg() override; + + //Methods from XSecurityEnvironment + virtual ::sal_Int32 SAL_CALL verifyCertificate( + const css::uno::Reference< + css::security::XCertificate >& xCert, + const css::uno::Sequence< + css::uno::Reference< css::security::XCertificate > > & + intermediateCerts) override; + + virtual ::sal_Int32 SAL_CALL getCertificateCharacters( const css::uno::Reference< css::security::XCertificate >& xCert ) override; + + virtual OUString SAL_CALL getSecurityEnvironmentInformation() override; + + virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificate > > SAL_CALL getPersonalCertificates() override; + + /** We reinterpret the first parameter (originally issuerName) as keyId. We have no other way to identify a gpg key. */ + virtual css::uno::Reference< css::security::XCertificate > SAL_CALL getCertificate( const OUString& keyId, const css::uno::Sequence< sal_Int8 >& serialNumber ) override; + + virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificate > > SAL_CALL buildCertificatePath( + const css::uno::Reference< css::security::XCertificate >& beginCert ) override; + + virtual css::uno::Reference< css::security::XCertificate > SAL_CALL createCertificateFromRaw( + const css::uno::Sequence< sal_Int8 >& rawCertificate ) override; + virtual css::uno::Reference< css::security::XCertificate > SAL_CALL createCertificateFromAscii( + const OUString& asciiCertificate ) override; + + GpgME::Context& getGpgContext() { return *m_ctx; } + virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificate > > SAL_CALL getAllCertificates() override; + +private: + css::uno::Sequence< css::uno::Reference< css::security::XCertificate > > getCertificatesImpl( bool bPrivateOnly ); +} ; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/gpg/XMLEncryption.cxx b/xmlsecurity/source/gpg/XMLEncryption.cxx new file mode 100644 index 0000000000..65083ff68b --- /dev/null +++ b/xmlsecurity/source/gpg/XMLEncryption.cxx @@ -0,0 +1,37 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "XMLEncryption.hxx" + +using namespace css::uno; +using namespace css::lang; +using namespace css::xml::wrapper; +using namespace css::xml::crypto; + +XMLEncryptionGpg::XMLEncryptionGpg() { +} + +XMLEncryptionGpg::~XMLEncryptionGpg() { +} + +/* XXMLEncryption */ +Reference< XXMLEncryptionTemplate > SAL_CALL XMLEncryptionGpg::encrypt(const Reference< XXMLEncryptionTemplate >& /*aTemplate*/, + const Reference< XSecurityEnvironment >& /*aEnvironment*/) +{ + return nullptr; +} + +/* XXMLEncryption */ +Reference< XXMLEncryptionTemplate > SAL_CALL XMLEncryptionGpg::decrypt(const Reference< XXMLEncryptionTemplate >& /*aTemplate*/, + const Reference< XXMLSecurityContext >& /*aSecurityCtx*/) +{ + return nullptr; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/gpg/XMLEncryption.hxx b/xmlsecurity/source/gpg/XMLEncryption.hxx new file mode 100644 index 0000000000..4ff47ccc49 --- /dev/null +++ b/xmlsecurity/source/gpg/XMLEncryption.hxx @@ -0,0 +1,37 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include + +#include +#include + +namespace com::sun::star::xml::crypto { class XXMLEncryptionTemplate; } +namespace com::sun::star::xml::crypto { class XXMLSecurityContext; } + +class XMLEncryptionGpg : public cppu::WeakImplHelper< css::xml::crypto::XXMLEncryption > +{ +public: + explicit XMLEncryptionGpg(); + virtual ~XMLEncryptionGpg() override; + + // XXMLEncryption + virtual css::uno::Reference< css::xml::crypto::XXMLEncryptionTemplate > SAL_CALL encrypt( + const css::uno::Reference< css::xml::crypto::XXMLEncryptionTemplate >& aTemplate, + const css::uno::Reference< css::xml::crypto::XSecurityEnvironment >& aEnvironment) override; + + virtual css::uno::Reference< css::xml::crypto::XXMLEncryptionTemplate > SAL_CALL decrypt( + const css::uno::Reference< css::xml::crypto::XXMLEncryptionTemplate >& aTemplate, + const css::uno::Reference< css::xml::crypto::XXMLSecurityContext >& aContext) override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/gpg/XMLSecurityContext.cxx b/xmlsecurity/source/gpg/XMLSecurityContext.cxx new file mode 100644 index 0000000000..1fb407113f --- /dev/null +++ b/xmlsecurity/source/gpg/XMLSecurityContext.cxx @@ -0,0 +1,87 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "XMLSecurityContext.hxx" + +#include +#include + +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& 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 + 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 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 SAL_CALL XMLSecurityContextGpg::getSupportedServiceNames() +{ + return { OUString("com.sun.star.xml.crypto.XMLSecurityContext") }; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/gpg/XMLSecurityContext.hxx b/xmlsecurity/source/gpg/XMLSecurityContext.hxx new file mode 100644 index 0000000000..e3dea73101 --- /dev/null +++ b/xmlsecurity/source/gpg/XMLSecurityContext.hxx @@ -0,0 +1,58 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include +#include + +#include +#include +#include + +#include + +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 SAL_CALL getSecurityEnvironmentByIndex(sal_Int32 index) override; + + virtual css::uno::Reference SAL_CALL getSecurityEnvironment() override; + + virtual sal_Int32 SAL_CALL getDefaultSecurityEnvironmentIndex() override; + + virtual void SAL_CALL setDefaultSecurityEnvironmentIndex( sal_Int32 nDefaultEnvIndex ) override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override ; + + virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override ; + + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override ; +} ; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/gpg/xmlsignature_gpgimpl.cxx b/xmlsecurity/source/gpg/xmlsignature_gpgimpl.cxx new file mode 100644 index 0000000000..22488144f7 --- /dev/null +++ b/xmlsecurity/source/gpg/xmlsignature_gpgimpl.cxx @@ -0,0 +1,532 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include + +#if defined _MSC_VER && defined __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wundef" +#endif +#include +#if defined _MSC_VER && defined __clang__ +#pragma clang diagnostic pop +#endif +#include +#include +#include +#include +#include + +#include +#include +#include + +#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(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(aEnvironment.get()); + if( pSecEnv == nullptr ) + throw RuntimeException() ; + + setErrorRecorder(); + + //Create Signature context + pDsigCtx = xmlSecDSigCtxCreate( nullptr ) ; + if( pDsigCtx == nullptr ) + { + clearErrorRecorder(); + return aTemplate; + } + + // set intended operation to sign - several asserts inside libxmlsec + // wanting that for digest / transforms + pDsigCtx->operation = xmlSecTransformOperationSign; + + // we default to SHA512 for all digests - nss crypto does not have it... + //pDsigCtx->defDigestMethodId = xmlSecTransformSha512Id; + + // Calculate digest for all references + xmlNodePtr cur = xmlSecGetNextElementNode(pNode->children); + if( cur != nullptr ) + cur = xmlSecGetNextElementNode(cur->children); + while( cur != nullptr ) + { + // some of those children I suppose should be reference elements + if( xmlSecCheckNodeName(cur, xmlSecNodeReference, xmlSecDSigNs) ) + { + xmlSecDSigReferenceCtxPtr pDsigRefCtx = + xmlSecDSigReferenceCtxCreate(pDsigCtx, + xmlSecDSigReferenceOriginSignedInfo); + if(pDsigRefCtx == nullptr) + throw RuntimeException(); + + // add this one to the list + if( xmlSecPtrListAdd(&(pDsigCtx->signedInfoReferences), + pDsigRefCtx) < 0 ) + { + // TODO resource handling + xmlSecDSigReferenceCtxDestroy(pDsigRefCtx); + throw RuntimeException(); + } + + if( xmlSecDSigReferenceCtxProcessNode(pDsigRefCtx, cur) < 0 ) + throw RuntimeException(); + + // final check - all good? + if(pDsigRefCtx->status != xmlSecDSigStatusSucceeded) + { + pDsigCtx->status = xmlSecDSigStatusInvalid; + return aTemplate; // TODO - harder error? + } + } + + cur = xmlSecGetNextElementNode(cur->next); + } + + // get me a digestible buffer from the signature template! + // ------------------------------------------------------- + + // run the transformations over SignedInfo element (first child of + // pNode) + xmlSecNodeSetPtr nodeset = nullptr; + cur = xmlSecGetNextElementNode(pNode->children); + // TODO assert that... + nodeset = xmlSecNodeSetGetChildren(pNode->doc, cur, 1, 0); + if(nodeset == nullptr) + throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol."); + + if( xmlSecTransformCtxXmlExecute(&(pDsigCtx->transformCtx), nodeset) < 0 ) + throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol."); + + // now extract the keyid from PGPData + // walk xml tree to PGPData node - go to children, first is + // SignedInfo, 2nd is signaturevalue, 3rd is KeyInfo + // 1st child is PGPData, 1st grandchild is PGPKeyID + cur = xmlSecGetNextElementNode(pNode->children); + // TODO error handling + cur = xmlSecGetNextElementNode(cur->next); + cur = xmlSecGetNextElementNode(cur->next); + cur = xmlSecGetNextElementNode(cur->children); + // check that this is now PGPData + if(!xmlSecCheckNodeName(cur, xmlSecNodePGPData, xmlSecDSigNs)) + throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol."); + // check that this is now PGPKeyID + cur = xmlSecGetNextElementNode(cur->children); + static const xmlChar xmlSecNodePGPKeyID[] = "PGPKeyID"; + if(!xmlSecCheckNodeName(cur, xmlSecNodePGPKeyID, xmlSecDSigNs)) + throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol."); + + GpgME::Context& rCtx=pSecEnv->getGpgContext(); + rCtx.setKeyListMode(GPGME_KEYLIST_MODE_LOCAL); + GpgME::Error err; + xmlChar* pKey=xmlNodeGetContent(cur); + xmlSecSize nWritten; + int nRet = xmlSecBase64Decode_ex(pKey, reinterpret_cast(pKey), xmlStrlen(pKey), &nWritten); + if(nRet < 0) + throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol."); + if( rCtx.addSigningKey( + rCtx.key( + reinterpret_cast(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(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(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(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(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 aEnvironment = aSecurityCtx->getSecurityEnvironmentByIndex(i); + + SecurityEnvironmentGpg* pSecEnv = + dynamic_cast(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(xmlSecBufferGetData(pDsigCtx->transformCtx.result)), + xmlSecBufferGetSize(pDsigCtx->transformCtx.result), false); + + SAL_INFO("xmlsecurity.xmlsec.gpg", "Validating SignatureInfo: " << xmlSecBufferGetData(pDsigCtx->transformCtx.result)); + + // walk xml tree to sign value node - go to children, first is + // SignedInfo, 2nd is signaturevalue + cur = xmlSecGetNextElementNode(pNode->children); + cur = xmlSecGetNextElementNode(cur->next); + + if(!xmlSecCheckNodeName(cur, xmlSecNodeSignatureValue, xmlSecDSigNs)) + throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol."); + xmlChar* pSignatureValue=xmlNodeGetContent(cur); + xmlSecSize nSigSize; + int nRet = xmlSecBase64Decode_ex(pSignatureValue, reinterpret_cast(pSignatureValue), xmlStrlen(pSignatureValue), &nSigSize); + if( nRet < 0) + throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol."); + + GpgME::Data data_signature( + reinterpret_cast(pSignatureValue), + nSigSize, false); + + GpgME::VerificationResult verify_res=rCtx.verifyDetachedSignature( + data_signature, data_text); + + // TODO: needs some more error handling, needs checking _all_ signatures + if( verify_res.isNull() || verify_res.numSignatures() == 0 + // there is at least 1 signature and it is anything else than fully valid + || ( (verify_res.numSignatures() > 0) + && verify_res.signature(0).status().encodedError() > 0 ) ) + { + // let's try again, but this time import the public key + // payload (avoiding that in a first cut for being a bit + // speedier. also prevents all too easy poisoning/sha1 + // fingerprint collision attacks) + + // walk xml tree to PGPData node - go to children, first is + // SignedInfo, 2nd is signaturevalue, 3rd is KeyInfo + // 1st child is PGPData, 1st or 2nd grandchild is PGPKeyPacket + cur = xmlSecGetNextElementNode(pNode->children); + // TODO error handling + cur = xmlSecGetNextElementNode(cur->next); + cur = xmlSecGetNextElementNode(cur->next); + cur = xmlSecGetNextElementNode(cur->children); + // check that this is now PGPData + if(!xmlSecCheckNodeName(cur, xmlSecNodePGPData, xmlSecDSigNs)) + throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol."); + // check that this is now PGPKeyPacket + cur = xmlSecGetNextElementNode(cur->children); + static const xmlChar xmlSecNodePGPKeyPacket[] = "PGPKeyPacket"; + if(!xmlSecCheckNodeName(cur, xmlSecNodePGPKeyPacket, xmlSecDSigNs)) + { + // not this one, maybe the next? + cur = xmlSecGetNextElementNode(cur->next); + if(!xmlSecCheckNodeName(cur, xmlSecNodePGPKeyPacket, xmlSecDSigNs)) + { + // ok, giving up + clearErrorRecorder(); + xmlFree(pSignatureValue); + + return aTemplate; + } + } + + // got a key packet, import & re-validate + xmlChar* pKeyPacket=xmlNodeGetContent(cur); + xmlSecSize nKeyLen; + nRet = xmlSecBase64Decode_ex(pKeyPacket, reinterpret_cast(pKeyPacket), xmlStrlen(pKeyPacket), &nKeyLen); + if( nRet < 0) + throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol."); + + GpgME::Data data_key( + reinterpret_cast(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 seqServiceNames { "com.sun.star.xml.crypto.XMLSignature" }; + return seqServiceNames ; +} + +OUString XMLSignature_GpgImpl::impl_getImplementationName() { + return "com.sun.star.xml.security.bridge.xmlsec.XMLSignature_GpgImpl" ; +} + +//Helper for registry +Reference< XInterface > XMLSignature_GpgImpl::impl_createInstance( const Reference< XMultiServiceFactory >& ) { + return Reference< XInterface >( *new XMLSignature_GpgImpl ) ; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/helper/UriBindingHelper.cxx b/xmlsecurity/source/helper/UriBindingHelper.cxx new file mode 100644 index 0000000000..f6c36d2c8b --- /dev/null +++ b/xmlsecurity/source/helper/UriBindingHelper.cxx @@ -0,0 +1,113 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include +#include + +#include +#include +#include +#include +#include + +using namespace com::sun::star; + +// XUriBinding + +UriBindingHelper::UriBindingHelper() +{ +} + +UriBindingHelper::UriBindingHelper( const css::uno::Reference < css::embed::XStorage >& rxStorage ) +{ + mxStorage = rxStorage; +} + +void SAL_CALL UriBindingHelper::setUriBinding( const OUString& /*uri*/, const uno::Reference< io::XInputStream >&) +{ +} + +uno::Reference< io::XInputStream > SAL_CALL UriBindingHelper::getUriBinding( const OUString& uri ) +{ + uno::Reference< io::XInputStream > xInputStream; + if ( mxStorage.is() ) + { + xInputStream = OpenInputStream( mxStorage, uri ); + } + else + { + SvFileStream* pStream = new SvFileStream( uri, StreamMode::READ ); + sal_uInt64 nBytes = pStream->TellEnd(); + SvLockBytesRef xLockBytes = new SvLockBytes( pStream, true ); + xInputStream = new utl::OInputStreamHelper( xLockBytes, nBytes ); + } + return xInputStream; +} + +uno::Reference < io::XInputStream > UriBindingHelper::OpenInputStream( const uno::Reference < embed::XStorage >& rxStore, const OUString& rURI ) +{ + OSL_ASSERT(!rURI.isEmpty()); + uno::Reference < io::XInputStream > xInStream; + + OUString aURI(rURI); + // Ignore leading slash, don't attempt to open a storage with name "". + if (aURI.startsWith("/")) + aURI = aURI.copy(1); + // Ignore query part of the URI. + sal_Int32 nQueryPos = aURI.indexOf('?'); + if (nQueryPos != -1) + aURI = aURI.copy(0, nQueryPos); + + + sal_Int32 nSepPos = aURI.indexOf( '/' ); + if ( nSepPos == -1 ) + { + // Cloning because of I can't keep all storage references open + // MBA with think about a better API... + const OUString sName = ::rtl::Uri::decode( + aURI, rtl_UriDecodeStrict, rtl_UriCharClassRelSegment); + if (sName.isEmpty() && !aURI.isEmpty()) + throw uno::Exception("Could not decode URI for stream element.", nullptr); + + uno::Reference< io::XStream > xStream; + if (!rxStore->hasByName(sName)) + SAL_WARN("xmlsecurity.helper", "expected stream, but not found: " << sName); + else + xStream = rxStore->cloneStreamElement( sName ); + if ( !xStream.is() ) + throw uno::RuntimeException(); + xInStream = xStream->getInputStream(); + } + else + { + const OUString aStoreName = ::rtl::Uri::decode( + aURI.copy( 0, nSepPos ), rtl_UriDecodeStrict, rtl_UriCharClassRelSegment); + if (aStoreName.isEmpty() && !aURI.isEmpty()) + throw uno::Exception("Could not decode URI for stream element.", nullptr); + + OUString aElement = aURI.copy( nSepPos+1 ); + uno::Reference < embed::XStorage > xSubStore = rxStore->openStorageElement( aStoreName, embed::ElementModes::READ ); + xInStream = OpenInputStream( xSubStore, aElement ); + } + return xInStream; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/helper/documentsignaturehelper.cxx b/xmlsecurity/source/helper/documentsignaturehelper.cxx new file mode 100644 index 0000000000..8e666b14ba --- /dev/null +++ b/xmlsecurity/source/helper/documentsignaturehelper.cxx @@ -0,0 +1,650 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace css::xml::sax; + +namespace +{ +std::u16string_view getElement(std::u16string_view version, size_t * index) +{ + while (*index < version.size() && version[*index] == '0') { + ++*index; + } + return o3tl::getToken(version, u'.', *index); +} + + +// Return 1 if version1 is greater than version 2, 0 if they are equal +//and -1 if version1 is less version 2 +int compareVersions( + std::u16string_view version1, std::u16string_view version2) +{ + for (size_t i1 = 0, i2 = 0; i1 != std::u16string_view::npos || i2 != std::u16string_view::npos;) { + std::u16string_view e1(getElement(version1, &i1)); + std::u16string_view e2(getElement(version2, &i2)); + if (e1.size() < e2.size()) { + return -1; + } else if (e1.size() > e2.size()) { + return 1; + } else if (e1 < e2) { + return -1; + } else if (e1 > e2) { + return 1; + } + } + return 0; +} +} + +static void ImplFillElementList( + std::vector< OUString >& rList, const Reference < css::embed::XStorage >& rxStore, + std::u16string_view rRootStorageName, const bool bRecursive, + const DocumentSignatureAlgorithm mode) +{ + const Sequence< OUString > aElements = rxStore->getElementNames(); + + for ( const auto& rName : aElements ) + { + if (rName == "[Content_Types].xml") + // OOXML + continue; + + // If the user enabled validating according to OOo 3.0 + // then mimetype and all content of META-INF must be excluded. + if (mode != DocumentSignatureAlgorithm::OOo3_2 + && (rName == "META-INF" || rName == "mimetype")) + { + continue; + } + else + { + OUString sEncName = ::rtl::Uri::encode( + rName, rtl_UriCharClassRelSegment, + rtl_UriEncodeStrict, RTL_TEXTENCODING_UTF8); + if (sEncName.isEmpty() && !rName.isEmpty()) + throw css::uno::RuntimeException("Failed to encode element name of XStorage", nullptr); + + if ( rxStore->isStreamElement( rName ) ) + { + //Exclude documentsignatures.xml! + if (rName == + DocumentSignatureHelper::GetDocumentContentSignatureDefaultStreamName()) + continue; + OUString aFullName( rRootStorageName + sEncName ); + rList.push_back(aFullName); + } + else if ( bRecursive && rxStore->isStorageElement( rName ) ) + { + Reference < css::embed::XStorage > xSubStore = rxStore->openStorageElement( rName, css::embed::ElementModes::READ ); + OUString aFullRootName( rRootStorageName + sEncName + "/" ); + ImplFillElementList(rList, xSubStore, aFullRootName, bRecursive, mode); + } + } + } +} + + +bool DocumentSignatureHelper::isODFPre_1_2(std::u16string_view sVersion) +{ + //The property version exists only if the document is at least version 1.2 + //That is, if the document has version 1.1 and sVersion is empty. + //The constant is defined in comphelper/documentconstants.hxx + return compareVersions(sVersion, ODFVER_012_TEXT) == -1; +} + +bool DocumentSignatureHelper::isOOo3_2_Signature(const SignatureInformation & sigInfo) +{ + return std::any_of(sigInfo.vSignatureReferenceInfors.cbegin(), + sigInfo.vSignatureReferenceInfors.cend(), + [](const SignatureReferenceInformation& info) { return info.ouURI == "META-INF/manifest.xml"; }); +} + +DocumentSignatureAlgorithm +DocumentSignatureHelper::getDocumentAlgorithm( + std::u16string_view sODFVersion, const SignatureInformation & sigInfo) +{ + OSL_ASSERT(!sODFVersion.empty()); + DocumentSignatureAlgorithm mode = DocumentSignatureAlgorithm::OOo3_2; + if (!isOOo3_2_Signature(sigInfo)) + { + if (isODFPre_1_2(sODFVersion)) + mode = DocumentSignatureAlgorithm::OOo2; + else + mode = DocumentSignatureAlgorithm::OOo3_0; + } + return mode; +} + +//The function creates a list of files which are to be signed or for which +//the signature is to be validated. The strings are UTF8 encoded URIs which +//contain '/' as path separators. +// +//The algorithm how document signatures are created and validated has +//changed over time. The change affects only which files within the document +//are changed. Document signatures created by OOo 2.x only used particular files. Since +//OOo 3.0 everything except "mimetype" and "META-INF" are signed. As of OOo 3.2 everything +//except META-INF/documentsignatures.xml is signed. +//Signatures are validated according to the algorithm which was then used for validation. +//That is, when validating a signature which was created by OOo 3.0, then mimetype and +//META-INF are not used. +// +//When a signature is created then we always use the latest algorithm. That is, we use +//that of OOo 3.2 +std::vector< OUString > +DocumentSignatureHelper::CreateElementList( + const Reference < css::embed::XStorage >& rxStore, + DocumentSignatureMode eMode, + const DocumentSignatureAlgorithm mode) +{ + std::vector< OUString > aElements; + OUString aSep( "/" ); + + switch ( eMode ) + { + case DocumentSignatureMode::Content: + { + if (mode == DocumentSignatureAlgorithm::OOo2) //that is, ODF 1.0, 1.1 + { + // 1) Main content + ImplFillElementList(aElements, rxStore, std::u16string_view(), false, mode); + + // 2) Pictures... + OUString aSubStorageName( "Pictures" ); + try + { + Reference < css::embed::XStorage > xSubStore = rxStore->openStorageElement( aSubStorageName, css::embed::ElementModes::READ ); + ImplFillElementList( + aElements, xSubStore, Concat2View(aSubStorageName+aSep), true, mode); + } + catch(css::io::IOException& ) + { + ; // Doesn't have to exist... + } + // 3) OLE... + aSubStorageName = "ObjectReplacements"; + try + { + Reference < css::embed::XStorage > xSubStore = rxStore->openStorageElement( aSubStorageName, css::embed::ElementModes::READ ); + ImplFillElementList( + aElements, xSubStore, Concat2View(aSubStorageName+aSep), true, mode); + xSubStore.clear(); + + // Object folders... + const Sequence< OUString > aElementNames = rxStore->getElementNames(); + for ( const auto& rName : aElementNames ) + { + if ( ( rName.match( "Object " ) ) && rxStore->isStorageElement( rName ) ) + { + Reference < css::embed::XStorage > xTmpSubStore = rxStore->openStorageElement( rName, css::embed::ElementModes::READ ); + ImplFillElementList( + aElements, xTmpSubStore, Concat2View(rName+aSep), true, mode); + } + } + } + catch( css::io::IOException& ) + { + ; // Doesn't have to exist... + } + } + else + { + // Everything except META-INF + ImplFillElementList(aElements, rxStore, std::u16string_view(), true, mode); + } + } + break; + case DocumentSignatureMode::Macros: + { + // 1) Macros + OUString aSubStorageName( "Basic" ); + try + { + Reference < css::embed::XStorage > xSubStore = rxStore->openStorageElement( aSubStorageName, css::embed::ElementModes::READ ); + ImplFillElementList( + aElements, xSubStore, Concat2View(aSubStorageName+aSep), true, mode); + } + catch( css::io::IOException& ) + { + ; // Doesn't have to exist... + } + + // 2) Dialogs + aSubStorageName = "Dialogs"; + try + { + Reference < css::embed::XStorage > xSubStore = rxStore->openStorageElement( aSubStorageName, css::embed::ElementModes::READ ); + ImplFillElementList( + aElements, xSubStore, Concat2View(aSubStorageName+aSep), true, mode); + } + catch( css::io::IOException& ) + { + ; // Doesn't have to exist... + } + // 3) Scripts + aSubStorageName = "Scripts"; + try + { + Reference < css::embed::XStorage > xSubStore = rxStore->openStorageElement( aSubStorageName, css::embed::ElementModes::READ ); + ImplFillElementList( + aElements, xSubStore, Concat2View(aSubStorageName+aSep), true, mode); + } + catch( css::io::IOException& ) + { + ; // Doesn't have to exist... + } + } + break; + case DocumentSignatureMode::Package: + { + // Everything except META-INF + ImplFillElementList(aElements, rxStore, std::u16string_view(), true, mode); + } + break; + } + + return aElements; +} + +void DocumentSignatureHelper::AppendContentTypes(const uno::Reference& xStorage, std::vector& rElements) +{ + if (!xStorage.is() || !xStorage->hasByName("[Content_Types].xml")) + // ODF + return; + + uno::Reference xRelStream(xStorage->openStreamElement("[Content_Types].xml", embed::ElementModes::READ), uno::UNO_QUERY); + uno::Sequence< uno::Sequence > 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& rDefaults = aContentTypeInfo[0]; + const uno::Sequence& rOverrides = aContentTypeInfo[1]; + + for (OUString& rElement : rElements) + { + auto it = std::find_if(rOverrides.begin(), rOverrides.end(), [&](const beans::StringPair& rPair) + { + return rPair.First == Concat2View("/" + rElement); + }); + + if (it != rOverrides.end()) + { + rElement = "/" + rElement + "?ContentType=" + it->Second; + continue; + } + + it = std::find_if(rDefaults.begin(), rDefaults.end(), [&](const beans::StringPair& rPair) + { + return rElement.endsWith(Concat2View("." + rPair.First)); + }); + + if (it != rDefaults.end()) + { + rElement = "/" + rElement + "?ContentType=" + it->Second; + continue; + } + SAL_WARN("xmlsecurity.helper", "found no content type for " << rElement); + } + + std::sort(rElements.begin(), rElements.end()); +} + +SignatureStreamHelper DocumentSignatureHelper::OpenSignatureStream( + const Reference < css::embed::XStorage >& rxStore, sal_Int32 nOpenMode, DocumentSignatureMode eDocSigMode ) +{ + sal_Int32 nSubStorageOpenMode = css::embed::ElementModes::READ; + if ( nOpenMode & css::embed::ElementModes::WRITE ) + nSubStorageOpenMode = css::embed::ElementModes::WRITE; + + SignatureStreamHelper aHelper; + + if (!rxStore.is()) + return aHelper; + + if (rxStore->hasByName("META-INF")) + { + try + { + aHelper.xSignatureStorage = rxStore->openStorageElement( "META-INF", nSubStorageOpenMode ); + if ( aHelper.xSignatureStorage.is() ) + { + OUString aSIGStreamName; + if ( eDocSigMode == DocumentSignatureMode::Content ) + aSIGStreamName = DocumentSignatureHelper::GetDocumentContentSignatureDefaultStreamName(); + else if ( eDocSigMode == DocumentSignatureMode::Macros ) + aSIGStreamName = DocumentSignatureHelper::GetScriptingContentSignatureDefaultStreamName(); + else + aSIGStreamName = DocumentSignatureHelper::GetPackageSignatureDefaultStreamName(); + +#ifdef SAL_LOG_INFO + aHelper.xSignatureStream + = aHelper.xSignatureStorage->openStreamElement(aSIGStreamName, nOpenMode); + SAL_INFO("xmlsecurity.helper", + "DocumentSignatureHelper::OpenSignatureStream: stream name is '" + << aSIGStreamName << "'"); + if (aHelper.xSignatureStream.is()) + { + uno::Reference xInputStream(aHelper.xSignatureStream, + uno::UNO_QUERY); + sal_Int64 nSize = 0; + uno::Reference xPropertySet(xInputStream, uno::UNO_QUERY); + xPropertySet->getPropertyValue("Size") >>= nSize; + if (nSize >= 0 || nSize < SAL_MAX_INT32) + { + uno::Sequence aData; + xInputStream->readBytes(aData, nSize); + SAL_INFO("xmlsecurity.helper", + "DocumentSignatureHelper::OpenSignatureStream: stream content is '" + << OString(reinterpret_cast(aData.getArray()), + aData.getLength()) + << "'"); + } + } + aHelper.xSignatureStream.clear(); +#endif + + aHelper.xSignatureStream = aHelper.xSignatureStorage->openStreamElement( aSIGStreamName, nOpenMode ); + } + } + catch(css::io::IOException& ) + { + // Doesn't have to exist... + SAL_WARN_IF( nOpenMode != css::embed::ElementModes::READ, "xmlsecurity.helper", "Error creating signature stream..." ); + } + } + else if(rxStore->hasByName("[Content_Types].xml")) + { + try + { + if (rxStore->hasByName("_xmlsignatures") && (nOpenMode & embed::ElementModes::TRUNCATE)) + // Truncate, then all signatures will be written -> remove previous ones. + rxStore->removeElement("_xmlsignatures"); + + aHelper.xSignatureStorage = rxStore->openStorageElement("_xmlsignatures", nSubStorageOpenMode); + aHelper.nStorageFormat = embed::StorageFormats::OFOPXML; + } + catch (const io::IOException&) + { + TOOLS_WARN_EXCEPTION_IF(nOpenMode != css::embed::ElementModes::READ, "xmlsecurity.helper", "DocumentSignatureHelper::OpenSignatureStream:"); + } + } + + return aHelper; +} + +/** Check whether the current file can be signed with GPG (only ODF >= 1.2 can currently) */ +bool DocumentSignatureHelper::CanSignWithGPG( + const Reference < css::embed::XStorage >& rxStore, + std::u16string_view sOdfVersion) +{ + if (!rxStore.is()) + return false; + + if (rxStore->hasByName("META-INF")) // ODF + { + return !isODFPre_1_2(sOdfVersion); + } + + return false; +} + + + +//sElementList contains all files which are expected to be signed. Only those files must me signed, +//no more, no less. +//The DocumentSignatureAlgorithm indicates if the document was created with OOo 2.x. Then +//the uri s in the Reference elements in the signature, were not properly encoded. +// For example: +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 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 vUriSegments; + for (sal_Int32 nIndex = 0; nIndex >= 0; ) + vUriSegments.push_back(OUString(o3tl::getToken(rUri, 0, '/', nIndex ))); + + std::vector 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& xDocumentHandler) +{ + rtl::Reference pAttributeList(new comphelper::AttributeList()); + pAttributeList->AddAttribute("Algorithm", ALGO_XMLDSIGSHA256); + xDocumentHandler->startElement("DigestMethod", uno::Reference(pAttributeList)); + xDocumentHandler->endElement("DigestMethod"); +} + +static void WriteXadesCert( + uno::Reference const& xDocumentHandler, + SignatureInformation::X509CertInfo const& rCertInfo) +{ + xDocumentHandler->startElement("xd:Cert", uno::Reference(new comphelper::AttributeList())); + xDocumentHandler->startElement("xd:CertDigest", uno::Reference(new comphelper::AttributeList())); + DocumentSignatureHelper::writeDigestMethod(xDocumentHandler); + xDocumentHandler->startElement("DigestValue", uno::Reference(new comphelper::AttributeList())); + assert(!rCertInfo.CertDigest.isEmpty()); + xDocumentHandler->characters(rCertInfo.CertDigest); + xDocumentHandler->endElement("DigestValue"); + xDocumentHandler->endElement("xd:CertDigest"); + xDocumentHandler->startElement("xd:IssuerSerial", uno::Reference(new comphelper::AttributeList())); + xDocumentHandler->startElement("X509IssuerName", uno::Reference(new comphelper::AttributeList())); + xDocumentHandler->characters(rCertInfo.X509IssuerName); + xDocumentHandler->endElement("X509IssuerName"); + xDocumentHandler->startElement("X509SerialNumber", uno::Reference(new comphelper::AttributeList())); + xDocumentHandler->characters(rCertInfo.X509SerialNumber); + xDocumentHandler->endElement("X509SerialNumber"); + xDocumentHandler->endElement("xd:IssuerSerial"); + xDocumentHandler->endElement("xd:Cert"); +} + +void DocumentSignatureHelper::writeSignedProperties( + const uno::Reference& xDocumentHandler, + const SignatureInformation& signatureInfo, + const OUString& sDate, const bool bWriteSignatureLineData) +{ + { + rtl::Reference pAttributeList(new comphelper::AttributeList()); + pAttributeList->AddAttribute("Id", "idSignedProperties_" + signatureInfo.ouSignatureId); + xDocumentHandler->startElement("xd:SignedProperties", uno::Reference(pAttributeList)); + } + + xDocumentHandler->startElement("xd:SignedSignatureProperties", uno::Reference(new comphelper::AttributeList())); + xDocumentHandler->startElement("xd:SigningTime", uno::Reference(new comphelper::AttributeList())); + xDocumentHandler->characters(sDate); + xDocumentHandler->endElement("xd:SigningTime"); + xDocumentHandler->startElement("xd:SigningCertificate", uno::Reference(new comphelper::AttributeList())); + assert(signatureInfo.GetSigningCertificate() || !signatureInfo.ouGpgKeyID.isEmpty()); + if (signatureInfo.GetSigningCertificate()) + { + // how should this deal with multiple X509Data elements? + // for now, let's write all of the certificates ... + for (auto const& rData : signatureInfo.X509Datas) + { + for (auto const& it : rData) + { + WriteXadesCert(xDocumentHandler, it); + } + } + } + else + { + // for PGP, write empty mandatory X509IssuerName, X509SerialNumber + SignatureInformation::X509CertInfo temp; + temp.CertDigest = signatureInfo.ouGpgKeyID; + WriteXadesCert(xDocumentHandler, temp); + } + xDocumentHandler->endElement("xd:SigningCertificate"); + xDocumentHandler->startElement("xd:SignaturePolicyIdentifier", uno::Reference(new comphelper::AttributeList())); + xDocumentHandler->startElement("xd:SignaturePolicyImplied", uno::Reference(new comphelper::AttributeList())); + xDocumentHandler->endElement("xd:SignaturePolicyImplied"); + xDocumentHandler->endElement("xd:SignaturePolicyIdentifier"); + + if (bWriteSignatureLineData && !signatureInfo.ouSignatureLineId.isEmpty() + && signatureInfo.aValidSignatureImage.is() && signatureInfo.aInvalidSignatureImage.is()) + { + rtl::Reference pAttributeList(new comphelper::AttributeList()); + pAttributeList->AddAttribute( + "xmlns:loext", "urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0"); + xDocumentHandler->startElement( + "loext:SignatureLine", + Reference(pAttributeList)); + + { + // Write SignatureLineId element + xDocumentHandler->startElement( + "loext:SignatureLineId", + Reference(new comphelper::AttributeList())); + xDocumentHandler->characters(signatureInfo.ouSignatureLineId); + xDocumentHandler->endElement("loext:SignatureLineId"); + } + + { + // Write SignatureLineValidImage element + xDocumentHandler->startElement( + "loext:SignatureLineValidImage", + Reference(new comphelper::AttributeList())); + + OUString aGraphicInBase64; + Graphic aGraphic(signatureInfo.aValidSignatureImage); + if (!XOutBitmap::GraphicToBase64(aGraphic, aGraphicInBase64, false)) + SAL_WARN("xmlsecurity.helper", "could not convert graphic to base64"); + + xDocumentHandler->characters(aGraphicInBase64); + xDocumentHandler->endElement("loext:SignatureLineValidImage"); + } + + { + // Write SignatureLineInvalidImage element + xDocumentHandler->startElement( + "loext:SignatureLineInvalidImage", + Reference(new comphelper::AttributeList())); + OUString aGraphicInBase64; + Graphic aGraphic(signatureInfo.aInvalidSignatureImage); + if (!XOutBitmap::GraphicToBase64(aGraphic, aGraphicInBase64, false)) + SAL_WARN("xmlsecurity.helper", "could not convert graphic to base64"); + xDocumentHandler->characters(aGraphicInBase64); + xDocumentHandler->endElement("loext:SignatureLineInvalidImage"); + } + + xDocumentHandler->endElement("loext:SignatureLine"); + } + + xDocumentHandler->endElement("xd:SignedSignatureProperties"); + + xDocumentHandler->endElement("xd:SignedProperties"); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/helper/documentsignaturemanager.cxx b/xmlsecurity/source/helper/documentsignaturemanager.cxx new file mode 100644 index 0000000000..80d74c27ba --- /dev/null +++ b/xmlsecurity/source/helper/documentsignaturemanager.cxx @@ -0,0 +1,705 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include + +#include + +using namespace css; +using namespace css::graphic; +using namespace css::uno; + +DocumentSignatureManager::DocumentSignatureManager( + const uno::Reference& 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(); + + 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 xReader + = packages::manifest::ManifestReader::create(mxContext); + + if (mxStore->hasByName("META-INF")) + { + //Get the manifest.xml + uno::Reference xSubStore( + mxStore->openStorageElement("META-INF", embed::ElementModes::READ), UNO_SET_THROW); + + uno::Reference xStream( + xSubStore->openStreamElement("manifest.xml", css::embed::ElementModes::READ), + UNO_QUERY_THROW); + + m_manifest = xReader->readManifestSequence(xStream); + } + return true; +} + +/* Using the zip storage, we cannot get the properties "MediaType" and "IsEncrypted" + We use the manifest to find out if a file is xml and if it is encrypted. + The parameter is an encoded uri. However, the manifest contains paths. Therefore + the path is encoded as uri, so they can be compared. +*/ +bool DocumentSignatureManager::isXML(std::u16string_view rURI) +{ + SAL_WARN_IF(!mxStore.is(), "xmlsecurity.helper", "empty storage reference"); + + bool bIsXML = false; + bool bPropsAvailable = false; + static constexpr OUStringLiteral sPropFullPath(u"FullPath"); + static constexpr OUStringLiteral sPropMediaType(u"MediaType"); + static constexpr OUStringLiteral sPropDigest(u"Digest"); + + if (readManifest()) + { + for (const uno::Sequence& entry : std::as_const(m_manifest)) + { + OUString sPath; + OUString sMediaType; + bool bEncrypted = false; + for (const beans::PropertyValue& prop : entry) + { + if (prop.Name == sPropFullPath) + prop.Value >>= sPath; + else if (prop.Name == sPropMediaType) + prop.Value >>= sMediaType; + else if (prop.Name == sPropDigest) + bEncrypted = true; + } + if (DocumentSignatureHelper::equalsReferenceUriManifestPath(rURI, sPath)) + { + bIsXML = sMediaType == "text/xml" && !bEncrypted; + bPropsAvailable = true; + break; + } + } + } + if (!bPropsAvailable) + { + //This would be the case for at least mimetype, META-INF/manifest.xml + //META-INF/macrosignatures.xml. + //Files can only be encrypted if they are in the manifest.xml. + //That is, the current file cannot be encrypted, otherwise bPropsAvailable + //would be true. + size_t nSep = rURI.rfind('.'); + if (nSep != std::u16string_view::npos) + { + std::u16string_view aExt = rURI.substr(nSep + 1); + if (o3tl::equalsIgnoreAsciiCase(aExt, u"XML")) + bIsXML = true; + } + } + return bIsXML; +} + +//If bTempStream is true, then a temporary stream is return. If it is false then, the actual +//signature stream is used. +//Every time the user presses Add a new temporary stream is created. +//We keep the temporary stream as member because ImplGetSignatureInformations +//will later access the stream to create DocumentSignatureInformation objects +//which are stored in maCurrentSignatureInformations. +SignatureStreamHelper DocumentSignatureManager::ImplOpenSignatureStream(sal_Int32 nStreamOpenMode, + bool bTempStream) +{ + SignatureStreamHelper aHelper; + if (mxStore.is() && mxStore->hasByName("[Content_Types].xml")) + aHelper.nStorageFormat = embed::StorageFormats::OFOPXML; + + if (bTempStream) + { + if (nStreamOpenMode & embed::ElementModes::TRUNCATE) + { + //We write always into a new temporary stream. + mxTempSignatureStream = new utl::TempFileFastService; + if (aHelper.nStorageFormat != embed::StorageFormats::OFOPXML) + aHelper.xSignatureStream = mxTempSignatureStream; + else + { + mxTempSignatureStorage = comphelper::OStorageHelper::GetStorageOfFormatFromStream( + ZIP_STORAGE_FORMAT_STRING, mxTempSignatureStream); + aHelper.xSignatureStorage = mxTempSignatureStorage; + } + } + else + { + //When we read from the temp stream, then we must have previously + //created one. + SAL_WARN_IF(!mxTempSignatureStream.is(), "xmlsecurity.helper", + "empty temp. signature stream reference"); + } + aHelper.xSignatureStream = mxTempSignatureStream; + if (aHelper.nStorageFormat == embed::StorageFormats::OFOPXML) + aHelper.xSignatureStorage = mxTempSignatureStorage; + } + else + { + //No temporary stream + if (!mxSignatureStream.is()) + { + //We may not have a dedicated stream for writing the signature + //So we take one directly from the storage + //Or DocumentDigitalSignatures::showDocumentContentSignatures was called, + //in which case Add/Remove is not allowed. This is done, for example, if the + //document is readonly + aHelper = DocumentSignatureHelper::OpenSignatureStream(mxStore, nStreamOpenMode, + meSignatureMode); + } + else + { + aHelper.xSignatureStream = mxSignatureStream; + } + } + + if (nStreamOpenMode & embed::ElementModes::TRUNCATE) + { + if (aHelper.xSignatureStream.is() + && aHelper.nStorageFormat != embed::StorageFormats::OFOPXML) + { + uno::Reference 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 xSeek(aHelper.xSignatureStream, uno::UNO_QUERY_THROW); + xSeek->seek(0); + } + + return aHelper; +} + +bool DocumentSignatureManager::add( + const uno::Reference& xCert, + const uno::Reference& xSecurityContext, + const OUString& rDescription, sal_Int32& nSecurityId, bool bAdESCompliant, + const OUString& rSignatureLineId, const Reference& xValidGraphic, + const Reference& xInvalidGraphic) +{ + if (!xCert.is()) + { + SAL_WARN("xmlsecurity.helper", "no certificate selected"); + return false; + } + + // GPG or X509 key? + uno::Reference 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(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 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(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> aCertPath + = xSecurityContext->getSecurityEnvironment()->buildCertificatePath(xCert); + + OUStringBuffer aStrBuffer; + for (uno::Reference const& rxCertificate : aCertPath) + { + comphelper::Base64::encode(aStrBuffer, rxCertificate->getEncoded()); + OUString aString = aStrBuffer.makeStringAndClear(); + maSignatureHelper.AddEncapsulatedX509Certificate(aString); + } + + std::vector 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 xOutputStream(aStreamHelper.xSignatureStream, + uno::UNO_QUERY_THROW); + uno::Reference xSaxWriter + = maSignatureHelper.CreateDocumentHandlerWithHeader(xOutputStream); + + // Export old signatures... + uno::Reference 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 xTransact(aStreamHelper.xSignatureStorage, + uno::UNO_QUERY); + xTransact->commit(); + uno::Reference xOutputStream(aStreamHelper.xSignatureStream, + uno::UNO_QUERY); + xOutputStream->closeOutput(); + + uno::Reference 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 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 xOutputStream(aStreamHelper.xSignatureStream, + uno::UNO_QUERY_THROW); + uno::Reference xSaxWriter + = maSignatureHelper.CreateDocumentHandlerWithHeader(xOutputStream); + + uno::Reference 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 xTransact(aStreamHelper.xSignatureStorage, + uno::UNO_QUERY); + xTransact->commit(); + uno::Reference xOutputStream(aStreamHelper.xSignatureStream, + uno::UNO_QUERY); + xOutputStream->closeOutput(); + + uno::Reference 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 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 const xSecEnv( + getSecurityEnvironment()); + getSignatureHelper().CheckAndUpdateSignatureInformation(xSecEnv, it); + } + } + + maCurrentSignatureInformations = maSignatureHelper.GetSignatureInformations(); + } + else + { + // Something not ZIP based, try PDF. + uno::Reference 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 xOutputStream(aStreamHelper.xSignatureStream, + uno::UNO_QUERY); + uno::Reference xSaxWriter + = maSignatureHelper.CreateDocumentHandlerWithHeader(xOutputStream); + + uno::Reference 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 xTrans(aStreamHelper.xSignatureStorage, + uno::UNO_QUERY); + xTrans->commit(); + } +} + +uno::Reference DocumentSignatureManager::getSecurityEnvironment() +{ + return mxSecurityContext.is() ? mxSecurityContext->getSecurityEnvironment() + : uno::Reference(); +} + +uno::Reference +DocumentSignatureManager::getGpgSecurityEnvironment() +{ + return mxGpgSecurityContext.is() ? mxGpgSecurityContext->getSecurityEnvironment() + : uno::Reference(); +} + +uno::Reference const& +DocumentSignatureManager::getSecurityContext() const +{ + return mxSecurityContext; +} + +uno::Reference const& +DocumentSignatureManager::getGpgSecurityContext() const +{ + return mxGpgSecurityContext; +} + +void DocumentSignatureManager::setModel(const uno::Reference& xModel) +{ + mxModel = xModel; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/helper/ooxmlsecexporter.cxx b/xmlsecurity/source/helper/ooxmlsecexporter.cxx new file mode 100644 index 0000000000..804cfd2748 --- /dev/null +++ b/xmlsecurity/source/helper/ooxmlsecexporter.cxx @@ -0,0 +1,565 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "ooxmlsecexporter.hxx" + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +using namespace com::sun::star; +using namespace css::xml::sax; + +struct OOXMLSecExporter::Impl +{ +private: + const uno::Reference& m_xComponentContext; + const uno::Reference& m_xRootStorage; + const uno::Reference& m_xDocumentHandler; + const SignatureInformation& m_rInformation; + OUString m_aSignatureTimeValue; + +public: + Impl(const uno::Reference& xComponentContext, + const uno::Reference& xRootStorage, + const uno::Reference& 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& 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 inside idPackageObject. + void writePackageObjectSignatureProperties(); + /// Writes a single inside . + void writeManifestReference(const SignatureReferenceInformation& rReference); + void writeOfficeObject(); + /// Writes . + void writeSignatureInfo(); + void writePackageSignature(); + void writeSignatureLineImages(); +}; + +bool OOXMLSecExporter::Impl::isOOXMLDenylist(std::u16string_view rStreamName) +{ + static const std::initializer_list 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 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(new comphelper::AttributeList())); + + writeCanonicalizationMethod(); + writeSignatureMethod(); + writeSignedInfoReferences(); + + m_xDocumentHandler->endElement("SignedInfo"); +} + +void OOXMLSecExporter::Impl::writeCanonicalizationMethod() +{ + rtl::Reference pAttributeList(new comphelper::AttributeList()); + pAttributeList->AddAttribute("Algorithm", ALGO_C14N); + m_xDocumentHandler->startElement("CanonicalizationMethod", + uno::Reference(pAttributeList)); + m_xDocumentHandler->endElement("CanonicalizationMethod"); +} + +void OOXMLSecExporter::Impl::writeCanonicalizationTransform() +{ + rtl::Reference pAttributeList(new comphelper::AttributeList()); + pAttributeList->AddAttribute("Algorithm", ALGO_C14N); + m_xDocumentHandler->startElement("Transform", + uno::Reference(pAttributeList)); + m_xDocumentHandler->endElement("Transform"); +} + +void OOXMLSecExporter::Impl::writeSignatureMethod() +{ + rtl::Reference pAttributeList(new comphelper::AttributeList()); + + if (m_rInformation.eAlgorithmID == svl::crypto::SignatureMethodAlgorithm::ECDSA) + pAttributeList->AddAttribute("Algorithm", ALGO_ECDSASHA256); + else + pAttributeList->AddAttribute("Algorithm", ALGO_RSASHA256); + + m_xDocumentHandler->startElement("SignatureMethod", + uno::Reference(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 pAttributeList( + new comphelper::AttributeList()); + if (!rReference.ouURI.startsWith("idSignedProperties")) + pAttributeList->AddAttribute("Type", + "http://www.w3.org/2000/09/xmldsig#Object"); + else + pAttributeList->AddAttribute("Type", + "http://uri.etsi.org/01903#SignedProperties"); + pAttributeList->AddAttribute("URI", "#" + rReference.ouURI); + m_xDocumentHandler->startElement( + "Reference", uno::Reference(pAttributeList)); + } + if (rReference.ouURI.startsWith("idSignedProperties")) + { + m_xDocumentHandler->startElement( + "Transforms", + uno::Reference(new comphelper::AttributeList())); + writeCanonicalizationTransform(); + m_xDocumentHandler->endElement("Transforms"); + } + + DocumentSignatureHelper::writeDigestMethod(m_xDocumentHandler); + m_xDocumentHandler->startElement( + "DigestValue", + uno::Reference(new comphelper::AttributeList())); + m_xDocumentHandler->characters(rReference.ouDigestValue); + m_xDocumentHandler->endElement("DigestValue"); + m_xDocumentHandler->endElement("Reference"); + } + } +} + +void OOXMLSecExporter::Impl::writeSignatureValue() +{ + m_xDocumentHandler->startElement("SignatureValue", uno::Reference( + new comphelper::AttributeList())); + m_xDocumentHandler->characters(m_rInformation.ouSignatureValue); + m_xDocumentHandler->endElement("SignatureValue"); +} + +void OOXMLSecExporter::Impl::writeKeyInfo() +{ + m_xDocumentHandler->startElement( + "KeyInfo", uno::Reference(new comphelper::AttributeList())); + assert(m_rInformation.GetSigningCertificate()); + for (auto const& rData : m_rInformation.X509Datas) + { + m_xDocumentHandler->startElement( + "X509Data", uno::Reference(new comphelper::AttributeList())); + for (auto const& it : rData) + { + m_xDocumentHandler->startElement( + "X509Certificate", + uno::Reference(new comphelper::AttributeList())); + m_xDocumentHandler->characters(it.X509Certificate); + m_xDocumentHandler->endElement("X509Certificate"); + } + m_xDocumentHandler->endElement("X509Data"); + } + m_xDocumentHandler->endElement("KeyInfo"); +} + +void OOXMLSecExporter::Impl::writePackageObject() +{ + rtl::Reference pAttributeList(new comphelper::AttributeList()); + pAttributeList->AddAttribute("Id", "idPackageObject_" + m_rInformation.ouSignatureId); + m_xDocumentHandler->startElement("Object", + uno::Reference(pAttributeList)); + + writeManifest(); + writePackageObjectSignatureProperties(); + + m_xDocumentHandler->endElement("Object"); +} + +void OOXMLSecExporter::Impl::writeManifest() +{ + m_xDocumentHandler->startElement( + "Manifest", uno::Reference(new comphelper::AttributeList())); + const SignatureReferenceInformations& rReferences = m_rInformation.vSignatureReferenceInfors; + for (const SignatureReferenceInformation& rReference : rReferences) + { + if (rReference.nType != SignatureReferenceType::SAMEDOCUMENT) + { + if (OOXMLSecExporter::Impl::isOOXMLDenylist(rReference.ouURI)) + continue; + + writeManifestReference(rReference); + } + } + m_xDocumentHandler->endElement("Manifest"); +} + +void OOXMLSecExporter::Impl::writeRelationshipTransform(const OUString& rURI) +{ + uno::Reference xHierarchicalStorageAccess(m_xRootStorage, + uno::UNO_QUERY); + uno::Reference xRelStream( + xHierarchicalStorageAccess->openStreamElementByHierarchicalName(rURI, + embed::ElementModes::READ), + uno::UNO_QUERY); + { + rtl::Reference pAttributeList(new comphelper::AttributeList()); + pAttributeList->AddAttribute("Algorithm", ALGO_RELATIONSHIP); + m_xDocumentHandler->startElement("Transform", + uno::Reference(pAttributeList)); + } + + const uno::Sequence> aRelationsInfo + = comphelper::OFOPXMLHelper::ReadRelationsInfoSequence(xRelStream, rURI, + m_xComponentContext); + for (const uno::Sequence& 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 pAttributeList(new comphelper::AttributeList()); + pAttributeList->AddAttribute("xmlns:mdssi", NS_MDSSI); + pAttributeList->AddAttribute("SourceId", aId); + m_xDocumentHandler->startElement("mdssi:RelationshipReference", + uno::Reference(pAttributeList)); + m_xDocumentHandler->endElement("mdssi:RelationshipReference"); + } + + m_xDocumentHandler->endElement("Transform"); +} + +void OOXMLSecExporter::Impl::writePackageObjectSignatureProperties() +{ + m_xDocumentHandler->startElement( + "SignatureProperties", + uno::Reference(new comphelper::AttributeList())); + { + rtl::Reference pAttributeList(new comphelper::AttributeList()); + pAttributeList->AddAttribute("Id", "idSignatureTime_" + m_rInformation.ouSignatureId); + pAttributeList->AddAttribute("Target", "#" + m_rInformation.ouSignatureId); + m_xDocumentHandler->startElement("SignatureProperty", + uno::Reference(pAttributeList)); + } + { + rtl::Reference pAttributeList(new comphelper::AttributeList()); + pAttributeList->AddAttribute("xmlns:mdssi", NS_MDSSI); + m_xDocumentHandler->startElement("mdssi:SignatureTime", + uno::Reference(pAttributeList)); + } + m_xDocumentHandler->startElement( + "mdssi:Format", uno::Reference(new comphelper::AttributeList())); + m_xDocumentHandler->characters("YYYY-MM-DDThh:mm:ssTZD"); + m_xDocumentHandler->endElement("mdssi:Format"); + + m_xDocumentHandler->startElement( + "mdssi:Value", uno::Reference(new comphelper::AttributeList())); + if (!m_rInformation.ouDateTime.isEmpty()) + m_aSignatureTimeValue = m_rInformation.ouDateTime; + else + { + m_aSignatureTimeValue = utl::toISO8601(m_rInformation.stDateTime); + // Ignore sub-seconds. + sal_Int32 nCommaPos = m_aSignatureTimeValue.indexOf(','); + if (nCommaPos != -1) + { + m_aSignatureTimeValue + = OUString::Concat(m_aSignatureTimeValue.subView(0, nCommaPos)) + "Z"; + } + } + m_xDocumentHandler->characters(m_aSignatureTimeValue); + m_xDocumentHandler->endElement("mdssi:Value"); + + m_xDocumentHandler->endElement("mdssi:SignatureTime"); + m_xDocumentHandler->endElement("SignatureProperty"); + m_xDocumentHandler->endElement("SignatureProperties"); +} + +void OOXMLSecExporter::Impl::writeManifestReference(const SignatureReferenceInformation& rReference) +{ + rtl::Reference pAttributeList(new comphelper::AttributeList()); + pAttributeList->AddAttribute("URI", rReference.ouURI); + m_xDocumentHandler->startElement("Reference", + uno::Reference(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( + new comphelper::AttributeList())); + + writeRelationshipTransform(aURI); + writeCanonicalizationTransform(); + + m_xDocumentHandler->endElement("Transforms"); + } + + DocumentSignatureHelper::writeDigestMethod(m_xDocumentHandler); + m_xDocumentHandler->startElement( + "DigestValue", uno::Reference(new comphelper::AttributeList())); + m_xDocumentHandler->characters(rReference.ouDigestValue); + m_xDocumentHandler->endElement("DigestValue"); + m_xDocumentHandler->endElement("Reference"); +} + +void OOXMLSecExporter::Impl::writeOfficeObject() +{ + { + rtl::Reference pAttributeList(new comphelper::AttributeList()); + pAttributeList->AddAttribute("Id", "idOfficeObject_" + m_rInformation.ouSignatureId); + m_xDocumentHandler->startElement("Object", + uno::Reference(pAttributeList)); + } + m_xDocumentHandler->startElement( + "SignatureProperties", + uno::Reference(new comphelper::AttributeList())); + { + rtl::Reference pAttributeList(new comphelper::AttributeList()); + pAttributeList->AddAttribute("Id", "idOfficeV1Details_" + m_rInformation.ouSignatureId); + pAttributeList->AddAttribute("Target", "#" + m_rInformation.ouSignatureId); + m_xDocumentHandler->startElement("SignatureProperty", + uno::Reference(pAttributeList)); + } + writeSignatureInfo(); + m_xDocumentHandler->endElement("SignatureProperty"); + m_xDocumentHandler->endElement("SignatureProperties"); + m_xDocumentHandler->endElement("Object"); +} + +void OOXMLSecExporter::Impl::writeSignatureInfo() +{ + rtl::Reference pAttributeList(new comphelper::AttributeList()); + pAttributeList->AddAttribute("xmlns", "http://schemas.microsoft.com/office/2006/digsig"); + m_xDocumentHandler->startElement("SignatureInfoV1", + uno::Reference(pAttributeList)); + + m_xDocumentHandler->startElement( + "SetupID", uno::Reference(new comphelper::AttributeList())); + m_xDocumentHandler->characters(m_rInformation.ouSignatureLineId); + m_xDocumentHandler->endElement("SetupID"); + m_xDocumentHandler->startElement( + "SignatureText", uno::Reference(new comphelper::AttributeList())); + m_xDocumentHandler->endElement("SignatureText"); + m_xDocumentHandler->startElement("SignatureImage", uno::Reference( + new comphelper::AttributeList())); + m_xDocumentHandler->endElement("SignatureImage"); + m_xDocumentHandler->startElement("SignatureComments", uno::Reference( + new comphelper::AttributeList())); + m_xDocumentHandler->characters(m_rInformation.ouDescription); + m_xDocumentHandler->endElement("SignatureComments"); + // Just hardcode something valid according to [MS-OFFCRYPTO]. + m_xDocumentHandler->startElement("WindowsVersion", uno::Reference( + new comphelper::AttributeList())); + m_xDocumentHandler->characters("6.1"); + m_xDocumentHandler->endElement("WindowsVersion"); + m_xDocumentHandler->startElement( + "OfficeVersion", uno::Reference(new comphelper::AttributeList())); + m_xDocumentHandler->characters("16.0"); + m_xDocumentHandler->endElement("OfficeVersion"); + m_xDocumentHandler->startElement("ApplicationVersion", uno::Reference( + new comphelper::AttributeList())); + m_xDocumentHandler->characters("16.0"); + m_xDocumentHandler->endElement("ApplicationVersion"); + m_xDocumentHandler->startElement( + "Monitors", uno::Reference(new comphelper::AttributeList())); + m_xDocumentHandler->characters("1"); + m_xDocumentHandler->endElement("Monitors"); + m_xDocumentHandler->startElement( + "HorizontalResolution", + uno::Reference(new comphelper::AttributeList())); + m_xDocumentHandler->characters("1280"); + m_xDocumentHandler->endElement("HorizontalResolution"); + m_xDocumentHandler->startElement("VerticalResolution", uno::Reference( + new comphelper::AttributeList())); + m_xDocumentHandler->characters("800"); + m_xDocumentHandler->endElement("VerticalResolution"); + m_xDocumentHandler->startElement( + "ColorDepth", uno::Reference(new comphelper::AttributeList())); + m_xDocumentHandler->characters("32"); + m_xDocumentHandler->endElement("ColorDepth"); + m_xDocumentHandler->startElement( + "SignatureProviderId", + uno::Reference(new comphelper::AttributeList())); + m_xDocumentHandler->characters("{00000000-0000-0000-0000-000000000000}"); + m_xDocumentHandler->endElement("SignatureProviderId"); + m_xDocumentHandler->startElement( + "SignatureProviderUrl", + uno::Reference(new comphelper::AttributeList())); + m_xDocumentHandler->endElement("SignatureProviderUrl"); + m_xDocumentHandler->startElement( + "SignatureProviderDetails", + uno::Reference(new comphelper::AttributeList())); + m_xDocumentHandler->characters( + "9"); // This is what MSO 2016 writes, though [MS-OFFCRYPTO] doesn't document what the value means. + m_xDocumentHandler->endElement("SignatureProviderDetails"); + m_xDocumentHandler->startElement( + "SignatureType", uno::Reference(new comphelper::AttributeList())); + m_xDocumentHandler->characters("2"); + m_xDocumentHandler->endElement("SignatureType"); + + m_xDocumentHandler->endElement("SignatureInfoV1"); +} + +void OOXMLSecExporter::Impl::writePackageSignature() +{ + m_xDocumentHandler->startElement( + "Object", uno::Reference(new comphelper::AttributeList())); + { + rtl::Reference pAttributeList(new comphelper::AttributeList()); + pAttributeList->AddAttribute("xmlns:xd", NS_XD); + pAttributeList->AddAttribute("Target", "#" + m_rInformation.ouSignatureId); + m_xDocumentHandler->startElement("xd:QualifyingProperties", + uno::Reference(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 pAttributeList(new comphelper::AttributeList()); + pAttributeList->AddAttribute("Id", "idValidSigLnImg"); + m_xDocumentHandler->startElement("Object", + uno::Reference(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 pAttributeList(new comphelper::AttributeList()); + pAttributeList->AddAttribute("Id", "idInvalidSigLnImg"); + m_xDocumentHandler->startElement("Object", + uno::Reference(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 pAttributeList(new comphelper::AttributeList()); + pAttributeList->AddAttribute("xmlns", NS_XMLDSIG); + pAttributeList->AddAttribute("Id", m_rInformation.ouSignatureId); + getDocumentHandler()->startElement("Signature", + uno::Reference(pAttributeList)); + + writeSignedInfo(); + writeSignatureValue(); + writeKeyInfo(); + writePackageObject(); + writeOfficeObject(); + writePackageSignature(); + writeSignatureLineImages(); + + getDocumentHandler()->endElement("Signature"); +} + +OOXMLSecExporter::OOXMLSecExporter( + const uno::Reference& xComponentContext, + const uno::Reference& xRootStorage, + const uno::Reference& xDocumentHandler, + const SignatureInformation& rInformation) + : m_pImpl( + std::make_unique(xComponentContext, xRootStorage, xDocumentHandler, rInformation)) +{ +} + +OOXMLSecExporter::~OOXMLSecExporter() = default; + +void OOXMLSecExporter::writeSignature() { m_pImpl->writeSignature(); } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/helper/ooxmlsecexporter.hxx b/xmlsecurity/source/helper/ooxmlsecexporter.hxx new file mode 100644 index 0000000000..77ea7c4849 --- /dev/null +++ b/xmlsecurity/source/helper/ooxmlsecexporter.hxx @@ -0,0 +1,47 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include + +#include + +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 m_pImpl; + +public: + OOXMLSecExporter(const css::uno::Reference& xComponentContext, + const css::uno::Reference& xRootStorage, + const css::uno::Reference& xDocumentHandler, + const SignatureInformation& rInformation); + ~OOXMLSecExporter(); + void writeSignature(); +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/helper/ooxmlsecparser.cxx b/xmlsecurity/source/helper/ooxmlsecparser.cxx new file mode 100644 index 0000000000..2692190ccb --- /dev/null +++ b/xmlsecurity/source/helper/ooxmlsecparser.cxx @@ -0,0 +1,1352 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + + +#include "ooxmlsecparser.hxx" +#include +#include + +#include +#include +#include + +#include + +#include + +using namespace com::sun::star; + +class OOXMLSecParser::Context +{ + protected: + friend class OOXMLSecParser; + OOXMLSecParser & m_rParser; + private: + std::optional m_pOldNamespaceMap; + + public: + Context(OOXMLSecParser& rParser, + std::optional&& pOldNamespaceMap) + : m_rParser(rParser) + , m_pOldNamespaceMap(std::move(pOldNamespaceMap)) + { + } + + virtual ~Context() = default; + + virtual void StartElement( + css::uno::Reference const& /*xAttrs*/) + { + } + + virtual void EndElement() + { + } + + virtual std::unique_ptr CreateChildContext( + std::optional&& 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&& pOldNamespaceMap) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference const& xAttrs) override + { + m_rParser.HandleIdAttr(xAttrs); + } +}; + +auto OOXMLSecParser::Context::CreateChildContext( + std::optional&& pOldNamespaceMap, + sal_uInt16 const /*nNamespace*/, OUString const& /*rName*/) +-> std::unique_ptr +{ + // default: create new base context + return std::make_unique(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&& pOldNamespaceMap, + bool const isReferenced) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_isReferenced(isReferenced) + { + } + + OUString CheckIdAttrReferenced(css::uno::Reference 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&& 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&& 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&& 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&& pOldNamespaceMap, + OUString& rIssuerName, OUString& rSerialNumber) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rX509IssuerName(rIssuerName) + , m_rX509SerialNumber(rSerialNumber) + { + } + + virtual std::unique_ptr CreateChildContext( + std::optional&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "X509IssuerName") + { + return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_rX509IssuerName); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "X509SerialNumber") + { + return std::make_unique(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> m_X509IssuerSerials; + std::vector m_X509Certificates; + + public: + DsX509DataContext(OOXMLSecParser& rParser, + std::optional&& pOldNamespaceMap) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void EndElement() override + { + m_rParser.m_pXSecController->setX509Data(m_X509IssuerSerials, m_X509Certificates); + } + + virtual std::unique_ptr CreateChildContext( + std::optional&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "X509IssuerSerial") + { + m_X509IssuerSerials.emplace_back(); + return std::make_unique(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(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&& pOldNamespaceMap) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference const& xAttrs) override + { + m_rParser.HandleIdAttr(xAttrs); + } + + virtual std::unique_ptr CreateChildContext( + std::optional&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "X509Data") + { + return std::make_unique(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&& pOldNamespaceMap) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference 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&& pOldNamespaceMap, + OUString & rValue) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rValue(rValue) + { + } + + virtual void StartElement( + css::uno::Reference 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&& pOldNamespaceMap, + sal_Int32& rReferenceDigestID) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rReferenceDigestID(rReferenceDigestID) + { + } + + virtual void StartElement( + css::uno::Reference 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&& pOldNamespaceMap, + bool& rIsC14N) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rIsC14N(rIsC14N) + { + } + + virtual void StartElement( + css::uno::Reference 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&& pOldNamespaceMap, + bool& rIsC14N) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rIsC14N(rIsC14N) + { + } + + virtual std::unique_ptr CreateChildContext( + std::optional&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "Transform") + { + return std::make_unique(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&& pOldNamespaceMap) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference 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 CreateChildContext( + std::optional&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "Transforms") + { + return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_IsC14N); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "DigestMethod") + { + return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_nReferenceDigestID); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "DigestValue") + { + return std::make_unique(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&& pOldNamespaceMap) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference 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&& pOldNamespaceMap) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference const& xAttrs) override + { + m_rParser.HandleIdAttr(xAttrs); + } + + virtual void EndElement() override + { + m_rParser.m_pXSecController->setReferenceCount(); + } + + virtual std::unique_ptr CreateChildContext( + std::optional&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "SignatureMethod") + { + return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "Reference") + { + return std::make_unique(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&& pOldNamespaceMap, + OUString& rDigestValue, sal_Int32& rReferenceDigestID) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rDigestValue(rDigestValue) + , m_rReferenceDigestID(rReferenceDigestID) + { + } + + virtual std::unique_ptr CreateChildContext( + std::optional&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "DigestMethod") + { + return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_rReferenceDigestID); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "DigestValue") + { + return std::make_unique(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&& 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 CreateChildContext( + std::optional&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "CertDigest") + { + return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_CertDigest, m_nReferenceDigestID); + } + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "IssuerSerial") + { + return std::make_unique(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&& pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual std::unique_ptr CreateChildContext( + std::optional&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "Cert") + { + return std::make_unique(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&& 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&& pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void StartElement( + css::uno::Reference const& xAttrs) override + { + CheckIdAttrReferenced(xAttrs); + } + + virtual std::unique_ptr CreateChildContext( + std::optional&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SigningTime") + { + return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SigningCertificate") + { + return std::make_unique(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&& pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void StartElement( + css::uno::Reference const& xAttrs) override + { + CheckIdAttrReferenced(xAttrs); + } + + virtual std::unique_ptr CreateChildContext( + std::optional&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SignedSignatureProperties") + { + return std::make_unique(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&& pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void StartElement( + css::uno::Reference const& xAttrs) override + { + CheckIdAttrReferenced(xAttrs); + } + + virtual std::unique_ptr CreateChildContext( + std::optional&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SignedProperties") + { + return std::make_unique(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&& 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&& 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&& pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void StartElement( + css::uno::Reference const& xAttrs) override + { + CheckIdAttrReferenced(xAttrs); + } + + virtual std::unique_ptr CreateChildContext( + std::optional&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_MSODIGSIG && rName == "SetupID") + { + return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_SetupID); + } + if (nNamespace == XML_NAMESPACE_MSODIGSIG && rName == "SignatureComments") + { + return std::make_unique(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&& 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&& pOldNamespaceMap, + OUString& rValue) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rValue(rValue) + { + } + + virtual std::unique_ptr CreateChildContext( + std::optional&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_MDSSI && rName == "Value") + { + return std::make_unique(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&& pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void StartElement( + css::uno::Reference 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 CreateChildContext( + std::optional&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_MDSSI && rName == "SignatureTime") + { + m_Property = SignatureProperty::Date; + return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_Value); + } + if (nNamespace == XML_NAMESPACE_MSODIGSIG && rName == "SignatureInfoV1") + { + return std::make_unique(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&& pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void StartElement( + css::uno::Reference const& xAttrs) override + { + CheckIdAttrReferenced(xAttrs); + } + + virtual std::unique_ptr CreateChildContext( + std::optional&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "SignatureProperty") + { + return std::make_unique(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&& pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void StartElement( + css::uno::Reference const& xAttrs) override + { + CheckIdAttrReferenced(xAttrs); + } + +#if 0 + ??? + virtual void EndElement() override + { + m_rParser.m_pXSecController->setReferenceCount(); + } +#endif + + virtual std::unique_ptr CreateChildContext( + std::optional&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "Reference") + { + return std::make_unique(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&& 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 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 CreateChildContext( + std::optional&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "SignatureProperties") + { + return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "QualifyingProperties") + { + return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "Manifest") + { + return std::make_unique(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&& pOldNamespaceMap) + : OOXMLSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference 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 CreateChildContext( + std::optional&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "SignedInfo") + { + return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "SignatureValue") + { + return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "KeyInfo") + { + return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "Object") + { + return std::make_unique(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 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& xAttribs) +{ + assert(m_pNamespaceMap); + std::optional pRewindMap( + SvXMLImport::processNSAttributes(m_pNamespaceMap, nullptr, xAttribs)); + + OUString localName; + sal_uInt16 const nPrefix(m_pNamespaceMap->GetKeyByAttrName(rName, &localName)); + + std::unique_ptr 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& xLocator) +{ + if (m_xNextHandler.is()) + m_xNextHandler->setDocumentLocator(xLocator); +} + +void SAL_CALL OOXMLSecParser::initialize(const uno::Sequence& rArguments) +{ + rArguments[0] >>= m_xNextHandler; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/helper/ooxmlsecparser.hxx b/xmlsecurity/source/helper/ooxmlsecparser.hxx new file mode 100644 index 0000000000..1ac72a46f0 --- /dev/null +++ b/xmlsecurity/source/helper/ooxmlsecparser.hxx @@ -0,0 +1,110 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include +#include + +#include + +#include + +#include +#include +#include + +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> m_ContextStack; + std::optional m_pNamespaceMap; + + XSecController* m_pXSecController; + css::uno::Reference m_xNextHandler; + + XMLSignatureHelper& m_rXMLSignatureHelper; + + OUString HandleIdAttr(css::uno::Reference 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& 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& xLocator) override; + + // XInitialization + virtual void SAL_CALL initialize(const css::uno::Sequence& rArguments) override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/helper/pdfsignaturehelper.cxx b/xmlsecurity/source/helper/pdfsignaturehelper.cxx new file mode 100644 index 0000000000..3c0084c8b4 --- /dev/null +++ b/xmlsecurity/source/helper/pdfsignaturehelper.cxx @@ -0,0 +1,626 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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& xModel, sal_Int32& rPage) +{ + uno::Reference xController(xModel->getCurrentController(), uno::UNO_QUERY); + if (!xController.is()) + { + return false; + } + + uno::Reference 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& xModel, sal_Int32& rPage, + std::vector& rSignatureLineShape) +{ + if (!xModel.is()) + { + return; + } + + if (!GetSignatureLinePage(xModel, rPage)) + { + return; + } + + uno::Reference xShapes(xModel->getCurrentSelection(), uno::UNO_QUERY); + if (!xShapes.is() || xShapes->getCount() < 1) + { + return; + } + + uno::Reference 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 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 xStream(new utl::OStreamWrapper(aStream)); + aMediaDescriptor["OutputStream"] <<= xStream; + uno::Sequence aFilterData( + comphelper::InitPropertySequence({ { "Selection", uno::Any(xShapes) } })); + aMediaDescriptor["FilterData"] <<= aFilterData; + xStorable->storeToURL("private:stream", aMediaDescriptor.getAsConstPropertyValueList()); + xStream->flush(); + + aStream.Seek(0); + rSignatureLineShape = std::vector(aStream.GetSize()); + aStream.ReadBytes(rSignatureLineShape.data(), rSignatureLineShape.size()); +} + +/// Represents a parsed signature. +struct Signature +{ + std::unique_ptr m_pSignature; + /// Offset+length pairs. + std::vector> m_aByteRanges; +}; + +/// Turns an array of floats into offset + length pairs. +void GetByteRangesFromPDF(const std::unique_ptr& pSignature, + std::vector>& rByteRanges) +{ + std::vector 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& 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& rSignedEOFs, + const std::vector& 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 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& rPageChecksums, + int nMDPPerm) +{ + auto pPdfium = vcl::pdf::PDFiumLibrary::get(); + std::unique_ptr 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 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 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 aSignedPages; + AnalyizeSignatureStream(aSignatureStream, aSignedPages, nMDPPerm); + + SvMemoryStream aFullStream; + nPos = rStream.Tell(); + rStream.Seek(0); + aFullStream.WriteStream(rStream); + rStream.Seek(nPos); + aFullStream.Seek(0); + std::vector 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& rSignatureEOFs, + const std::vector& rTrailerEnds) +{ + std::vector 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& xInputStream) +{ + if (!xInputStream.is()) + { + SAL_WARN("xmlsecurity.helper", "input stream missing"); + return false; + } + + std::unique_ptr 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 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 aSignatures(nSignatureCount); + for (int i = 0; i < nSignatureCount; ++i) + { + std::unique_ptr pSignature = pPdfDocument->getSignature(i); + std::vector> aByteRanges; + GetByteRangesFromPDF(pSignature, aByteRanges); + aSignatures[i] = Signature{ std::move(pSignature), aByteRanges }; + } + + std::set aSignatureEOFs; + for (const auto& rSignature : aSignatures) + { + size_t nEOF = 0; + if (GetEOFOfSignature(rSignature, nEOF)) + { + aSignatureEOFs.insert(nEOF); + } + } + + std::vector 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 +PDFSignatureHelper::GetDocumentSignatureInformations( + const uno::Reference& xSecEnv) const +{ + uno::Sequence 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& xCertificate) +{ + m_xCertificate = xCertificate; +} + +void PDFSignatureHelper::SetDescription(const OUString& rDescription) +{ + m_aDescription = rDescription; +} + +bool PDFSignatureHelper::Sign(const uno::Reference& xModel, + const uno::Reference& xInputStream, bool bAdES) +{ + std::unique_ptr 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 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 xStream(xInputStream, uno::UNO_QUERY); + std::unique_ptr 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& xInputStream, + sal_uInt16 nPosition) +{ + std::unique_ptr 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 xStream(xInputStream, uno::UNO_QUERY); + uno::Reference xTruncate(xStream, uno::UNO_QUERY); + if (!xTruncate.is()) + { + SAL_WARN("xmlsecurity.helper", "failed to truncate"); + return false; + } + xTruncate->truncate(); + std::unique_ptr pOutStream(utl::UcbStreamHelper::CreateStream(xStream, true)); + if (!aDocument.Write(*pOutStream)) + { + SAL_WARN("xmlsecurity.helper", "failed to write without signature"); + return false; + } + + return true; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/helper/xmlsignaturehelper.cxx b/xmlsecurity/source/helper/xmlsignaturehelper.cxx new file mode 100644 index 0000000000..0b5825b125 --- /dev/null +++ b/xmlsecurity/source/helper/xmlsignaturehelper.cxx @@ -0,0 +1,713 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +constexpr OUStringLiteral NS_DOCUMENTSIGNATURES = u"http://openoffice.org/2004/documentsignatures"; +constexpr OUStringLiteral NS_DOCUMENTSIGNATURES_ODF_1_2 = u"urn:oasis:names:tc:opendocument:xmlns:digitalsignature:1.0"; +constexpr OUString OOXML_SIGNATURE_ORIGIN = u"http://schemas.openxmlformats.org/package/2006/relationships/digital-signature/origin"_ustr; +constexpr OUString OOXML_SIGNATURE_SIGNATURE = u"http://schemas.openxmlformats.org/package/2006/relationships/digital-signature/signature"_ustr; + +using namespace ::com::sun::star; +using namespace ::com::sun::star::graphic; +using namespace ::com::sun::star::uno; + +XMLSignatureHelper::XMLSignatureHelper( const uno::Reference< uno::XComponentContext >& rxCtx) + : mxCtx(rxCtx), mbODFPre1_2(false) +{ + mpXSecController = new XSecController(rxCtx); + mbError = false; +} + +XMLSignatureHelper::~XMLSignatureHelper() +{ +} + +void XMLSignatureHelper::SetStorage( + const Reference < css::embed::XStorage >& rxStorage, + std::u16string_view sODFVersion) +{ + SAL_WARN_IF( mxUriBinding.is(), "xmlsecurity.helper", "SetStorage - UriBinding already set!" ); + mxUriBinding = new UriBindingHelper( rxStorage ); + SAL_WARN_IF(!rxStorage.is(), "xmlsecurity.helper", "SetStorage - empty storage!"); + mbODFPre1_2 = DocumentSignatureHelper::isODFPre_1_2(sODFVersion); +} + + +void XMLSignatureHelper::SetStartVerifySignatureHdl( const Link& rLink ) +{ + maStartVerifySignatureHdl = rLink; +} + + +void XMLSignatureHelper::StartMission(const uno::Reference& 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& xValidGraphic) +{ + mpXSecController->setSignatureLineValidGraphic(nSecurityId, xValidGraphic); +} + +void XMLSignatureHelper::SetSignatureLineInvalidGraphic( + sal_Int32 nSecurityId, const css::uno::Reference& 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 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 pAttributeList = new comphelper::AttributeList(); + OUString sNamespace; + if (mbODFPre1_2) + sNamespace = NS_DOCUMENTSIGNATURES; + else + sNamespace = NS_DOCUMENTSIGNATURES_ODF_1_2; + + pAttributeList->AddAttribute( + "xmlns", + sNamespace); + + xSaxWriter->startDocument(); + xSaxWriter->startElement( + "document-signatures", + pAttributeList); + + return xSaxWriter; +} + +void XMLSignatureHelper::CloseDocumentHandler( const uno::Reference& 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& xRootStorage, const uno::Reference& xSignatureStorage, const SignatureInformation& rInformation, int nSignatureIndex) +{ + uno::Reference 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 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& 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 xSubStorage = xStorage->openStorageElement("_rels", nOpenMode); + uno::Reference xRelStream(xSubStorage->openStreamElement("origin.sigs.rels", nOpenMode), uno::UNO_QUERY); + uno::Sequence< uno::Sequence > aRelationsInfo = comphelper::OFOPXMLHelper::ReadRelationsInfoSequence(xRelStream, u"origin.sigs.rels", mxCtx); + + for (sal_Int32 i = 0; i < aRelationsInfo.getLength(); ++i) + { + const uno::Sequence& 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 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 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 aData; + xInputStream->readBytes(aData, nSize); + mpXSecController->setSignatureBytes(aData); + } + } + } + + return true; +} + +bool XMLSignatureHelper::ReadAndVerifySignatureStorageStream(const css::uno::Reference& xInputStream) +{ + mbError = false; + + // Create the input source. + xml::sax::InputSource aParserInput; + aParserInput.aInputStream = xInputStream; + + // Create the sax parser. + uno::Reference xParser = xml::sax::Parser::create(mxCtx); + + // Create the signature reader. + uno::Reference 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& xStorage, bool bAdd) +{ + sal_Int32 nOpenMode = embed::ElementModes::READWRITE; + uno::Reference xSubStorage = xStorage->openStorageElement("_rels", nOpenMode); + uno::Reference xRelStream(xSubStorage->openStreamElement(".rels", nOpenMode), uno::UNO_QUERY); + std::vector< uno::Sequence > aRelationsInfo = comphelper::sequenceToContainer< std::vector< uno::Sequence > >(comphelper::OFOPXMLHelper::ReadRelationsInfoSequence(xRelStream, u".rels", mxCtx)); + + // Do we have a relation already? + bool bHaveRelation = false; + int nCount = 0; + for (const uno::Sequence& rRelation : aRelationsInfo) + { + auto aRelation = comphelper::sequenceToContainer< std::vector >(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 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 >::iterator it = aRelationsInfo.begin(); it != aRelationsInfo.end();) + { + auto aRelation = comphelper::sequenceToContainer< std::vector >(*it); + if (std::any_of(aRelation.begin(), aRelation.end(), lcl_isSignatureOriginType)) + it = aRelationsInfo.erase(it); + else + ++it; + } + } + + // Write it back. + uno::Reference xTruncate(xRelStream, uno::UNO_QUERY); + xTruncate->truncate(); + uno::Reference xOutputStream(xRelStream, uno::UNO_QUERY); + comphelper::OFOPXMLHelper::WriteRelationsInfoSequence(xOutputStream, comphelper::containerToSequence(aRelationsInfo), mxCtx); + + // Commit it. + uno::Reference xTransact(xSubStorage, uno::UNO_QUERY); + xTransact->commit(); + xTransact.set(xStorage, uno::UNO_QUERY); + xTransact->commit(); +} + +void XMLSignatureHelper::ExportSignatureRelations(const css::uno::Reference& xStorage, int nSignatureCount) +{ + // Write the empty file, its relations will be the signatures. + sal_Int32 nOpenMode = embed::ElementModes::READWRITE; + uno::Reference xOriginStream(xStorage->openStreamElement("origin.sigs", nOpenMode), uno::UNO_QUERY); + uno::Reference xTruncate(xOriginStream, uno::UNO_QUERY); + xTruncate->truncate(); + xOriginStream->closeOutput(); + + // Write the relations. + uno::Reference xSubStorage = xStorage->openStorageElement("_rels", nOpenMode); + uno::Reference xRelStream(xSubStorage->openStreamElement("origin.sigs.rels", nOpenMode), uno::UNO_QUERY); + std::vector< uno::Sequence > aRelations; + for (int i = 0; i < nSignatureCount; ++i) + { + std::vector 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 xTransact(xSubStorage, uno::UNO_QUERY); + xTransact->commit(); +} + +void XMLSignatureHelper::ExportSignatureContentTypes(const css::uno::Reference& xStorage, int nSignatureCount) +{ + uno::Reference xStream = xStorage->openStreamElement("[Content_Types].xml", embed::ElementModes::READWRITE); + uno::Reference xInputStream = xStream->getInputStream(); + uno::Sequence< uno::Sequence > 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& rDefaults = pContentTypeInfo[0]; + auto aDefaults = comphelper::sequenceToContainer< std::vector >(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& rOverrides = pContentTypeInfo[1]; + auto aOverrides = comphelper::sequenceToContainer< std::vector >(rOverrides); + std::erase_if(aOverrides, [](const beans::StringPair& rPair) + { + return rPair.First.startsWith("/_xmlsignatures/sig"); + }); + + // Add our signature overrides. + for (int i = 1; i <= nSignatureCount; ++i) + aOverrides.emplace_back("/_xmlsignatures/sig" + OUString::number(i) + ".xml", "application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml"); + + rOverrides = comphelper::containerToSequence(aOverrides); + uno::Reference xOutputStream = xStream->getOutputStream(); + uno::Reference xTruncate(xOutputStream, uno::UNO_QUERY); + xTruncate->truncate(); + comphelper::OFOPXMLHelper::WriteContentSequence(xOutputStream, rDefaults, rOverrides, mxCtx); + uno::Reference xTransact(xStorage, uno::UNO_QUERY); + xTransact->commit(); +} +void XMLSignatureHelper::CreateAndWriteOOXMLSignature(const uno::Reference& xRootStorage, const uno::Reference& xSignatureStorage, int nSignatureIndex) +{ + uno::Reference xOutputStream(xSignatureStorage->openStreamElement("sig" + OUString::number(nSignatureIndex) + ".xml", embed::ElementModes::READWRITE), uno::UNO_QUERY); + uno::Reference 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 const& xSecEnv, + std::vector const& rX509CertInfos, + std::vector> & rCerts, + std::vector & rSorted) -> bool +{ + assert(rCerts.empty()); + assert(rSorted.empty()); + if (rX509CertInfos.empty()) + { + SAL_WARN("xmlsecurity.comp", "no X509Data"); + return false; + } + std::vector> 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 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 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> +XMLSignatureHelper::CheckAndUpdateSignatureInformation( + uno::Reference 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> certs; + std::vector datas; + // TODO: for now, just merge all X509Datas together for checking... + // (this will probably break round-trip of signature with multiple X509Data, + // no idea if that is a problem) + SignatureInformation::X509Data temp; + SignatureInformation::X509Data tempResult; + for (auto const& rData : rInfo.X509Datas) + { + for (auto const& it : rData) + { + temp.emplace_back(it); + } + } + if (CheckX509Data(xSecEnv, temp, certs, tempResult)) + { + datas.emplace_back(tempResult); + } + + // rInfo is a copy, update the original + mpXSecController->UpdateSignatureInformation(rInfo.nSecurityId, std::move(datas)); + return certs; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/helper/xsecctl.cxx b/xmlsecurity/source/helper/xsecctl.cxx new file mode 100644 index 0000000000..08b822f157 --- /dev/null +++ b/xmlsecurity/source/helper/xsecctl.cxx @@ -0,0 +1,1005 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include +#include +#include +#include +#include +#if HAVE_FEATURE_GPGME +# include +#endif + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include "ooxmlsecexporter.hxx" +#include + +using namespace com::sun::star; + +namespace +{ +OUString getDigestURI(sal_Int32 nID) +{ + switch( nID ) + { + case css::xml::crypto::DigestID::SHA1: + return ALGO_XMLDSIGSHA1; + case css::xml::crypto::DigestID::SHA256: + return ALGO_XMLDSIGSHA256; + case css::xml::crypto::DigestID::SHA512: + return ALGO_XMLDSIGSHA512; + default: + return ALGO_XMLDSIGSHA1; + } +} +OUString getSignatureURI(svl::crypto::SignatureMethodAlgorithm eAlgorithm, sal_Int32 nDigestID) +{ + OUString aRet; + + if (eAlgorithm == svl::crypto::SignatureMethodAlgorithm::ECDSA) + { + switch (nDigestID) + { + case css::xml::crypto::DigestID::SHA1: + aRet = ALGO_ECDSASHA1; + break; + case css::xml::crypto::DigestID::SHA256: + aRet = ALGO_ECDSASHA256; + break; + case css::xml::crypto::DigestID::SHA512: + aRet = ALGO_ECDSASHA512; + break; + default: + aRet = ALGO_ECDSASHA1; + break; + } + } + if (!aRet.isEmpty()) + return aRet; + + switch (nDigestID) + { + case css::xml::crypto::DigestID::SHA1: + return ALGO_RSASHA1; + case css::xml::crypto::DigestID::SHA256: + return ALGO_RSASHA256; + case css::xml::crypto::DigestID::SHA512: + return ALGO_RSASHA512; + default: + return ALGO_RSASHA1; + } +} +} + +XSecController::XSecController( css::uno::Reference xCtx ) + : mxCtx(std::move(xCtx)) + , m_nNextSecurityId(1) + , m_bIsPreviousNodeInitializable(false) + , m_bIsSAXEventKeeperConnected(false) + , m_bIsCollectingElement(false) + , m_bIsBlocking(false) + , m_eStatusOfSecurityComponents(InitializationState::UNINITIALIZED) + , m_bIsSAXEventKeeperSticky(false) + , m_nReservedSignatureId(0) + , m_bVerifyCurrentSignature(false) +{ +} + +XSecController::~XSecController() +{ +} + + +/* + * private methods + */ +int XSecController::findSignatureInfor( sal_Int32 nSecurityId) const +/****** XSecController/findSignatureInfor ************************************* + * + * NAME + * findSignatureInfor -- find SignatureInformation struct for a particular + * signature + * + * SYNOPSIS + * index = findSignatureInfor( nSecurityId ); + * + * INPUTS + * nSecurityId - the signature's id + * + * RESULT + * index - the index of the signature, or -1 when no such signature + * existing + ******************************************************************************/ +{ + int i; + int size = m_vInternalSignatureInformations.size(); + + for (i=0; i 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 arg{ css::uno::Any( + uno::Reference(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()); + + 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 aArgs{ css::uno::Any( + uno::Reference()) }; + xInitialization->initialize(aArgs); + } + else + { + css::uno::Reference< css::xml::sax::XParser > xParser(m_xPreviousNodeOnSAXChain, css::uno::UNO_QUERY); + xParser->setDocumentHandler(uno::Reference()); + } + } + + 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& 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 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& xDocumentHandler, + const SignatureInformation& signatureInfo) +{ + { + rtl::Reference pAttributeList(new comphelper::AttributeList()); + pAttributeList->AddAttribute("Id", "idUnsignedProperties_" + signatureInfo.ouSignatureId); + xDocumentHandler->startElement("xd:UnsignedProperties", uno::Reference(pAttributeList)); + } + + { + xDocumentHandler->startElement("xd:UnsignedSignatureProperties", uno::Reference(new comphelper::AttributeList())); + + { + xDocumentHandler->startElement("xd:CertificateValues", uno::Reference(new comphelper::AttributeList())); + + { + for (const auto& i: signatureInfo.maEncapsulatedX509Certificates) + { + xDocumentHandler->startElement("xd:EncapsulatedX509Certificate", uno::Reference(new comphelper::AttributeList())); + xDocumentHandler->characters(i); + xDocumentHandler->endElement("xd:EncapsulatedX509Certificate"); + } + } + + xDocumentHandler->endElement("xd:CertificateValues"); + } + + xDocumentHandler->endElement("xd:UnsignedSignatureProperties"); + } + + xDocumentHandler->endElement("xd:UnsignedProperties"); +} + +} + +void XSecController::exportSignature( + const css::uno::Reference& 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 pAttributeList; + + /* + * Write Signature element + */ + pAttributeList = new comphelper::AttributeList(); + pAttributeList->AddAttribute( + "xmlns", + NS_XMLDSIG); + + if (!signatureInfo.ouSignatureId.isEmpty()) + { + pAttributeList->AddAttribute( + "Id", + signatureInfo.ouSignatureId); + } + + xDocumentHandler->startElement( "Signature", pAttributeList); + { + /* Write SignedInfo element */ + xDocumentHandler->startElement( + "SignedInfo", + css::uno::Reference< css::xml::sax::XAttributeList > (new comphelper::AttributeList())); + { + /* Write CanonicalizationMethod element */ + pAttributeList = new comphelper::AttributeList(); + pAttributeList->AddAttribute( + "Algorithm", + ALGO_C14N); + xDocumentHandler->startElement( "CanonicalizationMethod", pAttributeList ); + xDocumentHandler->endElement( "CanonicalizationMethod" ); + + /* Write SignatureMethod element */ + pAttributeList = new comphelper::AttributeList(); + + // TODO: actually roundtrip this value from parsing documentsignatures.xml - entirely + // broken to assume this would in any way relate to the 1st reference's digest algo + + // Assume that all Reference elements use the same DigestMethod:Algorithm, and that the + // SignatureMethod:Algorithm should be the corresponding one. + pAttributeList->AddAttribute( + "Algorithm", + getSignatureURI(signatureInfo.eAlgorithmID, vReferenceInfors[0].nDigestID)); + xDocumentHandler->startElement( "SignatureMethod", pAttributeList ); + xDocumentHandler->endElement( "SignatureMethod" ); + + /* Write Reference element */ + int j; + int refNum = vReferenceInfors.size(); + + for(j=0; jAddAttribute( + "URI", + refInfor.ouURI); + } + else + /* + * same-document reference + */ + { + if (refInfor.ouURI.startsWith("idSignedProperties")) + { + pAttributeList->AddAttribute("URI", "#idSignedProperties_" + signatureInfo.ouSignatureId); + if (bXAdESCompliantIfODF && !refInfor.ouType.isEmpty()) + { + // The reference which points to the SignedProperties + // shall have this specific type. + pAttributeList->AddAttribute("Type", refInfor.ouType); + } + } + else + { + pAttributeList->AddAttribute( + "URI", + "#" + refInfor.ouURI); + } + } + + xDocumentHandler->startElement( "Reference", pAttributeList ); + { + /* Write Transforms element */ + if (refInfor.nType == SignatureReferenceType::XMLSTREAM) + /* + * xml stream, so c14n transform is needed + */ + { + xDocumentHandler->startElement( + "Transforms", + css::uno::Reference< css::xml::sax::XAttributeList > (new comphelper::AttributeList())); + { + pAttributeList = new comphelper::AttributeList(); + pAttributeList->AddAttribute( + "Algorithm", + ALGO_C14N); + xDocumentHandler->startElement( + "Transform", + pAttributeList ); + xDocumentHandler->endElement( "Transform" ); + } + xDocumentHandler->endElement( "Transforms" ); + } + + /* Write DigestMethod element */ + pAttributeList = new comphelper::AttributeList(); + pAttributeList->AddAttribute( + "Algorithm", + getDigestURI(refInfor.nDigestID)); + xDocumentHandler->startElement( + "DigestMethod", + pAttributeList ); + xDocumentHandler->endElement( "DigestMethod" ); + + /* Write DigestValue element */ + xDocumentHandler->startElement( + "DigestValue", + css::uno::Reference< css::xml::sax::XAttributeList > (new comphelper::AttributeList())); + xDocumentHandler->characters( refInfor.ouDigestValue ); + xDocumentHandler->endElement( "DigestValue" ); + } + xDocumentHandler->endElement( "Reference" ); + } + } + xDocumentHandler->endElement( "SignedInfo" ); + + /* Write SignatureValue element */ + xDocumentHandler->startElement( + "SignatureValue", + css::uno::Reference< css::xml::sax::XAttributeList > (new comphelper::AttributeList())); + xDocumentHandler->characters( signatureInfo.ouSignatureValue ); + xDocumentHandler->endElement( "SignatureValue" ); + + /* Write KeyInfo element */ + xDocumentHandler->startElement( + "KeyInfo", + css::uno::Reference< css::xml::sax::XAttributeList > (new comphelper::AttributeList())); + { + // GPG or X509 key? + if (!signatureInfo.ouGpgCertificate.isEmpty()) + { + pAttributeList = new comphelper::AttributeList(); + pAttributeList->AddAttribute("xmlns:loext", NS_LOEXT); + /* Write PGPData element */ + xDocumentHandler->startElement( + "PGPData", + pAttributeList); + { + /* Write keyid element */ + xDocumentHandler->startElement( + "PGPKeyID", + css::uno::Reference< css::xml::sax::XAttributeList > (new comphelper::AttributeList())); + xDocumentHandler->characters(signatureInfo.ouGpgKeyID); + xDocumentHandler->endElement( "PGPKeyID" ); + + /* Write PGPKeyPacket element */ + if (!signatureInfo.ouGpgCertificate.isEmpty()) + { + xDocumentHandler->startElement( + "PGPKeyPacket", + css::uno::Reference< css::xml::sax::XAttributeList > (new comphelper::AttributeList())); + xDocumentHandler->characters( signatureInfo.ouGpgCertificate ); + xDocumentHandler->endElement( "PGPKeyPacket" ); + } + + /* Write PGPOwner element */ + xDocumentHandler->startElement( + "loext:PGPOwner", + css::uno::Reference< css::xml::sax::XAttributeList >(new comphelper::AttributeList())); + xDocumentHandler->characters( signatureInfo.ouGpgOwner ); + xDocumentHandler->endElement( "loext:PGPOwner" ); + } + xDocumentHandler->endElement( "PGPData" ); + } + else + { + assert(signatureInfo.GetSigningCertificate()); + for (auto const& rData : signatureInfo.X509Datas) + { + /* Write X509Data element */ + xDocumentHandler->startElement( + "X509Data", + css::uno::Reference< css::xml::sax::XAttributeList > (new comphelper::AttributeList())); + { + for (auto const& it : rData) + { + /* Write X509IssuerSerial element */ + xDocumentHandler->startElement( + "X509IssuerSerial", + css::uno::Reference< css::xml::sax::XAttributeList > (new comphelper::AttributeList())); + { + /* Write X509IssuerName element */ + xDocumentHandler->startElement( + "X509IssuerName", + css::uno::Reference< css::xml::sax::XAttributeList > (new comphelper::AttributeList())); + xDocumentHandler->characters(it.X509IssuerName); + xDocumentHandler->endElement( "X509IssuerName" ); + + /* Write X509SerialNumber element */ + xDocumentHandler->startElement( + "X509SerialNumber", + css::uno::Reference< css::xml::sax::XAttributeList > (new comphelper::AttributeList())); + xDocumentHandler->characters(it.X509SerialNumber); + xDocumentHandler->endElement( "X509SerialNumber" ); + } + xDocumentHandler->endElement( "X509IssuerSerial" ); + + /* Write X509Certificate element */ + if (!it.X509Certificate.isEmpty()) + { + xDocumentHandler->startElement( + "X509Certificate", + css::uno::Reference< css::xml::sax::XAttributeList > (new comphelper::AttributeList())); + xDocumentHandler->characters(it.X509Certificate); + xDocumentHandler->endElement( "X509Certificate" ); + } + } + } + xDocumentHandler->endElement( "X509Data" ); + } + } + } + xDocumentHandler->endElement( "KeyInfo" ); + + OUString sDate; + + /* Write Object element */ + xDocumentHandler->startElement( + "Object", + css::uno::Reference< css::xml::sax::XAttributeList > (new comphelper::AttributeList())); + { + /* Write SignatureProperties element */ + xDocumentHandler->startElement( + "SignatureProperties", + css::uno::Reference< css::xml::sax::XAttributeList > (new comphelper::AttributeList())); + { + /* Write SignatureProperty element */ + pAttributeList = new comphelper::AttributeList(); + pAttributeList->AddAttribute( + "Id", + signatureInfo.ouDateTimePropertyId); + pAttributeList->AddAttribute( + "Target", + "#" + signatureInfo.ouSignatureId); + xDocumentHandler->startElement( + "SignatureProperty", + pAttributeList); + { + /* Write timestamp element */ + + pAttributeList = new comphelper::AttributeList(); + pAttributeList->AddAttribute( + "xmlns:dc", + NS_DC); + + xDocumentHandler->startElement( + "dc:date", + pAttributeList); + + OUStringBuffer buffer; + //If the xml signature was already contained in the document, + //then we use the original date and time string, rather than the + //converted one. This avoids writing a different string due to + //e.g. rounding issues and thus breaking the signature. + if (!signatureInfo.ouDateTime.isEmpty()) + buffer = signatureInfo.ouDateTime; + else + { + buffer = utl::toISO8601(signatureInfo.stDateTime); + // xsd:dateTime must use period as separator for fractional seconds, while + // utl::toISO8601 uses comma (as allowed, and even recommended, by ISO8601). + buffer.replace(',', '.'); + } + sDate = buffer.makeStringAndClear(); + xDocumentHandler->characters( sDate ); + + xDocumentHandler->endElement( + "dc:date"); + } + xDocumentHandler->endElement( "SignatureProperty" ); + } + + // Write signature description. + if (!signatureInfo.ouDescription.isEmpty()) + { + // SignatureProperty element. + pAttributeList = new comphelper::AttributeList(); + pAttributeList->AddAttribute("Id", signatureInfo.ouDescriptionPropertyId); + pAttributeList->AddAttribute("Target", "#" + signatureInfo.ouSignatureId); + xDocumentHandler->startElement("SignatureProperty", pAttributeList); + + { + // Description element. + pAttributeList = new comphelper::AttributeList(); + pAttributeList->AddAttribute("xmlns:dc", NS_DC); + + xDocumentHandler->startElement("dc:description", pAttributeList); + xDocumentHandler->characters(signatureInfo.ouDescription); + xDocumentHandler->endElement("dc:description"); + } + + xDocumentHandler->endElement("SignatureProperty"); + } + + xDocumentHandler->endElement( "SignatureProperties" ); + } + xDocumentHandler->endElement( "Object" ); + + // In XAdES, write another Object element for the QualifyingProperties + if (bXAdESCompliantIfODF) + { + pAttributeList = new comphelper::AttributeList(); + pAttributeList->AddAttribute("xmlns:xd", NS_XD); + xDocumentHandler->startElement( + "Object", + pAttributeList); + { + pAttributeList = new comphelper::AttributeList(); + pAttributeList->AddAttribute("Target", "#" + signatureInfo.ouSignatureId); + xDocumentHandler->startElement( + "xd:QualifyingProperties", + pAttributeList); + DocumentSignatureHelper::writeSignedProperties(xDocumentHandler, signatureInfo, sDate, true); + writeUnsignedProperties(xDocumentHandler, signatureInfo); + xDocumentHandler->endElement( "xd:QualifyingProperties" ); + } + xDocumentHandler->endElement( "Object" ); + } + } + xDocumentHandler->endElement( "Signature" ); +} + +void XSecController::exportOOXMLSignature(const uno::Reference& xRootStorage, const uno::Reference& xDocumentHandler, const SignatureInformation& rInformation) +{ + OOXMLSecExporter aExporter(mxCtx, xRootStorage, xDocumentHandler, rInformation); + aExporter.writeSignature(); +} + +void XSecController::UpdateSignatureInformation(sal_Int32 const nSecurityId, + std::vector && 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 +#include + +#include +#include +#include + +#include +#include +#include + +class XSecParser::Context +{ + protected: + friend class XSecParser; + XSecParser & m_rParser; + private: + std::optional m_pOldNamespaceMap; + + public: + Context(XSecParser& rParser, + std::optional&& pOldNamespaceMap) + : m_rParser(rParser) + , m_pOldNamespaceMap(std::move(pOldNamespaceMap)) + { + } + + virtual ~Context() = default; + + virtual void StartElement( + css::uno::Reference const& /*xAttrs*/) + { + } + + virtual void EndElement() + { + } + + virtual std::unique_ptr CreateChildContext( + std::optional&& 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&& pOldNamespaceMap) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference const& xAttrs) override + { + m_rParser.HandleIdAttr(xAttrs); + } +}; + +auto XSecParser::Context::CreateChildContext( + std::optional&& pOldNamespaceMap, + sal_uInt16 const /*nNamespace*/, OUString const& /*rName*/) +-> std::unique_ptr +{ + // default: create new base context + return std::make_unique(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&& pOldNamespaceMap, + bool const isReferenced) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_isReferenced(isReferenced) + { + } + + OUString CheckIdAttrReferenced(css::uno::Reference 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&& 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&& 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&& 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&& pOldNamespaceMap) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference const& /*xAttrs*/) override + { + m_rParser.m_pXSecController->switchGpgSignature(); + } + + virtual std::unique_ptr CreateChildContext( + std::optional&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "PGPKeyID") + { + return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "PGPKeyPacket") + { + return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); + } + if (nNamespace == XML_NAMESPACE_LO_EXT && rName == "PGPOwner") + { + return std::make_unique(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&& 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&& 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&& 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&& pOldNamespaceMap, + OUString& rIssuerName, OUString& rSerialNumber) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rX509IssuerName(rIssuerName) + , m_rX509SerialNumber(rSerialNumber) + { + } + + virtual std::unique_ptr CreateChildContext( + std::optional&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "X509IssuerName") + { + return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_rX509IssuerName); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "X509SerialNumber") + { + return std::make_unique(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> m_X509IssuerSerials; + std::vector m_X509Certificates; + + public: + DsX509DataContext(XSecParser& rParser, + std::optional&& pOldNamespaceMap) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void EndElement() override + { + m_rParser.m_pXSecController->setX509Data(m_X509IssuerSerials, m_X509Certificates); + } + + virtual std::unique_ptr CreateChildContext( + std::optional&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "X509IssuerSerial") + { + m_X509IssuerSerials.emplace_back(); + return std::make_unique(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(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&& pOldNamespaceMap) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference const& xAttrs) override + { + m_rParser.HandleIdAttr(xAttrs); + } + + virtual std::unique_ptr CreateChildContext( + std::optional&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "X509Data") + { + return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "PGPData") + { + return std::make_unique(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&& pOldNamespaceMap) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference 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&& pOldNamespaceMap, + OUString& rValue) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rValue(rValue) + { + } + + virtual void StartElement( + css::uno::Reference 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&& pOldNamespaceMap, + sal_Int32& rReferenceDigestID) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rReferenceDigestID(rReferenceDigestID) + { + } + + virtual void StartElement( + css::uno::Reference 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&& pOldNamespaceMap, + bool& rIsC14N) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rIsC14N(rIsC14N) + { + } + + virtual void StartElement( + css::uno::Reference 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&& pOldNamespaceMap, + bool& rIsC14N) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rIsC14N(rIsC14N) + { + } + + virtual std::unique_ptr CreateChildContext( + std::optional&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "Transform") + { + return std::make_unique(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&& pOldNamespaceMap) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference 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 CreateChildContext( + std::optional&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "Transforms") + { + return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_IsC14N); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "DigestMethod") + { + return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_nReferenceDigestID); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "DigestValue") + { + return std::make_unique(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&& pOldNamespaceMap) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference 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&& pOldNamespaceMap) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference const& xAttrs) override + { + m_rParser.HandleIdAttr(xAttrs); + } + + virtual void EndElement() override + { + m_rParser.m_pXSecController->setReferenceCount(); + } + + virtual std::unique_ptr CreateChildContext( + std::optional&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "SignatureMethod") + { + return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "Reference") + { + return std::make_unique(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&& pOldNamespaceMap) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference 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&& pOldNamespaceMap) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference const& xAttrs) override + { + m_rParser.HandleIdAttr(xAttrs); + } + + virtual std::unique_ptr CreateChildContext( + std::optional&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "EncapsulatedX509Certificate") + { + return std::make_unique(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&& pOldNamespaceMap) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference const& xAttrs) override + { + m_rParser.HandleIdAttr(xAttrs); + } + + virtual std::unique_ptr CreateChildContext( + std::optional&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "CertificateValues") + { + return std::make_unique(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&& pOldNamespaceMap) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference const& xAttrs) override + { + m_rParser.HandleIdAttr(xAttrs); + } + + virtual std::unique_ptr CreateChildContext( + std::optional&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "UnsignedSignatureProperties") + { + return std::make_unique(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&& 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&& 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&& 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&& pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual std::unique_ptr CreateChildContext( + std::optional&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_LO_EXT && rName == "SignatureLineId") + { + return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + if (nNamespace == XML_NAMESPACE_LO_EXT && rName == "SignatureLineValidImage") + { + return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + if (nNamespace == XML_NAMESPACE_LO_EXT && rName == "SignatureLineInvalidImage") + { + return std::make_unique(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&& pOldNamespaceMap, + OUString& rDigestValue, sal_Int32& rReferenceDigestID) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + , m_rDigestValue(rDigestValue) + , m_rReferenceDigestID(rReferenceDigestID) + { + } + + virtual std::unique_ptr CreateChildContext( + std::optional&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "DigestMethod") + { + return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_rReferenceDigestID); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "DigestValue") + { + return std::make_unique(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&& 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 CreateChildContext( + std::optional&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "CertDigest") + { + return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_CertDigest, m_nReferenceDigestID); + } + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "IssuerSerial") + { + return std::make_unique(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&& pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual std::unique_ptr CreateChildContext( + std::optional&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "Cert") + { + return std::make_unique(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&& 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&& pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void StartElement( + css::uno::Reference const& xAttrs) override + { + CheckIdAttrReferenced(xAttrs); + } + + virtual std::unique_ptr CreateChildContext( + std::optional&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SigningTime") + { + return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SigningCertificate") + { + return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + if (nNamespace == XML_NAMESPACE_LO_EXT && rName == "SignatureLine") + { + return std::make_unique(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&& pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void StartElement( + css::uno::Reference const& xAttrs) override + { + CheckIdAttrReferenced(xAttrs); + } + + virtual std::unique_ptr CreateChildContext( + std::optional&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SignedSignatureProperties") + { + return std::make_unique(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&& pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void StartElement( + css::uno::Reference const& xAttrs) override + { + CheckIdAttrReferenced(xAttrs); + } + + virtual std::unique_ptr CreateChildContext( + std::optional&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SignedProperties") + { + return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "UnsignedProperties") + { + return std::make_unique(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&& 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&& 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&& pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void StartElement( + css::uno::Reference 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 CreateChildContext( + std::optional&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DC && rName == "date") + { + m_Property = SignatureProperty::Date; + return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_Value); + } + if (nNamespace == XML_NAMESPACE_DC && rName == "description") + { + m_Property = SignatureProperty::Description; + return std::make_unique(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&& pOldNamespaceMap, + bool const isReferenced) + : ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced) + { + } + + virtual void StartElement( + css::uno::Reference const& xAttrs) override + { + CheckIdAttrReferenced(xAttrs); + } + + virtual std::unique_ptr CreateChildContext( + std::optional&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "SignatureProperty") + { + return std::make_unique(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&& 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 const& xAttrs) override + { + CheckIdAttrReferenced(xAttrs); + } + + virtual std::unique_ptr CreateChildContext( + std::optional&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "SignatureProperties") + { + return std::make_unique(m_rParser, std::move(pOldNamespaceMap), m_isReferenced); + } + if (nNamespace == XML_NAMESPACE_XADES132 && rName == "QualifyingProperties") + { + return std::make_unique(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&& pOldNamespaceMap) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual void StartElement( + css::uno::Reference 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 CreateChildContext( + std::optional&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "SignedInfo") + { + return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "SignatureValue") + { + return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "KeyInfo") + { + return std::make_unique(m_rParser, std::move(pOldNamespaceMap)); + } + if (nNamespace == XML_NAMESPACE_DS && rName == "Object") + { + return std::make_unique(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&& pOldNamespaceMap) + : XSecParser::Context(rParser, std::move(pOldNamespaceMap)) + { + } + + virtual std::unique_ptr CreateChildContext( + std::optional&& pOldNamespaceMap, + sal_uInt16 const nNamespace, OUString const& rName) override + { + if (nNamespace == XML_NAMESPACE_DS && rName == "Signature") + { + return std::make_unique(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 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 pRewindMap( + SvXMLImport::processNSAttributes(m_pNamespaceMap, nullptr, xAttribs)); + + OUString localName; + sal_uInt16 const nPrefix(m_pNamespaceMap->GetKeyByAttrName(rName, &localName)); + + std::unique_ptr pContext; + + if (m_ContextStack.empty()) + { + if ((nPrefix != XML_NAMESPACE_DSIG && nPrefix != XML_NAMESPACE_DSIG_OOO) + || localName != "document-signatures") + { + throw css::xml::sax::SAXException( + "xmlsecurity: unexpected root element", nullptr, + css::uno::Any()); + } + + pContext.reset(new DsigSignaturesContext(*this, std::move(pRewindMap))); + + } + else + { + pContext = m_ContextStack.top()->CreateChildContext( + std::move(pRewindMap), nPrefix, localName); + } + + m_ContextStack.push(std::move(pContext)); + + try + { + m_ContextStack.top()->StartElement(xAttribs); + + if (m_xNextHandler.is()) + { + m_xNextHandler->startElement(rName, xAttribs); + } + } + catch (css::uno::Exception& ) + {//getCaughtException MUST be the first line in the catch block + css::uno::Any exc = cppu::getCaughtException(); + throw css::xml::sax::SAXException( + "xmlsecurity: Exception in XSecParser::startElement", + nullptr, exc); + } + catch (...) + { + throw css::xml::sax::SAXException( + "xmlsecurity: unexpected exception in XSecParser::startElement", nullptr, + css::uno::Any()); + } +} + +void SAL_CALL XSecParser::endElement(const OUString& rName) +{ + assert(!m_ContextStack.empty()); // this should be checked by sax parser? + + try + { + m_ContextStack.top()->EndElement(); + + if (m_xNextHandler.is()) + { + m_xNextHandler->endElement(rName); + } + } + catch (css::uno::Exception& ) + {//getCaughtException MUST be the first line in the catch block + css::uno::Any exc = cppu::getCaughtException(); + throw css::xml::sax::SAXException( + "xmlsecurity: Exception in XSecParser::endElement", + nullptr, exc); + } + catch (...) + { + throw css::xml::sax::SAXException( + "xmlsecurity: unexpected exception in XSecParser::endElement", nullptr, + css::uno::Any()); + } + + if (m_ContextStack.top()->m_pOldNamespaceMap) + { + m_pNamespaceMap = std::move(m_ContextStack.top()->m_pOldNamespaceMap); + } + m_ContextStack.pop(); +} + +void SAL_CALL XSecParser::characters(const OUString& rChars) +{ + assert(!m_ContextStack.empty()); // this should be checked by sax parser? + m_ContextStack.top()->Characters(rChars); + + if (m_xNextHandler.is()) + { + m_xNextHandler->characters(rChars); + } +} + +void SAL_CALL XSecParser::ignorableWhitespace( const OUString& aWhitespaces ) +{ + if (m_xNextHandler.is()) + { + m_xNextHandler->ignorableWhitespace( aWhitespaces ); + } +} + +void SAL_CALL XSecParser::processingInstruction( const OUString& aTarget, const OUString& aData ) +{ + if (m_xNextHandler.is()) + { + m_xNextHandler->processingInstruction(aTarget, aData); + } +} + +void SAL_CALL XSecParser::setDocumentLocator( const css::uno::Reference< css::xml::sax::XLocator >& xLocator ) +{ + if (m_xNextHandler.is()) + { + m_xNextHandler->setDocumentLocator( xLocator ); + } +} + +/* + * XInitialization + */ +void SAL_CALL XSecParser::initialize( + const css::uno::Sequence< css::uno::Any >& aArguments ) +{ + aArguments[0] >>= m_xNextHandler; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/helper/xsecparser.hxx b/xmlsecurity/source/helper/xsecparser.hxx new file mode 100644 index 0000000000..6279d65439 --- /dev/null +++ b/xmlsecurity/source/helper/xsecparser.hxx @@ -0,0 +1,159 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include +#include + +#include + +#include + +#include +#include +#include + +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> m_ContextStack; + std::optional 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 const& xAttrs); + static OUString getIdAttr(const css::uno::Reference< + css::xml::sax::XAttributeList >& xAttribs ); + +public: + XSecParser(XMLSignatureHelper& rXMLSignatureHelper, XSecController* pXSecController); + + /* + * XDocumentHandler + */ + virtual void SAL_CALL startDocument( ) override; + + virtual void SAL_CALL endDocument( ) override; + + virtual void SAL_CALL startElement( + const OUString& aName, + const css::uno::Reference< + css::xml::sax::XAttributeList >& xAttribs ) override; + + virtual void SAL_CALL endElement( const OUString& aName ) override; + + virtual void SAL_CALL characters( const OUString& aChars ) override; + + virtual void SAL_CALL ignorableWhitespace( const OUString& aWhitespaces ) override; + + virtual void SAL_CALL processingInstruction( + const OUString& aTarget, + const OUString& aData ) override; + + virtual void SAL_CALL setDocumentLocator( + const css::uno::Reference< + css::xml::sax::XLocator >& xLocator ) override; + + /* + * XInitialization + */ + virtual void SAL_CALL initialize( + const css::uno::Sequence< css::uno::Any >& aArguments ) override; +}; + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/helper/xsecsign.cxx b/xmlsecurity/source/helper/xsecsign.cxx new file mode 100644 index 0000000000..6788f694ec --- /dev/null +++ b/xmlsecurity/source/helper/xsecsign.cxx @@ -0,0 +1,462 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include + +#include +#include +#include +#include + +#include +#include + +namespace com::sun::star::graphic { class XGraphic; } + +using namespace css; +using namespace css::uno; +using namespace css::graphic; + +/* protected: for signature generation */ +OUString XSecController::createId() +{ + sal_uInt8 aSeq[16]; + rtl_createUuid( aSeq, nullptr, true ); + + char str[68]="ID_"; + int length = 3; + for (sal_uInt8 i : aSeq) + { + SAL_WNODEPRECATED_DECLARATIONS_PUSH // sprintf (macOS 13 SDK) + length += sprintf(str+length, "%04x", i); + SAL_WNODEPRECATED_DECLARATIONS_POP + } + + return OUString::createFromAscii(str); +} + +css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > XSecController::prepareSignatureToWrite( + InternalSignatureInformation& internalSignatureInfor, + sal_Int32 nStorageFormat, + bool bXAdESCompliantIfODF) +{ + sal_Int32 nSecurityId = internalSignatureInfor.signatureInfor.nSecurityId; + SignatureReferenceInformations& vReferenceInfors = internalSignatureInfor.signatureInfor.vSignatureReferenceInfors; + + sal_Int32 nIdOfSignatureElementCollector; + + nIdOfSignatureElementCollector = + m_xSAXEventKeeper->addSecurityElementCollector( css::xml::crypto::sax::ElementMarkPriority_AFTERMODIFY, true ); + + m_xSAXEventKeeper->setSecurityId(nIdOfSignatureElementCollector, nSecurityId); + + rtl::Reference xSignatureCreator(new SignatureCreatorImpl); + + css::uno::Sequence args + { + Any(OUString::number(nSecurityId)), + Any(uno::Reference(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; isetSecurityId(keeperId, nSecurityId); + m_xSAXEventKeeper->addReferenceResolvedListener( keeperId, xSignatureCreator); + xSignatureCreator->setReferenceId( keeperId ); + nReferenceCount++; + } + } + + xSignatureCreator->setReferenceCount( nReferenceCount ); + + /* + * adds all URI binding + */ + for(int i=0; i 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& 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& 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& 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 xSEKHandler(m_xSAXEventKeeper); + + int i; + int sigNum = m_vInternalSignatureInformations.size(); + + for (i=0; isetNextHandler( nullptr ); + m_bIsSAXEventKeeperSticky = false; + } + + return rc; +} + +bool XSecController::WriteOOXMLSignature(const uno::Reference& xRootStorage, const uno::Reference& 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 xSEKHandler(m_xSAXEventKeeper); + + for (InternalSignatureInformation & rInformation : m_vInternalSignatureInformations) + { + // Prepare the signature creator. + rInformation.xReferenceResolvedListener = prepareSignatureToWrite(rInformation, embed::StorageFormats::OFOPXML, false); + + exportOOXMLSignature(xRootStorage, xSEKHandler, rInformation.signatureInfor); + } + + m_bIsSAXEventKeeperSticky = false; + chainOff(); + + bRet = true; + } + catch(const uno::Exception&) + { + } + + m_xSAXEventKeeper->setNextHandler(nullptr); + m_bIsSAXEventKeeperSticky = false; + } + + return bRet; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/helper/xsecverify.cxx b/xmlsecurity/source/helper/xsecverify.cxx new file mode 100644 index 0000000000..c45bece5fe --- /dev/null +++ b/xmlsecurity/source/helper/xsecverify.cxx @@ -0,0 +1,630 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include +#include "xsecparser.hxx" +#include "ooxmlsecparser.hxx" +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 xInitialization(xReferenceResolvedListener, css::uno::UNO_QUERY); + + css::uno::Sequence args + { + Any(OUString::number(nSecurityId)), + Any(uno::Reference(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 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( + m_vInternalSignatureInformations.back().xReferenceResolvedListener.get()); + if (pImpl) + { + css::uno::Reference 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 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 xReferenceCollector + (isi.xReferenceResolvedListener, css::uno::UNO_QUERY); + xReferenceCollector->setReferenceCount( referenceCount ); +} + +void XSecController::setX509Data( + std::vector> & rX509IssuerSerials, + std::vector 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 const xSecEnv(m_xSecurityContext->getSecurityEnvironment()); + uno::Reference 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& 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 const xSecEnv(m_xSecurityContext->getSecurityEnvironment()); + uno::Reference 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 lcl_getGraphicFromString(std::u16string_view rImage) +{ + Sequence seq; + comphelper::Base64::decode(seq, rImage); + + Reference< graphic::XGraphic > xGraphic; + if( !seq.hasElements() ) + return Reference(); + + 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; isetNextHandler(nullptr); + } + + sal_Int32 nKeeperId = m_xSAXEventKeeper->addSecurityElementCollector( + css::xml::crypto::sax::ElementMarkPriority_BEFOREMODIFY, false ); + + css::uno::Reference xReferenceCollector + ( isi.xReferenceResolvedListener, css::uno::UNO_QUERY ); + + m_xSAXEventKeeper->setSecurityId(nKeeperId, isi.signatureInfor.nSecurityId); + m_xSAXEventKeeper->addReferenceResolvedListener( nKeeperId, isi.xReferenceResolvedListener); + xReferenceCollector->setReferenceId( nKeeperId ); + + isi.vKeeperIds[j] = nKeeperId; + break; + } + } + } + + if ( bJustChainingOn ) + { + m_xSAXEventKeeper->setNextHandler(xHandler); + } +} + +void XSecController::addSignature( sal_Int32 nSignatureId ) +{ + SAL_WARN_IF( !m_xSecParser.is(), "xmlsecurity.helper", "No XSecParser initialized" ); + + m_nReservedSignatureId = nSignatureId; + m_bVerifyCurrentSignature = true; +} + +css::uno::Reference< css::xml::sax::XDocumentHandler > const & XSecController::createSignatureReader(XMLSignatureHelper& rXMLSignatureHelper, sal_Int32 nType) +{ + if (nType == embed::StorageFormats::OFOPXML) + m_xSecParser = new OOXMLSecParser(rXMLSignatureHelper, this); + else + m_xSecParser = new XSecParser(rXMLSignatureHelper, this); + css::uno::Reference< css::lang::XInitialization > xInitialization(m_xSecParser, uno::UNO_QUERY); + + setSAXChainConnector(xInitialization); + + return m_xSecParser; +} + +void XSecController::releaseSignatureReader() +{ + clearSAXChainConnector( ); + m_xSecParser.clear(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/biginteger.cxx b/xmlsecurity/source/xmlsec/biginteger.cxx new file mode 100644 index 0000000000..1a4ab6fd9d --- /dev/null +++ b/xmlsecurity/source/xmlsec/biginteger.cxx @@ -0,0 +1,106 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include + +#include +#include + +#include + +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(onumeral.getStr()), static_cast(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(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(integer.getConstArray()), integer.getLength() ) < 0 ) { + xmlSecBnFinalize( &bn ) ; + return aRet ; + } + + chNumeral = xmlSecBnToDecString( &bn ) ; + if( chNumeral == nullptr ) { + xmlSecBnFinalize( &bn ) ; + return aRet ; + } + + aRet = OUString::createFromAscii( reinterpret_cast(chNumeral) ) ; + + xmlSecBnFinalize( &bn ) ; + xmlFree( chNumeral ) ; + } + + return aRet ; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/certificateextension_certextn.cxx b/xmlsecurity/source/xmlsec/certificateextension_certextn.cxx new file mode 100644 index 0000000000..d7325759de --- /dev/null +++ b/xmlsecurity/source/xmlsec/certificateextension_certextn.cxx @@ -0,0 +1,47 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "certificateextension_certextn.hxx" + +#include + +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(value, vlen); + } else { + m_xExtnValue = css::uno::Sequence(); + } + + if( id != nullptr && idlen != 0 ) { + m_xExtnId = comphelper::arrayToSequence(id, idlen); + } else { + m_xExtnId = css::uno::Sequence(); + } + + m_critical = critical ; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/certificateextension_certextn.hxx b/xmlsecurity/source/xmlsec/certificateextension_certextn.hxx new file mode 100644 index 0000000000..ac84596c83 --- /dev/null +++ b/xmlsecurity/source/xmlsec/certificateextension_certextn.hxx @@ -0,0 +1,36 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include +#include + +struct CertificateExtension_CertExtn +{ + bool m_critical; + css::uno::Sequence m_xExtnId; + css::uno::Sequence m_xExtnValue; + + CertificateExtension_CertExtn(); + void setCertExtn(unsigned char const* value, unsigned int vlen, unsigned char const* id, + unsigned int idlen, bool critical); +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/certificateextension_xmlsecimpl.hxx b/xmlsecurity/source/xmlsec/certificateextension_xmlsecimpl.hxx new file mode 100644 index 0000000000..9db5867fc7 --- /dev/null +++ b/xmlsecurity/source/xmlsec/certificateextension_xmlsecimpl.hxx @@ -0,0 +1,56 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include +#include +#include +#include "certificateextension_certextn.hxx" + +class CertificateExtension_XmlSecImpl : public ::cppu::WeakImplHelper< + css::security::XCertificateExtension > +{ + private: + CertificateExtension_CertExtn m_Extn; + + public: + //Methods from XCertificateExtension + virtual sal_Bool SAL_CALL isCritical() override + { + return m_Extn.m_critical; + } + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getExtensionId() override + { + return m_Extn.m_xExtnId; + } + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getExtensionValue() override + { + return m_Extn.m_xExtnValue; + } + + void setCertExtn(unsigned char const * value, unsigned int vlen, unsigned char const * id, unsigned int idlen, bool critical) + { + m_Extn.setCertExtn(value, vlen, id, idlen, critical); + } +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/errorcallback.cxx b/xmlsecurity/source/xmlsec/errorcallback.cxx new file mode 100644 index 0000000000..a535ffa770 --- /dev/null +++ b/xmlsecurity/source/xmlsec/errorcallback.cxx @@ -0,0 +1,68 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include + +#include + +#include +#include + +#ifdef _WIN32 +#include +#include +#include +#endif + +extern "C" { + +static void errorCallback(const char* file, + int line, + const char* func, + const char* errorObject, + const char* errorSubject, + int reason, + const char* msg) +{ + const char* pErrorObject = errorObject ? errorObject : ""; + const char* pErrorSubject = errorSubject ? errorSubject : ""; + const char* pMsg = msg ? msg : ""; + OUString systemErrorString; + +#ifdef _WIN32 + systemErrorString = " " + WindowsErrorString(GetLastError()); +#endif + + SAL_WARN("xmlsecurity.xmlsec", file << ":" << line << ": " << func << "() '" << pErrorObject << "' '" << pErrorSubject << "' " << reason << " '" << pMsg << "'" << systemErrorString); +} + +} + +void setErrorRecorder() +{ + xmlSecErrorsSetCallback(errorCallback); +} + +void clearErrorRecorder() +{ + xmlSecErrorsSetCallback(nullptr); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/mscrypt/akmngr.cxx b/xmlsecurity/source/xmlsec/mscrypt/akmngr.cxx new file mode 100644 index 0000000000..ec3cecd4a7 --- /dev/null +++ b/xmlsecurity/source/xmlsec/mscrypt/akmngr.cxx @@ -0,0 +1,229 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include + +#include "akmngr.hxx" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace xmlsecurity +{ + +/** + * MSCryptoAppliedKeysMngrCreate: + * + * Create and load key store and certificate database into keys manager + * + * Returns keys manager pointer on success or NULL otherwise. + */ +xmlSecKeysMngrPtr MSCryptoAppliedKeysMngrCreate() +{ + xmlSecKeysMngrPtr keyMngr = nullptr ; + xmlSecKeyStorePtr keyStore = nullptr ; + + keyStore = xmlSecKeyStoreCreate(xmlSecMSCngKeysStoreId); + if (keyStore == nullptr) + { + xmlSecError(XMLSEC_ERRORS_HERE, + nullptr, + "xmlSecKeyStoreCreate", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE) ; + return nullptr ; + } + + keyMngr = xmlSecKeysMngrCreate() ; + if (keyMngr == nullptr) + { + xmlSecError(XMLSEC_ERRORS_HERE, + nullptr, + "xmlSecKeysMngrCreate", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE) ; + + xmlSecKeyStoreDestroy(keyStore) ; + return nullptr ; + } + + /*- + * Add key store to manager, from now on keys manager destroys the store if + * needed + */ + if (xmlSecKeysMngrAdoptKeysStore(keyMngr, keyStore) < 0) + { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyStoreGetName(keyStore)), + "xmlSecKeysMngrAdoptKeyStore", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE) ; + + xmlSecKeyStoreDestroy(keyStore) ; + xmlSecKeysMngrDestroy(keyMngr) ; + return nullptr ; + } + + /*- + * Initialize crypto library specific data in keys manager + */ + if (xmlSecMSCngKeysMngrInit(keyMngr) < 0) + { + xmlSecError(XMLSEC_ERRORS_HERE, + nullptr, + "xmlSecMSCngKeysMngrInit", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + + xmlSecKeysMngrDestroy(keyMngr); + return nullptr; + } + + /*- + * Set certificate database to X509 key data store + */ + /*- + * At present, MS Crypto engine do not provide a way to setup a cert store. + */ + + /*- + * Set the getKey callback + */ + keyMngr->getKey = xmlSecKeysMngrGetKey ; + + return keyMngr ; +} + +int +MSCryptoAppliedKeysMngrAdoptKeyStore( + xmlSecKeysMngrPtr mngr, + HCERTSTORE keyStore +) +{ + xmlSecKeyDataStorePtr x509Store ; + + xmlSecAssert2(mngr != nullptr, -1) ; + xmlSecAssert2(keyStore != nullptr, -1) ; + + x509Store = xmlSecKeysMngrGetDataStore(mngr, xmlSecMSCngX509StoreId); + if (x509Store == nullptr) + { + xmlSecError(XMLSEC_ERRORS_HERE, + nullptr, + "xmlSecKeysMngrGetDataStore", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE) ; + return -1 ; + } + + if (xmlSecMSCngX509StoreAdoptKeyStore(x509Store, keyStore) < 0) + { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(x509Store)), + "xmlSecMSCngX509StoreAdoptKeyStore", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return -1; + } + + return 0 ; +} + +int +MSCryptoAppliedKeysMngrAdoptTrustedStore( + xmlSecKeysMngrPtr mngr, + HCERTSTORE trustedStore +) +{ + xmlSecKeyDataStorePtr x509Store ; + + xmlSecAssert2(mngr != nullptr, -1) ; + xmlSecAssert2(trustedStore != nullptr, -1) ; + + x509Store = xmlSecKeysMngrGetDataStore(mngr, xmlSecMSCngX509StoreId); + if (x509Store == nullptr) + { + xmlSecError(XMLSEC_ERRORS_HERE, + nullptr, + "xmlSecKeysMngrGetDataStore", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE) ; + return -1 ; + } + + if (xmlSecMSCngX509StoreAdoptTrustedStore(x509Store, trustedStore) < 0) + { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(x509Store)), + "xmlSecMSCngX509StoreAdoptKeyStore", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return -1; + } + + return 0 ; +} + +int +MSCryptoAppliedKeysMngrAdoptUntrustedStore( + xmlSecKeysMngrPtr mngr, + HCERTSTORE untrustedStore +) +{ + xmlSecKeyDataStorePtr x509Store ; + + xmlSecAssert2(mngr != nullptr, -1) ; + xmlSecAssert2(untrustedStore != nullptr, -1) ; + + x509Store = xmlSecKeysMngrGetDataStore(mngr, xmlSecMSCngX509StoreId); + if (x509Store == nullptr) + { + xmlSecError(XMLSEC_ERRORS_HERE, + nullptr, + "xmlSecKeysMngrGetDataStore", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE) ; + return -1 ; + } + + if (xmlSecMSCngX509StoreAdoptUntrustedStore(x509Store, untrustedStore) < 0) + { + xmlSecError(XMLSEC_ERRORS_HERE, + xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(x509Store)), + "xmlSecMSCngX509StoreAdoptKeyStore", + XMLSEC_ERRORS_R_XMLSEC_FAILED, + XMLSEC_ERRORS_NO_MESSAGE); + return -1; + } + + return 0 ; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/xmlsecurity/source/xmlsec/mscrypt/akmngr.hxx b/xmlsecurity/source/xmlsec/mscrypt/akmngr.hxx new file mode 100644 index 0000000000..e5942ba2af --- /dev/null +++ b/xmlsecurity/source/xmlsec/mscrypt/akmngr.hxx @@ -0,0 +1,56 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#if !defined WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +#endif +#include +#include + +#include +#include +#include + +namespace xmlsecurity +{ + +xmlSecKeysMngrPtr MSCryptoAppliedKeysMngrCreate(); + +int +MSCryptoAppliedKeysMngrAdoptKeyStore( + xmlSecKeysMngrPtr mngr, + HCERTSTORE keyStore +) ; + +int +MSCryptoAppliedKeysMngrAdoptTrustedStore( + xmlSecKeysMngrPtr mngr, + HCERTSTORE trustedStore +) ; + +int +MSCryptoAppliedKeysMngrAdoptUntrustedStore( + xmlSecKeysMngrPtr mngr, + HCERTSTORE untrustedStore +) ; + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/xmlsecurity/source/xmlsec/mscrypt/oid.hxx b/xmlsecurity/source/xmlsec/mscrypt/oid.hxx new file mode 100644 index 0000000000..ce573d8827 --- /dev/null +++ b/xmlsecurity/source/xmlsec/mscrypt/oid.hxx @@ -0,0 +1,153 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include + +typedef struct { + char const *oid; + char const *desc; +} OIDItem; + +OIDItem OIDs[] = { + {"1.2.840.113549", "RSA Data Security Inc."}, + {"1.2.840.113549.1", "PKCS"}, + {"1.2.840.113549.2", "RSA digest algorithm"}, + {"1.2.840.113549.3", "RSA cipher algorithm"}, + {"1.2.840.113549.1.1", "PKCS #1"}, + {"1.2.840.113549.1.2", "Unknown"}, + {"1.2.840.113549.1.3", "Unknown"}, + {"1.2.840.113549.1.4", "Unknown"}, + {"1.2.840.113549.1.5", "PKCS #5"}, + {"1.2.840.113549.1.6", "Unknown"}, + {"1.2.840.113549.1.7", "PKCS #7"}, + {"1.2.840.113549.1.8", "Unknown"}, + {"1.2.840.113549.1.9", "PKCS #9"}, + {"1.2.840.113549.1.10", "Unknown"}, + {"1.2.840.113549.1.12", "PKCS #12"}, + {"1.2.840.113549.1.1.2", "PKCS #1 MD2 With RSA Encryption"}, + {"1.2.840.113549.1.1.3", "PKCS #1 MD4 With RSA Encryption"}, + {"1.2.840.113549.1.1.4", "PKCS #1 MD5 With RSA Encryption"}, + {"1.2.840.113549.1.1.1", "PKCS #1 RSA Encryption"}, + {"1.2.840.113549.1.1.2", "PKCS #1 MD2 With RSA Encryption"}, + {"1.2.840.113549.1.1.3", "PKCS #1 MD4 With RSA Encryption"}, + {"1.2.840.113549.1.1.4", "PKCS #1 MD5 With RSA Encryption"}, + {"1.2.840.113549.1.1.5", "PKCS #1 SHA-1 With RSA Encryption"}, + {"1.2.840.113549.1.1.5", "PKCS #1 SHA-1 With RSA Encryption"}, + {"1.2.840.113549.1.3.1", "Unknown"}, + {"1.2.840.113549.1.7.1", "PKCS #7 Data"}, + {"1.2.840.113549.1.7.2", "PKCS #7 Signed Data"}, + {"1.2.840.113549.1.7.3", "PKCS #7 Enveloped Data"}, + {"1.2.840.113549.1.7.4", "PKCS #7 Signed and Enveloped Data"}, + {"1.2.840.113549.1.7.5", "PKCS #7 Digested Data"}, + {"1.2.840.113549.1.7.6", "PKCS #7 Encrypted Data"}, + {"1.2.840.113549.1.9.1", "PKCS #9 Email Address"}, + {"1.2.840.113549.1.9.2", "PKCS #9 Unstructured Name"}, + {"1.2.840.113549.1.9.3", "PKCS #9 Content Type"}, + {"1.2.840.113549.1.9.4", "PKCS #9 Message Digest"}, + {"1.2.840.113549.1.9.5", "PKCS #9 Signing Time"}, + {"1.2.840.113549.1.9.6", "PKCS #9 Counter Signature"}, + {"1.2.840.113549.1.9.7", "PKCS #9 Challenge Password"}, + {"1.2.840.113549.1.9.8", "PKCS #9 Unstructured Address"}, + {"1.2.840.113549.1.9.9", "PKCS #9 Extended Certificate Attributes"}, + {"1.2.840.113549.1.9.15", "PKCS #9 S/MIME Capabilities"}, + {"1.2.840.113549.1.9.15.1", "Unknown"}, + {"1.2.840.113549.3.2", "RC2-CBC"}, + {"1.2.840.113549.3.4", "RC4"}, + {"1.2.840.113549.3.7", "DES-EDE3-CBC"}, + {"1.2.840.113549.3.9", "RC5-CBCPad"}, + {"1.2.840.10046", "ANSI X9.42"}, + {"1.2.840.10046.2.1", "Diffie-Hellman Public Key Algorithm"}, + {"1.2.840.10040", "ANSI X9.57"}, + {"1.2.840.10040.4.1", "ANSI X9.57 DSA Signature"}, + {"1.2.840.10040.4.3", "ANSI X9.57 Algorithm DSA Signature with SHA-1 Digest"}, + {"2.5", "Directory"}, + {"2.5.8", "X.500-defined algorithms"}, + {"2.5.8.1", "X.500-defined encryption algorithms"}, + {"2.5.8.2", "Unknown"}, + {"2.5.8.3", "Unknown"}, + {"2.5.8.1.1", "RSA Encryption Algorithm"}, + {"1.3.14", "Open Systems Implementors Workshop"}, + {"1.3.14.3.2", "OIW SECSIG Algorithm"}, + {"1.3.14.3.2.2", "Unknown"}, + {"1.3.14.3.2.3", "Unknown"}, + {"1.3.14.3.2.4", "Unknown"}, + {"1.3.14.3.2.6", "DES-ECB"}, + {"1.3.14.3.2.7", "DES-CBC"}, + {"1.3.14.3.2.8", "DES-OFB"}, + {"1.3.14.3.2.9", "DES-CFB"}, + {"1.3.14.3.2.10", "DES-MAC"}, + {"1.3.14.3.2.11", "Unknown"}, + {"1.3.14.3.2.12", "Unknown"}, + {"1.3.14.3.2.13", "Unknown"}, + {"1.3.14.3.2.14", "Unknown"}, + {"1.3.14.3.2.15", "ISO SHA with RSA Signature"}, + {"1.3.14.3.2.16", "Unknown"}, + {"1.3.14.3.2.17", "DES-EDE"}, + {"1.3.14.3.2.18", "Unknown"}, + {"1.3.14.3.2.19", "Unknown"}, + {"1.3.14.3.2.20", "Unknown"}, + {"1.3.14.3.2.21", "Unknown"}, + {"1.3.14.3.2.22", "Unknown"}, + {"1.3.14.3.2.23", "Unknown"}, + {"1.3.14.3.2.24", "Unknown"}, + {"1.3.14.3.2.25", "Unknown"}, + {"1.3.14.3.2.26", "SHA-1"}, + {"1.3.14.3.2.27", "Forgezza DSA Signature with SHA-1 Digest"}, + {"1.3.14.3.2.28", "Unknown"}, + {"1.3.14.3.2.29", "Unknown"}, + {"1.3.14.7.2", "Unknown"}, + {"1.3.14.7.2.1", "Unknown"}, + {"1.3.14.7.2.2", "Unknown"}, + {"1.3.14.7.2.3", "Unknown"}, + {"1.3.14.7.2.2.1", "Unknown"}, + {"1.3.14.7.2.3.1", "Unknown"}, + {"2.16.840.1.101.2.1", "US DOD Infosec"}, + {"2.16.840.1.101.2.1.1.1", "Unknown"}, + {"2.16.840.1.101.2.1.1.2", "MISSI DSS Algorithm (Old)"}, + {"2.16.840.1.101.2.1.1.3", "Unknown"}, + {"2.16.840.1.101.2.1.1.4", "Skipjack CBC64"}, + {"2.16.840.1.101.2.1.1.5", "Unknown"}, + {"2.16.840.1.101.2.1.1.6", "Unknown"}, + {"2.16.840.1.101.2.1.1.7", "Unknown"}, + {"2.16.840.1.101.2.1.1.8", "Unknown"}, + {"2.16.840.1.101.2.1.1.9", "Unknown"}, + {"2.16.840.1.101.2.1.1.10", "MISSI KEA Algorithm"}, + {"2.16.840.1.101.2.1.1.11", "Unknown"}, + {"2.16.840.1.101.2.1.1.12", "MISSI KEA and DSS Algorithm (Old)"}, + {"2.16.840.1.101.2.1.1.13", "Unknown"}, + {"2.16.840.1.101.2.1.1.14", "Unknown"}, + {"2.16.840.1.101.2.1.1.15", "Unknown"}, + {"2.16.840.1.101.2.1.1.16", "Unknown"}, + {"2.16.840.1.101.2.1.1.17", "Unknown"}, + {"2.16.840.1.101.2.1.1.18", "Unknown"}, + {"2.16.840.1.101.2.1.1.19", "MISSI DSS Algorithm"}, + {"2.16.840.1.101.2.1.1.20", "MISSI KEA and DSS Algorithm"}, + {"2.16.840.1.101.2.1.1.21", "Unknown"}, + {"1.2.643.2.2.35.0", "GOST_R_34.10-2001_Test"}, + {"1.2.643.2.2.35.1", "GOST_R_34.10-2001_Sign_DH_PRO"}, + {"1.2.643.2.2.35.2", "GOST_R_34.10-2001_Sign_DH_CARD"}, + {"1.2.643.2.2.35.3", "GOST_R_34.10-2001_Sign_DH"}, + {"1.2.643.2.2.36.0", "GOST_R_34.10-2001_Sign_DH_PRO"} +}; + +const int nOID = SAL_N_ELEMENTS(OIDs); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/mscrypt/sanextension_mscryptimpl.cxx b/xmlsecurity/source/xmlsec/mscrypt/sanextension_mscryptimpl.cxx new file mode 100644 index 0000000000..6ded5fa0cb --- /dev/null +++ b/xmlsecurity/source/xmlsec/mscrypt/sanextension_mscryptimpl.cxx @@ -0,0 +1,131 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#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(m_xExtnValue.getArray()), m_xExtnValue.getLength(), CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG, nullptr,&subjectName, &size); + + auto arrCertAltNameEntry = std::make_unique(subjectName->cAltEntry); + + for (unsigned int i = 0; i < static_cast(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( + 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( + pEntry->IPAddress.pbData, pEntry->IPAddress.cbData) ); + arrCertAltNameEntry[i].Value <<= ipAddress; + break; + } + case CERT_ALT_NAME_REGISTERED_ID : + arrCertAltNameEntry[i].Type = ExtAltNameType_REGISTERED_ID; + arrCertAltNameEntry[i].Value <<= OUString::createFromAscii(pEntry->pszRegisteredID); + break; + } + } + m_Entries = ::comphelper::arrayToSequence< css::security::CertAltNameEntry >(arrCertAltNameEntry.get(), subjectName->cAltEntry); + } + + return m_Entries; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/mscrypt/sanextension_mscryptimpl.hxx b/xmlsecurity/source/xmlsec/mscrypt/sanextension_mscryptimpl.hxx new file mode 100644 index 0000000000..6c65c84f86 --- /dev/null +++ b/xmlsecurity/source/xmlsec/mscrypt/sanextension_mscryptimpl.hxx @@ -0,0 +1,66 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#if !defined WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class SanExtensionImpl : public ::cppu::WeakImplHelper< + css::security::XSanExtension > +{ + private: + bool m_critical ; + css::uno::Sequence< sal_Int8 > m_xExtnId ; + css::uno::Sequence< sal_Int8 > m_xExtnValue ; + + css::uno::Sequence< css::security::CertAltNameEntry > m_Entries; + + public: + SanExtensionImpl() ; + virtual ~SanExtensionImpl() override; + + //Methods from XCertificateExtension + virtual sal_Bool SAL_CALL isCritical() override; + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getExtensionId() override; + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getExtensionValue() override; + + //Methods from XSanExtension + + virtual css::uno::Sequence< css::security::CertAltNameEntry > SAL_CALL getAlternativeNames() override; + + //Helper method + void setCertExtn( unsigned char* value, unsigned int vlen, unsigned char* id, unsigned int idlen, bool critical ) ; +} ; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.cxx b/xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.cxx new file mode 100644 index 0000000000..cd3d40eb14 --- /dev/null +++ b/xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.cxx @@ -0,0 +1,1110 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include +#include + +#if !defined WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +#endif +#include +#include +#include +#include +#include "securityenvironment_mscryptimpl.hxx" + +#include "x509certificate_mscryptimpl.hxx" +#include +#include +#include +#include +#include +#include "akmngr.hxx" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace ::com::sun::star; +using namespace ::com::sun::star::lang ; + +using ::com::sun::star::xml::crypto::XSecurityEnvironment ; +using ::com::sun::star::security::XCertificate ; + +static rtl::Reference MswcryCertContextToXCert( PCCERT_CONTEXT cert ) ; + +namespace { + +struct CertErrorToString{ + DWORD error; + char const * name; +}; + +} + +CertErrorToString const arErrStrings[] = +{ + { 0x00000000, "CERT_TRUST_NO_ERROR"}, + { 0x00000001, "CERT_TRUST_IS_NOT_TIME_VALID"}, + { 0x00000002, "CERT_TRUST_IS_NOT_TIME_NESTED"}, + { 0x00000004, "CERT_TRUST_IS_REVOKED" }, + { 0x00000008, "CERT_TRUST_IS_NOT_SIGNATURE_VALID" }, + { 0x00000010, "CERT_TRUST_IS_NOT_SIGNATURE_VALID"}, + { 0x00000020, "CERT_TRUST_IS_UNTRUSTED_ROOT"}, + { 0x00000040, "CERT_TRUST_REVOCATION_STATUS_UNKNOWN"}, + { 0x00000080, "CERT_TRUST_IS_CYCLIC"}, + { 0x00000100, "CERT_TRUST_INVALID_EXTENSION"}, + { 0x00000200, "CERT_TRUST_INVALID_POLICY_CONSTRAINTS"}, + { 0x00000400, "CERT_TRUST_INVALID_BASIC_CONSTRAINTS"}, + { 0x00000800, "CERT_TRUST_INVALID_NAME_CONSTRAINTS"}, + { 0x00001000, "CERT_TRUST_HAS_NOT_SUPPORTED_NAME_CONSTRAINT"}, + { 0x00002000, "CERT_TRUST_HAS_NOT_DEFINED_NAME_CONSTRAINT"}, + { 0x00004000, "CERT_TRUST_HAS_NOT_PERMITTED_NAME_CONSTRAINT"}, + { 0x00008000, "CERT_TRUST_HAS_EXCLUDED_NAME_CONSTRAINT"}, + { 0x01000000, "CERT_TRUST_IS_OFFLINE_REVOCATION"}, + { 0x02000000, "CERT_TRUST_NO_ISSUANCE_CHAIN_POLICY"}, + { 0x04000000, "CERT_TRUST_IS_EXPLICIT_DISTRUST"}, + { 0x08000000, "CERT_TRUST_HAS_NOT_SUPPORTED_CRITICAL_EXT"}, + //Chain errors + { 0x00010000, "CERT_TRUST_IS_PARTIAL_CHAIN"}, + { 0x00020000, "CERT_TRUST_CTL_IS_NOT_TIME_VALID"}, + { 0x00040000, "CERT_TRUST_CTL_IS_NOT_SIGNATURE_VALID"}, + { 0x00080000, "CERT_TRUST_CTL_IS_NOT_VALID_FOR_USAGE"} +}; + +static void traceTrustStatus(DWORD err) +{ + if (err == 0) + SAL_INFO("xmlsecurity.xmlsec", " " << arErrStrings[0].name); + for (auto const & arErrStringIter : arErrStrings) + { + if (arErrStringIter.error & err) + SAL_INFO("xmlsecurity.xmlsec", " " << arErrStringIter.name); + } +} + +SecurityEnvironment_MSCryptImpl::SecurityEnvironment_MSCryptImpl( const uno::Reference< uno::XComponentContext >& xContext ) : m_hProv( 0 ) , m_pszContainer( nullptr ) , m_hKeyStore( nullptr ), m_hCertStore( nullptr ), m_hMySystemStore(nullptr), m_hRootSystemStore(nullptr), m_hTrustSystemStore(nullptr), m_hCaSystemStore(nullptr), m_bEnableDefault( false ){ + + m_xServiceManager.set(xContext, uno::UNO_QUERY); +} + +SecurityEnvironment_MSCryptImpl::~SecurityEnvironment_MSCryptImpl() { + + if( m_hProv != 0 ) { + CryptReleaseContext( m_hProv, 0 ) ; + m_hProv = 0 ; + } + + if( m_pszContainer != nullptr ) { + //TODO: Don't know whether or not it should be released now. + m_pszContainer = nullptr ; + } + + if( m_hCertStore != nullptr ) { + CertCloseStore( m_hCertStore, CERT_CLOSE_STORE_FORCE_FLAG ) ; + m_hCertStore = nullptr ; + } + + if( m_hKeyStore != nullptr ) { + CertCloseStore( m_hKeyStore, CERT_CLOSE_STORE_FORCE_FLAG ) ; + m_hKeyStore = nullptr ; + } + + //i120675, close the store handles + if( m_hMySystemStore != nullptr ) { + CertCloseStore( m_hMySystemStore, CERT_CLOSE_STORE_CHECK_FLAG ) ; + m_hMySystemStore = nullptr ; + } + + if( m_hRootSystemStore != nullptr ) { + CertCloseStore( m_hRootSystemStore, CERT_CLOSE_STORE_CHECK_FLAG ) ; + m_hRootSystemStore = nullptr ; + } + + if( m_hTrustSystemStore != nullptr ) { + CertCloseStore( m_hTrustSystemStore, CERT_CLOSE_STORE_CHECK_FLAG ) ; + m_hTrustSystemStore = nullptr ; + } + + if( m_hCaSystemStore != nullptr ) { + CertCloseStore( m_hCaSystemStore, CERT_CLOSE_STORE_CHECK_FLAG ) ; + m_hCaSystemStore = nullptr ; + } +} + +/* XServiceInfo */ +OUString SAL_CALL SecurityEnvironment_MSCryptImpl::getImplementationName() { + return "com.sun.star.xml.crypto.SecurityEnvironment"; +} + +/* XServiceInfo */ +sal_Bool SAL_CALL SecurityEnvironment_MSCryptImpl::supportsService( const OUString& serviceName) { + return cppu::supportsService(this, serviceName); +} +/* XServiceInfo */ +uno::Sequence< OUString > SAL_CALL SecurityEnvironment_MSCryptImpl::getSupportedServiceNames() { + return { "com.sun.star.xml.crypto.SecurityEnvironment" }; +} + +HCRYPTPROV SecurityEnvironment_MSCryptImpl::getCryptoProvider() { + return m_hProv ; +} + +void SecurityEnvironment_MSCryptImpl::setCryptoProvider( HCRYPTPROV aProv ) { + if( m_hProv != 0 ) { + CryptReleaseContext( m_hProv, 0 ) ; + m_hProv = 0 ; + } + + if( aProv != 0 ) { + m_hProv = aProv ; + } +} + +LPCTSTR SecurityEnvironment_MSCryptImpl::getKeyContainer() { + return m_pszContainer ; +} + +void SecurityEnvironment_MSCryptImpl::setKeyContainer( LPCTSTR aKeyContainer ) { + //TODO: Don't know whether or not it should be copied. + m_pszContainer = aKeyContainer ; +} + + +HCERTSTORE SecurityEnvironment_MSCryptImpl::getCryptoSlot() { + return m_hKeyStore ; +} + +void SecurityEnvironment_MSCryptImpl::setCryptoSlot( HCERTSTORE aSlot) { + if( m_hKeyStore != nullptr ) { + CertCloseStore( m_hKeyStore, CERT_CLOSE_STORE_FORCE_FLAG ) ; + m_hKeyStore = nullptr ; + } + + if( aSlot != nullptr ) { + m_hKeyStore = CertDuplicateStore( aSlot ) ; + } +} + +HCERTSTORE SecurityEnvironment_MSCryptImpl::getCertDb() { + return m_hCertStore ; +} + +void SecurityEnvironment_MSCryptImpl::setCertDb( HCERTSTORE aCertDb ) { + if( m_hCertStore != nullptr ) { + CertCloseStore( m_hCertStore, CERT_CLOSE_STORE_FORCE_FLAG ) ; + m_hCertStore = nullptr ; + } + + if( aCertDb != nullptr ) { + m_hCertStore = CertDuplicateStore( aCertDb ) ; + } +} + +#ifdef SAL_LOG_INFO + +// Based on sample code from MSDN + +static OUString get_system_name(const void *pvSystemStore, + DWORD dwFlags) +{ + LPCWSTR ppwszSystemName; + if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG) + { + _CERT_SYSTEM_STORE_RELOCATE_PARA const * pRelocatePara; + pRelocatePara = static_cast<_CERT_SYSTEM_STORE_RELOCATE_PARA const *>(pvSystemStore); + ppwszSystemName = pRelocatePara->pwszSystemStore; + } + else + { + ppwszSystemName = static_cast(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 xcert ; + std::vector< rtl::Reference > 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 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(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(malloc( cryptSerialNumber.cbData)); + if (!cryptSerialNumber.pbData) + { + free( certInfo.Issuer.pbData ) ; + throw uno::RuntimeException() ; + } + for( i = 0; i < cryptSerialNumber.cbData; i ++ ) + cryptSerialNumber.pbData[i] = serialNumber[ cryptSerialNumber.cbData - i - 1 ] ; + + certInfo.SerialNumber.cbData = cryptSerialNumber.cbData ; + certInfo.SerialNumber.pbData = cryptSerialNumber.pbData ; + + // Get the Cert from all store. + for( i = 0 ; i < 6 ; i ++ ) + { + switch(i) + { + case 0: + if(m_hKeyStore == nullptr) continue ; + hCertStore = m_hKeyStore ; + break; + case 1: + if(m_hCertStore == nullptr) continue ; + hCertStore = m_hCertStore ; + break; + case 2: + hCertStore = CertOpenSystemStoreW( 0, L"MY" ) ; + if(hCertStore == nullptr || !m_bEnableDefault) continue ; + break; + case 3: + hCertStore = CertOpenSystemStoreW( 0, L"Root" ) ; + if(hCertStore == nullptr || !m_bEnableDefault) continue ; + break; + case 4: + hCertStore = CertOpenSystemStoreW( 0, L"Trust" ) ; + if(hCertStore == nullptr || !m_bEnableDefault) continue ; + break; + case 5: + hCertStore = CertOpenSystemStoreW( 0, L"CA" ) ; + if(hCertStore == nullptr || !m_bEnableDefault) continue ; + break; + default: + i=6; + continue; + } + +/******************************************************************************* + * This code reserved for remind us there are another way to find one cert by + * IssuerName&serialnumber. You can use the code to replaced the function + * CertFindCertificateInStore IF and ONLY IF you must find one special cert in + * certStore but can not be found by CertFindCertificateInStore , then , you + * should also change the same part in libxmlsec/.../src/mscrypto/x509vfy.c#875. + * By Chandler Peng(chandler.peng@sun.com) + *****/ +/******************************************************************************* + pCertContext = NULL ; + found = 0; + do{ + // 1. enum the certs has same string in the issuer string. + pCertContext = CertEnumCertificatesInStore( hCertStore , pCertContext ) ; + if( pCertContext != NULL ) + { + // 2. check the cert's issuer name . + char* issuer = NULL ; + DWORD cbIssuer = 0 ; + + cbIssuer = CertNameToStr( + X509_ASN_ENCODING | PKCS_7_ASN_ENCODING , + &( pCertContext->pCertInfo->Issuer ), + CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG , + NULL, 0 + ) ; + + if( cbIssuer == 0 ) continue ; // discard this cert; + + issuer = (char *)malloc( cbIssuer ) ; + if( issuer == NULL ) // discard this cert; + { + free( cryptSerialNumber.pbData) ; + free( certInfo.Issuer.pbData ) ; + CertFreeCertificateContext( pCertContext ) ; + if(i != 0 && i != 1) CertCloseStore( hCertStore, CERT_CLOSE_STORE_CHECK_FLAG ) ; + throw RuntimeException() ; + } + + cbIssuer = CertNameToStr( + X509_ASN_ENCODING | PKCS_7_ASN_ENCODING , + &( pCertContext->pCertInfo->Issuer ), + CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG , + issuer, cbIssuer + ) ; + + if( cbIssuer <= 0 ) + { + free( issuer ) ; + continue ;// discard this cert; + } + + if(strncmp(pszName , issuer , cbIssuer) != 0) + { + free( issuer ) ; + continue ;// discard this cert; + } + free( issuer ) ; + + // 3. check the serial number. + if( memcmp( cryptSerialNumber.pbData , pCertContext->pCertInfo->SerialNumber.pbData , cryptSerialNumber.cbData ) != 0 ) + { + continue ;// discard this cert; + } + + // 4. confirm and break; + found = 1; + break ; + } + + }while(pCertContext); + + if(i != 0 && i != 1) CertCloseStore( hCertStore, CERT_CLOSE_STORE_CHECK_FLAG ) ; + if( found != 0 ) break; // Found the certificate. +********************************************************************************/ + + pCertContext = CertFindCertificateInStore( + hCertStore, + X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, + 0, + CERT_FIND_SUBJECT_CERT, + &certInfo, + nullptr + ) ; + + if(i != 0 && i != 1) CertCloseStore( hCertStore, CERT_CLOSE_STORE_CHECK_FLAG ) ; + if( pCertContext != nullptr ) break ; // Found the certificate. + + } + + free(cryptSerialNumber.pbData); + free(certInfo.Issuer.pbData); + + if( pCertContext != nullptr ) { + xcert = MswcryCertContextToXCert(pCertContext); + CertFreeCertificateContext(pCertContext); + } + + return xcert ; +} + +uno::Reference< XCertificate > SecurityEnvironment_MSCryptImpl::getCertificate( const OUString& issuerName, const OUString& serialNumber ) { + uno::Sequence< sal_Int8 > serial = xmlsecurity::numericStringToBigInteger( serialNumber ) ; + return getCertificate( issuerName, serial ) ; +} + +uno::Sequence< uno::Reference < XCertificate > > SecurityEnvironment_MSCryptImpl::buildCertificatePath( const uno::Reference< XCertificate >& begin ) { + PCCERT_CHAIN_CONTEXT pChainContext ; + PCCERT_CONTEXT pCertContext ; + + CERT_ENHKEY_USAGE enhKeyUsage ; + CERT_USAGE_MATCH certUsage ; + CERT_CHAIN_PARA chainPara ; + + enhKeyUsage.cUsageIdentifier = 0 ; + enhKeyUsage.rgpszUsageIdentifier = nullptr ; + certUsage.dwType = USAGE_MATCH_TYPE_AND ; + certUsage.Usage = enhKeyUsage ; + chainPara.cbSize = sizeof( CERT_CHAIN_PARA ) ; + chainPara.RequestedUsage = certUsage ; + + const auto* xcert = dynamic_cast(begin.get()); + if( xcert == nullptr ) { + throw uno::RuntimeException() ; + } + + pCertContext = xcert->getMswcryCert() ; + + pChainContext = nullptr ; + + bool bChain = false; + if( pCertContext != nullptr ) + { + HCERTSTORE hAdditionalStore = nullptr; + HCERTSTORE hCollectionStore = nullptr; + if (m_hCertStore && m_hKeyStore) + { + //Merge m_hCertStore and m_hKeyStore into one store. + hCollectionStore = CertOpenStore( + CERT_STORE_PROV_COLLECTION , + 0 , + 0 , + 0 , + nullptr + ) ; + if (hCollectionStore != nullptr) + { + CertAddStoreToCollection ( + hCollectionStore , + m_hCertStore , + CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG , + 0) ; + CertAddStoreToCollection ( + hCollectionStore , + m_hKeyStore, + CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG , + 0) ; + hAdditionalStore = hCollectionStore; + } + + } + + //if the merge of both stores failed then we add only m_hCertStore + if (hAdditionalStore == nullptr && m_hCertStore) + hAdditionalStore = m_hCertStore; + else if (hAdditionalStore == nullptr && m_hKeyStore) + hAdditionalStore = m_hKeyStore; + else + hAdditionalStore = nullptr; + + //CertGetCertificateChain searches by default in MY, CA, ROOT and TRUST + bChain = CertGetCertificateChain( + nullptr , + pCertContext , + nullptr , //use current system time + hAdditionalStore, + &chainPara , + CERT_CHAIN_REVOCATION_CHECK_CHAIN | CERT_CHAIN_TIMESTAMP_TIME , + nullptr , + &pChainContext); + if (!bChain) + pChainContext = nullptr; + + //Close the additional store + CertCloseStore(hCollectionStore, CERT_CLOSE_STORE_CHECK_FLAG); + } + + if(bChain && pChainContext != nullptr && pChainContext->cChain > 0 ) + { + PCCERT_CONTEXT pCertInChain ; + PCERT_SIMPLE_CHAIN pCertChain ; + rtl::Reference 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 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(oscert.getStr()), static_cast(oscert.getLength()) ) ; + xmlSecSize certSize; + int nRet = xmlSecBase64Decode_ex( chCert, reinterpret_cast(chCert), xmlStrlen( chCert ), &certSize ) ; + if (nRet < 0 || certSize == 0) + { + xmlFree(chCert); + return nullptr; + } + + uno::Sequence rawCert(comphelper::arrayToSequence(chCert, certSize)); + + xmlFree( chCert ) ; + + return createCertificateFromRaw( rawCert ) ; +} + +static HCERTSTORE getCertStoreForIntermediatCerts( + const uno::Sequence< uno::Reference< css::security::XCertificate > >& seqCerts) +{ + HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, 0, nullptr); + if (store == nullptr) + return nullptr; + + for (int i = 0; i < seqCerts.getLength(); i++) + { + SAL_INFO("xmlsecurity.xmlsec", "Added temporary certificate: " << seqCerts[i]->getSubjectName()); + + uno::Sequence data = seqCerts[i]->getEncoded(); + PCCERT_CONTEXT cert = CertCreateCertificateContext( + X509_ASN_ENCODING, reinterpret_cast(&data[0]), data.getLength()); + //Adding the certificate creates a copy and not just increases the ref count + //Therefore we free later the certificate that we now add + CertAddCertificateContextToStore(store, cert, CERT_STORE_ADD_ALWAYS, nullptr); + CertFreeCertificateContext(cert); + } + return store; +} + +static bool CheckUnitTestStore(PCCERT_CHAIN_CONTEXT const pChainContext, DWORD ignoreFlags) +{ + bool ret = false; + static char const*const pVar = getenv("LIBO_TEST_CRYPTOAPI_PKCS7"); + if (!pVar) + { + return ret; + } + if (pChainContext->cChain == 0) + { + return ret; + } + PCERT_SIMPLE_CHAIN pSimpleChain = pChainContext->rgpChain[0]; + // check if untrusted root is the only problem + if (pSimpleChain->TrustStatus.dwErrorStatus & ~(CERT_TRUST_IS_UNTRUSTED_ROOT | ignoreFlags)) + { + return ret; + } + + // leak this store, re-opening is a waste of time in tests + static HCERTSTORE const hExtra = CertOpenStore( + CERT_STORE_PROV_FILENAME_A, + PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, + 0, + CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG, + OString(OString::Concat(pVar) + "/test.p7b").getStr()); + assert(hExtra != nullptr); + if (pSimpleChain->cElement < 1) + { + SAL_WARN("xmlsecurity.xmlsec", "unexpected empty chain"); + return ret; + } + PCCERT_CONTEXT const pRoot(pSimpleChain->rgpElement[pSimpleChain->cElement-1]->pCertContext); + PCCERT_CONTEXT const pIssuerCert = CertFindCertificateInStore( + hExtra, + PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, + 0, + CERT_FIND_SUBJECT_NAME, + &pRoot->pCertInfo->Subject, + nullptr); + if (pIssuerCert) + { + // check that it signed itself + DWORD flags = CERT_STORE_SIGNATURE_FLAG; + bool result = CertVerifySubjectCertificateContext(pRoot, pIssuerCert, &flags); + if (result && flags == 0) + { + ret = true; + } + } + CertFreeCertificateContext(pIssuerCert); + return ret; +} + +//We return only valid or invalid, as long as the API documentation expresses +//explicitly that all validation steps are carried out even if one or several +//errors occur. See also +//http://wiki.openoffice.org/wiki/Certificate_Path_Validation#Validation_status +sal_Int32 SecurityEnvironment_MSCryptImpl::verifyCertificate( + const uno::Reference< css::security::XCertificate >& aCert, + const uno::Sequence< uno::Reference< css::security::XCertificate > >& seqCerts) +{ + sal_Int32 validity = css::security::CertificateValidity::INVALID; + PCCERT_CHAIN_CONTEXT pChainContext = nullptr; + PCCERT_CONTEXT pCertContext = nullptr; + + SAL_INFO("xmlsecurity.xmlsec", "Start verification of certificate: " << aCert->getSubjectName()); + + const auto* xcert = dynamic_cast(aCert.get()); + if( xcert == nullptr ) { + throw uno::RuntimeException() ; + } + + pCertContext = xcert->getMswcryCert() ; + + CERT_ENHKEY_USAGE enhKeyUsage ; + CERT_USAGE_MATCH certUsage ; + CERT_CHAIN_PARA chainPara = {}; + + //Prepare parameter for CertGetCertificateChain + enhKeyUsage.cUsageIdentifier = 0 ; + enhKeyUsage.rgpszUsageIdentifier = nullptr ; + certUsage.dwType = USAGE_MATCH_TYPE_AND ; + certUsage.Usage = enhKeyUsage ; + chainPara.cbSize = sizeof( CERT_CHAIN_PARA ) ; + chainPara.RequestedUsage = certUsage ; + + + HCERTSTORE hCollectionStore = nullptr; + HCERTSTORE hIntermediateCertsStore = nullptr; + bool bChain = false; + if( pCertContext != nullptr ) + { + hIntermediateCertsStore = + getCertStoreForIntermediatCerts(seqCerts); + + //Merge m_hCertStore and m_hKeyStore and the store of the intermediate + //certificates into one store. + hCollectionStore = CertOpenStore( + CERT_STORE_PROV_COLLECTION , + 0 , + 0 , + 0 , + nullptr + ) ; + if (hCollectionStore != nullptr) + { + CertAddStoreToCollection ( + hCollectionStore , + m_hCertStore , + CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG , + 0) ; + CertAddStoreToCollection ( + hCollectionStore , + m_hKeyStore, + CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG , + 0) ; + CertAddStoreToCollection ( + hCollectionStore, + hIntermediateCertsStore, + CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, + 0); + + } + + //CertGetCertificateChain searches by default in MY, CA, ROOT and TRUST + //We do not check revocation of the root. In most cases there are none. + //Then we would get CERT_TRUST_REVOCATION_STATUS_UNKNOWN + SAL_INFO("xmlsecurity.xmlsec", "Verifying cert using revocation information."); + bChain = CertGetCertificateChain( + nullptr , + pCertContext , + nullptr , //use current system time + hCollectionStore, + &chainPara , + CERT_CHAIN_REVOCATION_CHECK_CHAIN | CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT, + nullptr , + &pChainContext); + + if (bChain && pChainContext->cChain > 0) + { + SAL_INFO("xmlsecurity.xmlsec", "Overall error status (all chains):"); + traceTrustStatus(pChainContext->TrustStatus.dwErrorStatus); + //highest quality chains come first + PCERT_SIMPLE_CHAIN pSimpleChain = pChainContext->rgpChain[0]; + SAL_INFO("xmlsecurity.xmlsec", "Error status of first chain:"); + traceTrustStatus(pSimpleChain->TrustStatus.dwErrorStatus); + + //CERT_TRUST_REVOCATION_STATUS_UNKNOWN is also set if a certificate + //has no AIA(OCSP) or CRLDP extension and there is no CRL locally installed. + DWORD revocationFlags = CERT_TRUST_REVOCATION_STATUS_UNKNOWN | + CERT_TRUST_IS_OFFLINE_REVOCATION; + DWORD otherErrorsMask = ~revocationFlags; + if (!(pSimpleChain->TrustStatus.dwErrorStatus & otherErrorsMask) + || CheckUnitTestStore(pChainContext, revocationFlags)) + + { + //No errors except maybe those caused by missing revocation information + //Check if there are errors + if ( pSimpleChain->TrustStatus.dwErrorStatus & revocationFlags) + { + //No revocation information. Because MSDN documentation is not + //clear about if all other tests are performed if an error occurs, + //we test again, without requiring revocation checking. + CertFreeCertificateChain(pChainContext); + pChainContext = nullptr; + SAL_INFO("xmlsecurity.xmlsec", "Checking again but without requiring revocation information."); + bChain = CertGetCertificateChain( + nullptr , + pCertContext , + nullptr , //use current system time + hCollectionStore, + &chainPara , + 0, + nullptr , + &pChainContext); + if (bChain + && pChainContext->cChain > 0 + && pChainContext->rgpChain[0]->TrustStatus.dwErrorStatus == CERT_TRUST_NO_ERROR) + { + SAL_INFO("xmlsecurity.xmlsec", "Certificate is valid."); + validity = css::security::CertificateValidity::VALID; + } + else if (CheckUnitTestStore(pChainContext, 0)) + { + SAL_INFO("xmlsecurity.xmlsec", "root certificate found in extra test store"); + validity = css::security::CertificateValidity::VALID; + } + else + { + SAL_INFO("xmlsecurity.xmlsec", "Certificate is invalid."); + } + } + else + { + //valid and revocation information available + SAL_INFO("xmlsecurity.xmlsec", "Certificate is valid."); + validity = css::security::CertificateValidity::VALID; + } + } + else + { + //invalid + SAL_INFO("xmlsecurity.xmlsec", "Certificate is invalid."); + validity = css::security::CertificateValidity::INVALID ; + } + } + else + { + SAL_INFO("xmlsecurity.xmlsec", "CertGetCertificateChain failed."); + } + } + + if (pChainContext) + { + CertFreeCertificateChain(pChainContext); + pChainContext = nullptr; + } + + //Close the additional store, do not destroy the contained certs + CertCloseStore(hCollectionStore, CERT_CLOSE_STORE_CHECK_FLAG); + //Close the temporary store containing the intermediate certificates and make + //sure all certificates are deleted. + CertCloseStore(hIntermediateCertsStore, CERT_CLOSE_STORE_CHECK_FLAG); + + return validity ; +} + +sal_Int32 SecurityEnvironment_MSCryptImpl::getCertificateCharacters( const css::uno::Reference< css::security::XCertificate >& aCert ) { + sal_Int32 characters ; + PCCERT_CONTEXT pCertContext ; + + const auto* xcert = dynamic_cast(aCert.get()); + if( xcert == nullptr ) { + throw uno::RuntimeException() ; + } + + pCertContext = xcert->getMswcryCert() ; + + characters = 0x00000000 ; + + //Firstly, make sentence whether or not the cert is self-signed. + if( CertCompareCertificateName( X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &(pCertContext->pCertInfo->Subject), &(pCertContext->pCertInfo->Issuer) ) ) { + characters |= css::security::CertificateCharacters::SELF_SIGNED ; + } else { + characters &= ~ css::security::CertificateCharacters::SELF_SIGNED ; + } + + //Secondly, make sentence whether or not the cert has a private key. + { + BOOL fCallerFreeProv ; + DWORD dwKeySpec ; + NCRYPT_KEY_HANDLE hKey = 0; + DWORD dwFlags = CRYPT_ACQUIRE_ONLY_NCRYPT_KEY_FLAG; + HCRYPTPROV_OR_NCRYPT_KEY_HANDLE* phCryptProvOrNCryptKey = &hKey; + if( CryptAcquireCertificatePrivateKey( pCertContext , + dwFlags, + nullptr , + phCryptProvOrNCryptKey, + &dwKeySpec, + &fCallerFreeProv ) + ) { + characters |= css::security::CertificateCharacters::HAS_PRIVATE_KEY ; + + if (hKey && fCallerFreeProv) + NCryptFreeObject(hKey); + } else { + characters &= ~ css::security::CertificateCharacters::HAS_PRIVATE_KEY ; + } + } + return characters ; +} + +void SecurityEnvironment_MSCryptImpl::enableDefaultCrypt( bool enable ) { + m_bEnableDefault = enable ; +} + +bool SecurityEnvironment_MSCryptImpl::defaultEnabled() { + return m_bEnableDefault ; +} + +static rtl::Reference MswcryCertContextToXCert( PCCERT_CONTEXT cert ) +{ + rtl::Reference 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 const& /*rSeq*/) +{ + return cppu::acquire(new SecurityEnvironment_MSCryptImpl(pCtx)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.hxx b/xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.hxx new file mode 100644 index 0000000000..5867b2b462 --- /dev/null +++ b/xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.hxx @@ -0,0 +1,168 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#if !defined WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include + + +class SecurityEnvironment_MSCryptImpl : public ::cppu::WeakImplHelper< + css::xml::crypto::XSecurityEnvironment , + css::lang::XServiceInfo > +{ + private: + //crypto provider and key container + HCRYPTPROV m_hProv ; + LPCTSTR m_pszContainer ; + + //Key store + HCERTSTORE m_hKeyStore ; + + //Certificate store + HCERTSTORE m_hCertStore ; + + // i120675, save the store handles + HCERTSTORE m_hMySystemStore; + HCERTSTORE m_hRootSystemStore; + HCERTSTORE m_hTrustSystemStore; + HCERTSTORE m_hCaSystemStore; + + //Enable default system cryptography setting + bool m_bEnableDefault ; + + //Service manager + css::uno::Reference< css::lang::XMultiServiceFactory > m_xServiceManager ; + + public: + explicit SecurityEnvironment_MSCryptImpl( const css::uno::Reference< css::uno::XComponentContext >& xContext ) ; + virtual ~SecurityEnvironment_MSCryptImpl() override; + + //Methods from XSecurityEnvironment + virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificate > > SAL_CALL getPersonalCertificates() override; + virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificate > > SAL_CALL getAllCertificates() override + { return css::uno::Sequence< css::uno::Reference< css::security::XCertificate > >(); } + + virtual css::uno::Reference< css::security::XCertificate > SAL_CALL getCertificate( + const OUString& issuerName, + const css::uno::Sequence< sal_Int8 >& serialNumber ) override; + + /// @throws css::uno::SecurityException + /// @throws css::uno::RuntimeException + virtual css::uno::Reference< css::security::XCertificate > getCertificate( + const OUString& issuerName, + const OUString& serialNumber ) ; + + virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificate > > SAL_CALL buildCertificatePath( + const css::uno::Reference< css::security::XCertificate >& beginCert ) override; + + virtual css::uno::Reference< css::security::XCertificate > SAL_CALL createCertificateFromRaw( + const css::uno::Sequence< sal_Int8 >& rawCertificate ) override; + + virtual css::uno::Reference< css::security::XCertificate > SAL_CALL createCertificateFromAscii( + const OUString& asciiCertificate ) override; + + virtual ::sal_Int32 SAL_CALL verifyCertificate( + const css::uno::Reference< css::security::XCertificate >& xCert, + const css::uno::Sequence< css::uno::Reference< + css::security::XCertificate > >& intermediateCertificates) override; + + virtual ::sal_Int32 SAL_CALL getCertificateCharacters( + const css::uno::Reference< css::security::XCertificate >& xCert ) override; + + virtual OUString SAL_CALL getSecurityEnvironmentInformation( ) override; + + + //Methods from XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + + virtual sal_Bool SAL_CALL supportsService( + const OUString& ServiceName + ) override; + + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; + + /// @throws css::uno::Exception + /// @throws css::uno::RuntimeException + HCRYPTPROV getCryptoProvider() ; + /// @throws css::uno::Exception + /// @throws css::uno::RuntimeException + void setCryptoProvider( HCRYPTPROV aProv ) ; + + /// @throws css::uno::Exception + /// @throws css::uno::RuntimeException + LPCTSTR getKeyContainer() ; + /// @throws css::uno::Exception + /// @throws css::uno::RuntimeException + void setKeyContainer( LPCTSTR aKeyContainer ) ; + + /// @throws css::uno::Exception + /// @throws css::uno::RuntimeException + HCERTSTORE getCryptoSlot() ; + /// @throws css::uno::Exception + /// @throws css::uno::RuntimeException + void setCryptoSlot( HCERTSTORE aKeyStore ) ; + + /// @throws css::uno::Exception + /// @throws css::uno::RuntimeException + HCERTSTORE getCertDb() ; + /// @throws css::uno::Exception + /// @throws css::uno::RuntimeException + void setCertDb( HCERTSTORE aCertDb ) ; + + /// @throws css::uno::Exception + /// @throws css::uno::RuntimeException + void enableDefaultCrypt( bool enable ) ; + /// @throws css::uno::Exception + /// @throws css::uno::RuntimeException + bool defaultEnabled() ; + + /// @throws css::uno::Exception + /// @throws css::uno::RuntimeException + xmlSecKeysMngrPtr createKeysManager() ; + + /// @throws css::uno::Exception + /// @throws css::uno::RuntimeException + static void destroyKeysManager(xmlSecKeysMngrPtr pKeysMngr) ; +} ; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/mscrypt/seinitializer_mscryptimpl.cxx b/xmlsecurity/source/xmlsec/mscrypt/seinitializer_mscryptimpl.cxx new file mode 100644 index 0000000000..99381e5e25 --- /dev/null +++ b/xmlsecurity/source/xmlsec/mscrypt/seinitializer_mscryptimpl.cxx @@ -0,0 +1,172 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include + +#include "seinitializer_mscryptimpl.hxx" + +#include "securityenvironment_mscryptimpl.hxx" + +#include +#include +#include +#include +#include +#include + +using namespace com::sun::star; +namespace cssl = com::sun::star::lang; +namespace cssxc = com::sun::star::xml::crypto; + +SEInitializer_MSCryptImpl::SEInitializer_MSCryptImpl( + const uno::Reference< uno::XComponentContext > &rxContext) + :mxContext( rxContext ) +{ +} + +SEInitializer_MSCryptImpl::~SEInitializer_MSCryptImpl() +{ +} + +/* XSEInitializer */ +uno::Reference< cssxc::XXMLSecurityContext > SAL_CALL + SEInitializer_MSCryptImpl::createSecurityContext( + const OUString& sCertDB ) +{ + const char* n_pCertStore ; + HCERTSTORE n_hStoreHandle ; + OString sCertDir; + + //Initialize the crypto engine + if( sCertDB.getLength() > 0 ) + { + sCertDir = OUStringToOString(sCertDB, RTL_TEXTENCODING_ASCII_US); + n_pCertStore = sCertDir.getStr(); + n_hStoreHandle = CertOpenSystemStoreW( 0, o3tl::toW(sCertDB.getStr())) ; + if( n_hStoreHandle == nullptr ) + { + return nullptr; + } + } + else + { + n_pCertStore = nullptr ; + n_hStoreHandle = nullptr ; + } + + xmlSecMSCngAppInit(n_pCertStore); + + try { + /* Build Security Environment */ + uno::Reference< cssxc::XSecurityEnvironment > xSecEnv = cssxc::SecurityEnvironment::create( mxContext ); + + /* Setup key slot and certDb */ + SecurityEnvironment_MSCryptImpl* pSecEnv = dynamic_cast(xSecEnv.get()); + if( pSecEnv == nullptr ) + { + if( n_hStoreHandle != nullptr ) + { + CertCloseStore( n_hStoreHandle, CERT_CLOSE_STORE_FORCE_FLAG ) ; + } + + xmlSecMSCngAppShutdown(); + return nullptr; + } + + if( n_hStoreHandle != nullptr ) + { + pSecEnv->setCryptoSlot( n_hStoreHandle ) ; + pSecEnv->setCertDb( n_hStoreHandle ) ; + } + else + { + pSecEnv->enableDefaultCrypt( true ) ; + } + + /* Build XML Security Context */ + uno::Reference< cssxc::XXMLSecurityContext > xSecCtx = cssxc::XMLSecurityContext::create( mxContext ); + + xSecCtx->setDefaultSecurityEnvironmentIndex(xSecCtx->addSecurityEnvironment( xSecEnv )) ; + return xSecCtx; + } + catch( uno::Exception& ) + { + if( n_hStoreHandle != nullptr ) + { + CertCloseStore( n_hStoreHandle, CERT_CLOSE_STORE_FORCE_FLAG ) ; + } + + xmlSecMSCngAppShutdown(); + return nullptr; + } +} + +void SAL_CALL SEInitializer_MSCryptImpl::freeSecurityContext( const uno::Reference< cssxc::XXMLSecurityContext >&) +{ + /* + uno::Reference< cssxc::XSecurityEnvironment > xSecEnv + = securityContext->getSecurityEnvironment(); + + if( xSecEnv.is() ) + { + uno::Reference< cssl::XUnoTunnel > xEnvTunnel( xSecEnv , uno::UNO_QUERY ) ; + if (auto pSecEnv = comphelper::getFromUnoTunnel(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 const& /*rSeq*/) +{ + return cppu::acquire(new SEInitializer_MSCryptImpl(pCtx)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/mscrypt/seinitializer_mscryptimpl.hxx b/xmlsecurity/source/xmlsec/mscrypt/seinitializer_mscryptimpl.hxx new file mode 100644 index 0000000000..182ba5e5af --- /dev/null +++ b/xmlsecurity/source/xmlsec/mscrypt/seinitializer_mscryptimpl.hxx @@ -0,0 +1,71 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include + +class SEInitializer_MSCryptImpl : public cppu::WeakImplHelper +< + css::xml::crypto::XSEInitializer, + css::lang::XServiceInfo +> +/****** SEInitializer_MSCryptImpl.hxx/CLASS SEInitializer_MSCryptImpl *********** + * + * NAME + * SEInitializer_MSCryptImpl -- Class to initialize a Security Context + * instance + * + * FUNCTION + * Use this class to initialize a XmlSec based Security Context + * instance. After this instance is used up, use this class to free this + * instance. + ******************************************************************************/ +{ +private: + css::uno::Reference< css::uno::XComponentContext > mxContext; + +public: + explicit SEInitializer_MSCryptImpl(const css::uno::Reference< css::uno::XComponentContext > &rxContext); + virtual ~SEInitializer_MSCryptImpl() override; + + /* XSEInitializer */ + virtual css::uno::Reference< css::xml::crypto::XXMLSecurityContext > + SAL_CALL createSecurityContext( const OUString& certDB ) override; + + virtual void SAL_CALL freeSecurityContext( const css::uno::Reference< + css::xml::crypto::XXMLSecurityContext >& securityContext ) override; + + /* XServiceInfo */ + virtual OUString SAL_CALL getImplementationName( ) override; + + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx b/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx new file mode 100644 index 0000000000..bd4ef701e6 --- /dev/null +++ b/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx @@ -0,0 +1,783 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include +#include +#include +#include +#include +#include "x509certificate_mscryptimpl.hxx" +#include +#include +#include "sanextension_mscryptimpl.hxx" + +#include "oid.hxx" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace com::sun::star; +using namespace ::com::sun::star::uno ; +using namespace ::com::sun::star::security ; + +using ::com::sun::star::security::XCertificate ; +using ::com::sun::star::util::DateTime ; + +/*Returns the index within rRawString where sTypeName starts and where it ends. + The starting index is pair.first. The ending index in pair.second points + one char after the last character of the type. + sTypeName can be + "S" or "CN" (without ""). Do not use spaces at the beginning of the type name. + If the type name is not found then pair.first and pair.second are -1. +*/ +static std::pair< sal_Int32, sal_Int32 > +findTypeInDN(const OUString& rRawString, std::u16string_view sTypeName) +{ + std::pair< sal_Int32, sal_Int32 > retVal; + bool bInEscape = false; + bool bInValue = false; + bool bFound = false; + sal_Int32 nTypeNameStart = 0; + sal_Int32 length = rRawString.getLength(); + + for (sal_Int32 i = 0; i < length; i++) + { + sal_Unicode c = rRawString[i]; + + if (c == '=') + { + if (! bInValue) + { + std::u16string_view sType = rRawString.subView(nTypeNameStart, i - nTypeNameStart); + sType = o3tl::trim(sType); + if (o3tl::equalsIgnoreAsciiCase(sType, sTypeName)) + { + bFound = true; + break; + } + } + } + else if (c == '"') + { + if (!bInEscape) + { + //If this is the quote is the first of the couple which enclose the + //whole value, because the value contains special characters + //then we just drop it. That is, this character must be followed by + //a character which is not '"'. + if ( i + 1 < length && rRawString[i+1] == '"') + bInEscape = true; + else + bInValue = !bInValue; //value is enclosed in " " + } + else + { + //This quote is escaped by a preceding quote and therefore is + //part of the value + bInEscape = false; + } + } + else if (c == ',' || c == '+') + { + //The comma separate the attribute value pairs. + //If the comma is not part of a value (the value would then be enclosed in '"'), + //then we have reached the end of the value + if (!bInValue) + { + //The next char is the start of the new type + nTypeNameStart = i + 1; + } + } + } + + //Found the Type Name, but there can still be spaces after the last comma + //and the beginning of the type. + if (bFound) + { + while (true) + { + sal_Unicode c = rRawString[nTypeNameStart]; + if (c != ' ' && c != '\t') + //found + break; + nTypeNameStart ++; + } + // search end (one after last letter) + sal_Int32 nTypeNameEnd = nTypeNameStart; + nTypeNameEnd++; + while (true) + { + sal_Unicode c = rRawString[nTypeNameEnd]; + if (c == ' ' || c == '\t' || c == '=') + break; + nTypeNameEnd++; + } + retVal = std::make_pair(nTypeNameStart, nTypeNameEnd); + } + else + { + retVal = std::make_pair(-1, -1); + } + return retVal; +} + + +/* + MS Crypto uses the 'S' tag (equal to the 'ST' tag in NSS), but the NSS can't recognise + it, so the 'S' tag should be changed to 'ST' tag. However I am not sure if this is necessary + anymore, because we provide always the signers certificate when signing. So libmlsec can find + the private key based on the provided certificate (X509Certificate element) and does not need + the issuer name (X509IssuerName element). The issuer name in the xml signature has also no + effect for the signature nor the certificate validation. + In many RFCs, for example 4519, on speaks of 'ST'. However, the certificate does not contain + strings for type names. Instead it uses OIDs. + */ + +static OUString replaceTagSWithTagST(OUString const & oldDN) +{ + std::pair 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(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(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(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 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(new SanExtensionImpl()); + else + xExtn = new CertificateExtension_XmlSecImpl; + + xExtn->setCertExtn( pExtn->Value.pbData, pExtn->Value.cbData, reinterpret_cast(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 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(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(&rawCert[0]), rawCert.getLength() ) ; + } +} + +static OUString findOIDDescription(char const *oid) +{ + OUString ouOID = OUString::createFromAscii( oid ); + for (int i=0; i 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 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::vectorbuffer(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(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 SAL_CALL X509Certificate_MSCryptImpl::getSupportedServiceNames() +{ + return { OUString() }; +} + +namespace xmlsecurity { + +// based on some guesswork and: +// https://datatracker.ietf.org/doc/html/rfc1485 +// https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-certnametostra#CERT_X500_NAME_STR +// the main problem appears to be that in values NSS uses \ escapes but CryptoAPI requires " quotes around value +static OUString CompatDNNSS(OUString const& rDN) +{ + OUStringBuffer buf(rDN.getLength()); + enum { DEFAULT, INVALUE, INQUOTE } state(DEFAULT); + for (sal_Int32 i = 0; i < rDN.getLength(); ++i) + { + if (state == DEFAULT) + { + buf.append(rDN[i]); + if (rDN[i] == '=') + { + if (rDN.getLength() == i+1) + { + break; // invalid? + } + else + { + buf.append('"'); + state = INVALUE; + } + } + } + else if (state == INVALUE) + { + if (rDN[i] == '+' || rDN[i] == ',' || rDN[i] == ';') + { + buf.append("\"" + OUStringChar(rDN[i])); + state = DEFAULT; + } + else if (rDN[i] == '\\') + { + if (rDN.getLength() == i+1) + { + break; // invalid? + } + if (rDN[i+1] == '"') + { + buf.append('"'); + } + buf.append(rDN[i+1]); + ++i; + } + else + { + buf.append(rDN[i]); + } + if (i+1 == rDN.getLength()) + { + buf.append('"'); + state = DEFAULT; + } + } + } + return buf.makeStringAndClear(); +} + +static bool EncodeDistinguishedName(std::u16string_view const rName, CERT_NAME_BLOB & rBlob) +{ + LPCWSTR pszError; + if (!CertStrToNameW(X509_ASN_ENCODING, + reinterpret_cast(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(rName.data()), CERT_X500_NAME_STR, + nullptr, rBlob.pbData, &rBlob.cbData, &pszError)) + { + SAL_INFO("xmlsecurity.xmlsec", "CertStrToNameW failed: " << WindowsErrorString(GetLastError()) << "; " << OUString(o3tl::toU(pszError))); + return false; + } + return true; +} + +bool EqualDistinguishedNames( + std::u16string_view const rName1, std::u16string_view const rName2, + EqualMode const eMode) +{ + if (eMode == COMPAT_BOTH && !rName1.empty() && rName1 == rName2) + { // handle case where both need to be converted + return true; + } + CERT_NAME_BLOB blob1; + if (!EncodeDistinguishedName(rName1, blob1)) + { + return false; + } + CERT_NAME_BLOB blob2; + bool ret(false); + if (EncodeDistinguishedName(rName2, blob2)) + { + ret = CertCompareCertificateName(X509_ASN_ENCODING, + &blob1, &blob2) == TRUE; + delete[] blob2.pbData; + } + if (!ret && eMode == COMPAT_2ND) + { + CERT_NAME_BLOB blob2compat; + if (!EncodeDistinguishedName(CompatDNNSS(OUString(rName2)), blob2compat)) + { + delete[] blob1.pbData; + return false; + } + ret = CertCompareCertificateName(X509_ASN_ENCODING, + &blob1, &blob2compat) == TRUE; + delete[] blob2compat.pbData; + } + delete[] blob1.pbData; + return ret; +} + +} // namespace xmlsecurity + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.hxx b/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.hxx new file mode 100644 index 0000000000..ba02281794 --- /dev/null +++ b/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.hxx @@ -0,0 +1,91 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#if !defined WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class X509Certificate_MSCryptImpl : public ::cppu::WeakImplHelper< + css::security::XCertificate , + css::lang::XServiceInfo > , public xmlsecurity::Certificate +{ + private: + const CERT_CONTEXT* m_pCertContext ; + + public: + X509Certificate_MSCryptImpl() ; + virtual ~X509Certificate_MSCryptImpl() override; + + //Methods from XCertificate + virtual sal_Int16 SAL_CALL getVersion() override; + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSerialNumber() override; + virtual OUString SAL_CALL getIssuerName() override; + virtual OUString SAL_CALL getSubjectName() override; + virtual css::util::DateTime SAL_CALL getNotValidBefore() override; + virtual css::util::DateTime SAL_CALL getNotValidAfter() override; + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getIssuerUniqueID() override; + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSubjectUniqueID() override; + virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificateExtension > > SAL_CALL getExtensions() override; + virtual css::uno::Reference< css::security::XCertificateExtension > SAL_CALL findCertificateExtension( const css::uno::Sequence< sal_Int8 >& oid ) override; + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getEncoded() override; + virtual OUString SAL_CALL getSubjectPublicKeyAlgorithm() override; + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSubjectPublicKeyValue() override; + virtual OUString SAL_CALL getSignatureAlgorithm() override; + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSHA1Thumbprint() override; + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getMD5Thumbprint() override; + virtual css::security::CertificateKind SAL_CALL getCertificateKind() override; + + + virtual sal_Int32 SAL_CALL getCertificateUsage( ) override; + + /// @see xmlsecurity::Certificate::getSHA256Thumbprint(). + virtual css::uno::Sequence 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 SAL_CALL getSupportedServiceNames() override; +} ; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/mscrypt/xmlsecuritycontext_mscryptimpl.cxx b/xmlsecurity/source/xmlsec/mscrypt/xmlsecuritycontext_mscryptimpl.cxx new file mode 100644 index 0000000000..f024a39b47 --- /dev/null +++ b/xmlsecurity/source/xmlsec/mscrypt/xmlsecuritycontext_mscryptimpl.cxx @@ -0,0 +1,153 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include + +#include +#include "securityenvironment_mscryptimpl.hxx" + +#include +#include "akmngr.hxx" + +#include + +using namespace ::com::sun::star; +using namespace ::com::sun::star::lang ; + +using ::com::sun::star::xml::crypto::XSecurityEnvironment ; +using ::com::sun::star::xml::crypto::XXMLSecurityContext ; + +namespace { + +class XMLSecurityContext_MSCryptImpl : public ::cppu::WeakImplHelper< + css::xml::crypto::XXMLSecurityContext , + css::lang::XServiceInfo > +{ + private: + //xmlSecKeysMngrPtr m_pKeysMngr ; + css::uno::Reference< css::xml::crypto::XSecurityEnvironment > m_xSecurityEnvironment ; + + public: + XMLSecurityContext_MSCryptImpl(); + + //Methods from XXMLSecurityContext + virtual sal_Int32 SAL_CALL addSecurityEnvironment( + const css::uno::Reference< css::xml::crypto::XSecurityEnvironment >& aSecurityEnvironment + ) override; + + virtual ::sal_Int32 SAL_CALL getSecurityEnvironmentNumber( ) override; + + virtual css::uno::Reference< + css::xml::crypto::XSecurityEnvironment > SAL_CALL + getSecurityEnvironmentByIndex( ::sal_Int32 index ) override; + + virtual css::uno::Reference< + css::xml::crypto::XSecurityEnvironment > SAL_CALL + getSecurityEnvironment( ) override; + + virtual ::sal_Int32 SAL_CALL getDefaultSecurityEnvironmentIndex( ) override; + + virtual void SAL_CALL setDefaultSecurityEnvironmentIndex( sal_Int32 nDefaultEnvIndex ) override; + + + //Methods from XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + + virtual sal_Bool SAL_CALL supportsService( + const OUString& ServiceName + ) override; + + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; +}; + +} + +XMLSecurityContext_MSCryptImpl::XMLSecurityContext_MSCryptImpl() +{ +} + +sal_Int32 SAL_CALL XMLSecurityContext_MSCryptImpl::addSecurityEnvironment( + const css::uno::Reference< css::xml::crypto::XSecurityEnvironment >& aSecurityEnvironment) +{ + if( !aSecurityEnvironment.is() ) + { + throw uno::RuntimeException() ; + } + + m_xSecurityEnvironment = aSecurityEnvironment; + + return 0; +} + + +sal_Int32 SAL_CALL XMLSecurityContext_MSCryptImpl::getSecurityEnvironmentNumber( ) +{ + return 1; +} + +css::uno::Reference< css::xml::crypto::XSecurityEnvironment > SAL_CALL + XMLSecurityContext_MSCryptImpl::getSecurityEnvironmentByIndex( sal_Int32 index ) +{ + if (index != 0) + { + throw uno::RuntimeException() ; + } + return m_xSecurityEnvironment; +} + +css::uno::Reference< css::xml::crypto::XSecurityEnvironment > SAL_CALL + XMLSecurityContext_MSCryptImpl::getSecurityEnvironment( ) +{ + return m_xSecurityEnvironment; +} + +sal_Int32 SAL_CALL XMLSecurityContext_MSCryptImpl::getDefaultSecurityEnvironmentIndex( ) +{ + return 0; +} + +void SAL_CALL XMLSecurityContext_MSCryptImpl::setDefaultSecurityEnvironmentIndex( sal_Int32 /*nDefaultEnvIndex*/ ) +{ + //dummy +} + +/* XServiceInfo */ +OUString SAL_CALL XMLSecurityContext_MSCryptImpl::getImplementationName() { + return "com.sun.star.xml.crypto.XMLSecurityContext" ; +} + +/* XServiceInfo */ +sal_Bool SAL_CALL XMLSecurityContext_MSCryptImpl::supportsService( const OUString& serviceName) { + return cppu::supportsService(this, serviceName); +} + +/* XServiceInfo */ +uno::Sequence< OUString > SAL_CALL XMLSecurityContext_MSCryptImpl::getSupportedServiceNames() { + return { "com.sun.star.xml.crypto.XMLSecurityContext" }; +} + +extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface* +com_sun_star_xml_crypto_XMLSecurityContext_get_implementation( + uno::XComponentContext* /*pCtx*/, uno::Sequence const& /*rSeq*/) +{ + return cppu::acquire(new XMLSecurityContext_MSCryptImpl); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/mscrypt/xmlsignature_mscryptimpl.cxx b/xmlsecurity/source/xmlsec/mscrypt/xmlsignature_mscryptimpl.cxx new file mode 100644 index 0000000000..2a3709938a --- /dev/null +++ b/xmlsecurity/source/xmlsec/mscrypt/xmlsignature_mscryptimpl.cxx @@ -0,0 +1,305 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include + +#include + +#include +#include + +#include "securityenvironment_mscryptimpl.hxx" + +#include +#include +#include +#include +#include + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno ; +using namespace ::com::sun::star::lang ; + +using ::com::sun::star::xml::wrapper::XXMLElementWrapper ; +using ::com::sun::star::xml::crypto::XSecurityEnvironment ; +using ::com::sun::star::xml::crypto::XXMLSignature ; +using ::com::sun::star::xml::crypto::XXMLSignatureTemplate ; +using ::com::sun::star::xml::crypto::XXMLSecurityContext ; +using ::com::sun::star::xml::crypto::XUriBinding ; + +namespace { + +class XMLSignature_MSCryptImpl : public ::cppu::WeakImplHelper< + css::xml::crypto::XXMLSignature , + css::lang::XServiceInfo > +{ + public: + explicit XMLSignature_MSCryptImpl(); + + //Methods from XXMLSignature + virtual css::uno::Reference< css::xml::crypto::XXMLSignatureTemplate > SAL_CALL generate( + const css::uno::Reference< css::xml::crypto::XXMLSignatureTemplate >& aTemplate , + const css::uno::Reference< css::xml::crypto::XSecurityEnvironment >& aEnvironment + ) override; + + virtual css::uno::Reference< css::xml::crypto::XXMLSignatureTemplate > SAL_CALL validate( + const css::uno::Reference< css::xml::crypto::XXMLSignatureTemplate >& aTemplate , + const css::uno::Reference< css::xml::crypto::XXMLSecurityContext >& aContext + ) override; + + //Methods from XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + + virtual sal_Bool SAL_CALL supportsService( + const OUString& ServiceName + ) override; + + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; +} ; + +} + +XMLSignature_MSCryptImpl::XMLSignature_MSCryptImpl() { +} + +/* XXMLSignature */ +Reference< XXMLSignatureTemplate > +SAL_CALL XMLSignature_MSCryptImpl::generate( + const Reference< XXMLSignatureTemplate >& aTemplate , + const Reference< XSecurityEnvironment >& aEnvironment +) +{ + xmlSecKeysMngrPtr pMngr = nullptr ; + xmlSecDSigCtxPtr pDsigCtx = nullptr ; + xmlNodePtr pNode = nullptr ; + + if( !aTemplate.is() ) + throw RuntimeException() ; + + if( !aEnvironment.is() ) + throw RuntimeException() ; + + //Get Keys Manager + SecurityEnvironment_MSCryptImpl* pSecEnv = dynamic_cast(aEnvironment.get()); + if( pSecEnv == nullptr ) + throw RuntimeException() ; + + //Get the xml node + Reference< XXMLElementWrapper > xElement = aTemplate->getTemplate() ; + if( !xElement.is() ) { + throw RuntimeException() ; + } + + XMLElementWrapper_XmlSecImpl* pElement = dynamic_cast(xElement.get()); + if( pElement == nullptr ) { + throw RuntimeException() ; + } + + pNode = pElement->getNativeElement() ; + + //Get the stream/URI binding + Reference< XUriBinding > xUriBinding = aTemplate->getBinding() ; + if( xUriBinding.is() ) { + //Register the stream input callbacks into libxml2 + if( xmlRegisterStreamInputCallbacks( xUriBinding ) < 0 ) + throw RuntimeException() ; + } + + setErrorRecorder( ); + + pMngr = pSecEnv->createKeysManager(); + if( !pMngr ) { + throw RuntimeException() ; + } + + //Create Signature context + pDsigCtx = xmlSecDSigCtxCreate( pMngr ) ; + if( pDsigCtx == nullptr ) + { + //throw XMLSignatureException() ; + SecurityEnvironment_MSCryptImpl::destroyKeysManager( pMngr ); + clearErrorRecorder(); + return aTemplate; + } + + //Sign the template + if( xmlSecDSigCtxSign( pDsigCtx , pNode ) == 0 ) + { + if (pDsigCtx->status == xmlSecDSigStatusSucceeded) + aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED); + else + aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_UNKNOWN); + } + else + { + aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_UNKNOWN); + } + + + xmlSecDSigCtxDestroy( pDsigCtx ) ; + SecurityEnvironment_MSCryptImpl::destroyKeysManager( pMngr ); + + //Unregistered the stream/URI binding + if( xUriBinding.is() ) + xmlUnregisterStreamInputCallbacks() ; + + clearErrorRecorder(); + return aTemplate ; +} + +/* XXMLSignature */ +Reference< XXMLSignatureTemplate > +SAL_CALL XMLSignature_MSCryptImpl::validate( + const Reference< XXMLSignatureTemplate >& aTemplate , + const Reference< XXMLSecurityContext >& aSecurityCtx +) { + xmlSecKeysMngrPtr pMngr = nullptr ; + xmlSecDSigCtxPtr pDsigCtx = nullptr ; + xmlNodePtr pNode = nullptr ; + + if( !aTemplate.is() ) + throw RuntimeException() ; + + if( !aSecurityCtx.is() ) + throw RuntimeException() ; + + //Get Keys Manager + Reference< XSecurityEnvironment > xSecEnv + = aSecurityCtx->getSecurityEnvironmentByIndex( + aSecurityCtx->getDefaultSecurityEnvironmentIndex()); + SecurityEnvironment_MSCryptImpl* pSecEnv = dynamic_cast(xSecEnv.get()); + if( pSecEnv == nullptr ) + throw RuntimeException() ; + + //Get the xml node + Reference< XXMLElementWrapper > xElement = aTemplate->getTemplate() ; + if( !xElement.is() ) + throw RuntimeException() ; + + XMLElementWrapper_XmlSecImpl* pElement = dynamic_cast(xElement.get()); + if( pElement == nullptr ) + throw RuntimeException() ; + + pNode = pElement->getNativeElement() ; + + //Get the stream/URI binding + Reference< XUriBinding > xUriBinding = aTemplate->getBinding() ; + if( xUriBinding.is() ) { + //Register the stream input callbacks into libxml2 + if( xmlRegisterStreamInputCallbacks( xUriBinding ) < 0 ) + throw RuntimeException() ; + } + + setErrorRecorder( ); + + pMngr = pSecEnv->createKeysManager(); + if( !pMngr ) { + throw RuntimeException() ; + } + + //Create Signature context + pDsigCtx = xmlSecDSigCtxCreate( pMngr ) ; + if( pDsigCtx == nullptr ) + { + SecurityEnvironment_MSCryptImpl::destroyKeysManager( pMngr ); + clearErrorRecorder(); + return aTemplate; + } + + // We do certificate verification ourselves. + pDsigCtx->keyInfoReadCtx.flags |= XMLSEC_KEYINFO_FLAGS_X509DATA_DONT_VERIFY_CERTS; + + // limit possible key data to valid X509 certificates only, no KeyValues + if (xmlSecPtrListAdd(&(pDsigCtx->keyInfoReadCtx.enabledKeyData), BAD_CAST xmlSecMSCngKeyDataX509GetKlass()) < 0) + throw RuntimeException("failed to limit allowed key data"); + + //Verify signature + //The documentation says that the signature is only valid if the return value is 0 (that is, not < 0) + //AND pDsigCtx->status == xmlSecDSigStatusSucceeded. That is, we must not make any assumptions, if + //the return value is < 0. Then we must regard the signature as INVALID. We cannot use the + //error recorder feature to get the ONE error that made the verification fail, because there is no + //documentation/specification as to how to interpret the number of recorded errors and what is the initial + //error. + int rs = xmlSecDSigCtxVerify(pDsigCtx , pNode); + + // Also verify manifest: this is empty for ODF, but contains everything (except signature metadata) for OOXML. + xmlSecSize nReferenceCount = xmlSecPtrListGetSize(&pDsigCtx->manifestReferences); + // Require that all manifest references are also good. + xmlSecSize nReferenceGood = 0; + for (xmlSecSize nReference = 0; nReference < nReferenceCount; ++nReference) + { + xmlSecDSigReferenceCtxPtr pReference = static_cast(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 const& /*rSeq*/) +{ + return cppu::acquire(new XMLSignature_MSCryptImpl); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/certerrors.h b/xmlsecurity/source/xmlsec/nss/certerrors.h new file mode 100644 index 0000000000..e8b7b38737 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/certerrors.h @@ -0,0 +1,385 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +{SEC_ERROR_IO, "An I/O error occurred during security authorization."}, + +{SEC_ERROR_LIBRARY_FAILURE, "security library failure."}, + +{SEC_ERROR_BAD_DATA, "security library: received bad data."}, + +{SEC_ERROR_OUTPUT_LEN, "security library: output length error."}, + +{SEC_ERROR_INPUT_LEN, "security library has experienced an input length error."}, + +{SEC_ERROR_INVALID_ARGS, "security library: invalid arguments."}, + +{SEC_ERROR_INVALID_ALGORITHM, "security library: invalid algorithm."}, + +{SEC_ERROR_INVALID_AVA, "security library: invalid AVA."}, + +{SEC_ERROR_INVALID_TIME, "Improperly formatted time string."}, + +{SEC_ERROR_BAD_DER, "security library: improperly formatted DER-encoded message."}, + +{SEC_ERROR_BAD_SIGNATURE, "Peer's certificate has an invalid signature."}, + +{SEC_ERROR_EXPIRED_CERTIFICATE, "Peer's Certificate has expired."}, + +{SEC_ERROR_REVOKED_CERTIFICATE, "Peer's Certificate has been revoked."}, + +{SEC_ERROR_UNKNOWN_ISSUER, "Peer's Certificate issuer is not recognized."}, + +{SEC_ERROR_BAD_KEY, "Peer's public key is invalid."}, + +{SEC_ERROR_BAD_PASSWORD, "The security password entered is incorrect."}, + +{SEC_ERROR_RETRY_PASSWORD, "New password entered incorrectly. Please try again."}, + +{SEC_ERROR_NO_NODELOCK, "security library: no nodelock."}, + +{SEC_ERROR_BAD_DATABASE, "security library: bad database."}, + +{SEC_ERROR_NO_MEMORY, "security library: memory allocation failure."}, + +{SEC_ERROR_UNTRUSTED_ISSUER, "Peer's certificate issuer has been marked as not trusted by the user."}, + +{SEC_ERROR_UNTRUSTED_CERT, "Peer's certificate has been marked as not trusted by the user."}, + +{SEC_ERROR_DUPLICATE_CERT, "Certificate already exists in your database."}, + +{SEC_ERROR_DUPLICATE_CERT_NAME, "Downloaded certificate's name duplicates one already in your database."}, + +{SEC_ERROR_ADDING_CERT, "Error adding certificate to database."}, + +{SEC_ERROR_FILING_KEY, "Error refiling the key for this certificate."}, + +{SEC_ERROR_NO_KEY, "The private key for this certificate cannot be found in key database"}, + +{SEC_ERROR_CERT_VALID, "This certificate is valid."}, + +{SEC_ERROR_CERT_NOT_VALID, "This certificate is not valid."}, + +{SEC_ERROR_CERT_NO_RESPONSE, "Cert Library: No Response"}, + +{SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE, "The certificate issuer's certificate has expired. Check your system date and time."}, + +{SEC_ERROR_CRL_EXPIRED, "The CRL for the certificate's issuer has expired. Update it or check your system date and time."}, + +{SEC_ERROR_CRL_BAD_SIGNATURE, "The CRL for the certificate's issuer has an invalid signature."}, + +{SEC_ERROR_CRL_INVALID, "New CRL has an invalid format."}, + +{SEC_ERROR_EXTENSION_VALUE_INVALID, "Certificate extension value is invalid."}, + +{SEC_ERROR_EXTENSION_NOT_FOUND, "Certificate extension not found."}, + +{SEC_ERROR_CA_CERT_INVALID, "Issuer certificate is invalid."}, + +{SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID, "Certificate path length constraint is invalid."}, + +{SEC_ERROR_CERT_USAGES_INVALID, "Certificate usages field is invalid."}, + +{SEC_INTERNAL_ONLY, "**Internal ONLY module**"}, + +{SEC_ERROR_INVALID_KEY, "The key does not support the requested operation."}, + +{SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION, "Certificate contains unknown critical extension."}, + +{SEC_ERROR_OLD_CRL, "New CRL is not later than the current one."}, + +{SEC_ERROR_NO_EMAIL_CERT, "Not encrypted or signed: you do not yet have an email certificate."}, + +{SEC_ERROR_NO_RECIPIENT_CERTS_QUERY, "Not encrypted: you do not have certificates for each of the recipients."}, + +{SEC_ERROR_NOT_A_RECIPIENT, "Cannot decrypt: you are not a recipient, or matching certificate and \ +private key not found."}, + +{SEC_ERROR_PKCS7_KEYALG_MISMATCH, "Cannot decrypt: key encryption algorithm does not match your certificate."}, + +{SEC_ERROR_PKCS7_BAD_SIGNATURE, "Signature verification failed: no signer found, too many signers found, \ +or improper or corrupted data."}, + +{SEC_ERROR_UNSUPPORTED_KEYALG, "Unsupported or unknown key algorithm."}, + +{SEC_ERROR_DECRYPTION_DISALLOWED, "Cannot decrypt: encrypted using a disallowed algorithm or key size."}, + + +/* Fortezza Alerts */ +{XP_SEC_FORTEZZA_BAD_CARD, "Fortezza card has not been properly initialized. \ +Please remove it and return it to your issuer."}, + +{XP_SEC_FORTEZZA_NO_CARD, "No Fortezza cards Found"}, + +{XP_SEC_FORTEZZA_NONE_SELECTED, "No Fortezza card selected"}, + +{XP_SEC_FORTEZZA_MORE_INFO, "Please select a personality to get more info on"}, + +{XP_SEC_FORTEZZA_PERSON_NOT_FOUND, "Personality not found"}, + +{XP_SEC_FORTEZZA_NO_MORE_INFO, "No more information on that Personality"}, + +{XP_SEC_FORTEZZA_BAD_PIN, "Invalid Pin"}, + +{XP_SEC_FORTEZZA_PERSON_ERROR, "Couldn't initialize Fortezza personalities."}, +/* end fortezza alerts. */ + +{SEC_ERROR_NO_KRL, "No KRL for this site's certificate has been found."}, + +{SEC_ERROR_KRL_EXPIRED, "The KRL for this site's certificate has expired."}, + +{SEC_ERROR_KRL_BAD_SIGNATURE, "The KRL for this site's certificate has an invalid signature."}, + +{SEC_ERROR_REVOKED_KEY, "The key for this site's certificate has been revoked."}, + +{SEC_ERROR_KRL_INVALID, "New KRL has an invalid format."}, + +{SEC_ERROR_NEED_RANDOM, "security library: need random data."}, + +{SEC_ERROR_NO_MODULE, "security library: no security module can perform the requested operation."}, + +{SEC_ERROR_NO_TOKEN, "The security card or token does not exist, needs to be initialized, or has been removed."}, + +{SEC_ERROR_READ_ONLY, "security library: read-only database."}, + +{SEC_ERROR_NO_SLOT_SELECTED, "No slot or token was selected."}, + +{SEC_ERROR_CERT_NICKNAME_COLLISION, "A certificate with the same nickname already exists."}, + +{SEC_ERROR_KEY_NICKNAME_COLLISION, "A key with the same nickname already exists."}, + +{SEC_ERROR_SAFE_NOT_CREATED, "error while creating safe object"}, + +{SEC_ERROR_BAGGAGE_NOT_CREATED, "error while creating baggage object"}, + +{XP_JAVA_REMOVE_PRINCIPAL_ERROR, "Couldn't remove the principal"}, + +{XP_JAVA_DELETE_PRIVILEGE_ERROR, "Couldn't delete the privilege"}, + +{XP_JAVA_CERT_NOT_EXISTS_ERROR, "This principal doesn't have a certificate"}, + +{SEC_ERROR_BAD_EXPORT_ALGORITHM, "Required algorithm is not allowed."}, + +{SEC_ERROR_EXPORTING_CERTIFICATES, "Error attempting to export certificates."}, + +{SEC_ERROR_IMPORTING_CERTIFICATES, "Error attempting to import certificates."}, + +{SEC_ERROR_PKCS12_DECODING_PFX, "Unable to import. Decoding error. File not valid."}, + +{SEC_ERROR_PKCS12_INVALID_MAC, "Unable to import. Invalid MAC. Incorrect password or corrupt file."}, + +{SEC_ERROR_PKCS12_UNSUPPORTED_MAC_ALGORITHM, "Unable to import. MAC algorithm not supported."}, + +{SEC_ERROR_PKCS12_UNSUPPORTED_TRANSPORT_MODE, "Unable to import. Only password integrity and privacy modes supported."}, + +{SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE, "Unable to import. File structure is corrupt."}, + +{SEC_ERROR_PKCS12_UNSUPPORTED_PBE_ALGORITHM, "Unable to import. Encryption algorithm not supported."}, + +{SEC_ERROR_PKCS12_UNSUPPORTED_VERSION, "Unable to import. File version not supported."}, + +{SEC_ERROR_PKCS12_PRIVACY_PASSWORD_INCORRECT, "Unable to import. Incorrect privacy password."}, + +{SEC_ERROR_PKCS12_CERT_COLLISION, "Unable to import. Same nickname already exists in database."}, + +{SEC_ERROR_USER_CANCELLED, "The user pressed cancel."}, + +{SEC_ERROR_PKCS12_DUPLICATE_DATA, "Not imported, already in database."}, + +{SEC_ERROR_MESSAGE_SEND_ABORTED, "Message not sent."}, + +{SEC_ERROR_INADEQUATE_KEY_USAGE, "Certificate key usage inadequate for attempted operation."}, + +{SEC_ERROR_INADEQUATE_CERT_TYPE, "Certificate type not approved for application."}, + +{SEC_ERROR_CERT_ADDR_MISMATCH, "Address in signing certificate does not match address in message headers."}, + +{SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY, "Unable to import. Error attempting to import private key."}, + +{SEC_ERROR_PKCS12_IMPORTING_CERT_CHAIN, "Unable to import. Error attempting to import certificate chain."}, + +{SEC_ERROR_PKCS12_UNABLE_TO_LOCATE_OBJECT_BY_NAME, "Unable to export. Unable to locate certificate or key by nickname."}, + +{SEC_ERROR_PKCS12_UNABLE_TO_EXPORT_KEY, "Unable to export. Private Key could not be located and exported."}, + +{SEC_ERROR_PKCS12_UNABLE_TO_WRITE, "Unable to export. Unable to write the export file."}, + +{SEC_ERROR_PKCS12_UNABLE_TO_READ, "Unable to import. Unable to read the import file."}, + +{SEC_ERROR_PKCS12_KEY_DATABASE_NOT_INITIALIZED, "Unable to export. Key database corrupt or deleted."}, + +{SEC_ERROR_KEYGEN_FAIL, "Unable to generate public/private key pair."}, + +{SEC_ERROR_INVALID_PASSWORD, "Password entered is invalid. Please pick a different one."}, + +{SEC_ERROR_RETRY_OLD_PASSWORD, "Old password entered incorrectly. Please try again."}, + +{SEC_ERROR_BAD_NICKNAME, "Certificate nickname already in use."}, + +{SEC_ERROR_NOT_FORTEZZA_ISSUER, "Peer FORTEZZA chain has a non-FORTEZZA Certificate."}, + +{SEC_ERROR_CANNOT_MOVE_SENSITIVE_KEY, "A sensitive key cannot be moved to the slot where it is needed."}, + +{SEC_ERROR_JS_INVALID_MODULE_NAME, "Invalid module name."}, + +{SEC_ERROR_JS_INVALID_DLL, "Invalid module path/filename"}, + +{SEC_ERROR_JS_ADD_MOD_FAILURE, "Unable to add module"}, + +{SEC_ERROR_JS_DEL_MOD_FAILURE, "Unable to delete module"}, + +{SEC_ERROR_OLD_KRL, "New KRL is not later than the current one."}, + +{SEC_ERROR_CKL_CONFLICT, "New CKL has different issuer than current CKL. Delete current CKL."}, + +{SEC_ERROR_CERT_NOT_IN_NAME_SPACE, "The Certifying Authority for this certificate is not permitted to issue a \ +certificate with this name."}, + +{SEC_ERROR_KRL_NOT_YET_VALID, "The key revocation list for this certificate is not yet valid."}, + +{SEC_ERROR_CRL_NOT_YET_VALID, "The certificate revocation list for this certificate is not yet valid."}, + +{SEC_ERROR_UNKNOWN_CERT, "The requested certificate could not be found."}, + +{SEC_ERROR_UNKNOWN_SIGNER, "The signer's certificate could not be found."}, + +{SEC_ERROR_CERT_BAD_ACCESS_LOCATION, "The location for the certificate status server has invalid format."}, + +{SEC_ERROR_OCSP_UNKNOWN_RESPONSE_TYPE, "The OCSP response cannot be fully decoded; it is of an unknown type."}, + +{SEC_ERROR_OCSP_BAD_HTTP_RESPONSE, "The OCSP server returned unexpected/invalid HTTP data."}, + +{SEC_ERROR_OCSP_MALFORMED_REQUEST, "The OCSP server found the request to be corrupted or improperly formed."}, + +{SEC_ERROR_OCSP_SERVER_ERROR, "The OCSP server experienced an internal error."}, + +{SEC_ERROR_OCSP_TRY_SERVER_LATER, "The OCSP server suggests trying again later."}, + +{SEC_ERROR_OCSP_REQUEST_NEEDS_SIG, "The OCSP server requires a signature on this request."}, + +{SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST, "The OCSP server has refused this request as unauthorized."}, + +{SEC_ERROR_OCSP_UNKNOWN_RESPONSE_STATUS, "The OCSP server returned an unrecognizable status."}, + +{SEC_ERROR_OCSP_UNKNOWN_CERT, "The OCSP server has no status for the certificate."}, + +{SEC_ERROR_OCSP_NOT_ENABLED, "You must enable OCSP before performing this operation."}, + +{SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER, "You must set the OCSP default responder before performing this operation."}, + +{SEC_ERROR_OCSP_MALFORMED_RESPONSE, "The response from the OCSP server was corrupted or improperly formed."}, + +{SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE, "The signer of the OCSP response is not authorized to give status for \ +this certificate."}, + +{SEC_ERROR_OCSP_FUTURE_RESPONSE, "The OCSP response is not yet valid (contains a date in the future},."}, + +{SEC_ERROR_OCSP_OLD_RESPONSE, "The OCSP response contains out-of-date information."}, + +{SEC_ERROR_DIGEST_NOT_FOUND, "The CMS or PKCS #7 Digest was not found in signed message."}, + +{SEC_ERROR_UNSUPPORTED_MESSAGE_TYPE, "The CMS or PKCS #7 Message type is unsupported."}, + +{SEC_ERROR_MODULE_STUCK, "PKCS #11 module could not be removed because it is still in use."}, + +{SEC_ERROR_BAD_TEMPLATE, "Could not decode ASN.1 data. Specified template was invalid."}, + +{SEC_ERROR_CRL_NOT_FOUND, "No matching CRL was found."}, + +{SEC_ERROR_REUSED_ISSUER_AND_SERIAL, "You are attempting to import a cert with the same issuer/serial as \ +an existing cert, but that is not the same cert."}, + +{SEC_ERROR_BUSY, "NSS could not shutdown. Objects are still in use."}, + +{SEC_ERROR_EXTRA_INPUT, "DER-encoded message contained extra unused data."}, + +{SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE, "Unsupported elliptic curve."}, + +{SEC_ERROR_UNSUPPORTED_EC_POINT_FORM, "Unsupported elliptic curve point form."}, + +{SEC_ERROR_UNRECOGNIZED_OID, "Unrecognized Object Identifier."}, + +{SEC_ERROR_OCSP_INVALID_SIGNING_CERT, "Invalid OCSP signing certificate in OCSP response."}, + +{SEC_ERROR_REVOKED_CERTIFICATE_CRL, "Certificate is revoked in issuer's certificate revocation list."}, + +{SEC_ERROR_REVOKED_CERTIFICATE_OCSP, "Issuer's OCSP responder reports certificate is revoked."}, + +{SEC_ERROR_CRL_INVALID_VERSION, "Issuer's Certificate Revocation List has an unknown version number."}, + +{SEC_ERROR_CRL_V1_CRITICAL_EXTENSION, "Issuer's V1 Certificate Revocation List has a critical extension."}, + +{SEC_ERROR_CRL_UNKNOWN_CRITICAL_EXTENSION, "Issuer's V2 Certificate Revocation List has an unknown critical extension."}, + +{SEC_ERROR_UNKNOWN_OBJECT_TYPE, "Unknown object type specified."}, + +{SEC_ERROR_INCOMPATIBLE_PKCS11, "PKCS #11 driver violates the spec in an incompatible way."}, + +{SEC_ERROR_NO_EVENT, "No new slot event is available at this time."}, + +{SEC_ERROR_CRL_ALREADY_EXISTS, "CRL already exists."}, + +{SEC_ERROR_NOT_INITIALIZED, "NSS is not initialized."}, + +{SEC_ERROR_TOKEN_NOT_LOGGED_IN, "The operation failed because the PKCS#11 token is not logged in."}, + +{SEC_ERROR_OCSP_RESPONDER_CERT_INVALID, "Configured OCSP responder's certificate is invalid."}, + +{SEC_ERROR_OCSP_BAD_SIGNATURE, "OCSP response has an invalid signature."}, + +{SEC_ERROR_OUT_OF_SEARCH_LIMITS, "Cert validation search is out of search limits"}, + +{SEC_ERROR_INVALID_POLICY_MAPPING, "Policy mapping contains anypolicy"}, + +{SEC_ERROR_POLICY_VALIDATION_FAILED, "Cert chain fails policy validation"}, + +{SEC_ERROR_UNKNOWN_AIA_LOCATION_TYPE, "Unknown location type in cert AIA extension"}, + +{SEC_ERROR_BAD_HTTP_RESPONSE, "Server returned bad HTTP response"}, + +{SEC_ERROR_BAD_LDAP_RESPONSE, "Server returned bad LDAP response"}, + +{SEC_ERROR_FAILED_TO_ENCODE_DATA, "Failed to encode data with ASN1 encoder"}, + +{SEC_ERROR_BAD_INFO_ACCESS_LOCATION, "Bad information access location in cert extension"}, + +{SEC_ERROR_LIBPKIX_INTERNAL, "Libpkix internal error occurred during cert validation."}, + +#if ( NSS_VMAJOR > 3 ) || ( NSS_VMAJOR == 3 && NSS_VMINOR > 12 ) || ( NSS_VMAJOR == 3 && NSS_VMINOR == 12 && NSS_VPATCH > 2 ) +// following 3 errors got first used in NSS 3.12.3 +// they were in the header even in 3.12.2 but there was missing the mapping in pk11err.c +// see also https://bugzilla.mozilla.org/show_bug.cgi?id=453364 + +{SEC_ERROR_PKCS11_GENERAL_ERROR, "A PKCS #11 module returned CKR_GENERAL_ERROR, indicating that an unrecoverable error has occurred."}, + +{SEC_ERROR_PKCS11_FUNCTION_FAILED, "A PKCS #11 module returned CKR_FUNCTION_FAILED, indicating that the requested function could not be performed. Trying the same operation again might succeed."}, + +{SEC_ERROR_PKCS11_DEVICE_ERROR, "A PKCS #11 module returned CKR_DEVICE_ERROR, indicating that a problem has occurred with the token or slot."}, + +#endif + +#if ( NSS_VMAJOR > 3 ) || ( NSS_VMAJOR == 3 && NSS_VMINOR > 12 ) || ( NSS_VMAJOR == 3 && NSS_VMINOR == 12 && NSS_VPATCH > 3 ) +// following 2 errors got added in NSS 3.12.4 + +{SEC_ERROR_BAD_INFO_ACCESS_METHOD, "Unknown information access method in certificate extension."}, + +{SEC_ERROR_CRL_IMPORT_FAILED, "Error attempting to import a CRL."}, + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/ciphercontext.cxx b/xmlsecurity/source/xmlsec/nss/ciphercontext.cxx new file mode 100644 index 0000000000..c3bbfdb0f2 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/ciphercontext.cxx @@ -0,0 +1,389 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include +#include +#include +#include + +#include "ciphercontext.hxx" +#include // for NSS_VMINOR +#include + +constexpr size_t nAESGCMIVSize = 12; +constexpr size_t nAESGCMTagSize = 16; + +using namespace ::com::sun::star; + +uno::Reference< xml::crypto::XCipherContext > OCipherContext::Create( CK_MECHANISM_TYPE nNSSCipherID, const uno::Sequence< ::sal_Int8 >& aKey, const uno::Sequence< ::sal_Int8 >& aInitializationVector, bool bEncryption, bool bW3CPadding ) +{ + ::rtl::Reference< OCipherContext > xResult = new OCipherContext; + + xResult->m_pSlot = PK11_GetBestSlot( nNSSCipherID, nullptr ); + if (!xResult->m_pSlot) + { + SAL_WARN("xmlsecurity.nss", "PK11_GetBestSlot failed"); + throw uno::RuntimeException("PK11_GetBestSlot failed"); + } + + SECItem aKeyItem = { siBuffer, + const_cast(reinterpret_cast(aKey.getConstArray())), + sal::static_int_cast(aKey.getLength()) }; + xResult->m_pSymKey = PK11_ImportSymKey(xResult->m_pSlot, nNSSCipherID, + PK11_OriginDerive, bEncryption ? CKA_ENCRYPT : CKA_DECRYPT, &aKeyItem, nullptr); + if (!xResult->m_pSymKey) + { + SAL_WARN("xmlsecurity.nss", "PK11_ImportSymKey failed"); + throw uno::RuntimeException("PK11_ImportSymKey failed"); + } + + if (nNSSCipherID == CKM_AES_GCM) + { + // TODO: when runtime requirements are raised to NSS 3.52, + // cleanup according to + // https://fedoraproject.org/wiki/Changes/NssGCMParams +#if NSS_VMINOR >= 52 + xResult->m_pSecParam = SECITEM_AllocItem(nullptr, nullptr, sizeof(CK_NSS_GCM_PARAMS)); +#else + xResult->m_pSecParam = SECITEM_AllocItem(nullptr, nullptr, sizeof(CK_GCM_PARAMS)); +#endif + if (!xResult->m_pSecParam) + { + SAL_WARN("xmlsecurity.nss", "SECITEM_AllocItem failed"); + throw uno::RuntimeException("SECITEM_AllocItem failed"); + } + assert(aInitializationVector.getLength() == nAESGCMIVSize); + xResult->m_AESGCMIV = aInitializationVector; +#if NSS_VMINOR >= 52 + auto *const pParams = reinterpret_cast(xResult->m_pSecParam->data); +#else + auto *const pParams = reinterpret_cast(xResult->m_pSecParam->data); +#endif + pParams->pIv = const_cast(reinterpret_cast(xResult->m_AESGCMIV.getConstArray())); + pParams->ulIvLen = sal::static_int_cast(xResult->m_AESGCMIV.getLength()); + pParams->pAAD = nullptr; + pParams->ulAADLen = 0; + pParams->ulTagBits = nAESGCMTagSize * 8; + } + else + { + SECItem aIVItem = { siBuffer, + const_cast(reinterpret_cast(aInitializationVector.getConstArray())), + sal::static_int_cast(aInitializationVector.getLength()) }; + xResult->m_pSecParam = PK11_ParamFromIV(nNSSCipherID, &aIVItem); + if (!xResult->m_pSecParam) + { + SAL_WARN("xmlsecurity.nss", "PK11_ParamFromIV failed"); + throw uno::RuntimeException("PK11_ParamFromIV failed"); + } + + xResult->m_pContext = PK11_CreateContextBySymKey( nNSSCipherID, bEncryption ? CKA_ENCRYPT : CKA_DECRYPT, xResult->m_pSymKey, xResult->m_pSecParam); + if (!xResult->m_pContext) + { + SAL_WARN("xmlsecurity.nss", "PK11_CreateContextBySymKey failed"); + throw uno::RuntimeException("PK11_CreateContextBySymKey failed"); + } + } + + xResult->m_bEncryption = bEncryption; + xResult->m_bW3CPadding = bW3CPadding; + xResult->m_bPadding = bW3CPadding || ( PK11_GetPadMechanism( nNSSCipherID ) == nNSSCipherID ); + // in NSS 3.94, a global default value of 8 is returned for CKM_AES_GCM + xResult->m_nBlockSize = nNSSCipherID == CKM_AES_GCM ? 16 : PK11_GetBlockSize(nNSSCipherID, xResult->m_pSecParam); + if (SAL_MAX_INT8 < xResult->m_nBlockSize) + { + SAL_WARN("xmlsecurity.nss", "PK11_GetBlockSize unexpected result"); + throw uno::RuntimeException("PK11_GetBlockSize unexpected result"); + } + return xResult; +} + +void OCipherContext::Dispose() +{ + if ( m_pContext ) + { + PK11_DestroyContext( m_pContext, PR_TRUE ); + m_pContext = nullptr; + } + + if ( m_pSecParam ) + { + SECITEM_FreeItem( m_pSecParam, PR_TRUE ); + m_pSecParam = nullptr; + } + + if ( m_pSymKey ) + { + PK11_FreeSymKey( m_pSymKey ); + m_pSymKey = nullptr; + } + + if ( m_pSlot ) + { + PK11_FreeSlot( m_pSlot ); + m_pSlot = nullptr; + } + + m_bDisposed = true; +} + +uno::Sequence< ::sal_Int8 > SAL_CALL OCipherContext::convertWithCipherContext( const uno::Sequence< ::sal_Int8 >& aData ) +{ + std::unique_lock aGuard( m_aMutex ); + + if ( m_bBroken ) + throw uno::RuntimeException(); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + if (m_AESGCMIV.getLength()) + { + if (SAL_MAX_INT32 - nAESGCMIVSize - nAESGCMTagSize <= static_cast(m_aLastBlock.getLength()) + static_cast(aData.getLength())) + { + m_bBroken = true; + throw uno::RuntimeException("overflow"); + } + m_aLastBlock.realloc(m_aLastBlock.getLength() + aData.getLength()); + memcpy(m_aLastBlock.getArray() + m_aLastBlock.getLength() - aData.getLength(), aData.getConstArray(), aData.getLength()); + return {}; + } + + uno::Sequence< sal_Int8 > aToConvert; + if ( aData.hasElements() ) + { + sal_Int32 nOldLastBlockLen = m_aLastBlock.getLength(); + + sal_Int32 nAvailableData = nOldLastBlockLen + aData.getLength(); + sal_Int32 nToConvertLen; + if ( m_bEncryption || !m_bW3CPadding ) + { + assert(nOldLastBlockLen < m_nBlockSize); + if ( nAvailableData % m_nBlockSize == 0 ) + nToConvertLen = nAvailableData; + else if ( nAvailableData < m_nBlockSize ) + nToConvertLen = 0; + else + nToConvertLen = nAvailableData - nAvailableData % m_nBlockSize; + } + else + { + assert(nOldLastBlockLen < m_nBlockSize * 2); + // decryption with W3C padding needs at least one block for finalizing + if ( nAvailableData < m_nBlockSize * 2 ) + nToConvertLen = 0; + else + nToConvertLen = nAvailableData - nAvailableData % m_nBlockSize - m_nBlockSize; + } + + aToConvert.realloc( nToConvertLen ); + if ( nToConvertLen == 0 ) + { + m_aLastBlock.realloc( nOldLastBlockLen + aData.getLength() ); + memcpy( m_aLastBlock.getArray() + nOldLastBlockLen, aData.getConstArray(), aData.getLength() ); + // aToConvert stays empty + } + else if ( nToConvertLen < nOldLastBlockLen ) + { + memcpy( aToConvert.getArray(), m_aLastBlock.getConstArray(), nToConvertLen ); + memcpy( m_aLastBlock.getArray(), m_aLastBlock.getConstArray() + nToConvertLen, nOldLastBlockLen - nToConvertLen ); + m_aLastBlock.realloc( nOldLastBlockLen - nToConvertLen + aData.getLength() ); + memcpy( m_aLastBlock.getArray() + nOldLastBlockLen - nToConvertLen, aData.getConstArray(), aData.getLength() ); + } + else + { + memcpy( aToConvert.getArray(), m_aLastBlock.getConstArray(), nOldLastBlockLen ); + if ( nToConvertLen > nOldLastBlockLen ) + memcpy( aToConvert.getArray() + nOldLastBlockLen, aData.getConstArray(), nToConvertLen - nOldLastBlockLen ); + m_aLastBlock.realloc( nAvailableData - nToConvertLen ); + memcpy( m_aLastBlock.getArray(), aData.getConstArray() + nToConvertLen - nOldLastBlockLen, nAvailableData - nToConvertLen ); + } + } + + uno::Sequence< sal_Int8 > aResult; + assert(aToConvert.getLength() % m_nBlockSize == 0); + if ( aToConvert.hasElements() ) + { + int nResultLen = 0; + aResult.realloc( aToConvert.getLength() + m_nBlockSize ); + if ( PK11_CipherOp( m_pContext, reinterpret_cast< unsigned char* >( aResult.getArray() ), &nResultLen, aResult.getLength(), reinterpret_cast< const unsigned char* >( aToConvert.getConstArray() ), aToConvert.getLength() ) != SECSuccess ) + { + m_bBroken = true; + Dispose(); + throw uno::RuntimeException("PK11_CipherOp failed"); + } + + m_nConverted += aToConvert.getLength(); + aResult.realloc( nResultLen ); + } + + return aResult; +} + +uno::Sequence< ::sal_Int8 > SAL_CALL OCipherContext::finalizeCipherContextAndDispose() +{ + std::unique_lock aGuard( m_aMutex ); + + if ( m_bBroken ) + throw uno::RuntimeException(); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + if (m_AESGCMIV.getLength()) + { + uno::Sequence aResult; + unsigned outLen; + if (m_bEncryption) + { + assert(sal::static_int_cast(m_aLastBlock.getLength()) <= SAL_MAX_INT32 - nAESGCMIVSize - nAESGCMTagSize); + // add space for IV and tag + aResult.realloc(m_aLastBlock.getLength() + nAESGCMIVSize + nAESGCMTagSize); + // W3C xmlenc-core1 requires the IV preceding the ciphertext, + // but NSS doesn't do it, so copy it manually + memcpy(aResult.getArray(), m_AESGCMIV.getConstArray(), nAESGCMIVSize); + if (PK11_Encrypt(m_pSymKey, CKM_AES_GCM, m_pSecParam, + reinterpret_cast(aResult.getArray() + nAESGCMIVSize), + &outLen, aResult.getLength() - nAESGCMIVSize, + reinterpret_cast(m_aLastBlock.getConstArray()), + m_aLastBlock.getLength()) != SECSuccess) + { + m_bBroken = true; + Dispose(); + throw uno::RuntimeException("PK11_Encrypt failed"); + } + assert(outLen == sal::static_int_cast(aResult.getLength() - nAESGCMIVSize)); + } + else if (nAESGCMIVSize + nAESGCMTagSize < sal::static_int_cast(m_aLastBlock.getLength())) + { + if (0 != memcmp(m_AESGCMIV.getConstArray(), m_aLastBlock.getConstArray(), nAESGCMIVSize)) + { + m_bBroken = true; + Dispose(); + throw uno::RuntimeException("inconsistent IV"); + } + aResult.realloc(m_aLastBlock.getLength() - nAESGCMIVSize - nAESGCMTagSize); + if (PK11_Decrypt(m_pSymKey, CKM_AES_GCM, m_pSecParam, + reinterpret_cast(aResult.getArray()), + &outLen, aResult.getLength(), + reinterpret_cast(m_aLastBlock.getConstArray() + nAESGCMIVSize), + m_aLastBlock.getLength() - nAESGCMIVSize) != SECSuccess) + { + m_bBroken = true; + Dispose(); + throw uno::RuntimeException("PK11_Decrypt failed"); + } + assert(outLen == sal::static_int_cast(aResult.getLength())); + } + else + { + m_bBroken = true; + Dispose(); + throw uno::RuntimeException("incorrect size of input"); + } + Dispose(); + return aResult; + } + + assert(m_nBlockSize <= SAL_MAX_INT8); + assert(m_nConverted % m_nBlockSize == 0); // whole blocks are converted + sal_Int32 nSizeForPadding = ( m_nConverted + m_aLastBlock.getLength() ) % m_nBlockSize; + + // if it is decryption, the amount of data should be rounded to the block size even in case of padding + if ( ( !m_bPadding || !m_bEncryption ) && nSizeForPadding ) + throw uno::RuntimeException("The data should contain complete blocks only." ); + + if ( m_bW3CPadding && m_bEncryption ) + { + // in this case the last block should be smaller than standard block + // it will be increased with the padding + assert(m_aLastBlock.getLength() < m_nBlockSize); + + // W3CPadding handling for encryption + sal_Int32 nPaddingSize = m_nBlockSize - nSizeForPadding; + sal_Int32 nOldLastBlockLen = m_aLastBlock.getLength(); + m_aLastBlock.realloc( nOldLastBlockLen + nPaddingSize ); + auto pLastBlock = m_aLastBlock.getArray(); + + if ( nPaddingSize > 1 ) + { + rtlRandomPool aRandomPool = rtl_random_createPool(); + rtl_random_getBytes( aRandomPool, pLastBlock + nOldLastBlockLen, nPaddingSize - 1 ); + rtl_random_destroyPool ( aRandomPool ); + } + pLastBlock[m_aLastBlock.getLength() - 1] = static_cast< sal_Int8 >( nPaddingSize ); + } + + // finally should the last block be smaller than two standard blocks + assert(m_aLastBlock.getLength() < m_nBlockSize * 2); + + uno::Sequence< sal_Int8 > aResult; + if ( m_aLastBlock.hasElements() ) + { + int nPrefResLen = 0; + aResult.realloc( m_aLastBlock.getLength() + m_nBlockSize ); + if ( PK11_CipherOp( m_pContext, reinterpret_cast< unsigned char* >( aResult.getArray() ), &nPrefResLen, aResult.getLength(), reinterpret_cast< const unsigned char* >( m_aLastBlock.getConstArray() ), m_aLastBlock.getLength() ) != SECSuccess ) + { + m_bBroken = true; + Dispose(); + throw uno::RuntimeException("PK11_CipherOp failed"); + } + + aResult.realloc( nPrefResLen ); + m_aLastBlock.realloc( 0 ); + } + + sal_Int32 nPrefixLen = aResult.getLength(); + aResult.realloc( nPrefixLen + m_nBlockSize * 2 ); + unsigned nFinalLen = 0; + if ( PK11_DigestFinal( m_pContext, reinterpret_cast< unsigned char* >( aResult.getArray() + nPrefixLen ), &nFinalLen, aResult.getLength() - nPrefixLen ) != SECSuccess ) + { + m_bBroken = true; + Dispose(); + throw uno::RuntimeException("PK11_DigestFinal failed"); + } + + aResult.realloc( nPrefixLen + nFinalLen ); + + if ( m_bW3CPadding && !m_bEncryption ) + { + // W3CPadding handling for decryption + // aResult should have enough data, except if the input was completely empty + + // see https://www.w3.org/TR/xmlenc-core1/#sec-Alg-Block + if (aResult.getLength() < m_nBlockSize + || aResult[aResult.getLength()-1] <= 0 + || m_nBlockSize < aResult[aResult.getLength()-1]) + { + m_bBroken = true; + Dispose(); + throw uno::RuntimeException("incorrect size of padding"); + } + + aResult.realloc(aResult.getLength() - aResult[aResult.getLength()-1]); + } + + Dispose(); + + return aResult; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/ciphercontext.hxx b/xmlsecurity/source/xmlsec/nss/ciphercontext.hxx new file mode 100644 index 0000000000..d2c002ec46 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/ciphercontext.hxx @@ -0,0 +1,81 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include + +#include +#include +#include +#include + +class OCipherContext : public cppu::WeakImplHelper< css::xml::crypto::XCipherContext > +{ +private: + std::mutex m_aMutex; + + PK11SlotInfo* m_pSlot; + PK11SymKey* m_pSymKey; + SECItem* m_pSecParam; + PK11Context* m_pContext; + + sal_Int32 m_nBlockSize; + css::uno::Sequence< sal_Int8 > m_aLastBlock; + css::uno::Sequence m_AESGCMIV; + + bool m_bEncryption; + bool m_bPadding; + bool m_bW3CPadding; + sal_Int64 m_nConverted; + + bool m_bDisposed; + bool m_bBroken; + + void Dispose(); + + OCipherContext() + : m_pSlot( nullptr ) + , m_pSymKey( nullptr ) + , m_pSecParam( nullptr ) + , m_pContext( nullptr ) + , m_nBlockSize( 0 ) + , m_bEncryption( false ) + , m_bPadding( false ) + , m_bW3CPadding( false ) + , m_nConverted( 0 ) + , m_bDisposed( false ) + , m_bBroken( false ) + {} + +public: + + virtual ~OCipherContext() override + { + Dispose(); + } + + static css::uno::Reference< css::xml::crypto::XCipherContext > Create( CK_MECHANISM_TYPE nNSSCipherID, const css::uno::Sequence< ::sal_Int8 >& aKey, const css::uno::Sequence< ::sal_Int8 >& aInitializationVector, bool bEncryption, bool bW3CPadding ); + + // XCipherContext + virtual css::uno::Sequence< ::sal_Int8 > SAL_CALL convertWithCipherContext( const css::uno::Sequence< ::sal_Int8 >& aData ) override; + virtual css::uno::Sequence< ::sal_Int8 > SAL_CALL finalizeCipherContextAndDispose( ) override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/digestcontext.cxx b/xmlsecurity/source/xmlsec/nss/digestcontext.cxx new file mode 100644 index 0000000000..63c128e702 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/digestcontext.cxx @@ -0,0 +1,94 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include + +#include +#include "digestcontext.hxx" + +using namespace ::com::sun::star; + +ODigestContext::~ODigestContext() +{ + if ( m_pContext ) + { + PK11_DestroyContext( m_pContext, PR_TRUE ); + m_pContext = nullptr; + } +} + +void SAL_CALL ODigestContext::updateDigest( const uno::Sequence< ::sal_Int8 >& aData ) +{ + std::scoped_lock aGuard( m_aMutex ); + + if ( m_bBroken ) + throw uno::RuntimeException(); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + if (m_b1KData && m_nDigested >= 1024) + return; + + uno::Sequence< sal_Int8 > aToDigest = aData; + if ( m_b1KData && m_nDigested + aData.getLength() > 1024 ) + aToDigest.realloc( 1024 - m_nDigested ); + + if ( PK11_DigestOp( m_pContext, reinterpret_cast< const unsigned char* >( aToDigest.getConstArray() ), aToDigest.getLength() ) != SECSuccess ) + { + PK11_DestroyContext( m_pContext, PR_TRUE ); + m_pContext = nullptr; + m_bBroken = true; + throw uno::RuntimeException(); + } + + m_nDigested += aToDigest.getLength(); +} + +uno::Sequence< ::sal_Int8 > SAL_CALL ODigestContext::finalizeDigestAndDispose() +{ + std::scoped_lock aGuard( m_aMutex ); + + if ( m_bBroken ) + throw uno::RuntimeException(); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + uno::Sequence< sal_Int8 > aResult( m_nDigestLength ); + unsigned int nResultLen = 0; + if ( PK11_DigestFinal( m_pContext, reinterpret_cast< unsigned char* >( aResult.getArray() ), &nResultLen, aResult.getLength() ) != SECSuccess ) + { + PK11_DestroyContext( m_pContext, PR_TRUE ); + m_pContext = nullptr; + m_bBroken = true; + throw uno::RuntimeException(); + } + + PK11_DestroyContext( m_pContext, PR_TRUE ); + m_pContext = nullptr; + m_bDisposed = true; + + aResult.realloc( nResultLen ); + return aResult; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/digestcontext.hxx b/xmlsecurity/source/xmlsec/nss/digestcontext.hxx new file mode 100644 index 0000000000..72e1864851 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/digestcontext.hxx @@ -0,0 +1,59 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include + +#include +#include +#include + +class ODigestContext : public cppu::WeakImplHelper< css::xml::crypto::XDigestContext > +{ +private: + std::mutex m_aMutex; + + PK11Context* m_pContext; + sal_Int32 const m_nDigestLength; + bool const m_b1KData; + sal_Int32 m_nDigested; + + bool m_bDisposed; + bool m_bBroken; + +public: + ODigestContext( PK11Context* pContext, sal_Int32 nDigestLength, bool b1KData ) + : m_pContext( pContext ) + , m_nDigestLength( nDigestLength ) + , m_b1KData( b1KData ) + , m_nDigested( 0 ) + , m_bDisposed( false ) + , m_bBroken( false ) + {} + + virtual ~ODigestContext() override; + + + // XDigestContext + virtual void SAL_CALL updateDigest( const css::uno::Sequence< ::sal_Int8 >& aData ) override; + virtual css::uno::Sequence< ::sal_Int8 > SAL_CALL finalizeDigestAndDispose() override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/nssinitializer.cxx b/xmlsecurity/source/xmlsec/nss/nssinitializer.cxx new file mode 100644 index 0000000000..bf74fa04ce --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/nssinitializer.cxx @@ -0,0 +1,647 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "digestcontext.hxx" +#include "ciphercontext.hxx" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace cssu = css::uno; +namespace cssl = css::lang; + +using namespace com::sun::star; + +#define ROOT_CERTS "Root Certs for OpenOffice.org" + +extern "C" { + +static void nsscrypto_finalize(); + +} + +namespace +{ + +class InitNSSPrivate +{ +private: + std::optional m_oTempFileDatabaseDirectory; + +public: + OUString getTempDatabasePath() + { + if (!m_oTempFileDatabaseDirectory) + { + m_oTempFileDatabaseDirectory.emplace(nullptr, true); + m_oTempFileDatabaseDirectory->EnableKillingFile(); + } + return m_oTempFileDatabaseDirectory->GetFileName(); + } + + void reset() + { + if (m_oTempFileDatabaseDirectory) + { + m_oTempFileDatabaseDirectory.reset(); + } + } +}; + +comphelper::SingletonRef* getInitNSSPrivate() +{ + static comphelper::SingletonRef 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 xInstance = rxContext->getServiceManager()->createInstanceWithContext("com.sun.star.mozilla.MozillaBootstrap", rxContext); + OSL_ENSURE( xInstance.is(), "failed to create instance" ); + + uno::Reference xMozillaBootstrap(xInstance,uno::UNO_QUERY); + OSL_ENSURE( xMozillaBootstrap.is(), "failed to create instance" ); + + if (xMozillaBootstrap.is()) + { + for (auto const productTypeIter : productTypes) + { + OUString profile = xMozillaBootstrap->getDefaultProfile(productTypeIter); + + if (!profile.isEmpty()) + { + OUString sProfilePath = xMozillaBootstrap->getProfilePath(productTypeIter, profile); + if (m_sNSSPath.isEmpty()) + { + SAL_INFO("xmlsecurity.xmlsec", "Using Mozilla profile " << sProfilePath); + m_sNSSPath = sProfilePath; + } + break; + } + } + } + + SAL_INFO_IF(m_sNSSPath.isEmpty(), "xmlsecurity.xmlsec", "No Mozilla profile found"); + return m_sNSSPath; +} + +css::uno::Sequence SAL_CALL ONSSInitializer::getNSSProfiles() +{ + ONSSInitializer::getMozillaCurrentProfile(m_xContext); + + std::vector aProfileList; + aProfileList.reserve(10); + + mozilla::MozillaProductType productTypes[3] = { + mozilla::MozillaProductType_Thunderbird, + mozilla::MozillaProductType_Firefox, + mozilla::MozillaProductType_Mozilla }; + + uno::Reference xInstance = m_xContext->getServiceManager()->createInstanceWithContext("com.sun.star.mozilla.MozillaBootstrap", m_xContext); + OSL_ENSURE(xInstance.is(), "failed to create instance" ); + + uno::Reference xMozillaBootstrap(xInstance,uno::UNO_QUERY); + + if (xMozillaBootstrap.is()) + { + for (auto const productTypeIter : productTypes) + { + uno::Sequence aProductProfileList; + xMozillaBootstrap->getProfileList(productTypeIter, aProductProfileList); + for (const auto& sProfile : std::as_const(aProductProfileList)) + aProfileList.push_back({sProfile, xMozillaBootstrap->getProfilePath(productTypeIter, sProfile), productTypeIter}); + } + } + + OUString sUserSelect; + try + { + sUserSelect = officecfg::Office::Common::Security::Scripting::CertDir::get().value_or(OUString());; + if (!lcl_pathExists(sUserSelect)) + sUserSelect = OUString(); + } + catch (const uno::Exception &) + { + TOOLS_WARN_EXCEPTION("xmlsecurity.xmlsec", "getMozillaCurrentProfile:"); + } + aProfileList.push_back({"MANUAL", sUserSelect, mozilla::MozillaProductType_Default}); + + const char* pEnv = getenv("MOZILLA_CERTIFICATE_FOLDER"); + aProfileList.push_back({"MOZILLA_CERTIFICATE_FOLDER", + pEnv ? OStringToOUString(pEnv, osl_getThreadTextEncoding()) : OUString(), + mozilla::MozillaProductType_Default}); + + return comphelper::containerToSequence(aProfileList); +} + +bool ONSSInitializer::m_bIsNSSinitialized = false; +OUString ONSSInitializer::m_sNSSPath; + +OUString SAL_CALL ONSSInitializer::getNSSPath() +{ + ONSSInitializer::getMozillaCurrentProfile(m_xContext); + return m_sNSSPath; +}; + +sal_Bool SAL_CALL ONSSInitializer::getIsNSSinitialized() +{ + return m_bIsNSSinitialized; +} + +ONSSInitializer::ONSSInitializer(css::uno::Reference< css::uno::XComponentContext > xContext) + : m_xContext(std::move(xContext)) +{ +} + +ONSSInitializer::ONSSInitializer() +{ +} + +namespace +{ + +//Older versions of Firefox (FF), for example FF2, and Thunderbird (TB) 2 write +//the roots certificate module (libnssckbi.so), which they use, into the +//profile. This module will then already be loaded during NSS_Init (and the +//other init functions). This fails in two cases. First, FF3 was used to create +//the profile, or possibly used that profile before, and second the profile was +//used on a different platform. +// +//Then one needs to add the roots module oneself. This should be done with +//SECMOD_LoadUserModule rather than SECMOD_AddNewModule. The latter would write +//the location of the roots module to the profile, which makes FF2 and TB2 use +//it instead of their own module. +// +//When using SYSTEM_NSS then the libnss3.so lib is typically found in /usr/lib. +//This folder may, however, NOT contain the roots certificate module. That is, +//just providing the library name in SECMOD_LoadUserModule or +//SECMOD_AddNewModule will FAIL to load the mozilla unless the LD_LIBRARY_PATH +//contains an FF or TB installation. +//ATTENTION: DO NOT call this function directly instead use initNSS +//return true - whole initialization was successful +//param out_nss_init = true: at least the NSS initialization (NSS_InitReadWrite +//was successful and therefore NSS_Shutdown should be called when terminating. +bool nsscrypto_initialize(css::uno::Reference 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 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 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(aStr.getStr()), + nullptr, // no parent + PR_FALSE); // do not recurse + + if (RootsModule) + { + + bool found = RootsModule->loaded; + + SECMOD_DestroyModule(RootsModule); + RootsModule = nullptr; + if (found) + SAL_INFO("xmlsecurity.xmlsec", "Added new root certificate module " ROOT_CERTS " contained in " << ospath); + else + { + SAL_INFO("xmlsecurity.xmlsec", "FAILED to load the new root certificate module " ROOT_CERTS "contained in " << ospath); + return_value = false; + } + } + else + { + SAL_INFO("xmlsecurity.xmlsec", "FAILED to add new root certificate module " ROOT_CERTS " contained in " << ospath); + return_value = false; + + } + } + else + { + SAL_INFO("xmlsecurity.xmlsec", "Adding new root certificate module failed."); + return_value = false; + } + } + + return return_value; +#else + return true; +#endif +} + +} // namespace + +// must be extern "C" because we pass the function pointer to atexit +extern "C" void nsscrypto_finalize() +{ + SECMODModule *RootsModule = SECMOD_FindModule(ROOT_CERTS); + + if (RootsModule) + { + + if (SECSuccess == SECMOD_UnloadUserModule(RootsModule)) + { + SAL_INFO("xmlsecurity.xmlsec", "Unloaded module \"" ROOT_CERTS "\"."); + } + else + { + SAL_INFO("xmlsecurity.xmlsec", "Failed unloading module \"" ROOT_CERTS "\"."); + } + SECMOD_DestroyModule(RootsModule); + } + else + { + SAL_INFO("xmlsecurity.xmlsec", "Unloading module \"" ROOT_CERTS "\" failed because it was not found."); + } + PK11_LogoutAll(); + (void)NSS_Shutdown(); + + (*getInitNSSPrivate())->reset(); +} + + +ONSSInitializer::~ONSSInitializer() +{ +} + +bool ONSSInitializer::initNSS( const css::uno::Reference< css::uno::XComponentContext > &rxContext ) +{ + static bool gbInitialized = [&rxContext]() + { + bool bNSSInit = false; + bool bInitialized = nsscrypto_initialize( rxContext, bNSSInit ); + if (bNSSInit) + atexit(nsscrypto_finalize); + return bInitialized; + }(); + return gbInitialized; +} + +css::uno::Reference< css::xml::crypto::XDigestContext > SAL_CALL ONSSInitializer::getDigestContext( ::sal_Int32 nDigestID, const css::uno::Sequence< css::beans::NamedValue >& aParams ) +{ + SECOidTag nNSSDigestID = SEC_OID_UNKNOWN; + sal_Int32 nDigestLength = 0; + bool b1KData = false; + if ( nDigestID == css::xml::crypto::DigestID::SHA256 + || nDigestID == css::xml::crypto::DigestID::SHA256_1K ) + { + nNSSDigestID = SEC_OID_SHA256; + nDigestLength = 32; + b1KData = ( nDigestID == css::xml::crypto::DigestID::SHA256_1K ); + } + else if ( nDigestID == css::xml::crypto::DigestID::SHA1 + || nDigestID == css::xml::crypto::DigestID::SHA1_1K ) + { + nNSSDigestID = SEC_OID_SHA1; + nDigestLength = 20; + b1KData = ( nDigestID == css::xml::crypto::DigestID::SHA1_1K ); + } + else if ( nDigestID == css::xml::crypto::DigestID::SHA512 + || nDigestID == css::xml::crypto::DigestID::SHA512_1K ) + { + nNSSDigestID = SEC_OID_SHA512; + nDigestLength = 64; + b1KData = ( nDigestID == css::xml::crypto::DigestID::SHA512_1K ); + } + else + throw css::lang::IllegalArgumentException("Unexpected digest requested.", css::uno::Reference< css::uno::XInterface >(), 1 ); + + if ( aParams.hasElements() ) + throw css::lang::IllegalArgumentException("Unexpected arguments provided for digest creation.", css::uno::Reference< css::uno::XInterface >(), 2 ); + + css::uno::Reference< css::xml::crypto::XDigestContext > xResult; + if( initNSS( m_xContext ) ) + { + PK11Context* pContext = PK11_CreateDigestContext( nNSSDigestID ); + if ( pContext && PK11_DigestBegin( pContext ) == SECSuccess ) + xResult = new ODigestContext( pContext, nDigestLength, b1KData ); + } + + return xResult; +} + +css::uno::Reference< css::xml::crypto::XCipherContext > SAL_CALL ONSSInitializer::getCipherContext( ::sal_Int32 nCipherID, const css::uno::Sequence< ::sal_Int8 >& aKey, const css::uno::Sequence< ::sal_Int8 >& aInitializationVector, sal_Bool bEncryption, const css::uno::Sequence< css::beans::NamedValue >& aParams ) +{ + CK_MECHANISM_TYPE nNSSCipherID = 0; + bool bW3CPadding = false; + switch (nCipherID) + { + case css::xml::crypto::CipherID::AES_CBC_W3C_PADDING: + nNSSCipherID = CKM_AES_CBC; + bW3CPadding = true; + break; + case css::xml::crypto::CipherID::AES_GCM_W3C: + nNSSCipherID = CKM_AES_GCM; + break; + default: + throw css::lang::IllegalArgumentException("Unexpected cipher requested.", css::uno::Reference< css::uno::XInterface >(), 1); + } + + if ( aKey.getLength() != 16 && aKey.getLength() != 24 && aKey.getLength() != 32 ) + throw css::lang::IllegalArgumentException("Unexpected key length.", css::uno::Reference< css::uno::XInterface >(), 2 ); + + if ( aParams.hasElements() ) + throw css::lang::IllegalArgumentException("Unexpected arguments provided for cipher creation.", css::uno::Reference< css::uno::XInterface >(), 5 ); + + css::uno::Reference< css::xml::crypto::XCipherContext > xResult; + if( initNSS( m_xContext ) ) + { + if ( aInitializationVector.getLength() != PK11_GetIVLength( nNSSCipherID ) ) + throw css::lang::IllegalArgumentException("Unexpected length of initialization vector.", css::uno::Reference< css::uno::XInterface >(), 3 ); + + xResult = OCipherContext::Create( nNSSCipherID, aKey, aInitializationVector, bEncryption, bW3CPadding ); + assert(xResult.is()); + } + + return xResult; +} + +/* XServiceInfo */ +OUString SAL_CALL ONSSInitializer::getImplementationName() +{ + return "com.sun.star.xml.crypto.NSSInitializer"; +} + +sal_Bool SAL_CALL ONSSInitializer::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +cssu::Sequence< OUString > SAL_CALL ONSSInitializer::getSupportedServiceNames( ) +{ + return { NSS_SERVICE_NAME }; +} + +#ifndef XMLSEC_CRYPTO_NSS +extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface* +com_sun_star_xml_crypto_NSSInitializer_get_implementation( + uno::XComponentContext* pCtx, uno::Sequence const& /*rSeq*/) +{ + return cppu::acquire(new ONSSInitializer(pCtx)); +} +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/nssinitializer.hxx b/xmlsecurity/source/xmlsec/nss/nssinitializer.hxx new file mode 100644 index 0000000000..c461dd5c97 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/nssinitializer.hxx @@ -0,0 +1,68 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include +#include + +#include + +namespace com::sun::star::uno { class XComponentContext; } + +inline constexpr OUString NSS_SERVICE_NAME = u"com.sun.star.xml.crypto.NSSInitializer"_ustr; + +class ONSSInitializer : public cppu::WeakImplHelper +< + css::xml::crypto::XNSSInitializer, + css::lang::XServiceInfo +> +{ +protected: + css::uno::Reference< css::uno::XComponentContext > m_xContext; + static OUString m_sNSSPath; + static bool m_bIsNSSinitialized; + + ONSSInitializer(); + +public: + explicit ONSSInitializer(css::uno::Reference xContext); + virtual ~ONSSInitializer() override; + + static bool initNSS( const css::uno::Reference< css::uno::XComponentContext > &rxContext ); + static const OUString & getMozillaCurrentProfile(const css::uno::Reference< css::uno::XComponentContext > &rxContext, bool bSetActive = false); + + /* XNSSInitializer */ + virtual OUString SAL_CALL getNSSPath() override; + virtual sal_Bool SAL_CALL getIsNSSinitialized() override; + virtual css::uno::Sequence SAL_CALL getNSSProfiles() override; + + /* XDigestContextSupplier */ + virtual css::uno::Reference< css::xml::crypto::XDigestContext > SAL_CALL getDigestContext( ::sal_Int32 nDigestID, const css::uno::Sequence< css::beans::NamedValue >& aParams ) override; + + /* XCipherContextSupplier */ + virtual css::uno::Reference< css::xml::crypto::XCipherContext > SAL_CALL getCipherContext( ::sal_Int32 nCipherID, const css::uno::Sequence< ::sal_Int8 >& aKey, const css::uno::Sequence< ::sal_Int8 >& aInitializationVector, sal_Bool bEncryption, const css::uno::Sequence< css::beans::NamedValue >& aParams ) override; + + /* XServiceInfo */ + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/nssrenam.h b/xmlsecurity/source/xmlsec/nss/nssrenam.h new file mode 100644 index 0000000000..47280408b7 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/nssrenam.h @@ -0,0 +1,41 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 2001 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +#pragma once + +#define CERT_NewTempCertificate __CERT_NewTempCertificate +#define PK11_GetKeyData __PK11_GetKeyData +#define CERT_DecodeDERCertificate __CERT_DecodeDERCertificate + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/sanextension_nssimpl.cxx b/xmlsecurity/source/xmlsec/nss/sanextension_nssimpl.cxx new file mode 100644 index 0000000000..1395cb2e8a --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/sanextension_nssimpl.cxx @@ -0,0 +1,164 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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(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(); + + 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(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(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(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(m_Entries); +} + +OString SanExtensionImpl::removeOIDFromString( const OString &oidString) +{ + OString objID; + constexpr std::string_view oid("OID."); + if (oidString.match(oid)) + objID = oidString.copy(oid.size()); + else + objID = oidString; + return objID; + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/sanextension_nssimpl.hxx b/xmlsecurity/source/xmlsec/nss/sanextension_nssimpl.hxx new file mode 100644 index 0000000000..3716d414e5 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/sanextension_nssimpl.hxx @@ -0,0 +1,65 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +class SanExtensionImpl : public ::cppu::WeakImplHelper< + css::security::XSanExtension > +{ + private: + CertificateExtension_CertExtn m_Extn; + std::vector m_Entries; + + static OString removeOIDFromString( const OString &oid); + + public: + //Methods from XCertificateExtension + virtual sal_Bool SAL_CALL isCritical() override + { + return m_Extn.m_critical; + } + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getExtensionId() override + { + return m_Extn.m_xExtnId; + } + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getExtensionValue() override + { + return m_Extn.m_xExtnValue; + } + + void setCertExtn(unsigned char const * value, unsigned int vlen, unsigned char const * id, unsigned int idlen, bool critical) + { + m_Extn.setCertExtn(value, vlen, id, idlen, critical); + } + + //Methods from XSanExtension + + virtual css::uno::Sequence< css::security::CertAltNameEntry > SAL_CALL getAlternativeNames() override ; +} ; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/secerror.cxx b/xmlsecurity/source/xmlsec/nss/secerror.cxx new file mode 100644 index 0000000000..b7e623ce00 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/secerror.cxx @@ -0,0 +1,152 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include +#include "secerror.hxx" +#include +#include +#include + +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(-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(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(node->arg); + switch (errorFlags) + { + case NS_CERT_TYPE_SSL_CLIENT: + case NS_CERT_TYPE_SSL_SERVER: + specificError = "Certificate cannot be used for SSL."; + break; + case NS_CERT_TYPE_SSL_CA: + specificError = "Certificate cannot be used as an SSL CA."; + break; + case NS_CERT_TYPE_EMAIL: + specificError = "Certificate cannot be used for SMIME."; + break; + case NS_CERT_TYPE_EMAIL_CA: + specificError = "Certificate cannot be used as an SMIME CA."; + break; + case NS_CERT_TYPE_OBJECT_SIGNING: + specificError = "Certificate cannot be used for object signing."; + break; + case NS_CERT_TYPE_OBJECT_SIGNING_CA: + specificError = "Certificate cannot be used as an object signing CA."; + break; + default: + specificError = "[unknown usage]."; + break; + } + break; + case SEC_ERROR_UNKNOWN_ISSUER: + specificError = "Unknown issuer:"; + issuer = node->cert->issuerName; + break; + case SEC_ERROR_UNTRUSTED_ISSUER: + specificError = "Untrusted issuer:"; + issuer = node->cert->issuerName; + break; + case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE: + specificError = "Expired issuer certificate:"; + issuer = node->cert->issuerName; + break; + default: + break; + } + if (specificError) + SAL_INFO("xmlsecurity.xmlsec", specificError); + if (issuer) + SAL_INFO("xmlsecurity.xmlsec", issuer); + } + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/secerror.hxx b/xmlsecurity/source/xmlsec/nss/secerror.hxx new file mode 100644 index 0000000000..bd59078262 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/secerror.hxx @@ -0,0 +1,31 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include + +#include +#include + +const char* getCertError(PRErrorCode errNum); + +void printChainFailure(CERTVerifyLog* log); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.cxx b/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.cxx new file mode 100644 index 0000000000..2ab5b011e2 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.cxx @@ -0,0 +1,878 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "nssrenam.h" +#include +#include +#include + +#include +#include +#include +#include "securityenvironment_nssimpl.hxx" +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "x509certificate_nssimpl.hxx" +#include "secerror.hxx" +#include +#include + +// added for password exception +#include +#include +#include + +namespace csss = ::com::sun::star::security; +using namespace ::com::sun::star::security; +using namespace com::sun::star; +using namespace ::com::sun::star::uno ; +using namespace ::com::sun::star::lang ; + +using ::com::sun::star::security::XCertificate ; + +namespace std +{ +template <> struct default_delete +{ + void operator()(PRArenaPool* ptr) { PORT_FreeArena(ptr, PR_FALSE); } +}; +} + +static rtl::Reference NssCertToXCert( CERTCertificate* cert ) ; +static rtl::Reference 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(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 seqServiceNames{ "com.sun.star.xml.crypto.SecurityEnvironment" }; + return seqServiceNames; +} + +OUString SecurityEnvironment_NssImpl::getSecurityEnvironmentInformation() +{ + OUStringBuffer buff; + for (auto& slot : m_Slots) + { + buff.appendAscii(PK11_GetTokenName(slot)); + buff.append("\n"); + } + return buff.makeStringAndClear(); +} + +void SecurityEnvironment_NssImpl::addCryptoSlot( PK11SlotInfo* aSlot) +{ + PK11_ReferenceSlot(aSlot); + m_Slots.push_back(aSlot); +} + +//Could we have multiple cert dbs? +void SecurityEnvironment_NssImpl::setCertDb( CERTCertDBHandle* aCertDb ) { + m_pHandler = aCertDb ; +} + +void SecurityEnvironment_NssImpl::adoptSymKey( PK11SymKey* aSymKey ) { + if( aSymKey == nullptr ) return; + + //First try to find the key in the list + if (std::find(m_tSymKeyList.begin(), m_tSymKeyList.end(), aSymKey) != m_tSymKeyList.end()) + return; + + //If we do not find the key in the list, add a new node + PK11SymKey* symkey = PK11_ReferenceSymKey( aSymKey ) ; + if( symkey == nullptr ) + throw RuntimeException() ; + + try { + m_tSymKeyList.push_back( symkey ) ; + } catch ( Exception& ) { + PK11_FreeSymKey( symkey ) ; + } +} + +void SecurityEnvironment_NssImpl::updateSlots() +{ + //In case new tokens are present then we can obtain the corresponding slot + std::scoped_lock guard(m_mutex); + + m_Slots.clear(); + m_tSymKeyList.clear(); + + PK11SlotList * slotList = PK11_GetAllTokens( CKM_INVALID_MECHANISM, PR_FALSE, PR_FALSE, nullptr ) ; + if( slotList == nullptr ) + return; + + for (PK11SlotListElement* slotEle = slotList->head ; slotEle != nullptr; slotEle = slotEle->next) + { + PK11SlotInfo * pSlot = slotEle->slot ; + + if(pSlot != nullptr) + { + SAL_INFO( + "xmlsecurity.xmlsec", + "Found a slot: SlotName=" << PK11_GetSlotName(pSlot) + << ", TokenName=" << PK11_GetTokenName(pSlot)); + +//The following code which is commented out checks if a slot, that is a smart card for example, is +// able to generate a symmetric key of type CKM_DES3_CBC. If this fails then this token +// will not be used. This key is possibly used for the encryption service. However, all +// interfaces and services used for public key signature and encryption are not published +// and the encryption is not used in OOo. Therefore it does not do any harm to remove +// this code, hence allowing smart cards which cannot generate this type of key. +// +// By doing this, the encryption may fail if a smart card is being used which does not +// support this key generation. +// + PK11SymKey * pSymKey = PK11_KeyGen( pSlot , CKM_DES3_CBC, nullptr, 128, nullptr ) ; +// if( pSymKey == NULL ) +// { +// PK11_FreeSlot( pSlot ) ; +// SAL_INFO( "xmlsecurity", "XMLSEC: Error - pSymKey is NULL" ); +// continue; +// } + addCryptoSlot(pSlot); + + if (pSymKey != nullptr) + { + adoptSymKey( pSymKey ) ; + PK11_FreeSymKey( pSymKey ) ; + pSymKey = nullptr; + } + + }// end of if(pSlot != NULL) + }// end of for + + PK11_FreeSlotList(slotList); +} + +Sequence< Reference < XCertificate > > +SecurityEnvironment_NssImpl::getPersonalCertificates() +{ + std::vector< rtl::Reference > 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 xcert = NssPrivKeyToXCert( curPri->key ) ; + if( xcert != nullptr ) + certsList.push_back( xcert ) ; + } + SECKEY_DestroyPrivateKeyList( priKeyList ) ; + } + + + } + + if( certsList.size() != 0 ) { + return comphelper::containerToSequence>(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 xcert; + CERTIssuerAndSN issuerAndSN ; + CERTCertificate* cert ; + CERTName* nmIssuer ; + char* chIssuer ; + SECItem* derIssuer ; + std::unique_ptr 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(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(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(const_cast(serialNumber.getConstArray())); + issuerAndSN.serialNumber.len = serialNumber.getLength() ; + + cert = CERT_FindCertByIssuerAndSN( m_pHandler, &issuerAndSN ) ; + if( cert != nullptr ) { + xcert = NssCertToXCert( cert ) ; + } + + PL_strfree( chIssuer ) ; + CERT_DestroyName( nmIssuer ) ; + //SECITEM_FreeItem( derIssuer, PR_FALSE ) ; + CERT_DestroyCertificate( cert ) ; + + return xcert ; +} + +Sequence< Reference < XCertificate > > SecurityEnvironment_NssImpl::buildCertificatePath( const Reference< XCertificate >& begin ) { + + X509Certificate_NssImpl* xcert = dynamic_cast(begin.get()); + if( xcert == nullptr ) { + throw RuntimeException() ; + } + + // Remember the signing certificate. + m_xSigningCertificate = xcert; + + const CERTCertificate* cert = xcert->getNssCert() ; + if (!cert) + return {}; + + //Get the system clock time + int64 timeboundary = PR_Now() ; + CERTCertList* certChain = CERT_GetCertChainFromCert( const_cast(cert), timeboundary, certUsageAnyCA ) ; + + if( !certChain ) + return {}; + + std::vector> aCertChain; + + for (CERTCertListNode* node = CERT_LIST_HEAD(certChain); !CERT_LIST_END(node, certChain); node = CERT_LIST_NEXT(node)) { + rtl::Reference 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 SecurityEnvironment_NssImpl::createAndAddCertificateFromPackage( + const css::uno::Sequence& raDERCertificate, + std::u16string_view raString) +{ + auto pCertificateBytes = reinterpret_cast(const_cast(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 pX509Certificate = new X509Certificate_NssImpl(); + pX509Certificate->setCert(pCERTCertificate); + return pX509Certificate; +} + +rtl::Reference SecurityEnvironment_NssImpl::createX509CertificateFromDER(const css::uno::Sequence& aDerCertificate) +{ + rtl::Reference pX509Certificate; + + if (aDerCertificate.hasElements()) + { + pX509Certificate = new X509Certificate_NssImpl(); + if (pX509Certificate == nullptr) + throw RuntimeException(); + pX509Certificate->setRawCert(aDerCertificate); + } + return pX509Certificate; +} + +Reference 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(oscert.getStr()), static_cast(oscert.getLength()) ) ; + xmlSecSize certSize; + int nRet = xmlSecBase64Decode_ex( chCert, reinterpret_cast(chCert), xmlStrlen( chCert ), &certSize ) ; + if (nRet < 0 || certSize == 0) + { + xmlFree(chCert); + return nullptr; + } + + Sequence< sal_Int8 > rawCert(comphelper::arrayToSequence(chCert, certSize)) ; + + xmlFree( chCert ) ; + + return createCertificateFromRaw( rawCert ) ; +} + +sal_Int32 SecurityEnvironment_NssImpl :: +verifyCertificate( const Reference< csss::XCertificate >& aCert, + const Sequence< Reference< csss::XCertificate > >& intermediateCerts ) +{ + sal_Int32 validity = csss::CertificateValidity::INVALID; + const CERTCertificate* cert ; + + SAL_INFO("xmlsecurity.xmlsec", "Start verification of certificate: " << aCert->getSubjectName()); + + const X509Certificate_NssImpl* xcert = dynamic_cast(aCert.get()); + if( xcert == nullptr ) { + throw RuntimeException() ; + } + + //CERT_PKIXVerifyCert does not take a db as argument. It will therefore + //internally use CERT_GetDefaultCertDB + //Make sure m_pHandler is the default DB + OSL_ASSERT(m_pHandler == CERT_GetDefaultCertDB()); + CERTCertDBHandle * certDb = m_pHandler != nullptr ? m_pHandler : CERT_GetDefaultCertDB(); + cert = xcert->getNssCert() ; + if( !cert ) + return css::security::CertificateValidity::INVALID; + + + ::std::vector vecTmpNSSCertificates; + + //prepare the intermediate certificates + for (const auto& rIntermediateCert : intermediateCerts) + { + Sequence der = rIntermediateCert->getEncoded(); + SECItem item; + item.type = siBuffer; + item.data = reinterpret_cast(der.getArray()); + item.len = der.getLength(); + + CERTCertificate* certTmp = CERT_NewTempCertificate(certDb, &item, + nullptr /* nickname */, + PR_FALSE /* isPerm */, + PR_TRUE /* copyDER */); + if (!certTmp) + { + SAL_INFO("xmlsecurity.xmlsec", "Failed to add a temporary certificate: " << rIntermediateCert->getIssuerName()); + + } + else + { + SAL_INFO("xmlsecurity.xmlsec", "Added temporary certificate: " << + (certTmp->subjectName ? certTmp->subjectName : "")); + vecTmpNSSCertificates.push_back(certTmp); + } + } + + + SECStatus status ; + + CERTVerifyLog log; + log.arena = PORT_NewArena(512); + log.head = log.tail = nullptr; + log.count = 0; + + CERT_EnableOCSPChecking(certDb); + CERT_DisableOCSPDefaultResponder(certDb); + CERTValOutParam cvout[5]; + CERTValInParam cvin[3]; + int ncvinCount=0; + +#if ( NSS_VMAJOR > 3 ) || ( NSS_VMAJOR == 3 && NSS_VMINOR > 12 ) || ( NSS_VMAJOR == 3 && NSS_VMINOR == 12 && NSS_VPATCH > 0 ) + cvin[ncvinCount].type = cert_pi_useAIACertFetch; + cvin[ncvinCount].value.scalar.b = PR_TRUE; + ncvinCount++; +#endif + + PRUint64 revFlagsLeaf[2]; + PRUint64 revFlagsChain[2]; + CERTRevocationFlags rev; + rev.leafTests.number_of_defined_methods = 2; + rev.leafTests.cert_rev_flags_per_method = revFlagsLeaf; + //the flags are defined in cert.h + //We check both leaf and chain. + //It is enough if one revocation method has fresh info, + //but at least one must have some. Otherwise validation fails. + //!!! using leaf test and CERT_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE + // when validating a root certificate will result in "revoked". Usually + //there is no revocation information available for the root cert because + //it must be trusted anyway and it does itself issue revocation information. + //When we use the flag here and OOo shows the certification path then the root + //cert is invalid while all other can be valid. It would probably best if + //this interface method returned the whole chain. + //Otherwise we need to check if the certificate is self-signed and if it is + //then not use the flag when doing the leaf-test. + rev.leafTests.cert_rev_flags_per_method[cert_revocation_method_crl] = + CERT_REV_M_TEST_USING_THIS_METHOD + | CERT_REV_M_IGNORE_IMPLICIT_DEFAULT_SOURCE; + rev.leafTests.cert_rev_flags_per_method[cert_revocation_method_ocsp] = + CERT_REV_M_TEST_USING_THIS_METHOD + | CERT_REV_M_IGNORE_IMPLICIT_DEFAULT_SOURCE; + rev.leafTests.number_of_preferred_methods = 0; + rev.leafTests.preferred_methods = nullptr; + rev.leafTests.cert_rev_method_independent_flags = + CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST; + + rev.chainTests.number_of_defined_methods = 2; + rev.chainTests.cert_rev_flags_per_method = revFlagsChain; + rev.chainTests.cert_rev_flags_per_method[cert_revocation_method_crl] = + CERT_REV_M_TEST_USING_THIS_METHOD + | CERT_REV_M_IGNORE_IMPLICIT_DEFAULT_SOURCE; + rev.chainTests.cert_rev_flags_per_method[cert_revocation_method_ocsp] = + CERT_REV_M_TEST_USING_THIS_METHOD + | CERT_REV_M_IGNORE_IMPLICIT_DEFAULT_SOURCE; + rev.chainTests.number_of_preferred_methods = 0; + rev.chainTests.preferred_methods = nullptr; + rev.chainTests.cert_rev_method_independent_flags = + CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST; + + + cvin[ncvinCount].type = cert_pi_revocationFlags; + cvin[ncvinCount].value.pointer.revocation = &rev; + ncvinCount++; + // does not work, not implemented yet in 3.12.4 +// cvin[ncvinCount].type = cert_pi_keyusage; +// cvin[ncvinCount].value.scalar.ui = KU_DIGITAL_SIGNATURE; +// ncvinCount++; + cvin[ncvinCount].type = cert_pi_end; + + cvout[0].type = cert_po_trustAnchor; + cvout[0].value.pointer.cert = nullptr; + cvout[1].type = cert_po_errorLog; + cvout[1].value.pointer.log = &log; + cvout[2].type = cert_po_end; + + // We check SSL server certificates, CA certificates and signing certificates. + // + // ToDo check keyusage, looking at CERT_KeyUsageAndTypeForCertUsage ( + // mozilla/security/nss/lib/certdb/certdb.c indicates that + // certificateUsageSSLClient, certificateUsageSSLServer and certificateUsageSSLCA + // are sufficient. They cover the key usages for digital signature, key agreement + // and encipherment and certificate signature + + //never use the following usages because they are not checked properly + // certificateUsageUserCertImport + // certificateUsageVerifyCA + // certificateUsageAnyCA + // certificateUsageProtectedObjectSigner + + UsageDescription arUsages[5]; + arUsages[0] = UsageDescription( certificateUsageSSLClient, "certificateUsageSSLClient" ); + arUsages[1] = UsageDescription( certificateUsageSSLServer, "certificateUsageSSLServer" ); + arUsages[2] = UsageDescription( certificateUsageSSLCA, "certificateUsageSSLCA" ); + arUsages[3] = UsageDescription( certificateUsageEmailSigner, "certificateUsageEmailSigner" ); + arUsages[4] = UsageDescription( certificateUsageEmailRecipient, "certificateUsageEmailRecipient" ); + + int numUsages = std::size(arUsages); + for (int i = 0; i < numUsages; i++) + { + SAL_INFO("xmlsecurity.xmlsec", "Testing usage " << i+1 << + " of " << numUsages << ": " << + arUsages[i].description << + " (0x" << std::hex << static_cast(arUsages[i].usage) << ")" << std::dec); + + status = CERT_PKIXVerifyCert(const_cast(cert), arUsages[i].usage, + cvin, cvout, nullptr); + if( status == SECSuccess ) + { + SAL_INFO("xmlsecurity.xmlsec", "CERT_PKIXVerifyCert returned SECSuccess."); + //When an intermediate or root certificate is checked then we expect the usage + //certificateUsageSSLCA. This, however, will be only set when in the trust settings dialog + //the button "This certificate can identify websites" is checked. If for example only + //"This certificate can identify mail users" is set then the end certificate can + //be validated and the returned usage will contain certificateUsageEmailRecipient. + //But checking directly the root or intermediate certificate will fail. In the + //certificate path view the end certificate will be shown as valid but the others + //will be displayed as invalid. + + validity = csss::CertificateValidity::VALID; + SAL_INFO("xmlsecurity.xmlsec", "Certificate is valid."); + CERTCertificate * issuerCert = cvout[0].value.pointer.cert; + if (issuerCert) + { + SAL_INFO("xmlsecurity.xmlsec", "Root certificate: " << issuerCert->subjectName); + CERT_DestroyCertificate(issuerCert); + }; + + break; + } + else + { + PRIntn err = PR_GetError(); + SAL_INFO("xmlsecurity.xmlsec", "Error: " << err << ": " << getCertError(err)); + + /* Display validation results */ + if ( log.count > 0) + { + CERTVerifyLogNode *node = nullptr; + printChainFailure(&log); + + for (node = log.head; node; node = node->next) { + if (node->cert) + CERT_DestroyCertificate(node->cert); + } + log.head = log.tail = nullptr; + log.count = 0; + } + SAL_INFO("xmlsecurity.xmlsec", "Certificate is invalid."); + } + } + + //Destroying the temporary certificates + for (auto& tmpCert : vecTmpNSSCertificates) + { + SAL_INFO("xmlsecurity.xmlsec", "Destroying temporary certificate"); + CERT_DestroyCertificate(tmpCert); + } + PORT_FreeArena(log.arena, true); + return validity ; +} + +sal_Int32 SecurityEnvironment_NssImpl::getCertificateCharacters( + const css::uno::Reference< css::security::XCertificate >& aCert ) { + sal_Int32 characters ; + const CERTCertificate* cert ; + + const X509Certificate_NssImpl* xcert = dynamic_cast(aCert.get()); + if( xcert == nullptr ) { + throw RuntimeException() ; + } + + cert = xcert->getNssCert() ; + + characters = 0x00000000 ; + + //Firstly, find out whether or not the cert is self-signed. + if( SECITEM_CompareItem( &(cert->derIssuer), &(cert->derSubject) ) == SECEqual ) { + characters |= css::security::CertificateCharacters::SELF_SIGNED ; + } else { + characters &= ~ css::security::CertificateCharacters::SELF_SIGNED ; + } + + //Secondly, find out whether or not the cert has a private key. + + /* + * i40394 + * + * mmi : need to check whether the cert's slot is valid first + */ + SECKEYPrivateKey* priKey = nullptr; + + if (cert->slot != nullptr) + { + priKey = PK11_FindPrivateKeyFromCert( cert->slot, const_cast(cert), nullptr ) ; + } + if(priKey == nullptr) + { + for (auto& slot : m_Slots) + { + priKey = PK11_FindPrivateKeyFromCert(slot, const_cast(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 NssCertToXCert( CERTCertificate* cert ) +{ + if( cert != nullptr ) { + rtl::Reference xcert = new X509Certificate_NssImpl() ; + xcert->setCert( cert ) ; + return xcert; + } + + return nullptr; +} + +rtl::Reference NssPrivKeyToXCert( SECKEYPrivateKey* priKey ) +{ + if( priKey != nullptr ) { + rtl::Reference 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 sarSlots(new PK11SlotInfo*[cSlots]); + PK11SlotInfo** slots = sarSlots.get(); + int count = 0; + for (const auto& slot : m_Slots) + { + slots[count] = slot; + ++count; + } + + xmlSecKeysMngrPtr pKeysMngr = xmlSecKeysMngrCreate(); + if (!pKeysMngr) + throw RuntimeException(); + + if (xmlSecNssAppDefaultKeysMngrInit(pKeysMngr) < 0) + throw RuntimeException(); + + // Adopt the private key of the signing certificate, if it has any. + if (m_xSigningCertificate) + { + SECKEYPrivateKey* pPrivateKey = SECKEY_CopyPrivateKey(m_xSigningCertificate->getPrivateKey()); + if (pPrivateKey) + { + xmlSecKeyDataPtr pKeyData = xmlSecNssPKIAdoptKey(pPrivateKey, nullptr); + xmlSecKeyPtr pKey = xmlSecKeyCreate(); + xmlSecKeySetValue(pKey, pKeyData); + xmlSecNssAppDefaultKeysMngrAdoptKey(pKeysMngr, pKey); + } + else + { + SAL_WARN("xmlsecurity.xmlsec", "Can't get the private key from the certificate."); + } + } + + return pKeysMngr; +} + +void SecurityEnvironment_NssImpl::destroyKeysManager(xmlSecKeysMngrPtr pKeysMngr) { + if( pKeysMngr != nullptr ) { + xmlSecKeysMngrDestroy( pKeysMngr ) ; + } +} + +SECKEYPrivateKey* SecurityEnvironment_NssImpl::insertPrivateKey(css::uno::Sequence const & raPrivateKey) +{ + PK11SlotInfo* pSlot = PK11_GetInternalKeySlot(); + + if (!pSlot) + return nullptr; + + SECItem aDerPrivateKeyInfo; + aDerPrivateKeyInfo.data = reinterpret_cast(const_cast(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 SecurityEnvironment_NssImpl::createDERCertificateWithPrivateKey( + Sequence const & raDERCertificate, Sequence const & raPrivateKey) +{ + SECKEYPrivateKey* pPrivateKey = insertPrivateKey(raPrivateKey); + + if (!pPrivateKey) + return uno::Reference(); + + return createAndAddCertificateFromPackage(raDERCertificate, u"TCu,TCu,TCu"); +} + +uno::Reference SecurityEnvironment_NssImpl::addDERCertificateToTheDatabase( + uno::Sequence 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 const& /*rSeq*/) +{ + return cppu::acquire(new SecurityEnvironment_NssImpl); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.hxx b/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.hxx new file mode 100644 index 0000000000..c0e4698998 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.hxx @@ -0,0 +1,139 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include + +#include +#include + +#include +#include + +#include + +namespace com::sun::star::security { class XCertificate; } +class X509Certificate_NssImpl; + +class SecurityEnvironment_NssImpl : public ::cppu::WeakImplHelper< + css::xml::crypto::XSecurityEnvironment, + css::xml::crypto::XCertificateCreator, + css::lang::XServiceInfo > +{ +private: + + std::vector< PK11SlotInfo* > m_Slots; + /// The last used certificate which has the private key for signing. + rtl::Reference m_xSigningCertificate; + + std::mutex m_mutex; + + CERTCertDBHandle* m_pHandler ; + std::vector< PK11SymKey* > m_tSymKeyList ; + + public: + SecurityEnvironment_NssImpl(); + virtual ~SecurityEnvironment_NssImpl() override; + + //Methods from XSecurityEnvironment + + //Methods from XServiceInfo + virtual OUString SAL_CALL getImplementationName() override ; + + virtual sal_Bool SAL_CALL supportsService( + const OUString& ServiceName + ) override ; + + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override ; + + virtual ::sal_Int32 SAL_CALL verifyCertificate( + const css::uno::Reference< + css::security::XCertificate >& xCert, + const css::uno::Sequence< + css::uno::Reference< css::security::XCertificate > > & + intermediateCerts) override ; + + virtual ::sal_Int32 SAL_CALL getCertificateCharacters( const css::uno::Reference< css::security::XCertificate >& xCert ) override ; + + virtual OUString SAL_CALL getSecurityEnvironmentInformation( ) override; + + /// @throws css::uno::Exception + /// @throws css::uno::RuntimeException + void setCertDb( CERTCertDBHandle* aCertDb ) ; + + /// @throws css::uno::Exception + /// @throws css::uno::RuntimeException + void adoptSymKey( PK11SymKey* aSymKey ) ; + + virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificate > > SAL_CALL getPersonalCertificates() override ; + virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificate > > SAL_CALL getAllCertificates() override + { return css::uno::Sequence< css::uno::Reference< css::security::XCertificate > >(); } + + virtual css::uno::Reference< css::security::XCertificate > SAL_CALL getCertificate( const OUString& issuerName, const css::uno::Sequence< sal_Int8 >& serialNumber ) override ; + + virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificate > > SAL_CALL buildCertificatePath( const css::uno::Reference< css::security::XCertificate >& beginCert ) override ; + + virtual css::uno::Reference< css::security::XCertificate > SAL_CALL createCertificateFromRaw( const css::uno::Sequence< sal_Int8 >& rawCertificate ) override ; + virtual css::uno::Reference< css::security::XCertificate > SAL_CALL createCertificateFromAscii( const OUString& asciiCertificate ) override ; + + // Methods of XCertificateCreator + css::uno::Reference SAL_CALL addDERCertificateToTheDatabase( + css::uno::Sequence const & raDERCertificate, + OUString const & raTrustString) override; + + css::uno::Reference SAL_CALL createDERCertificateWithPrivateKey( + css::uno::Sequence const & raDERCertificate, + css::uno::Sequence 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 createAndAddCertificateFromPackage( + const css::uno::Sequence& raDerCertificate, + std::u16string_view raString); + static SECKEYPrivateKey* insertPrivateKey(css::uno::Sequence const & raPrivateKey); + + static rtl::Reference createX509CertificateFromDER(const css::uno::Sequence& raDerCertificate); + + /// @throws css::uno::Exception + /// @throws css::uno::RuntimeException + void addCryptoSlot( PK11SlotInfo* aSlot ) ; +} ; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/seinitializer_nssimpl.cxx b/xmlsecurity/source/xmlsec/nss/seinitializer_nssimpl.cxx new file mode 100644 index 0000000000..6b5c3d6c5b --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/seinitializer_nssimpl.cxx @@ -0,0 +1,144 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include + +#include "seinitializer_nssimpl.hxx" +#include "securityenvironment_nssimpl.hxx" + +#include + + +using namespace com::sun::star; + + +SEInitializer_NssImpl::SEInitializer_NssImpl( const css::uno::Reference< css::uno::XComponentContext > &rxContext ) +{ + m_xContext = rxContext; +} + +SEInitializer_NssImpl::~SEInitializer_NssImpl() +{ +} + +/* XSEInitializer */ +uno::Reference< css::xml::crypto::XXMLSecurityContext > SAL_CALL + SEInitializer_NssImpl::createSecurityContext( const OUString& ) +{ + CERTCertDBHandle *pCertHandle = nullptr ; + + if( !initNSS( m_xContext ) ) + return nullptr; + + pCertHandle = CERT_GetDefaultCertDB() ; + + try + { + /* Build XML Security Context */ + uno::Reference< css::xml::crypto::XXMLSecurityContext > xSecCtx = css::xml::crypto::XMLSecurityContext::create( m_xContext ); + + uno::Reference< css::xml::crypto::XSecurityEnvironment > xSecEnv = css::xml::crypto::SecurityEnvironment::create( m_xContext ); + SecurityEnvironment_NssImpl* pSecEnv = dynamic_cast(xSecEnv.get()); + assert(pSecEnv && "can only succeed"); + pSecEnv->setCertDb(pCertHandle); + + sal_Int32 n = xSecCtx->addSecurityEnvironment(xSecEnv); + //originally the SecurityEnvironment with the internal slot was set as default + xSecCtx->setDefaultSecurityEnvironmentIndex( n ); + return xSecCtx; + } + catch( const uno::Exception& ) + { + //PK11_LogoutAll(); + //NSS_Shutdown(); + return nullptr; + } +} + +void SAL_CALL SEInitializer_NssImpl::freeSecurityContext( const uno::Reference< css::xml::crypto::XXMLSecurityContext >& ) +{ + /* + * because the security context will free all its content when it + * is destructed, so here no free process for the security context + * is needed. + */ + //PK11_LogoutAll(); + //NSS_Shutdown(); +} + +/* XServiceInfo */ +OUString SAL_CALL SEInitializer_NssImpl::getImplementationName( ) +{ + return "com.sun.star.xml.crypto.SEInitializer"; +} +sal_Bool SAL_CALL SEInitializer_NssImpl::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService( this, rServiceName ); +} +uno::Sequence< OUString > SAL_CALL SEInitializer_NssImpl::getSupportedServiceNames( ) +{ + return { "com.sun.star.xml.crypto.SEInitializer" }; +} + +namespace { + +class NSSInitializer_NssImpl : public SEInitializer_NssImpl +{ +public: + explicit NSSInitializer_NssImpl(const uno::Reference& xContext); + OUString SAL_CALL getImplementationName() override; + uno::Sequence SAL_CALL getSupportedServiceNames() override; +}; + +} + +NSSInitializer_NssImpl::NSSInitializer_NssImpl(const uno::Reference& xContext) + : SEInitializer_NssImpl(xContext) +{ +} + +OUString NSSInitializer_NssImpl::getImplementationName() +{ + return "com.sun.star.xml.crypto.NSSInitializer"; +} + +uno::Sequence 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 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 const& /*rSeq*/) +{ + return cppu::acquire(new SEInitializer_NssImpl(pCtx)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/seinitializer_nssimpl.hxx b/xmlsecurity/source/xmlsec/nss/seinitializer_nssimpl.hxx new file mode 100644 index 0000000000..f078f387af --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/seinitializer_nssimpl.hxx @@ -0,0 +1,55 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include + +#include + +#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 &rxContext); + virtual ~SEInitializer_NssImpl() override; + + /* XSEInitializer */ + virtual css::uno::Reference< css::xml::crypto::XXMLSecurityContext > + SAL_CALL createSecurityContext( const OUString& ) override; + + virtual void SAL_CALL freeSecurityContext( const css::uno::Reference< + css::xml::crypto::XXMLSecurityContext >& securityContext ) override; + + /* XServiceInfo */ + virtual OUString SAL_CALL getImplementationName( ) override; + + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx b/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx new file mode 100644 index 0000000000..e1526ea90d --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx @@ -0,0 +1,602 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "nssrenam.h" +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include "x509certificate_nssimpl.hxx" + +#include +#include + +#include "sanextension_nssimpl.hxx" +#include +#include +#include + +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(*( 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(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(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(m_pCert->subjectID.data, + m_pCert->subjectID.len) ; + } else { + return css::uno::Sequence< sal_Int8 >(); + } +} + +css::uno::Sequence< css::uno::Reference< css::security::XCertificateExtension > > SAL_CALL X509Certificate_NssImpl::getExtensions() { + if( m_pCert != nullptr && m_pCert->extensions != nullptr ) { + CERTCertExtension** extns ; + int len ; + + for( len = 0, extns = m_pCert->extensions; *extns != nullptr; len ++, extns ++ ) ; + css::uno::Sequence< css::uno::Reference< css::security::XCertificateExtension > > xExtns( len ) ; + auto xExtnsRange = asNonConstRange(xExtns); + + for( extns = m_pCert->extensions, len = 0; *extns != nullptr; extns ++, len ++ ) { + const SECItem id = (*extns)->id; + OString oidString(CERT_GetOidString(&id)); + + bool crit; + if( (*extns)->critical.data == nullptr ) + crit = false ; + else + crit = (*extns)->critical.data[0] == 0xFF; + + // remove "OID." prefix if existing + OString objID; + constexpr std::string_view oid("OID."); + if (oidString.match(oid)) + objID = oidString.copy(oid.size()); + else + objID = oidString; + + unsigned char* value = (*extns)->value.data; + unsigned int vlen = (*extns)->value.len; + unsigned char* objid = reinterpret_cast(const_cast(objID.getStr())); + unsigned int objidlen = objID.getLength(); + + if (objID == "2.5.29.17") + { + rtl::Reference pExtn = new SanExtensionImpl; + pExtn->setCertExtn(value, vlen, objid, objidlen, crit); + xExtnsRange[len] = pExtn ; + } + else + { + rtl::Reference 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(const_cast(oid.getConstArray())); + idItem.len = oid.getLength() ; + + css::uno::Reference 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 xSanImpl( + new SanExtensionImpl); + xSanImpl->setCertExtn(value, vlen, objid, objidlen, crit); + xExtn = xSanImpl.get(); + } + else + { + rtl::Reference 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(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(const_cast(rawCert.getConstArray())); + certItem.len = rawCert.getLength() ; + + cert = CERT_DecodeDERCertificate( &certItem, PR_TRUE, nullptr ) ; + if( cert == nullptr ) + throw css::uno::RuntimeException() ; + + if( m_pCert != nullptr ) { + CERT_DestroyCertificate( m_pCert ) ; + m_pCert = nullptr ; + } + + m_pCert = cert ; +} + +SECKEYPrivateKey* X509Certificate_NssImpl::getPrivateKey() +{ + if (m_pCert && m_pCert->slot) + { + SECKEYPrivateKey* pPrivateKey = PK11_FindPrivateKeyFromCert(m_pCert->slot, m_pCert, nullptr); + if (pPrivateKey) + return pPrivateKey; + pPrivateKey = PK11_FindKeyByDERCert(m_pCert->slot, m_pCert, nullptr); + if (pPrivateKey) + { + SAL_INFO("xmlsecurity.xmlsec", "fallback from PK11_FindPrivateKeyFromCert to PK11_FindKeyByDERCert needed"); + return pPrivateKey; + } + SAL_WARN("xmlsecurity.xmlsec", "X509Certificate_NssImpl::getPrivateKey() cannot find private key"); + } + return nullptr; +} + +static OUString getAlgorithmDescription(SECAlgorithmID const *aid) +{ + SECOidTag tag; + tag = SECOID_GetAlgorithmTag(aid); + + const char *pDesc = SECOID_FindOIDTagDescription(tag); + + return OUString::createFromAscii( pDesc ) ; +} + +static css::uno::Sequence< sal_Int8 > getThumbprint(CERTCertificate const *pCert, SECOidTag id) +{ + if( pCert != nullptr ) + { + SECStatus rv; + unsigned char fingerprint[32]; + int length = 0; + switch (id) + { + case SEC_OID_MD5: + length = MD5_LENGTH; + break; + case SEC_OID_SHA1: + length = SHA1_LENGTH; + break; + case SEC_OID_SHA256: + length = SHA256_LENGTH; + break; + default: + break; + } + + memset(fingerprint, 0, sizeof fingerprint); + rv = PK11_HashBuf(id, fingerprint, pCert->derCert.data, pCert->derCert.len); + if(rv == SECStatus::SECSuccess) + { + return comphelper::arrayToSequence(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(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 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 SAL_CALL X509Certificate_NssImpl::getSupportedServiceNames() { return { OUString() }; } + +namespace xmlsecurity { + +// based on some guesswork and: +// https://datatracker.ietf.org/doc/html/rfc1485 +// https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-certnametostra#CERT_X500_NAME_STR +// the main problem appears to be that in values " is escaped as "" vs. \" +static OUString CompatDNCryptoAPI(std::u16string_view rDN) +{ + OUStringBuffer buf(rDN.size()); + enum { DEFAULT, INVALUE, INQUOTE } state(DEFAULT); + for (size_t i = 0; i < rDN.size(); ++i) + { + if (state == DEFAULT) + { + buf.append(rDN[i]); + if (rDN[i] == '=') + { + if (rDN.size() == i+1) + { + break; // invalid? + } + else if (rDN[i+1] == '"') + { + buf.append(rDN[i+1]); + ++i; + state = INQUOTE; + } + else + { + state = INVALUE; + } + } + } + else if (state == INVALUE) + { + if (rDN[i] == '+' || rDN[i] == ',' || rDN[i] == ';') + { + state = DEFAULT; + } + buf.append(rDN[i]); + } + else + { + assert(state == INQUOTE); + if (rDN[i] == '"') + { + if (rDN.size() != i+1 && rDN[i+1] == '"') + { + buf.append(OUString::Concat("\\") + OUStringChar(rDN[i+1])); + ++i; + } + else + { + buf.append(rDN[i]); + state = DEFAULT; + } + } + else + { + buf.append(rDN[i]); + } + } + } + return buf.makeStringAndClear(); +} + +bool EqualDistinguishedNames( + std::u16string_view const rName1, std::u16string_view const rName2, + EqualMode const eMode) +{ + if (eMode == COMPAT_BOTH && !rName1.empty() && rName1 == rName2) + { // handle case where both need to be converted + return true; + } + CERTName *const pName1(CERT_AsciiToName(OUStringToOString(rName1, RTL_TEXTENCODING_UTF8).getStr())); + if (pName1 == nullptr) + { + return false; + } + CERTName *const pName2(CERT_AsciiToName(OUStringToOString(rName2, RTL_TEXTENCODING_UTF8).getStr())); + bool ret(false); + if (pName2) + { + ret = (CERT_CompareName(pName1, pName2) == SECEqual); + CERT_DestroyName(pName2); + } + if (!ret && eMode == COMPAT_2ND) + { + CERTName *const pName2Compat(CERT_AsciiToName(OUStringToOString( + CompatDNCryptoAPI(rName2), RTL_TEXTENCODING_UTF8).getStr())); + if (pName2Compat == nullptr) + { + CERT_DestroyName(pName1); + return false; + } + ret = CERT_CompareName(pName1, pName2Compat) == SECEqual; + CERT_DestroyName(pName2Compat); + } + CERT_DestroyName(pName1); + return ret; +} + +} // namespace xmlsecurity + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.hxx b/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.hxx new file mode 100644 index 0000000000..9ad50f12ba --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.hxx @@ -0,0 +1,97 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +class X509Certificate_NssImpl : public ::cppu::WeakImplHelper< + css::security::XCertificate , + css::lang::XServiceInfo > , public xmlsecurity::Certificate +{ + private: + CERTCertificate* m_pCert; + + public: + X509Certificate_NssImpl() ; + virtual ~X509Certificate_NssImpl() override ; + + //Methods from XCertificate + virtual sal_Int16 SAL_CALL getVersion( ) override ; + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSerialNumber( ) override ; + + virtual OUString SAL_CALL getIssuerName( ) override ; + virtual OUString SAL_CALL getSubjectName( ) override ; + + virtual css::util::DateTime SAL_CALL getNotValidBefore( ) override ; + virtual css::util::DateTime SAL_CALL getNotValidAfter( ) override ; + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getIssuerUniqueID( ) override ; + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSubjectUniqueID( ) override ; + + virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificateExtension > > SAL_CALL getExtensions( ) override ; + + virtual css::uno::Reference< css::security::XCertificateExtension > SAL_CALL findCertificateExtension( const css::uno::Sequence< sal_Int8 >& oid ) override ; + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getEncoded( ) override ; + + virtual OUString SAL_CALL getSubjectPublicKeyAlgorithm() override ; + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSubjectPublicKeyValue() override ; + + virtual OUString SAL_CALL getSignatureAlgorithm() override ; + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSHA1Thumbprint() override ; + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getMD5Thumbprint() override ; + virtual css::security::CertificateKind SAL_CALL getCertificateKind() override; + + virtual sal_Int32 SAL_CALL getCertificateUsage( ) override ; + + /// @see xmlsecurity::Certificate::getSHA256Thumbprint(). + virtual css::uno::Sequence getSHA256Thumbprint() override; + + /// @see xmlsecurity::Certificate::getSignatureMethodAlgorithm(). + virtual svl::crypto::SignatureMethodAlgorithm getSignatureMethodAlgorithm() override; + + //Helper methods + void setCert( CERTCertificate* cert ) ; + const CERTCertificate* getNssCert() const ; + + /// @throws css::uno::RuntimeException + void setRawCert( const css::uno::Sequence< sal_Int8 >& rawCert ) ; + SECKEYPrivateKey* getPrivateKey(); + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override; + virtual css::uno::Sequence SAL_CALL getSupportedServiceNames() override; +} ; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/xmlsecuritycontext_nssimpl.cxx b/xmlsecurity/source/xmlsec/nss/xmlsecuritycontext_nssimpl.cxx new file mode 100644 index 0000000000..9ccf0ab982 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/xmlsecuritycontext_nssimpl.cxx @@ -0,0 +1,150 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include +#include +#include +#include +#include + +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 +{ +private: + std::vector> m_vSecurityEnvironments; + + sal_Int32 m_nDefaultEnvIndex; + +public: + XMLSecurityContext_NssImpl(); + + //XXMLSecurityContext + virtual sal_Int32 SAL_CALL addSecurityEnvironment( + const uno::Reference& aSecurityEnvironment) override; + + virtual ::sal_Int32 SAL_CALL getSecurityEnvironmentNumber() override; + + virtual uno::Reference + SAL_CALL getSecurityEnvironmentByIndex(::sal_Int32 index) override; + + virtual uno::Reference + 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 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 const& /*rSeq*/) +{ + return cppu::acquire(new XMLSecurityContext_NssImpl); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/xmlsignature_nssimpl.cxx b/xmlsecurity/source/xmlsec/nss/xmlsignature_nssimpl.cxx new file mode 100644 index 0000000000..4c5cc4b418 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/xmlsignature_nssimpl.cxx @@ -0,0 +1,321 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include + +#include + +#include +#include +#include + +#include "securityenvironment_nssimpl.hxx" + +#include +#include + +#include +#include + +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 +{ + void operator()(xmlSecKeysMngrPtr ptr) { SecurityEnvironment_NssImpl::destroyKeysManager(ptr); } +}; +template <> struct default_delete +{ + void operator()(xmlSecDSigCtxPtr ptr) { xmlSecDSigCtxDestroy(ptr); } +}; +} + +namespace { + +class XMLSignature_NssImpl + : public ::cppu::WeakImplHelper +{ +public: + explicit XMLSignature_NssImpl(); + + //Methods from XXMLSignature + virtual uno::Reference SAL_CALL + generate(const uno::Reference& aTemplate, + const uno::Reference& aEnvironment) override; + + virtual uno::Reference SAL_CALL + validate(const uno::Reference& aTemplate, + const uno::Reference& aContext) override; + + //Methods from XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + + virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override; + + virtual uno::Sequence SAL_CALL getSupportedServiceNames() override; +}; + +} + +XMLSignature_NssImpl::XMLSignature_NssImpl() { +} + +/* XXMLSignature */ +Reference< XXMLSignatureTemplate > +SAL_CALL XMLSignature_NssImpl::generate( + const Reference< XXMLSignatureTemplate >& aTemplate , + const Reference< XSecurityEnvironment >& aEnvironment +) +{ + xmlNodePtr pNode = nullptr ; + + if( !aTemplate.is() ) + throw RuntimeException() ; + + if( !aEnvironment.is() ) + throw RuntimeException() ; + + //Get the xml node + Reference< XXMLElementWrapper > xElement = aTemplate->getTemplate() ; + if( !xElement.is() ) { + throw RuntimeException() ; + } + + XMLElementWrapper_XmlSecImpl* pElement + = dynamic_cast(xElement.get()); + if( pElement == nullptr ) { + throw RuntimeException() ; + } + + pNode = pElement->getNativeElement() ; + + //Get the stream/URI binding + Reference< XUriBinding > xUriBinding = aTemplate->getBinding() ; + if( xUriBinding.is() ) { + //Register the stream input callbacks into libxml2 + if( xmlRegisterStreamInputCallbacks( xUriBinding ) < 0 ) + throw RuntimeException() ; + } + + //Get Keys Manager + + // the key manager should be retrieved from SecurityEnvironment, instead of SecurityContext + SecurityEnvironment_NssImpl* pSecEnv + = dynamic_cast(aEnvironment.get()); + if( pSecEnv == nullptr ) + throw RuntimeException() ; + + setErrorRecorder(); + + std::unique_ptr pMngr(pSecEnv->createKeysManager()); + if( !pMngr ) { + throw RuntimeException() ; + } + + //Create Signature context + std::unique_ptr pDsigCtx(xmlSecDSigCtxCreate(pMngr.get())); + if( pDsigCtx == nullptr ) + { + //throw XMLSignatureException() ; + clearErrorRecorder(); + return aTemplate; + } + + //Sign the template + if( xmlSecDSigCtxSign( pDsigCtx.get() , pNode ) == 0 ) + { + if (pDsigCtx->status == xmlSecDSigStatusSucceeded) + aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED); + else + aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_UNKNOWN); + } + else + { + aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_UNKNOWN); + } + + //Unregistered the stream/URI binding + if( xUriBinding.is() ) + xmlUnregisterStreamInputCallbacks() ; + + clearErrorRecorder(); + return aTemplate ; +} + +/* XXMLSignature */ +Reference< XXMLSignatureTemplate > +SAL_CALL XMLSignature_NssImpl::validate( + const Reference< XXMLSignatureTemplate >& aTemplate , + const Reference< XXMLSecurityContext >& aSecurityCtx +) { + xmlNodePtr pNode = nullptr ; + //sal_Bool valid ; + + if( !aTemplate.is() ) + throw RuntimeException() ; + + if( !aSecurityCtx.is() ) + throw RuntimeException() ; + + //Get the xml node + Reference< XXMLElementWrapper > xElement = aTemplate->getTemplate() ; + if( !xElement.is() ) + throw RuntimeException() ; + + XMLElementWrapper_XmlSecImpl* pElement + = dynamic_cast(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 aEnvironment = aSecurityCtx->getSecurityEnvironmentByIndex(i); + + //Get Keys Manager + SecurityEnvironment_NssImpl* pSecEnv + = dynamic_cast(aEnvironment.get()); + if( pSecEnv == nullptr ) + throw RuntimeException() ; + + std::unique_ptr pMngr(pSecEnv->createKeysManager()); + if( !pMngr ) { + throw RuntimeException() ; + } + + //Create Signature context + std::unique_ptr 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(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(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 aServiceNames = getSupportedServiceNames(); + for (OUString const & rCurrentServiceName : aServiceNames) + { + if (rCurrentServiceName == rServiceName) + return true; + } + return false; +} + +/* XServiceInfo */ +Sequence 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 const& /*rSeq*/) +{ + return cppu::acquire(new XMLSignature_NssImpl); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/saxhelper.cxx b/xmlsecurity/source/xmlsec/saxhelper.cxx new file mode 100644 index 0000000000..ff576db496 --- /dev/null +++ b/xmlsecurity/source/xmlsec/saxhelper.cxx @@ -0,0 +1,364 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include + +#include + +#include +#include + +#include +#include + +#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(ostr.getStr()), static_cast(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(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(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(fullName) ) ; + fullName = nullptr ; + } + + if( attrs != nullptr ) + { + for( int i = 0 ; attrs[i] != nullptr ; ++i ) + { + xmlFree( const_cast(attrs[i]) ) ; + attrs[i] = nullptr ; + } + + xmlFree( static_cast(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(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(chars) ) ; + } +} + +/** + * XDocumentHandler -- preprocessing instruction + */ +void SAXHelper::processingInstruction( + std::u16string_view aTarget, + std::u16string_view aData ) +{ + xmlChar* target = nullptr ; + xmlChar* data = nullptr ; + + target = ous_to_xmlstr( aTarget ) ; + data = ous_to_xmlstr( aData ) ; + + m_pSaxHandler->processingInstruction( m_pParserCtxt , target , data ) ; + + if( target != nullptr ) + { + xmlFree( target ) ; + target = nullptr ; + } + + if( data != nullptr ) + { + xmlFree( data ) ; + data = nullptr ; + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/xmldocumentwrapper_xmlsecimpl.cxx b/xmlsecurity/source/xmlsec/xmldocumentwrapper_xmlsecimpl.cxx new file mode 100644 index 0000000000..918735d380 --- /dev/null +++ b/xmlsecurity/source/xmlsec/xmldocumentwrapper_xmlsecimpl.cxx @@ -0,0 +1,900 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include +#include +#include +#include +#include +#include "xmlelementwrapper_xmlsecimpl.hxx" +#include +#include + +#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()); + + 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 pAttributeList = new comphelper::AttributeList(); + + xmlNsPtr pNsDef = pNode->nsDef; + + while (pNsDef != nullptr) + { + const xmlChar* pNsPrefix = pNsDef->prefix; + const xmlChar* pNsHref = pNsDef->href; + + if (pNsDef->prefix == nullptr) + { + pAttributeList->AddAttribute( + STRXMLNS, + OUString::fromUtf8(reinterpret_cast(pNsHref))); + } + else + { + pAttributeList->AddAttribute( + STRXMLNS ":" + +OUString::fromUtf8(reinterpret_cast(pNsPrefix)), + OUString::fromUtf8(reinterpret_cast(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(pAttrName)); + } + else + { + ouAttrName = OUString::fromUtf8(reinterpret_cast(pAttrNs->prefix)) + + ":" + OUString::fromUtf8(reinterpret_cast(pAttrName)); + } + + pAttributeList->AddAttribute( + ouAttrName, + OUString::fromUtf8(reinterpret_cast(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(pNode->content))); + } + + xHandler2->characters(OUString::fromUtf8(reinterpret_cast(pNode->content))); + } + else if (type == XML_PI_NODE) + { + if (xHandler.is()) + { + xHandler->processingInstruction( + OUString::fromUtf8(reinterpret_cast(pNode->name)), + OUString::fromUtf8(reinterpret_cast(pNode->content))); + } + + xHandler2->processingInstruction( + OUString::fromUtf8(reinterpret_cast(pNode->name)), + OUString::fromUtf8(reinterpret_cast(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(pNode->name)); + if (pNode->ns != nullptr) + { + xmlNsPtr pNs = pNode->ns; + + if (pNs->prefix != nullptr) + { + OString sPrefix(reinterpret_cast(pNs->prefix)); + sNodeName = sPrefix + ":" + sNodeName; + } + } + + return sNodeName; +} + +xmlNodePtr XMLDocumentWrapper_XmlSecImpl::checkElement( const uno::Reference< css::xml::wrapper::XXMLElementWrapper >& xXMLElement) +/****** XMLDocumentWrapper_XmlSecImpl/checkElement **************************** + * + * NAME + * checkElement -- Retrieves the node wrapped by an XXMLElementWrapper + * interface + * + * INPUTS + * xXMLElement - the XXMLElementWrapper interface wrapping a node + * + * RESULT + * node - the node wrapped in the XXMLElementWrapper interface + ******************************************************************************/ +{ + xmlNodePtr rc = nullptr; + + if (xXMLElement.is()) + { + XMLElementWrapper_XmlSecImpl* pElement + = dynamic_cast(xXMLElement.get()); + + if( pElement == nullptr ) { + throw uno::RuntimeException() ; + } + + rc = pElement->getNativeElement(); + } + + return rc; +} + +sal_Int32 XMLDocumentWrapper_XmlSecImpl::recursiveDelete( + const xmlNodePtr pNode) +/****** XMLDocumentWrapper_XmlSecImpl/recursiveDelete ************************* + * + * NAME + * recursiveDelete -- Deletes a particular node with its branch. + * + * FUNCTION + * Deletes a particular node with its branch, while reserving the nodes + * (and their branches) listed in the m_aReservedNodes. + * The deletion process is performed in the tree order, that is, a node + * is deleted after its previous sibling node is deleted, a parent node + * is deleted after its branch is deleted. + * During the deletion process when the m_pStopAtNode is reached, the + * progress is interrupted at once. + * + * INPUTS + * pNode - the node to be deleted + * + * RESULT + * result - the result of the deletion process, can be one of following + * values: + * NODE_STOPPED - the process is interrupted by meeting the + * m_pStopAtNode + * NODE_NOTREMOVED - the pNode is not completely removed + * because there is its descendant in the + * m_aReservedNodes list + * NODE_REMOVED - the pNode and its branch are completely + * removed + * + * NOTES + * The node in the m_aReservedNodes list must be in the tree order, otherwise + * the result is unpredictable. + ******************************************************************************/ +{ + if (pNode == m_pStopAtNode) + { + return NODE_STOPPED; + } + + if (pNode != m_pCurrentReservedNode) + { + xmlNodePtr pChild = pNode->children; + + xmlNodePtr pNextSibling; + bool bIsRemoved = true; + sal_Int32 nResult; + + while( pChild != nullptr ) + { + pNextSibling = pChild->next; + nResult = recursiveDelete(pChild); + + switch (nResult) + { + case NODE_STOPPED: + return NODE_STOPPED; + case NODE_NOTREMOVED: + bIsRemoved = false; + break; + case NODE_REMOVED: + removeNode(pChild); + break; + default: + throw uno::RuntimeException(); + } + + pChild = pNextSibling; + } + + if (pNode == m_pCurrentElement) + { + bIsRemoved = false; + } + + return bIsRemoved?NODE_REMOVED:NODE_NOTREMOVED; + } + else + { + getNextReservedNode(); + return NODE_NOTREMOVED; + } +} + +void XMLDocumentWrapper_XmlSecImpl::getNextReservedNode() +/****** XMLDocumentWrapper_XmlSecImpl/getNextReservedNode ********************* + * + * NAME + * getNextReservedNode -- Highlights the next reserved node in the + * reserved node list + * + * FUNCTION + * The m_aReservedNodes array holds a node list, while the + * m_pCurrentReservedNode points to the one currently highlighted. + * This method is used to highlight the next node in the node list. + * This method is called at the time when the current highlighted node + * has been already processed, and the next node should be ready. + ******************************************************************************/ +{ + if (m_nReservedNodeIndex < m_aReservedNodes.getLength()) + { + m_pCurrentReservedNode = checkElement( m_aReservedNodes[m_nReservedNodeIndex] ); + m_nReservedNodeIndex ++; + } + else + { + m_pCurrentReservedNode = nullptr; + } +} + +void XMLDocumentWrapper_XmlSecImpl::removeNode(const xmlNodePtr pNode) const +/****** XMLDocumentWrapper_XmlSecImpl/removeNode ****************************** + * + * NAME + * removeNode -- Deletes a node with its branch unconditionally + * + * FUNCTION + * Delete the node along with its branch from the document. + * + * INPUTS + * pNode - the node to be deleted + ******************************************************************************/ +{ + /* you can't remove the current node */ + OSL_ASSERT( m_pCurrentElement != pNode ); + + xmlAttrPtr pAttr = pNode->properties; + + while (pAttr != nullptr) + { + if (!stricmp(reinterpret_cast(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("id") ); + if (idAttr == nullptr) + { + idAttr = xmlHasProp( pNode, reinterpret_cast("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(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(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(i)); + aAttributesRange[i].sValue =xAttribs->getValueByIndex(static_cast(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 const& /*rSeq*/) +{ + return cppu::acquire(new XMLDocumentWrapper_XmlSecImpl()); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/xmlelementwrapper_xmlsecimpl.cxx b/xmlsecurity/source/xmlsec/xmlelementwrapper_xmlsecimpl.cxx new file mode 100644 index 0000000000..ccc4f03dd9 --- /dev/null +++ b/xmlsecurity/source/xmlsec/xmlelementwrapper_xmlsecimpl.cxx @@ -0,0 +1,58 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include "xmlelementwrapper_xmlsecimpl.hxx" +#include +#include + +namespace com::sun::star::uno { class XComponentContext; } + +using namespace com::sun::star; + +XMLElementWrapper_XmlSecImpl::XMLElementWrapper_XmlSecImpl(const xmlNodePtr pNode) + : m_pElement( pNode ) +{ +} + +/* XServiceInfo */ +OUString SAL_CALL XMLElementWrapper_XmlSecImpl::getImplementationName( ) +{ + return "com.sun.star.xml.wrapper.XMLElementWrapper"; +} + +sal_Bool SAL_CALL XMLElementWrapper_XmlSecImpl::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService( this, rServiceName ); +} + +uno::Sequence< OUString > SAL_CALL XMLElementWrapper_XmlSecImpl::getSupportedServiceNames( ) +{ + return { "com.sun.star.xml.wrapper.XMLElementWrapper" }; +} + +extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface* +com_sun_star_xml_wrapper_XMLElementWrapper_get_implementation( + uno::XComponentContext* /*pCtx*/, uno::Sequence const& /*rSeq*/) +{ + return cppu::acquire(new XMLElementWrapper_XmlSecImpl(nullptr)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/xmlelementwrapper_xmlsecimpl.hxx b/xmlsecurity/source/xmlsec/xmlelementwrapper_xmlsecimpl.hxx new file mode 100644 index 0000000000..93ce721f0b --- /dev/null +++ b/xmlsecurity/source/xmlsec/xmlelementwrapper_xmlsecimpl.hxx @@ -0,0 +1,72 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include +#include +#include + +#include +#include + +class XMLElementWrapper_XmlSecImpl : public cppu::WeakImplHelper +< + css::xml::wrapper::XXMLElementWrapper, + css::lang::XServiceInfo +> +/****** XMLElementWrapper_XmlSecImpl.hxx/CLASS XMLElementWrapper_XmlSecImpl *** + * + * NAME + * XMLElementWrapper_XmlSecImpl -- Class to wrap a libxml2 node + * + * FUNCTION + * Used as a wrapper class to transfer a libxml2 node structure + * between different UNO components. + ******************************************************************************/ +{ +private: + /* the libxml2 node wrapped by this object */ + xmlNodePtr const m_pElement; + +public: + explicit XMLElementWrapper_XmlSecImpl(const xmlNodePtr pNode); + + /* XXMLElementWrapper */ + + /* css::lang::XServiceInfo */ + virtual OUString SAL_CALL getImplementationName( ) override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; + +public: + /* + * NAME + * getNativeElement -- Retrieves the libxml2 node wrapped by this object + * + * SYNOPSIS + * pNode = getNativeElement(); + * + * RESULT + * pNode - the libxml2 node wrapped by this object + */ + xmlNodePtr getNativeElement( ) const { return m_pElement;} +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/xmlsec_init.cxx b/xmlsecurity/source/xmlsec/xmlsec_init.cxx new file mode 100644 index 0000000000..410408ed2e --- /dev/null +++ b/xmlsecurity/source/xmlsec/xmlsec_init.cxx @@ -0,0 +1,73 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include + +#include + +#include + +#include +#ifdef XMLSEC_CRYPTO_MSCRYPTO +#include +#endif +#ifdef XMLSEC_CRYPTO_NSS +#include +#endif + +using namespace css::uno; + +XSECXMLSEC_DLLPUBLIC void initXmlSec() +{ + //Init xmlsec library + if( xmlSecInit() < 0 ) { + throw RuntimeException() ; + } + + //Init xmlsec crypto engine library +#ifdef XMLSEC_CRYPTO_MSCRYPTO + if( xmlSecMSCngInit() < 0 ) { + xmlSecShutdown(); + throw RuntimeException(); + } +#endif +#ifdef XMLSEC_CRYPTO_NSS + if( xmlSecNssInit() < 0 ) { + xmlSecShutdown(); + throw RuntimeException(); + } +#endif + + //Enable external stream handlers + if( xmlEnableStreamInputCallbacks() < 0 ) { +#ifdef XMLSEC_CRYPTO_MSCRYPTO + xmlSecMSCngShutdown(); +#endif +#ifdef XMLSEC_CRYPTO_NSS + xmlSecNssShutdown(); +#endif + xmlSecShutdown() ; + throw RuntimeException() ; + } +} + +XSECXMLSEC_DLLPUBLIC void deInitXmlSec() +{ + xmlDisableStreamInputCallbacks(); +#ifdef XMLSEC_CRYPTO_MSCRYPTO + xmlSecMSCngShutdown(); +#endif +#ifdef XMLSEC_CRYPTO_NSS + xmlSecNssShutdown(); +#endif + xmlSecShutdown(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/xmlstreamio.cxx b/xmlsecurity/source/xmlsec/xmlstreamio.cxx new file mode 100644 index 0000000000..b3ee767120 --- /dev/null +++ b/xmlsecurity/source/xmlsec/xmlstreamio.cxx @@ -0,0 +1,251 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include + +/* + * Implementation of the I/O interfaces based on stream and URI binding + */ +#include +#include +#include +#include +#include +#include + +#include + +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(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(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(context); + pInputStream->release() ; + SAL_INFO("xmlsecurity.xmlsec", "xmlStreamRead: closed context " << context); + } + } + + return 0 ; +} + +} + +int xmlEnableStreamInputCallbacks() +{ + if (!g_bInputCallbacksEnabled) + { + //Register the callbacks into xmlSec + //In order to make the xmlsec io finding the callbacks firstly, + //I put the callbacks at the very beginning. + + //Cleanup the older callbacks. + //Notes: all none default callbacks will lose. + xmlSecIOCleanupCallbacks() ; + + // Make sure that errors are reported via SAL_WARN(). + setErrorRecorder(); + comphelper::ScopeGuard g([] { clearErrorRecorder(); }); + + // Newer xmlsec wants the callback order in the opposite direction. + if (xmlSecCheckVersionExt(1, 2, 26, xmlSecCheckVersionABICompatible)) + { + //Register the default callbacks. + //Notes: the error will cause xmlsec working problems. + int cbs = xmlSecIORegisterDefaultCallbacks() ; + if( cbs < 0 ) { + return -1 ; + } + + //Register my classbacks. + cbs = xmlSecIORegisterCallbacks( + xmlStreamMatch, + xmlStreamOpen, + xmlStreamRead, + xmlStreamClose ) ; + if( cbs < 0 ) { + return -1 ; + } + } + else + { + //Register my classbacks. + int cbs = xmlSecIORegisterCallbacks( + xmlStreamMatch, + xmlStreamOpen, + xmlStreamRead, + xmlStreamClose ) ; + if( cbs < 0 ) { + return -1 ; + } + + //Register the default callbacks. + //Notes: the error will cause xmlsec working problems. + cbs = xmlSecIORegisterDefaultCallbacks() ; + if( cbs < 0 ) { + return -1 ; + } + } + + g_bInputCallbacksEnabled = true; + } + + return 0 ; +} + +int xmlRegisterStreamInputCallbacks( + css::uno::Reference< css::xml::crypto::XUriBinding > const & aUriBinding +) { + if (!g_bInputCallbacksEnabled) + { + if( xmlEnableStreamInputCallbacks() < 0 ) + return -1 ; + } + + if (!g_bInputCallbacksRegistered) + g_bInputCallbacksRegistered = true; + + m_xUriBinding = aUriBinding ; + + return 0 ; +} + +int xmlUnregisterStreamInputCallbacks() +{ + if (g_bInputCallbacksRegistered) + { + //Clear the uri-stream binding + m_xUriBinding.clear() ; + + //disable the registered flag + g_bInputCallbacksRegistered = false; + } + + return 0 ; +} + +void xmlDisableStreamInputCallbacks() { + xmlUnregisterStreamInputCallbacks() ; + g_bInputCallbacksEnabled = false; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/test_docs/CAs/README.txt b/xmlsecurity/test_docs/CAs/README.txt new file mode 100644 index 0000000000..b454f1fafd --- /dev/null +++ b/xmlsecurity/test_docs/CAs/README.txt @@ -0,0 +1,383 @@ +This folder contains the directory structures needed by openssl to create +and manager certificates. + + + +################################################################################ + +Root 1 +====== +Valid root CA certificate. +Provides CRL = NO +Provides CRL via HTTP = NO +Provides OCSP = NO + +Sub CA 1 Root 1 +=============== +Valid intermediate CA certificate. +Provides CRL = NO +Provides CRL via HTTP = NO +Provides OCSP = NO +CRLDP = NO +AIA = NO + +User 1 Sub CA 1 Root 1 +====================== +Valid end certificate. +CRLDP = NO +AIA = NO + +################################################################################ + +Root 2 +====== +Valid root CA certificate. +Provides CRL = NO +Provides CRL via HTTP = NO +Provides OCSP = NO + +Sub CA 1 Root 2 +=============== +Valid intermediate CA certificate. +Provides CRL = YES +Provides CRL via HTTP = NO +Provides OCSP = NO +CRLDP = NO +AIA = NO + +User 1 Sub CA 1 Root 2 +====================== +Valid end certificate. +CRLDP = NO +AIA = NO + +################################################################################ + +Root 3 +====== +Valid root CA certificate. +Provides CRL = YES +Provides CRL via HTTP = NO +Provides OCSP = NO + +Sub CA 1 Root 3 +=============== +Valid intermediate CA certificate. +Provides CRL = NO +Provides CRL via HTTP = NO +Provides OCSP = NO +CRLDP = NO +AIA = NO + +User 1 Sub CA 1 Root 3 +====================== +Valid end certificate. +CRLDP = NO +AIA = NO + +################################################################################ + +Root 4 +====== +Valid root CA certificate. +Provides CRL = YES +Provides CRL via HTTP = NO +Provides OCSP = NO + +Revoked certificates: + +- Sub CA 2 Root 4 + + +Sub CA 1 Root 4 +=============== +Valid intermediate CA certificate. +Provides CRL = YES +Provides CRL via HTTP = NO +Provides OCSP = NO +CRLDP = NO +AIA = NO + +Revoked certificates: + +- User 2 Sub CA 1 Root 4 + + +User 1 Sub CA 1 Root 4 +====================== +Valid end certificate. +CRLDP = NO +AIA = NO + +User 2 Sub CA 1 Root 4 +====================== +Revoked end certificate. +CRLDP = NO +AIA = NO + +Sub CA 2 Root 4 +=============== +Revoked intermediate CA certificate. Reason = keyCompromise +Provides CRL = YES +Provides CRL via HTTP = NO +Provides OCSP = NO +CRLDP = NO +AIA = NO + +Revoked certificates: + +- User 2 Sub CA 2 Root 4 + +User 1 Sub CA 2 Root 4 +====================== +Valid end certificate. Issuer is revoked. +CRLDP = NO +AIA = NO + +User 2 Sub CA 2 Root 4 +====================== +Revoked end certificate. Reason = keyCompromise. Issuer is revoked. +CRLDP = NO +AIA = NO + +################################################################################ + +Root 5 +====== +Valid root CA certificate. +Provides CRL = NO +Provides CRL via HTTP = NO +Provides OCSP = NO + +Sub CA 1 Root 5 +=============== +Valid intermediate CA certificate. +Provides CRL = NO +Provides CRL via HTTP = YES +Provides OCSP = NO +CRLDP = URL=http://localhost:8901/demoCA/crl/Root_5.crl +AIA = NO + +User 1 Sub CA 1 Root 5 +====================== +Valid end certificate. +CRLDP = URL=http://localhost:8902/demoCA/crl/Sub_CA_1_Root_5.crl +AIA = NO + + +################################################################################ + +Root 6 +====== +Valid root CA certificate. +Provides CRL = NO +Provides CRL via HTTP = YES +Provides OCSP = NO + +Sub CA 1 Root 6 +=============== +Valid intermediate CA certificate. +Provides CRL = NO +Provides CRL via HTTP = NO +Provides OCSP = NO +CRLDP = URL=http://localhost:8901/demoCA/crl/Root_6.crl +AIA = NO + +User 1 Sub CA 1 Root 6 +====================== +Valid end certificate. +CRLDP = URL=http://localhost:8902/demoCA/crl/Sub_CA_1_Root_6.crl +AIA = NO + +################################################################################ + +Root 7 +====== +Valid root CA certificate. +Provides CRL = NO +Provides CRL via HTTP = YES +Provides OCSP = NO + +Revoked certificates: + +- Sub CA 2 Root 7 + + +Sub CA 1 Root 7 +=============== +Valid intermediate CA certificate. +Provides CRL = NO +Provides CRL via HTTP = YES +Provides OCSP = NO +CRLDP = URL=http://localhost:8901/demoCA/crl/Root_7.crl +AIA = NO + +Revoked certificates: + +- User 2 Sub CA 1 Root 7 + + +User 1 Sub CA 1 Root 7 +====================== +Valid end certificate. +CRLDP = URL=http://localhost:8902/demoCA/crl/Sub_CA_1_Root_7.crl +AIA = NO + +User 2 Sub CA 1 Root 7 +====================== +Revoked end certificate. Reason = CACompromise. +CRLDP = URL=http://localhost:8902/demoCA/crl/Sub_CA_1_Root_7.crl +AIA = NO + +Sub CA 2 Root 7 +=============== +Revoked intermediate CA certificate. Reason = keyCompromise +Provides CRL = NO +Provides CRL via HTTP = YES +Provides OCSP = NO +CRLDP = URL=http://localhost:8901/demoCA/crl/Root_7.crl +AIA = NO + +Revoked certificates: + +- User 2 Sub CA 2 Root 7 + +User 1 Sub CA 2 Root 7 +====================== +Valid end certificate. Issuer is revoked. +CRLDP = URL=http://localhost:8902/demoCA/crl/Sub_CA_2_Root_7.crl +AIA = NO + +User 2 Sub CA 2 Root 7 +====================== +Revoked end certificate. Reason = CACompromise. Issuer is revoked. +CRLDP = URL=http://localhost:8902/demoCA/crl/Sub_CA_2_Root_7.crl +AIA = NO + +################################################################################ + +Root 8 +====== +Valid root CA certificate. +Provides CRL = NO +Provides CRL via HTTP = NO +Provides OCSP = YES + +Revoked certificates: + +- Sub CA 2 Root 8 + + +Sub CA 1 Root 8 +=============== +Valid intermediate CA certificate. +Provides CRL = NO +Provides CRL via HTTP = NO +Provides OCSP = YES +CRLDP = +AIA = OCSP;URI:http://localhost:8888 + +Revoked certificates: + +- User 2 Sub CA 1 Root 8 + + +User 1 Sub CA 1 Root 8 +====================== +Valid end certificate. +CRLDP = NO +AIA = OCSP;URI:http://localhost:8889 + +User 2 Sub CA 1 Root 8 +====================== +Revoked end certificate. Reason = superseded. +CRLDP = NO +AIA = OCSP;URI:http://localhost:8889 + +Sub CA 2 Root 8 +=============== +Revoked intermediate CA certificate. Reason = superseded. +Provides CRL = NO +Provides CRL via HTTP = NO +Provides OCSP = YES +CRLDP = NO +AIA = OCSP;URI:http://localhost:8888 + +Revoked certificates: + +- User 2 Sub CA 2 Root 8 + +User 1 Sub CA 2 Root 8 +====================== +Valid end certificate. Issuer is revoked. +CRLDP = NO +AIA = OCSP;URI:http://localhost:8889 + +User 2 Sub CA 2 Root 8 +====================== +Revoked end certificate. Reason = superseded. Issuer is revoked. +CRLDP = NO +AIA = OCSP;URI:http://localhost:8889 + +################################################################################ + +Root 9 +====== +Valid root CA certificate. (Not installed.) +Provides CRL = YES +Provides CRL via HTTP = NO +Provides OCSP = NO + +Sub CA 1 Root 9 +=============== +Valid intermediate CA certificate. +Provides CRL = YES +Provides CRL via HTTP = NO +Provides OCSP = NO +CRLDP = NO +AIA = NO + +User 1 Sub CA 1 Root 9 +====================== +Valid end certificate. +CRLDP = NO +AIA = NO + +################################################################################ + +Root 10 +====== +Valid root CA certificate. +Provides CRL = YES +Provides CRL via HTTP = NO +Provides OCSP = NO + +Sub CA 1 Root 10 +=============== +Valid intermediate CA certificate. (Not installed.) +Provides CRL = NO +Provides CRL via HTTP = YES +Provides OCSP = NO +CRLDP = NO +AIA = NO + +User 1 Sub CA 1 Root 10 +====================== +Valid end certificate. +CRLDP = URI:http://localhost:8902/demoCA/crl/Sub_CA_1_Root_10.crl +AIA = caIssuers;URI:http://localhost:8910/demoCA/Sub_CA_1_Root_10.crt + +################################################################################ + +Root 11 +====== +Valid root CA certificate. +Provides CRL = YES +Provides CRL via HTTP = NO +Provides OCSP = NO + +User x Root 11 +====================== +All certificate issues by Root 11 are valid end certificate. Currently there are +31 certificates. + diff --git a/xmlsecurity/test_docs/CAs/Root_1/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Root_1/demoCA/cacert.pem new file mode 100644 index 0000000000..091052e3ab --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_1/demoCA/cacert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDBDCCAm2gAwIBAgIJAJWwBSvtwjktMA0GCSqGSIb3DQEBBQUAMF8xCzAJBgNV +BAYTAkRFMRAwDgYDVQQIEwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9y +ZzEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgMTAeFw0wOTEx +MTgxNDU1NDFaFw0zNDExMTIxNDU1NDFaMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw +gYkCgYEAvrD6NFWcOQQVxIuXw5Pzpy667PZbBP80ow2Bbnj+RFCI/LbgfQTsC8Bw +eSlQGX7IqMHkCTuWNJw7CoNeOLFhRMtm0DEKnEkZlM0t6kpFshbs12jZu9okcnII +F5uIoKxx/thbD5AbC1Q74vZr6XOXY5Sc+k9Ic6Jwhe9ZyEt6SUsCAwEAAaOBxzCB +xDAdBgNVHQ4EFgQUD/rG69/OuLuzqT5Cprrs0pPKR6QwgZEGA1UdIwSBiTCBhoAU +D/rG69/OuLuzqT5Cprrs0pPKR6ShY6RhMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgMYIJAJWwBSvtwjktMA8GA1UdEwEB/wQF +MAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAqORur4HQGdQOQCaiyZR5u0+9mM/0w79y +r8Cmt+H8WB5BBeDgCyOcmaZjF0eEoRBF/ZhtlO54i4CH/yb/Pl6gGlxfGZL9iLu0 +tv4HRIIibnoi0N7Z0r/dhJcrTHo4Ha8EARhAqxoNUSlGVBsaKUfjW9RyCjv4Akyi +WUSwsmtd/sY= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_1/demoCA/crl/DO_NOT_CREATE_A_CRL b/xmlsecurity/test_docs/CAs/Root_1/demoCA/crl/DO_NOT_CREATE_A_CRL new file mode 100644 index 0000000000..e69de29bb2 diff --git a/xmlsecurity/test_docs/CAs/Root_1/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Root_1/demoCA/crlnumber new file mode 100644 index 0000000000..83b33d238d --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_1/demoCA/crlnumber @@ -0,0 +1 @@ +1000 diff --git a/xmlsecurity/test_docs/CAs/Root_1/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Root_1/demoCA/index.txt new file mode 100644 index 0000000000..9a6e64301b --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_1/demoCA/index.txt @@ -0,0 +1 @@ +V 341112150713Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 1 Root 1 diff --git a/xmlsecurity/test_docs/CAs/Root_1/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Root_1/demoCA/index.txt.attr new file mode 100644 index 0000000000..8f7e63a347 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_1/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Root_1/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Root_1/demoCA/newcerts/1000.pem new file mode 100644 index 0000000000..be26aa5d8f --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_1/demoCA/newcerts/1000.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 1 + Validity + Not Before: Nov 18 15:07:13 2009 GMT + Not After : Nov 12 15:07:13 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 1 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:d9:3a:8d:64:95:87:76:76:e8:61:c3:e9:65:f4: + a6:b7:0c:77:0e:4b:10:e8:14:a3:e1:84:69:7c:8e: + 97:d2:7d:01:ad:b2:dc:5c:cd:c6:91:a1:f3:93:7c: + 54:36:64:e3:ca:22:ca:00:cb:c6:91:ab:6b:26:88: + 69:60:9a:61:d7:59:17:db:93:7d:09:36:da:28:cb: + ec:2d:a4:26:bb:1a:42:20:b8:08:b2:0f:b9:77:a6: + 80:71:cf:13:f5:37:a2:90:4d:ab:e8:97:49:d2:80: + 94:8f:b1:9d:5a:b4:9f:de:ff:fa:b6:d6:e0:45:5f: + cc:d4:10:1e:32:46:7b:ba:55 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 37:71:74:81:44:DD:1E:B1:60:96:41:B7:4B:38:C4:B7:79:1B:CF:8A + X509v3 Authority Key Identifier: + keyid:0F:FA:C6:EB:DF:CE:B8:BB:B3:A9:3E:42:A6:BA:EC:D2:93:CA:47:A4 + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 1 + serial:95:B0:05:2B:ED:C2:39:2D + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 18:f6:02:5e:75:04:5f:eb:3b:07:41:85:c0:9e:08:29:58:3d: + b5:6f:c2:aa:24:0d:93:1d:17:fc:be:d6:43:ac:43:d7:4d:a0: + 2c:40:fd:3d:d5:7e:91:46:25:49:62:ba:e9:7f:67:c2:fc:8a: + c3:a0:37:bf:ec:f9:54:bf:61:10:35:dd:5b:bb:da:7c:70:54: + 32:13:b9:ae:7d:ea:a5:7d:aa:55:3e:ef:0a:ef:12:fd:c3:f6: + e5:25:98:97:34:02:64:fd:88:79:b3:e2:f4:fc:ff:e7:d3:98: + f1:d9:d5:18:d9:b4:62:ae:99:88:61:2e:ff:02:6a:13:35:fe: + 37:c7 +-----BEGIN CERTIFICATE----- +MIIDBjCCAm+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCAxMB4XDTA5MTExODE1MDcx +M1oXDTM0MTExMjE1MDcxM1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCAxMIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDZOo1klYd2duhhw+ll9Ka3DHcOSxDoFKPhhGl8jpfSfQGtstxczcaR +ofOTfFQ2ZOPKIsoAy8aRq2smiGlgmmHXWRfbk30JNtooy+wtpCa7GkIguAiyD7l3 +poBxzxP1N6KQTavol0nSgJSPsZ1atJ/e//q21uBFX8zUEB4yRnu6VQIDAQABo4HH +MIHEMB0GA1UdDgQWBBQ3cXSBRN0esWCWQbdLOMS3eRvPijCBkQYDVR0jBIGJMIGG +gBQP+sbr3864u7OpPkKmuuzSk8pHpKFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCAxggkAlbAFK+3COS0wDwYDVR0TAQH/ +BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQAY9gJedQRf6zsHQYXAnggpWD21b8Kq +JA2THRf8vtZDrEPXTaAsQP091X6RRiVJYrrpf2fC/IrDoDe/7PlUv2EQNd1bu9p8 +cFQyE7mufeqlfapVPu8K7xL9w/blJZiXNAJk/Yh5s+L0/P/n05jx2dUY2bRirpmI +YS7/AmoTNf43xw== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_1/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Root_1/demoCA/private/cakey.pem new file mode 100644 index 0000000000..6d38b24e6f --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_1/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,2D2CC3782F59A842 + +901JcMMdeCfHjfY05bkyLIsgMxwu4SFJPXZH75ebFtJQpkQQf5WNhSlo3sgKJ5MF +GZeqQw4w9CmN+CNqQENZOOGrVKxT+sFtWIgSLVk4hrLzPtsT7domHc1yUKfpBH/w +xo/bsL5wZPqcsxSdlmd4FA0PKzW/rhyYvRxF0oKQx2PVnJKT29WbhwlYurI3+2gG +pS+N6f7awWjmgyqYvFuFo7DWhERDDL/Bi/sJ7qFinijtfp1CkVG1XWFZ8Tu9ij+t +KPT3fpWbh4sV0V1ZGng7EPb4c+p/+GHvKsGM9N5kuyxufllNzAeIy6hfTR3mxn0i +Ep4CoufMi0JwNEfgwBB+o47k1hVoBTn0ofXc2iP6iQWsoC5ZoPPGLLklWK3Tur7P +kpng8UECTxV2s6J3nYkAoHfy+TzK+nssFPpE8zDmaprpeTj9oh3KrPTn0IdoPHcx +oI3yqWqDK9uErJBBCAjLF0SPJWAsmp0HsJaGnj5ErVe0yy3jBxVWogVDSWkoWU0W ++umK1pSQrS1A/oKErsnbhPi8XAD/gd4etEaKdcY538QKgE2tdPvhLoAeXxslyOfG +UiPohtmcm2Mva7vT0Iu1MGKplw76DxmmM1Rpf3+u7Kwf/+K6bMOSBGZQJhjE2AuZ +aPyHX8gCNlZfqB6eeuWdbqIHhTN5dS2Bba3QquvS84Vgb3O2ck+vdjmdPEeetvA7 +7S4WZYHBRmz1ZHwdfSvwyBkdTRP5YrUhrIthbqy2NjcP9TkpQmJaDIlWXsGY738q +zTsjCkcnS06x0/JvHe1I8IAib+MFsmGI7Dw25fzgY3ReS4wZRZdU0A== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Root_1/demoCA/serial b/xmlsecurity/test_docs/CAs/Root_1/demoCA/serial new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_1/demoCA/serial @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Root_1/openssl.cfg b/xmlsecurity/test_docs/CAs/Root_1/openssl.cfg new file mode 100644 index 0000000000..0dd15bd9ec --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_1/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Root_10/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Root_10/demoCA/cacert.pem new file mode 100644 index 0000000000..72e6c66e2e --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_10/demoCA/cacert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDBzCCAnCgAwIBAgIJAL/ID7vZoDprMA0GCSqGSIb3DQEBBQUAMGAxCzAJBgNV +BAYTAkRFMRAwDgYDVQQIEwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9y +ZzEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxEDAOBgNVBAMTB1Jvb3QgMTAwHhcNMDkx +MTIzMTUwNzA0WhcNMzQxMTE3MTUwNzA0WjBgMQswCQYDVQQGEwJERTEQMA4GA1UE +CBMHSGFtYnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0Rl +dmVsb3BtZW50MRAwDgYDVQQDEwdSb290IDEwMIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQC5qE1pk/tI2i60IrVhlwS77j7jAyktxRuwKJqBECd2ZD2/goO8wcwD +R/wfrh+zuLWRwFb57PF1O7ig+WNhQk3GDhXhMbuB82Bwjb/n5phKDWHsAIqDRbH4 +vpl/7sWYXvE46zf41PpQPgudOtqpeL1ENFoHKZOJthkBc4Yx6HTUSQIDAQABo4HI +MIHFMB0GA1UdDgQWBBTIp6OAIHRsb+wReva+JhA3MYewejCBkgYDVR0jBIGKMIGH +gBTIp6OAIHRsb+wReva+JhA3MYeweqFkpGIwYDELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMIIJAL/ID7vZoDprMA8GA1UdEwEB +/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAroDDzqZQL+7NeQuePohejcGfFR/0 +vtbQ3AYViQ2JS42gQpaNaMNcVCvO0nUwLHldLNVdQsn9P0ultu6KcUKkBbY4/2Xp +er6RMQWsrKVLnszgIi2gk1NiNwZ+N9RISJvElaQuIciZs+8sM6LOPybVTArMjxEo +U3VqHTViFfOvWC0= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_10/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Root_10/demoCA/crlnumber new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_10/demoCA/crlnumber @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Root_10/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Root_10/demoCA/index.txt new file mode 100644 index 0000000000..2db3924cea --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_10/demoCA/index.txt @@ -0,0 +1 @@ +V 341117151448Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 1 Root 10 diff --git a/xmlsecurity/test_docs/CAs/Root_10/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Root_10/demoCA/index.txt.attr new file mode 100644 index 0000000000..8f7e63a347 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_10/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Root_10/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Root_10/demoCA/newcerts/1000.pem new file mode 100644 index 0000000000..1f27b97b3d --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_10/demoCA/newcerts/1000.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 10 + Validity + Not Before: Nov 23 15:14:48 2009 GMT + Not After : Nov 17 15:14:48 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 10 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:e4:d5:66:14:88:9f:79:41:50:b0:d1:a0:1b:98: + bf:b0:21:34:30:36:70:58:6f:8b:58:f1:b9:58:3a: + ce:29:6b:65:b6:11:f7:0d:c8:a6:c3:be:db:0f:2a: + 4e:c7:42:df:c9:0e:13:c0:00:0f:af:b5:71:c4:bc: + dd:82:fc:4a:27:c0:ee:af:ba:e1:7b:67:de:6b:bb: + ac:4c:fe:88:01:1a:73:4e:f5:32:15:3a:d0:cb:6b: + 97:84:1b:6c:d0:d6:91:a8:a4:5a:87:2a:69:61:36: + 1d:42:cc:16:d0:03:9c:c6:90:5c:61:20:8b:b1:be: + b6:54:24:5b:6f:1f:a9:5a:6f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 11:63:A1:BE:8B:E3:56:07:E6:A3:9F:23:39:72:7D:E3:22:B6:53:39 + X509v3 Authority Key Identifier: + keyid:C8:A7:A3:80:20:74:6C:6F:EC:11:7A:F6:BE:26:10:37:31:87:B0:7A + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 10 + serial:BF:C8:0F:BB:D9:A0:3A:6B + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 6b:0f:75:6d:56:b0:4e:45:19:65:ad:50:ef:4e:87:6c:95:5d: + 05:39:5a:43:5c:b4:51:25:9a:ec:f4:93:d1:f0:f6:91:dd:a3: + 77:95:0c:74:3c:a9:7c:c2:f6:62:ce:bf:58:5f:66:1f:d0:55: + ca:d8:2d:c4:1e:29:3a:ad:55:2c:9d:2c:8f:8e:9e:ce:ac:17: + 7e:1b:d1:16:d9:12:76:5c:2d:3f:9d:70:66:aa:39:34:f0:ec: + 31:4b:4b:5a:14:0c:c5:5b:3c:c8:47:02:90:cb:77:d7:4f:88: + 10:a7:80:3d:ca:19:5c:b5:04:c9:f0:e1:1b:5a:5f:fb:61:b2: + 14:b5 +-----BEGIN CERTIFICATE----- +MIIDCTCCAnKgAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMDAeFw0wOTExMjMxNTE0 +NDhaFw0zNDExMTcxNTE0NDhaMGkxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxGTAXBgNVBAMTEFN1YiBDQSAxIFJvb3QgMTAwgZ8wDQYJKoZIhvcNAQEBBQAD +gY0AMIGJAoGBAOTVZhSIn3lBULDRoBuYv7AhNDA2cFhvi1jxuVg6zilrZbYR9w3I +psO+2w8qTsdC38kOE8AAD6+1ccS83YL8SifA7q+64Xtn3mu7rEz+iAEac071MhU6 +0Mtrl4QbbNDWkaikWocqaWE2HULMFtADnMaQXGEgi7G+tlQkW28fqVpvAgMBAAGj +gcgwgcUwHQYDVR0OBBYEFBFjob6L41YH5qOfIzlyfeMitlM5MIGSBgNVHSMEgYow +gYeAFMino4AgdGxv7BF69r4mEDcxh7B6oWSkYjBgMQswCQYDVQQGEwJERTEQMA4G +A1UECBMHSGFtYnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsT +C0RldmVsb3BtZW50MRAwDgYDVQQDEwdSb290IDEwggkAv8gPu9mgOmswDwYDVR0T +AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBrD3VtVrBORRllrVDvTodslV0F +OVpDXLRRJZrs9JPR8PaR3aN3lQx0PKl8wvZizr9YX2Yf0FXK2C3EHik6rVUsnSyP +jp7OrBd+G9EW2RJ2XC0/nXBmqjk08OwxS0taFAzFWzzIRwKQy3fXT4gQp4A9yhlc +tQTJ8OEbWl/7YbIUtQ== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_10/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Root_10/demoCA/private/cakey.pem new file mode 100644 index 0000000000..f75ccc08ef --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_10/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,78CCF9A24E7B5044 + +ppKSX6K7DHnU4EvbmBAIzWDJ35yGppjzNdWRKpB7rkGW60dW0Cw0Jmbxf1dfbUC+ +UTWtxE+i0x159jF7jGobPvLFQnAg1ZPUUIgeXJt+fqf/OghY4i8x82BdSlaKJ293 +GgwR9m1N1I2/6ydob+9KwzJhOPhmylyUyRJVAx/OF86E9G4nxtuJA1c1nzSBgwR5 +7uHU0LiY5A42iTDiMmu7Jw4vj6Cy81P88hmyoVzo4JQG8YFuJyLz2ei+DJ3/572z +BCefqDKmlmI2vvayZW1jgpLDlTwmqiIGUDBBipN4vDmqZAdEbv/9BjLkS4Svy3PU +xaFs1tFQzv8ivGpyPWU5naoTKhmMhOEAKpEi6YqWbcD/qKn1pRrYSyVyD9zNXHEK +QrXjTP+D/DMSHNJTo5WI4kxvwSZtPI97vaCTmxkrjnIXDPD5L4v9dJUdejnngsqn +cHB/C/05dR0RLEp5CHrl0hwGiIY1IgQXmGHY2HEUyQYttyJ5jdY0pdnn9n0eQxHr +9Mg3WneWC42XHw0pyqEsgiMmr8SjaF42MSrMB6y4WEVtBstn03LTdFnRIFTgZ5Mj +l/O2mSk+YUBR4CYTUTRaWpzCAZmFVy98I8KQgrhi8t96wrRe0+9tB1uC5PoDNR5P +CcgsmiEPeqolPZwOmnDdij+DcIiT43Sx2vDYGfDtqc+kur/O6noYyX8Kf7wzcpan +V4gHTCEOrlcRiEcVIxAQFDpB8CERG9fJvnBdZE9Gjepz6OatRpE/2kDZMelwRcEx +V5zeE1qNS51gdq2dE0qYkdyU1yfbNUouqtFy/z1sXU6Q5nR1r21jFQ== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Root_10/demoCA/serial b/xmlsecurity/test_docs/CAs/Root_10/demoCA/serial new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_10/demoCA/serial @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Root_10/openssl.cfg b/xmlsecurity/test_docs/CAs/Root_10/openssl.cfg new file mode 100644 index 0000000000..f48e3d5a34 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_10/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Root_7.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/cacert.pem new file mode 100644 index 0000000000..8cfffd9a6c --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/cacert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDBzCCAnCgAwIBAgIJAI3gSU2IIGPLMA0GCSqGSIb3DQEBBQUAMGAxCzAJBgNV +BAYTAkRFMRAwDgYDVQQIEwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9y +ZzEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxEDAOBgNVBAMTB1Jvb3QgMTEwHhcNMTAw +MTE0MTEzNzA1WhcNMzUwMTA4MTEzNzA2WjBgMQswCQYDVQQGEwJERTEQMA4GA1UE +CBMHSGFtYnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0Rl +dmVsb3BtZW50MRAwDgYDVQQDEwdSb290IDExMIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDKGrq6yC3tyctcBo+iz31MF2yvDiQ7YFgez8TswNvb3USOPOUPsCaB +ufVN6ULSqmGi5BzFIW7CVAj5L+iCrrwMtPyG86fKbvgdWmLepz5a4S1y+vydnQ0B +rJCNdxmLdQK+l/P7jzrH5xhcR62DPQ2lLabvmixvylHv4H6cFjJ98wIDAQABo4HI +MIHFMB0GA1UdDgQWBBToarvCkOpscCI+9vZIGwPmvremVTCBkgYDVR0jBIGKMIGH +gBToarvCkOpscCI+9vZIGwPmvremVaFkpGIwYDELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMYIJAI3gSU2IIGPLMA8GA1UdEwEB +/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAZRXdBfSqhY+xELs28/gjsZ4/mUvu +LKL3PruRCNqUgIOznEdxsQXsmLIQhEPZ4a4jd31srFD2j5gJmZ8KdeFXII9NRvIX +RpRcrl2uclHXWbIC7s6xiATDWumrL2nXB5bU4qYMZ0ybytXprIwkzqRFXUrEHcYm +OXJCSKayIviQ6G0= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Root_11/demoCA/crlnumber new file mode 100644 index 0000000000..83b33d238d --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/crlnumber @@ -0,0 +1 @@ +1000 diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Root_11/demoCA/index.txt new file mode 100644 index 0000000000..f6c52e5ac2 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/index.txt @@ -0,0 +1,35 @@ +V 350108161110Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\xC5\xB9\xC5\xBA\xC5\xBB\xC5\xBC\xC5\xBD\xC5\xBE \xEF\xAC\xB3 j\xCE\xAC\xCE\xAD\xCE\xAE +V 350108161614Z 1001 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\xC5\xB9\xC5\xBA\xC5\xBB\xC5\xBC\xC5\xBD\xC5\xBE \xEF\xAD\x86 j\xCE\xAC\xCE\xAD\xCE\xAE +V 350112144417Z 1002 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x04\x0F\x04\x10\x04\x11\x04\x12\x04\x13\x04\x14 +V 350112153942Z 1003 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x01y\x01z\x01{\x00 \x03\xA6\x03\xA7\x03\xA8\x03\xA9 +V 350112160038Z 1004 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00"\x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00s\x00" +V 350112160547Z 1005 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00"\x00"\x00d\x00o\x00u\x00b\x00l\x00e\x00 \x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00s\x00"\x00" +V 350112160921Z 1006 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00"\x00"\x00t\x00w\x00o\x00 \x00s\x00t\x00a\x00r\x00t\x00i\x00n\x00g\x00 \x00o\x00n\x00e\x00 \x00e\x00n\x00d\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00" +V 350112161153Z 1007 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00"\x00s\x00t\x00a\x00r\x00t\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e +V 350112161405Z 1008 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00e\x00n\x00d\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00" +V 350112161631Z 1009 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00"\x00q\x00u\x00o\x00t\x00e +V 350112161857Z 100A unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00d\x00o\x00u\x00b\x00l\x00e\x00 \x00"\x00"\x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00q\x00u\x00o\x00t\x00e +V 350113090237Z 100B unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00p\x00a\x00r\x00t\x00i\x00a\x00l\x00l\x00y\x00 \x00"\x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00" +V 350113094852Z 100C unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00"\x00U\x00s\x00e\x00r\x00 \x001\x001\x00,\x00 \x00s\x00t\x00a\x00r\x00t\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e +V 350113095110Z 100D unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00U\x00s\x00e\x00r\x00 \x001\x002\x00,\x00 \x00e\x00n\x00d\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00" +V 350113095308Z 100E unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00"\x00U\x00s\x00e\x00r\x00 \x001\x003\x00,\x00 \x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00s\x00" +V 350113095502Z 100F unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00U\x00s\x00e\x00r\x00 \x001\x004\x00 \x00"\x00,\x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00q\x00u\x00o\x00t\x00e\x00" +V 350113095752Z 1010 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00\\x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00s\x00\ +V 350113095922Z 1011 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00\\x00\\x00d\x00o\x00u\x00b\x00l\x00e\x00 \x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00s\x00\\x00\ +V 350113100207Z 1012 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00\\x00\\x00t\x00w\x00o\x00 \x00s\x00t\x00a\x00r\x00t\x00i\x00n\x00g\x00 \x00o\x00n\x00e\x00 \x00e\x00n\x00d\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00\ +V 350113100436Z 1013 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00\\x00s\x00t\x00a\x00r\x00t\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e +V 350113100550Z 1014 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00e\x00n\x00d\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00\ +V 350113100707Z 1015 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00\\x00q\x00u\x00o\x00t\x00e +V 350113100950Z 1016 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00d\x00o\x00u\x00b\x00l\x00e\x00 \x00\\x00\\x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00q\x00u\x00o\x00t\x00e +V 350113101153Z 1017 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00p\x00a\x00r\x00t\x00i\x00a\x00l\x00l\x00y\x00 \x00\\x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00\ +V 350113101338Z 1018 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00\\x00U\x00s\x00e\x00r\x00 \x002\x003\x00,\x00 \x00s\x00t\x00a\x00r\x00t\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e +V 350113101450Z 1019 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00U\x00s\x00e\x00r\x00 \x002\x004\x00,\x00 \x00e\x00n\x00d\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00\ +V 350113101610Z 101A unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00\\x00U\x00s\x00e\x00r\x00 \x002\x005\x00,\x00 \x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00\ +V 350113101745Z 101B unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00U\x00s\x00e\x00r\x00 \x002\x006\x00\\x00,\x00 \x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00q\x00u\x00o\x00t\x00e +V 350113101913Z 101C unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=comma, comma, comma , +V 350113102047Z 101D unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=equal CN=User 28 +V 350113102213Z 101E unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 29+OU=ooo +V 350113102601Z 101F unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00U\x00s\x00e\x00r\x00 \x003\x000\x00<\x00 \x00>\x00#\x00;\x00 \x00"\x00+\x00" +V 350113102847Z 1020 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00U\x00s\x00e\x00r\x00 \x003\x001\x00 \x00\\x00"\x00a\x00,\x00b\x00"\x00+\x00C\x00N\x00=\x00U\x00S\x00,\x00 \x00>\x00 \x00\\x00\\x00d\x00e\x00 \x00< +V 350113104059Z 1021 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00U\x00s\x00e\x00r\x00 \x001\x004\x00 \x00"\x00,\x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00q\x00u\x00o\x00t\x00e +V 111108105139Z 1022 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 35 diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Root_11/demoCA/index.txt.attr new file mode 100644 index 0000000000..8f7e63a347 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1000.pem new file mode 100644 index 0000000000..6efde26f7e --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1000.pem @@ -0,0 +1,57 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 14 16:11:10 2010 GMT + Not After : Jan 8 16:11:10 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\xC5\xB9\xC5\xBA\xC5\xBB\xC5\xBC\xC5\xBD\xC5\xBE \xEF\xAC\xB3 j\xCE\xAC\xCE\xAD\xCE\xAE + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:c5:8e:23:dc:00:60:ab:13:ac:00:15:c8:2f:13: + 04:4a:05:15:38:1e:ea:43:cb:68:8e:e3:08:cc:a4: + bb:ef:78:3e:4a:d3:3c:89:50:95:c4:16:6f:a4:89: + 97:4a:07:ad:17:b4:96:1e:54:87:82:ed:22:a4:15: + f7:cf:09:83:b7:4d:ee:75:70:8c:71:5a:b8:e7:4d: + 27:b4:f8:eb:19:67:8f:58:3f:4c:5f:b3:ca:aa:bd: + 5b:95:d7:b4:ba:d4:bc:0e:69:01:52:b9:8a:2d:55: + 83:9e:4d:3f:01:0c:f1:d7:bd:c9:82:54:d2:71:d6: + 51:9c:55:4c:a3:82:43:35:2f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + CA:DF:DA:1A:F7:9C:D8:41:19:34:69:EA:67:74:68:CA:A3:24:0F:9F + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + Signature Algorithm: sha1WithRSAEncryption + 28:3a:db:4b:fd:15:4c:bb:ea:74:b4:53:4f:75:2a:92:3c:78: + b6:86:aa:39:bc:b0:67:3a:5a:00:f1:1e:74:5c:c7:2b:19:4f: + f4:c0:4d:ff:01:4c:b2:0f:b5:49:14:c3:9a:96:ce:61:b6:c7: + 37:82:44:75:76:fc:bd:5d:74:f9:22:ae:f2:36:cb:20:b7:e3: + c8:c8:01:ae:d5:01:f6:5e:b4:cb:ca:76:fe:72:98:f3:0a:c3: + ac:76:fa:41:67:b4:5c:92:67:fa:ca:17:02:80:00:d8:b6:d5: + 01:03:89:25:97:96:60:86:0c:0b:d8:64:94:c9:77:43:28:06: + f9:4e +-----BEGIN CERTIFICATE----- +MIIClzCCAgCgAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTQxNjEx +MTBaFw0zNTAxMDgxNjExMTBaMHExCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxITAfBgNVBAMUGMW5xbrFu8W8xb3FviDvrLMgas6szq3OrjCBnzANBgkqhkiG +9w0BAQEFAAOBjQAwgYkCgYEAxY4j3ABgqxOsABXILxMESgUVOB7qQ8tojuMIzKS7 +73g+StM8iVCVxBZvpImXSgetF7SWHlSHgu0ipBX3zwmDt03udXCMcVq4500ntPjr +GWePWD9MX7PKqr1blde0utS8DmkBUrmKLVWDnk0/AQzx173JglTScdZRnFVMo4JD +NS8CAwEAAaNPME0wCwYDVR0PBAQDAgXgMB0GA1UdDgQWBBTK39oa95zYQRk0aepn +dGjKoyQPnzAfBgNVHSMEGDAWgBToarvCkOpscCI+9vZIGwPmvremVTANBgkqhkiG +9w0BAQUFAAOBgQAoOttL/RVMu+p0tFNPdSqSPHi2hqo5vLBnOloA8R50XMcrGU/0 +wE3/AUyyD7VJFMOals5htsc3gkR1dvy9XXT5Iq7yNssgt+PIyAGu1QH2XrTLynb+ +cpjzCsOsdvpBZ7Rckmf6yhcCgADYttUBA4kll5ZghgwL2GSUyXdDKAb5Tg== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1002.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1002.pem new file mode 100644 index 0000000000..037410ad79 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1002.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4098 (0x1002) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 18 14:44:17 2010 GMT + Not After : Jan 12 14:44:17 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x04\x0F\x04\x10\x04\x11\x04\x12\x04\x13\x04\x14 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:b4:d3:fd:a0:56:2b:d9:72:66:e3:fc:4b:5b:70: + fb:9c:23:10:0b:b9:8a:c4:d1:dd:1d:37:cd:20:f4: + 9d:52:c3:8f:80:14:26:c4:3e:dc:3d:af:38:86:70: + 2f:e1:54:1c:a6:5e:b6:6a:2d:73:b4:2d:88:7c:ed: + eb:63:34:bf:ef:d0:a8:e0:00:ea:f0:24:50:68:3b: + ff:03:4a:22:e0:eb:5c:a4:e8:65:e4:c7:e7:38:e9: + ce:0c:44:3e:36:08:fe:82:d8:50:b9:13:43:3b:17: + 77:09:ef:7b:cc:9f:b4:7d:5d:f7:ab:8e:ab:c0:11: + bc:7a:07:ea:98:51:c0:27:1f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 49:1F:9A:43:D9:43:B9:89:0C:00:D9:90:C8:BC:9C:67:CD:8D:3E:C6 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 2 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 03:bc:24:ba:71:8b:4f:cc:3a:60:5a:04:13:15:4e:b0:79:e7: + 94:6c:9b:3b:4c:5d:d8:26:75:f5:94:04:71:5a:3e:b9:8c:5f: + b5:3d:e0:bb:8b:64:71:8f:0d:9a:99:b8:ff:ec:14:c0:c0:ca: + 63:5a:4e:1d:75:77:7a:2f:fb:12:90:25:44:ba:d8:2f:03:39: + 86:ef:88:4a:cc:69:79:0b:ff:a6:66:83:45:08:17:0b:0c:05: + f9:25:7c:6a:30:05:b3:61:df:1a:fe:2c:ca:49:e9:73:bd:b3: + 11:6b:bf:04:b0:a6:46:76:21:40:95:5c:78:b3:aa:4b:fd:03: + ee:51 +-----BEGIN CERTIFICATE----- +MIICszCCAhygAwIBAgICEAIwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTgxNDQ0 +MTdaFw0zNTAxMTIxNDQ0MTdaMGUxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxFTATBgNVBAMeDAQPBBAEEQQSBBMEFDCBnzANBgkqhkiG9w0BAQEFAAOBjQAw +gYkCgYEAtNP9oFYr2XJm4/xLW3D7nCMQC7mKxNHdHTfNIPSdUsOPgBQmxD7cPa84 +hnAv4VQcpl62ai1ztC2IfO3rYzS/79Co4ADq8CRQaDv/A0oi4OtcpOhl5MfnOOnO +DEQ+Ngj+gthQuRNDOxd3Ce97zJ+0fV33q46rwBG8egfqmFHAJx8CAwEAAaN3MHUw +CwYDVR0PBAQDAgXgMB0GA1UdDgQWBBRJH5pD2UO5iQwA2ZDIvJxnzY0+xjAfBgNV +HSMEGDAWgBToarvCkOpscCI+9vZIGwPmvremVTAmBgNVHREEHzAdpBswGTEXMBUG +A1UEAxMOVXNlciAyIFJvb3QgMTEwDQYJKoZIhvcNAQEFBQADgYEAA7wkunGLT8w6 +YFoEExVOsHnnlGybO0xd2CZ19ZQEcVo+uYxftT3gu4tkcY8Nmpm4/+wUwMDKY1pO +HXV3ei/7EpAlRLrYLwM5hu+ISsxpeQv/pmaDRQgXCwwF+SV8ajAFs2HfGv4syknp +c72zEWu/BLCmRnYhQJVceLOqS/0D7lE= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1003.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1003.pem new file mode 100644 index 0000000000..95589b2271 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1003.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4099 (0x1003) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 18 15:39:42 2010 GMT + Not After : Jan 12 15:39:42 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x01y\x01z\x01{\x00 \x03\xA6\x03\xA7\x03\xA8\x03\xA9 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:d6:d8:62:3c:69:c9:dd:93:b3:e9:65:63:89:03: + 4e:f8:8a:e1:8b:9d:92:c6:43:ca:8e:af:fd:6e:9c: + c7:66:31:48:f4:ce:5e:be:38:c5:6c:1b:48:c9:61: + f5:78:8a:e9:74:ac:a8:98:9c:83:f9:b0:74:e3:25: + 7c:5a:bb:df:5f:73:ef:fc:a0:dc:6a:ac:07:a2:b8: + 52:ea:7a:42:ba:9f:74:3c:00:cc:26:46:ba:90:5d: + 45:78:02:57:e7:47:9f:8e:94:9c:5a:31:ab:f3:ff: + bc:9f:7f:d9:b0:a6:f6:86:70:a6:9d:52:ff:c8:19: + 47:88:75:78:6a:73:d5:97:e9 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + E3:01:F6:1E:51:6D:FC:DB:BF:82:A9:12:21:4B:E2:46:FF:E8:EE:FF + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 1 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 68:f0:88:18:d5:98:63:da:42:39:47:bf:51:22:f6:0b:8e:46: + b0:8c:83:b0:4d:07:a4:e3:a9:66:76:4d:41:23:1a:6b:dc:d8: + d1:85:b1:bf:4f:f9:e6:01:4a:36:a9:a3:26:2d:0b:33:cc:36: + 97:c6:40:b6:77:26:1c:06:f2:1b:fa:0a:ef:5c:61:8d:0d:9c: + 3c:d3:0f:db:dd:60:69:8c:24:c6:70:bc:f8:3b:38:19:90:7a: + f3:4f:7e:7c:b7:69:b6:0f:55:e1:4b:da:77:cd:b1:fe:5f:f1: + c1:8a:f8:3d:26:10:3d:40:6f:83:17:0a:d8:dd:da:a1:27:10: + a1:73 +-----BEGIN CERTIFICATE----- +MIICtzCCAiCgAwIBAgICEAMwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTgxNTM5 +NDJaFw0zNTAxMTIxNTM5NDJaMGkxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxGTAXBgNVBAMeEAF5AXoBewAgA6YDpwOoA6kwgZ8wDQYJKoZIhvcNAQEBBQAD +gY0AMIGJAoGBANbYYjxpyd2Ts+llY4kDTviK4YudksZDyo6v/W6cx2YxSPTOXr44 +xWwbSMlh9XiK6XSsqJicg/mwdOMlfFq7319z7/yg3GqsB6K4Uup6QrqfdDwAzCZG +upBdRXgCV+dHn46UnFoxq/P/vJ9/2bCm9oZwpp1S/8gZR4h1eGpz1ZfpAgMBAAGj +dzB1MAsGA1UdDwQEAwIF4DAdBgNVHQ4EFgQU4wH2HlFt/Nu/gqkSIUviRv/o7v8w +HwYDVR0jBBgwFoAU6Gq7wpDqbHAiPvb2SBsD5r63plUwJgYDVR0RBB8wHaQbMBkx +FzAVBgNVBAMTDlVzZXIgMSBSb290IDExMA0GCSqGSIb3DQEBBQUAA4GBAGjwiBjV +mGPaQjlHv1Ei9guORrCMg7BNB6TjqWZ2TUEjGmvc2NGFsb9P+eYBSjapoyYtCzPM +NpfGQLZ3JhwG8hv6Cu9cYY0NnDzTD9vdYGmMJMZwvPg7OBmQevNPfny3abYPVeFL +2nfNsf5f8cGK+D0mED1Ab4MXCtjd2qEnEKFz +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1004.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1004.pem new file mode 100644 index 0000000000..6f57ca6845 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1004.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4100 (0x1004) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 18 16:00:38 2010 GMT + Not After : Jan 12 16:00:38 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00"\x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00s\x00" + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:c9:ff:37:16:4d:7a:ad:59:bd:f2:c4:dc:4f:79: + 6a:f6:21:c7:ef:cd:af:f1:39:34:24:92:f4:46:d3: + 8b:43:31:55:11:3e:22:2b:85:19:38:ed:0b:35:3c: + 73:fc:b9:17:e8:73:99:21:a2:20:30:b4:e9:11:c6: + 7a:61:fa:fa:fe:eb:c8:30:c4:73:5f:77:f2:fc:42: + b7:10:29:ac:9e:8a:c2:df:25:9b:44:17:05:a3:39: + d9:1b:58:62:fb:2c:86:07:f7:f0:28:7b:5a:38:1b: + 6a:de:88:fb:ad:32:f4:53:e2:a1:c5:0f:68:db:64: + ae:39:2a:5e:02:d0:b5:38:07 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 86:2F:46:D0:A9:F9:3F:22:BD:57:83:51:35:F9:67:11:A2:00:AB:33 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 3 Root 11 + Signature Algorithm: sha1WithRSAEncryption + bb:f6:61:ae:30:94:3a:4a:d6:d5:cb:b5:50:bb:ca:0e:ab:9f: + 09:e9:78:d4:2f:20:fe:18:4e:d8:61:db:97:28:a9:d9:dc:e5: + 06:f8:6c:41:c2:5a:95:53:47:7e:a7:73:c9:45:4f:6b:30:fc: + fd:17:9a:7b:a9:d8:27:57:a9:fd:8d:e7:7e:4b:3e:98:11:42: + 00:39:1a:55:4b:3d:a5:de:75:3c:43:5a:33:10:d3:cf:4e:04: + 0a:71:d4:93:2b:0b:2b:15:82:7b:04:46:9b:50:da:18:84:66: + 31:75:36:5b:09:eb:82:5d:7d:e1:35:a3:a4:6c:b2:ac:c8:fa: + bd:5f +-----BEGIN CERTIFICATE----- +MIICyzCCAjSgAwIBAgICEAQwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTgxNjAw +MzhaFw0zNTAxMTIxNjAwMzhaMH0xCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxLTArBgNVBAMeJAAiAGUAbgBjAGwAbwBzAGkAbgBnACAAcQB1AG8AdABlAHMA +IjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAyf83Fk16rVm98sTcT3lq9iHH +782v8Tk0JJL0RtOLQzFVET4iK4UZOO0LNTxz/LkX6HOZIaIgMLTpEcZ6Yfr6/uvI +MMRzX3fy/EK3ECmsnorC3yWbRBcFoznZG1hi+yyGB/fwKHtaOBtq3oj7rTL0U+Kh +xQ9o22SuOSpeAtC1OAcCAwEAAaN3MHUwCwYDVR0PBAQDAgXgMB0GA1UdDgQWBBSG +L0bQqfk/Ir1Xg1E1+WcRogCrMzAfBgNVHSMEGDAWgBToarvCkOpscCI+9vZIGwPm +vremVTAmBgNVHREEHzAdpBswGTEXMBUGA1UEAxMOVXNlciAzIFJvb3QgMTEwDQYJ +KoZIhvcNAQEFBQADgYEAu/ZhrjCUOkrW1cu1ULvKDqufCel41C8g/hhO2GHblyip +2dzlBvhsQcJalVNHfqdzyUVPazD8/Reae6nYJ1ep/Y3nfks+mBFCADkaVUs9pd51 +PENaMxDTz04ECnHUkysLKxWCewRGm1DaGIRmMXU2Wwnrgl194TWjpGyyrMj6vV8= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1005.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1005.pem new file mode 100644 index 0000000000..3a2f7522d1 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1005.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4101 (0x1005) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 18 16:05:47 2010 GMT + Not After : Jan 12 16:05:47 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00"\x00"\x00d\x00o\x00u\x00b\x00l\x00e\x00 \x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00s\x00"\x00" + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:de:4d:31:93:c5:1b:7c:2b:85:86:da:89:3d:06: + 6f:6d:44:a5:de:6c:6a:06:28:b0:96:7b:40:34:01: + af:e4:b1:f4:93:f1:25:78:b0:43:ea:92:2a:87:60: + e8:be:7e:c9:b6:02:f8:14:93:1b:b8:5f:cb:2c:24: + e2:80:24:f0:5c:6d:77:f2:dc:ef:90:d6:d1:78:22: + 53:f0:7f:45:ad:f2:1a:9d:25:08:13:c8:62:6b:9e: + 88:79:3d:9e:b4:0a:05:11:79:7d:a1:b2:46:89:f3: + 45:ce:f3:22:2e:17:ab:e1:a9:b1:04:93:3b:f3:ca: + e6:60:c0:fd:91:7f:34:80:65 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + C1:6E:6A:FB:5A:B1:0C:67:07:C8:7E:F1:8D:86:F6:D0:27:56:6D:73 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 4 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 61:72:4b:33:1d:60:91:08:19:4f:ff:ec:8e:9e:83:71:d7:00: + 96:0a:b5:82:b7:8c:a6:3f:70:64:36:ac:25:a7:f1:a9:83:f1: + 63:f8:29:06:fa:58:86:8a:fd:25:9e:77:38:dd:c7:3b:cd:68: + 91:8e:f4:57:42:c9:6b:88:87:ec:24:57:38:84:fb:c0:d9:bc: + 6c:1c:6e:9d:9d:b9:da:cc:7e:fe:f9:bd:29:be:14:26:6f:63: + 1f:6f:6a:f1:dd:fd:d2:03:69:f2:36:e1:35:e0:57:72:d5:e3: + 09:ee:6a:08:45:b4:73:e9:d1:18:c2:38:1d:86:53:53:6d:bf: + f0:1e +-----BEGIN CERTIFICATE----- +MIIC3jCCAkegAwIBAgICEAUwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTgxNjA1 +NDdaFw0zNTAxMTIxNjA1NDdaMIGPMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MT8wPQYDVQQDHjYAIgAiAGQAbwB1AGIAbABlACAAZQBuAGMAbABvAHMAaQBu +AGcAIABxAHUAbwB0AGUAcwAiACIwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB +AN5NMZPFG3wrhYbaiT0Gb21Epd5sagYosJZ7QDQBr+Sx9JPxJXiwQ+qSKodg6L5+ +ybYC+BSTG7hfyywk4oAk8Fxtd/Lc75DW0XgiU/B/Ra3yGp0lCBPIYmueiHk9nrQK +BRF5faGyRonzRc7zIi4Xq+GpsQSTO/PK5mDA/ZF/NIBlAgMBAAGjdzB1MAsGA1Ud +DwQEAwIF4DAdBgNVHQ4EFgQUwW5q+1qxDGcHyH7xjYb20CdWbXMwHwYDVR0jBBgw +FoAU6Gq7wpDqbHAiPvb2SBsD5r63plUwJgYDVR0RBB8wHaQbMBkxFzAVBgNVBAMT +DlVzZXIgNCBSb290IDExMA0GCSqGSIb3DQEBBQUAA4GBAGFySzMdYJEIGU//7I6e +g3HXAJYKtYK3jKY/cGQ2rCWn8amD8WP4KQb6WIaK/SWedzjdxzvNaJGO9FdCyWuI +h+wkVziE+8DZvGwcbp2dudrMfv75vSm+FCZvYx9vavHd/dIDafI24TXgV3LV4wnu +aghFtHPp0RjCOB2GU1Ntv/Ae +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1006.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1006.pem new file mode 100644 index 0000000000..cb72b8d161 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1006.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4102 (0x1006) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 18 16:09:21 2010 GMT + Not After : Jan 12 16:09:21 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00"\x00"\x00t\x00w\x00o\x00 \x00s\x00t\x00a\x00r\x00t\x00i\x00n\x00g\x00 \x00o\x00n\x00e\x00 \x00e\x00n\x00d\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00" + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:d1:a4:91:c7:28:84:f8:54:63:09:1f:bc:2e:4e: + a3:be:54:01:42:2e:f7:ef:4f:b8:46:a9:35:b1:b3: + 29:0e:8b:f7:b5:fa:b7:71:5b:33:03:ac:e6:b5:f6: + ba:f5:ba:21:72:ed:7d:ea:f0:f1:2c:55:2a:a9:c6: + d8:54:ef:12:f0:f5:37:ca:57:b2:3c:ce:7c:5a:57: + 86:68:a2:51:82:80:bd:58:a5:04:1c:e8:cf:f6:5b: + 4e:d2:6a:79:63:eb:ac:52:7c:61:8c:fe:0a:6b:b2: + f6:16:9c:94:ae:a6:f6:69:b9:d5:0b:26:0d:01:7f: + 62:d2:58:c2:02:53:25:63:0d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 45:DF:D7:35:D1:13:E4:8F:E3:0D:E3:7E:A9:9A:5D:56:00:64:4E:43 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 5 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 9d:bd:dc:dc:8e:a8:e8:e4:15:cb:14:c1:6a:ab:d8:ab:e6:e5: + 4f:f5:a8:8b:2c:ab:80:e2:31:f9:89:d8:12:ba:9c:4f:b3:f5: + bb:7e:ee:8b:df:58:d3:b2:ee:f8:c5:46:c3:5d:2e:a9:35:d0: + 7a:1e:80:18:14:4d:78:6e:f1:c8:9a:51:db:86:3e:2c:04:4a: + 0a:2f:f1:7a:01:e3:1b:31:d7:1d:f1:32:c4:04:db:b9:7e:c4: + fd:b0:c1:41:3f:8a:b3:88:4f:4a:9c:a6:38:11:2a:4a:0f:8b: + d0:9a:8a:2c:33:fe:7f:42:b5:93:8d:54:df:de:2b:b1:08:5c: + d9:0d +-----BEGIN CERTIFICATE----- +MIIC6DCCAlGgAwIBAgICEAYwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTgxNjA5 +MjFaFw0zNTAxMTIxNjA5MjFaMIGZMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MUkwRwYDVQQDHkAAIgAiAHQAdwBvACAAcwB0AGEAcgB0AGkAbgBnACAAbwBu +AGUAIABlAG4AZABpAG4AZwAgAHEAdQBvAHQAZQAiMIGfMA0GCSqGSIb3DQEBAQUA +A4GNADCBiQKBgQDRpJHHKIT4VGMJH7wuTqO+VAFCLvfvT7hGqTWxsykOi/e1+rdx +WzMDrOa19rr1uiFy7X3q8PEsVSqpxthU7xLw9TfKV7I8znxaV4ZoolGCgL1YpQQc +6M/2W07Sanlj66xSfGGM/gprsvYWnJSupvZpudULJg0Bf2LSWMICUyVjDQIDAQAB +o3cwdTALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFEXf1zXRE+SP4w3jfqmaXVYAZE5D +MB8GA1UdIwQYMBaAFOhqu8KQ6mxwIj729kgbA+a+t6ZVMCYGA1UdEQQfMB2kGzAZ +MRcwFQYDVQQDEw5Vc2VyIDUgUm9vdCAxMTANBgkqhkiG9w0BAQUFAAOBgQCdvdzc +jqjo5BXLFMFqq9ir5uVP9aiLLKuA4jH5idgSupxPs/W7fu6L31jTsu74xUbDXS6p +NdB6HoAYFE14bvHImlHbhj4sBEoKL/F6AeMbMdcd8TLEBNu5fsT9sMFBP4qziE9K +nKY4ESpKD4vQmoosM/5/QrWTjVTf3iuxCFzZDQ== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1007.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1007.pem new file mode 100644 index 0000000000..ce9b36d12d --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1007.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4103 (0x1007) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 18 16:11:53 2010 GMT + Not After : Jan 12 16:11:53 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00"\x00s\x00t\x00a\x00r\x00t\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:d1:99:9c:20:2e:65:ee:0f:ce:cb:8a:d8:70:c8: + 04:3c:ac:2f:14:7c:6c:8f:5e:95:36:f8:53:74:5b: + 88:bf:a1:43:73:04:ab:3a:42:b4:7c:2c:3c:3b:63: + 7e:ef:82:c5:bb:b1:28:9b:8b:b7:29:72:3d:30:08: + e9:a2:d7:4b:08:e2:2e:e6:d4:9f:75:29:31:23:be: + b4:30:5d:94:30:41:38:a1:d5:34:bc:69:f5:d8:8d: + c6:08:cc:28:4a:92:22:2b:19:89:f5:ad:7c:49:89: + b3:63:c6:e5:6c:86:d7:62:05:1b:97:db:2d:fb:c2: + 47:e5:51:a6:f0:50:6f:e3:53 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 5F:DA:34:F6:6F:BA:9E:12:99:DC:02:2A:4C:3E:8C:0D:14:A1:9B:2B + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 6 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 24:af:11:b6:1a:5c:d1:bf:70:93:85:c0:2e:10:96:4d:b7:ad: + 4e:d7:c4:7e:87:a1:3b:20:d7:bf:04:07:cc:91:13:0c:ad:66: + 08:d6:2e:b6:d0:aa:d0:45:0e:c0:92:3d:7c:a6:82:19:04:3c: + 9a:b3:5e:e8:fe:9e:5c:d6:17:75:73:e3:3c:64:0c:ae:5d:92: + 2a:eb:0e:ef:04:f5:ce:a5:7f:1f:2f:1d:05:a0:70:f4:24:80: + c3:38:35:2d:e5:ac:a7:11:4a:3e:a2:b2:d1:14:91:ba:b0:d8: + 5f:be:80:8a:34:2c:72:fb:00:47:88:47:9e:34:65:12:ad:9f: + ff:99 +-----BEGIN CERTIFICATE----- +MIICxTCCAi6gAwIBAgICEAcwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTgxNjEx +NTNaFw0zNTAxMTIxNjExNTNaMHcxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxJzAlBgNVBAMeHgAiAHMAdABhAHIAdABpAG4AZwAgAHEAdQBvAHQAZTCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0ZmcIC5l7g/Oy4rYcMgEPKwvFHxsj16V +NvhTdFuIv6FDcwSrOkK0fCw8O2N+74LFu7Eom4u3KXI9MAjpotdLCOIu5tSfdSkx +I760MF2UMEE4odU0vGn12I3GCMwoSpIiKxmJ9a18SYmzY8blbIbXYgUbl9st+8JH +5VGm8FBv41MCAwEAAaN3MHUwCwYDVR0PBAQDAgXgMB0GA1UdDgQWBBRf2jT2b7qe +EpncAipMPowNFKGbKzAfBgNVHSMEGDAWgBToarvCkOpscCI+9vZIGwPmvremVTAm +BgNVHREEHzAdpBswGTEXMBUGA1UEAxMOVXNlciA2IFJvb3QgMTEwDQYJKoZIhvcN +AQEFBQADgYEAJK8Rthpc0b9wk4XALhCWTbetTtfEfoehOyDXvwQHzJETDK1mCNYu +ttCq0EUOwJI9fKaCGQQ8mrNe6P6eXNYXdXPjPGQMrl2SKusO7wT1zqV/Hy8dBaBw +9CSAwzg1LeWspxFKPqKy0RSRurDYX76AijQscvsAR4hHnjRlEq2f/5k= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1008.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1008.pem new file mode 100644 index 0000000000..8d6f2bd25c --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1008.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4104 (0x1008) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 18 16:14:05 2010 GMT + Not After : Jan 12 16:14:05 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00e\x00n\x00d\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00" + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:a6:a8:3f:60:a7:9a:3b:20:c9:2c:8c:4f:cd:11: + 1f:0d:a9:2a:2c:eb:12:80:0c:55:8a:4d:06:ef:b2: + 5f:2e:47:be:0d:10:22:8a:15:57:29:4a:90:63:f9: + 1c:13:85:47:c7:c9:b9:76:09:10:a9:b1:94:5c:8d: + c9:f4:01:26:43:e4:d4:98:d6:00:1a:d4:cd:2a:d1: + cd:7e:4c:4e:ab:18:78:5a:fb:b2:ec:a3:87:a1:0e: + 84:3f:70:cf:ca:02:24:c8:d7:1b:83:a3:ac:a5:f0: + 10:c5:de:b7:a2:6c:0b:0c:9d:ab:32:a3:1a:c9:ae: + 9b:48:a8:65:cd:50:db:0b:cf + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 91:32:56:26:62:63:A1:32:B0:BC:D0:91:F1:D8:F2:94:CB:10:F1:91 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 7 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 4c:d5:2f:ab:fb:83:f8:11:c9:d2:df:aa:dc:e9:b8:38:2e:53: + e1:3a:5b:bb:0a:bf:72:f7:47:b5:57:de:82:8a:e6:bb:7d:62: + af:1b:9c:8e:4a:f5:cf:0b:ac:e9:06:16:ca:59:f1:7f:d7:45: + c0:88:84:ee:f4:c7:8b:e0:39:aa:c7:b7:95:b9:fe:a2:4a:3a: + 41:df:d0:02:bf:6f:54:30:9a:9a:0a:a6:04:5f:f4:17:52:d6: + c2:39:43:5e:b9:a3:86:0f:3d:ad:eb:a3:81:f4:cc:90:29:17: + dc:46:5e:6b:9c:f6:70:0f:b2:0f:dc:0f:9c:9f:09:6c:fa:31: + 6c:01 +-----BEGIN CERTIFICATE----- +MIICwTCCAiqgAwIBAgICEAgwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTgxNjE0 +MDVaFw0zNTAxMTIxNjE0MDVaMHMxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxIzAhBgNVBAMeGgBlAG4AZABpAG4AZwAgAHEAdQBvAHQAZQAiMIGfMA0GCSqG +SIb3DQEBAQUAA4GNADCBiQKBgQCmqD9gp5o7IMksjE/NER8NqSos6xKADFWKTQbv +sl8uR74NECKKFVcpSpBj+RwThUfHybl2CRCpsZRcjcn0ASZD5NSY1gAa1M0q0c1+ +TE6rGHha+7Lso4ehDoQ/cM/KAiTI1xuDo6yl8BDF3reibAsMnasyoxrJrptIqGXN +UNsLzwIDAQABo3cwdTALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFJEyViZiY6EysLzQ +kfHY8pTLEPGRMB8GA1UdIwQYMBaAFOhqu8KQ6mxwIj729kgbA+a+t6ZVMCYGA1Ud +EQQfMB2kGzAZMRcwFQYDVQQDEw5Vc2VyIDcgUm9vdCAxMTANBgkqhkiG9w0BAQUF +AAOBgQBM1S+r+4P4EcnS36rc6bg4LlPhOlu7Cr9y90e1V96Ciua7fWKvG5yOSvXP +C6zpBhbKWfF/10XAiITu9MeL4Dmqx7eVuf6iSjpB39ACv29UMJqaCqYEX/QXUtbC +OUNeuaOGDz2t66OB9MyQKRfcRl5rnPZwD7IP3A+cnwls+jFsAQ== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1009.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1009.pem new file mode 100644 index 0000000000..c1a94dae5d --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1009.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4105 (0x1009) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 18 16:16:31 2010 GMT + Not After : Jan 12 16:16:31 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00"\x00q\x00u\x00o\x00t\x00e + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:b4:3b:c7:b0:6c:b5:f2:b3:a5:79:89:54:de:af: + 03:3c:0e:c9:57:15:8e:73:2a:48:83:18:59:ce:b4: + 12:fb:5c:92:28:69:75:18:f9:0f:24:15:95:38:b2: + 4c:81:07:90:97:3b:d7:3a:ab:a6:92:5a:9f:5a:1f: + fe:14:ac:4d:b5:5e:6a:a6:0f:98:55:08:07:09:07: + a5:fb:79:9e:a0:2d:73:99:92:ad:6e:bc:75:36:d0: + b5:f1:1c:91:3a:d4:49:8a:60:1e:a7:01:2f:bc:d9: + cd:b4:f4:70:b4:38:d1:3c:d3:ee:00:df:b3:83:45: + 63:5c:5d:28:47:bc:b1:b9:57 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + D6:18:38:7B:14:4B:D6:72:42:A9:53:E2:1D:BE:81:88:26:DB:0A:06 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 8 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 98:f3:ac:db:7b:a0:00:d2:58:be:74:21:ff:09:29:4c:0c:1a: + 7a:1f:dd:e2:f3:f4:9a:52:5d:da:ac:10:30:f9:b8:93:10:60: + 46:bf:48:47:bd:af:87:a1:d9:c6:46:81:b3:0d:a4:f8:ba:ca: + 17:7c:f2:f9:46:03:62:7f:32:6b:f0:7c:75:a4:05:44:cb:10: + 42:36:ce:12:c0:b9:e5:5f:e0:7b:c6:c8:39:5c:0c:50:30:a0: + f6:fe:e1:a2:e6:00:b3:fc:86:56:11:66:d8:41:81:e3:4e:15: + e5:68:9d:1c:b0:c4:4f:ab:86:75:55:fa:39:58:3f:7c:68:03: + e0:76 +-----BEGIN CERTIFICATE----- +MIICwTCCAiqgAwIBAgICEAkwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTgxNjE2 +MzFaFw0zNTAxMTIxNjE2MzFaMHMxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxIzAhBgNVBAMeGgBtAGkAZABkAGwAZQAgACIAcQB1AG8AdABlMIGfMA0GCSqG +SIb3DQEBAQUAA4GNADCBiQKBgQC0O8ewbLXys6V5iVTerwM8DslXFY5zKkiDGFnO +tBL7XJIoaXUY+Q8kFZU4skyBB5CXO9c6q6aSWp9aH/4UrE21XmqmD5hVCAcJB6X7 +eZ6gLXOZkq1uvHU20LXxHJE61EmKYB6nAS+82c209HC0ONE80+4A37ODRWNcXShH +vLG5VwIDAQABo3cwdTALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFNYYOHsUS9ZyQqlT +4h2+gYgm2woGMB8GA1UdIwQYMBaAFOhqu8KQ6mxwIj729kgbA+a+t6ZVMCYGA1Ud +EQQfMB2kGzAZMRcwFQYDVQQDEw5Vc2VyIDggUm9vdCAxMTANBgkqhkiG9w0BAQUF +AAOBgQCY86zbe6AA0li+dCH/CSlMDBp6H93i8/SaUl3arBAw+biTEGBGv0hHva+H +odnGRoGzDaT4usoXfPL5RgNifzJr8Hx1pAVEyxBCNs4SwLnlX+B7xsg5XAxQMKD2 +/uGi5gCz/IZWEWbYQYHjThXlaJ0csMRPq4Z1Vfo5WD98aAPgdg== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100A.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100A.pem new file mode 100644 index 0000000000..a3a79bf831 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100A.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4106 (0x100a) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 18 16:18:57 2010 GMT + Not After : Jan 12 16:18:57 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00d\x00o\x00u\x00b\x00l\x00e\x00 \x00"\x00"\x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00q\x00u\x00o\x00t\x00e + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:e5:3f:d4:e1:d6:26:2a:c9:40:1d:34:3c:1e:e8: + f4:54:67:6b:6c:a5:b7:fe:04:bb:cb:0e:c0:2d:26: + 61:c1:81:80:9d:da:1b:fd:d3:7a:7a:57:78:c5:f6: + e6:4b:ad:2d:a2:8d:49:b3:ac:18:ca:1c:25:67:44: + 7c:8e:b5:ab:ec:f7:a8:da:b7:37:ed:77:76:b2:8f: + bb:15:b2:e3:45:5f:b2:2a:aa:27:b7:f1:bc:37:8f: + b7:b4:c5:ff:45:fd:67:04:25:47:2c:1a:a7:63:1e: + 97:f6:ac:d7:39:cf:ef:24:63:a1:87:9b:36:97:92: + fa:d9:4d:a9:fa:dd:c9:fb:75 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 62:F1:43:E3:B1:7B:98:0D:69:A4:8F:CF:32:F7:6D:E6:88:D6:23:90 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 9 Root 11 + Signature Algorithm: sha1WithRSAEncryption + ab:46:88:13:e8:02:63:4e:f2:a0:5a:48:7e:35:a4:c2:f8:55: + 33:cb:ef:45:55:30:81:a1:9e:c2:c7:43:cd:19:23:1f:df:3f: + 8b:b8:7e:69:5e:98:06:b1:47:dd:e5:05:e2:3a:19:cf:af:e3: + dd:7b:75:e5:53:b0:bc:4e:58:40:bf:3b:d2:9c:7f:9e:b1:66: + f8:3f:58:c4:5f:ab:be:1f:03:fb:89:47:a4:25:8a:1e:10:e0: + 20:33:70:07:13:92:32:e1:bf:92:6a:d5:89:03:2c:ad:e1:85: + 8c:b3:1d:ee:0c:35:70:2f:aa:e5:e0:77:97:b0:9b:a3:0d:22: + 6f:dc +-----BEGIN CERTIFICATE----- +MIIC0jCCAjugAwIBAgICEAowDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTgxNjE4 +NTdaFw0zNTAxMTIxNjE4NTdaMIGDMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MTMwMQYDVQQDHioAZABvAHUAYgBsAGUAIAAiACIAbQBpAGQAZABsAGUAIABx +AHUAbwB0AGUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOU/1OHWJirJQB00 +PB7o9FRna2ylt/4Eu8sOwC0mYcGBgJ3aG/3TenpXeMX25kutLaKNSbOsGMocJWdE +fI61q+z3qNq3N+13drKPuxWy40VfsiqqJ7fxvDePt7TF/0X9ZwQlRywap2Mel/as +1znP7yRjoYebNpeS+tlNqfrdyft1AgMBAAGjdzB1MAsGA1UdDwQEAwIF4DAdBgNV +HQ4EFgQUYvFD47F7mA1ppI/PMvdt5ojWI5AwHwYDVR0jBBgwFoAU6Gq7wpDqbHAi +Pvb2SBsD5r63plUwJgYDVR0RBB8wHaQbMBkxFzAVBgNVBAMTDlVzZXIgOSBSb290 +IDExMA0GCSqGSIb3DQEBBQUAA4GBAKtGiBPoAmNO8qBaSH41pML4VTPL70VVMIGh +nsLHQ80ZIx/fP4u4fmlemAaxR93lBeI6Gc+v4917deVTsLxOWEC/O9Kcf56xZvg/ +WMRfq74fA/uJR6Qlih4Q4CAzcAcTkjLhv5Jq1YkDLK3hhYyzHe4MNXAvquXgd5ew +m6MNIm/c +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100B.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100B.pem new file mode 100644 index 0000000000..75684732d7 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100B.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4107 (0x100b) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 09:02:37 2010 GMT + Not After : Jan 13 09:02:37 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00p\x00a\x00r\x00t\x00i\x00a\x00l\x00l\x00y\x00 \x00"\x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00" + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:ae:9f:8e:b8:88:8e:ed:53:aa:2a:2c:ed:f1:6c: + 99:47:9f:ab:8b:4e:8e:d8:2e:c2:78:2c:54:f9:29: + 14:27:b9:6a:3c:33:3f:06:51:ba:76:15:0a:16:60: + db:f2:f0:db:af:5b:38:be:18:42:b4:31:02:ba:6f: + 19:00:57:be:d0:f3:7c:6b:34:36:e8:7c:45:77:0d: + f5:d0:7c:0e:23:64:7c:59:02:5c:54:15:71:82:be: + 98:3f:c9:2d:f0:9e:d5:f0:32:02:44:61:5b:2f:71: + 16:13:9a:b3:2b:28:ff:d5:d8:3d:00:9c:eb:ec:b7: + 04:e2:b6:15:42:45:e5:ef:3f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 8C:2C:B6:8B:82:43:DC:41:EC:AC:D4:75:E8:DA:D8:3F:A9:A0:F5:31 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 10 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 48:a6:51:46:5b:44:a5:be:18:ed:8f:d4:c6:d2:3c:86:8f:e7: + e5:f4:a2:5d:51:aa:00:9b:bc:d8:b1:d3:f4:24:a0:a1:0d:80: + 2e:7e:62:26:ee:8c:4b:bd:79:0c:39:bd:6e:af:db:92:b6:03: + b1:b0:49:95:a7:59:28:54:30:33:fc:7e:2f:0f:a2:ce:90:27: + 29:b9:d8:3f:99:36:e9:81:9f:f5:fa:cb:f9:f2:05:b5:48:60: + 4d:50:4d:1e:ba:45:fd:f1:99:84:a6:79:0b:6b:76:eb:73:9d: + 5c:47:27:be:0d:23:0b:97:cc:9d:5a:80:fa:9b:ff:66:e7:37: + 60:a4 +-----BEGIN CERTIFICATE----- +MIIC3zCCAkigAwIBAgICEAswDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkwOTAy +MzdaFw0zNTAxMTMwOTAyMzdaMIGPMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MT8wPQYDVQQDHjYAcABhAHIAdABpAGEAbABsAHkAIAAiAGUAbgBjAGwAbwBz +AGkAbgBnACAAcQB1AG8AdABlACIwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB +AK6fjriIju1Tqios7fFsmUefq4tOjtguwngsVPkpFCe5ajwzPwZRunYVChZg2/Lw +269bOL4YQrQxArpvGQBXvtDzfGs0Nuh8RXcN9dB8DiNkfFkCXFQVcYK+mD/JLfCe +1fAyAkRhWy9xFhOasyso/9XYPQCc6+y3BOK2FUJF5e8/AgMBAAGjeDB2MAsGA1Ud +DwQEAwIF4DAdBgNVHQ4EFgQUjCy2i4JD3EHsrNR16NrYP6mg9TEwHwYDVR0jBBgw +FoAU6Gq7wpDqbHAiPvb2SBsD5r63plUwJwYDVR0RBCAwHqQcMBoxGDAWBgNVBAMT +D1VzZXIgMTAgUm9vdCAxMTANBgkqhkiG9w0BAQUFAAOBgQBIplFGW0Slvhjtj9TG +0jyGj+fl9KJdUaoAm7zYsdP0JKChDYAufmIm7oxLvXkMOb1ur9uStgOxsEmVp1ko +VDAz/H4vD6LOkCcpudg/mTbpgZ/1+sv58gW1SGBNUE0eukX98ZmEpnkLa3brc51c +Rye+DSMLl8ydWoD6m/9m5zdgpA== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100C.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100C.pem new file mode 100644 index 0000000000..115190ca67 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100C.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4108 (0x100c) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 09:48:52 2010 GMT + Not After : Jan 13 09:48:52 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00"\x00U\x00s\x00e\x00r\x00 \x001\x001\x00,\x00 \x00s\x00t\x00a\x00r\x00t\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:e2:8b:a9:94:06:b0:cb:e7:1b:a3:fd:7c:70:d1: + 66:e6:2d:aa:c7:ec:2e:e3:08:c3:39:3f:48:47:fd: + 09:67:2d:16:17:87:c0:e3:4d:c1:cc:6b:3f:c4:7b: + 74:d5:71:70:d6:74:8a:a2:17:fd:39:78:f8:c7:b3: + 42:54:ac:f7:07:d7:6f:55:da:03:15:11:e0:c2:d8: + 95:d2:87:c3:9c:3d:94:96:9d:01:81:5d:61:43:aa: + 4c:92:d5:68:aa:6c:73:88:52:7b:ee:9b:76:65:0d: + 2a:ae:3d:83:71:41:44:8b:23:7d:a6:f9:3c:81:56: + 6c:9b:52:96:87:c8:97:18:8d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 48:89:BE:3C:AA:C9:5A:38:6B:CA:FA:C8:B2:BB:F7:E1:44:4B:7B:08 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 11 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 23:c9:5b:f5:9f:59:ff:97:0b:79:35:2d:32:db:b7:4b:b1:c9: + 2b:1e:cf:88:7b:b4:4e:f0:ed:13:a3:64:85:8f:d6:70:b5:ed: + 2a:57:92:a0:b4:14:96:48:7a:aa:a4:19:59:df:d9:a9:0f:86: + a3:e5:ec:b5:67:ef:c3:ee:23:dd:c3:3e:24:86:6c:09:03:59: + ab:93:d6:c7:0a:4c:ef:c5:4a:be:d6:ff:0f:2e:81:8e:18:d5: + 44:21:3a:0e:86:04:aa:86:8a:38:1e:d6:07:75:d0:08:be:ef: + 29:7d:d2:fc:85:8d:0c:d3:bd:ea:47:be:40:bb:fa:2f:29:fc: + c6:d8 +-----BEGIN CERTIFICATE----- +MIIC2TCCAkKgAwIBAgICEAwwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkwOTQ4 +NTJaFw0zNTAxMTMwOTQ4NTJaMIGJMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MTkwNwYDVQQDHjAAIgBVAHMAZQByACAAMQAxACwAIABzAHQAYQByAHQAaQBu +AGcAIABxAHUAbwB0AGUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOKLqZQG +sMvnG6P9fHDRZuYtqsfsLuMIwzk/SEf9CWctFheHwONNwcxrP8R7dNVxcNZ0iqIX +/Tl4+MezQlSs9wfXb1XaAxUR4MLYldKHw5w9lJadAYFdYUOqTJLVaKpsc4hSe+6b +dmUNKq49g3FBRIsjfab5PIFWbJtSlofIlxiNAgMBAAGjeDB2MAsGA1UdDwQEAwIF +4DAdBgNVHQ4EFgQUSIm+PKrJWjhryvrIsrv34URLewgwHwYDVR0jBBgwFoAU6Gq7 +wpDqbHAiPvb2SBsD5r63plUwJwYDVR0RBCAwHqQcMBoxGDAWBgNVBAMTD1VzZXIg +MTEgUm9vdCAxMTANBgkqhkiG9w0BAQUFAAOBgQAjyVv1n1n/lwt5NS0y27dLsckr +Hs+Ie7RO8O0To2SFj9Zwte0qV5KgtBSWSHqqpBlZ39mpD4aj5ey1Z+/D7iPdwz4k +hmwJA1mrk9bHCkzvxUq+1v8PLoGOGNVEIToOhgSqhoo4HtYHddAIvu8pfdL8hY0M +073qR75Au/ovKfzG2A== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100D.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100D.pem new file mode 100644 index 0000000000..95e419a174 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100D.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4109 (0x100d) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 09:51:10 2010 GMT + Not After : Jan 13 09:51:10 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00U\x00s\x00e\x00r\x00 \x001\x002\x00,\x00 \x00e\x00n\x00d\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00" + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:bf:4f:93:6b:6b:86:76:30:31:3b:0e:eb:b7:a6: + b9:a3:3e:84:ea:d5:31:50:5a:df:f4:3f:67:11:5a: + a5:28:23:58:37:67:a5:5c:72:6d:f2:fc:80:81:55: + 78:86:28:e9:60:c2:0a:d0:17:3c:3a:e9:a8:01:71: + 64:b8:27:f4:42:e0:d7:69:f5:4e:ef:14:07:69:fd: + de:7b:af:c8:a4:0c:9c:56:00:8b:76:67:d1:ba:a9: + e7:40:63:77:da:44:d3:89:5c:a7:5a:ea:d5:f3:9b: + 15:43:f3:08:2d:bc:8a:bf:4a:5b:57:01:f0:c7:97: + fe:b0:93:b2:1b:79:a0:4e:ad + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 0A:A2:A6:09:88:23:56:82:9E:60:8B:79:23:61:CA:BF:D4:F7:ED:A9 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 12 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 64:3e:b6:a6:5e:0d:6f:b3:e7:f6:c7:1f:4a:48:96:4c:fe:13: + 3c:4a:7b:e7:46:51:56:45:66:02:e4:79:1a:7f:15:a4:e9:5b: + f7:4c:68:cf:cf:b0:7b:e2:ba:57:37:23:c6:cd:ba:75:85:e8: + eb:d5:ca:a2:6d:9a:75:84:4b:7b:47:38:58:bc:0a:4b:cc:2c: + 2a:0d:eb:7e:ac:36:6f:0b:a5:26:b7:d3:0b:0f:e7:cc:26:db: + bb:01:48:5b:38:49:f5:3e:2d:75:c0:d6:11:ad:3e:a0:b6:8a: + 8e:7f:4d:10:2c:7b:d7:03:0d:de:da:6b:e0:07:06:90:73:1f: + dd:f1 +-----BEGIN CERTIFICATE----- +MIIC1TCCAj6gAwIBAgICEA0wDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkwOTUx +MTBaFw0zNTAxMTMwOTUxMTBaMIGFMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MTUwMwYDVQQDHiwAVQBzAGUAcgAgADEAMgAsACAAZQBuAGQAaQBuAGcAIABx +AHUAbwB0AGUAIjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAv0+Ta2uGdjAx +Ow7rt6a5oz6E6tUxUFrf9D9nEVqlKCNYN2elXHJt8vyAgVV4hijpYMIK0Bc8Oumo +AXFkuCf0QuDXafVO7xQHaf3ee6/IpAycVgCLdmfRuqnnQGN32kTTiVynWurV85sV +Q/MILbyKv0pbVwHwx5f+sJOyG3mgTq0CAwEAAaN4MHYwCwYDVR0PBAQDAgXgMB0G +A1UdDgQWBBQKoqYJiCNWgp5gi3kjYcq/1PftqTAfBgNVHSMEGDAWgBToarvCkOps +cCI+9vZIGwPmvremVTAnBgNVHREEIDAepBwwGjEYMBYGA1UEAxMPVXNlciAxMiBS +b290IDExMA0GCSqGSIb3DQEBBQUAA4GBAGQ+tqZeDW+z5/bHH0pIlkz+EzxKe+dG +UVZFZgLkeRp/FaTpW/dMaM/PsHviulc3I8bNunWF6OvVyqJtmnWES3tHOFi8CkvM +LCoN636sNm8LpSa30wsP58wm27sBSFs4SfU+LXXA1hGtPqC2io5/TRAse9cDDd7a +a+AHBpBzH93x +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100E.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100E.pem new file mode 100644 index 0000000000..f91766a0a8 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100E.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4110 (0x100e) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 09:53:08 2010 GMT + Not After : Jan 13 09:53:08 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00"\x00U\x00s\x00e\x00r\x00 \x001\x003\x00,\x00 \x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00s\x00" + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:e0:b2:b3:77:34:32:23:3c:45:ce:1f:5f:9a:60: + c5:59:af:2f:bf:73:8e:be:3d:88:8d:97:4f:fe:8a: + 00:b9:71:7f:07:3a:1e:6a:5b:37:8a:ff:58:8f:f1: + b3:e5:0b:9d:35:58:57:6d:da:d1:15:cd:52:7f:e2: + 15:25:16:d4:d6:1e:71:a6:f3:f7:c5:6d:01:64:fc: + 20:d4:4e:6a:f2:f9:b9:2a:36:f8:ae:e6:17:a8:f9: + 8e:7c:bb:75:e5:24:39:ad:4c:18:c8:bb:07:22:cd: + d1:a6:52:93:7f:24:5f:90:dd:0f:64:07:70:42:67: + 39:9b:1f:ea:5e:bb:cd:df:ab + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 75:49:D0:1F:A0:B3:A2:C6:F2:7F:CF:16:A3:4C:4B:DF:D6:4C:07:9D + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 13 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 5d:60:60:06:aa:8a:2d:ee:20:2a:ee:fb:b5:99:8c:ed:d8:67: + 28:30:d8:26:a7:e0:1c:6e:5d:e1:4c:5e:c8:f9:02:e2:2e:c4: + 1e:58:e9:84:bc:d7:79:4e:d5:c5:ea:ba:74:aa:4e:30:9d:2b: + 98:c8:0b:fe:7f:eb:fb:e9:24:5f:f8:17:27:a9:ce:7c:ff:4b: + 88:15:3e:25:18:71:73:bf:b6:bf:c5:51:6b:1d:db:32:1d:ae: + 00:bf:ed:a5:65:99:16:43:8d:d2:6d:27:53:fc:65:9a:91:94: + 7b:44:c8:58:a1:f1:2b:95:86:0b:2d:2d:94:10:6f:5e:be:f8: + 7b:8e +-----BEGIN CERTIFICATE----- +MIIC3zCCAkigAwIBAgICEA4wDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkwOTUz +MDhaFw0zNTAxMTMwOTUzMDhaMIGPMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MT8wPQYDVQQDHjYAIgBVAHMAZQByACAAMQAzACwAIABlAG4AYwBsAG8AcwBp +AG4AZwAgAHEAdQBvAHQAZQBzACIwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB +AOCys3c0MiM8Rc4fX5pgxVmvL79zjr49iI2XT/6KALlxfwc6HmpbN4r/WI/xs+UL +nTVYV23a0RXNUn/iFSUW1NYecabz98VtAWT8INROavL5uSo2+K7mF6j5jny7deUk +Oa1MGMi7ByLN0aZSk38kX5DdD2QHcEJnOZsf6l67zd+rAgMBAAGjeDB2MAsGA1Ud +DwQEAwIF4DAdBgNVHQ4EFgQUdUnQH6Czosbyf88Wo0xL39ZMB50wHwYDVR0jBBgw +FoAU6Gq7wpDqbHAiPvb2SBsD5r63plUwJwYDVR0RBCAwHqQcMBoxGDAWBgNVBAMT +D1VzZXIgMTMgUm9vdCAxMTANBgkqhkiG9w0BAQUFAAOBgQBdYGAGqoot7iAq7vu1 +mYzt2GcoMNgmp+Acbl3hTF7I+QLiLsQeWOmEvNd5TtXF6rp0qk4wnSuYyAv+f+v7 +6SRf+Bcnqc58/0uIFT4lGHFzv7a/xVFrHdsyHa4Av+2lZZkWQ43SbSdT/GWakZR7 +RMhYofErlYYLLS2UEG9evvh7jg== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100F.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100F.pem new file mode 100644 index 0000000000..34a9b97c5f --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100F.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4111 (0x100f) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 09:55:02 2010 GMT + Not After : Jan 13 09:55:02 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00U\x00s\x00e\x00r\x00 \x001\x004\x00 \x00"\x00,\x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00q\x00u\x00o\x00t\x00e\x00" + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:d7:b7:68:39:6e:80:18:83:2e:d7:0a:e5:f1:3f: + 27:80:68:59:a8:05:ac:7f:d9:6e:5d:7f:1c:58:86: + b7:74:b5:51:3d:64:09:4a:a0:ff:e7:10:0e:bc:8a: + f0:d1:54:18:0a:ed:68:0a:a2:33:e5:9f:f0:3d:7f: + 24:9c:46:34:ba:45:8f:05:59:51:2d:fb:32:1d:79: + 51:37:1a:4b:f8:6e:c5:49:c0:49:9e:ef:2b:ae:aa: + 03:fa:ff:55:08:69:85:0d:b4:06:53:ee:20:4e:74: + 6c:ca:b8:98:8d:64:8f:b5:99:a9:06:37:32:ca:ca: + eb:31:16:ce:97:e8:17:0d:9d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + A7:D8:65:FB:E9:A1:F6:A4:16:76:1C:2E:5B:F3:1B:8E:08:B1:1D:7F + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 14 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 35:54:0f:d2:d3:ec:9e:a6:ea:e6:51:69:27:a3:f1:ae:ea:ef: + f9:da:ca:2a:50:f1:9e:2a:7c:74:43:d6:7f:91:ad:5a:5c:e2: + da:f3:cb:27:a2:78:99:75:0b:9e:e9:3a:bd:3e:31:14:6a:06: + b7:3f:59:d1:0a:67:03:a4:32:63:cd:b1:b6:5c:68:bb:bb:e2: + 23:a6:ff:8e:55:e5:92:a6:a8:b3:87:3d:25:21:9c:2a:6f:ab: + 09:ad:f5:e6:e6:d8:37:62:f2:30:ac:51:da:f4:9c:1d:06:f6: + f3:73:2f:6a:3b:7f:53:0d:c0:2e:ad:cc:6e:81:fe:ce:e3:53: + 0e:23 +-----BEGIN CERTIFICATE----- +MIIC1zCCAkCgAwIBAgICEA8wDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkwOTU1 +MDJaFw0zNTAxMTMwOTU1MDJaMIGHMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MTcwNQYDVQQDHi4AVQBzAGUAcgAgADEANAAgACIALABtAGkAZABkAGwAZQAg +AHEAdQBvAHQAZQAiMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDXt2g5boAY +gy7XCuXxPyeAaFmoBax/2W5dfxxYhrd0tVE9ZAlKoP/nEA68ivDRVBgK7WgKojPl +n/A9fyScRjS6RY8FWVEt+zIdeVE3Gkv4bsVJwEme7yuuqgP6/1UIaYUNtAZT7iBO +dGzKuJiNZI+1makGNzLKyusxFs6X6BcNnQIDAQABo3gwdjALBgNVHQ8EBAMCBeAw +HQYDVR0OBBYEFKfYZfvpofakFnYcLlvzG44IsR1/MB8GA1UdIwQYMBaAFOhqu8KQ +6mxwIj729kgbA+a+t6ZVMCcGA1UdEQQgMB6kHDAaMRgwFgYDVQQDEw9Vc2VyIDE0 +IFJvb3QgMTEwDQYJKoZIhvcNAQEFBQADgYEANVQP0tPsnqbq5lFpJ6Pxrurv+drK +KlDxnip8dEPWf5GtWlzi2vPLJ6J4mXULnuk6vT4xFGoGtz9Z0QpnA6QyY82xtlxo +u7viI6b/jlXlkqaos4c9JSGcKm+rCa315ubYN2LyMKxR2vScHQb283Mvajt/Uw3A +Lq3MboH+zuNTDiM= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1010.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1010.pem new file mode 100644 index 0000000000..ae0a417473 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1010.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4112 (0x1010) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 09:57:52 2010 GMT + Not After : Jan 13 09:57:52 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00\\x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00s\x00\ + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:a1:cc:00:2b:07:2b:e7:ac:80:29:cb:40:37:e3: + 1f:a3:c5:13:86:16:63:6b:cc:b8:c1:aa:54:fd:57: + 0f:de:4c:69:2f:e5:5f:f0:a9:bb:25:74:48:ee:36: + 77:6b:08:b5:95:a9:00:aa:15:31:9e:d8:f6:25:53: + 78:9d:bc:2b:8f:7a:19:32:12:8c:13:60:7d:76:1e: + 4e:b1:e4:51:c7:43:c0:e6:ee:d9:61:df:85:90:a0: + 95:3c:a2:81:83:3d:22:f6:8d:42:ee:69:fa:5c:ae: + 1c:b5:52:02:fb:ec:a6:12:2f:bb:fb:6c:a8:61:95: + 08:6c:d2:e5:1e:90:61:a6:27 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 2F:C9:F6:94:E6:1E:91:13:CE:75:A1:17:FD:1D:93:7E:45:CE:4D:67 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 15 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 19:d0:dc:4c:c8:59:f0:7a:14:f2:51:54:e5:9e:5a:b3:27:0b: + d7:36:0f:74:38:07:26:65:1a:b5:94:1a:1f:b2:b7:3d:ee:b1: + 90:05:83:41:6a:98:5f:25:b4:cb:5c:49:12:24:35:d6:97:cf: + 50:2e:0a:17:41:0b:75:e9:6a:a4:fb:bb:c2:cc:c1:94:64:03: + 81:c4:25:d2:3f:3e:8f:d1:29:44:db:a9:3c:7f:0c:2c:6d:48: + 38:cb:8f:56:82:9c:d3:f3:f3:20:1f:45:19:8e:ea:91:9c:c1: + 25:cf:20:1d:bb:70:7e:b9:a0:c5:34:78:93:5f:2b:d9:fd:d5: + de:ad +-----BEGIN CERTIFICATE----- +MIICzDCCAjWgAwIBAgICEBAwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkwOTU3 +NTJaFw0zNTAxMTMwOTU3NTJaMH0xCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxLTArBgNVBAMeJABcAGUAbgBjAGwAbwBzAGkAbgBnACAAcQB1AG8AdABlAHMA +XDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAocwAKwcr56yAKctAN+Mfo8UT +hhZja8y4wapU/VcP3kxpL+Vf8Km7JXRI7jZ3awi1lakAqhUxntj2JVN4nbwrj3oZ +MhKME2B9dh5OseRRx0PA5u7ZYd+FkKCVPKKBgz0i9o1C7mn6XK4ctVIC++ymEi+7 ++2yoYZUIbNLlHpBhpicCAwEAAaN4MHYwCwYDVR0PBAQDAgXgMB0GA1UdDgQWBBQv +yfaU5h6RE851oRf9HZN+Rc5NZzAfBgNVHSMEGDAWgBToarvCkOpscCI+9vZIGwPm +vremVTAnBgNVHREEIDAepBwwGjEYMBYGA1UEAxMPVXNlciAxNSBSb290IDExMA0G +CSqGSIb3DQEBBQUAA4GBABnQ3EzIWfB6FPJRVOWeWrMnC9c2D3Q4ByZlGrWUGh+y +tz3usZAFg0FqmF8ltMtcSRIkNdaXz1AuChdBC3XpaqT7u8LMwZRkA4HEJdI/Po/R +KUTbqTx/DCxtSDjLj1aCnNPz8yAfRRmO6pGcwSXPIB27cH65oMU0eJNfK9n91d6t +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1011.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1011.pem new file mode 100644 index 0000000000..21222706f4 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1011.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4113 (0x1011) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 09:59:22 2010 GMT + Not After : Jan 13 09:59:22 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00\\x00\\x00d\x00o\x00u\x00b\x00l\x00e\x00 \x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00s\x00\\x00\ + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:a4:e3:64:10:9f:0a:e4:35:bb:e3:e1:f0:28:86: + 8a:f2:6e:d3:f8:44:ac:58:7b:f5:dd:1c:71:17:bf: + 3e:14:29:55:f0:5c:c9:ed:36:c0:7f:e7:cc:7c:a3: + c4:9a:13:4f:7d:6c:b3:1e:ab:24:ba:1a:ff:48:96: + 67:a5:ca:e5:75:30:24:70:3a:94:d2:92:db:29:2b: + 69:1f:1d:a4:da:37:91:57:03:79:d7:0a:c7:a9:09: + 14:a8:70:60:b5:a3:62:4f:b8:bf:0a:22:0a:9c:83: + 3a:4d:1a:47:06:97:f1:4a:38:78:95:45:10:9e:44: + 90:fb:6e:13:ba:3a:1b:b7:4b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + A5:32:FD:E7:0D:90:82:17:34:E1:AD:2A:48:5D:78:27:2B:C9:2A:B8 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 16 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 96:ee:46:fc:41:4f:55:0d:bc:46:27:5a:3c:09:7c:17:6c:e3: + 9e:3a:85:eb:3b:e2:f7:a5:ab:b5:ae:aa:44:81:d7:b7:29:39: + b8:20:40:1e:36:da:a8:03:8b:3a:96:c3:2e:ba:cd:81:b9:af: + a0:a5:95:b0:3b:55:c1:85:9d:3d:c2:d0:7b:a4:d0:0e:16:7c: + 26:ba:85:e5:96:f0:f9:cc:28:c4:ed:83:e8:6f:30:a8:22:7a: + 7e:3b:99:d6:b2:3d:a2:90:1e:c9:9b:70:0a:af:04:d9:7c:46: + 52:e2:5a:d3:57:d6:18:a9:e9:55:ee:00:e8:10:a1:84:ed:ca: + 2b:bf +-----BEGIN CERTIFICATE----- +MIIC3zCCAkigAwIBAgICEBEwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkwOTU5 +MjJaFw0zNTAxMTMwOTU5MjJaMIGPMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MT8wPQYDVQQDHjYAXABcAGQAbwB1AGIAbABlACAAZQBuAGMAbABvAHMAaQBu +AGcAIABxAHUAbwB0AGUAcwBcAFwwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB +AKTjZBCfCuQ1u+Ph8CiGivJu0/hErFh79d0ccRe/PhQpVfBcye02wH/nzHyjxJoT +T31ssx6rJLoa/0iWZ6XK5XUwJHA6lNKS2ykraR8dpNo3kVcDedcKx6kJFKhwYLWj +Yk+4vwoiCpyDOk0aRwaX8Uo4eJVFEJ5EkPtuE7o6G7dLAgMBAAGjeDB2MAsGA1Ud +DwQEAwIF4DAdBgNVHQ4EFgQUpTL95w2Qghc04a0qSF14JyvJKrgwHwYDVR0jBBgw +FoAU6Gq7wpDqbHAiPvb2SBsD5r63plUwJwYDVR0RBCAwHqQcMBoxGDAWBgNVBAMT +D1VzZXIgMTYgUm9vdCAxMTANBgkqhkiG9w0BAQUFAAOBgQCW7kb8QU9VDbxGJ1o8 +CXwXbOOeOoXrO+L3pau1rqpEgde3KTm4IEAeNtqoA4s6lsMuus2Bua+gpZWwO1XB +hZ09wtB7pNAOFnwmuoXllvD5zCjE7YPobzCoInp+O5nWsj2ikB7Jm3AKrwTZfEZS +4lrTV9YYqelV7gDoEKGE7corvw== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1012.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1012.pem new file mode 100644 index 0000000000..b75551711c --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1012.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4114 (0x1012) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 10:02:07 2010 GMT + Not After : Jan 13 10:02:07 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00\\x00\\x00t\x00w\x00o\x00 \x00s\x00t\x00a\x00r\x00t\x00i\x00n\x00g\x00 \x00o\x00n\x00e\x00 \x00e\x00n\x00d\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00\ + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:e9:8c:31:90:52:8d:ef:c6:6a:10:17:7d:37:a3: + ef:00:34:19:dd:a4:1a:f6:cc:37:b0:19:c8:9d:f6: + 9f:f8:3d:15:c9:cf:73:ab:0a:42:f2:54:5b:cc:12: + fb:64:35:54:c9:50:36:18:6c:b6:b0:cf:d6:1e:30: + 0b:0d:fa:f3:25:99:d7:49:20:dd:cc:04:d7:bb:07: + 00:b9:b9:87:8c:75:e5:28:a6:74:a9:b4:96:36:b8: + 15:62:84:0c:7a:a2:f3:07:9c:5c:8f:7a:22:3d:ba: + a4:06:69:f6:ce:d2:36:a0:62:e1:ae:67:aa:23:24: + ac:1d:53:ac:bf:b6:30:74:f7 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + C0:28:3E:BA:44:88:99:A0:80:67:AA:3E:B6:D4:12:A7:35:DA:A6:BB + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 17 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 06:5b:fb:65:55:34:ca:2c:1a:c2:2d:2a:97:1b:a1:68:f6:0c: + 13:18:03:44:f9:0d:37:a1:8c:b1:f7:bc:b7:74:a8:aa:c1:e7: + 36:e7:b9:e0:64:79:76:63:98:7b:1d:d8:80:8c:d9:26:61:a8: + e7:07:96:60:e9:8a:24:78:cb:9c:f3:35:15:c9:d9:0c:2e:68: + 68:48:9c:df:6b:56:3f:aa:47:34:36:b0:ef:0e:d2:e0:ee:a9: + a9:6a:27:93:60:27:5f:42:76:9c:e0:aa:74:6c:b9:aa:de:fe: + 86:98:5a:3d:73:c5:15:38:c8:ff:09:8e:ed:da:06:74:fb:67: + 92:51 +-----BEGIN CERTIFICATE----- +MIIC6TCCAlKgAwIBAgICEBIwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDAy +MDdaFw0zNTAxMTMxMDAyMDdaMIGZMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MUkwRwYDVQQDHkAAXABcAHQAdwBvACAAcwB0AGEAcgB0AGkAbgBnACAAbwBu +AGUAIABlAG4AZABpAG4AZwAgAHEAdQBvAHQAZQBcMIGfMA0GCSqGSIb3DQEBAQUA +A4GNADCBiQKBgQDpjDGQUo3vxmoQF303o+8ANBndpBr2zDewGcid9p/4PRXJz3Or +CkLyVFvMEvtkNVTJUDYYbLawz9YeMAsN+vMlmddJIN3MBNe7BwC5uYeMdeUopnSp +tJY2uBVihAx6ovMHnFyPeiI9uqQGafbO0jagYuGuZ6ojJKwdU6y/tjB09wIDAQAB +o3gwdjALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFMAoPrpEiJmggGeqPrbUEqc12qa7 +MB8GA1UdIwQYMBaAFOhqu8KQ6mxwIj729kgbA+a+t6ZVMCcGA1UdEQQgMB6kHDAa +MRgwFgYDVQQDEw9Vc2VyIDE3IFJvb3QgMTEwDQYJKoZIhvcNAQEFBQADgYEABlv7 +ZVU0yiwawi0qlxuhaPYMExgDRPkNN6GMsfe8t3SoqsHnNue54GR5dmOYex3YgIzZ +JmGo5weWYOmKJHjLnPM1FcnZDC5oaEic32tWP6pHNDaw7w7S4O6pqWonk2AnX0J2 +nOCqdGy5qt7+hphaPXPFFTjI/wmO7doGdPtnklE= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1013.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1013.pem new file mode 100644 index 0000000000..2b48a29b0e --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1013.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4115 (0x1013) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 10:04:36 2010 GMT + Not After : Jan 13 10:04:36 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00\\x00s\x00t\x00a\x00r\x00t\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:bb:73:a4:4e:45:8e:80:b1:65:b6:d8:3b:96:c8: + 3b:c4:2e:40:98:2a:a9:0d:2e:75:29:df:dd:28:8f: + dc:65:4e:2f:8b:24:55:f4:5b:95:5e:d8:29:c8:31: + aa:53:41:a6:1b:2a:cc:8d:67:b6:d8:5f:56:7d:bd: + 0e:17:88:9b:28:b8:fc:54:ff:0e:1f:d9:59:f7:6f: + 99:46:76:86:69:87:f7:07:51:f6:1a:76:91:37:40: + 96:de:5a:0e:c1:20:7f:b5:1b:79:c2:63:13:50:dc: + f0:35:11:2c:4a:30:e0:68:8f:dc:51:4c:2b:61:ba: + a5:e6:ad:72:8b:c4:e1:2d:73 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 31:AE:51:BD:37:3E:EB:D6:98:7D:BD:DF:45:0C:92:4E:73:58:35:AA + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 18 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 51:34:24:4b:78:89:95:5d:43:15:3e:62:fc:40:a0:34:a5:6e: + 83:b5:ee:f0:93:ae:8a:27:97:9c:66:54:c9:aa:f5:9b:96:88: + 43:25:76:b6:0d:06:36:6c:0e:08:5f:15:45:c6:cc:d1:62:18: + 6b:fa:cd:af:53:7c:7c:97:30:13:a7:03:ac:db:04:25:bb:22: + 7d:49:70:30:69:9f:c8:22:94:32:40:83:d3:d1:9d:1c:2a:64: + cf:a9:42:0c:ce:0c:b8:3d:63:33:bb:e1:85:45:a7:79:89:ac: + 0c:1b:b5:a4:e0:1d:4d:99:d6:68:9b:c2:67:97:9c:9d:2c:57: + 12:fe +-----BEGIN CERTIFICATE----- +MIICxjCCAi+gAwIBAgICEBMwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDA0 +MzZaFw0zNTAxMTMxMDA0MzZaMHcxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxJzAlBgNVBAMeHgBcAHMAdABhAHIAdABpAG4AZwAgAHEAdQBvAHQAZTCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAu3OkTkWOgLFlttg7lsg7xC5AmCqpDS51 +Kd/dKI/cZU4viyRV9FuVXtgpyDGqU0GmGyrMjWe22F9Wfb0OF4ibKLj8VP8OH9lZ +92+ZRnaGaYf3B1H2GnaRN0CW3loOwSB/tRt5wmMTUNzwNREsSjDgaI/cUUwrYbql +5q1yi8ThLXMCAwEAAaN4MHYwCwYDVR0PBAQDAgXgMB0GA1UdDgQWBBQxrlG9Nz7r +1ph9vd9FDJJOc1g1qjAfBgNVHSMEGDAWgBToarvCkOpscCI+9vZIGwPmvremVTAn +BgNVHREEIDAepBwwGjEYMBYGA1UEAxMPVXNlciAxOCBSb290IDExMA0GCSqGSIb3 +DQEBBQUAA4GBAFE0JEt4iZVdQxU+YvxAoDSlboO17vCTroonl5xmVMmq9ZuWiEMl +drYNBjZsDghfFUXGzNFiGGv6za9TfHyXMBOnA6zbBCW7In1JcDBpn8gilDJAg9PR +nRwqZM+pQgzODLg9YzO74YVFp3mJrAwbtaTgHU2Z1mibwmeXnJ0sVxL+ +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1014.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1014.pem new file mode 100644 index 0000000000..a2027e9d8a --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1014.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4116 (0x1014) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 10:05:50 2010 GMT + Not After : Jan 13 10:05:50 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00e\x00n\x00d\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00\ + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:ca:cc:98:77:0c:10:dd:0e:87:a2:da:b6:e6:97: + 91:36:71:54:de:2b:f8:de:18:b7:23:eb:e5:e3:57: + ae:cf:0b:6d:86:0f:63:f0:c4:4e:2a:66:48:33:c4: + e3:0b:2c:f5:e6:e5:e5:0f:f8:e0:a1:bc:11:06:a1: + 19:16:ec:44:77:a6:db:7d:d6:78:29:1f:57:f1:9d: + 3c:b4:3a:2b:3b:94:64:6d:e3:ce:b3:fa:d8:28:e2: + ed:76:9a:97:41:64:7c:0d:48:b8:1d:6a:56:e3:f9: + 4c:88:e9:1a:3c:b8:af:7a:13:67:19:59:36:46:79: + 52:72:ea:51:80:65:be:e2:0f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + D2:D8:8D:EE:39:D7:EA:15:23:00:7C:9D:48:1C:51:17:F8:80:86:CE + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 19 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 6e:05:c4:48:32:4a:62:6f:a3:8c:23:af:47:dd:d4:c7:c1:91: + 17:7e:cd:36:73:39:a3:7b:c9:ae:da:f6:e1:bd:82:d6:72:17: + 78:20:a2:27:ad:f5:d2:3f:10:66:e0:d8:ba:10:00:c3:76:5b: + de:36:cb:2a:91:25:89:08:0e:2a:6a:81:d0:a7:49:70:42:f3: + 94:a3:bf:6c:6b:b9:fa:fd:f9:d4:1f:6f:75:27:b9:0d:d3:d2: + fd:5d:0d:dc:f5:34:29:a2:3a:2f:04:ab:48:41:6d:d7:2b:fd: + 42:02:99:3c:cf:aa:6b:98:66:17:83:39:4a:6f:47:36:ad:db: + 22:6e +-----BEGIN CERTIFICATE----- +MIICwjCCAiugAwIBAgICEBQwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDA1 +NTBaFw0zNTAxMTMxMDA1NTBaMHMxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxIzAhBgNVBAMeGgBlAG4AZABpAG4AZwAgAHEAdQBvAHQAZQBcMIGfMA0GCSqG +SIb3DQEBAQUAA4GNADCBiQKBgQDKzJh3DBDdDoei2rbml5E2cVTeK/jeGLcj6+Xj +V67PC22GD2PwxE4qZkgzxOMLLPXm5eUP+OChvBEGoRkW7ER3ptt91ngpH1fxnTy0 +Ois7lGRt486z+tgo4u12mpdBZHwNSLgdalbj+UyI6Ro8uK96E2cZWTZGeVJy6lGA +Zb7iDwIDAQABo3gwdjALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFNLYje451+oVIwB8 +nUgcURf4gIbOMB8GA1UdIwQYMBaAFOhqu8KQ6mxwIj729kgbA+a+t6ZVMCcGA1Ud +EQQgMB6kHDAaMRgwFgYDVQQDEw9Vc2VyIDE5IFJvb3QgMTEwDQYJKoZIhvcNAQEF +BQADgYEAbgXESDJKYm+jjCOvR93Ux8GRF37NNnM5o3vJrtr24b2C1nIXeCCiJ631 +0j8QZuDYuhAAw3Zb3jbLKpEliQgOKmqB0KdJcELzlKO/bGu5+v351B9vdSe5DdPS +/V0N3PU0KaI6LwSrSEFt1yv9QgKZPM+qa5hmF4M5Sm9HNq3bIm4= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1015.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1015.pem new file mode 100644 index 0000000000..d9d3f941e6 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1015.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4117 (0x1015) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 10:07:07 2010 GMT + Not After : Jan 13 10:07:07 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00\\x00q\x00u\x00o\x00t\x00e + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:f0:7c:07:f6:13:52:ce:13:cf:8a:5f:7f:5f:3c: + d4:93:c8:a0:43:1f:e2:fc:3f:62:63:be:b5:17:e0: + 32:b0:d0:c2:9a:35:9e:3b:29:30:b4:13:78:18:ae: + 80:ba:fb:f3:fc:81:ad:aa:47:18:eb:fc:d1:76:de: + b6:cf:55:65:5e:3e:15:93:8e:9c:39:4e:a3:ae:1d: + c0:49:22:dc:25:09:33:95:0d:b5:62:7c:96:0b:05: + b6:10:ae:ee:f8:18:24:9f:d4:ed:b3:4c:a9:4d:f2: + be:6c:66:37:b9:17:cb:14:df:52:b4:a8:de:63:0d: + 4f:78:58:16:ab:f2:3f:f6:a9 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 41:CC:3D:88:34:10:21:13:A2:34:24:B6:4E:F9:33:3C:B3:FA:56:BC + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 20 Root 11 + Signature Algorithm: sha1WithRSAEncryption + a7:17:c3:92:37:10:ee:9a:12:65:32:82:56:93:82:fa:0e:40: + 9f:ae:30:6a:b1:6f:85:18:7f:ff:9c:30:49:b7:56:bf:a3:86: + d7:dd:5d:79:d1:7f:9a:95:b6:bd:1d:43:cc:2c:aa:7a:40:c4: + de:17:02:22:74:ec:a9:cd:8d:93:f6:6c:98:7e:bb:6a:68:70: + 66:d4:a0:8f:1a:7a:8e:9e:38:35:aa:87:6a:e5:db:80:69:51: + 51:68:46:4f:3d:da:17:df:6f:22:60:77:95:55:d3:12:1b:11: + c1:6f:c1:96:78:00:47:61:af:53:c0:37:44:6b:92:67:7f:14: + 79:80 +-----BEGIN CERTIFICATE----- +MIICwjCCAiugAwIBAgICEBUwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDA3 +MDdaFw0zNTAxMTMxMDA3MDdaMHMxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxIzAhBgNVBAMeGgBtAGkAZABkAGwAZQAgAFwAcQB1AG8AdABlMIGfMA0GCSqG +SIb3DQEBAQUAA4GNADCBiQKBgQDwfAf2E1LOE8+KX39fPNSTyKBDH+L8P2JjvrUX +4DKw0MKaNZ47KTC0E3gYroC6+/P8ga2qRxjr/NF23rbPVWVePhWTjpw5TqOuHcBJ +ItwlCTOVDbVifJYLBbYQru74GCSf1O2zTKlN8r5sZje5F8sU31K0qN5jDU94WBar +8j/2qQIDAQABo3gwdjALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFEHMPYg0ECETojQk +tk75Mzyz+la8MB8GA1UdIwQYMBaAFOhqu8KQ6mxwIj729kgbA+a+t6ZVMCcGA1Ud +EQQgMB6kHDAaMRgwFgYDVQQDEw9Vc2VyIDIwIFJvb3QgMTEwDQYJKoZIhvcNAQEF +BQADgYEApxfDkjcQ7poSZTKCVpOC+g5An64warFvhRh//5wwSbdWv6OG191dedF/ +mpW2vR1DzCyqekDE3hcCInTsqc2Nk/ZsmH67amhwZtSgjxp6jp44NaqHauXbgGlR +UWhGTz3aF99vImB3lVXTEhsRwW/BlngAR2GvU8A3RGuSZ38UeYA= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1016.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1016.pem new file mode 100644 index 0000000000..9f4e006f02 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1016.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4118 (0x1016) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 10:09:50 2010 GMT + Not After : Jan 13 10:09:50 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00d\x00o\x00u\x00b\x00l\x00e\x00 \x00\\x00\\x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00q\x00u\x00o\x00t\x00e + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:cd:22:93:9a:93:18:34:2f:50:e0:cc:23:f4:60: + bc:96:60:d5:a5:f9:da:45:9a:5b:a3:0a:fb:71:25: + 4c:bd:60:84:19:f5:93:28:c1:5d:b9:8d:05:05:4d: + 01:85:aa:9e:5b:08:9c:01:f8:32:90:fe:ef:7f:eb: + cb:b3:8b:b2:c8:d1:79:d6:47:a3:d8:df:f1:d0:56: + 04:04:bd:41:72:fc:98:75:10:d2:9b:b5:bc:55:a1: + fa:19:01:67:93:09:48:0a:67:ec:4d:12:47:37:6f: + c2:53:0e:c9:7a:30:ec:1d:9d:a5:e2:64:d8:92:4d: + ed:ec:b2:bb:10:96:76:28:47 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + DC:FF:9A:2B:49:51:1E:FB:A7:3A:90:94:1B:E0:3E:34:89:13:48:EE + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 21 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 16:aa:a6:b7:0e:e3:d2:ba:7e:9b:59:f6:cc:ce:5d:4d:2a:f2: + 95:60:46:24:dd:ea:e8:08:e6:60:9c:33:82:8c:34:a2:d8:38: + fb:75:fe:31:79:10:78:7d:93:44:3b:00:90:83:a4:15:52:8d: + 3a:b4:9c:c0:6f:95:2c:4f:d8:b3:3b:cf:69:ab:3c:41:3a:43: + 1b:0a:8b:b0:b4:aa:8b:bf:6f:96:e2:65:4a:00:3a:49:bc:9a: + a1:cd:13:b1:24:93:f6:44:cd:d3:71:91:da:4f:dd:75:3d:68: + 5c:6b:49:14:8a:23:b5:b6:4f:b6:41:d0:a7:16:7c:67:4c:b3: + 0a:88 +-----BEGIN CERTIFICATE----- +MIIC0zCCAjygAwIBAgICEBYwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDA5 +NTBaFw0zNTAxMTMxMDA5NTBaMIGDMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MTMwMQYDVQQDHioAZABvAHUAYgBsAGUAIABcAFwAbQBpAGQAZABsAGUAIABx +AHUAbwB0AGUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM0ik5qTGDQvUODM +I/RgvJZg1aX52kWaW6MK+3ElTL1ghBn1kyjBXbmNBQVNAYWqnlsInAH4MpD+73/r +y7OLssjRedZHo9jf8dBWBAS9QXL8mHUQ0pu1vFWh+hkBZ5MJSApn7E0SRzdvwlMO +yXow7B2dpeJk2JJN7eyyuxCWdihHAgMBAAGjeDB2MAsGA1UdDwQEAwIF4DAdBgNV +HQ4EFgQU3P+aK0lRHvunOpCUG+A+NIkTSO4wHwYDVR0jBBgwFoAU6Gq7wpDqbHAi +Pvb2SBsD5r63plUwJwYDVR0RBCAwHqQcMBoxGDAWBgNVBAMTD1VzZXIgMjEgUm9v +dCAxMTANBgkqhkiG9w0BAQUFAAOBgQAWqqa3DuPSun6bWfbMzl1NKvKVYEYk3ero +COZgnDOCjDSi2Dj7df4xeRB4fZNEOwCQg6QVUo06tJzAb5UsT9izO89pqzxBOkMb +CouwtKqLv2+W4mVKADpJvJqhzROxJJP2RM3TcZHaT911PWhca0kUiiO1tk+2QdCn +FnxnTLMKiA== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1017.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1017.pem new file mode 100644 index 0000000000..7bb12fa789 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1017.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4119 (0x1017) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 10:11:53 2010 GMT + Not After : Jan 13 10:11:53 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00p\x00a\x00r\x00t\x00i\x00a\x00l\x00l\x00y\x00 \x00\\x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00\ + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:e7:c9:bb:89:11:2f:2c:39:bc:d3:f5:d9:86:d4: + 8e:d7:20:11:81:75:30:25:7e:2b:29:70:61:83:38: + 24:d1:0f:cc:0b:88:71:29:06:05:a5:53:d2:00:2f: + 12:0c:7d:42:e6:47:33:de:cc:f8:7b:2a:5d:d9:cb: + 69:24:91:38:bf:0c:1a:12:cf:1e:f9:44:c2:1c:e8: + 6f:ea:ab:8b:92:4c:93:8c:69:61:b9:57:b3:1d:d0: + 03:3e:13:9d:30:bd:b2:b9:d9:c7:9b:4d:18:45:b0: + 19:19:15:58:4c:bd:5a:a1:59:4f:f0:1f:99:26:3b: + 4e:76:c6:bb:21:3c:94:bc:d9 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 43:E4:70:39:E3:91:80:2A:C3:BC:1A:F4:A3:51:4B:99:C5:20:93:A6 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 22 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 28:ce:8c:f0:bf:56:c6:a4:02:df:dd:1d:75:dc:cf:62:a0:92: + 58:64:91:8c:bb:96:3c:52:d5:66:6c:31:7e:1c:d9:a8:e5:1c: + a6:9f:5e:26:3f:69:71:c6:d7:5d:02:4f:a7:42:a5:85:fa:38: + 01:43:36:54:75:4c:51:a2:99:5d:72:05:9a:9b:fc:5e:83:9b: + a0:ef:11:b1:a4:dd:a5:50:2f:d0:14:dd:04:0f:8b:93:7e:4b: + 3e:24:04:45:d0:98:46:49:74:9f:d7:b4:68:09:dc:b6:ac:35: + 3f:5d:f9:ee:77:a4:35:46:75:a4:6a:d6:c1:53:4f:d2:0c:38: + 3c:df +-----BEGIN CERTIFICATE----- +MIIC3zCCAkigAwIBAgICEBcwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDEx +NTNaFw0zNTAxMTMxMDExNTNaMIGPMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MT8wPQYDVQQDHjYAcABhAHIAdABpAGEAbABsAHkAIABcAGUAbgBjAGwAbwBz +AGkAbgBnACAAcQB1AG8AdABlAFwwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB +AOfJu4kRLyw5vNP12YbUjtcgEYF1MCV+KylwYYM4JNEPzAuIcSkGBaVT0gAvEgx9 +QuZHM97M+HsqXdnLaSSROL8MGhLPHvlEwhzob+qri5JMk4xpYblXsx3QAz4TnTC9 +srnZx5tNGEWwGRkVWEy9WqFZT/AfmSY7TnbGuyE8lLzZAgMBAAGjeDB2MAsGA1Ud +DwQEAwIF4DAdBgNVHQ4EFgQUQ+RwOeORgCrDvBr0o1FLmcUgk6YwHwYDVR0jBBgw +FoAU6Gq7wpDqbHAiPvb2SBsD5r63plUwJwYDVR0RBCAwHqQcMBoxGDAWBgNVBAMT +D1VzZXIgMjIgUm9vdCAxMTANBgkqhkiG9w0BAQUFAAOBgQAozozwv1bGpALf3R11 +3M9ioJJYZJGMu5Y8UtVmbDF+HNmo5Rymn14mP2lxxtddAk+nQqWF+jgBQzZUdUxR +opldcgWam/xeg5ug7xGxpN2lUC/QFN0ED4uTfks+JARF0JhGSXSf17RoCdy2rDU/ +Xfnud6Q1RnWkatbBU0/SDDg83w== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1018.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1018.pem new file mode 100644 index 0000000000..d134dc5f3e --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1018.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4120 (0x1018) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 10:13:38 2010 GMT + Not After : Jan 13 10:13:38 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00\\x00U\x00s\x00e\x00r\x00 \x002\x003\x00,\x00 \x00s\x00t\x00a\x00r\x00t\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:b9:e3:64:f8:02:be:98:47:de:c6:f4:22:14:4f: + 22:fe:17:8c:14:7f:b8:27:44:51:9d:5a:79:33:b4: + d0:21:27:b0:ed:f9:9f:3d:54:ef:ba:3a:d8:89:2a: + ca:a8:8f:f3:f6:a7:6b:5f:0a:58:2d:a0:e3:05:3a: + 26:a6:1e:b6:89:a1:e1:71:11:e7:16:93:29:69:f8: + 14:a2:e3:d7:4e:e5:60:40:d7:40:c5:37:d6:95:7c: + 4f:35:fd:a8:82:7f:90:32:1d:99:e7:8a:b9:93:a4: + f3:23:0a:a5:f9:56:31:73:d8:e3:cb:d6:0e:2f:2b: + ee:8e:b5:ca:eb:63:82:1c:0b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 80:A8:F7:13:E3:E8:F8:A6:60:94:21:C1:FE:54:54:89:AC:4B:DF:45 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 23 Root 11 + Signature Algorithm: sha1WithRSAEncryption + be:31:bd:4a:56:80:64:f0:1e:ea:77:4a:f3:e3:ec:f0:ad:27: + cc:05:01:fa:d2:12:7c:8e:85:5b:37:54:9c:4f:96:2d:1c:81: + e4:21:3d:4b:d9:86:1a:6c:29:5e:88:f2:ae:04:f1:70:87:25: + b9:9a:4a:ef:dd:21:f9:17:33:ee:a1:eb:38:fb:c4:73:72:70: + 0c:67:58:96:95:8c:2c:5a:4a:31:28:50:52:64:65:5c:63:60: + de:24:df:a0:e9:0d:c0:b6:d6:4c:51:a7:5a:e8:dd:f6:ff:49: + e6:6f:7f:86:38:5d:c7:f9:eb:55:f1:b2:89:3b:cd:41:f7:5d: + a8:b0 +-----BEGIN CERTIFICATE----- +MIIC2TCCAkKgAwIBAgICEBgwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDEz +MzhaFw0zNTAxMTMxMDEzMzhaMIGJMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MTkwNwYDVQQDHjAAXABVAHMAZQByACAAMgAzACwAIABzAHQAYQByAHQAaQBu +AGcAIABxAHUAbwB0AGUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALnjZPgC +vphH3sb0IhRPIv4XjBR/uCdEUZ1aeTO00CEnsO35nz1U77o62IkqyqiP8/ana18K +WC2g4wU6JqYetomh4XER5xaTKWn4FKLj107lYEDXQMU31pV8TzX9qIJ/kDIdmeeK +uZOk8yMKpflWMXPY48vWDi8r7o61yutjghwLAgMBAAGjeDB2MAsGA1UdDwQEAwIF +4DAdBgNVHQ4EFgQUgKj3E+Po+KZglCHB/lRUiaxL30UwHwYDVR0jBBgwFoAU6Gq7 +wpDqbHAiPvb2SBsD5r63plUwJwYDVR0RBCAwHqQcMBoxGDAWBgNVBAMTD1VzZXIg +MjMgUm9vdCAxMTANBgkqhkiG9w0BAQUFAAOBgQC+Mb1KVoBk8B7qd0rz4+zwrSfM +BQH60hJ8joVbN1ScT5YtHIHkIT1L2YYabCleiPKuBPFwhyW5mkrv3SH5FzPuoes4 ++8RzcnAMZ1iWlYwsWkoxKFBSZGVcY2DeJN+g6Q3AttZMUada6N32/0nmb3+GOF3H ++etV8bKJO81B912osA== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1019.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1019.pem new file mode 100644 index 0000000000..66c3f15bfd --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1019.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4121 (0x1019) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 10:14:50 2010 GMT + Not After : Jan 13 10:14:50 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00U\x00s\x00e\x00r\x00 \x002\x004\x00,\x00 \x00e\x00n\x00d\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00\ + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:9c:cd:78:e7:11:1d:61:d4:0c:c6:87:c9:28:47: + 84:23:6b:86:c3:38:37:62:5a:9a:4b:50:fc:b7:f3: + d9:4b:1b:20:ff:06:42:bb:22:33:c5:22:12:2c:bb: + e6:c8:08:69:0e:af:e9:22:45:9f:ef:2c:26:46:d7: + 1b:36:db:70:58:32:bc:3d:d7:7d:64:27:44:54:6c: + 89:12:88:d7:31:3d:3f:5c:96:cb:69:9f:b1:a9:e0: + 9a:de:50:b7:ad:d8:29:bf:bc:3c:21:e9:a2:79:21: + 46:81:ea:90:df:44:0c:6c:bb:f8:47:c8:e9:79:d1: + 8d:40:1b:5d:d3:75:9b:e4:0b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 81:14:09:35:7F:F6:7A:83:6B:19:C2:22:24:92:E6:D4:EF:52:1C:0B + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 24 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 7c:65:0b:e2:cd:ca:00:e8:40:0f:37:70:a1:89:54:5d:03:06: + 2c:60:56:dc:2f:b7:01:ac:75:58:f6:82:8f:91:63:e2:91:d1: + 17:7b:bd:63:b9:9c:4e:46:86:3e:a6:f5:a6:56:ac:90:2a:f4: + d8:a0:6c:02:15:6e:d9:f6:2a:f8:9a:c4:48:bd:cd:54:82:55: + c6:d5:52:76:09:e3:3d:17:8d:5c:46:16:ae:9e:56:df:9f:c3: + 05:15:6f:ae:d0:b5:76:67:48:2d:5a:3c:59:da:1b:13:c3:84: + 5e:2a:57:8d:86:9a:f1:8a:5d:01:47:93:44:62:af:65:03:e1: + df:10 +-----BEGIN CERTIFICATE----- +MIIC1TCCAj6gAwIBAgICEBkwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDE0 +NTBaFw0zNTAxMTMxMDE0NTBaMIGFMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MTUwMwYDVQQDHiwAVQBzAGUAcgAgADIANAAsACAAZQBuAGQAaQBuAGcAIABx +AHUAbwB0AGUAXDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAnM145xEdYdQM +xofJKEeEI2uGwzg3YlqaS1D8t/PZSxsg/wZCuyIzxSISLLvmyAhpDq/pIkWf7ywm +RtcbNttwWDK8Pdd9ZCdEVGyJEojXMT0/XJbLaZ+xqeCa3lC3rdgpv7w8IemieSFG +geqQ30QMbLv4R8jpedGNQBtd03Wb5AsCAwEAAaN4MHYwCwYDVR0PBAQDAgXgMB0G +A1UdDgQWBBSBFAk1f/Z6g2sZwiIkkubU71IcCzAfBgNVHSMEGDAWgBToarvCkOps +cCI+9vZIGwPmvremVTAnBgNVHREEIDAepBwwGjEYMBYGA1UEAxMPVXNlciAyNCBS +b290IDExMA0GCSqGSIb3DQEBBQUAA4GBAHxlC+LNygDoQA83cKGJVF0DBixgVtwv +twGsdVj2go+RY+KR0Rd7vWO5nE5Ghj6m9aZWrJAq9NigbAIVbtn2KviaxEi9zVSC +VcbVUnYJ4z0XjVxGFq6eVt+fwwUVb67QtXZnSC1aPFnaGxPDhF4qV42GmvGKXQFH +k0Rir2UD4d8Q +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101A.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101A.pem new file mode 100644 index 0000000000..ba352d83d1 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101A.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4122 (0x101a) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 10:16:10 2010 GMT + Not After : Jan 13 10:16:10 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00\\x00U\x00s\x00e\x00r\x00 \x002\x005\x00,\x00 \x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00\ + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:ad:20:4a:85:d2:a8:2a:f8:0e:4c:b5:2d:72:a5: + 1d:0e:b1:8a:76:2c:b0:bf:7a:48:b8:57:29:cb:40: + c5:8a:e8:0e:d3:f6:f9:b1:90:a6:4a:bb:82:45:fd: + c2:ff:03:fa:fc:4a:5d:93:0b:52:a2:17:10:b1:7e: + 13:1d:9d:28:26:e3:44:bd:fd:26:da:b2:7b:47:e1: + c4:35:ea:53:1b:94:76:cc:f2:f6:c1:86:f2:18:46: + e1:71:c0:5d:e5:8f:0a:10:7a:ea:61:af:d0:ba:28: + 22:13:77:0f:7d:9e:e0:0a:f0:92:ce:dd:b3:5d:a6: + df:c1:eb:a8:29:57:e6:71:65 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + C3:EE:4A:7E:AC:46:2D:BA:42:F7:33:1F:E7:49:FA:21:D3:BC:DD:49 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 25 Root 11 + Signature Algorithm: sha1WithRSAEncryption + bf:63:34:12:e3:4b:83:4e:e5:c5:08:c3:b3:ea:be:38:33:38: + 3c:99:c3:ca:08:84:05:d4:21:53:7a:7d:43:86:c2:63:e2:d3: + 7c:21:3c:72:fa:c6:f3:bf:2b:10:5e:ca:4b:2c:2c:1c:e3:10: + eb:7c:ff:b1:20:b2:47:1b:b3:3e:77:b6:74:fb:83:85:ac:b8: + c9:5b:ca:8a:14:2f:e4:81:6e:04:6f:c8:37:c0:9f:c0:41:0f: + b4:6e:21:82:69:51:e8:68:09:72:c4:8c:72:db:47:0b:a5:52: + d7:e7:b3:5d:10:9c:ed:14:af:1c:fd:0b:11:a3:fd:f9:b9:2d: + 48:b5 +-----BEGIN CERTIFICATE----- +MIIC3TCCAkagAwIBAgICEBowDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDE2 +MTBaFw0zNTAxMTMxMDE2MTBaMIGNMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MT0wOwYDVQQDHjQAXABVAHMAZQByACAAMgA1ACwAIABlAG4AYwBsAG8AcwBp +AG4AZwAgAHEAdQBvAHQAZQBcMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCt +IEqF0qgq+A5MtS1ypR0OsYp2LLC/eki4VynLQMWK6A7T9vmxkKZKu4JF/cL/A/r8 +Sl2TC1KiFxCxfhMdnSgm40S9/SbasntH4cQ16lMblHbM8vbBhvIYRuFxwF3ljwoQ +euphr9C6KCITdw99nuAK8JLO3bNdpt/B66gpV+ZxZQIDAQABo3gwdjALBgNVHQ8E +BAMCBeAwHQYDVR0OBBYEFMPuSn6sRi26QvczH+dJ+iHTvN1JMB8GA1UdIwQYMBaA +FOhqu8KQ6mxwIj729kgbA+a+t6ZVMCcGA1UdEQQgMB6kHDAaMRgwFgYDVQQDEw9V +c2VyIDI1IFJvb3QgMTEwDQYJKoZIhvcNAQEFBQADgYEAv2M0EuNLg07lxQjDs+q+ +ODM4PJnDygiEBdQhU3p9Q4bCY+LTfCE8cvrG878rEF7KSywsHOMQ63z/sSCyRxuz +Pne2dPuDhay4yVvKihQv5IFuBG/IN8CfwEEPtG4hgmlR6GgJcsSMcttHC6VS1+ez +XRCc7RSvHP0LEaP9+bktSLU= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101B.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101B.pem new file mode 100644 index 0000000000..4c03562a8e --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101B.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4123 (0x101b) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 10:17:45 2010 GMT + Not After : Jan 13 10:17:45 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00U\x00s\x00e\x00r\x00 \x002\x006\x00\\x00,\x00 \x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00q\x00u\x00o\x00t\x00e + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:ec:4c:2b:ba:b1:e5:ba:83:e8:64:6c:67:fe:f9: + 84:9a:71:68:0b:10:b0:2e:2c:21:d8:6d:c8:cc:de: + 82:76:15:b8:74:a0:4b:3c:39:f0:ee:3a:08:6c:0e: + 0c:36:51:ed:44:04:ca:2b:76:30:6f:85:d4:f6:f0: + 7e:53:2b:17:90:6a:7b:79:e0:c2:00:f2:5f:dd:19: + 8f:09:7a:a2:c8:85:95:24:e0:41:39:ec:75:e1:c7: + 03:ba:6d:e9:81:48:8b:36:38:e0:99:3e:58:04:e3: + 03:8d:e4:3b:95:98:0a:23:96:f1:96:50:06:5d:71: + 6f:02:e1:c5:cd:e0:5c:c4:7b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 1D:A3:64:F0:93:51:C2:F2:1A:BB:D0:2D:20:95:5E:19:94:4C:72:BB + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 26 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 8c:c1:56:7d:d9:a8:f7:af:4b:57:4a:a5:2a:32:11:12:e0:d8: + 0e:10:39:8f:17:53:25:f5:c6:57:55:e4:f0:16:f2:11:cc:af: + cc:44:6b:23:6f:8e:2a:df:ee:ff:f0:d4:3f:0a:85:7e:19:de: + f8:cf:69:be:8b:59:ad:3c:be:3c:d7:32:ac:ba:82:91:28:23: + 71:ba:b5:29:05:e4:98:ee:2b:bb:56:04:7f:8b:69:c5:f9:4c: + 1b:0b:2e:3a:46:41:8e:da:16:68:9f:c7:57:71:8e:97:0d:b0: + a1:92:ae:7c:75:46:ef:b4:6d:8e:e7:53:07:23:a4:e1:e0:f0: + e7:3b +-----BEGIN CERTIFICATE----- +MIIC1TCCAj6gAwIBAgICEBswDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDE3 +NDVaFw0zNTAxMTMxMDE3NDVaMIGFMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MTUwMwYDVQQDHiwAVQBzAGUAcgAgADIANgBcACwAIABtAGkAZABkAGwAZQAg +AHEAdQBvAHQAZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA7EwrurHluoPo +ZGxn/vmEmnFoCxCwLiwh2G3IzN6CdhW4dKBLPDnw7joIbA4MNlHtRATKK3Ywb4XU +9vB+UysXkGp7eeDCAPJf3RmPCXqiyIWVJOBBOex14ccDum3pgUiLNjjgmT5YBOMD +jeQ7lZgKI5bxllAGXXFvAuHFzeBcxHsCAwEAAaN4MHYwCwYDVR0PBAQDAgXgMB0G +A1UdDgQWBBQdo2Twk1HC8hq70C0glV4ZlExyuzAfBgNVHSMEGDAWgBToarvCkOps +cCI+9vZIGwPmvremVTAnBgNVHREEIDAepBwwGjEYMBYGA1UEAxMPVXNlciAyNiBS +b290IDExMA0GCSqGSIb3DQEBBQUAA4GBAIzBVn3ZqPevS1dKpSoyERLg2A4QOY8X +UyX1xldV5PAW8hHMr8xEayNvjirf7v/w1D8KhX4Z3vjPab6LWa08vjzXMqy6gpEo +I3G6tSkF5JjuK7tWBH+LacX5TBsLLjpGQY7aFmifx1dxjpcNsKGSrnx1Ru+0bY7n +UwcjpOHg8Oc7 +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101C.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101C.pem new file mode 100644 index 0000000000..c403402f3d --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101C.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4124 (0x101c) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 10:19:13 2010 GMT + Not After : Jan 13 10:19:13 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=comma, comma, comma , + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:af:2e:02:1a:b8:ed:7e:6e:27:2f:6e:ca:dc:57: + 11:17:88:37:38:37:26:d0:fb:d0:ee:ad:f3:a8:ad: + f5:8a:53:04:6a:82:a7:31:b5:e6:ce:88:24:fa:22: + 75:84:1b:a8:8c:fd:7f:63:0c:fc:13:41:82:60:a3: + 19:33:3d:d3:18:6e:09:c5:c7:e7:e9:9e:49:dd:f4: + 77:ef:f1:06:91:9a:c5:57:68:e5:0f:59:19:8d:53: + ff:cb:ae:11:33:48:5c:eb:72:e8:2f:67:ae:94:42: + d3:5b:2e:31:e3:6f:a7:5e:5e:9c:ea:2c:d2:c3:af: + 66:10:34:32:e5:2d:3f:55:c1 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + A1:FB:82:9C:27:AD:83:67:5E:8C:CC:A2:BA:32:3C:30:26:74:F4:CE + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 27 Root 11 + Signature Algorithm: sha1WithRSAEncryption + c6:72:8b:f8:57:9e:b7:bf:b1:f3:99:41:1c:8c:47:a1:93:d8: + 62:8e:2d:68:6c:db:12:02:86:e0:66:65:c1:7c:c4:83:35:4c: + 16:53:fd:34:c1:3c:60:15:fc:3d:3b:90:07:68:ca:af:a1:10: + 39:c4:6b:15:a6:1a:71:51:20:ea:35:84:ef:8f:ac:51:bc:d7: + 84:d8:35:71:44:8e:8c:4f:59:76:3d:b3:5f:5c:26:9e:bc:ee: + 09:40:13:3b:38:85:02:56:7d:97:db:4d:3d:b5:a1:66:cf:df: + 19:7a:2f:71:b7:a4:12:c3:9b:df:83:f9:a8:8a:00:68:e4:3a: + ee:25 +-----BEGIN CERTIFICATE----- +MIICvTCCAiagAwIBAgICEBwwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDE5 +MTNaFw0zNTAxMTMxMDE5MTNaMG4xCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxHjAcBgNVBAMTFWNvbW1hLCBjb21tYSwgY29tbWEgLDCBnzANBgkqhkiG9w0B +AQEFAAOBjQAwgYkCgYEAry4CGrjtfm4nL27K3FcRF4g3ODcm0PvQ7q3zqK31ilME +aoKnMbXmzogk+iJ1hBuojP1/Ywz8E0GCYKMZMz3TGG4Jxcfn6Z5J3fR37/EGkZrF +V2jlD1kZjVP/y64RM0hc63LoL2eulELTWy4x42+nXl6c6izSw69mEDQy5S0/VcEC +AwEAAaN4MHYwCwYDVR0PBAQDAgXgMB0GA1UdDgQWBBSh+4KcJ62DZ16MzKK6Mjww +JnT0zjAfBgNVHSMEGDAWgBToarvCkOpscCI+9vZIGwPmvremVTAnBgNVHREEIDAe +pBwwGjEYMBYGA1UEAxMPVXNlciAyNyBSb290IDExMA0GCSqGSIb3DQEBBQUAA4GB +AMZyi/hXnre/sfOZQRyMR6GT2GKOLWhs2xIChuBmZcF8xIM1TBZT/TTBPGAV/D07 +kAdoyq+hEDnEaxWmGnFRIOo1hO+PrFG814TYNXFEjoxPWXY9s19cJp687glAEzs4 +hQJWfZfbTT21oWbP3xl6L3G3pBLDm9+D+aiKAGjkOu4l +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101D.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101D.pem new file mode 100644 index 0000000000..2790a2abd2 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101D.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4125 (0x101d) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 10:20:47 2010 GMT + Not After : Jan 13 10:20:47 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=equal CN=User 28 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:ae:df:12:64:ab:d9:2f:ee:21:64:b5:08:c5:c8: + 8f:a1:ad:0e:b9:28:91:69:74:13:a5:aa:49:fe:fa: + 02:9d:37:db:0a:3b:26:6a:20:25:3d:f9:2d:b2:3b: + 39:c8:c6:e3:a7:aa:a1:0b:b2:1b:58:43:e6:3c:3f: + 67:fe:bb:bd:9b:b5:d9:de:e9:ed:76:ab:fd:f5:c8: + 15:b2:fb:a6:3f:23:ef:9f:5f:71:43:b3:be:55:1e: + 85:5f:13:b1:6b:9d:42:d7:30:a8:d2:9b:fe:71:7a: + c7:d3:60:7a:cf:e2:83:75:83:b8:1c:d3:ef:ee:94: + 3f:14:63:aa:7c:15:4e:42:1d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 3B:2D:2B:5F:2E:E6:32:23:AE:47:B7:30:25:CB:ED:B0:6D:0C:30:E4 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 28 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 5b:cf:de:92:f8:ac:39:fb:0a:81:70:5b:17:d0:0d:0d:85:5e: + 2e:7d:be:d1:1a:ad:1d:99:a4:a6:f0:48:5a:7b:04:39:e2:93: + ff:80:84:f6:a1:e6:8a:52:12:55:46:c0:57:84:d9:c3:13:92: + 61:d7:41:af:39:09:57:05:25:01:90:68:7c:7c:5c:85:c6:f2: + fe:0e:37:e3:58:68:f9:32:fc:41:2c:35:36:f4:cf:ea:55:2d: + 52:7c:fb:37:32:35:cf:82:eb:fc:f1:39:f1:51:f1:e1:5b:d6: + 58:e1:7f:d4:50:ce:cf:07:f2:e5:f5:e2:dd:fe:55:3f:64:07: + 90:4f +-----BEGIN CERTIFICATE----- +MIICuDCCAiGgAwIBAgICEB0wDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDIw +NDdaFw0zNTAxMTMxMDIwNDdaMGkxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxGTAXBgNVBAMTEGVxdWFsIENOPVVzZXIgMjgwgZ8wDQYJKoZIhvcNAQEBBQAD +gY0AMIGJAoGBAK7fEmSr2S/uIWS1CMXIj6GtDrkokWl0E6WqSf76Ap032wo7Jmog +JT35LbI7OcjG46eqoQuyG1hD5jw/Z/67vZu12d7p7Xar/fXIFbL7pj8j759fcUOz +vlUehV8TsWudQtcwqNKb/nF6x9Nges/ig3WDuBzT7+6UPxRjqnwVTkIdAgMBAAGj +eDB2MAsGA1UdDwQEAwIF4DAdBgNVHQ4EFgQUOy0rXy7mMiOuR7cwJcvtsG0MMOQw +HwYDVR0jBBgwFoAU6Gq7wpDqbHAiPvb2SBsD5r63plUwJwYDVR0RBCAwHqQcMBox +GDAWBgNVBAMTD1VzZXIgMjggUm9vdCAxMTANBgkqhkiG9w0BAQUFAAOBgQBbz96S ++Kw5+wqBcFsX0A0NhV4ufb7RGq0dmaSm8EhaewQ54pP/gIT2oeaKUhJVRsBXhNnD +E5Jh10GvOQlXBSUBkGh8fFyFxvL+DjfjWGj5MvxBLDU29M/qVS1SfPs3MjXPguv8 +8TnxUfHhW9ZY4X/UUM7PB/Ll9eLd/lU/ZAeQTw== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101E.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101E.pem new file mode 100644 index 0000000000..f12a0c1c0d --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101E.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4126 (0x101e) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 10:22:13 2010 GMT + Not After : Jan 13 10:22:13 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 29+OU=ooo + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:ae:12:dc:26:fe:7f:b8:3f:47:a2:dc:83:a1:70: + 6d:ab:db:e5:3c:28:d5:18:32:2c:8d:ee:85:c6:f9: + f4:8b:31:34:71:de:91:79:fb:56:b4:9c:af:3e:b1: + c6:de:06:3f:32:fc:45:9d:9b:dd:15:0f:b5:c3:98: + ab:8c:1e:3d:63:7c:2a:c5:b9:38:3d:50:6c:81:9e: + f0:b3:5b:41:1a:ec:15:b2:7f:2b:b4:d4:42:aa:ca: + e6:89:b0:c6:58:bd:2d:38:f3:4d:85:c3:08:d7:45: + 48:42:d7:fe:ee:7a:c0:22:41:c0:c6:cb:77:7c:22: + 43:07:35:dc:88:7c:49:3a:9b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + E0:19:7F:AC:F8:6A:42:7E:84:CA:8C:84:45:75:4E:9D:A1:D1:2A:72 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 29 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 85:c9:ea:82:e2:ac:f6:b3:15:51:11:bd:69:81:31:8f:ee:d3: + f9:f4:8e:d5:27:34:20:89:76:eb:8a:5b:02:69:9b:97:89:d7: + 6b:aa:03:7f:b5:40:f9:ac:54:ce:8f:30:fd:3e:78:72:91:96: + dc:a6:bd:64:42:f8:e4:18:1a:e3:b5:db:08:fe:1e:fc:3d:a2: + 55:21:ad:0f:1a:87:df:f2:65:87:4d:91:52:c1:46:c1:c0:7c: + cc:81:79:97:dc:2e:41:cc:ae:8c:8e:79:4e:02:49:7c:c5:b0: + 3e:8e:d9:f0:aa:6b:a6:2f:e7:d2:21:5b:7f:57:e8:f7:f6:00: + 3c:ad +-----BEGIN CERTIFICATE----- +MIICtjCCAh+gAwIBAgICEB4wDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDIy +MTNaFw0zNTAxMTMxMDIyMTNaMGcxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxFzAVBgNVBAMTDlVzZXIgMjkrT1U9b29vMIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQCuEtwm/n+4P0ei3IOhcG2r2+U8KNUYMiyN7oXG+fSLMTRx3pF5+1a0 +nK8+scbeBj8y/EWdm90VD7XDmKuMHj1jfCrFuTg9UGyBnvCzW0Ea7BWyfyu01EKq +yuaJsMZYvS04802FwwjXRUhC1/7uesAiQcDGy3d8IkMHNdyIfEk6mwIDAQABo3gw +djALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFOAZf6z4akJ+hMqMhEV1Tp2h0SpyMB8G +A1UdIwQYMBaAFOhqu8KQ6mxwIj729kgbA+a+t6ZVMCcGA1UdEQQgMB6kHDAaMRgw +FgYDVQQDEw9Vc2VyIDI5IFJvb3QgMTEwDQYJKoZIhvcNAQEFBQADgYEAhcnqguKs +9rMVURG9aYExj+7T+fSO1Sc0IIl264pbAmmbl4nXa6oDf7VA+axUzo8w/T54cpGW +3Ka9ZEL45Bga47XbCP4e/D2iVSGtDxqH3/Jlh02RUsFGwcB8zIF5l9wuQcyujI55 +TgJJfMWwPo7Z8Kprpi/n0iFbf1fo9/YAPK0= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101F.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101F.pem new file mode 100644 index 0000000000..1393b9ed3e --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101F.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4127 (0x101f) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 10:26:01 2010 GMT + Not After : Jan 13 10:26:01 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00U\x00s\x00e\x00r\x00 \x003\x000\x00<\x00 \x00>\x00#\x00;\x00 \x00"\x00+\x00" + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:cf:40:99:4d:a5:5d:73:2a:78:72:9c:32:94:15: + 1e:01:40:b4:68:8f:b8:4e:38:aa:b9:82:96:5a:5c: + 03:d5:db:09:42:46:d8:2d:f0:da:f8:1a:f0:85:10: + f2:cb:1f:be:50:b7:ae:6f:22:80:f2:bf:14:73:84: + da:30:b9:54:26:0d:72:1c:55:99:50:c6:78:a3:37: + 15:b2:9c:03:22:dc:ea:8b:f5:07:32:f3:d9:76:64: + 92:a3:4f:73:12:e2:43:79:0e:e6:44:17:99:79:49: + 73:65:da:03:3d:be:db:e3:4f:ae:6c:d0:6c:e6:4a: + d3:83:45:5d:83:18:d5:cc:29 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + D9:EA:10:1D:D3:F5:30:AD:30:0E:80:73:14:22:1A:26:35:90:DC:67 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 30 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 42:3a:02:d5:7b:23:9f:cc:5b:b8:d4:c8:e8:0c:e3:0d:8a:17: + 65:b6:87:ce:c9:dc:f7:84:95:e0:17:ea:11:8b:15:30:e1:a2: + 42:6c:4e:f0:31:fa:fd:ff:03:37:d4:ec:4c:1d:29:8d:07:8a: + c8:de:0b:d6:df:d7:2e:12:8a:00:a0:ca:be:48:af:17:36:63: + 8e:f2:cf:80:8b:a1:e2:33:ef:42:db:91:d3:8e:4b:02:55:5e: + f7:79:11:5c:6d:ef:64:8b:53:a6:af:f5:0f:e2:75:7a:d6:85: + f6:60:d5:7e:d6:8c:0e:37:84:a9:50:2b:c7:e6:63:bf:1d:14: + aa:bf +-----BEGIN CERTIFICATE----- +MIICyDCCAjGgAwIBAgICEB8wDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDI2 +MDFaFw0zNTAxMTMxMDI2MDFaMHkxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxKTAnBgNVBAMeIABVAHMAZQByACAAMwAwADwAIAA+ACMAOwAgACIAKwAiMIGf +MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDPQJlNpV1zKnhynDKUFR4BQLRoj7hO +OKq5gpZaXAPV2wlCRtgt8Nr4GvCFEPLLH75Qt65vIoDyvxRzhNowuVQmDXIcVZlQ +xnijNxWynAMi3OqL9Qcy89l2ZJKjT3MS4kN5DuZEF5l5SXNl2gM9vtvjT65s0Gzm +StODRV2DGNXMKQIDAQABo3gwdjALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFNnqEB3T +9TCtMA6AcxQiGiY1kNxnMB8GA1UdIwQYMBaAFOhqu8KQ6mxwIj729kgbA+a+t6ZV +MCcGA1UdEQQgMB6kHDAaMRgwFgYDVQQDEw9Vc2VyIDMwIFJvb3QgMTEwDQYJKoZI +hvcNAQEFBQADgYEAQjoC1Xsjn8xbuNTI6AzjDYoXZbaHzsnc94SV4BfqEYsVMOGi +QmxO8DH6/f8DN9TsTB0pjQeKyN4L1t/XLhKKAKDKvkivFzZjjvLPgIuh4jPvQtuR +045LAlVe93kRXG3vZItTpq/1D+J1etaF9mDVftaMDjeEqVArx+Zjvx0Uqr8= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1020.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1020.pem new file mode 100644 index 0000000000..40e90d4cbe --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1020.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4128 (0x1020) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 10:28:47 2010 GMT + Not After : Jan 13 10:28:47 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00U\x00s\x00e\x00r\x00 \x003\x001\x00 \x00\\x00"\x00a\x00,\x00b\x00"\x00+\x00C\x00N\x00=\x00U\x00S\x00,\x00 \x00>\x00 \x00\\x00\\x00d\x00e\x00 \x00< + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:ac:02:18:e0:1c:54:bb:76:97:2e:d3:67:78:b7: + 14:78:46:83:7c:e9:5c:2b:2f:25:bb:bf:90:c0:52: + ea:2c:79:d6:9d:af:b5:f8:86:a2:bf:56:9b:0f:33: + ed:ef:d2:2c:57:c6:0a:25:b3:f7:9b:a1:7a:3b:75: + 0b:18:86:23:64:2a:23:b0:60:f1:d8:05:b4:a6:7b: + 77:21:30:b4:0d:f1:af:e1:fb:d6:88:a8:5b:5d:7e: + a2:bf:ce:20:f6:c0:7a:89:f2:0f:33:47:6d:49:0f: + 3d:59:27:f9:95:c0:3b:a3:1c:18:a1:2d:95:09:e8: + d2:95:ac:10:92:fc:db:84:e3 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + F8:BA:7E:78:BC:70:33:D3:45:68:37:59:3A:06:AC:65:B1:15:74:F0 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 31 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 0f:a8:53:f0:56:76:df:a8:b3:5b:d1:e8:98:62:8f:a6:13:96: + c3:6b:ca:3f:e1:09:37:54:6f:ac:15:4b:74:0c:6c:3f:fe:de: + 36:58:a2:9d:a0:1f:18:97:2c:1d:bc:c6:df:ee:aa:5b:d3:da: + 2f:51:02:7a:ba:a9:7e:4d:cf:47:16:0b:f1:b1:e1:28:2b:fe: + a4:9d:50:96:cd:c5:45:09:35:50:93:9b:97:a9:23:2a:5e:f0: + 2e:16:18:3f:50:7a:83:59:c5:6c:79:99:d3:ea:12:ef:15:a9: + b0:93:1e:4b:26:6c:63:13:7f:d3:5a:0c:4d:0b:f4:51:21:98: + 4f:81 +-----BEGIN CERTIFICATE----- +MIIC5TCCAk6gAwIBAgICECAwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDI4 +NDdaFw0zNTAxMTMxMDI4NDdaMIGVMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MUUwQwYDVQQDHjwAVQBzAGUAcgAgADMAMQAgAFwAIgBhACwAYgAiACsAQwBO +AD0AVQBTACwAIAA+ACAAXABcAGQAZQAgADwwgZ8wDQYJKoZIhvcNAQEBBQADgY0A +MIGJAoGBAKwCGOAcVLt2ly7TZ3i3FHhGg3zpXCsvJbu/kMBS6ix51p2vtfiGor9W +mw8z7e/SLFfGCiWz95uhejt1CxiGI2QqI7Bg8dgFtKZ7dyEwtA3xr+H71oioW11+ +or/OIPbAeonyDzNHbUkPPVkn+ZXAO6McGKEtlQno0pWsEJL824TjAgMBAAGjeDB2 +MAsGA1UdDwQEAwIF4DAdBgNVHQ4EFgQU+Lp+eLxwM9NFaDdZOgasZbEVdPAwHwYD +VR0jBBgwFoAU6Gq7wpDqbHAiPvb2SBsD5r63plUwJwYDVR0RBCAwHqQcMBoxGDAW +BgNVBAMTD1VzZXIgMzEgUm9vdCAxMTANBgkqhkiG9w0BAQUFAAOBgQAPqFPwVnbf +qLNb0eiYYo+mE5bDa8o/4Qk3VG+sFUt0DGw//t42WKKdoB8YlywdvMbf7qpb09ov +UQJ6uql+Tc9HFgvxseEoK/6knVCWzcVFCTVQk5uXqSMqXvAuFhg/UHqDWcVseZnT +6hLvFamwkx5LJmxjE3/TWgxNC/RRIZhPgQ== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1021.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1021.pem new file mode 100644 index 0000000000..443c074628 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1021.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4129 (0x1021) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 10:40:59 2010 GMT + Not After : Jan 13 10:40:59 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00U\x00s\x00e\x00r\x00 \x001\x004\x00 \x00"\x00,\x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00q\x00u\x00o\x00t\x00e + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:da:7a:30:0d:63:da:74:05:ef:3e:d2:f4:2b:1b: + 50:e3:64:67:98:7d:2f:83:e7:77:7b:b8:72:9b:c8: + 9e:65:de:cc:2a:7b:76:c2:08:05:7a:ce:88:3e:ed: + b5:75:89:36:d2:4a:bb:3b:66:ac:57:2b:15:99:c9: + d4:74:ca:f5:eb:ff:80:b7:9f:6b:48:2f:3b:a7:51: + c4:12:af:96:ca:ac:b9:ea:23:fd:93:f7:7d:5b:d1: + ab:7c:24:1e:fe:48:dc:33:de:45:d6:8c:86:5a:b9: + 56:3c:e4:a9:f1:8c:d7:41:01:da:04:2a:7d:06:c3: + 5b:a4:cc:5f:6c:ef:7c:4e:ef + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 49:E2:AE:12:D7:EF:C3:B5:02:65:DD:CF:B2:62:E6:25:ED:3D:10:9C + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 14 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 8b:ca:d2:93:cb:d1:cc:a9:67:a3:be:75:cf:ca:cd:22:78:cc: + 7c:f9:f1:2c:94:2c:60:bd:0f:18:16:26:fe:de:0d:19:5a:87: + de:34:8c:1f:eb:89:37:74:63:d4:d9:cd:59:35:06:24:a5:6f: + f2:c6:69:f4:b5:37:6d:ae:8b:d3:5d:5e:43:8f:36:7d:f8:0c: + 30:3f:74:3d:e2:85:89:75:58:36:0f:df:72:17:47:22:c6:fd: + 47:e3:d6:73:d1:40:89:e8:9a:ba:53:14:5c:3a:de:a9:85:a8: + 8f:b0:27:81:4d:87:ef:bb:6b:bf:8c:8a:71:9b:94:1d:30:d5: + 12:ed +-----BEGIN CERTIFICATE----- +MIIC1TCCAj6gAwIBAgICECEwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDQw +NTlaFw0zNTAxMTMxMDQwNTlaMIGFMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MTUwMwYDVQQDHiwAVQBzAGUAcgAgADEANAAgACIALABtAGkAZABkAGwAZQAg +AHEAdQBvAHQAZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA2nowDWPadAXv +PtL0KxtQ42RnmH0vg+d3e7hym8ieZd7MKnt2wggFes6IPu21dYk20kq7O2asVysV +mcnUdMr16/+At59rSC87p1HEEq+Wyqy56iP9k/d9W9GrfCQe/kjcM95F1oyGWrlW +POSp8YzXQQHaBCp9BsNbpMxfbO98Tu8CAwEAAaN4MHYwCwYDVR0PBAQDAgXgMB0G +A1UdDgQWBBRJ4q4S1+/DtQJl3c+yYuYl7T0QnDAfBgNVHSMEGDAWgBToarvCkOps +cCI+9vZIGwPmvremVTAnBgNVHREEIDAepBwwGjEYMBYGA1UEAxMPVXNlciAxNCBS +b290IDExMA0GCSqGSIb3DQEBBQUAA4GBAIvK0pPL0cypZ6O+dc/KzSJ4zHz58SyU +LGC9DxgWJv7eDRlah940jB/riTd0Y9TZzVk1BiSlb/LGafS1N22ui9NdXkOPNn34 +DDA/dD3ihYl1WDYP33IXRyLG/Ufj1nPRQInomrpTFFw63qmFqI+wJ4FNh++7a7+M +inGblB0w1RLt +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1022.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1022.pem new file mode 100644 index 0000000000..6902605756 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1022.pem @@ -0,0 +1,64 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4130 (0x1022) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Nov 8 10:51:39 2010 GMT + Not After : Nov 8 10:51:39 2011 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 35 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:9b:36:00:64:f3:ce:93:97:62:19:fa:78:d9:6f: + 92:6a:b9:d2:9a:4e:06:2c:02:52:cd:93:50:84:28: + 19:42:a2:4a:34:e2:cd:e6:b0:39:7a:c8:4d:84:bc: + 71:51:ed:5d:6c:7e:f9:cc:01:5a:4b:73:50:a9:3b: + 5d:ad:cc:89:f7:dc:e0:dd:0a:ff:48:01:a9:34:19: + c0:6a:ee:4b:20:f4:cf:3c:94:c1:ae:88:0f:c9:42: + 1a:a6:47:31:fe:37:04:00:bb:ec:07:5f:cb:ee:70: + c4:c7:7c:6f:ee:03:19:76:de:0b:df:d0:48:91:67: + 55:9b:90:91:f4:ce:56:04:d5 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 91:47:AC:29:95:5D:EF:72:14:8F:82:45:07:E2:94:49:75:C6:7D:73 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DNS:alt.openoffice.org, IP Address:192.168.7.1, IP Address:13:0:0:0:0:0:0:17, email:my@other.address, Registered ID:1.2.3.4, othername:, DirName:/C=DE/O=OpenOffice.org/OU=Development/CN=User 32 Root 11, URI:http://my.url.here/ + Signature Algorithm: sha1WithRSAEncryption + 6e:80:e6:1e:86:3d:d2:65:a6:17:fa:80:2d:2e:dc:85:32:05: + a1:69:82:e1:79:d1:dc:de:69:cd:9e:f0:cc:90:75:a9:45:ee: + 73:46:fe:29:69:c0:99:bb:fc:3a:db:c0:5f:69:c6:b7:ea:9a: + 63:b2:8e:29:2c:a5:5a:88:88:94:75:4b:ab:0a:72:f6:3a:aa: + 5d:6b:3a:5c:b6:9b:57:f5:c1:51:af:df:3c:a6:8a:a3:da:70: + 66:61:49:12:06:78:98:9f:bc:78:3c:43:6d:08:94:aa:32:b6: + f3:cc:af:0d:29:fe:96:47:7d:fe:4a:61:48:90:11:0b:bd:0f: + a0:fd +-----BEGIN CERTIFICATE----- +MIIDajCCAtOgAwIBAgICECIwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDExMDgxMDUx +MzlaFw0xMTExMDgxMDUxMzlaMGAxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxEDAOBgNVBAMTB1VzZXIgMzUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB +AJs2AGTzzpOXYhn6eNlvkmq50ppOBiwCUs2TUIQoGUKiSjTizeawOXrITYS8cVHt +XWx++cwBWktzUKk7Xa3Miffc4N0K/0gBqTQZwGruSyD0zzyUwa6ID8lCGqZHMf43 +BAC77Adfy+5wxMd8b+4DGXbeC9/QSJFnVZuQkfTOVgTVAgMBAAGjggExMIIBLTAL +BgNVHQ8EBAMCBeAwHQYDVR0OBBYEFJFHrCmVXe9yFI+CRQfilEl1xn1zMB8GA1Ud +IwQYMBaAFOhqu8KQ6mxwIj729kgbA+a+t6ZVMIHdBgNVHREEgdUwgdKCEmFsdC5v +cGVub2ZmaWNlLm9yZ4cEwKgHAYcQABMAAAAAAAAAAAAAAAAAF4EQbXlAb3RoZXIu +YWRkcmVzc4gDKgMEoB4GAyoDBKAXDBVzb21lIG90aGVyIGlkZW50aWZpZXKkWDBW +MQswCQYDVQQGEwJERTEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsT +C0RldmVsb3BtZW50MRgwFgYDVQQDEw9Vc2VyIDMyIFJvb3QgMTGGE2h0dHA6Ly9t +eS51cmwuaGVyZS8wDQYJKoZIhvcNAQEFBQADgYEAboDmHoY90mWmF/qALS7chTIF +oWmC4XnR3N5pzZ7wzJB1qUXuc0b+KWnAmbv8OtvAX2nGt+qaY7KOKSylWoiIlHVL +qwpy9jqqXWs6XLabV/XBUa/fPKaKo9pwZmFJEgZ4mJ+8eDxDbQiUqjK288yvDSn+ +lkd9/kphSJARC70PoP0= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/private/cakey.pem new file mode 100644 index 0000000000..fb0dd164ef --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,F268674FF1377D42 + +kJQy9qJMCqZyDVs3+ZKQnh22enecltKSYzd0S1dIN1chgQ0RzLEiWBHmHCVP/yB0 +YoKrQ07FUR/uSLqTbyhAl+KDVcNvqrj/NeWs0n8zqN0ZF6wQtxtDrWFWmHNAvQXU +2kO1CvjYiruapgwmVDDJV1qf25byenQv9LMyQMD6EPU1XqFeamklidALdkb7DylA +WL6EIg4vhh96ZaG6PwLcB9rho0QRrXrLS6SHiklNBN5fHUWOfDyhXJ7K4HvzH1SS +/EtqgyKKxH5irTRdoJg2OaDBAahyW93CneEnFdufDgzvCdrsg79Z2GFz7TDJEfW4 +rnoqoXTdei1Ah+t1BC4uXXAU8DR0xusnJi0qJDJ7ETRBhROlNhTRF8TAHll+5dIf +9772GwVT+hADZn1qJgmhPiN4f8Fx33k5NOcwb0X/0Z1mzULrwm1P6lng0DsusDo0 +dr/wFyRjWZEWhMcL/sIO1BwVTBPcE8CACnXutehs44DBWd91EQ4+PWNq7oPtHFw8 +09d30h4aJJZF/SGRi+f/czFyZF4WS2Q+UWmNNKJX8wCGQqzUb02kVwMEWHiNFiEo +V8xI3JXVmKHDWlgdoIz9kVe//3AfY5y+52cYLdqaNW8IsgWZC8SC9Lk9j5uaNZ/I +leNppt4ID7mfYPqjEXEKleC+1ncwFwdVl/zaa/fM78sWqDYrLZC47DToLfoQ9Gez +3dj3554iHTe61Jd7JsK85pYsrIHAeYppOpqzLyQmCu3twBl3uGD7KXxvdZRt8foE +Vrg/QSIB4E6gfSBP0UrXzsnga8tjVyqRW2vAvt0uLn945ducapf9oQ== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/serial b/xmlsecurity/test_docs/CAs/Root_11/demoCA/serial new file mode 100644 index 0000000000..b70608fe85 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/serial @@ -0,0 +1 @@ +1023 diff --git a/xmlsecurity/test_docs/CAs/Root_11/openssl.cfg b/xmlsecurity/test_docs/CAs/Root_11/openssl.cfg new file mode 100644 index 0000000000..dd84cb9069 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/openssl.cfg @@ -0,0 +1,298 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert +utf8 = yes +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask =pkix + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 +commonName_default =User 14 \",middle quote + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +#nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move +subjectAltName=DNS:alt.openoffice.org,IP:192.168.7.1,IP:13::17,email:my@other.address,RID:1.2.3.4,otherName:1.2.3.4;UTF8:some other identifier,dirName:dir_sect,URI:http://my.url.here/ +# Copy subject details +# issuerAltName=issuer:copy + + +[dir_sect] +C=DE +O=OpenOffice.org +OU=Development +CN=User 32 Root 11 + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Root_7.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Root_2/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Root_2/demoCA/cacert.pem new file mode 100644 index 0000000000..e64badeef6 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_2/demoCA/cacert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDBDCCAm2gAwIBAgIJAKKvFYnsc1SGMA0GCSqGSIb3DQEBBQUAMF8xCzAJBgNV +BAYTAkRFMRAwDgYDVQQIEwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9y +ZzEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgMjAeFw0wOTEx +MTgxNTQ2NTJaFw0zNDExMTIxNTQ2NTJaMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgMjCBnzANBgkqhkiG9w0BAQEFAAOBjQAw +gYkCgYEAsJSDLnSsoNY1U8hS0g5cmu7ihp+nvDvx8C75Wav80KumG9gcS3icmSOm +vPVqUmJq5o9CKM8z4vJR7D3e+Wf7S7XHMdL0uXuQi+QQCB1aMAWMxo7xnoWAXZrS +LG1BWUjD9sdKCHuQfFQv9ke3cA2dGZFSMsUD73JYoo0RD72ftFkCAwEAAaOBxzCB +xDAdBgNVHQ4EFgQUX7xM2usKDLUjQ14kMid5QfWCowIwgZEGA1UdIwSBiTCBhoAU +X7xM2usKDLUjQ14kMid5QfWCowKhY6RhMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgMoIJAKKvFYnsc1SGMA8GA1UdEwEB/wQF +MAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAqfEPhXASt24n8P9mDKisEn2EIYmJKLaY +AVwXLPXUOiMlqrfPRKpseQII4WmDCRxMa6bKCwf4pKUWIpTpDhRZCUespaLz1AcU +ntv+HTXq1ECK+akK33fsh5qMvokfzZM+Q0zCiFV/c2aTTGSM5mV3/q810RUlNQY3 +1y+AN+6fRqE= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_2/demoCA/crl/DO_NOT_CREATE_A_CRL b/xmlsecurity/test_docs/CAs/Root_2/demoCA/crl/DO_NOT_CREATE_A_CRL new file mode 100644 index 0000000000..e69de29bb2 diff --git a/xmlsecurity/test_docs/CAs/Root_2/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Root_2/demoCA/crlnumber new file mode 100644 index 0000000000..83b33d238d --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_2/demoCA/crlnumber @@ -0,0 +1 @@ +1000 diff --git a/xmlsecurity/test_docs/CAs/Root_2/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Root_2/demoCA/index.txt new file mode 100644 index 0000000000..3e79e22d7c --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_2/demoCA/index.txt @@ -0,0 +1 @@ +V 341112155538Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 1 Root 2 diff --git a/xmlsecurity/test_docs/CAs/Root_2/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Root_2/demoCA/index.txt.attr new file mode 100644 index 0000000000..8f7e63a347 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_2/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Root_2/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Root_2/demoCA/newcerts/1000.pem new file mode 100644 index 0000000000..36a8eb3c07 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_2/demoCA/newcerts/1000.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 2 + Validity + Not Before: Nov 18 15:55:38 2009 GMT + Not After : Nov 12 15:55:38 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 2 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:f0:7a:16:4c:ab:06:b2:af:27:9c:7d:3f:86:da: + de:7a:c3:01:67:77:56:49:09:ed:ed:31:72:83:e8: + 75:9c:4c:ce:f9:97:b6:63:3c:e2:ca:83:80:92:03: + 9c:96:e2:de:72:79:c1:cf:3e:3f:b9:0d:b4:87:c7: + 75:e6:56:8d:aa:f8:77:47:11:4e:fe:07:b0:1d:64: + 06:73:4b:6f:d4:ac:da:0f:05:87:b1:f1:98:a9:f5: + 8a:a1:a8:ed:17:9c:26:b8:da:92:63:d2:53:87:e6: + fc:ed:44:de:94:56:90:3e:a2:a1:67:08:cb:38:d4: + cf:17:3b:7e:ff:7a:97:c0:7b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 8C:F3:2C:30:A2:E8:62:50:70:BC:FC:71:A0:41:FA:E0:58:B4:4D:B8 + X509v3 Authority Key Identifier: + keyid:5F:BC:4C:DA:EB:0A:0C:B5:23:43:5E:24:32:27:79:41:F5:82:A3:02 + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 2 + serial:A2:AF:15:89:EC:73:54:86 + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 52:83:16:ab:0e:43:2d:b3:e4:0f:6c:c1:63:d4:86:ac:e7:1e: + ee:7b:ee:9b:0c:ff:4f:e0:59:d5:e4:27:af:68:bf:a7:f5:2a: + a3:c9:e3:2b:8d:b7:31:26:f6:04:80:4e:f2:a5:bf:da:63:5e: + 8c:d6:c6:b2:46:a0:46:10:2f:84:9f:02:76:f3:c8:33:05:62: + 0c:5f:2d:cc:06:23:53:9f:d9:f8:46:e4:2e:5c:da:05:fc:bf: + db:45:b4:ac:8d:8b:b5:4b:60:7b:7b:26:34:7f:b1:4b:41:96: + 41:26:70:7a:9d:78:a2:9b:e0:de:62:a2:04:86:9f:ed:7c:a6: + 20:eb +-----BEGIN CERTIFICATE----- +MIIDBjCCAm+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCAyMB4XDTA5MTExODE1NTUz +OFoXDTM0MTExMjE1NTUzOFowaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCAyMIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDwehZMqwayryecfT+G2t56wwFnd1ZJCe3tMXKD6HWcTM75l7ZjPOLK +g4CSA5yW4t5yecHPPj+5DbSHx3XmVo2q+HdHEU7+B7AdZAZzS2/UrNoPBYex8Zip +9YqhqO0XnCa42pJj0lOH5vztRN6UVpA+oqFnCMs41M8XO37/epfAewIDAQABo4HH +MIHEMB0GA1UdDgQWBBSM8ywwouhiUHC8/HGgQfrgWLRNuDCBkQYDVR0jBIGJMIGG +gBRfvEza6woMtSNDXiQyJ3lB9YKjAqFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCAyggkAoq8ViexzVIYwDwYDVR0TAQH/ +BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBSgxarDkMts+QPbMFj1Ias5x7ue+6b +DP9P4FnV5CevaL+n9SqjyeMrjbcxJvYEgE7ypb/aY16M1sayRqBGEC+EnwJ288gz +BWIMXy3MBiNTn9n4RuQuXNoF/L/bRbSsjYu1S2B7eyY0f7FLQZZBJnB6nXiim+De +YqIEhp/tfKYg6w== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_2/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Root_2/demoCA/private/cakey.pem new file mode 100644 index 0000000000..7ef7ef0a5e --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_2/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,52B792B2B0E03BD6 + +GIFY+N2q5LMcrtTplZUToF0/nuplr7ASLAe7lEcDLTTHeBTO+w4ScB62Dl6veeEU +3/pPevG+V3HIA5ukywX334DuWjL3bFIsPg8a3NKKn0nTpmwqHqXZ53kbSMHIiu6v +MkvGeVLLxLhnCsqQ8HI2ccuxGSXLA0rqlnrZTOtvQpw9ohpCM3CX1GeekLc83bL/ +4HHmw8nNL+OCH4l9g3Y8XpN3ySRgl+lWmoKxl9s2Mn7jFoaqSXuuH3wIu9D2kJxS +qfVs/fo12j8RWXSIMpiCJFCOx1v+zzX7dJ0cyim83WF2OHsOW03UYnWzgk44iz4d +/WVWJuRU3gEwpN3CDdhzBZuYw9DmaG8HLHYT15CSdkQrfHeFM3Axcoju7b887JX7 +sOHU6h4ebMVhAswAXKGlTKOY2PO1GE9cKoa2jxnB2z8Dhe8rxzuvWyr5BfXrS3KT +lM6pjxZSoGMcmG7FtDgU/aAIn+DPR/rdB7tfZwP3GoVV+n3jRi8LU5I3wbi4z70o +bwXMb7zN13WHFszZgPX4tHD3jjyLwk7rFmMJ17L3K6eOAlGg8o+FBgoqYFQo05sY +2SElOibX8RIj9m9lerNLOxB5ty2VDUSaytJ0b1gPTXAdsaryq7tKFxIrNKpiJ1qk +snQSJyr2JwRqBLRwkXZV5CliWwZJGGJsC9I5fAMuuW6qkDhsSQ1fIJsGn/SbbiZj +lnZVY/33vHMltbwEgY4GuQWm29VYJwLWk925BY/nQ5fWPARYsap04JIwtperrZKj +XETzTrnTje6sVl32aCLdYlwsVbh04zRwUFharCz5vtDdVeHrfsBDKA== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Root_2/demoCA/serial b/xmlsecurity/test_docs/CAs/Root_2/demoCA/serial new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_2/demoCA/serial @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Root_2/openssl.cfg b/xmlsecurity/test_docs/CAs/Root_2/openssl.cfg new file mode 100644 index 0000000000..0dd15bd9ec --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_2/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Root_3/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Root_3/demoCA/cacert.pem new file mode 100644 index 0000000000..55be155218 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_3/demoCA/cacert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDBDCCAm2gAwIBAgIJAJVv8OMrvnb5MA0GCSqGSIb3DQEBBQUAMF8xCzAJBgNV +BAYTAkRFMRAwDgYDVQQIEwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9y +ZzEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgMzAeFw0wOTEx +MjAwNzM2MTVaFw0zNDExMTQwNzM2MTVaMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgMzCBnzANBgkqhkiG9w0BAQEFAAOBjQAw +gYkCgYEA3L6zaGhxFC+Mf55dzotmPKxdZndlxSVVOVI93JrxKVfn8mYOCZEjdb9Q +65vgLxGXMC9LCiF6SfT8dIfav1hUugmLaLzBesPu6h4kHN33/7Asj8BzY5I57uvF +sMLNL5hHFRRqtBqHvmO2G8zjHPluObnBzaQNCbdZxYODeh1GFpECAwEAAaOBxzCB +xDAdBgNVHQ4EFgQUaf8w7B80mmc6ayDS33/1BQTt+RwwgZEGA1UdIwSBiTCBhoAU +af8w7B80mmc6ayDS33/1BQTt+RyhY6RhMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgM4IJAJVv8OMrvnb5MA8GA1UdEwEB/wQF +MAMBAf8wDQYJKoZIhvcNAQEFBQADgYEABPdAJer/8FoOAMWszhfz/BEjF97TTFs1 +KqSEiuymswG706weo9tcnP8u81AITQPSWZE1ALQN5L35Zvg6ubJsNM3+VSoQ6hZj +G9oWAJzFN7DhIqs3Xb13eBH/0yqAdTuFB5uLcJdR3GIXGFvcU/5FZBpYnORVqvg4 +irKv2VvyCR0= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_3/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Root_3/demoCA/crlnumber new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_3/demoCA/crlnumber @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Root_3/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Root_3/demoCA/index.txt new file mode 100644 index 0000000000..dd9a47ee64 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_3/demoCA/index.txt @@ -0,0 +1 @@ +V 341114074039Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 1 Root 3 diff --git a/xmlsecurity/test_docs/CAs/Root_3/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Root_3/demoCA/index.txt.attr new file mode 100644 index 0000000000..8f7e63a347 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_3/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Root_3/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Root_3/demoCA/newcerts/1000.pem new file mode 100644 index 0000000000..c14880b580 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_3/demoCA/newcerts/1000.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 3 + Validity + Not Before: Nov 20 07:40:39 2009 GMT + Not After : Nov 14 07:40:39 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 3 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:9e:87:1f:af:f0:a0:1c:f4:9e:f8:c3:e7:ee:d3: + cb:a8:e2:54:98:ba:dd:7e:dc:6e:14:e1:7e:7f:5b: + 1e:ef:53:3d:89:76:ea:e2:b3:6c:08:0d:e8:c8:4d: + 24:40:ff:92:f3:5b:51:f7:90:ac:69:37:29:90:f5: + e8:95:6f:67:d1:10:cd:7b:dd:65:38:d6:25:ec:63: + 39:ba:2e:ea:13:58:8e:7a:82:8e:10:d1:7b:77:7a: + 08:d5:82:66:62:a4:83:39:ad:f5:83:d5:2f:5c:bc: + 23:6e:c8:78:8b:38:9f:eb:a3:67:ba:43:fa:e4:07: + 3f:90:72:db:0c:f9:49:0e:0d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 1B:2D:E0:A2:26:7F:0D:BA:38:7E:EC:06:81:81:0F:12:74:4C:5A:4D + X509v3 Authority Key Identifier: + keyid:69:FF:30:EC:1F:34:9A:67:3A:6B:20:D2:DF:7F:F5:05:04:ED:F9:1C + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 3 + serial:95:6F:F0:E3:2B:BE:76:F9 + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 6f:ac:53:9d:16:6e:95:ed:97:60:ed:c8:a8:96:ab:24:c5:1e: + d5:d7:26:98:fb:b5:aa:ef:da:a4:91:6a:82:55:ec:21:a2:08: + 24:c7:0c:a7:58:0c:06:69:3d:04:7d:08:f1:0b:77:41:ad:1c: + 13:c2:bd:17:c9:9e:ff:df:64:69:8b:58:f1:bc:40:bd:cf:e4: + 57:29:bc:5e:93:84:61:56:4c:e6:c1:3a:2c:6e:71:ea:5d:67: + c0:54:be:4f:2f:27:a8:59:8d:29:94:ba:c6:6c:ff:ed:25:3d: + 0b:fa:93:c9:45:f4:d5:a3:3d:be:8a:f1:9d:c4:92:d5:5c:d2: + 77:7c +-----BEGIN CERTIFICATE----- +MIIDBjCCAm+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCAzMB4XDTA5MTEyMDA3NDAz +OVoXDTM0MTExNDA3NDAzOVowaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCAzMIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQCehx+v8KAc9J74w+fu08uo4lSYut1+3G4U4X5/Wx7vUz2Jduris2wI +DejITSRA/5LzW1H3kKxpNymQ9eiVb2fREM173WU41iXsYzm6LuoTWI56go4Q0Xt3 +egjVgmZipIM5rfWD1S9cvCNuyHiLOJ/ro2e6Q/rkBz+QctsM+UkODQIDAQABo4HH +MIHEMB0GA1UdDgQWBBQbLeCiJn8Nujh+7AaBgQ8SdExaTTCBkQYDVR0jBIGJMIGG +gBRp/zDsHzSaZzprINLff/UFBO35HKFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCAzggkAlW/w4yu+dvkwDwYDVR0TAQH/ +BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBvrFOdFm6V7Zdg7ciolqskxR7V1yaY ++7Wq79qkkWqCVewhoggkxwynWAwGaT0EfQjxC3dBrRwTwr0XyZ7/32Rpi1jxvEC9 +z+RXKbxek4RhVkzmwTosbnHqXWfAVL5PLyeoWY0plLrGbP/tJT0L+pPJRfTVoz2+ +ivGdxJLVXNJ3fA== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_3/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Root_3/demoCA/private/cakey.pem new file mode 100644 index 0000000000..445d86f995 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_3/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,24B61B9BC2D90894 + +pJUmVTVcjD3b4WKoSDJHrxHYOJ5/6P0FyQRYaJhnDXpcC5cQywl7yuD3HpRh3cXT +Y5k6d1E64St3I/IDImdbiEEDbjlSG9gfFf9vYeP/Xlpaja0Y9Q2ePnQvJY47HB7+ +qkrt6b+3yIW024wHi83dzaeYeNUJaY1jGsra2TzGk/+hYrf6yvnyehEAsy5WChof +bfaQ29RrGTlzf6IpSRpiHUL7nVl+eHfbGLX4Ih8aEFXpcnoWtpY8FgQ5+bJxMeR4 +R2ge0c3G0VIBXBRRUoGsU0ZcRLdxYUFcDGZse50ZboUwvROfPCimowcyWKluV9yj +l4+e3glYcwGHRqHYArsLDUV2hzHHEJ1IKn4E+oExqQSGgDQgUDN0kjlRPPxWQb29 +6dZSHW4VXW609Q10FKbPuCocgQ2Ut2bNGWqXsiNNTr39iB0r/hA/V4bKy3G8ogsH +AQFp6D9LaFlt9ZFA49Y4WoPzSY9J2C4eFJzQ+jhCpeapzQ54BWNTYMQe+SJHkp1O +PWVovUrRbTDesIUeY1UJuSnbDotOc6vzEAsP+FIL2qUySUGG/CPyAf3R4FyahwjL +bgU5kmpzBKsgqRYrO2yfLz5/3/e9xUGfHVi8lbI5f21NQKesqHY2xS2NmGvakzbe +ZvD3bhythAR5L0Pp+tiiHE1LUAbcKp90aFPeaONDpUtrRU21gqqvEKnnubCvnjmE +l6GrH2WKSgxJbQ3GGqNaDg1ivB8XXyjx7guvBzpA0Pe2YCYMa0RI27GywNkv+RsR +eo3ox2QhUpvPxUl3ijwOPN3EFXrq0gdlYQJBWW3GLlX4Q71KJF+jUQ== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Root_3/demoCA/serial b/xmlsecurity/test_docs/CAs/Root_3/demoCA/serial new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_3/demoCA/serial @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Root_3/openssl.cfg b/xmlsecurity/test_docs/CAs/Root_3/openssl.cfg new file mode 100644 index 0000000000..51e5205253 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_3/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Root_4/README.txt b/xmlsecurity/test_docs/CAs/Root_4/README.txt new file mode 100644 index 0000000000..b9fb278a27 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_4/README.txt @@ -0,0 +1,4 @@ +Revoked certificates: + +- Sub CA 2 Root 4 + diff --git a/xmlsecurity/test_docs/CAs/Root_4/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Root_4/demoCA/cacert.pem new file mode 100644 index 0000000000..45b4ce8a5f --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_4/demoCA/cacert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDBDCCAm2gAwIBAgIJAKKTRnQ7puOtMA0GCSqGSIb3DQEBBQUAMF8xCzAJBgNV +BAYTAkRFMRAwDgYDVQQIEwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9y +ZzEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgNDAeFw0wOTEx +MjAwODM1MDRaFw0zNDExMTQwODM1MDRaMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgNDCBnzANBgkqhkiG9w0BAQEFAAOBjQAw +gYkCgYEA2k+jPArotoY09an0BpF3RYIPP/5RN04E4S+Ulp/ipttaVxtAC0ojJSlp +0PGp/vIodFT9pkBb0nq56LHjFLj+lyW5tKAR+4B+VVvzwJhUBD8qHjYJE30vWZ88 +3+3I+GmXDzy962kQxrb4J6dBwGImoqhBTXWOxGnPjXxtovzYmMECAwEAAaOBxzCB +xDAdBgNVHQ4EFgQUuo2hl9zEOR+QtVFrEBnyRg2pZY4wgZEGA1UdIwSBiTCBhoAU +uo2hl9zEOR+QtVFrEBnyRg2pZY6hY6RhMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgNIIJAKKTRnQ7puOtMA8GA1UdEwEB/wQF +MAMBAf8wDQYJKoZIhvcNAQEFBQADgYEARdHX1KRJ/DE1zOkbjINPX4pFjTMIIfKd +ncEBM7Po20it75Hbl8bHoxwCrjOu+9L1xaTCWcunyqv26yrjVpORPHPODLMc2W8x +FQm39hL6a0RjqurDlhcrjor3HD7hQ+GjEUDAX6Pk9RDxN+uMHvF5/5WCEhSn2aLT +IozGu5SmZys= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_4/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Root_4/demoCA/crlnumber new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_4/demoCA/crlnumber @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Root_4/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Root_4/demoCA/index.txt new file mode 100644 index 0000000000..f07b3377de --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_4/demoCA/index.txt @@ -0,0 +1,2 @@ +V 341114083727Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 1 Root 4 +R 341114092227Z 091120092718Z,keyCompromise 1001 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 2 Root 4 diff --git a/xmlsecurity/test_docs/CAs/Root_4/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Root_4/demoCA/index.txt.attr new file mode 100644 index 0000000000..8f7e63a347 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_4/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Root_4/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Root_4/demoCA/newcerts/1000.pem new file mode 100644 index 0000000000..3910371181 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_4/demoCA/newcerts/1000.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 4 + Validity + Not Before: Nov 20 08:37:27 2009 GMT + Not After : Nov 14 08:37:27 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 4 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:da:b0:21:94:89:b0:00:89:cb:69:59:9b:0d:fe: + 1f:b9:a0:a8:44:92:55:5f:0b:d5:e5:08:63:bd:47: + 6b:11:4d:b1:a8:12:6f:c1:cf:cb:9e:ae:e2:c1:03: + 68:46:59:0b:96:7c:21:45:9b:14:81:d8:f1:83:70: + 6b:3d:b4:56:65:49:87:1d:ab:e2:08:6a:49:66:0e: + 59:b4:da:7a:3f:72:23:b8:1f:fb:78:f5:f0:2d:c4: + fe:d9:94:6e:2e:c3:6e:95:ba:38:60:d1:0b:fa:16: + c7:02:71:ef:3e:71:72:63:26:56:35:1e:8b:ec:47: + 87:25:6e:bc:90:d0:8b:37:2d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 96:9A:2D:06:F6:76:4F:83:68:7B:9C:69:C4:18:BB:4A:EB:46:38:E4 + X509v3 Authority Key Identifier: + keyid:BA:8D:A1:97:DC:C4:39:1F:90:B5:51:6B:10:19:F2:46:0D:A9:65:8E + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 4 + serial:A2:93:46:74:3B:A6:E3:AD + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 45:77:ba:6b:b6:a7:2a:0f:6b:38:90:9f:0a:18:11:c7:54:7b: + c9:3b:9a:93:90:96:f0:04:0a:56:87:30:e0:f5:d8:84:40:39: + 90:85:ca:e7:38:1b:d8:df:2f:bd:73:91:13:cb:a6:c9:b0:7a: + f7:59:77:6b:9a:d5:86:78:06:dc:40:14:ce:ea:43:a8:ae:ed: + a2:03:64:51:3a:47:7a:9f:df:2d:65:49:56:a5:39:cf:28:2a: + ac:ab:fd:e1:93:fd:3e:56:e8:eb:7a:11:a8:f7:f9:1a:a1:83: + 1f:92:f7:da:4e:c6:d9:67:dd:67:ff:be:6f:e5:24:e1:6e:cc: + 94:3c +-----BEGIN CERTIFICATE----- +MIIDBjCCAm+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA0MB4XDTA5MTEyMDA4Mzcy +N1oXDTM0MTExNDA4MzcyN1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA0MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDasCGUibAAictpWZsN/h+5oKhEklVfC9XlCGO9R2sRTbGoEm/Bz8ue +ruLBA2hGWQuWfCFFmxSB2PGDcGs9tFZlSYcdq+IIaklmDlm02no/ciO4H/t49fAt +xP7ZlG4uw26Vujhg0Qv6FscCce8+cXJjJlY1HovsR4clbryQ0Is3LQIDAQABo4HH +MIHEMB0GA1UdDgQWBBSWmi0G9nZPg2h7nGnEGLtK60Y45DCBkQYDVR0jBIGJMIGG +gBS6jaGX3MQ5H5C1UWsQGfJGDalljqFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA0ggkAopNGdDum460wDwYDVR0TAQH/ +BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBFd7prtqcqD2s4kJ8KGBHHVHvJO5qT +kJbwBApWhzDg9diEQDmQhcrnOBvY3y+9c5ETy6bJsHr3WXdrmtWGeAbcQBTO6kOo +ru2iA2RROkd6n98tZUlWpTnPKCqsq/3hk/0+VujrehGo9/kaoYMfkvfaTsbZZ91n +/75v5SThbsyUPA== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_4/demoCA/newcerts/1001.pem b/xmlsecurity/test_docs/CAs/Root_4/demoCA/newcerts/1001.pem new file mode 100644 index 0000000000..9d951ee267 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_4/demoCA/newcerts/1001.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4097 (0x1001) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 4 + Validity + Not Before: Nov 20 09:22:27 2009 GMT + Not After : Nov 14 09:22:27 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 2 Root 4 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:e5:8d:27:4e:09:53:08:61:c6:23:25:9e:dd:9c: + 07:bf:81:38:5c:5c:10:8f:e4:12:2f:4e:2e:b1:a1: + cf:21:46:53:bf:e8:5e:de:17:3a:9d:f7:e8:ef:3e: + 9c:b4:29:37:4c:31:35:15:dc:98:e0:93:9c:ce:6a: + d6:e1:35:19:6b:d4:1d:3b:81:86:b1:e7:ff:1f:b8: + 34:a9:f9:de:4d:b8:62:ac:3b:d4:58:8e:5c:76:b5: + 07:7f:32:8a:3a:90:73:71:d5:da:f1:79:39:14:ed: + 1b:f1:8a:3e:be:48:bc:07:ec:f9:7c:03:14:fc:e7: + 55:a3:65:81:c7:6c:70:0b:ff + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 69:DE:B6:99:C4:95:F7:5A:FA:41:6B:4C:F6:C3:6D:89:AA:37:31:9D + X509v3 Authority Key Identifier: + keyid:BA:8D:A1:97:DC:C4:39:1F:90:B5:51:6B:10:19:F2:46:0D:A9:65:8E + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 4 + serial:A2:93:46:74:3B:A6:E3:AD + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + bc:cf:43:eb:72:b1:71:a7:94:8e:cd:5b:fc:d8:21:31:83:db: + a9:de:c7:5b:14:e5:7b:90:43:e6:05:df:db:6e:95:5f:24:ac: + 0c:a1:8a:ac:c6:cf:f2:03:cd:a0:30:ae:d3:a9:41:07:c9:b1: + be:4b:e0:fc:a2:76:09:07:75:6a:fa:e4:2f:a3:3a:cd:81:68: + ab:f6:06:c4:32:08:25:6e:e8:e7:36:9c:1a:f7:42:73:f8:b0: + d8:42:3e:85:c2:11:23:10:d6:6a:e4:8f:53:cb:8b:8b:1b:5a: + 4d:6d:9d:34:45:26:52:d2:ee:6d:8f:23:ff:00:92:f5:99:62: + 4c:41 +-----BEGIN CERTIFICATE----- +MIIDBjCCAm+gAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA0MB4XDTA5MTEyMDA5MjIy +N1oXDTM0MTExNDA5MjIyN1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDIgUm9vdCA0MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDljSdOCVMIYcYjJZ7dnAe/gThcXBCP5BIvTi6xoc8hRlO/6F7eFzqd +9+jvPpy0KTdMMTUV3Jjgk5zOatbhNRlr1B07gYax5/8fuDSp+d5NuGKsO9RYjlx2 +tQd/Moo6kHNx1drxeTkU7Rvxij6+SLwH7Pl8AxT851WjZYHHbHAL/wIDAQABo4HH +MIHEMB0GA1UdDgQWBBRp3raZxJX3WvpBa0z2w22JqjcxnTCBkQYDVR0jBIGJMIGG +gBS6jaGX3MQ5H5C1UWsQGfJGDalljqFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA0ggkAopNGdDum460wDwYDVR0TAQH/ +BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQC8z0PrcrFxp5SOzVv82CExg9up3sdb +FOV7kEPmBd/bbpVfJKwMoYqsxs/yA82gMK7TqUEHybG+S+D8onYJB3Vq+uQvozrN +gWir9gbEMgglbujnNpwa90Jz+LDYQj6FwhEjENZq5I9Ty4uLG1pNbZ00RSZS0u5t +jyP/AJL1mWJMQQ== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_4/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Root_4/demoCA/private/cakey.pem new file mode 100644 index 0000000000..003d2f3b56 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_4/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,26D3AA1ECCD64EF2 + +Smy62JNi1/1qKZI1q2lF13336vwJWfw+ii4g/ZwMJWuwTWUGXWZ1o9B9pZFo78KM +pMlasoCwAoI3lepMIwxtSRMgstxacJ4QRVPdevo7Qq6+++qNXdkqq9pYM19dsOiu +UNpbPXVvKQZnvm0ZFCjqiylvjCaQVQRScdwu9cJyq2qIQ1laXQoW2fPYBb8KSsCO +B5E76zAGdRlzEglT9Qkjbi2dQWxWpMHFfWZydFJnNbuh7O+RxCSOJN3jXlDRGPag +IwL4mFX8dElCwWhNpdd1pXF2ZXQ2S6Ke1MoOXRvJ7XVvEfnGyHpHQRdNB0M9gJCf +3ynJ0UUiCvXJs/6NEcOZzZ+R38XfMvsOcG1jNuh2KE5hW3cGbQMV2TPZMHjGE/qn +EhX+vzIOhRUPTUQjrjmV/lgioL4pMKFBXyfr2tkNLVOfzQtIXVfgxF1ooVmZFGKR +fAmHRbXKSrGWPJkX75bdlVnQ15qz5dU7PkIohGwGojOHuTWLXzKtOuLs7KMmH/i1 +5MhxcoXbI4R+hX/oj2Es4MKYFcSI0MID9Z5Se6z/yaz++5P9OrEGrXydg4W5YSuc +Q+MovUuqNoDH+Mo0z2P2DL4OxcIkBYoUVFOnIL2v5thRgbdWk05m0OBWYnvue9MG +CiuA49Lqg0H2ViZrDCyGDQNBkDkW7AKHYhVe3afHSDENX+wsgB1oj1bMvWNLQfCB +2IOYjv+of7tNOvIH6AuaJDqF2TYOm4ipcjSD/SEuKfrOgXlq6702tRhL4aAfHa6K +o1yrUfAxLwqN/TjSDNfOIUr5ro24tYnUaUnYPpn/zwZ5WfitZ4RGBg== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Root_4/demoCA/serial b/xmlsecurity/test_docs/CAs/Root_4/demoCA/serial new file mode 100644 index 0000000000..7d802a3e71 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_4/demoCA/serial @@ -0,0 +1 @@ +1002 diff --git a/xmlsecurity/test_docs/CAs/Root_4/openssl.cfg b/xmlsecurity/test_docs/CAs/Root_4/openssl.cfg new file mode 100644 index 0000000000..51e5205253 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_4/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Root_5/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Root_5/demoCA/cacert.pem new file mode 100644 index 0000000000..631deb24de --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_5/demoCA/cacert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDBDCCAm2gAwIBAgIJAPA9tqmpnKNOMA0GCSqGSIb3DQEBBQUAMF8xCzAJBgNV +BAYTAkRFMRAwDgYDVQQIEwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9y +ZzEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgNTAeFw0wOTEx +MjAxMDEwMzdaFw0zNDExMTQxMDEwMzdaMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgNTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw +gYkCgYEAwbqFK0+BWGylCl9gJj/eVuuNBcSgVetgx0cXwMRPHiwFZ8ilxPJm4kd0 +k2WDKHox5Ol8T0pU4n3fA5VmxjcfGnx03R8rFTn5deetrKQzyWUjz7EIl4mZYSvK +hwlbg5ZB4FJDYUoC/3eVHdQq2jUvRaQad1TvdBmvIMbDaYmTT3cCAwEAAaOBxzCB +xDAdBgNVHQ4EFgQUwdGg1FsLnX4xYfk5EJ8xEODSBrUwgZEGA1UdIwSBiTCBhoAU +wdGg1FsLnX4xYfk5EJ8xEODSBrWhY6RhMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgNYIJAPA9tqmpnKNOMA8GA1UdEwEB/wQF +MAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAeX2QYyrs9an5ObWjzauPCzr8hx6k8dF3 +YXU8f/JCf/fKG5u5WQZmmu0YZXMSaDyzqS3rKupDSm4kbfB9l9oTkgZszueI29pd +C/QIh8vUTiAlV5zxR4ypqmBg489W/uXdQPicuFhGFYX9EWjuGhwk8dL0dcUCufwX +UBYBlUiceFU= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_5/demoCA/crl/DO_NOT_CREATE_A_CRL b/xmlsecurity/test_docs/CAs/Root_5/demoCA/crl/DO_NOT_CREATE_A_CRL new file mode 100644 index 0000000000..e69de29bb2 diff --git a/xmlsecurity/test_docs/CAs/Root_5/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Root_5/demoCA/crlnumber new file mode 100644 index 0000000000..83b33d238d --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_5/demoCA/crlnumber @@ -0,0 +1 @@ +1000 diff --git a/xmlsecurity/test_docs/CAs/Root_5/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Root_5/demoCA/index.txt new file mode 100644 index 0000000000..d910b9acc9 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_5/demoCA/index.txt @@ -0,0 +1 @@ +V 341114113023Z 1001 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 1 Root 5 diff --git a/xmlsecurity/test_docs/CAs/Root_5/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Root_5/demoCA/index.txt.attr new file mode 100644 index 0000000000..8f7e63a347 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_5/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Root_5/demoCA/newcerts/1001.pem b/xmlsecurity/test_docs/CAs/Root_5/demoCA/newcerts/1001.pem new file mode 100644 index 0000000000..b350f6eb33 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_5/demoCA/newcerts/1001.pem @@ -0,0 +1,66 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4097 (0x1001) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 5 + Validity + Not Before: Nov 20 11:30:23 2009 GMT + Not After : Nov 14 11:30:23 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 5 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:97:fa:a2:49:d3:bf:c1:2e:7a:ed:83:83:3c:78: + 96:c8:b2:b9:67:af:c0:5e:0a:89:89:fb:94:59:32: + a8:2a:e4:20:2f:3b:3d:ce:53:4f:72:fc:6c:0b:93: + 38:c3:df:66:6e:d5:79:d0:a4:4e:41:84:43:3c:99: + 79:0c:e0:5f:19:1a:3d:f5:4b:11:28:0f:80:b0:a0: + 71:34:5b:90:71:c2:ef:1e:85:2e:5b:9f:3b:22:c3: + 18:f8:7c:1f:ef:1b:78:17:a0:44:60:46:7e:88:eb: + a7:60:a0:5c:2a:7c:37:99:fa:27:97:08:e8:89:ba: + bc:69:4b:79:93:8f:ad:b5:9b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 01:E9:B5:99:E4:6D:F9:8C:42:3D:09:10:0F:A7:75:C6:27:78:4A:AF + X509v3 Authority Key Identifier: + keyid:C1:D1:A0:D4:5B:0B:9D:7E:31:61:F9:39:10:9F:31:10:E0:D2:06:B5 + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 5 + serial:F0:3D:B6:A9:A9:9C:A3:4E + + X509v3 CRL Distribution Points: + URI:http://localhost:8901/demoCA/crl/Root_5.crl + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 6d:ca:34:05:99:ff:99:49:d3:6d:9d:ad:c6:99:da:9d:6c:94: + 62:77:ed:1c:39:23:d2:e8:b6:3e:df:63:dc:7c:10:3f:c2:ed: + f4:04:26:58:05:01:4c:ed:a9:83:43:3a:5d:fe:60:6d:5b:58: + dc:93:8c:94:69:b6:7f:02:48:30:9c:31:f4:7d:de:e0:de:04: + d2:dc:79:b7:60:c2:87:f7:c7:92:a2:f5:86:a7:0c:70:3b:a3: + a7:35:11:cf:a4:28:21:aa:8b:24:50:2e:96:41:be:66:01:bd: + b9:ec:04:0c:92:d9:8a:e7:a0:96:24:9b:f1:a2:9f:59:59:4a: + 32:a4 +-----BEGIN CERTIFICATE----- +MIIDRjCCAq+gAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA1MB4XDTA5MTEyMDExMzAy +M1oXDTM0MTExNDExMzAyM1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA1MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQCX+qJJ07/BLnrtg4M8eJbIsrlnr8BeComJ+5RZMqgq5CAvOz3OU09y +/GwLkzjD32Zu1XnQpE5BhEM8mXkM4F8ZGj31SxEoD4CwoHE0W5Bxwu8ehS5bnzsi +wxj4fB/vG3gXoERgRn6I66dgoFwqfDeZ+ieXCOiJurxpS3mTj621mwIDAQABo4IB +BjCCAQIwHQYDVR0OBBYEFAHptZnkbfmMQj0JEA+ndcYneEqvMIGRBgNVHSMEgYkw +gYaAFMHRoNRbC51+MWH5ORCfMRDg0ga1oWOkYTBfMQswCQYDVQQGEwJERTEQMA4G +A1UECBMHSGFtYnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsT +C0RldmVsb3BtZW50MQ8wDQYDVQQDEwZSb290IDWCCQDwPbapqZyjTjA8BgNVHR8E +NTAzMDGgL6AthitodHRwOi8vbG9jYWxob3N0Ojg5MDEvZGVtb0NBL2NybC9Sb290 +XzUuY3JsMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAbco0BZn/ +mUnTbZ2txpnanWyUYnftHDkj0ui2Pt9j3HwQP8Lt9AQmWAUBTO2pg0M6Xf5gbVtY +3JOMlGm2fwJIMJwx9H3e4N4E0tx5t2DCh/fHkqL1hqcMcDujpzURz6QoIaqLJFAu +lkG+ZgG9uewEDJLZiuegliSb8aKfWVlKMqQ= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_5/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Root_5/demoCA/private/cakey.pem new file mode 100644 index 0000000000..222320a9a0 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_5/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,5F2D7F26BBEBD8FB + +qFyJ/G/DFwA+Kx3cVldc6bOMRbbduL7x5DBjCqS20YfoQoyvDcyel8FYz4/8CQ9d +kmb4nrM0Dj8/FgDiite2E8+qJV4U8OIBsXelFd8FWC8hB4z0DtwVxIAiM6mTMMcu +bWta3Lu5xrNvU/vosB967COztoYB5XLLQ/DrRPoV+tvJx0Le3zXLzceIj4PicuIk +/Mh5NVqN5a5blaV1/1JvcfOQLCI0rNebP3iAYhwCkKyu6WkpSNuHIw5gaMC6KXpq +ORPf3m+3/YKHLS9/tg+9CPQrRpyzLV/TOUduq6HFfzh9ZRXd04Dpn0P61JVCypYo +9u62lnNCAtreyvCUttzANLgujbgT9HNsjzKTAD2g+zjwQPgIS4epNm5LBPsQv15A +Vuw7CnNlLa8PxUxuDUjoW2YaGUR3PHNUz+TA1U0UFxlNK/lgeekIvmSvPjVyROOB +SxOH88yAZWe6pWioS3uzeg1kf1F5sj9u+KHPyikUe3nUBrS1cZSRtQczhlWWocgm +GtfwQSSVSwRtd7CWe/nQHuSJyrIJCbWFaDhnVXRhr+tyDpLtoeApCvefvel0p/AY +LTaRcno3zUxZS3G8Cv71hBPR8y5di5dAxBSfLgMYxwBD3UFO6CPkmiJteIhHska9 +FJqR98hfvF+0hwFnaFUTszDMGK1xV20MeTMhLAwSlttbuwtWMTourFKtS6t1SomB +JOTkpiVfojTSAJX40ExQgNtvY+7ayNUBLX9NIuIcOjFbQa1LNmGy9cOPQD49x067 +fALGA+V1KO7sFeUrunkpHncYoux5OThq3iDJ2tPfBmyhTQhOSzN38w== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Root_5/demoCA/serial b/xmlsecurity/test_docs/CAs/Root_5/demoCA/serial new file mode 100644 index 0000000000..7d802a3e71 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_5/demoCA/serial @@ -0,0 +1 @@ +1002 diff --git a/xmlsecurity/test_docs/CAs/Root_5/openssl.cfg b/xmlsecurity/test_docs/CAs/Root_5/openssl.cfg new file mode 100644 index 0000000000..0ea6df2972 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_5/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Root_5.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Root_6/README.txt b/xmlsecurity/test_docs/CAs/Root_6/README.txt new file mode 100644 index 0000000000..e49615a51c --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_6/README.txt @@ -0,0 +1,5 @@ +To provide the CRL via HTTP run + +java -jar ../../tools/httpserv/dist/httpserv.jar -a 8901 + + diff --git a/xmlsecurity/test_docs/CAs/Root_6/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Root_6/demoCA/cacert.pem new file mode 100644 index 0000000000..5a7fc185b4 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_6/demoCA/cacert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDBDCCAm2gAwIBAgIJANhqTyT5yZQnMA0GCSqGSIb3DQEBBQUAMF8xCzAJBgNV +BAYTAkRFMRAwDgYDVQQIEwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9y +ZzEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgNjAeFw0wOTEx +MjAxMjI2MDFaFw0zNDExMTQxMjI2MDFaMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgNjCBnzANBgkqhkiG9w0BAQEFAAOBjQAw +gYkCgYEAslt6KM0bikDy8n0lNMeaNQiZk9Pcfsf6Vaasn9A8FABFn1chxV5zOMag +jo6CyZG1CNLhA841RtgiWVMc8BA+pDKzOQAzfgSk4VjXaY8nYgKEmGDKuNvls+kE +OKMkJibh/scNMDUOx8Bnc6S9LyYJAhZFrxm/lgmoIo7QMcdseIsCAwEAAaOBxzCB +xDAdBgNVHQ4EFgQUrCVem7W6TY69d7Kd2eKErnoxj/IwgZEGA1UdIwSBiTCBhoAU +rCVem7W6TY69d7Kd2eKErnoxj/KhY6RhMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgNoIJANhqTyT5yZQnMA8GA1UdEwEB/wQF +MAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAU6Sjyeo650mhSGK8JJBhDroVJgAryVF4 +wXEKWxK0yuO0TVZJxUWeHOESpegBW1eP5m9Pz0IHnxj6MsGBYq7SZU84awt4HJto +6O1ARZYfT9r+qTts33I/VVQVTJbvETF1vGsuAZfTTDhAJDqS2oueiPDSinzQxNMy +16L4Rajm8LE= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_6/demoCA/crl/DO_NOT_INSTALL_THIS_CRL b/xmlsecurity/test_docs/CAs/Root_6/demoCA/crl/DO_NOT_INSTALL_THIS_CRL new file mode 100644 index 0000000000..e69de29bb2 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 new file mode 100644 index 0000000000..df6dcb21ee Binary files /dev/null and b/xmlsecurity/test_docs/CAs/Root_6/demoCA/crl/Root_6.crl differ diff --git a/xmlsecurity/test_docs/CAs/Root_6/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Root_6/demoCA/crlnumber new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_6/demoCA/crlnumber @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Root_6/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Root_6/demoCA/index.txt new file mode 100644 index 0000000000..7f0df0d959 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_6/demoCA/index.txt @@ -0,0 +1 @@ +V 341114122807Z 1001 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 1 Root 6 diff --git a/xmlsecurity/test_docs/CAs/Root_6/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Root_6/demoCA/index.txt.attr new file mode 100644 index 0000000000..8f7e63a347 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_6/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Root_6/demoCA/newcerts/1001.pem b/xmlsecurity/test_docs/CAs/Root_6/demoCA/newcerts/1001.pem new file mode 100644 index 0000000000..0490b88cd7 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_6/demoCA/newcerts/1001.pem @@ -0,0 +1,66 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4097 (0x1001) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 6 + Validity + Not Before: Nov 20 12:28:07 2009 GMT + Not After : Nov 14 12:28:07 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 6 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:c4:d9:ab:27:06:66:41:0e:36:ff:d4:b1:d0:8c: + f7:b4:25:55:cd:fd:fa:a4:5a:e6:4f:d0:05:dc:a3: + e5:bd:8d:53:77:d1:ea:95:5a:52:81:c8:b6:36:a0: + 5f:3a:e1:85:1e:8a:48:91:7d:29:78:ff:ea:c5:e3: + ad:c4:27:d5:b7:8f:59:20:26:d4:45:87:6a:56:db: + ac:f5:f8:0a:88:82:9e:c2:00:06:fc:98:8a:fe:35: + c3:02:a1:67:08:06:42:e3:88:48:e0:8f:33:ff:f8: + a4:87:1a:3a:d9:54:0e:1c:09:3e:a0:f0:70:cd:b5: + b0:b2:7e:07:73:ad:20:64:69 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 89:8C:D7:71:EB:67:78:4E:D6:01:35:B2:AC:A1:B4:88:43:CE:70:A7 + X509v3 Authority Key Identifier: + keyid:AC:25:5E:9B:B5:BA:4D:8E:BD:77:B2:9D:D9:E2:84:AE:7A:31:8F:F2 + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 6 + serial:D8:6A:4F:24:F9:C9:94:27 + + X509v3 CRL Distribution Points: + URI:http://localhost:8901/demoCA/crl/Root_6.crl + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 55:5b:3b:6b:8a:d0:1b:d8:19:d9:96:85:4d:b4:a0:98:b1:bd: + 9f:0b:62:21:92:8b:4e:d3:d0:1b:91:3d:e3:f5:bd:ce:16:57: + fc:b7:84:15:51:fd:98:ab:32:59:28:0b:44:57:49:ec:ac:11: + 67:26:7a:a3:c5:b8:9d:2a:de:b6:7c:76:0a:e9:18:9f:98:87: + e8:80:c8:72:99:56:74:ab:73:1b:f4:e7:b9:b1:3a:f3:7b:0d: + 2f:5d:82:6c:d1:99:9f:23:be:23:fb:4c:0e:15:5e:f5:9f:90: + 88:d7:51:3a:6a:7a:f0:54:a5:c4:89:a5:0d:0a:4e:94:59:64: + 59:54 +-----BEGIN CERTIFICATE----- +MIIDRjCCAq+gAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA2MB4XDTA5MTEyMDEyMjgw +N1oXDTM0MTExNDEyMjgwN1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA2MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDE2asnBmZBDjb/1LHQjPe0JVXN/fqkWuZP0AXco+W9jVN30eqVWlKB +yLY2oF864YUeikiRfSl4/+rF463EJ9W3j1kgJtRFh2pW26z1+AqIgp7CAAb8mIr+ +NcMCoWcIBkLjiEjgjzP/+KSHGjrZVA4cCT6g8HDNtbCyfgdzrSBkaQIDAQABo4IB +BjCCAQIwHQYDVR0OBBYEFImM13HrZ3hO1gE1sqyhtIhDznCnMIGRBgNVHSMEgYkw +gYaAFKwlXpu1uk2OvXeyndnihK56MY/yoWOkYTBfMQswCQYDVQQGEwJERTEQMA4G +A1UECBMHSGFtYnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsT +C0RldmVsb3BtZW50MQ8wDQYDVQQDEwZSb290IDaCCQDYak8k+cmUJzA8BgNVHR8E +NTAzMDGgL6AthitodHRwOi8vbG9jYWxob3N0Ojg5MDEvZGVtb0NBL2NybC9Sb290 +XzYuY3JsMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAVVs7a4rQ +G9gZ2ZaFTbSgmLG9nwtiIZKLTtPQG5E94/W9zhZX/LeEFVH9mKsyWSgLRFdJ7KwR +ZyZ6o8W4nSretnx2CukYn5iH6IDIcplWdKtzG/TnubE683sNL12CbNGZnyO+I/tM +DhVe9Z+QiNdROmp68FSlxImlDQpOlFlkWVQ= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_6/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Root_6/demoCA/private/cakey.pem new file mode 100644 index 0000000000..166be01665 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_6/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,BADC417CBCEF5888 + +5vIfuyyd2rgqSPUElPa2YM8on+FeoYuAIB+mfVHy0nSGisUKjmQQACaeTVD+aO6S +UFBz3W/RJXCj/8x5+ZYa8Rj44DeSwlDrxSy5VBrWegOzujfGPqrzwCL/ASKGPPFN +RwK0i0niJsj6+oQOGgP6AIb08reX1tkT0GItwQMjIQAFETcDP8m1sA1kFpLhvBCF +dHyw0lfnh+NZ9nnpAdpVXwt8teccLUyEHARNscebg8vqjc2gRxi3KpT3pURg0dUc +eaGH8DIB5CuAYW2Mo1LLRQ0uvkFgSl56WcolYiRTy2KUMW7Gz7oBA5Qyb9lz25yV +9djt4Hrs9cI1p1TGmvSklGPKJUaTf0Yrf0XRkS6xknFVX4zzkbD4vYFelITSxeMT +pPVbjLSWiIo+mqBuW6i+LUNMt45b1RWM96pomrPRrGne4saJOkhVXTvv/pR4KB+S +J2iwlEDNOwzkxeqSB7lJuzIce/iUqERAzlXe8e0VVgy0P0UfOIViLWS98cuqR86H +P1rMYtWilAkLKBUYo+lS7f/3YD8E3V10XdBmYJFvmpHPXM2SP5HQZXtoNCXJNcvB +aAlb3c7InxfqLLn+kH6WgPzXXcXO7cxlZ3cXBbJf3IhRT3aBEnAH+s+DDCi0RCII +UiLOnrgfOEZuNyRhGin9R7WFRtnGYJjHTP54FMOY0f0Rj7ElT+xymeAZE8wyXKfi +MWDgswTYYkcC7uPJAJ8HnLtFixr9aEriug7yemGyr686oX8gLPdwrYwPYJBt7Q+b +0nf22SoMqMNWSCWcr89sc1AIb0ebX+FxtsN6j45ztEjZGjXYkk2iXQ== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Root_6/demoCA/serial b/xmlsecurity/test_docs/CAs/Root_6/demoCA/serial new file mode 100644 index 0000000000..7d802a3e71 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_6/demoCA/serial @@ -0,0 +1 @@ +1002 diff --git a/xmlsecurity/test_docs/CAs/Root_6/openssl.cfg b/xmlsecurity/test_docs/CAs/Root_6/openssl.cfg new file mode 100644 index 0000000000..f49c110901 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_6/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Root_6.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Root_7/README.txt b/xmlsecurity/test_docs/CAs/Root_7/README.txt new file mode 100644 index 0000000000..056f1b1339 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_7/README.txt @@ -0,0 +1,10 @@ +Revoked certificates: + +- Sub CA 2 Root 7 + + +To provide the CRL via HTTP run + +java -jar ../../tools/httpserv/dist/httpserv.jar -a 8901 + + diff --git a/xmlsecurity/test_docs/CAs/Root_7/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Root_7/demoCA/cacert.pem new file mode 100644 index 0000000000..01761f55bf --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_7/demoCA/cacert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDBDCCAm2gAwIBAgIJANXmY18YCYKJMA0GCSqGSIb3DQEBBQUAMF8xCzAJBgNV +BAYTAkRFMRAwDgYDVQQIEwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9y +ZzEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgNzAeFw0wOTEx +MjAxMzA0NDhaFw0zNDExMTQxMzA0NDhaMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgNzCBnzANBgkqhkiG9w0BAQEFAAOBjQAw +gYkCgYEAvG//bRySIKOz1hmmH6qx02wtf2ZO2skK/wxPnTAd+LLuH2upOfGkaFCi +hd1zsIshs9/TjtLNa4nplkYSvZlYBsbpIuNQZrEedbvLYV/zNdsnLfht+aX3yMuk +q1dh2BI0LdwXiyMyPwATJwQ96AXq/a+cZi1ZRBToCztZArJK/xMCAwEAAaOBxzCB +xDAdBgNVHQ4EFgQUgMb4C198SeSG/ciSxoBw2cBve94wgZEGA1UdIwSBiTCBhoAU +gMb4C198SeSG/ciSxoBw2cBve96hY6RhMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgN4IJANXmY18YCYKJMA8GA1UdEwEB/wQF +MAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAg15QATKSYmz+XGtnBLDnWu2Gk59nglH4 +gG3p1xiVVgOyQVGsvNr+3ETPTTcf6x+ap1+AHE9SJJ0/WQSuUHtOv6y/prp4MWbw +/QBL2WHS7adTFWxOJ/VWpb8GhTtJdG9PKYeSmVAtC1qzdI1zsjPYvHO3UJnokDkB +fY7kpaTJprg= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_7/demoCA/crl/DO_NOT_INSTALL_THIS_CRL b/xmlsecurity/test_docs/CAs/Root_7/demoCA/crl/DO_NOT_INSTALL_THIS_CRL new file mode 100644 index 0000000000..e69de29bb2 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 new file mode 100644 index 0000000000..0eefbda680 Binary files /dev/null and b/xmlsecurity/test_docs/CAs/Root_7/demoCA/crl/Root_7.crl differ diff --git a/xmlsecurity/test_docs/CAs/Root_7/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Root_7/demoCA/crlnumber new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_7/demoCA/crlnumber @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Root_7/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Root_7/demoCA/index.txt new file mode 100644 index 0000000000..24c3538724 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_7/demoCA/index.txt @@ -0,0 +1,2 @@ +V 341114130753Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 1 Root 7 +R 341114133506Z 091120133621Z,keyCompromise 1001 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 2 Root 7 diff --git a/xmlsecurity/test_docs/CAs/Root_7/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Root_7/demoCA/index.txt.attr new file mode 100644 index 0000000000..8f7e63a347 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_7/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Root_7/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Root_7/demoCA/newcerts/1000.pem new file mode 100644 index 0000000000..2dda8f2b28 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_7/demoCA/newcerts/1000.pem @@ -0,0 +1,66 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 7 + Validity + Not Before: Nov 20 13:07:53 2009 GMT + Not After : Nov 14 13:07:53 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 7 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:b0:ae:6d:0a:21:ae:8a:92:b1:16:25:d3:08:cb: + ac:b7:4c:53:6d:4b:b3:12:82:40:54:c9:44:28:fc: + 4e:10:e6:65:40:de:70:5d:8b:ab:1f:5c:77:03:43: + 3d:3a:3d:9e:f7:37:66:9a:33:68:a0:cf:ad:8f:f4: + fb:9c:a3:87:57:5d:ec:d6:55:5a:18:b5:e1:2b:d2: + c4:10:fe:f0:01:a5:da:29:ee:c4:af:15:c9:8c:dc: + 7c:45:84:bd:e5:5b:09:1f:16:1d:11:e7:61:e6:22: + e7:1f:c8:86:bf:a1:da:cb:fe:6b:7e:c0:6e:aa:7f: + 97:84:e8:8f:81:69:f1:26:87 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 54:64:15:7E:93:8A:19:C8:F9:B7:EF:60:A0:DF:5C:C8:15:56:C0:EE + X509v3 Authority Key Identifier: + keyid:80:C6:F8:0B:5F:7C:49:E4:86:FD:C8:92:C6:80:70:D9:C0:6F:7B:DE + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 7 + serial:D5:E6:63:5F:18:09:82:89 + + X509v3 CRL Distribution Points: + URI:http://localhost:8901/demoCA/crl/Root_7.crl + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 1a:bc:5a:4b:9a:d5:e8:c0:35:c2:61:0a:58:7d:33:e2:87:01: + 61:83:80:42:8d:1a:7e:b1:9a:58:d5:01:fd:e7:ae:5c:c8:65: + fb:9e:1d:bf:49:ba:ed:40:f4:05:7c:3b:2d:db:0e:53:d0:05: + a0:bd:15:87:c4:37:22:0b:a0:04:a3:ad:cb:57:b2:00:97:ee: + 8f:89:91:8e:7d:0b:e2:27:96:6e:0f:ab:73:33:59:fa:9f:37: + f2:77:79:99:af:72:ad:f9:49:05:ed:55:08:31:eb:97:0f:99: + 6e:9c:a3:df:f0:52:1a:14:4e:78:25:0c:8b:02:cb:56:e9:4d: + f5:9f +-----BEGIN CERTIFICATE----- +MIIDRjCCAq+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA3MB4XDTA5MTEyMDEzMDc1 +M1oXDTM0MTExNDEzMDc1M1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA3MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQCwrm0KIa6KkrEWJdMIy6y3TFNtS7MSgkBUyUQo/E4Q5mVA3nBdi6sf +XHcDQz06PZ73N2aaM2igz62P9Puco4dXXezWVVoYteEr0sQQ/vABpdop7sSvFcmM +3HxFhL3lWwkfFh0R52HmIucfyIa/odrL/mt+wG6qf5eE6I+BafEmhwIDAQABo4IB +BjCCAQIwHQYDVR0OBBYEFFRkFX6TihnI+bfvYKDfXMgVVsDuMIGRBgNVHSMEgYkw +gYaAFIDG+AtffEnkhv3IksaAcNnAb3veoWOkYTBfMQswCQYDVQQGEwJERTEQMA4G +A1UECBMHSGFtYnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsT +C0RldmVsb3BtZW50MQ8wDQYDVQQDEwZSb290IDeCCQDV5mNfGAmCiTA8BgNVHR8E +NTAzMDGgL6AthitodHRwOi8vbG9jYWxob3N0Ojg5MDEvZGVtb0NBL2NybC9Sb290 +XzcuY3JsMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAGrxaS5rV +6MA1wmEKWH0z4ocBYYOAQo0afrGaWNUB/eeuXMhl+54dv0m67UD0BXw7LdsOU9AF +oL0Vh8Q3IgugBKOty1eyAJfuj4mRjn0L4ieWbg+rczNZ+p838nd5ma9yrflJBe1V +CDHrlw+Zbpyj3/BSGhROeCUMiwLLVulN9Z8= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_7/demoCA/newcerts/1001.pem b/xmlsecurity/test_docs/CAs/Root_7/demoCA/newcerts/1001.pem new file mode 100644 index 0000000000..0d2a0f02a3 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_7/demoCA/newcerts/1001.pem @@ -0,0 +1,66 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4097 (0x1001) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 7 + Validity + Not Before: Nov 20 13:35:06 2009 GMT + Not After : Nov 14 13:35:06 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 2 Root 7 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:f9:3f:5e:76:52:9a:ce:5d:98:b0:00:d8:e0:65: + e7:78:11:4c:7b:c7:e2:d3:44:bf:8e:60:42:69:3e: + 75:67:65:24:ab:f7:07:d8:9d:be:0f:23:b5:c1:26: + 00:6b:c3:22:84:72:a9:96:dc:5f:63:fc:f5:e0:e3: + cc:da:0c:74:e9:31:51:91:89:27:8f:e5:17:41:6e: + 3d:5e:2a:13:cd:08:f7:f3:61:34:a1:f7:79:c6:bd: + 5d:2c:34:01:ea:5a:8c:48:97:36:d6:57:e0:80:03: + 2e:7a:03:83:4c:bd:b4:af:a2:fd:d7:4b:1a:f7:ab: + 9f:5a:22:2b:d1:25:73:dd:6f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 3B:50:26:45:6C:E2:FE:28:B1:71:0A:A8:95:2D:78:63:8E:2C:48:92 + X509v3 Authority Key Identifier: + keyid:80:C6:F8:0B:5F:7C:49:E4:86:FD:C8:92:C6:80:70:D9:C0:6F:7B:DE + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 7 + serial:D5:E6:63:5F:18:09:82:89 + + X509v3 CRL Distribution Points: + URI:http://localhost:8901/demoCA/crl/Root_7.crl + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 5f:b4:70:11:4f:d9:df:6a:6a:5a:4a:97:fe:8b:5d:9e:46:84: + e2:27:67:41:7c:a9:2e:9d:77:cc:e4:8c:d6:16:3c:39:7d:51: + 29:60:80:32:4f:a1:d0:b4:7f:2a:e5:60:f4:b8:d3:3b:94:f8: + a5:fb:15:99:cf:a9:c5:a7:59:c1:11:89:67:11:9c:ff:a9:ac: + dd:ca:a9:92:a8:60:26:c3:ab:74:41:86:b9:4d:1e:4a:c5:de: + 63:e6:da:2a:36:39:7b:6c:66:f3:20:57:d1:f1:36:4b:69:c5: + 04:a3:1f:cf:de:0c:10:d0:3f:07:e2:8e:0f:cd:41:26:c9:2e: + e9:1b +-----BEGIN CERTIFICATE----- +MIIDRjCCAq+gAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA3MB4XDTA5MTEyMDEzMzUw +NloXDTM0MTExNDEzMzUwNlowaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDIgUm9vdCA3MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQD5P152UprOXZiwANjgZed4EUx7x+LTRL+OYEJpPnVnZSSr9wfYnb4P +I7XBJgBrwyKEcqmW3F9j/PXg48zaDHTpMVGRiSeP5RdBbj1eKhPNCPfzYTSh93nG +vV0sNAHqWoxIlzbWV+CAAy56A4NMvbSvov3XSxr3q59aIivRJXPdbwIDAQABo4IB +BjCCAQIwHQYDVR0OBBYEFDtQJkVs4v4osXEKqJUteGOOLEiSMIGRBgNVHSMEgYkw +gYaAFIDG+AtffEnkhv3IksaAcNnAb3veoWOkYTBfMQswCQYDVQQGEwJERTEQMA4G +A1UECBMHSGFtYnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsT +C0RldmVsb3BtZW50MQ8wDQYDVQQDEwZSb290IDeCCQDV5mNfGAmCiTA8BgNVHR8E +NTAzMDGgL6AthitodHRwOi8vbG9jYWxob3N0Ojg5MDEvZGVtb0NBL2NybC9Sb290 +XzcuY3JsMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAX7RwEU/Z +32pqWkqX/otdnkaE4idnQXypLp13zOSM1hY8OX1RKWCAMk+h0LR/KuVg9LjTO5T4 +pfsVmc+pxadZwRGJZxGc/6ms3cqpkqhgJsOrdEGGuU0eSsXeY+baKjY5e2xm8yBX +0fE2S2nFBKMfz94MENA/B+KOD81BJsku6Rs= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_7/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Root_7/demoCA/private/cakey.pem new file mode 100644 index 0000000000..147ca4e9b6 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_7/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,B17A06040862AC63 + +9VJMswLGoelYtmpO17/f34Lb7j1I2vaK+RUg7fH09M6rQKurA2SmpsO7kJo7lMUb +lwXEC8+JC5b3OoUcPeHLkZ5e9bB+flMJQq+bkzWs4NWYI17gRs2Tc74xm04XRTsO +OYU+H7uOyRMAuS86hkQF13H3hCHcZkg8RZcvqfDXhsY8S7iyp0gErQv8IDmbIije +R7go3NdZXCmkuINKhhABFYnPxnEpaHxhIMNKykbSn+jby02LX57X/u4JDGfkzjCH +wyJMi9PiO7VbXvi8IPYnFz0IaCMVr5cltTh47/KiqACeAADQ6ETekrX9r7lngkRz +sqFuyqEtdi02ujElsGIaDCImQ5KbD2u2IQ3FX2b6Jwmd/uDmqQQwtEfarEoUxich +chCEUBGAiqRxLcrnRzjT+Reqgx7qGNurjP78kmKeD91hDm3tEHeWtecy4iA3C8z0 +aMZFOZLx1r7kf5/YaRMREcLPmreEWgFmkIMN004GdIvOwlsUjmAM7UMle+cef17v +h1hxbFsznzYLBk0zOYjmsTpI3dQHtxSUVsyUWXXVJ0Y4YhJSjMHlMOOCanGYOpGS +vipUNzLx4aIWfMmQdJePQM4uxO2FNwTc1IGyRpoOhj6vxroICuGK3WkxqZsN3VwR +hwNol0cNMNHbVacKvhh5PQJcmWiqmLEXaQD8VWgCNQVa0otS59vj+SeyW4ZvULBM +Od/9FhFfEBHQDxNSL+c6B/dXFIO1oY159ErdElAn+NPRtQcHAsnu8HknKLhry1NP +b4d+KZcTZAq9q97ltRQf9/hXBpA3ophMtbBFnnnh5WJuMMdDMNgGsg== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Root_7/demoCA/serial b/xmlsecurity/test_docs/CAs/Root_7/demoCA/serial new file mode 100644 index 0000000000..7d802a3e71 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_7/demoCA/serial @@ -0,0 +1 @@ +1002 diff --git a/xmlsecurity/test_docs/CAs/Root_7/openssl.cfg b/xmlsecurity/test_docs/CAs/Root_7/openssl.cfg new file mode 100644 index 0000000000..f2615bef4f --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_7/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Root_7.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Root_8/README.txt b/xmlsecurity/test_docs/CAs/Root_8/README.txt new file mode 100644 index 0000000000..d749d8ebcf --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_8/README.txt @@ -0,0 +1,9 @@ +Revoked certificates: + +- Sub CA 2 Root 8 + + +Start the OCSP responder: +openssl ocsp -index demoCA/index.txt -port 8888 -rsigner demoCA/cacert.pem -rkey demoCA/private/cakey.pem -CA demoCA/cacert.pem -text + + diff --git a/xmlsecurity/test_docs/CAs/Root_8/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Root_8/demoCA/cacert.pem new file mode 100644 index 0000000000..ef431ec952 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_8/demoCA/cacert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDBDCCAm2gAwIBAgIJALJH3moqTIMZMA0GCSqGSIb3DQEBBQUAMF8xCzAJBgNV +BAYTAkRFMRAwDgYDVQQIEwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9y +ZzEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgODAeFw0wOTEx +MjAxNTI4NTZaFw0zNDExMTQxNTI4NTZaMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgODCBnzANBgkqhkiG9w0BAQEFAAOBjQAw +gYkCgYEAmR4R07C/I8zEPsAEQdc/nzH74hLjEwImtiWKL8nVc70fwquIRzWLaavm +DaQE3g/ha00d2hepB2dUiR1nV2GhMYdV64eq1utEPU+tTIYpx163axOGLYLWwKc3 +cBaR2mCqZmAkS+WABHkCX9hsBn+Ju/XNxLDVcpBohVrx882+3kMCAwEAAaOBxzCB +xDAdBgNVHQ4EFgQU1mZ2yQX/qVCIlmDd+8cwGHJnQRkwgZEGA1UdIwSBiTCBhoAU +1mZ2yQX/qVCIlmDd+8cwGHJnQRmhY6RhMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgOIIJALJH3moqTIMZMA8GA1UdEwEB/wQF +MAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAfZylT15q6Dnpvf9jWoCovzvUoBqAwL1Z +UDEikhCpajYsrfXI3MRvKYkTvt18lgg2Y09gJ2vhfLBCaDp+ELUq0Vc5hIbblGGO +EA4vBuH5Yfho3AK3gKAtk7Rc9l/qP2rBPb1JVw79pRaz95IkYGeOp35pVDQfBN+i +jji5JSyOeYQ= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_8/demoCA/crl/DO_NOT_INSTALL_THIS_CRL b/xmlsecurity/test_docs/CAs/Root_8/demoCA/crl/DO_NOT_INSTALL_THIS_CRL new file mode 100644 index 0000000000..e69de29bb2 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 new file mode 100644 index 0000000000..8f91a1949a Binary files /dev/null and b/xmlsecurity/test_docs/CAs/Root_8/demoCA/crl/Root_8.crl differ diff --git a/xmlsecurity/test_docs/CAs/Root_8/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Root_8/demoCA/crlnumber new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_8/demoCA/crlnumber @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Root_8/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Root_8/demoCA/index.txt new file mode 100644 index 0000000000..831cbf1a38 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_8/demoCA/index.txt @@ -0,0 +1,2 @@ +V 341114153321Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 1 Root 8 +R 341114155533Z 091120155655Z,superseded 1001 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 2 Root 8 diff --git a/xmlsecurity/test_docs/CAs/Root_8/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Root_8/demoCA/index.txt.attr new file mode 100644 index 0000000000..8f7e63a347 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_8/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Root_8/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Root_8/demoCA/newcerts/1000.pem new file mode 100644 index 0000000000..b2d1deb759 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_8/demoCA/newcerts/1000.pem @@ -0,0 +1,66 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 8 + Validity + Not Before: Nov 20 15:33:21 2009 GMT + Not After : Nov 14 15:33:21 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 8 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:96:79:01:9f:4f:68:c1:09:0d:44:3a:82:e4:eb: + ad:70:7a:cf:b9:71:e5:fb:e0:c8:0c:21:79:3e:cb: + 78:91:7f:4a:a0:de:3e:37:0f:a1:6b:73:10:12:9b: + 08:c4:96:dc:cb:a8:5b:87:9b:75:24:e4:00:5e:4a: + 6f:4c:13:79:1f:57:13:8c:3e:1b:38:31:e1:77:74: + 52:f9:94:47:36:57:33:bd:de:08:11:a3:01:e1:53: + 1c:bd:7b:39:9c:5e:96:5c:a9:61:6c:cc:2b:90:8d: + 5a:3c:9e:f4:4b:6e:e5:97:64:86:f3:8e:e8:72:20: + 5d:0d:50:bf:e9:cf:be:d4:13 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + EF:BD:C8:8E:78:79:F9:76:4B:11:59:B6:C3:32:10:07:C0:BC:E3:8A + X509v3 Authority Key Identifier: + keyid:D6:66:76:C9:05:FF:A9:50:88:96:60:DD:FB:C7:30:18:72:67:41:19 + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 8 + serial:B2:47:DE:6A:2A:4C:83:19 + + Authority Information Access: + OCSP - URI:http://localhost:8888 + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 4c:95:44:3b:57:08:ec:01:ec:f9:3e:7c:89:1c:30:b1:4e:26: + 32:b6:57:fa:25:bc:ed:eb:d4:a2:1c:67:ee:b9:8b:d0:4c:57: + 8a:0e:db:a0:9d:92:e7:de:c6:73:01:e7:de:61:1b:b5:0e:d0: + c5:c1:a7:a6:ab:e0:c6:0b:51:dd:e5:a2:32:1f:c6:52:ea:d3: + 03:68:3a:f5:92:bd:8b:b8:03:bb:50:70:63:cc:ec:ed:3c:11: + 76:ca:ac:72:47:ad:99:6b:8e:07:9e:38:f2:63:e1:ba:d4:df: + a9:73:54:1d:74:89:94:01:2e:68:dd:97:e7:53:f9:cf:b6:7d: + fc:87 +-----BEGIN CERTIFICATE----- +MIIDOTCCAqKgAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA4MB4XDTA5MTEyMDE1MzMy +MVoXDTM0MTExNDE1MzMyMVowaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA4MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQCWeQGfT2jBCQ1EOoLk661wes+5ceX74MgMIXk+y3iRf0qg3j43D6Fr +cxASmwjEltzLqFuHm3Uk5ABeSm9ME3kfVxOMPhs4MeF3dFL5lEc2VzO93ggRowHh +Uxy9ezmcXpZcqWFszCuQjVo8nvRLbuWXZIbzjuhyIF0NUL/pz77UEwIDAQABo4H6 +MIH3MB0GA1UdDgQWBBTvvciOeHn5dksRWbbDMhAHwLzjijCBkQYDVR0jBIGJMIGG +gBTWZnbJBf+pUIiWYN37xzAYcmdBGaFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA4ggkAskfeaipMgxkwMQYIKwYBBQUH +AQEEJTAjMCEGCCsGAQUFBzABhhVodHRwOi8vbG9jYWxob3N0Ojg4ODgwDwYDVR0T +AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBMlUQ7VwjsAez5PnyJHDCxTiYy +tlf6Jbzt69SiHGfuuYvQTFeKDtugnZLn3sZzAefeYRu1DtDFwaemq+DGC1Hd5aIy +H8ZS6tMDaDr1kr2LuAO7UHBjzOztPBF2yqxyR62Za44HnjjyY+G61N+pc1QddImU +AS5o3ZfnU/nPtn38hw== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_8/demoCA/newcerts/1001.pem b/xmlsecurity/test_docs/CAs/Root_8/demoCA/newcerts/1001.pem new file mode 100644 index 0000000000..26368962e8 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_8/demoCA/newcerts/1001.pem @@ -0,0 +1,66 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4097 (0x1001) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 8 + Validity + Not Before: Nov 20 15:55:33 2009 GMT + Not After : Nov 14 15:55:33 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 2 Root 8 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:e9:91:38:d8:c1:36:e5:c1:d0:32:e8:ae:02:11: + 97:e5:c5:07:8f:5b:46:3a:3c:d9:49:5e:9a:4b:51: + 4c:b7:7d:e9:d1:4f:a7:15:8c:c6:10:f6:fa:5f:a9: + 0b:1b:bc:de:56:f5:ad:a3:a0:40:f1:75:10:58:74: + 37:f9:b7:9f:76:ca:46:96:4c:1a:81:f4:a2:ce:88: + 8b:9e:00:6d:42:b3:d6:68:d1:67:d6:9f:b8:9c:3f: + 43:c7:36:bf:41:88:1b:e8:74:26:a0:51:5c:e2:ee: + 6d:9d:73:bb:0d:36:e1:5c:68:9f:21:3b:b2:aa:ed: + 39:1d:ae:fc:b4:ca:38:c2:fb + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 1B:AB:6B:0F:42:91:DC:1E:D4:7A:95:87:30:2D:CC:11:4F:35:B7:73 + X509v3 Authority Key Identifier: + keyid:D6:66:76:C9:05:FF:A9:50:88:96:60:DD:FB:C7:30:18:72:67:41:19 + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 8 + serial:B2:47:DE:6A:2A:4C:83:19 + + Authority Information Access: + OCSP - URI:http://localhost:8888 + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 89:f8:8d:a8:e5:0b:2a:fb:f3:6a:80:2c:26:a1:a7:36:7e:a0: + c5:61:65:9d:7e:d6:47:60:b4:f6:72:e9:6e:2c:d9:f8:7f:c8: + 7a:5d:75:98:ad:88:de:e7:1b:44:a3:96:37:84:c0:b3:20:98: + 3b:b5:f6:ee:70:9c:04:7a:6c:88:05:75:7f:12:cf:b9:76:e8: + c0:17:0c:5e:eb:10:38:1e:54:41:58:56:f6:3c:ec:07:a5:c0: + 74:24:34:af:b3:c7:b2:58:85:47:0f:6c:e4:a0:9f:c8:7b:5c: + 95:77:17:e5:ad:eb:c3:86:44:f7:81:ef:cb:58:12:1a:6a:c7: + 19:95 +-----BEGIN CERTIFICATE----- +MIIDOTCCAqKgAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA4MB4XDTA5MTEyMDE1NTUz +M1oXDTM0MTExNDE1NTUzM1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDIgUm9vdCA4MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDpkTjYwTblwdAy6K4CEZflxQePW0Y6PNlJXppLUUy3fenRT6cVjMYQ +9vpfqQsbvN5W9a2joEDxdRBYdDf5t592ykaWTBqB9KLOiIueAG1Cs9Zo0WfWn7ic +P0PHNr9BiBvodCagUVzi7m2dc7sNNuFcaJ8hO7Kq7Tkdrvy0yjjC+wIDAQABo4H6 +MIH3MB0GA1UdDgQWBBQbq2sPQpHcHtR6lYcwLcwRTzW3czCBkQYDVR0jBIGJMIGG +gBTWZnbJBf+pUIiWYN37xzAYcmdBGaFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA4ggkAskfeaipMgxkwMQYIKwYBBQUH +AQEEJTAjMCEGCCsGAQUFBzABhhVodHRwOi8vbG9jYWxob3N0Ojg4ODgwDwYDVR0T +AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQCJ+I2o5Qsq+/NqgCwmoac2fqDF +YWWdftZHYLT2culuLNn4f8h6XXWYrYje5xtEo5Y3hMCzIJg7tfbucJwEemyIBXV/ +Es+5dujAFwxe6xA4HlRBWFb2POwHpcB0JDSvs8eyWIVHD2zkoJ/Ie1yVdxflrevD +hkT3ge/LWBIaascZlQ== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_8/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Root_8/demoCA/private/cakey.pem new file mode 100644 index 0000000000..dd11db4437 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_8/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,1DE6DE80057C280E + +1pXaFFR4KgVEWQzq73tQrfEkLZn7J0G0fxp1ZZYKOVdL3g/S4su2cXn5zfkSypjG +sTPnj9YuHzZiW1sB5M+U84b0aCSuh4+HK1Y+K6Us99psx/VaDq36uEBJZQviJ4zb +uF7ZT6NRGWMs3pIkFEHqi9TQ6mmeRgHMgkiI/mpM/26Y00dLpXdxBIGOCpKIPXwp +02mx/o9CHqI7ASuXV6ZAhawEmvFKKRNCKsKOaSs0CylGOT5nAaqWRp/IVMrm46wr +o7cErGgCZCPzQ5Ndx4553oSeWTjnm4iTS5UKg0nwPgS6sVhsr3zrTxIhS9zzcW2G +ycREX312K7q0zxtCxdNZxGeSfowRRy54JRoLf+O5yoNTRXYFjLxXGHgCTQRWgpIh +ggOmgUyIeNQXts4Qf6ddUtEcfGzMowCAJWTakXpOBoWj42mF85lDlcAAn8V1L90Q +MDF31HzrDAe3po4g+dNA6qdZrpSpnDDVp0oPsr3ooz1dLlwa8LWpPpq5PRgDWeQF +hcYrywI5tfUJyXv0xkEv+BIGKjGofWHGNtZWazBunhAVgWG/GQbzWxdSBS5w2waE +2Zo65PBqfLgRdnO6HYl15Pc5wm3gEQJo5VYgl7HmRpEt7lQrcnReqLWnsuHmqZ/H +vaEmGnSfXauVTvBVRXnrpznM/ROC9n2FR50lNIO1nAtMM7a0S0PIKgB+uNwAtsAR +Y4dY4YCS/io8wCL+DNBPtdvuY85/y5lnURpj9ojWO916WZsK/EFPJIQFuVwhal2C +Q9NVu8PXPDiBAHTVGZz8HoG32eYYUtqzeIY4Xo5ybUlnsNGlncWSqw== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Root_8/demoCA/serial b/xmlsecurity/test_docs/CAs/Root_8/demoCA/serial new file mode 100644 index 0000000000..7d802a3e71 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_8/demoCA/serial @@ -0,0 +1 @@ +1002 diff --git a/xmlsecurity/test_docs/CAs/Root_8/openssl.cfg b/xmlsecurity/test_docs/CAs/Root_8/openssl.cfg new file mode 100644 index 0000000000..077e13b2b5 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_8/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Root_7.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Root_9/DO_NOT_INSTALL_THIS_ROOT_CERT.txt b/xmlsecurity/test_docs/CAs/Root_9/DO_NOT_INSTALL_THIS_ROOT_CERT.txt new file mode 100644 index 0000000000..ee3d2b339e --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_9/DO_NOT_INSTALL_THIS_ROOT_CERT.txt @@ -0,0 +1 @@ +!!!DO NOT INSTALL THIS ROOT CERTIFICATE!!! diff --git a/xmlsecurity/test_docs/CAs/Root_9/demoCA/DO_NO_INSTALL_THIS_ROOT_CERTIFICATE b/xmlsecurity/test_docs/CAs/Root_9/demoCA/DO_NO_INSTALL_THIS_ROOT_CERTIFICATE new file mode 100644 index 0000000000..e69de29bb2 diff --git a/xmlsecurity/test_docs/CAs/Root_9/demoCA/Root_9.crt b/xmlsecurity/test_docs/CAs/Root_9/demoCA/Root_9.crt new file mode 100644 index 0000000000..66e316546e Binary files /dev/null and b/xmlsecurity/test_docs/CAs/Root_9/demoCA/Root_9.crt differ diff --git a/xmlsecurity/test_docs/CAs/Root_9/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Root_9/demoCA/cacert.pem new file mode 100644 index 0000000000..ca53f28f7a --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_9/demoCA/cacert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDBDCCAm2gAwIBAgIJAKTbFg1LjNSmMA0GCSqGSIb3DQEBBQUAMF8xCzAJBgNV +BAYTAkRFMRAwDgYDVQQIEwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9y +ZzEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgOTAeFw0wOTEx +MjMxMzUyNDNaFw0zNDExMTcxMzUyNDNaMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgOTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw +gYkCgYEAsOgehurKuYszsH2LFeGyHA9WYmCOMZmQfBFOgS/kO1Hkv6tNrDbshzyc +I/qOlpkosXUbQaaJPYoQmv3eTpfYxM9Dju5GkzOL03Q9J8AGe8RW1urMCfD5fC9g +XmhxAnIbrmDhS4K0lV8ngWwTQjmec9CV8SVBLQerrNtmcY/VvcMCAwEAAaOBxzCB +xDAdBgNVHQ4EFgQUzTNeq3MjUYC4A60SAQvFXo5VymQwgZEGA1UdIwSBiTCBhoAU +zTNeq3MjUYC4A60SAQvFXo5VymShY6RhMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgOYIJAKTbFg1LjNSmMA8GA1UdEwEB/wQF +MAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAqQkfiXNJm8l5v6qQzv6HwcDIgSQBuwkp +bN5FgHdLXaae/UOelXpmLSfrAbizw0Om1xLH/tnSeNY9MCGMGA4ScGU1hdNLUTIU +LK9upl/q+cHQayZL/Hz4Z8sqRNrP+E2m0GY0RMF1getJunfYZZV9VcsfbO3SqgAQ +exqICFDFi8M= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_9/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Root_9/demoCA/crlnumber new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_9/demoCA/crlnumber @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Root_9/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Root_9/demoCA/index.txt new file mode 100644 index 0000000000..c741bbfdac --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_9/demoCA/index.txt @@ -0,0 +1 @@ +V 341117135919Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 1 Root 9 diff --git a/xmlsecurity/test_docs/CAs/Root_9/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Root_9/demoCA/index.txt.attr new file mode 100644 index 0000000000..8f7e63a347 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_9/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Root_9/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Root_9/demoCA/newcerts/1000.pem new file mode 100644 index 0000000000..0b38d4db4c --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_9/demoCA/newcerts/1000.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 9 + Validity + Not Before: Nov 23 13:59:19 2009 GMT + Not After : Nov 17 13:59:19 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 9 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:a9:6d:7f:6a:08:fb:e2:3a:5e:83:3f:ff:58:ba: + 92:a1:79:9d:ce:d2:0c:16:15:f2:7e:b3:e4:45:9c: + 02:32:65:9b:02:90:78:05:95:e4:04:1d:4a:05:bb: + ea:f6:ac:ab:15:74:c2:bc:ee:2a:c1:80:55:3e:93: + 1f:5c:94:eb:cf:cf:8f:15:eb:b8:22:fe:69:61:51: + a9:08:b8:80:bd:48:99:da:85:10:1c:75:97:fd:d3: + c3:c4:0b:dd:eb:01:12:5d:ee:62:62:c3:0c:18:ea: + ed:76:ff:9b:1c:1f:c7:81:f9:9a:cd:e5:25:89:b2: + 13:57:56:f3:27:53:72:76:69 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 7B:D3:57:BF:6A:CB:6C:10:81:91:DA:95:DC:88:4F:A5:D0:DB:D1:46 + X509v3 Authority Key Identifier: + keyid:CD:33:5E:AB:73:23:51:80:B8:03:AD:12:01:0B:C5:5E:8E:55:CA:64 + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 9 + serial:A4:DB:16:0D:4B:8C:D4:A6 + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 17:67:b0:21:da:0d:a1:fe:09:62:d0:cf:1d:c0:c8:bd:d4:22: + dd:75:ec:04:e2:23:ae:ea:8c:15:fa:73:2e:83:f4:16:eb:c1: + e1:87:36:bd:58:d0:64:e0:6e:2c:bc:27:cb:dc:4b:58:01:80: + 48:27:53:bb:75:85:a7:19:b8:e2:c0:1f:9f:a2:18:27:82:3f: + 25:bf:17:d1:34:32:de:c4:81:9d:8a:39:6f:6b:1f:b6:12:61: + 74:78:96:6d:6e:52:23:4a:67:30:78:03:91:b7:89:bf:3c:4a: + 36:e3:95:21:38:35:af:05:55:81:05:25:91:78:ca:2f:5d:79: + d2:05 +-----BEGIN CERTIFICATE----- +MIIDBjCCAm+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA5MB4XDTA5MTEyMzEzNTkx +OVoXDTM0MTExNzEzNTkxOVowaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA5MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQCpbX9qCPviOl6DP/9YupKheZ3O0gwWFfJ+s+RFnAIyZZsCkHgFleQE +HUoFu+r2rKsVdMK87irBgFU+kx9clOvPz48V67gi/mlhUakIuIC9SJnahRAcdZf9 +08PEC93rARJd7mJiwwwY6u12/5scH8eB+ZrN5SWJshNXVvMnU3J2aQIDAQABo4HH +MIHEMB0GA1UdDgQWBBR701e/astsEIGR2pXciE+l0NvRRjCBkQYDVR0jBIGJMIGG +gBTNM16rcyNRgLgDrRIBC8VejlXKZKFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA5ggkApNsWDUuM1KYwDwYDVR0TAQH/ +BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQAXZ7Ah2g2h/gli0M8dwMi91CLddewE +4iOu6owV+nMug/QW68Hhhza9WNBk4G4svCfL3EtYAYBIJ1O7dYWnGbjiwB+fohgn +gj8lvxfRNDLexIGdijlvax+2EmF0eJZtblIjSmcweAORt4m/PEo245UhODWvBVWB +BSWReMovXXnSBQ== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_9/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Root_9/demoCA/private/cakey.pem new file mode 100644 index 0000000000..65149ff650 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_9/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,EEC173CF380C4BEC + +3ZAmsMS1aFKb3EfOncYO+hg0ucK80Y7pHg7GaH2/XZ+b6HmVQrHKuDrIcQNGEY5Z +QTCBeCGhmh7hnemBSrco4HURl/2LlA5CoYyd6CCc79VeUQZRJdLjL2thD4x/QwQs +Vh9uG+nunEAXK2kI2sFAxCScoCXSZmAgQqAANQ3SHyJ14e8BlOVgucfD0afYEDNE +udc86lO8+Lz7HfTvysnKO06pgp30ZFJlnBzSBXkXsTShPWEPg8f+2JRc+A5PbxVM +gz/S/ZrPMg8QyIfwwCGjRKzyRBeXVfquXqrwNqtGI+HXo4QaYYT8zuYUn9XuJsac +ZFn2BoXhI6TCBzyM+yuoXp+Xx5plY2A8QXaiLdKO2usV5xcXaBY3XTczrnOfJh7f +F3B2mbfhr/s4UJaFmnG4eULklFGADRY5tN2bIutsWmuuw17/ZwUSZxsjl+TybqVi +uvfmEqrSgoZ9Qz1vvRngVAAwJPAvQqsBQwkq3WapNeoLqmQeSHq/6z4G5RKPbkMs +t21L4SBUGQMhkZWAnJEtECDGsQpDjjwbDuJzrbVTSBiNvDWWeXJuGdyhzI6b17v7 +CZosIrzE82Oo0C+afWJVek2cB8rIMbgqEL+3Sj7x9c/kGeLx957d+geTSStqjD3z +P574kcEDP9ppEHalg1ygJ6t3SjkTNMWrbuYH+GlY8all7rniMDYUDMECIj3Xrv+Q +x3Yzv07FAooDYBE4pdWtTjpBlmwxa68XaMSDG28jQwTHck30GU/gwrM74CKWsg8y +4eZAaeQKHeUYFGsxWeYfmwr7aD4pG+VYGOmRmdia5PA= +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Root_9/demoCA/serial b/xmlsecurity/test_docs/CAs/Root_9/demoCA/serial new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_9/demoCA/serial @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Root_9/openssl.cfg b/xmlsecurity/test_docs/CAs/Root_9/openssl.cfg new file mode 100644 index 0000000000..f48e3d5a34 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_9/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Root_7.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/cacert.pem new file mode 100644 index 0000000000..be26aa5d8f --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/cacert.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 1 + Validity + Not Before: Nov 18 15:07:13 2009 GMT + Not After : Nov 12 15:07:13 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 1 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:d9:3a:8d:64:95:87:76:76:e8:61:c3:e9:65:f4: + a6:b7:0c:77:0e:4b:10:e8:14:a3:e1:84:69:7c:8e: + 97:d2:7d:01:ad:b2:dc:5c:cd:c6:91:a1:f3:93:7c: + 54:36:64:e3:ca:22:ca:00:cb:c6:91:ab:6b:26:88: + 69:60:9a:61:d7:59:17:db:93:7d:09:36:da:28:cb: + ec:2d:a4:26:bb:1a:42:20:b8:08:b2:0f:b9:77:a6: + 80:71:cf:13:f5:37:a2:90:4d:ab:e8:97:49:d2:80: + 94:8f:b1:9d:5a:b4:9f:de:ff:fa:b6:d6:e0:45:5f: + cc:d4:10:1e:32:46:7b:ba:55 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 37:71:74:81:44:DD:1E:B1:60:96:41:B7:4B:38:C4:B7:79:1B:CF:8A + X509v3 Authority Key Identifier: + keyid:0F:FA:C6:EB:DF:CE:B8:BB:B3:A9:3E:42:A6:BA:EC:D2:93:CA:47:A4 + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 1 + serial:95:B0:05:2B:ED:C2:39:2D + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 18:f6:02:5e:75:04:5f:eb:3b:07:41:85:c0:9e:08:29:58:3d: + b5:6f:c2:aa:24:0d:93:1d:17:fc:be:d6:43:ac:43:d7:4d:a0: + 2c:40:fd:3d:d5:7e:91:46:25:49:62:ba:e9:7f:67:c2:fc:8a: + c3:a0:37:bf:ec:f9:54:bf:61:10:35:dd:5b:bb:da:7c:70:54: + 32:13:b9:ae:7d:ea:a5:7d:aa:55:3e:ef:0a:ef:12:fd:c3:f6: + e5:25:98:97:34:02:64:fd:88:79:b3:e2:f4:fc:ff:e7:d3:98: + f1:d9:d5:18:d9:b4:62:ae:99:88:61:2e:ff:02:6a:13:35:fe: + 37:c7 +-----BEGIN CERTIFICATE----- +MIIDBjCCAm+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCAxMB4XDTA5MTExODE1MDcx +M1oXDTM0MTExMjE1MDcxM1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCAxMIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDZOo1klYd2duhhw+ll9Ka3DHcOSxDoFKPhhGl8jpfSfQGtstxczcaR +ofOTfFQ2ZOPKIsoAy8aRq2smiGlgmmHXWRfbk30JNtooy+wtpCa7GkIguAiyD7l3 +poBxzxP1N6KQTavol0nSgJSPsZ1atJ/e//q21uBFX8zUEB4yRnu6VQIDAQABo4HH +MIHEMB0GA1UdDgQWBBQ3cXSBRN0esWCWQbdLOMS3eRvPijCBkQYDVR0jBIGJMIGG +gBQP+sbr3864u7OpPkKmuuzSk8pHpKFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCAxggkAlbAFK+3COS0wDwYDVR0TAQH/ +BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQAY9gJedQRf6zsHQYXAnggpWD21b8Kq +JA2THRf8vtZDrEPXTaAsQP091X6RRiVJYrrpf2fC/IrDoDe/7PlUv2EQNd1bu9p8 +cFQyE7mufeqlfapVPu8K7xL9w/blJZiXNAJk/Yh5s+L0/P/n05jx2dUY2bRirpmI +YS7/AmoTNf43xw== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/crl/DO_NOT_CREATE_A_CRL b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/crl/DO_NOT_CREATE_A_CRL new file mode 100644 index 0000000000..e69de29bb2 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/crlnumber new file mode 100644 index 0000000000..83b33d238d --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/crlnumber @@ -0,0 +1 @@ +1000 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/index.txt new file mode 100644 index 0000000000..e2027ce9f4 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/index.txt @@ -0,0 +1 @@ +V 341112152323Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 1 Root 1 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/index.txt.attr new file mode 100644 index 0000000000..8f7e63a347 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/newcerts/1000.pem new file mode 100644 index 0000000000..e7d22dfd0c --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/newcerts/1000.pem @@ -0,0 +1,58 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 1 + Validity + Not Before: Nov 18 15:23:23 2009 GMT + Not After : Nov 12 15:23:23 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 1 Root 1 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:c8:41:66:84:c7:d5:c5:72:8f:a6:98:1b:59:e2: + 33:ca:0d:d2:24:b3:c1:47:db:11:e2:bf:23:da:32: + 68:41:cc:ff:28:fe:9a:39:49:e7:08:f0:22:75:15: + 61:99:9e:99:e5:14:65:71:60:00:0f:58:42:70:78: + 5a:1e:d8:fa:97:92:82:0e:e3:0c:ac:20:dc:b8:e3: + 5e:87:8b:89:e3:a1:c3:87:49:1d:92:a5:fd:7c:77: + 79:ce:1f:fa:9c:5a:17:d9:11:0c:f2:7f:1a:fa:d8: + 32:41:f8:69:80:ae:8a:66:bd:36:c2:21:65:57:08: + be:cf:f0:ec:83:15:98:6d:65 + Exponent: 65537 (0x10001) + X509v3 extensions: + Netscape Comment: + OpenSSL Generated Certificate + X509v3 Subject Key Identifier: + FF:BB:B0:7F:E3:0E:E3:8C:CF:EC:88:49:A9:0E:62:B5:D3:60:12:46 + X509v3 Authority Key Identifier: + keyid:37:71:74:81:44:DD:1E:B1:60:96:41:B7:4B:38:C4:B7:79:1B:CF:8A + + Signature Algorithm: sha1WithRSAEncryption + 33:dd:e8:57:3e:69:1b:a0:4c:83:51:99:dd:73:b0:0c:cb:c7: + c0:ff:12:8b:b6:3b:59:12:b9:f1:20:87:75:f0:71:6e:bc:94: + 47:72:62:ae:93:90:05:e2:ff:63:31:5a:d2:80:a5:4a:7f:57: + e9:f7:4e:3e:be:bd:4c:9e:74:07:19:b0:4d:88:97:af:23:a7: + 5a:23:af:d1:a9:98:9b:55:7e:fa:6b:18:77:03:c4:aa:49:bc: + b6:3d:66:3e:8d:0a:80:5f:ac:b9:58:fb:11:ef:60:db:ad:a8: + 79:41:83:1a:6a:61:87:99:64:2d:e4:6a:bb:c0:30:00:dd:69: + e5:92 +-----BEGIN CERTIFICATE----- +MIICvjCCAiegAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCAxMB4XDTA5 +MTExODE1MjMyM1oXDTM0MTExMjE1MjMyM1owbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAxIFN1YiBDQSAxIFJvb3QgMTCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAyEFmhMfVxXKPppgbWeIzyg3SJLPBR9sR +4r8j2jJoQcz/KP6aOUnnCPAidRVhmZ6Z5RRlcWAAD1hCcHhaHtj6l5KCDuMMrCDc +uONeh4uJ46HDh0kdkqX9fHd5zh/6nFoX2REM8n8a+tgyQfhpgK6KZr02wiFlVwi+ +z/DsgxWYbWUCAwEAAaNwMG4wLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJh +dGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBT/u7B/4w7jjM/siEmpDmK102ASRjAf +BgNVHSMEGDAWgBQ3cXSBRN0esWCWQbdLOMS3eRvPijANBgkqhkiG9w0BAQUFAAOB +gQAz3ehXPmkboEyDUZndc7AMy8fA/xKLtjtZErnxIId18HFuvJRHcmKuk5AF4v9j +MVrSgKVKf1fp904+vr1MnnQHGbBNiJevI6daI6/RqZibVX76axh3A8SqSby2PWY+ +jQqAX6y5WPsR72Dbrah5QYMaamGHmWQt5Gq7wDAA3Wnlkg== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/private/cakey.pem new file mode 100644 index 0000000000..602026a470 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,4E900CB191575111 + +vHLTGKUgxa3C35alVr0gWT30x8WW5Pmz4oFv23fMMWIXjrp/QLlRRmd2AO9H8rLb +3MWnA7cby5UTcrcsqwBA30TqhduNDi4iQFcOM60/S7yUFKjF5nj9bGi8XuUzMgTx +OrJuxMGkayLiELskZxEpi6SJvTEsSdreT6OvyhzXQfAFDodoJSW65oF08cuYxXzi +FFYFqvyWXa29WUyinBav5k3Mjax3Av3dYfMf/1u2n4vjGyjkfMg7mHrno19daWqa +FJsxHHFezq//G5+JvePWFQUo1b0fVh13fx9x1dCbCRGQ9duSXaI7BNfl2Jd2rlVk +xUMqnvd8VBNkW1AHxZL4csurQyO8ZQzg46w/kWaIMroeXbUnZYNJV7/TCs6nLGJF +iNwtsFAjunWgWttFbMx3X7L7T6f6cWXocOOTNeIDpH+W6Pw9vltrjzNPAyBBok17 +sboWXDtlihMrSq5lWzUSPE8gOueh7Bcf7fSnLTeXuOXgKooJVXelookSQzsilWmS +Fo5PTM+jOOaXVlbf8zfKFreLawohNkzagIxrCEP+HU+tF52ybJDP4mwPi1sQNcA0 +0luHyCL5EmaH5hVIqYeGUQoNPois5TqgYH1SEujyIuoNdEBi5r5qIRR/zz+BEpKU +Z1B+HmmSWb0hjfenFSSaSSmGyS6VW1wZsU2B+wcPr7r0uFqoWllkxYNmSdky6qmw +4Or0D6ayFUaJOQG6aTEfEVS31B4TUfFGfOLbeuUdwNa4/pNwMeFFSx+Xj7J3oYrn +udjIL0Hz8hhjLVXaPVcu/qkZ7pXhOVlRQJ7byx730G3+elUFalJ/eQ== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/serial new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/serial @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/openssl.cfg new file mode 100644 index 0000000000..0dd15bd9ec --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/DO_NOT_INSTALL_THIS_CERTIFICATE b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/DO_NOT_INSTALL_THIS_CERTIFICATE new file mode 100644 index 0000000000..e69de29bb2 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/README.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/README.txt new file mode 100644 index 0000000000..a18ed9ce0c --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/README.txt @@ -0,0 +1,19 @@ +Do NOT install !!! + + + +To provide the CRL via HTTP run + + + +java -jar ../../tools/httpserv/dist/httpserv.jar -a 8902 + + +To provide the intermediate certificate run + +java -jar ../../tools/httpserv/dist/httpserv.jar -a 8910 + + + + + diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/DO_NOT_INSTALL_THIS_CERTIFICATE b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/DO_NOT_INSTALL_THIS_CERTIFICATE new file mode 100644 index 0000000000..e69de29bb2 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 new file mode 100644 index 0000000000..2bb9a42894 Binary files /dev/null and b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/Sub_CA_1_Root_10.crt differ diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/cacert.pem new file mode 100644 index 0000000000..1f27b97b3d --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/cacert.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 10 + Validity + Not Before: Nov 23 15:14:48 2009 GMT + Not After : Nov 17 15:14:48 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 10 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:e4:d5:66:14:88:9f:79:41:50:b0:d1:a0:1b:98: + bf:b0:21:34:30:36:70:58:6f:8b:58:f1:b9:58:3a: + ce:29:6b:65:b6:11:f7:0d:c8:a6:c3:be:db:0f:2a: + 4e:c7:42:df:c9:0e:13:c0:00:0f:af:b5:71:c4:bc: + dd:82:fc:4a:27:c0:ee:af:ba:e1:7b:67:de:6b:bb: + ac:4c:fe:88:01:1a:73:4e:f5:32:15:3a:d0:cb:6b: + 97:84:1b:6c:d0:d6:91:a8:a4:5a:87:2a:69:61:36: + 1d:42:cc:16:d0:03:9c:c6:90:5c:61:20:8b:b1:be: + b6:54:24:5b:6f:1f:a9:5a:6f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 11:63:A1:BE:8B:E3:56:07:E6:A3:9F:23:39:72:7D:E3:22:B6:53:39 + X509v3 Authority Key Identifier: + keyid:C8:A7:A3:80:20:74:6C:6F:EC:11:7A:F6:BE:26:10:37:31:87:B0:7A + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 10 + serial:BF:C8:0F:BB:D9:A0:3A:6B + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 6b:0f:75:6d:56:b0:4e:45:19:65:ad:50:ef:4e:87:6c:95:5d: + 05:39:5a:43:5c:b4:51:25:9a:ec:f4:93:d1:f0:f6:91:dd:a3: + 77:95:0c:74:3c:a9:7c:c2:f6:62:ce:bf:58:5f:66:1f:d0:55: + ca:d8:2d:c4:1e:29:3a:ad:55:2c:9d:2c:8f:8e:9e:ce:ac:17: + 7e:1b:d1:16:d9:12:76:5c:2d:3f:9d:70:66:aa:39:34:f0:ec: + 31:4b:4b:5a:14:0c:c5:5b:3c:c8:47:02:90:cb:77:d7:4f:88: + 10:a7:80:3d:ca:19:5c:b5:04:c9:f0:e1:1b:5a:5f:fb:61:b2: + 14:b5 +-----BEGIN CERTIFICATE----- +MIIDCTCCAnKgAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMDAeFw0wOTExMjMxNTE0 +NDhaFw0zNDExMTcxNTE0NDhaMGkxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxGTAXBgNVBAMTEFN1YiBDQSAxIFJvb3QgMTAwgZ8wDQYJKoZIhvcNAQEBBQAD +gY0AMIGJAoGBAOTVZhSIn3lBULDRoBuYv7AhNDA2cFhvi1jxuVg6zilrZbYR9w3I +psO+2w8qTsdC38kOE8AAD6+1ccS83YL8SifA7q+64Xtn3mu7rEz+iAEac071MhU6 +0Mtrl4QbbNDWkaikWocqaWE2HULMFtADnMaQXGEgi7G+tlQkW28fqVpvAgMBAAGj +gcgwgcUwHQYDVR0OBBYEFBFjob6L41YH5qOfIzlyfeMitlM5MIGSBgNVHSMEgYow +gYeAFMino4AgdGxv7BF69r4mEDcxh7B6oWSkYjBgMQswCQYDVQQGEwJERTEQMA4G +A1UECBMHSGFtYnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsT +C0RldmVsb3BtZW50MRAwDgYDVQQDEwdSb290IDEwggkAv8gPu9mgOmswDwYDVR0T +AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBrD3VtVrBORRllrVDvTodslV0F +OVpDXLRRJZrs9JPR8PaR3aN3lQx0PKl8wvZizr9YX2Yf0FXK2C3EHik6rVUsnSyP +jp7OrBd+G9EW2RJ2XC0/nXBmqjk08OwxS0taFAzFWzzIRwKQy3fXT4gQp4A9yhlc +tQTJ8OEbWl/7YbIUtQ== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/crl/DO_NOT_INSTALL_THIS_CRL b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/crl/DO_NOT_INSTALL_THIS_CRL new file mode 100644 index 0000000000..e69de29bb2 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 new file mode 100644 index 0000000000..67ed32da5f Binary files /dev/null and b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/crl/Sub_CA_1_Root_10.crl differ diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/crlnumber new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/crlnumber @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/index.txt new file mode 100644 index 0000000000..810ec7ef2f --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/index.txt @@ -0,0 +1 @@ +V 341117153149Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 1 Root 10 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/index.txt.attr new file mode 100644 index 0000000000..8f7e63a347 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/newcerts/1000.pem new file mode 100644 index 0000000000..7449048bbc --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/newcerts/1000.pem @@ -0,0 +1,67 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 10 + Validity + Not Before: Nov 23 15:31:49 2009 GMT + Not After : Nov 17 15:31:49 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 1 Root 10 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:ce:41:53:5f:ba:d9:26:e4:45:14:74:a9:f2:9e: + fa:91:50:ea:fe:e7:76:76:6e:62:26:4c:a2:bd:c9: + 98:ce:1d:b3:74:ea:95:04:ec:d8:24:ac:29:de:2d: + 7f:2f:7f:10:94:24:d2:0c:0b:ff:d0:38:f1:a9:8f: + ee:25:97:bf:bd:b0:1f:24:d7:9d:7a:20:79:c0:73: + 97:12:cb:5a:cf:6d:4f:df:4a:a8:9c:1b:be:49:63: + 1f:b1:03:6d:c6:5f:69:5c:0d:7e:81:23:48:2a:76: + 80:53:53:d2:03:f6:56:6d:dc:e3:cc:be:cb:0f:c3: + 1b:b7:6e:79:33:e0:da:f6:5d + Exponent: 65537 (0x10001) + X509v3 extensions: + Authority Information Access: + CA Issuers - URI:http://localhost:8910/demoCA/Sub_CA_1_Root_10.crt + + X509v3 CRL Distribution Points: + URI:http://localhost:8902/demoCA/crl/Sub_CA_1_Root_10.crl + + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 90:DC:ED:B0:CB:62:A1:BE:8F:23:65:01:79:14:85:22:48:70:7B:A1 + X509v3 Authority Key Identifier: + keyid:11:63:A1:BE:8B:E3:56:07:E6:A3:9F:23:39:72:7D:E3:22:B6:53:39 + + Signature Algorithm: sha1WithRSAEncryption + 54:e3:d2:eb:dc:aa:db:8b:88:34:c6:b9:5b:f6:d8:ca:81:24: + d0:ba:4c:c2:a7:8e:82:22:d3:68:64:c9:61:9b:0a:00:3e:d1: + 4e:cb:83:1d:b9:c7:07:6a:5e:7b:b4:ca:92:0c:93:d7:9e:99: + e1:58:47:17:b0:a7:6d:68:5f:e5:59:f9:2a:d1:96:df:b6:9f: + bc:47:40:f2:71:ed:71:2b:8a:6e:6f:aa:29:9f:4d:98:ee:f1: + aa:63:b4:44:39:58:8a:f8:c2:af:8d:c1:49:92:b4:99:02:2f: + 27:c7:5b:f5:30:7c:ed:67:ff:cd:12:dc:a7:c4:8e:98:4f:2c: + e0:05 +-----BEGIN CERTIFICATE----- +MIIDODCCAqGgAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwaTELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEZMBcGA1UEAxMQU3ViIENBIDEgUm9vdCAxMDAeFw0w +OTExMjMxNTMxNDlaFw0zNDExMTcxNTMxNDlaMHAxCzAJBgNVBAYTAkRFMRAwDgYD +VQQIEwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxML +RGV2ZWxvcG1lbnQxIDAeBgNVBAMTF1VzZXIgMSBTdWIgQ0EgMSBSb290IDEwMIGf +MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOQVNfutkm5EUUdKnynvqRUOr+53Z2 +bmImTKK9yZjOHbN06pUE7NgkrCneLX8vfxCUJNIMC//QOPGpj+4ll7+9sB8k1516 +IHnAc5cSy1rPbU/fSqicG75JYx+xA23GX2lcDX6BI0gqdoBTU9ID9lZt3OPMvssP +wxu3bnkz4Nr2XQIDAQABo4HnMIHkME0GCCsGAQUFBwEBBEEwPzA9BggrBgEFBQcw +AoYxaHR0cDovL2xvY2FsaG9zdDo4OTEwL2RlbW9DQS9TdWJfQ0FfMV9Sb290XzEw +LmNydDBGBgNVHR8EPzA9MDugOaA3hjVodHRwOi8vbG9jYWxob3N0Ojg5MDIvZGVt +b0NBL2NybC9TdWJfQ0FfMV9Sb290XzEwLmNybDALBgNVHQ8EBAMCBeAwHQYDVR0O +BBYEFJDc7bDLYqG+jyNlAXkUhSJIcHuhMB8GA1UdIwQYMBaAFBFjob6L41YH5qOf +IzlyfeMitlM5MA0GCSqGSIb3DQEBBQUAA4GBAFTj0uvcqtuLiDTGuVv22MqBJNC6 +TMKnjoIi02hkyWGbCgA+0U7Lgx25xwdqXnu0ypIMk9eemeFYRxewp21oX+VZ+SrR +lt+2n7xHQPJx7XErim5vqimfTZju8apjtEQ5WIr4wq+NwUmStJkCLyfHW/UwfO1n +/80S3KfEjphPLOAF +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/private/cakey.pem new file mode 100644 index 0000000000..260e3aa946 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,170F9697C268C4B5 + +eIaE0ShuxMcOUBJBlI7PXIuKg69hDunjUz55iy0I+4sGc9tFK+vtjvDZWxx+dpZI +WKGto0fDeobBf3f2xgKQFcwAtUPtiTMXk8C0BYfAbXsTYBgOgvKwJGOIo5FsjukZ +VJCNlUM1mwX5P3OrLdyT0j8OoL6lINztYDhSC8XL12YJk1j05yN4Gl8N108JQMLA +sywA2Q6WIhPloZQXtHkiN2mlQ7WWwbSBbaUbdXNQKk6sXelFLPMOk+JOTCLp9kHU +svTBAg7RyWKBuUmtEmkipNLtYhdkRVJ/dgL3/TAsZET6cjDd/eZg+1Kl0pn93KGv +avSQKppkKNjUcWkZiuM1imS8+0qeMiw56JQGzMdEeSjadcTdsyYb0lssXmndK/z0 +90bA6GegvCnsq6Wj0Nz97GbK+ZMzA76e+HPQLli0j3poAlVwdzBCFRyLO4ET5Qzl +OhTewxKZxe2yx75chECWJS+CLOajHkVyUe3x6QzyVuU+YZqjXWkJP7rTcQJZFcml ++3PHYWy5RnZ2sKOegksr3+QtL+UmDVa1xEeIhk3m0IMiYZ9HNWlrg1gedY02y9yY +MGsCOkCF10KnCNIp4j5s1kGMicdMquDt0jTXwu+8jt6Skh8FWcr9aLf0bNc63oHg +NaI7Y3+Ssl3GLUGFOGwC0lpooZ10SoJJDK9xxEjt48vUfX+Npn3bRv+UlwfLBYLo +GENyNV3OVAsKYQ8fGIh/gTeIqwMUdo7Efcs6bdeqiOrYQhBl04Gty0I4cO6/lFGd +by/4SesYDXoVtaKto1B5VOQn+QxovF7eY1pK6wDBU8+EaJbGSNK9Rw== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/serial new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/serial @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/openssl.cfg new file mode 100644 index 0000000000..431650974b --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/openssl.cfg @@ -0,0 +1,293 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8889 +authorityInfoAccess = caIssuers;URI:http://localhost:8910/demoCA/Sub_CA_1_Root_10.crt +crlDistributionPoints=URI:http://localhost:8902/demoCA/crl/Sub_CA_1_Root_10.crl +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +#nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/cacert.pem new file mode 100644 index 0000000000..36a8eb3c07 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/cacert.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 2 + Validity + Not Before: Nov 18 15:55:38 2009 GMT + Not After : Nov 12 15:55:38 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 2 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:f0:7a:16:4c:ab:06:b2:af:27:9c:7d:3f:86:da: + de:7a:c3:01:67:77:56:49:09:ed:ed:31:72:83:e8: + 75:9c:4c:ce:f9:97:b6:63:3c:e2:ca:83:80:92:03: + 9c:96:e2:de:72:79:c1:cf:3e:3f:b9:0d:b4:87:c7: + 75:e6:56:8d:aa:f8:77:47:11:4e:fe:07:b0:1d:64: + 06:73:4b:6f:d4:ac:da:0f:05:87:b1:f1:98:a9:f5: + 8a:a1:a8:ed:17:9c:26:b8:da:92:63:d2:53:87:e6: + fc:ed:44:de:94:56:90:3e:a2:a1:67:08:cb:38:d4: + cf:17:3b:7e:ff:7a:97:c0:7b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 8C:F3:2C:30:A2:E8:62:50:70:BC:FC:71:A0:41:FA:E0:58:B4:4D:B8 + X509v3 Authority Key Identifier: + keyid:5F:BC:4C:DA:EB:0A:0C:B5:23:43:5E:24:32:27:79:41:F5:82:A3:02 + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 2 + serial:A2:AF:15:89:EC:73:54:86 + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 52:83:16:ab:0e:43:2d:b3:e4:0f:6c:c1:63:d4:86:ac:e7:1e: + ee:7b:ee:9b:0c:ff:4f:e0:59:d5:e4:27:af:68:bf:a7:f5:2a: + a3:c9:e3:2b:8d:b7:31:26:f6:04:80:4e:f2:a5:bf:da:63:5e: + 8c:d6:c6:b2:46:a0:46:10:2f:84:9f:02:76:f3:c8:33:05:62: + 0c:5f:2d:cc:06:23:53:9f:d9:f8:46:e4:2e:5c:da:05:fc:bf: + db:45:b4:ac:8d:8b:b5:4b:60:7b:7b:26:34:7f:b1:4b:41:96: + 41:26:70:7a:9d:78:a2:9b:e0:de:62:a2:04:86:9f:ed:7c:a6: + 20:eb +-----BEGIN CERTIFICATE----- +MIIDBjCCAm+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCAyMB4XDTA5MTExODE1NTUz +OFoXDTM0MTExMjE1NTUzOFowaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCAyMIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDwehZMqwayryecfT+G2t56wwFnd1ZJCe3tMXKD6HWcTM75l7ZjPOLK +g4CSA5yW4t5yecHPPj+5DbSHx3XmVo2q+HdHEU7+B7AdZAZzS2/UrNoPBYex8Zip +9YqhqO0XnCa42pJj0lOH5vztRN6UVpA+oqFnCMs41M8XO37/epfAewIDAQABo4HH +MIHEMB0GA1UdDgQWBBSM8ywwouhiUHC8/HGgQfrgWLRNuDCBkQYDVR0jBIGJMIGG +gBRfvEza6woMtSNDXiQyJ3lB9YKjAqFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCAyggkAoq8ViexzVIYwDwYDVR0TAQH/ +BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBSgxarDkMts+QPbMFj1Ias5x7ue+6b +DP9P4FnV5CevaL+n9SqjyeMrjbcxJvYEgE7ypb/aY16M1sayRqBGEC+EnwJ288gz +BWIMXy3MBiNTn9n4RuQuXNoF/L/bRbSsjYu1S2B7eyY0f7FLQZZBJnB6nXiim+De +YqIEhp/tfKYg6w== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/crlnumber new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/crlnumber @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/index.txt new file mode 100644 index 0000000000..ae1f2d1e4c --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/index.txt @@ -0,0 +1 @@ +V 341112160955Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 1 Root 2 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/index.txt.attr new file mode 100644 index 0000000000..8f7e63a347 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/newcerts/1000.pem new file mode 100644 index 0000000000..a8c0b74caf --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/newcerts/1000.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 2 + Validity + Not Before: Nov 18 16:09:55 2009 GMT + Not After : Nov 12 16:09:55 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 1 Root 2 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:c7:00:aa:e0:5a:42:af:9c:b5:43:8c:f4:7d:7a: + 0f:ee:a9:19:22:d8:47:14:af:b4:e4:dd:5d:41:92: + a1:2b:32:39:5c:71:88:10:e3:77:87:b6:d5:38:85: + de:4b:91:c6:17:97:8e:3d:96:b3:af:8c:9d:74:8c: + 88:7f:2a:72:9a:ca:1a:1b:56:6c:63:2e:a4:a0:fc: + 3a:7b:0d:c2:16:15:d0:80:15:29:de:cd:0b:74:bc: + 5e:31:84:71:a4:fd:be:9b:06:6a:0c:47:1d:f9:e4: + c1:98:ae:46:e6:e2:51:55:d5:bb:ab:05:28:69:b5: + f8:35:32:d6:f0:64:d8:44:81 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + Netscape Comment: + OpenSSL Generated Certificate + X509v3 Subject Key Identifier: + 71:60:2B:22:B5:DF:FC:38:7E:79:F3:EF:7C:96:5F:C1:D2:42:9C:61 + X509v3 Authority Key Identifier: + keyid:8C:F3:2C:30:A2:E8:62:50:70:BC:FC:71:A0:41:FA:E0:58:B4:4D:B8 + + Signature Algorithm: sha1WithRSAEncryption + e5:b8:1a:43:82:75:20:48:e0:52:d0:46:25:6f:f7:5b:a9:3f: + 9e:cd:db:45:da:15:53:95:e7:c8:74:7b:e0:e4:2c:8c:f6:4d: + 1c:73:6e:2c:11:eb:c1:dc:4c:1d:50:e3:e8:10:2f:03:20:06: + ff:d7:4f:c9:a2:2e:ef:85:27:92:31:47:64:c8:75:f2:fc:a4: + 9d:c9:53:55:c5:da:69:b0:96:99:fd:ac:c4:16:40:ea:0c:1b: + 32:c3:fd:65:1d:03:ad:be:60:88:7c:70:53:35:91:ce:13:e2: + 3d:23:6b:e8:23:c0:3c:9a:57:5f:ad:4b:03:94:92:16:62:f9: + d4:01 +-----BEGIN CERTIFICATE----- +MIICyzCCAjSgAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCAyMB4XDTA5 +MTExODE2MDk1NVoXDTM0MTExMjE2MDk1NVowbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAxIFN1YiBDQSAxIFJvb3QgMjCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAxwCq4FpCr5y1Q4z0fXoP7qkZIthHFK+0 +5N1dQZKhKzI5XHGIEON3h7bVOIXeS5HGF5eOPZazr4yddIyIfypymsoaG1ZsYy6k +oPw6ew3CFhXQgBUp3s0LdLxeMYRxpP2+mwZqDEcd+eTBmK5G5uJRVdW7qwUoabX4 +NTLW8GTYRIECAwEAAaN9MHswCwYDVR0PBAQDAgXgMCwGCWCGSAGG+EIBDQQfFh1P +cGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUcWArIrXf/Dh+ +efPvfJZfwdJCnGEwHwYDVR0jBBgwFoAUjPMsMKLoYlBwvPxxoEH64Fi0TbgwDQYJ +KoZIhvcNAQEFBQADgYEA5bgaQ4J1IEjgUtBGJW/3W6k/ns3bRdoVU5XnyHR74OQs +jPZNHHNuLBHrwdxMHVDj6BAvAyAG/9dPyaIu74UnkjFHZMh18vyknclTVcXaabCW +mf2sxBZA6gwbMsP9ZR0Drb5giHxwUzWRzhPiPSNr6CPAPJpXX61LA5SSFmL51AE= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/private/cakey.pem new file mode 100644 index 0000000000..ba6119464f --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,A5EF3D451C410026 + +RByk5Bn7uG1eixW1qTghnNri2bQHvnrNUYcpSL/mJIx6NjuYEY6vE/vQ9A9qcjuZ +8NInLR1w+EmSlDS499za8dfllaJ4/djswWN+4gtkoP/kKF390AcNgIpf/gIiJX6d +tkrw3Esst2gUwdtdhWItQNh0qZoeWpY9KlraDdEYVZt46JmsgwEIufzHyHTHf53C +E9ZP7/vYBQeHPOvMGsvhwZWAZZOO5GnD4fktbVAnybQdnlPgJDrRTGabbTdawQNc +8GJoG6hgJPcwlYm7NbRrtB18L3bG4bxx95fjqeOtvGDSUxSY+FNV7B2xQpivnBu6 +ppLdwTRYHQGOCJSCZoCtW+GYM7wXR2L4kGXMPwB4hHUAQXt+Tva9TP0t96313lMW +bFTRgTcT71eBidEkUIn1OrOL/Al2lXvSaDhm0P2F0yElzj3JN/gqrIUChaXWcLrS +CZuOGA2zGpoBASQ5jF+CyC+5mEkmDgvbmAXiJNjNmK/ColklpTNRSGk65Vr8AufA +d/yoSQCGprhMgqhviue40MGSsOD58TLwR4Tsm5ptze0QYRNC2SkKCrgtS0IEXh/Z +/9cMAgwOypW1T7LMOV+rG9DOyKx9Ye+oxPLCHdS7wN4h6blusiESbbUW0f5wqAzF +FCe6VEd+AjahnQLjw7O8vP4zl8q99cjOYD5SB+wqYrr0beEely7xdpKrDMgXqiBe +tOE9XvgU9KR59GZd0l6FPRkpZCUA+3Wuu4Zvrbam5kEbxVy+VTamWd5cRrxbJBM4 +Ipn414lfeq/5Foz13roErJE6gbWxXeCFDzg0z5fjWc2T41PX58x4Tw== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/req.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/req.pem new file mode 100644 index 0000000000..cc93d02e54 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/req.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIBqDCCARECAQAwaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1cmcxFzAV +BgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVudDEYMBYG +A1UEAxMPU3ViIENBIDEgUm9vdCAyMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB +gQDwehZMqwayryecfT+G2t56wwFnd1ZJCe3tMXKD6HWcTM75l7ZjPOLKg4CSA5yW +4t5yecHPPj+5DbSHx3XmVo2q+HdHEU7+B7AdZAZzS2/UrNoPBYex8Zip9YqhqO0X +nCa42pJj0lOH5vztRN6UVpA+oqFnCMs41M8XO37/epfAewIDAQABoAAwDQYJKoZI +hvcNAQEFBQADgYEADbuni6Yq0l5FJGFDUaabv4T75XxyMWy+k6wSojSt1thtwcJI +Bx5x1ngG5VyxeNmqyjLvd2KeYsVaV8M9J9ty40QGL8F83OArJPGADtBSM+gwmjdu +C+ksYL+5Yl8vSY3M7tKqJB2AFk2QlfP5okMQWRJ5QFTTwA8EFpHFsy4gsks= +-----END CERTIFICATE REQUEST----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/serial new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/serial @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/openssl.cfg new file mode 100644 index 0000000000..51e5205253 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/cacert.pem new file mode 100644 index 0000000000..c14880b580 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/cacert.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 3 + Validity + Not Before: Nov 20 07:40:39 2009 GMT + Not After : Nov 14 07:40:39 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 3 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:9e:87:1f:af:f0:a0:1c:f4:9e:f8:c3:e7:ee:d3: + cb:a8:e2:54:98:ba:dd:7e:dc:6e:14:e1:7e:7f:5b: + 1e:ef:53:3d:89:76:ea:e2:b3:6c:08:0d:e8:c8:4d: + 24:40:ff:92:f3:5b:51:f7:90:ac:69:37:29:90:f5: + e8:95:6f:67:d1:10:cd:7b:dd:65:38:d6:25:ec:63: + 39:ba:2e:ea:13:58:8e:7a:82:8e:10:d1:7b:77:7a: + 08:d5:82:66:62:a4:83:39:ad:f5:83:d5:2f:5c:bc: + 23:6e:c8:78:8b:38:9f:eb:a3:67:ba:43:fa:e4:07: + 3f:90:72:db:0c:f9:49:0e:0d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 1B:2D:E0:A2:26:7F:0D:BA:38:7E:EC:06:81:81:0F:12:74:4C:5A:4D + X509v3 Authority Key Identifier: + keyid:69:FF:30:EC:1F:34:9A:67:3A:6B:20:D2:DF:7F:F5:05:04:ED:F9:1C + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 3 + serial:95:6F:F0:E3:2B:BE:76:F9 + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 6f:ac:53:9d:16:6e:95:ed:97:60:ed:c8:a8:96:ab:24:c5:1e: + d5:d7:26:98:fb:b5:aa:ef:da:a4:91:6a:82:55:ec:21:a2:08: + 24:c7:0c:a7:58:0c:06:69:3d:04:7d:08:f1:0b:77:41:ad:1c: + 13:c2:bd:17:c9:9e:ff:df:64:69:8b:58:f1:bc:40:bd:cf:e4: + 57:29:bc:5e:93:84:61:56:4c:e6:c1:3a:2c:6e:71:ea:5d:67: + c0:54:be:4f:2f:27:a8:59:8d:29:94:ba:c6:6c:ff:ed:25:3d: + 0b:fa:93:c9:45:f4:d5:a3:3d:be:8a:f1:9d:c4:92:d5:5c:d2: + 77:7c +-----BEGIN CERTIFICATE----- +MIIDBjCCAm+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCAzMB4XDTA5MTEyMDA3NDAz +OVoXDTM0MTExNDA3NDAzOVowaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCAzMIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQCehx+v8KAc9J74w+fu08uo4lSYut1+3G4U4X5/Wx7vUz2Jduris2wI +DejITSRA/5LzW1H3kKxpNymQ9eiVb2fREM173WU41iXsYzm6LuoTWI56go4Q0Xt3 +egjVgmZipIM5rfWD1S9cvCNuyHiLOJ/ro2e6Q/rkBz+QctsM+UkODQIDAQABo4HH +MIHEMB0GA1UdDgQWBBQbLeCiJn8Nujh+7AaBgQ8SdExaTTCBkQYDVR0jBIGJMIGG +gBRp/zDsHzSaZzprINLff/UFBO35HKFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCAzggkAlW/w4yu+dvkwDwYDVR0TAQH/ +BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBvrFOdFm6V7Zdg7ciolqskxR7V1yaY ++7Wq79qkkWqCVewhoggkxwynWAwGaT0EfQjxC3dBrRwTwr0XyZ7/32Rpi1jxvEC9 +z+RXKbxek4RhVkzmwTosbnHqXWfAVL5PLyeoWY0plLrGbP/tJT0L+pPJRfTVoz2+ +ivGdxJLVXNJ3fA== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/crl/DO_NOT_CREATE_A_CRL b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/crl/DO_NOT_CREATE_A_CRL new file mode 100644 index 0000000000..e69de29bb2 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/crlnumber new file mode 100644 index 0000000000..83b33d238d --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/crlnumber @@ -0,0 +1 @@ +1000 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/index.txt new file mode 100644 index 0000000000..bd3b5eaeae --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/index.txt @@ -0,0 +1 @@ +V 341114075225Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 1 Root 3 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/index.txt.attr new file mode 100644 index 0000000000..8f7e63a347 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/newcerts/1000.pem new file mode 100644 index 0000000000..46d60bda0a --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/newcerts/1000.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 3 + Validity + Not Before: Nov 20 07:52:25 2009 GMT + Not After : Nov 14 07:52:25 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 1 Root 3 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:bc:82:f1:75:77:02:f8:fb:3a:c2:8d:3c:1b:cb: + b2:63:2e:89:07:92:6b:b4:e1:ab:ce:30:a1:a4:82: + 38:30:64:2a:ba:01:c6:ac:ee:03:cc:65:bf:83:3e: + 39:b8:ce:ac:45:99:97:f9:94:e2:7d:5d:f3:c5:f7: + d4:a5:d6:57:cf:24:c1:d7:56:eb:00:9c:5d:80:bc: + 23:0c:91:d6:8e:2a:62:f6:af:4d:c9:19:5b:dd:16: + be:21:54:51:71:be:f2:c6:64:c5:bb:8e:37:49:c9: + 4d:68:82:3a:42:8a:e3:de:ab:fa:c7:ff:a5:b4:c7: + 53:8f:17:a4:66:9d:c3:8e:b1 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + Netscape Comment: + OpenSSL Generated Certificate + X509v3 Subject Key Identifier: + 0B:DD:2E:E9:5C:8A:5F:67:C9:75:4C:B3:04:DB:95:2F:D8:74:76:EF + X509v3 Authority Key Identifier: + keyid:1B:2D:E0:A2:26:7F:0D:BA:38:7E:EC:06:81:81:0F:12:74:4C:5A:4D + + Signature Algorithm: sha1WithRSAEncryption + 18:2f:af:1a:27:c7:f8:81:cd:d5:31:a0:f2:06:05:94:d6:12: + 11:88:24:ae:4f:f6:86:18:bf:d0:1b:c9:19:7a:47:30:0e:fb: + 30:b2:50:31:8d:30:6b:8b:54:17:67:bc:b8:c1:d5:1c:6c:95: + c5:e4:c4:ad:12:39:2f:38:ee:53:6a:cf:be:1c:4f:ac:98:0c: + ea:eb:0b:48:3d:5e:7a:2b:ed:02:8b:34:89:0a:d8:32:b4:6f: + f4:b2:06:96:aa:6b:ae:19:38:ec:9f:47:43:3b:7b:bd:71:38: + 99:4f:b4:1e:87:95:73:63:76:d4:ff:21:57:2c:c3:f4:3c:fd: + cb:c3 +-----BEGIN CERTIFICATE----- +MIICyzCCAjSgAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCAzMB4XDTA5 +MTEyMDA3NTIyNVoXDTM0MTExNDA3NTIyNVowbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAxIFN1YiBDQSAxIFJvb3QgMzCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvILxdXcC+Ps6wo08G8uyYy6JB5JrtOGr +zjChpII4MGQqugHGrO4DzGW/gz45uM6sRZmX+ZTifV3zxffUpdZXzyTB11brAJxd +gLwjDJHWjipi9q9NyRlb3Ra+IVRRcb7yxmTFu443SclNaII6Qorj3qv6x/+ltMdT +jxekZp3DjrECAwEAAaN9MHswCwYDVR0PBAQDAgXgMCwGCWCGSAGG+EIBDQQfFh1P +cGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUC90u6VyKX2fJ +dUyzBNuVL9h0du8wHwYDVR0jBBgwFoAUGy3goiZ/Dbo4fuwGgYEPEnRMWk0wDQYJ +KoZIhvcNAQEFBQADgYEAGC+vGifH+IHN1TGg8gYFlNYSEYgkrk/2hhi/0BvJGXpH +MA77MLJQMY0wa4tUF2e8uMHVHGyVxeTErRI5LzjuU2rPvhxPrJgM6usLSD1eeivt +Aos0iQrYMrRv9LIGlqprrhk47J9HQzt7vXE4mU+0HoeVc2N21P8hVyzD9Dz9y8M= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/private/cakey.pem new file mode 100644 index 0000000000..8d893cdf9e --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,EF032FCF0827A7AA + +vTlvOy1d4MK41zEZfeUWDO7kjLqZ53jK6JdXhKT2P9MnstGf1S0QxwbEKP+KWj+4 +lwS7fSXs6/s2Q5OrG9QSV4bm5Sob0OpDfoc1GS24uSGvYXzhuyM9sjiITXvyGKCH ++0VQPV/GSXWShsk5CCzUXIBSBHDVxlEzmBvzWiHfcLEAwF1JJlh6ex9Xju9JL9sN +Gp4VMw9PML11V4iqNXKeyBZ87Bv/yew+bDACLCe7e1liBxdOj2ntc7mtpCrkf/pn +hLnJ1qKodcwgmmMLufa7//E1RCBMn1gml0YXMe+Grrn7tFdVWT/puKiSrKGgIbbB +RNf7JnG5E8Oy2V8NRk4SV5Au784fw5NMykQDCMJFp9aldwP7LlIUBPtPm/jpaY0V +e6tKT20e4Ru2mDzyfef8nhFRogMxvPrxVSxN8aI1u/soPMp55ypWrqg99QlsiZgG +MhpHaFODSWvHaFcwFY+gEDUmEH76S3wuOSgeFolvIPEETjw6Vc46Zi32N1ycQ1wz +NCbIGy2ftEzKIEOeXHAsuQiP+Cic1QYJEOxhvOq9VteYfilT7D9FQ2+QOqrl4+2X +hj2RaTJawpSFoWfEh7QM1ir0TPj3wRSTg6g3e0f+vAvI9AfVEP3ctPm6tpXirUgh +QOA1LZKZzHUYqr0q2TBvItyGsg3w7dxyeB6brCtzOzg+GpvNhaRZ1/+SVPxzYVgf +buLQIfvvLE6TmABxOloop1m61u6c6+Bg5kKHXSnUKehGv+iIxVLZgxrNkCFyyzX0 +Dpu9hkGYzVzE8QCujC09MZCKH/85iYGuEZtP81Mjyjs= +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/req.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/req.pem new file mode 100644 index 0000000000..dd08bf6717 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/req.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIBqDCCARECAQAwaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1cmcxFzAV +BgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVudDEYMBYG +A1UEAxMPU3ViIENBIDEgUm9vdCAzMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB +gQCehx+v8KAc9J74w+fu08uo4lSYut1+3G4U4X5/Wx7vUz2Jduris2wIDejITSRA +/5LzW1H3kKxpNymQ9eiVb2fREM173WU41iXsYzm6LuoTWI56go4Q0Xt3egjVgmZi +pIM5rfWD1S9cvCNuyHiLOJ/ro2e6Q/rkBz+QctsM+UkODQIDAQABoAAwDQYJKoZI +hvcNAQEFBQADgYEAiwW4WbC3V3wEBfPlIFiUagJHOettp5NyCzLULyQZE1FXs/zV +RxIi3Oxdaj643QZ8h6upKf9F60T8+oG15RBdp1ZjmBXnv7ZRx33LynExbxX0XKjo +Pg/8dGLFBomZqE8MpWbQtY5lRkQOkgt5XZLj5SMJQsgpVaAOPQcOg5Sqfag= +-----END CERTIFICATE REQUEST----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/serial new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/serial @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/openssl.cfg new file mode 100644 index 0000000000..51e5205253 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/README.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/README.txt new file mode 100644 index 0000000000..3ac354b8f8 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/README.txt @@ -0,0 +1,4 @@ +Revoked certificates: +--------------------- +- User 2 Sub CA 1 Root 4 + diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/cacert.pem new file mode 100644 index 0000000000..3910371181 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/cacert.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 4 + Validity + Not Before: Nov 20 08:37:27 2009 GMT + Not After : Nov 14 08:37:27 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 4 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:da:b0:21:94:89:b0:00:89:cb:69:59:9b:0d:fe: + 1f:b9:a0:a8:44:92:55:5f:0b:d5:e5:08:63:bd:47: + 6b:11:4d:b1:a8:12:6f:c1:cf:cb:9e:ae:e2:c1:03: + 68:46:59:0b:96:7c:21:45:9b:14:81:d8:f1:83:70: + 6b:3d:b4:56:65:49:87:1d:ab:e2:08:6a:49:66:0e: + 59:b4:da:7a:3f:72:23:b8:1f:fb:78:f5:f0:2d:c4: + fe:d9:94:6e:2e:c3:6e:95:ba:38:60:d1:0b:fa:16: + c7:02:71:ef:3e:71:72:63:26:56:35:1e:8b:ec:47: + 87:25:6e:bc:90:d0:8b:37:2d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 96:9A:2D:06:F6:76:4F:83:68:7B:9C:69:C4:18:BB:4A:EB:46:38:E4 + X509v3 Authority Key Identifier: + keyid:BA:8D:A1:97:DC:C4:39:1F:90:B5:51:6B:10:19:F2:46:0D:A9:65:8E + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 4 + serial:A2:93:46:74:3B:A6:E3:AD + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 45:77:ba:6b:b6:a7:2a:0f:6b:38:90:9f:0a:18:11:c7:54:7b: + c9:3b:9a:93:90:96:f0:04:0a:56:87:30:e0:f5:d8:84:40:39: + 90:85:ca:e7:38:1b:d8:df:2f:bd:73:91:13:cb:a6:c9:b0:7a: + f7:59:77:6b:9a:d5:86:78:06:dc:40:14:ce:ea:43:a8:ae:ed: + a2:03:64:51:3a:47:7a:9f:df:2d:65:49:56:a5:39:cf:28:2a: + ac:ab:fd:e1:93:fd:3e:56:e8:eb:7a:11:a8:f7:f9:1a:a1:83: + 1f:92:f7:da:4e:c6:d9:67:dd:67:ff:be:6f:e5:24:e1:6e:cc: + 94:3c +-----BEGIN CERTIFICATE----- +MIIDBjCCAm+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA0MB4XDTA5MTEyMDA4Mzcy +N1oXDTM0MTExNDA4MzcyN1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA0MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDasCGUibAAictpWZsN/h+5oKhEklVfC9XlCGO9R2sRTbGoEm/Bz8ue +ruLBA2hGWQuWfCFFmxSB2PGDcGs9tFZlSYcdq+IIaklmDlm02no/ciO4H/t49fAt +xP7ZlG4uw26Vujhg0Qv6FscCce8+cXJjJlY1HovsR4clbryQ0Is3LQIDAQABo4HH +MIHEMB0GA1UdDgQWBBSWmi0G9nZPg2h7nGnEGLtK60Y45DCBkQYDVR0jBIGJMIGG +gBS6jaGX3MQ5H5C1UWsQGfJGDalljqFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA0ggkAopNGdDum460wDwYDVR0TAQH/ +BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBFd7prtqcqD2s4kJ8KGBHHVHvJO5qT +kJbwBApWhzDg9diEQDmQhcrnOBvY3y+9c5ETy6bJsHr3WXdrmtWGeAbcQBTO6kOo +ru2iA2RROkd6n98tZUlWpTnPKCqsq/3hk/0+VujrehGo9/kaoYMfkvfaTsbZZ91n +/75v5SThbsyUPA== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/crlnumber new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/crlnumber @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/index.txt new file mode 100644 index 0000000000..88e41b76ac --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/index.txt @@ -0,0 +1,2 @@ +V 341114084401Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 1 Root 4 +R 341114085720Z 091120085929Z,keyCompromise 1001 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 2 Sub CA 1 Root 4 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/index.txt.attr new file mode 100644 index 0000000000..8f7e63a347 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/newcerts/1000.pem new file mode 100644 index 0000000000..73563ed969 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/newcerts/1000.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 4 + Validity + Not Before: Nov 20 08:44:01 2009 GMT + Not After : Nov 14 08:44:01 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 1 Root 4 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:c3:55:aa:1b:4f:f6:b4:78:be:ac:61:2a:92:94: + 73:1b:39:4c:0e:57:7e:da:78:03:7e:65:11:57:97: + e6:f4:0d:72:1f:f6:2b:a4:33:f9:5c:bd:2b:25:6c: + 58:29:73:b9:46:d5:db:e9:03:1d:a2:f8:8e:6e:c2: + b5:95:ec:ba:95:c3:ac:2e:c0:b6:40:ba:23:1d:74: + 75:91:cc:d6:3a:4c:15:4d:15:03:a4:e6:80:4a:93: + fe:6c:91:ab:77:60:3b:43:65:21:cd:04:3d:01:71: + 99:47:28:12:c8:9d:f9:d7:25:7a:30:82:76:c0:27: + 5e:c3:70:42:54:2a:0a:02:97 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + Netscape Comment: + OpenSSL Generated Certificate + X509v3 Subject Key Identifier: + D5:2F:1A:60:8E:F9:2E:8F:51:EB:F7:AB:24:47:80:CE:B6:8D:F1:63 + X509v3 Authority Key Identifier: + keyid:96:9A:2D:06:F6:76:4F:83:68:7B:9C:69:C4:18:BB:4A:EB:46:38:E4 + + Signature Algorithm: sha1WithRSAEncryption + 7a:83:0c:a0:2d:14:52:97:a1:0e:dd:b3:2e:a1:1f:0d:51:e7: + 98:2e:89:9a:36:a3:1b:af:28:95:13:ab:3e:31:2e:f6:fa:5f: + f7:85:8c:01:7a:1b:25:63:7e:d6:f9:8e:ad:84:9e:42:3e:1d: + f4:ad:dc:b1:20:91:83:8b:48:ad:34:2a:b9:cc:ae:06:e6:bc: + e1:05:e6:35:71:ca:43:98:3a:e5:93:52:e1:3c:3a:1b:83:53: + d3:a6:ba:6a:43:38:00:92:ba:fb:8f:a8:17:46:f9:32:ac:42: + 47:87:7f:2e:ae:76:49:88:55:1e:65:70:6c:d6:35:ab:64:48: + a9:66 +-----BEGIN CERTIFICATE----- +MIICyzCCAjSgAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA0MB4XDTA5 +MTEyMDA4NDQwMVoXDTM0MTExNDA4NDQwMVowbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAxIFN1YiBDQSAxIFJvb3QgNDCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAw1WqG0/2tHi+rGEqkpRzGzlMDld+2ngD +fmURV5fm9A1yH/YrpDP5XL0rJWxYKXO5RtXb6QMdoviObsK1ley6lcOsLsC2QLoj +HXR1kczWOkwVTRUDpOaASpP+bJGrd2A7Q2UhzQQ9AXGZRygSyJ351yV6MIJ2wCde +w3BCVCoKApcCAwEAAaN9MHswCwYDVR0PBAQDAgXgMCwGCWCGSAGG+EIBDQQfFh1P +cGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQU1S8aYI75Lo9R +6/erJEeAzraN8WMwHwYDVR0jBBgwFoAUlpotBvZ2T4Noe5xpxBi7SutGOOQwDQYJ +KoZIhvcNAQEFBQADgYEAeoMMoC0UUpehDt2zLqEfDVHnmC6JmjajG68olROrPjEu +9vpf94WMAXobJWN+1vmOrYSeQj4d9K3csSCRg4tIrTQqucyuBua84QXmNXHKQ5g6 +5ZNS4Tw6G4NT06a6akM4AJK6+4+oF0b5MqxCR4d/Lq52SYhVHmVwbNY1q2RIqWY= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/newcerts/1001.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/newcerts/1001.pem new file mode 100644 index 0000000000..7068aa0afd --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/newcerts/1001.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4097 (0x1001) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 4 + Validity + Not Before: Nov 20 08:57:20 2009 GMT + Not After : Nov 14 08:57:20 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 2 Sub CA 1 Root 4 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:ab:2a:df:93:6c:f0:b1:34:54:15:5b:06:4e:15: + bb:94:53:89:96:96:47:db:43:49:e7:66:d5:6b:53: + eb:04:54:d0:96:48:08:8f:8e:cc:70:e1:62:88:6a: + f3:ff:bc:65:55:b9:55:a6:29:22:c1:f6:16:9a:01: + 25:86:a9:72:c8:7c:0f:29:87:b9:14:51:34:d2:fc: + 01:3e:20:46:dc:54:3f:f3:03:d8:07:e0:6b:0c:78: + 70:d0:d0:93:83:e2:cf:53:fc:3b:d5:b0:c9:7d:40: + 8b:ee:5d:d3:30:e9:24:01:1e:b0:ac:de:1a:18:97: + a1:0d:58:79:5e:67:cd:99:bf + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + Netscape Comment: + OpenSSL Generated Certificate + X509v3 Subject Key Identifier: + 47:DB:A7:93:38:C2:0F:34:7F:B7:DE:35:C9:23:75:CC:30:93:A4:42 + X509v3 Authority Key Identifier: + keyid:96:9A:2D:06:F6:76:4F:83:68:7B:9C:69:C4:18:BB:4A:EB:46:38:E4 + + Signature Algorithm: sha1WithRSAEncryption + 97:70:47:74:ce:e1:f6:51:bf:cc:cf:0f:cf:cc:23:75:df:4b: + 3d:36:f0:70:0f:47:5d:c7:96:ad:b0:78:95:89:3a:2a:7a:ba: + 79:45:fe:2f:37:4c:69:76:ab:0a:10:ea:0d:5e:fe:28:04:44: + 9c:f3:8d:43:f5:15:fa:79:be:d3:86:f3:c1:b5:8b:5a:74:a9: + c5:b7:fe:e8:63:6e:1f:13:3a:c9:49:3b:45:0c:a6:64:b9:07: + 9b:1a:30:09:1d:5e:f0:2b:a9:55:aa:41:fa:85:0d:ef:dd:c3: + f5:58:52:bf:7f:6d:f4:18:06:f4:5a:71:af:e4:57:b0:0a:6e: + f6:76 +-----BEGIN CERTIFICATE----- +MIICyzCCAjSgAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA0MB4XDTA5 +MTEyMDA4NTcyMFoXDTM0MTExNDA4NTcyMFowbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAyIFN1YiBDQSAxIFJvb3QgNDCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAqyrfk2zwsTRUFVsGThW7lFOJlpZH20NJ +52bVa1PrBFTQlkgIj47McOFiiGrz/7xlVblVpikiwfYWmgElhqlyyHwPKYe5FFE0 +0vwBPiBG3FQ/8wPYB+BrDHhw0NCTg+LPU/w71bDJfUCL7l3TMOkkAR6wrN4aGJeh +DVh5XmfNmb8CAwEAAaN9MHswCwYDVR0PBAQDAgXgMCwGCWCGSAGG+EIBDQQfFh1P +cGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUR9unkzjCDzR/ +t941ySN1zDCTpEIwHwYDVR0jBBgwFoAUlpotBvZ2T4Noe5xpxBi7SutGOOQwDQYJ +KoZIhvcNAQEFBQADgYEAl3BHdM7h9lG/zM8Pz8wjdd9LPTbwcA9HXceWrbB4lYk6 +Knq6eUX+LzdMaXarChDqDV7+KAREnPONQ/UV+nm+04bzwbWLWnSpxbf+6GNuHxM6 +yUk7RQymZLkHmxowCR1e8CupVapB+oUN793D9VhSv39t9BgG9Fpxr+RXsApu9nY= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/private/cakey.pem new file mode 100644 index 0000000000..4c3de720f9 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,48187111D008BD14 + +9y5tseMMq8fPCuUelw75mRr1ALSrxNWatiMrmFM44I27wxIlaVgePNk3ovpuUpjB +RTArkp0zqA8tHCE/ZzE0cKtkxabTfrghxeKb2lAIrIUFwAFnMPEoB69M23qKblQD +/CbYquy6mpjzLBYwM0Ub8fj4d6fMCJ29Mqlbzj9XJ2oif8zW90lxE4CZNGEWKWaO +pF0ytqUM0aVIBVXZOGmeUpJlAgwdshYHD0JwoULWzFOa+9aks+wjYwQcDxbPq3YC +TBSzHiKd68YSDvK5VevIAIrSKEEqrXgsnL0k23/xkK5ZN8w9gmROrwpqg78Aa/cp +13luMYMRAm+hBfCFzKXvc8hV49UCPWOJcB4/p8to8Bx95UcJ17npG71yrNJgwTA6 +Wgj4pxtddt4QItVqv6usIvkMwD4pQqZ4y+5UMEvw2paG428+SN6YElH6/6yB/9Cc +B7BxhhaazM+AEulpvvfQgjpIqn5+QyaZ7GVcNh/Bi66tenNv9NBVqP1PmuZUMF77 +QddQGzCpxaSb/x/3InhMP2PgGN37B9ezm8ee+AQpmk1VzJ5zpiuoGbQ3oLnDVMKS +aNe7VIyhovq7tnJIuIft8jOEMFfPot9vgIwnHVQ4PF+KK0bzWjSK+6HyO+1Jkw/5 +TpHfQSxEVf8brC8g9l7+FjGSbHF80EzOUx1lMDe/BUzuVvRhiewqrlkCrPf90uuy +hEf1UKqrDK2i2iLBzZ0+OXba3wj20jFRaYLN5YykE6fKo/H6UjEn203nMI2Qi+2m +5j5dgDAOXnNWQN45MxIMu6xxPSaEcb8YUgfMqwytfVmo/xSioyoV+w== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/serial new file mode 100644 index 0000000000..7d802a3e71 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/serial @@ -0,0 +1 @@ +1002 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/openssl.cfg new file mode 100644 index 0000000000..51e5205253 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/README.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/README.txt new file mode 100644 index 0000000000..b266749a9e --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/README.txt @@ -0,0 +1,5 @@ +To provide the CRL via HTTP run + +java -jar ../../tools/httpserv/dist/httpserv.jar -a 8902 + + diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/cacert.pem new file mode 100644 index 0000000000..b350f6eb33 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/cacert.pem @@ -0,0 +1,66 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4097 (0x1001) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 5 + Validity + Not Before: Nov 20 11:30:23 2009 GMT + Not After : Nov 14 11:30:23 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 5 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:97:fa:a2:49:d3:bf:c1:2e:7a:ed:83:83:3c:78: + 96:c8:b2:b9:67:af:c0:5e:0a:89:89:fb:94:59:32: + a8:2a:e4:20:2f:3b:3d:ce:53:4f:72:fc:6c:0b:93: + 38:c3:df:66:6e:d5:79:d0:a4:4e:41:84:43:3c:99: + 79:0c:e0:5f:19:1a:3d:f5:4b:11:28:0f:80:b0:a0: + 71:34:5b:90:71:c2:ef:1e:85:2e:5b:9f:3b:22:c3: + 18:f8:7c:1f:ef:1b:78:17:a0:44:60:46:7e:88:eb: + a7:60:a0:5c:2a:7c:37:99:fa:27:97:08:e8:89:ba: + bc:69:4b:79:93:8f:ad:b5:9b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 01:E9:B5:99:E4:6D:F9:8C:42:3D:09:10:0F:A7:75:C6:27:78:4A:AF + X509v3 Authority Key Identifier: + keyid:C1:D1:A0:D4:5B:0B:9D:7E:31:61:F9:39:10:9F:31:10:E0:D2:06:B5 + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 5 + serial:F0:3D:B6:A9:A9:9C:A3:4E + + X509v3 CRL Distribution Points: + URI:http://localhost:8901/demoCA/crl/Root_5.crl + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 6d:ca:34:05:99:ff:99:49:d3:6d:9d:ad:c6:99:da:9d:6c:94: + 62:77:ed:1c:39:23:d2:e8:b6:3e:df:63:dc:7c:10:3f:c2:ed: + f4:04:26:58:05:01:4c:ed:a9:83:43:3a:5d:fe:60:6d:5b:58: + dc:93:8c:94:69:b6:7f:02:48:30:9c:31:f4:7d:de:e0:de:04: + d2:dc:79:b7:60:c2:87:f7:c7:92:a2:f5:86:a7:0c:70:3b:a3: + a7:35:11:cf:a4:28:21:aa:8b:24:50:2e:96:41:be:66:01:bd: + b9:ec:04:0c:92:d9:8a:e7:a0:96:24:9b:f1:a2:9f:59:59:4a: + 32:a4 +-----BEGIN CERTIFICATE----- +MIIDRjCCAq+gAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA1MB4XDTA5MTEyMDExMzAy +M1oXDTM0MTExNDExMzAyM1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA1MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQCX+qJJ07/BLnrtg4M8eJbIsrlnr8BeComJ+5RZMqgq5CAvOz3OU09y +/GwLkzjD32Zu1XnQpE5BhEM8mXkM4F8ZGj31SxEoD4CwoHE0W5Bxwu8ehS5bnzsi +wxj4fB/vG3gXoERgRn6I66dgoFwqfDeZ+ieXCOiJurxpS3mTj621mwIDAQABo4IB +BjCCAQIwHQYDVR0OBBYEFAHptZnkbfmMQj0JEA+ndcYneEqvMIGRBgNVHSMEgYkw +gYaAFMHRoNRbC51+MWH5ORCfMRDg0ga1oWOkYTBfMQswCQYDVQQGEwJERTEQMA4G +A1UECBMHSGFtYnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsT +C0RldmVsb3BtZW50MQ8wDQYDVQQDEwZSb290IDWCCQDwPbapqZyjTjA8BgNVHR8E +NTAzMDGgL6AthitodHRwOi8vbG9jYWxob3N0Ojg5MDEvZGVtb0NBL2NybC9Sb290 +XzUuY3JsMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAbco0BZn/ +mUnTbZ2txpnanWyUYnftHDkj0ui2Pt9j3HwQP8Lt9AQmWAUBTO2pg0M6Xf5gbVtY +3JOMlGm2fwJIMJwx9H3e4N4E0tx5t2DCh/fHkqL1hqcMcDujpzURz6QoIaqLJFAu +lkG+ZgG9uewEDJLZiuegliSb8aKfWVlKMqQ= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/crl/DO_NOT_INSTALL_THIS_CRL b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/crl/DO_NOT_INSTALL_THIS_CRL new file mode 100644 index 0000000000..e69de29bb2 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 new file mode 100644 index 0000000000..3aec2bba1d Binary files /dev/null and b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/crl/Sub_CA_1_Root_5.crl differ diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/crlnumber new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/crlnumber @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/index.txt new file mode 100644 index 0000000000..2f83d6f9b7 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/index.txt @@ -0,0 +1 @@ +V 341114113322Z 1002 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 1 Root 5 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/index.txt.attr new file mode 100644 index 0000000000..8f7e63a347 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/newcerts/1002.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/newcerts/1002.pem new file mode 100644 index 0000000000..59d5f7a2b4 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/newcerts/1002.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4098 (0x1002) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 5 + Validity + Not Before: Nov 20 11:33:22 2009 GMT + Not After : Nov 14 11:33:22 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 1 Root 5 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:d3:fd:a7:4f:ea:02:e2:b4:32:80:3f:64:bb:37: + 9d:9e:fa:86:b2:25:b3:1d:f6:5d:05:8e:2b:0c:bd: + 60:1e:e6:52:39:4c:84:9e:93:6c:d2:b4:2d:34:1a: + e7:42:b6:bf:34:bd:ca:44:31:fb:06:5e:20:0a:a1: + 22:ca:9b:4f:01:57:bd:b1:30:57:a9:0f:fc:06:ae: + 18:6c:2d:9e:70:7a:21:2a:fd:0c:f8:03:00:32:60: + 5d:37:c5:11:56:74:30:e4:03:3c:88:71:d5:79:d3: + 76:02:e1:85:87:63:4b:5b:cd:c9:1f:ca:85:7a:8c: + 3a:fd:a9:83:94:b9:6d:f6:95 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 CRL Distribution Points: + URI:http://localhost:8902/demoCA/crl/Sub_CA_1_Root_5.crl + + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + E0:53:2E:E4:6B:0B:99:C0:AD:C1:02:40:46:6C:35:EE:49:73:5D:0B + X509v3 Authority Key Identifier: + keyid:01:E9:B5:99:E4:6D:F9:8C:42:3D:09:10:0F:A7:75:C6:27:78:4A:AF + + Signature Algorithm: sha1WithRSAEncryption + 5f:6a:81:3b:56:e8:6d:33:0e:1e:6a:73:b1:e8:69:b7:3f:83: + 81:6c:73:7c:9d:f7:12:c9:bf:99:16:cf:56:38:e4:58:db:28: + a5:9c:e3:8e:ed:27:d2:da:53:41:80:2a:d4:c3:92:5d:b5:b4: + 5a:d6:17:f7:74:9d:83:13:06:7f:20:8e:50:5f:60:5b:3a:9a: + 9f:c2:58:5f:fa:07:90:df:a0:02:cf:c4:d7:7d:2e:b7:72:df: + 8f:93:ce:5a:b3:17:ba:73:93:20:64:b9:b2:ad:6e:89:63:c5: + 08:e1:a0:6a:b2:9d:1e:33:31:83:98:d1:05:7d:ec:48:72:1f: + dd:60 +-----BEGIN CERTIFICATE----- +MIIC5jCCAk+gAwIBAgICEAIwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA1MB4XDTA5 +MTEyMDExMzMyMloXDTM0MTExNDExMzMyMlowbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAxIFN1YiBDQSAxIFJvb3QgNTCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0/2nT+oC4rQygD9kuzednvqGsiWzHfZd +BY4rDL1gHuZSOUyEnpNs0rQtNBrnQra/NL3KRDH7Bl4gCqEiyptPAVe9sTBXqQ/8 +Bq4YbC2ecHohKv0M+AMAMmBdN8URVnQw5AM8iHHVedN2AuGFh2NLW83JH8qFeow6 +/amDlLlt9pUCAwEAAaOBlzCBlDBFBgNVHR8EPjA8MDqgOKA2hjRodHRwOi8vbG9j +YWxob3N0Ojg5MDIvZGVtb0NBL2NybC9TdWJfQ0FfMV9Sb290XzUuY3JsMAsGA1Ud +DwQEAwIF4DAdBgNVHQ4EFgQU4FMu5GsLmcCtwQJARmw17klzXQswHwYDVR0jBBgw +FoAUAem1meRt+YxCPQkQD6d1xid4Sq8wDQYJKoZIhvcNAQEFBQADgYEAX2qBO1bo +bTMOHmpzsehptz+DgWxzfJ33Esm/mRbPVjjkWNsopZzjju0n0tpTQYAq1MOSXbW0 +WtYX93SdgxMGfyCOUF9gWzqan8JYX/oHkN+gAs/E130ut3Lfj5POWrMXunOTIGS5 +sq1uiWPFCOGgarKdHjMxg5jRBX3sSHIf3WA= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/private/cakey.pem new file mode 100644 index 0000000000..fb9af1caa3 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,30B50FFE9747C5F2 + +pXO59gJmBcDztjZDwRRcJV+m/BBdF/NlI0WD7WBr4vR663B6hZw0hqAkCn3o0VbO +DzLsoQUMUv/70aXc2SgvS8LleG+mWCkPE+huzFjPAn6Z6+p0MhHrYRJ7iulPAVV0 ++wCs8+1UbvKyozLy+BfvEwGHEho8sr3w81y2noE2pjaQOE1JGKY91VnFz1yPhYHC +r26sO1DqoqtWS8XSe2FdREG/guKpoHtoUazQhCkgeBk18OImKlrxp1pT/haObv5i +5qILjSvMBjmrTCJDi1vgShEiAZTE318ipK5wCLKiA6UvZ3GMxb2xjy+na3CUTrzf +AAefrW4NaoyIWI8dRtPxFic678ZgqcRMdMW7BgdffLXX5IueCqHeTNS7xcr2T2gd +hzKxinZnY8MQosFeyzP3fYWxv5PY54HNmCnsN2SXJSOq+CPSsIvbDR5p1bhrcEf9 +1O815NhJTx2nPAkIC+7bemAkz2f3g09SuhtQTaCnZMwcAmnMAT0ewWJSxDCVOg5s +B/OPe8RJ1tiO7DnaZH6RQDPUCKaUgS9xSzCu1q0IWWbzUWioPIX13fFlvl9gAxbY ++FI6dD2DwHBTyiPLLyT7FBfwjnHul2zSn/jXnby7n1sILQIP0AQK0cJDS1ZdC2CB +oe4gwzSVCxp7v3Zfp1ZoyYOtei0gT6+bDvjBYsl90jyvyucWfKjlZiEauQV8gSOQ +G2iY5QZ0clAFg7MQKmHuTaAALk0IrauSW20eR/HF0/2R6xCt91zcyhwbOiZFNyQ3 +gtvwLu9ZzAHfWcnIEWxpYF68O+vj+g6Jpl/q6j8KaTta3smEBzgpow== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/serial new file mode 100644 index 0000000000..baccd0398f --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/serial @@ -0,0 +1 @@ +1003 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/openssl.cfg new file mode 100644 index 0000000000..963ab884f6 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ +crlDistributionPoints=URI:http://localhost:8902/demoCA/crl/Sub_CA_1_Root_5.crl +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +#nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/cacert.pem new file mode 100644 index 0000000000..0490b88cd7 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/cacert.pem @@ -0,0 +1,66 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4097 (0x1001) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 6 + Validity + Not Before: Nov 20 12:28:07 2009 GMT + Not After : Nov 14 12:28:07 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 6 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:c4:d9:ab:27:06:66:41:0e:36:ff:d4:b1:d0:8c: + f7:b4:25:55:cd:fd:fa:a4:5a:e6:4f:d0:05:dc:a3: + e5:bd:8d:53:77:d1:ea:95:5a:52:81:c8:b6:36:a0: + 5f:3a:e1:85:1e:8a:48:91:7d:29:78:ff:ea:c5:e3: + ad:c4:27:d5:b7:8f:59:20:26:d4:45:87:6a:56:db: + ac:f5:f8:0a:88:82:9e:c2:00:06:fc:98:8a:fe:35: + c3:02:a1:67:08:06:42:e3:88:48:e0:8f:33:ff:f8: + a4:87:1a:3a:d9:54:0e:1c:09:3e:a0:f0:70:cd:b5: + b0:b2:7e:07:73:ad:20:64:69 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 89:8C:D7:71:EB:67:78:4E:D6:01:35:B2:AC:A1:B4:88:43:CE:70:A7 + X509v3 Authority Key Identifier: + keyid:AC:25:5E:9B:B5:BA:4D:8E:BD:77:B2:9D:D9:E2:84:AE:7A:31:8F:F2 + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 6 + serial:D8:6A:4F:24:F9:C9:94:27 + + X509v3 CRL Distribution Points: + URI:http://localhost:8901/demoCA/crl/Root_6.crl + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 55:5b:3b:6b:8a:d0:1b:d8:19:d9:96:85:4d:b4:a0:98:b1:bd: + 9f:0b:62:21:92:8b:4e:d3:d0:1b:91:3d:e3:f5:bd:ce:16:57: + fc:b7:84:15:51:fd:98:ab:32:59:28:0b:44:57:49:ec:ac:11: + 67:26:7a:a3:c5:b8:9d:2a:de:b6:7c:76:0a:e9:18:9f:98:87: + e8:80:c8:72:99:56:74:ab:73:1b:f4:e7:b9:b1:3a:f3:7b:0d: + 2f:5d:82:6c:d1:99:9f:23:be:23:fb:4c:0e:15:5e:f5:9f:90: + 88:d7:51:3a:6a:7a:f0:54:a5:c4:89:a5:0d:0a:4e:94:59:64: + 59:54 +-----BEGIN CERTIFICATE----- +MIIDRjCCAq+gAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA2MB4XDTA5MTEyMDEyMjgw +N1oXDTM0MTExNDEyMjgwN1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA2MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDE2asnBmZBDjb/1LHQjPe0JVXN/fqkWuZP0AXco+W9jVN30eqVWlKB +yLY2oF864YUeikiRfSl4/+rF463EJ9W3j1kgJtRFh2pW26z1+AqIgp7CAAb8mIr+ +NcMCoWcIBkLjiEjgjzP/+KSHGjrZVA4cCT6g8HDNtbCyfgdzrSBkaQIDAQABo4IB +BjCCAQIwHQYDVR0OBBYEFImM13HrZ3hO1gE1sqyhtIhDznCnMIGRBgNVHSMEgYkw +gYaAFKwlXpu1uk2OvXeyndnihK56MY/yoWOkYTBfMQswCQYDVQQGEwJERTEQMA4G +A1UECBMHSGFtYnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsT +C0RldmVsb3BtZW50MQ8wDQYDVQQDEwZSb290IDaCCQDYak8k+cmUJzA8BgNVHR8E +NTAzMDGgL6AthitodHRwOi8vbG9jYWxob3N0Ojg5MDEvZGVtb0NBL2NybC9Sb290 +XzYuY3JsMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAVVs7a4rQ +G9gZ2ZaFTbSgmLG9nwtiIZKLTtPQG5E94/W9zhZX/LeEFVH9mKsyWSgLRFdJ7KwR +ZyZ6o8W4nSretnx2CukYn5iH6IDIcplWdKtzG/TnubE683sNL12CbNGZnyO+I/tM +DhVe9Z+QiNdROmp68FSlxImlDQpOlFlkWVQ= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/crl/DO_NOT_CREATE_A_CRL b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/crl/DO_NOT_CREATE_A_CRL new file mode 100644 index 0000000000..e69de29bb2 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/crlnumber new file mode 100644 index 0000000000..83b33d238d --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/crlnumber @@ -0,0 +1 @@ +1000 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/index.txt new file mode 100644 index 0000000000..6e4d7577df --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/index.txt @@ -0,0 +1 @@ +V 341114123743Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 1 Root 6 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/index.txt.attr new file mode 100644 index 0000000000..8f7e63a347 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/newcerts/1000.pem new file mode 100644 index 0000000000..538cb4e0bf --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/newcerts/1000.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 6 + Validity + Not Before: Nov 20 12:37:43 2009 GMT + Not After : Nov 14 12:37:43 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 1 Root 6 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:bb:ac:68:10:41:28:94:fd:fe:39:5e:63:cf:eb: + 9f:2b:20:82:f3:86:d2:e1:38:05:7e:95:cc:46:e5: + 42:8b:5c:0d:2c:ad:ad:44:c0:4c:2f:7c:75:e8:bd: + aa:cd:f2:05:16:18:a5:a3:fa:e7:a0:ba:57:31:e2: + b0:4d:85:9d:60:e4:41:92:49:3f:e1:79:47:52:e8: + 9e:71:be:88:10:6c:30:89:9f:55:84:9d:83:d0:c9: + 11:66:95:33:8b:44:38:86:45:05:b3:3a:54:c4:cf: + 4e:72:4c:00:07:d7:59:3a:8d:2f:cd:5e:0c:a0:95: + be:00:85:7a:a4:42:c2:f3:b7 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 CRL Distribution Points: + URI:http://localhost:8902/demoCA/crl/Sub_CA_1_Root_6.crl + + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 57:51:A4:44:AE:92:01:3C:9F:7E:82:67:C0:E5:B9:D7:A6:8F:A5:79 + X509v3 Authority Key Identifier: + keyid:89:8C:D7:71:EB:67:78:4E:D6:01:35:B2:AC:A1:B4:88:43:CE:70:A7 + + Signature Algorithm: sha1WithRSAEncryption + 7b:de:f2:2b:d7:94:ce:12:e2:f9:a7:b2:91:08:c6:51:3f:bc: + e2:87:ed:79:6d:3b:f5:38:6e:02:d4:63:e6:b8:a7:e5:df:f4: + 6e:b0:8a:bd:bb:b1:0b:e0:c2:cf:fa:af:0a:6a:a5:1f:28:ff: + de:21:bd:8a:f7:ec:48:35:bb:ab:97:c2:7a:31:6d:d1:73:8e: + ae:74:9b:94:86:73:06:06:da:6a:2c:82:04:b1:49:19:62:a9: + 05:e5:e7:2c:68:a1:3b:f4:bf:80:85:5b:1b:dc:21:7b:3d:c1: + ee:97:6c:72:35:2d:80:19:90:b4:ab:19:34:bb:88:5e:ea:70: + 27:df +-----BEGIN CERTIFICATE----- +MIIC5jCCAk+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA2MB4XDTA5 +MTEyMDEyMzc0M1oXDTM0MTExNDEyMzc0M1owbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAxIFN1YiBDQSAxIFJvb3QgNjCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAu6xoEEEolP3+OV5jz+ufKyCC84bS4TgF +fpXMRuVCi1wNLK2tRMBML3x16L2qzfIFFhilo/rnoLpXMeKwTYWdYORBkkk/4XlH +Uuiecb6IEGwwiZ9VhJ2D0MkRZpUzi0Q4hkUFszpUxM9OckwAB9dZOo0vzV4MoJW+ +AIV6pELC87cCAwEAAaOBlzCBlDBFBgNVHR8EPjA8MDqgOKA2hjRodHRwOi8vbG9j +YWxob3N0Ojg5MDIvZGVtb0NBL2NybC9TdWJfQ0FfMV9Sb290XzYuY3JsMAsGA1Ud +DwQEAwIF4DAdBgNVHQ4EFgQUV1GkRK6SATyffoJnwOW516aPpXkwHwYDVR0jBBgw +FoAUiYzXcetneE7WATWyrKG0iEPOcKcwDQYJKoZIhvcNAQEFBQADgYEAe97yK9eU +zhLi+aeykQjGUT+84ofteW079ThuAtRj5rin5d/0brCKvbuxC+DCz/qvCmqlHyj/ +3iG9ivfsSDW7q5fCejFt0XOOrnSblIZzBgbaaiyCBLFJGWKpBeXnLGihO/S/gIVb +G9whez3B7pdscjUtgBmQtKsZNLuIXupwJ98= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/private/cakey.pem new file mode 100644 index 0000000000..9912ee0880 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,8F1C89446B1EC221 + +joSSrVc7E1RavSuMdWDDAozXOV4Z0XIusMv5NjIWHLyKdW/SmFv6yfPy7PeuK1Qj +p/DuEO/ULU6SLmAhESXrdC8UzyL/B3hfPK3UzUzJzIRrDitF21SXLjMKU+KVxMrb +GkmstfsIQM157TZHOHJbk4F9zs9Xkl8ipKYDBpJrtVJo8gf4SeLfcEVXW9J0tlLU +Qi13SWWn4kGK+Latypx684S247Y0JfKSJ5BVHUGunmd+b/3mRpH1WARU03JmNqG9 +tyCJxyvCkkQh5Jnm4UEI72ywxSscemtFAzd5fa5LOrsVWOImSixfP1VdJvU0jCTv +gyXK03e/L+B+DhbUm2a6xkt+u83hQ2QjoGdmnfKwhX4vdYZBYINlBnHtHn2B8x2o +IXgLQmBFO/heY/K9wJ1BwwqPW31wHG3MhjRY7ooac1JAZsxS0/pU8cR/GNMpKjvE +fer3tGGUvPL3H1v3pT2XAA4Gm9pOtvnOHuLjbzg2mgNZScYMpcqa/vaQ5gXqCnhw +dtFrGVxEEQ5jTL23EAh4WfhPvsnewujr7Rkc6+a8xKpDJOHejgAPJYpXrYHg4poA +L0aQlIFSX1jriGu4KYAQiZO7bouhVWqcf9B3BNewr0kTaD7qq0gDvygCKLyrUyb7 +hqk0TwVfvmk7nYNFLBsTEcsB/el6jqH40oOfFo+ErlQzmdzRrKy9gBEaecDj8DxV +Fa8XPapE81O8WjS09a/WJNPW+3NdrI5wYMg72srOW8ll+AMtiUTWrAY2hIRxzZGt +VntCKwG/3j0v60jg+0wCP+l/IV4pPbV4He3ysxwM6lH1Y86XfaUBiA== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/serial new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/serial @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/openssl.cfg new file mode 100644 index 0000000000..188ed62e2a --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ +crlDistributionPoints=URI:http://localhost:8902/demoCA/crl/Sub_CA_1_Root_6.crl +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +#nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/README.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/README.txt new file mode 100644 index 0000000000..d70e0550a9 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/README.txt @@ -0,0 +1,3 @@ +To provide the CRL run: + +java -jar ../../tools/httpserv/dist/httpserv.jar -a 8902 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/cacert.pem new file mode 100644 index 0000000000..2dda8f2b28 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/cacert.pem @@ -0,0 +1,66 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 7 + Validity + Not Before: Nov 20 13:07:53 2009 GMT + Not After : Nov 14 13:07:53 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 7 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:b0:ae:6d:0a:21:ae:8a:92:b1:16:25:d3:08:cb: + ac:b7:4c:53:6d:4b:b3:12:82:40:54:c9:44:28:fc: + 4e:10:e6:65:40:de:70:5d:8b:ab:1f:5c:77:03:43: + 3d:3a:3d:9e:f7:37:66:9a:33:68:a0:cf:ad:8f:f4: + fb:9c:a3:87:57:5d:ec:d6:55:5a:18:b5:e1:2b:d2: + c4:10:fe:f0:01:a5:da:29:ee:c4:af:15:c9:8c:dc: + 7c:45:84:bd:e5:5b:09:1f:16:1d:11:e7:61:e6:22: + e7:1f:c8:86:bf:a1:da:cb:fe:6b:7e:c0:6e:aa:7f: + 97:84:e8:8f:81:69:f1:26:87 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 54:64:15:7E:93:8A:19:C8:F9:B7:EF:60:A0:DF:5C:C8:15:56:C0:EE + X509v3 Authority Key Identifier: + keyid:80:C6:F8:0B:5F:7C:49:E4:86:FD:C8:92:C6:80:70:D9:C0:6F:7B:DE + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 7 + serial:D5:E6:63:5F:18:09:82:89 + + X509v3 CRL Distribution Points: + URI:http://localhost:8901/demoCA/crl/Root_7.crl + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 1a:bc:5a:4b:9a:d5:e8:c0:35:c2:61:0a:58:7d:33:e2:87:01: + 61:83:80:42:8d:1a:7e:b1:9a:58:d5:01:fd:e7:ae:5c:c8:65: + fb:9e:1d:bf:49:ba:ed:40:f4:05:7c:3b:2d:db:0e:53:d0:05: + a0:bd:15:87:c4:37:22:0b:a0:04:a3:ad:cb:57:b2:00:97:ee: + 8f:89:91:8e:7d:0b:e2:27:96:6e:0f:ab:73:33:59:fa:9f:37: + f2:77:79:99:af:72:ad:f9:49:05:ed:55:08:31:eb:97:0f:99: + 6e:9c:a3:df:f0:52:1a:14:4e:78:25:0c:8b:02:cb:56:e9:4d: + f5:9f +-----BEGIN CERTIFICATE----- +MIIDRjCCAq+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA3MB4XDTA5MTEyMDEzMDc1 +M1oXDTM0MTExNDEzMDc1M1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA3MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQCwrm0KIa6KkrEWJdMIy6y3TFNtS7MSgkBUyUQo/E4Q5mVA3nBdi6sf +XHcDQz06PZ73N2aaM2igz62P9Puco4dXXezWVVoYteEr0sQQ/vABpdop7sSvFcmM +3HxFhL3lWwkfFh0R52HmIucfyIa/odrL/mt+wG6qf5eE6I+BafEmhwIDAQABo4IB +BjCCAQIwHQYDVR0OBBYEFFRkFX6TihnI+bfvYKDfXMgVVsDuMIGRBgNVHSMEgYkw +gYaAFIDG+AtffEnkhv3IksaAcNnAb3veoWOkYTBfMQswCQYDVQQGEwJERTEQMA4G +A1UECBMHSGFtYnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsT +C0RldmVsb3BtZW50MQ8wDQYDVQQDEwZSb290IDeCCQDV5mNfGAmCiTA8BgNVHR8E +NTAzMDGgL6AthitodHRwOi8vbG9jYWxob3N0Ojg5MDEvZGVtb0NBL2NybC9Sb290 +XzcuY3JsMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAGrxaS5rV +6MA1wmEKWH0z4ocBYYOAQo0afrGaWNUB/eeuXMhl+54dv0m67UD0BXw7LdsOU9AF +oL0Vh8Q3IgugBKOty1eyAJfuj4mRjn0L4ieWbg+rczNZ+p838nd5ma9yrflJBe1V +CDHrlw+Zbpyj3/BSGhROeCUMiwLLVulN9Z8= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/crl/DO_NOT_INSTALL_THIS_CRL b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/crl/DO_NOT_INSTALL_THIS_CRL new file mode 100644 index 0000000000..e69de29bb2 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 new file mode 100644 index 0000000000..f3f7e5cba2 Binary files /dev/null and b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/crl/Sub_CA_1_Root_7.crl differ diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/crlnumber new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/crlnumber @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/index.txt new file mode 100644 index 0000000000..8bcb130f6c --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/index.txt @@ -0,0 +1,2 @@ +V 341114131904Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 1 Root 7 +R 341114132648Z 091120132827Z,CACompromise 1001 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 2 Sub CA 1 Root 7 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/index.txt.attr new file mode 100644 index 0000000000..8f7e63a347 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/newcerts/1000.pem new file mode 100644 index 0000000000..234638d8ce --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/newcerts/1000.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 7 + Validity + Not Before: Nov 20 13:19:04 2009 GMT + Not After : Nov 14 13:19:04 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 1 Root 7 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:ce:23:98:19:ac:0d:7c:f0:60:a2:94:72:c3:ab: + a5:a1:6b:d3:af:8c:cb:b9:c9:ee:0b:3e:a4:2e:0e: + 08:a5:a9:4c:09:2f:1a:a0:fe:87:89:41:4a:aa:b6: + ac:b4:bc:d3:0e:f9:c3:12:1f:b1:90:b3:6d:72:a6: + 38:5b:9d:05:7e:97:ff:f4:e1:31:2b:b4:08:de:b1: + 43:fe:1d:7e:32:54:ce:db:d5:14:21:f3:ad:9f:26: + f3:c6:0b:77:51:e4:11:88:ad:86:e1:30:d1:af:87: + 29:c0:7b:92:db:68:06:74:ca:27:ac:0b:61:3a:ac: + ba:03:35:e7:8e:08:28:58:7d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 CRL Distribution Points: + URI:http://localhost:8902/demoCA/crl/Sub_CA_1_Root_7.crl + + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + DE:66:84:E4:9B:BF:70:00:BD:60:3D:34:45:96:FE:FD:D5:88:9B:CD + X509v3 Authority Key Identifier: + keyid:54:64:15:7E:93:8A:19:C8:F9:B7:EF:60:A0:DF:5C:C8:15:56:C0:EE + + Signature Algorithm: sha1WithRSAEncryption + 6e:da:66:d2:3b:00:d6:0b:5a:9f:21:28:de:e1:10:fe:fd:26: + db:a6:75:86:74:47:e4:b0:b7:c4:c1:dc:43:82:51:71:00:8f: + bf:71:9a:23:db:2d:79:27:a2:80:2e:12:a4:5f:13:0c:73:53: + 1e:5c:33:6a:e9:31:be:e2:ae:4f:55:b0:e8:0a:0f:54:f0:3a: + 7e:14:41:d7:34:18:58:90:26:63:7d:2c:1a:ab:93:7f:4a:3d: + 5e:cf:f1:9d:c3:76:ee:a4:76:1c:d8:f9:d0:ac:53:3c:1a:4d: + c7:fa:b6:23:54:4b:04:a1:e2:76:a5:e3:0d:b8:db:8e:d3:39: + c2:65 +-----BEGIN CERTIFICATE----- +MIIC5jCCAk+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA3MB4XDTA5 +MTEyMDEzMTkwNFoXDTM0MTExNDEzMTkwNFowbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAxIFN1YiBDQSAxIFJvb3QgNzCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAziOYGawNfPBgopRyw6uloWvTr4zLucnu +Cz6kLg4IpalMCS8aoP6HiUFKqrastLzTDvnDEh+xkLNtcqY4W50Ffpf/9OExK7QI +3rFD/h1+MlTO29UUIfOtnybzxgt3UeQRiK2G4TDRr4cpwHuS22gGdMonrAthOqy6 +AzXnjggoWH0CAwEAAaOBlzCBlDBFBgNVHR8EPjA8MDqgOKA2hjRodHRwOi8vbG9j +YWxob3N0Ojg5MDIvZGVtb0NBL2NybC9TdWJfQ0FfMV9Sb290XzcuY3JsMAsGA1Ud +DwQEAwIF4DAdBgNVHQ4EFgQU3maE5Ju/cAC9YD00RZb+/dWIm80wHwYDVR0jBBgw +FoAUVGQVfpOKGcj5t+9goN9cyBVWwO4wDQYJKoZIhvcNAQEFBQADgYEAbtpm0jsA +1gtanyEo3uEQ/v0m26Z1hnRH5LC3xMHcQ4JRcQCPv3GaI9steSeigC4SpF8TDHNT +HlwzaukxvuKuT1Ww6AoPVPA6fhRB1zQYWJAmY30sGquTf0o9Xs/xncN27qR2HNj5 +0KxTPBpNx/q2I1RLBKHidqXjDbjbjtM5wmU= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/newcerts/1001.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/newcerts/1001.pem new file mode 100644 index 0000000000..ddc504d77c --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/newcerts/1001.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4097 (0x1001) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 7 + Validity + Not Before: Nov 20 13:26:48 2009 GMT + Not After : Nov 14 13:26:48 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 2 Sub CA 1 Root 7 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:b3:58:b2:22:45:b9:37:83:e5:a4:6f:5d:4e:59: + 60:60:4e:46:26:27:9a:70:4d:34:89:cf:cb:4f:4f: + 0b:22:6e:e4:21:e6:ab:c9:0a:4a:c4:cd:6f:3c:db: + e8:a3:52:55:2d:26:1d:13:9a:8b:cf:38:25:4e:4f: + 4a:e3:39:01:fa:5b:10:a5:3e:e1:93:65:19:ca:8b: + 5c:9f:e8:19:ed:0a:ef:47:e9:11:73:28:ce:b0:95: + 10:3a:ce:b5:46:89:79:a3:90:ea:d5:ca:ac:c9:af: + ee:55:0d:6c:32:5f:d2:f1:76:1c:b9:e7:d2:ac:07: + 61:83:82:c5:95:5a:62:ff:67 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 CRL Distribution Points: + URI:http://localhost:8902/demoCA/crl/Sub_CA_1_Root_7.crl + + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 12:7A:7A:69:C5:FE:E0:23:FD:8E:51:25:55:94:9F:C8:44:D8:F2:29 + X509v3 Authority Key Identifier: + keyid:54:64:15:7E:93:8A:19:C8:F9:B7:EF:60:A0:DF:5C:C8:15:56:C0:EE + + Signature Algorithm: sha1WithRSAEncryption + 4a:57:08:6a:66:af:b4:05:4f:b3:4c:39:23:2b:5d:c9:88:7b: + 6f:b5:28:a3:5a:72:e6:0b:e2:9e:64:65:ce:8f:b5:31:0f:5f: + c7:b7:56:96:4f:d3:34:65:1a:ea:84:60:2b:fe:27:1f:75:fd: + 0f:53:e5:eb:25:d3:f6:2c:21:72:59:40:32:ba:ec:72:cc:64: + d6:1d:db:cf:ca:ec:91:0a:81:ef:f5:e4:56:31:a3:c2:9a:1d: + e9:5c:48:b0:7c:7b:e2:51:35:33:ad:a8:5c:79:ac:ee:bf:42: + fa:0b:a0:02:72:cc:5e:07:c0:d4:d3:96:26:16:3e:8c:32:8d: + b4:09 +-----BEGIN CERTIFICATE----- +MIIC5jCCAk+gAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA3MB4XDTA5 +MTEyMDEzMjY0OFoXDTM0MTExNDEzMjY0OFowbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAyIFN1YiBDQSAxIFJvb3QgNzCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAs1iyIkW5N4PlpG9dTllgYE5GJieacE00 +ic/LT08LIm7kIearyQpKxM1vPNvoo1JVLSYdE5qLzzglTk9K4zkB+lsQpT7hk2UZ +yotcn+gZ7QrvR+kRcyjOsJUQOs61Rol5o5Dq1cqsya/uVQ1sMl/S8XYcuefSrAdh +g4LFlVpi/2cCAwEAAaOBlzCBlDBFBgNVHR8EPjA8MDqgOKA2hjRodHRwOi8vbG9j +YWxob3N0Ojg5MDIvZGVtb0NBL2NybC9TdWJfQ0FfMV9Sb290XzcuY3JsMAsGA1Ud +DwQEAwIF4DAdBgNVHQ4EFgQUEnp6acX+4CP9jlElVZSfyETY8ikwHwYDVR0jBBgw +FoAUVGQVfpOKGcj5t+9goN9cyBVWwO4wDQYJKoZIhvcNAQEFBQADgYEASlcIamav +tAVPs0w5IytdyYh7b7Uoo1py5gvinmRlzo+1MQ9fx7dWlk/TNGUa6oRgK/4nH3X9 +D1Pl6yXT9iwhcllAMrrscsxk1h3bz8rskQqB7/XkVjGjwpod6VxIsHx74lE1M62o +XHms7r9C+gugAnLMXgfA1NOWJhY+jDKNtAk= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/private/cakey.pem new file mode 100644 index 0000000000..c107913a2f --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,D710D797627524D4 + +SC46mzOOSpNMZ9t2F3syLy0MmYOk3zBJnY/qcm/ggD4ETOse6zGpqhXVSeZdn3OG +Uwj+b9tCjVC/7GMWanH4DmshCv89IRljMyy5DShsOVmgAr0hqLZNlkKqQRRRHC4d +y9ozYq1J9Zcj16jTmCbpPJW8Ul7kblelNbD0nVgJABc6m6Di/syCFEC0KVGmoJZv +5QjxyNiulh0UNmmP+X6iEGPWw4s5JJdcAg5DFXjPiCvvGazvjCGTT38Hcnya4GkB +9aHo7KbjFU4P98zQKUAV0fSVU7+tzJrLxH0aefenbkIKI45xegOTJmcv8NEZ3YgQ +64r+OlmqOONmvcWrtUdhADvsl8oJ8Lz+1UYcyPpbYLUvMhj8Potf6C6rCz1GuQPS +EmGPltUAOcaylpnP/neyuErAMHGQI9Mn2dhLc/NGK6gxqZi1SawGbrit7Uv5il/n +O3zc7D+d1Jmdkcqm/BZKsMW5hwM3KF4gzb6zMe/8ZCmtqT4iH4eDqjFQfaWeBXNK +kTM8vMUNCU8yQjMYoWL8iL4NNJxRheD0l2FABcGTbWI159eXy8laenk5eBfYKIwl +YGnoylDD2F4W0mdMl2MJIYNYTRP7pAQhLnMbVNSgGDgk5Z0kUF2Kl2rNz+3w1c36 +L3VC/CGFp5/spnQHhYMH2oUAkliS0iev7bNJyhvycVQkMlwYu8KZKMtqyn9bnpU4 +Kd6XlXPwF3BHGrVVdcb6RQo65GrwT6j+hWRwUKgEvcxC7BjtsY1ZV3xRfsRQpA/b +1sTQ/W0ev09+OJAHWEedIg2sTTp5WSiF2whCz6yviFxEAeYIUEGVHw== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/serial new file mode 100644 index 0000000000..7d802a3e71 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/serial @@ -0,0 +1 @@ +1002 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/openssl.cfg new file mode 100644 index 0000000000..7cbc4664fa --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ +crlDistributionPoints=URI:http://localhost:8902/demoCA/crl/Sub_CA_1_Root_7.crl +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +#nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/README.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/README.txt new file mode 100644 index 0000000000..4d510fe39b --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/README.txt @@ -0,0 +1,13 @@ +Revoked certificates: + +- User 2 Sub CA 1 Root 8 + + +Start the OCSP responder: +openssl ocsp -index demoCA/index.txt -port 8889 -rsigner demoCA/cacert.pem -rkey demoCA/private/cakey.pem -CA demoCA/cacert.pem -text + + + + + + diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/cacert.pem new file mode 100644 index 0000000000..b2d1deb759 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/cacert.pem @@ -0,0 +1,66 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 8 + Validity + Not Before: Nov 20 15:33:21 2009 GMT + Not After : Nov 14 15:33:21 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 8 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:96:79:01:9f:4f:68:c1:09:0d:44:3a:82:e4:eb: + ad:70:7a:cf:b9:71:e5:fb:e0:c8:0c:21:79:3e:cb: + 78:91:7f:4a:a0:de:3e:37:0f:a1:6b:73:10:12:9b: + 08:c4:96:dc:cb:a8:5b:87:9b:75:24:e4:00:5e:4a: + 6f:4c:13:79:1f:57:13:8c:3e:1b:38:31:e1:77:74: + 52:f9:94:47:36:57:33:bd:de:08:11:a3:01:e1:53: + 1c:bd:7b:39:9c:5e:96:5c:a9:61:6c:cc:2b:90:8d: + 5a:3c:9e:f4:4b:6e:e5:97:64:86:f3:8e:e8:72:20: + 5d:0d:50:bf:e9:cf:be:d4:13 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + EF:BD:C8:8E:78:79:F9:76:4B:11:59:B6:C3:32:10:07:C0:BC:E3:8A + X509v3 Authority Key Identifier: + keyid:D6:66:76:C9:05:FF:A9:50:88:96:60:DD:FB:C7:30:18:72:67:41:19 + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 8 + serial:B2:47:DE:6A:2A:4C:83:19 + + Authority Information Access: + OCSP - URI:http://localhost:8888 + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 4c:95:44:3b:57:08:ec:01:ec:f9:3e:7c:89:1c:30:b1:4e:26: + 32:b6:57:fa:25:bc:ed:eb:d4:a2:1c:67:ee:b9:8b:d0:4c:57: + 8a:0e:db:a0:9d:92:e7:de:c6:73:01:e7:de:61:1b:b5:0e:d0: + c5:c1:a7:a6:ab:e0:c6:0b:51:dd:e5:a2:32:1f:c6:52:ea:d3: + 03:68:3a:f5:92:bd:8b:b8:03:bb:50:70:63:cc:ec:ed:3c:11: + 76:ca:ac:72:47:ad:99:6b:8e:07:9e:38:f2:63:e1:ba:d4:df: + a9:73:54:1d:74:89:94:01:2e:68:dd:97:e7:53:f9:cf:b6:7d: + fc:87 +-----BEGIN CERTIFICATE----- +MIIDOTCCAqKgAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA4MB4XDTA5MTEyMDE1MzMy +MVoXDTM0MTExNDE1MzMyMVowaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA4MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQCWeQGfT2jBCQ1EOoLk661wes+5ceX74MgMIXk+y3iRf0qg3j43D6Fr +cxASmwjEltzLqFuHm3Uk5ABeSm9ME3kfVxOMPhs4MeF3dFL5lEc2VzO93ggRowHh +Uxy9ezmcXpZcqWFszCuQjVo8nvRLbuWXZIbzjuhyIF0NUL/pz77UEwIDAQABo4H6 +MIH3MB0GA1UdDgQWBBTvvciOeHn5dksRWbbDMhAHwLzjijCBkQYDVR0jBIGJMIGG +gBTWZnbJBf+pUIiWYN37xzAYcmdBGaFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA4ggkAskfeaipMgxkwMQYIKwYBBQUH +AQEEJTAjMCEGCCsGAQUFBzABhhVodHRwOi8vbG9jYWxob3N0Ojg4ODgwDwYDVR0T +AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBMlUQ7VwjsAez5PnyJHDCxTiYy +tlf6Jbzt69SiHGfuuYvQTFeKDtugnZLn3sZzAefeYRu1DtDFwaemq+DGC1Hd5aIy +H8ZS6tMDaDr1kr2LuAO7UHBjzOztPBF2yqxyR62Za44HnjjyY+G61N+pc1QddImU +AS5o3ZfnU/nPtn38hw== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/crl/DO_NOT_INSTALL_THIS_CRL b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/crl/DO_NOT_INSTALL_THIS_CRL new file mode 100644 index 0000000000..e69de29bb2 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 new file mode 100644 index 0000000000..7a9ee345ea Binary files /dev/null and b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/crl/Sub_CA_1_Root_8.crl differ diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/crlnumber new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/crlnumber @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/index.txt new file mode 100644 index 0000000000..ff1b3fe194 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/index.txt @@ -0,0 +1,2 @@ +V 341114154212Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 1 Root 8 +R 341114154716Z 091120155036Z,superseded 1001 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 2 Sub CA 1 Root 8 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/index.txt.attr new file mode 100644 index 0000000000..8f7e63a347 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/newcerts/1000.pem new file mode 100644 index 0000000000..71456d01b1 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/newcerts/1000.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 8 + Validity + Not Before: Nov 20 15:42:12 2009 GMT + Not After : Nov 14 15:42:12 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 1 Root 8 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:b6:aa:34:ec:31:e5:9a:aa:fe:90:31:1f:e5:83: + 90:cb:9a:9e:15:cd:bb:35:1b:fc:3c:8b:d9:3d:29: + de:f4:07:3f:4c:06:9b:4f:db:21:a2:4b:87:8b:fd: + b4:61:31:de:34:6c:14:10:f9:a7:7a:e0:0a:e9:bf: + b3:83:a3:35:44:f4:ad:c3:d0:60:e8:71:8e:6d:c0: + 70:9a:16:85:65:7a:82:68:7c:67:ee:57:31:6b:e8: + fd:f2:3f:5f:c7:ec:4e:db:e7:8a:98:d6:15:45:13: + 14:03:bc:4e:8a:03:48:c2:e4:aa:c5:32:cf:80:82: + 45:16:8b:63:37:4b:d5:7a:97 + Exponent: 65537 (0x10001) + X509v3 extensions: + Authority Information Access: + OCSP - URI:http://localhost:8889 + + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 4E:0B:28:05:B5:07:8F:77:1E:A6:37:CB:CC:F0:CB:09:A4:8C:4A:1E + X509v3 Authority Key Identifier: + keyid:EF:BD:C8:8E:78:79:F9:76:4B:11:59:B6:C3:32:10:07:C0:BC:E3:8A + + Signature Algorithm: sha1WithRSAEncryption + 3e:f7:c5:94:58:2f:18:c9:11:29:29:28:33:bb:e7:6c:70:7c: + f8:c7:60:4a:e5:37:f2:bb:78:d9:52:1e:c2:a3:dd:b1:7f:da: + e1:8a:8b:9c:7e:d6:ee:ec:ef:94:37:b5:b8:97:26:92:01:56: + 78:15:44:4b:95:4d:d9:59:12:b0:89:86:e4:b5:7d:b4:73:0f: + f1:0d:a8:04:69:e4:3f:2a:6a:65:b9:0e:9a:06:f7:16:29:94: + 4d:ac:64:ab:e9:0f:06:3c:74:fe:4c:e1:71:98:bd:9f:bb:c1: + 2d:47:70:6a:3c:b3:76:0b:fc:c8:05:d6:4e:bf:33:9f:dd:58: + 74:9c +-----BEGIN CERTIFICATE----- +MIIC0jCCAjugAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA4MB4XDTA5 +MTEyMDE1NDIxMloXDTM0MTExNDE1NDIxMlowbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAxIFN1YiBDQSAxIFJvb3QgODCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAtqo07DHlmqr+kDEf5YOQy5qeFc27NRv8 +PIvZPSne9Ac/TAabT9shokuHi/20YTHeNGwUEPmneuAK6b+zg6M1RPStw9Bg6HGO +bcBwmhaFZXqCaHxn7lcxa+j98j9fx+xO2+eKmNYVRRMUA7xOigNIwuSqxTLPgIJF +FotjN0vVepcCAwEAAaOBgzCBgDAxBggrBgEFBQcBAQQlMCMwIQYIKwYBBQUHMAGG +FWh0dHA6Ly9sb2NhbGhvc3Q6ODg4OTALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFE4L +KAW1B493HqY3y8zwywmkjEoeMB8GA1UdIwQYMBaAFO+9yI54efl2SxFZtsMyEAfA +vOOKMA0GCSqGSIb3DQEBBQUAA4GBAD73xZRYLxjJESkpKDO752xwfPjHYErlN/K7 +eNlSHsKj3bF/2uGKi5x+1u7s75Q3tbiXJpIBVngVREuVTdlZErCJhuS1fbRzD/EN +qARp5D8qamW5DpoG9xYplE2sZKvpDwY8dP5M4XGYvZ+7wS1HcGo8s3YL/MgF1k6/ +M5/dWHSc +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/newcerts/1001.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/newcerts/1001.pem new file mode 100644 index 0000000000..51102e24a5 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/newcerts/1001.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4097 (0x1001) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 8 + Validity + Not Before: Nov 20 15:47:16 2009 GMT + Not After : Nov 14 15:47:16 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 2 Sub CA 1 Root 8 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:a1:55:67:7e:e5:7a:62:eb:2b:36:45:fa:1d:4d: + c7:0e:6d:db:f6:54:65:4d:55:39:14:ea:c1:ad:75: + 1b:2f:2f:3c:6e:67:e0:6d:c6:76:66:0c:11:a2:89: + fe:70:3b:24:3e:0d:2a:13:9f:86:b4:8a:a3:27:50: + 52:77:1f:b8:7b:85:4e:36:94:68:4f:23:2c:f6:a1: + 0f:01:bc:6d:d4:e9:a4:54:12:15:37:bd:6c:ba:ad: + ed:78:ed:00:cc:be:a9:20:99:f5:a5:db:96:ba:cb: + 89:6b:ff:30:36:5c:84:77:a8:0d:28:d3:f8:20:99: + 01:4d:0f:8e:b3:8e:de:8d:09 + Exponent: 65537 (0x10001) + X509v3 extensions: + Authority Information Access: + OCSP - URI:http://localhost:8889 + + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + FC:DC:A7:1C:CE:D2:A9:DA:9A:76:9D:AE:8F:C8:1E:56:BA:D2:D5:D5 + X509v3 Authority Key Identifier: + keyid:EF:BD:C8:8E:78:79:F9:76:4B:11:59:B6:C3:32:10:07:C0:BC:E3:8A + + Signature Algorithm: sha1WithRSAEncryption + 87:30:ed:08:e6:03:fa:cf:65:5a:ed:9e:83:db:64:5f:bb:6b: + 5c:f3:db:8d:b7:d0:95:35:8c:f6:c1:1c:2c:d9:0c:0a:41:27: + f9:1f:e4:aa:25:95:59:3c:45:85:ac:0f:02:42:92:67:e2:09: + 45:d3:c1:7b:6e:db:42:84:7b:0d:57:47:f5:07:38:dd:cf:38: + ac:29:b9:14:79:2e:04:a5:a0:d6:71:be:fa:6d:9e:b5:cd:89: + 99:d1:47:58:56:81:8c:d4:b0:96:c6:dc:a7:1b:b0:ef:6b:0c: + 25:5f:92:b8:01:b7:74:f0:e3:49:eb:30:29:9f:f3:b5:bd:ae: + 45:99 +-----BEGIN CERTIFICATE----- +MIIC0jCCAjugAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA4MB4XDTA5 +MTEyMDE1NDcxNloXDTM0MTExNDE1NDcxNlowbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAyIFN1YiBDQSAxIFJvb3QgODCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAoVVnfuV6YusrNkX6HU3HDm3b9lRlTVU5 +FOrBrXUbLy88bmfgbcZ2ZgwRoon+cDskPg0qE5+GtIqjJ1BSdx+4e4VONpRoTyMs +9qEPAbxt1OmkVBIVN71suq3teO0AzL6pIJn1pduWusuJa/8wNlyEd6gNKNP4IJkB +TQ+Os47ejQkCAwEAAaOBgzCBgDAxBggrBgEFBQcBAQQlMCMwIQYIKwYBBQUHMAGG +FWh0dHA6Ly9sb2NhbGhvc3Q6ODg4OTALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFPzc +pxzO0qnamnadro/IHla60tXVMB8GA1UdIwQYMBaAFO+9yI54efl2SxFZtsMyEAfA +vOOKMA0GCSqGSIb3DQEBBQUAA4GBAIcw7QjmA/rPZVrtnoPbZF+7a1zz24230JU1 +jPbBHCzZDApBJ/kf5KollVk8RYWsDwJCkmfiCUXTwXtu20KEew1XR/UHON3POKwp +uRR5LgSloNZxvvptnrXNiZnRR1hWgYzUsJbG3KcbsO9rDCVfkrgBt3Tw40nrMCmf +87W9rkWZ +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/private/cakey.pem new file mode 100644 index 0000000000..6c934e3ec8 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,D40C0B2149B20A3E + +u5VzDci4c2i/pIElAbIAVT81F72A2V3fpvZv8yUpQRai5ZPzciSc4oYgavdu3tLV +p8bS+60akNpr3/ti7sB4tQBcql/3FMdKLFCgflJgCH9ivr2UrUSIJOyu9UNoG2ym +UcJrvCSAqtksL11VLMb3SJO7TRYxJ/xOl69Auf0R+aRwdof9nSBO4jDPTqvR/X8L +j/plBnw7ENO0ravRnEEEAEiSgx/z0LkhzAsPTkrrkNN5eZ+kR2Sk/Uo5aTx3FTpB +RU+iZQxmbNTrxCErfYvSnMJ4w6soT+Bzezwfn2tVGLwbur/3gtuNMEHJpL0Y2st9 +aRBHHF6+DlJ30rqNWCVV5ZY+2wMUEPBtcRftLdmh3caw/9aN/NqVUGuvqmhWyTt7 +TJmnKLJhE9NSztQM2PuV7ka9jWp5D6KLv0g+cbedpEOw6VjYL5e1EKt0AOu4Pp2r +HerL1ouRmpzIQLpskFTwkccjVDQm/H2fnB/nVrjdWxi/U4QJ0EPHL8iCyyox5np+ +3HilWBkpyBSvMOhyGfPkUucsMZA6O7/XhDcciBSsCJ4SSMa5gQmfYfixQHKRwixS +O5sJADUnJkbo4hyvrptAolM/JJU+HN8IYnq541mJ72dXbyodheedRPIOpTCiLQam +1Y04wfuIFMN4w98O0oMpCbqcDsOHysxN1XYg2kMzlxYbwooFC5cud5+cEW6d9FWQ +kpZ8Wkigno3ytjpUXWb9TmsRcMNiQdgxlpkvN/eYhk4xsUpwzhA/M/HTkLkn8WtC +52EwCv9KcxF31AA0lOeI+oNfcyMruwNXwEkFn3eD36axZQ8QjPHfhw== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/serial new file mode 100644 index 0000000000..7d802a3e71 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/serial @@ -0,0 +1 @@ +1002 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/openssl.cfg new file mode 100644 index 0000000000..571237e7da --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +authorityInfoAccess = OCSP;URI:http://localhost:8889 +#crlDistributionPoints=URI:http://localhost:8902/demoCA/crl/Sub_CA_2_Root_7.crl +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +#nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/cacert.pem new file mode 100644 index 0000000000..0b38d4db4c --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/cacert.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 9 + Validity + Not Before: Nov 23 13:59:19 2009 GMT + Not After : Nov 17 13:59:19 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 9 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:a9:6d:7f:6a:08:fb:e2:3a:5e:83:3f:ff:58:ba: + 92:a1:79:9d:ce:d2:0c:16:15:f2:7e:b3:e4:45:9c: + 02:32:65:9b:02:90:78:05:95:e4:04:1d:4a:05:bb: + ea:f6:ac:ab:15:74:c2:bc:ee:2a:c1:80:55:3e:93: + 1f:5c:94:eb:cf:cf:8f:15:eb:b8:22:fe:69:61:51: + a9:08:b8:80:bd:48:99:da:85:10:1c:75:97:fd:d3: + c3:c4:0b:dd:eb:01:12:5d:ee:62:62:c3:0c:18:ea: + ed:76:ff:9b:1c:1f:c7:81:f9:9a:cd:e5:25:89:b2: + 13:57:56:f3:27:53:72:76:69 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 7B:D3:57:BF:6A:CB:6C:10:81:91:DA:95:DC:88:4F:A5:D0:DB:D1:46 + X509v3 Authority Key Identifier: + keyid:CD:33:5E:AB:73:23:51:80:B8:03:AD:12:01:0B:C5:5E:8E:55:CA:64 + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 9 + serial:A4:DB:16:0D:4B:8C:D4:A6 + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 17:67:b0:21:da:0d:a1:fe:09:62:d0:cf:1d:c0:c8:bd:d4:22: + dd:75:ec:04:e2:23:ae:ea:8c:15:fa:73:2e:83:f4:16:eb:c1: + e1:87:36:bd:58:d0:64:e0:6e:2c:bc:27:cb:dc:4b:58:01:80: + 48:27:53:bb:75:85:a7:19:b8:e2:c0:1f:9f:a2:18:27:82:3f: + 25:bf:17:d1:34:32:de:c4:81:9d:8a:39:6f:6b:1f:b6:12:61: + 74:78:96:6d:6e:52:23:4a:67:30:78:03:91:b7:89:bf:3c:4a: + 36:e3:95:21:38:35:af:05:55:81:05:25:91:78:ca:2f:5d:79: + d2:05 +-----BEGIN CERTIFICATE----- +MIIDBjCCAm+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA5MB4XDTA5MTEyMzEzNTkx +OVoXDTM0MTExNzEzNTkxOVowaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA5MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQCpbX9qCPviOl6DP/9YupKheZ3O0gwWFfJ+s+RFnAIyZZsCkHgFleQE +HUoFu+r2rKsVdMK87irBgFU+kx9clOvPz48V67gi/mlhUakIuIC9SJnahRAcdZf9 +08PEC93rARJd7mJiwwwY6u12/5scH8eB+ZrN5SWJshNXVvMnU3J2aQIDAQABo4HH +MIHEMB0GA1UdDgQWBBR701e/astsEIGR2pXciE+l0NvRRjCBkQYDVR0jBIGJMIGG +gBTNM16rcyNRgLgDrRIBC8VejlXKZKFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA5ggkApNsWDUuM1KYwDwYDVR0TAQH/ +BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQAXZ7Ah2g2h/gli0M8dwMi91CLddewE +4iOu6owV+nMug/QW68Hhhza9WNBk4G4svCfL3EtYAYBIJ1O7dYWnGbjiwB+fohgn +gj8lvxfRNDLexIGdijlvax+2EmF0eJZtblIjSmcweAORt4m/PEo245UhODWvBVWB +BSWReMovXXnSBQ== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/crlnumber new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/crlnumber @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/index.txt new file mode 100644 index 0000000000..8c466eaffd --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/index.txt @@ -0,0 +1 @@ +V 341117140202Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 1 Root 9 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/index.txt.attr new file mode 100644 index 0000000000..8f7e63a347 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/newcerts/1000.pem new file mode 100644 index 0000000000..e3ca26a8a3 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/newcerts/1000.pem @@ -0,0 +1,58 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 9 + Validity + Not Before: Nov 23 14:02:02 2009 GMT + Not After : Nov 17 14:02:02 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 1 Root 9 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:f2:d3:15:3c:73:42:ce:22:e4:40:3a:6b:02:f6: + 59:bd:66:0d:87:91:f4:c0:be:a9:ce:33:21:09:d9: + 4e:4b:03:51:87:c3:e9:75:91:e9:80:5e:fc:a1:f7: + 43:9b:c6:32:af:6d:77:4b:b6:dc:b1:08:a3:1f:a0: + 6d:ec:81:12:23:48:36:2d:7a:5a:d0:88:88:49:7c: + ce:ae:98:45:d8:ff:9f:15:72:ab:b4:85:f6:a5:23: + af:43:e4:64:45:da:20:e1:e0:3e:f2:87:ea:67:ea: + 0e:08:8a:c8:1c:ef:85:a5:e6:f3:54:68:02:fd:de: + bc:4d:a2:eb:7d:0d:7d:80:59 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 1B:56:DD:11:CE:38:A0:97:FF:BE:39:9C:AF:F4:60:82:3A:CA:5D:51 + X509v3 Authority Key Identifier: + keyid:7B:D3:57:BF:6A:CB:6C:10:81:91:DA:95:DC:88:4F:A5:D0:DB:D1:46 + + Signature Algorithm: sha1WithRSAEncryption + 54:5e:40:1d:83:35:67:23:01:28:35:e3:02:7f:9e:9f:ce:83: + fb:45:dd:5c:96:62:f5:28:45:c8:90:2a:7e:84:88:e9:e9:b7: + 21:17:e0:3b:ea:de:6d:a1:d5:37:90:ae:15:86:30:7f:82:81: + d1:bb:ca:d2:6c:7c:39:2e:e9:65:57:2b:74:47:04:49:99:74: + 63:c7:03:cc:7d:f4:b0:6e:92:75:bb:aa:28:dc:71:d3:95:73: + 15:f4:4f:38:43:9e:4f:9f:e3:97:5c:8d:dc:1e:ad:ad:1e:b7: + c2:b2:ca:87:ee:8e:a2:93:12:60:95:1a:fb:bf:42:c8:31:48: + 8a:43 +-----BEGIN CERTIFICATE----- +MIICnTCCAgagAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA5MB4XDTA5 +MTEyMzE0MDIwMloXDTM0MTExNzE0MDIwMlowbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAxIFN1YiBDQSAxIFJvb3QgOTCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA8tMVPHNCziLkQDprAvZZvWYNh5H0wL6p +zjMhCdlOSwNRh8PpdZHpgF78ofdDm8Yyr213S7bcsQijH6Bt7IESI0g2LXpa0IiI +SXzOrphF2P+fFXKrtIX2pSOvQ+RkRdog4eA+8ofqZ+oOCIrIHO+FpebzVGgC/d68 +TaLrfQ19gFkCAwEAAaNPME0wCwYDVR0PBAQDAgXgMB0GA1UdDgQWBBQbVt0Rzjig +l/++OZyv9GCCOspdUTAfBgNVHSMEGDAWgBR701e/astsEIGR2pXciE+l0NvRRjAN +BgkqhkiG9w0BAQUFAAOBgQBUXkAdgzVnIwEoNeMCf56fzoP7Rd1clmL1KEXIkCp+ +hIjp6bchF+A76t5todU3kK4VhjB/goHRu8rSbHw5LullVyt0RwRJmXRjxwPMffSw +bpJ1u6oo3HHTlXMV9E84Q55Pn+OXXI3cHq2tHrfCssqH7o6ikxJglRr7v0LIMUiK +Qw== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/private/cakey.pem new file mode 100644 index 0000000000..be54b542a4 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,6D4A43A204C02659 + +ZPB/XY3gNrLz1f2DqTRkoZiL64CjVUEPw6ujRi/cAaMfAB+p32O/obtFbMyZWfpv +aLaoPmQH5hagNgsQqOW6OrSguxQ9i64Wv795TzRBrSYRHJ1as73AfDcS9aeI61AM +kiweFkVFAOPfgKOczYO152uXxtdRm4kpVr/CMsYuViE7966dzFvjDlY4vTDAD32+ +KJemzfjwsyErT/nYJaaabEkxxn+O3nwhgVqueoYWI8VeLYotFU41wO1NrOQvshs0 +tyrs5meiuSNPVuKagTltWfHv9PlMyVne7XYiRv1k7CIPmEansBge9/lY5KoPLHGQ +CHjuuwPykf6jnW7QG9IAGKRNPSdlMBpOT97EvKgNZ9I0FB4lSumhrxkjPHrRKz/J +usV+mEcGGYrfAb2OT0B/YSddOk1rCtKXpRVUMF8dzD7AyVxnU0Sdub6lwjNojAGh +Nb8exIFnVBM0/ka19xvlcdY0q9du7e0MuVvy8NhE0vkoqqDrUUnCP8iqg+uRBVts +0P7yk1lucsrNw8JQveLuiHm6zxN91iUAsBguwoOHG6szp3X9GLvvGhpQWPxTIOyo +obPMw6lY0y9MHY6eW9ekXVWGMZL2GDpIKLq9kqzLTqhY9kDw9OXYio4UYLl9vQG4 +Akr4ogzm8SKNQkPnGHprCdQV5J4V7fOa4HTNJb6NlTvMFuC99Sst+PYdE4RAn3sT +Jn+Lj2g0fDDSjvLNohmrT08DAYAAinbNt/+6gI975syPxuqxggrgfis4cliI7pf8 +ecmKIoSlbsJVCSfgd5a/d7e+9KwNuqBqopLu2vfgUN1YiFlEwAEQaQ== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/serial new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/serial @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/openssl.cfg new file mode 100644 index 0000000000..4a5b97f530 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8889 +#crlDistributionPoints=URI:http://localhost:8902/demoCA/crl/Sub_CA_2_Root_7.crl +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +#nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/README.txt b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/README.txt new file mode 100644 index 0000000000..e020f03a54 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/README.txt @@ -0,0 +1,4 @@ +Revoked certificates: + +- User 2 Sub CA 2 Root 4 + diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/cacert.pem new file mode 100644 index 0000000000..9d951ee267 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/cacert.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4097 (0x1001) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 4 + Validity + Not Before: Nov 20 09:22:27 2009 GMT + Not After : Nov 14 09:22:27 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 2 Root 4 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:e5:8d:27:4e:09:53:08:61:c6:23:25:9e:dd:9c: + 07:bf:81:38:5c:5c:10:8f:e4:12:2f:4e:2e:b1:a1: + cf:21:46:53:bf:e8:5e:de:17:3a:9d:f7:e8:ef:3e: + 9c:b4:29:37:4c:31:35:15:dc:98:e0:93:9c:ce:6a: + d6:e1:35:19:6b:d4:1d:3b:81:86:b1:e7:ff:1f:b8: + 34:a9:f9:de:4d:b8:62:ac:3b:d4:58:8e:5c:76:b5: + 07:7f:32:8a:3a:90:73:71:d5:da:f1:79:39:14:ed: + 1b:f1:8a:3e:be:48:bc:07:ec:f9:7c:03:14:fc:e7: + 55:a3:65:81:c7:6c:70:0b:ff + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 69:DE:B6:99:C4:95:F7:5A:FA:41:6B:4C:F6:C3:6D:89:AA:37:31:9D + X509v3 Authority Key Identifier: + keyid:BA:8D:A1:97:DC:C4:39:1F:90:B5:51:6B:10:19:F2:46:0D:A9:65:8E + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 4 + serial:A2:93:46:74:3B:A6:E3:AD + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + bc:cf:43:eb:72:b1:71:a7:94:8e:cd:5b:fc:d8:21:31:83:db: + a9:de:c7:5b:14:e5:7b:90:43:e6:05:df:db:6e:95:5f:24:ac: + 0c:a1:8a:ac:c6:cf:f2:03:cd:a0:30:ae:d3:a9:41:07:c9:b1: + be:4b:e0:fc:a2:76:09:07:75:6a:fa:e4:2f:a3:3a:cd:81:68: + ab:f6:06:c4:32:08:25:6e:e8:e7:36:9c:1a:f7:42:73:f8:b0: + d8:42:3e:85:c2:11:23:10:d6:6a:e4:8f:53:cb:8b:8b:1b:5a: + 4d:6d:9d:34:45:26:52:d2:ee:6d:8f:23:ff:00:92:f5:99:62: + 4c:41 +-----BEGIN CERTIFICATE----- +MIIDBjCCAm+gAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA0MB4XDTA5MTEyMDA5MjIy +N1oXDTM0MTExNDA5MjIyN1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDIgUm9vdCA0MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDljSdOCVMIYcYjJZ7dnAe/gThcXBCP5BIvTi6xoc8hRlO/6F7eFzqd +9+jvPpy0KTdMMTUV3Jjgk5zOatbhNRlr1B07gYax5/8fuDSp+d5NuGKsO9RYjlx2 +tQd/Moo6kHNx1drxeTkU7Rvxij6+SLwH7Pl8AxT851WjZYHHbHAL/wIDAQABo4HH +MIHEMB0GA1UdDgQWBBRp3raZxJX3WvpBa0z2w22JqjcxnTCBkQYDVR0jBIGJMIGG +gBS6jaGX3MQ5H5C1UWsQGfJGDalljqFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA0ggkAopNGdDum460wDwYDVR0TAQH/ +BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQC8z0PrcrFxp5SOzVv82CExg9up3sdb +FOV7kEPmBd/bbpVfJKwMoYqsxs/yA82gMK7TqUEHybG+S+D8onYJB3Vq+uQvozrN +gWir9gbEMgglbujnNpwa90Jz+LDYQj6FwhEjENZq5I9Ty4uLG1pNbZ00RSZS0u5t +jyP/AJL1mWJMQQ== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/crlnumber new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/crlnumber @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/index.txt new file mode 100644 index 0000000000..554a773b4a --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/index.txt @@ -0,0 +1,2 @@ +V 341114093339Z 1001 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 2 Root 4 +R 341114095105Z 091120095246Z,keyCompromise 1002 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 2 Sub CA 2 Root 4 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/index.txt.attr new file mode 100644 index 0000000000..8f7e63a347 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/newcerts/1001.pem b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/newcerts/1001.pem new file mode 100644 index 0000000000..3fbf2133fb --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/newcerts/1001.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4097 (0x1001) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 2 Root 4 + Validity + Not Before: Nov 20 09:33:39 2009 GMT + Not After : Nov 14 09:33:39 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 2 Root 4 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:c6:b2:8e:e4:f1:67:0b:07:3c:8c:b8:78:d9:79: + b1:2e:d5:10:c5:e8:76:9a:25:3f:dd:a3:0b:e0:3f: + 9f:50:87:e9:f1:15:74:86:ce:a0:01:07:b2:37:d0: + 74:dc:96:69:b4:f1:0e:cd:15:37:ca:ba:ed:ea:a3: + 99:ec:43:d4:ac:1c:8b:9b:18:d0:cd:80:78:49:80: + ca:e3:85:c6:2d:9a:15:02:73:d3:97:08:1d:4b:68: + 95:52:e6:92:57:c7:f6:76:0c:f1:a7:3d:90:10:0c: + 35:a8:9c:d3:e4:10:30:20:04:7f:ea:ad:ef:39:0c: + 65:05:43:f4:b6:51:3a:e7:95 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + Netscape Comment: + OpenSSL Generated Certificate + X509v3 Subject Key Identifier: + 79:C2:63:88:76:DF:C6:6F:BD:1D:AF:57:6E:87:08:AC:55:5D:AD:D1 + X509v3 Authority Key Identifier: + keyid:69:DE:B6:99:C4:95:F7:5A:FA:41:6B:4C:F6:C3:6D:89:AA:37:31:9D + + Signature Algorithm: sha1WithRSAEncryption + 07:68:5f:e9:01:bc:e4:d7:78:16:2b:19:7f:c2:9d:15:74:91: + ea:6d:fb:c9:ee:29:07:ff:62:e2:6a:85:5e:85:7d:5f:b4:bc: + 48:e1:89:24:3e:03:21:42:c1:10:3f:c6:41:7e:04:30:86:db: + c5:7e:7e:9f:04:49:a0:1e:fc:93:8e:b3:d1:cf:39:e3:41:89: + c3:06:51:3f:15:d5:02:49:2a:0b:15:d1:25:30:12:b6:2a:f9: + 03:06:f1:03:84:ae:4e:86:e1:dc:e6:a3:36:a4:27:24:2b:db: + 3a:3c:15:48:6f:c7:9f:ce:38:34:06:94:e3:d3:64:f7:4d:9e: + b6:c0 +-----BEGIN CERTIFICATE----- +MIICyzCCAjSgAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDIgUm9vdCA0MB4XDTA5 +MTEyMDA5MzMzOVoXDTM0MTExNDA5MzMzOVowbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAxIFN1YiBDQSAyIFJvb3QgNDCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAxrKO5PFnCwc8jLh42XmxLtUQxeh2miU/ +3aML4D+fUIfp8RV0hs6gAQeyN9B03JZptPEOzRU3yrrt6qOZ7EPUrByLmxjQzYB4 +SYDK44XGLZoVAnPTlwgdS2iVUuaSV8f2dgzxpz2QEAw1qJzT5BAwIAR/6q3vOQxl +BUP0tlE655UCAwEAAaN9MHswCwYDVR0PBAQDAgXgMCwGCWCGSAGG+EIBDQQfFh1P +cGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUecJjiHbfxm+9 +Ha9XbocIrFVdrdEwHwYDVR0jBBgwFoAUad62mcSV91r6QWtM9sNtiao3MZ0wDQYJ +KoZIhvcNAQEFBQADgYEAB2hf6QG85Nd4FisZf8KdFXSR6m37ye4pB/9i4mqFXoV9 +X7S8SOGJJD4DIULBED/GQX4EMIbbxX5+nwRJoB78k46z0c8540GJwwZRPxXVAkkq +CxXRJTAStir5AwbxA4SuTobh3OajNqQnJCvbOjwVSG/Hn844NAaU49Nk902etsA= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/newcerts/1002.pem b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/newcerts/1002.pem new file mode 100644 index 0000000000..595fbbfafb --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/newcerts/1002.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4098 (0x1002) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 2 Root 4 + Validity + Not Before: Nov 20 09:51:05 2009 GMT + Not After : Nov 14 09:51:05 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 2 Sub CA 2 Root 4 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:f5:2d:4a:b8:5d:39:da:58:5c:3c:a5:7d:4c:98: + b8:32:db:43:a0:13:cb:25:f8:5b:0b:6a:f2:e0:8d: + de:8f:c6:ea:c5:1c:03:bf:e0:b1:c9:14:a4:85:4b: + ed:95:87:f7:88:88:86:9e:65:3d:6e:e8:c5:be:17: + e6:9b:09:8e:44:c1:0a:20:00:ae:b4:3d:ba:68:9f: + 3e:ea:76:3c:96:64:ee:a7:91:65:31:03:f5:fd:01: + e5:60:a0:5e:62:a0:37:7b:db:cf:71:78:58:cc:dd: + 74:fc:b3:b1:2e:6b:f3:ec:ad:ac:75:ae:d8:d6:42: + 28:0a:20:68:8d:20:4a:30:61 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + Netscape Comment: + OpenSSL Generated Certificate + X509v3 Subject Key Identifier: + 32:E4:11:DF:CD:54:D6:80:67:68:85:36:A0:C5:14:88:D6:85:DB:C9 + X509v3 Authority Key Identifier: + keyid:69:DE:B6:99:C4:95:F7:5A:FA:41:6B:4C:F6:C3:6D:89:AA:37:31:9D + + Signature Algorithm: sha1WithRSAEncryption + e1:c2:5d:63:42:27:f4:df:a2:f0:f5:61:c3:e3:ac:f7:b6:29: + a9:dd:34:63:0c:cc:c9:7b:5c:1b:ac:77:8f:1a:e1:f4:3b:c8: + 96:8a:89:f6:c0:f0:c4:3b:bd:6e:b7:e7:84:5c:38:4f:d3:66: + 55:d6:d3:f8:70:1f:14:ce:9f:d3:04:68:be:6b:81:fc:6c:b6: + 2f:31:3d:de:2a:4e:6c:66:c0:c2:09:c8:ef:be:c4:88:39:28: + e8:62:da:44:63:f4:5c:f4:bb:cf:4b:54:c9:c0:ce:b4:27:7b: + 1e:9c:2f:90:9e:18:da:8a:27:af:e5:37:ea:3f:99:86:f8:5d: + d1:cb +-----BEGIN CERTIFICATE----- +MIICyzCCAjSgAwIBAgICEAIwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDIgUm9vdCA0MB4XDTA5 +MTEyMDA5NTEwNVoXDTM0MTExNDA5NTEwNVowbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAyIFN1YiBDQSAyIFJvb3QgNDCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA9S1KuF052lhcPKV9TJi4MttDoBPLJfhb +C2ry4I3ej8bqxRwDv+CxyRSkhUvtlYf3iIiGnmU9bujFvhfmmwmORMEKIACutD26 +aJ8+6nY8lmTup5FlMQP1/QHlYKBeYqA3e9vPcXhYzN10/LOxLmvz7K2sda7Y1kIo +CiBojSBKMGECAwEAAaN9MHswCwYDVR0PBAQDAgXgMCwGCWCGSAGG+EIBDQQfFh1P +cGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUMuQR381U1oBn +aIU2oMUUiNaF28kwHwYDVR0jBBgwFoAUad62mcSV91r6QWtM9sNtiao3MZ0wDQYJ +KoZIhvcNAQEFBQADgYEA4cJdY0In9N+i8PVhw+Os97Ypqd00YwzMyXtcG6x3jxrh +9DvIloqJ9sDwxDu9brfnhFw4T9NmVdbT+HAfFM6f0wRovmuB/Gy2LzE93ipObGbA +wgnI777EiDko6GLaRGP0XPS7z0tUycDOtCd7HpwvkJ4Y2oonr+U36j+Zhvhd0cs= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/private/cakey.pem new file mode 100644 index 0000000000..a8f9640c8a --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,1BD121CFCC6764E4 + +k3SMhf7UEWvpfhEyvd7Zc6kJFmiZ1JTg7KAawQhFhoRbGIVA1rSmRbuBdJm4XdQ5 +OxEAC5bVx5o3yxyhGmEkZr1dkGXkzQ1tc2a4Exf2p0O5zjlHUaxd2A4/mRYVAT0e +LAIQ+D+yqSd2wmLkLaz3EGGlfIPS8amTpnhSOvai40NjbLlRpw5DqDP/2KVWp7jH +T4JNzU33Xd6QuBsTSWyXuhIEeuzyrDbou0LceHIZSaa8Jqvp3yKX6OBTUdCNakwR +QtLLag63ie87qEhqeHg2VvZuVVEyhNCjPf2zRfxsCx742wI4TyY28JpxjYlFzJxX +Zd9toqIGFwritEOcr6wAqVX7NlE8/dDFFdEK9fPuv/jLoOYCCwDRvIMgDTE76c1k +foRMDMmqe0KcMdp+fbcfNDnV/U8gle2902AbEOXJLhdDEVUG/LCwrnIeUrfMOKiY +LwPysGwVndUb3uTFJ2e+PqV9i96G+ewpN9/hI9fThE12t8rhkpIsozEMl7WsBMgD +tdKrA5l7eibshCpk+zkIwGhkdMYXhj7hmioWWBJeMdJ93Ba8f91kt1IvI+J2Mn2K +1/5D0ZKEGPoTSAlEgMZ888sYWkT6WMk0UXH2Nq8BqdrrSTUypY2Uz0nDbWvhLrCf +zac6RZu9TtFsKAY6CQnXHFUJ+dvRmcSNQMhrIKS2VZ2UkL2oXASzXW2c9Hx6LO7T +WHuR7bXZiJhI63gUGI9pMRCs5NoRuXdg3KutzSTy8EWKJDXDKcvTemiomUZFB6i5 +zduXL73Wf/VjMcs7iOAijd7czGre0LBwyvgeNUAK2gj7SaGkR3bPZg== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/serial new file mode 100644 index 0000000000..baccd0398f --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/serial @@ -0,0 +1 @@ +1003 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/openssl.cfg new file mode 100644 index 0000000000..51e5205253 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/README.txt b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/README.txt new file mode 100644 index 0000000000..e04f69532d --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/README.txt @@ -0,0 +1,12 @@ +Revoked certificates: + +- User 2 Sub 2 Root 7 + + +To provide the CRL via HTTP run + +java -jar ../../tools/httpserv/dist/httpserv.jar -a 8902 + + + + diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/cacert.pem new file mode 100644 index 0000000000..0d2a0f02a3 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/cacert.pem @@ -0,0 +1,66 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4097 (0x1001) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 7 + Validity + Not Before: Nov 20 13:35:06 2009 GMT + Not After : Nov 14 13:35:06 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 2 Root 7 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:f9:3f:5e:76:52:9a:ce:5d:98:b0:00:d8:e0:65: + e7:78:11:4c:7b:c7:e2:d3:44:bf:8e:60:42:69:3e: + 75:67:65:24:ab:f7:07:d8:9d:be:0f:23:b5:c1:26: + 00:6b:c3:22:84:72:a9:96:dc:5f:63:fc:f5:e0:e3: + cc:da:0c:74:e9:31:51:91:89:27:8f:e5:17:41:6e: + 3d:5e:2a:13:cd:08:f7:f3:61:34:a1:f7:79:c6:bd: + 5d:2c:34:01:ea:5a:8c:48:97:36:d6:57:e0:80:03: + 2e:7a:03:83:4c:bd:b4:af:a2:fd:d7:4b:1a:f7:ab: + 9f:5a:22:2b:d1:25:73:dd:6f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 3B:50:26:45:6C:E2:FE:28:B1:71:0A:A8:95:2D:78:63:8E:2C:48:92 + X509v3 Authority Key Identifier: + keyid:80:C6:F8:0B:5F:7C:49:E4:86:FD:C8:92:C6:80:70:D9:C0:6F:7B:DE + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 7 + serial:D5:E6:63:5F:18:09:82:89 + + X509v3 CRL Distribution Points: + URI:http://localhost:8901/demoCA/crl/Root_7.crl + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 5f:b4:70:11:4f:d9:df:6a:6a:5a:4a:97:fe:8b:5d:9e:46:84: + e2:27:67:41:7c:a9:2e:9d:77:cc:e4:8c:d6:16:3c:39:7d:51: + 29:60:80:32:4f:a1:d0:b4:7f:2a:e5:60:f4:b8:d3:3b:94:f8: + a5:fb:15:99:cf:a9:c5:a7:59:c1:11:89:67:11:9c:ff:a9:ac: + dd:ca:a9:92:a8:60:26:c3:ab:74:41:86:b9:4d:1e:4a:c5:de: + 63:e6:da:2a:36:39:7b:6c:66:f3:20:57:d1:f1:36:4b:69:c5: + 04:a3:1f:cf:de:0c:10:d0:3f:07:e2:8e:0f:cd:41:26:c9:2e: + e9:1b +-----BEGIN CERTIFICATE----- +MIIDRjCCAq+gAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA3MB4XDTA5MTEyMDEzMzUw +NloXDTM0MTExNDEzMzUwNlowaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDIgUm9vdCA3MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQD5P152UprOXZiwANjgZed4EUx7x+LTRL+OYEJpPnVnZSSr9wfYnb4P +I7XBJgBrwyKEcqmW3F9j/PXg48zaDHTpMVGRiSeP5RdBbj1eKhPNCPfzYTSh93nG +vV0sNAHqWoxIlzbWV+CAAy56A4NMvbSvov3XSxr3q59aIivRJXPdbwIDAQABo4IB +BjCCAQIwHQYDVR0OBBYEFDtQJkVs4v4osXEKqJUteGOOLEiSMIGRBgNVHSMEgYkw +gYaAFIDG+AtffEnkhv3IksaAcNnAb3veoWOkYTBfMQswCQYDVQQGEwJERTEQMA4G +A1UECBMHSGFtYnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsT +C0RldmVsb3BtZW50MQ8wDQYDVQQDEwZSb290IDeCCQDV5mNfGAmCiTA8BgNVHR8E +NTAzMDGgL6AthitodHRwOi8vbG9jYWxob3N0Ojg5MDEvZGVtb0NBL2NybC9Sb290 +XzcuY3JsMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAX7RwEU/Z +32pqWkqX/otdnkaE4idnQXypLp13zOSM1hY8OX1RKWCAMk+h0LR/KuVg9LjTO5T4 +pfsVmc+pxadZwRGJZxGc/6ms3cqpkqhgJsOrdEGGuU0eSsXeY+baKjY5e2xm8yBX +0fE2S2nFBKMfz94MENA/B+KOD81BJsku6Rs= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/crl/DO_NOT_INSTALL_THIS_CRL b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/crl/DO_NOT_INSTALL_THIS_CRL new file mode 100644 index 0000000000..e69de29bb2 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 new file mode 100644 index 0000000000..c4dd13d839 Binary files /dev/null and b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/crl/Sub_CA_2_Root_7.crl differ diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/crlnumber new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/crlnumber @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/index.txt new file mode 100644 index 0000000000..a5e282ddd1 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/index.txt @@ -0,0 +1,2 @@ +V 341114134608Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 2 Root 7 +R 341114135230Z 091120135413Z,CACompromise 1001 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 2 Sub CA 2 Root 7 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/index.txt.attr new file mode 100644 index 0000000000..8f7e63a347 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/newcerts/1000.pem new file mode 100644 index 0000000000..ff1f1fa667 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/newcerts/1000.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 2 Root 7 + Validity + Not Before: Nov 20 13:46:08 2009 GMT + Not After : Nov 14 13:46:08 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 2 Root 7 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:a7:6b:af:a2:6e:61:33:2e:71:7b:e2:38:44:d9: + 4c:da:6e:86:bb:c6:f5:64:8e:2e:8b:e8:71:c8:46: + ad:c5:46:05:d2:06:a6:89:e2:ce:1f:1c:a7:4c:94: + a4:24:56:93:07:b1:c4:52:44:69:27:0b:34:eb:31: + 20:71:63:5c:0a:33:aa:0c:39:71:ac:08:49:c3:66: + ac:cb:e3:a8:66:ab:5c:a2:00:7a:bb:24:e6:93:91: + 1e:0e:7c:83:9e:f2:10:87:3f:0e:c0:f6:e5:bf:2c: + d3:cc:17:4c:d5:9a:96:35:4b:4e:ca:72:3a:9b:90: + c8:4c:24:04:2f:51:99:20:95 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 CRL Distribution Points: + URI:http://localhost:8902/demoCA/crl/Sub_CA_2_Root_7.crl + + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 27:98:7E:F6:AD:82:6D:F4:7A:32:AE:F1:54:D1:07:AE:08:0E:0E:2B + X509v3 Authority Key Identifier: + keyid:3B:50:26:45:6C:E2:FE:28:B1:71:0A:A8:95:2D:78:63:8E:2C:48:92 + + Signature Algorithm: sha1WithRSAEncryption + 06:7d:0a:e8:fa:8b:87:1d:75:61:2b:c7:d1:6d:56:5f:26:e3: + 29:b4:c3:27:05:35:0f:b7:c1:20:42:95:0b:9d:34:16:5d:9b: + c2:48:c8:67:e1:e7:43:eb:10:9e:45:3e:44:da:7c:4b:19:05: + 00:66:91:83:ea:82:86:48:e8:87:ea:a0:9f:c9:1d:f8:af:13: + fd:2e:4e:50:7e:a0:d2:b0:5e:a4:6f:dd:e6:c8:11:60:bc:41: + e5:b6:01:4c:7a:af:32:f6:cc:5b:57:e6:e4:87:21:ec:17:98: + 67:eb:4d:2f:07:db:8f:70:e2:f3:77:8f:c7:ff:60:d6:d9:f7: + 82:e3 +-----BEGIN CERTIFICATE----- +MIIC5jCCAk+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDIgUm9vdCA3MB4XDTA5 +MTEyMDEzNDYwOFoXDTM0MTExNDEzNDYwOFowbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAxIFN1YiBDQSAyIFJvb3QgNzCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAp2uvom5hMy5xe+I4RNlM2m6Gu8b1ZI4u +i+hxyEatxUYF0gamieLOHxynTJSkJFaTB7HEUkRpJws06zEgcWNcCjOqDDlxrAhJ +w2asy+OoZqtcogB6uyTmk5EeDnyDnvIQhz8OwPblvyzTzBdM1ZqWNUtOynI6m5DI +TCQEL1GZIJUCAwEAAaOBlzCBlDBFBgNVHR8EPjA8MDqgOKA2hjRodHRwOi8vbG9j +YWxob3N0Ojg5MDIvZGVtb0NBL2NybC9TdWJfQ0FfMl9Sb290XzcuY3JsMAsGA1Ud +DwQEAwIF4DAdBgNVHQ4EFgQUJ5h+9q2CbfR6Mq7xVNEHrggODiswHwYDVR0jBBgw +FoAUO1AmRWzi/iixcQqolS14Y44sSJIwDQYJKoZIhvcNAQEFBQADgYEABn0K6PqL +hx11YSvH0W1WXybjKbTDJwU1D7fBIEKVC500Fl2bwkjIZ+HnQ+sQnkU+RNp8SxkF +AGaRg+qChkjoh+qgn8kd+K8T/S5OUH6g0rBepG/d5sgRYLxB5bYBTHqvMvbMW1fm +5Ich7BeYZ+tNLwfbj3Di83ePx/9g1tn3guM= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/newcerts/1001.pem b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/newcerts/1001.pem new file mode 100644 index 0000000000..f16cdf4aab --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/newcerts/1001.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4097 (0x1001) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 2 Root 7 + Validity + Not Before: Nov 20 13:52:30 2009 GMT + Not After : Nov 14 13:52:30 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 2 Sub CA 2 Root 7 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:d3:1f:7e:28:b6:fd:f0:bb:01:21:88:04:c4:da: + 3d:6a:ce:09:8e:04:29:a5:0f:38:db:74:d0:ee:ad: + 5c:95:79:16:11:c0:b1:51:69:95:bb:a8:8f:8b:1c: + 7b:8c:82:27:16:21:82:82:d7:36:6f:b3:bb:36:a8: + ad:69:e2:e3:cd:6f:ef:81:ac:fa:e3:a9:ac:86:b7: + 31:1d:75:11:a3:2e:1d:89:0b:9c:5e:03:45:7a:b0: + a9:9d:ee:31:f1:15:c1:c5:f6:26:8e:d4:89:72:8f: + f4:86:94:d1:49:37:24:56:84:10:db:cc:f2:1d:3e: + 58:66:97:b2:17:6f:15:cb:81 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 CRL Distribution Points: + URI:http://localhost:8902/demoCA/crl/Sub_CA_2_Root_7.crl + + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + CD:A2:AE:51:D0:CF:A2:89:3A:53:23:74:1D:69:10:EE:2A:40:3A:22 + X509v3 Authority Key Identifier: + keyid:3B:50:26:45:6C:E2:FE:28:B1:71:0A:A8:95:2D:78:63:8E:2C:48:92 + + Signature Algorithm: sha1WithRSAEncryption + 40:8a:be:55:1f:d9:0f:96:fd:54:dd:9f:6b:1d:b1:34:ed:b7: + 11:6d:72:a9:65:9a:39:bd:79:3b:d3:4e:0c:22:60:39:e8:c0: + 2c:34:64:09:2c:0c:aa:f7:f9:9d:f1:d9:b9:04:d6:e2:c4:cb: + d5:05:33:75:5e:87:c0:2c:80:06:8b:6e:9c:ad:0c:7f:03:c0: + f5:91:e4:3a:64:b9:52:3b:5a:e0:e5:79:32:89:fb:4a:54:68: + 9a:e6:72:3e:61:93:a3:2a:67:aa:95:d0:3d:37:33:5c:da:6e: + a6:ac:3d:b6:b1:ac:68:f0:8c:8b:6b:96:a5:f7:ed:2d:6e:64: + c7:11 +-----BEGIN CERTIFICATE----- +MIIC5jCCAk+gAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDIgUm9vdCA3MB4XDTA5 +MTEyMDEzNTIzMFoXDTM0MTExNDEzNTIzMFowbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAyIFN1YiBDQSAyIFJvb3QgNzCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0x9+KLb98LsBIYgExNo9as4JjgQppQ84 +23TQ7q1clXkWEcCxUWmVu6iPixx7jIInFiGCgtc2b7O7NqitaeLjzW/vgaz646ms +hrcxHXURoy4diQucXgNFerCpne4x8RXBxfYmjtSJco/0hpTRSTckVoQQ28zyHT5Y +ZpeyF28Vy4ECAwEAAaOBlzCBlDBFBgNVHR8EPjA8MDqgOKA2hjRodHRwOi8vbG9j +YWxob3N0Ojg5MDIvZGVtb0NBL2NybC9TdWJfQ0FfMl9Sb290XzcuY3JsMAsGA1Ud +DwQEAwIF4DAdBgNVHQ4EFgQUzaKuUdDPook6UyN0HWkQ7ipAOiIwHwYDVR0jBBgw +FoAUO1AmRWzi/iixcQqolS14Y44sSJIwDQYJKoZIhvcNAQEFBQADgYEAQIq+VR/Z +D5b9VN2fax2xNO23EW1yqWWaOb15O9NODCJgOejALDRkCSwMqvf5nfHZuQTW4sTL +1QUzdV6HwCyABotunK0MfwPA9ZHkOmS5Ujta4OV5Mon7SlRomuZyPmGToypnqpXQ +PTczXNpupqw9trGsaPCMi2uWpfftLW5kxxE= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/private/cakey.pem new file mode 100644 index 0000000000..1f95ffa3c3 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,70BBA561902B1296 + ++Pbay3A7tcxOMNFXIlyQ6Hpl4QxJJmzZzXT5UOfGZYYRYrFKv1489pqvzLNgp06z +nWvyILc3AUd4dWnzfkWvPN3fjJazGWXoZaYLfGgdccA0LdXh+TmqVHHxFjOZVFeO +lYlKqK6dUsybaciOhkYBKPs1ZFAaNtQLZc1/GVAA9jVYnfwNVmW14d5Q8gurZTp8 +qYwQmT9Sjm2j9USIFcD9MDH94gW77PI+XD1hu6PJTF8m7n8eSY9KcWfVmd/Qj9Ly +nzLRaS6SOKETWL4+fUaN6aDtddKGwFgagyDwlRRuizX18ZSue2qoK73AhLtZ8Gx/ +vgFLTsvcniZus9kzVrRm2dsWvzaVAmOwqN04IqD6bEr+kXq1obP/T+deGsRwR54K +wEy7NrkkMSGw4AOuxVNSO7NYgU2kXueAfvGU8SQiXuU1S7fdZpWci8T5Dm7FuP9B +iKsHqUH9GYgAVl+Y3dwa9n+mDaFkn4wxeVHDdL40XJT0LYCMz9PGKRy3JSTiHF// +j9BHDpIC+E8L9N01cJ74+p0bzLLOhZ7vyjx8umVJbNIAAlDbCrEi4ZFqwGvmdjHF +2dti2S0ALixAFQybub4s9Cp3QxfaWnYQOvV7A0SGhtHkjycaJwO0cSonQ8yEjJJJ +PQkIW9SK+xz/yDYMHqa/Yo5t53GkpCTKBo2STSdnXjnABNk3FAusf72POkIPcH99 +5uyje8bo+lS2VB/O/pm8tbf9mW9YEh/xd3VAglWiAMzYSfO1x0rSTpdqJMSDfOhK +ogim9NdrVwASi0JrE8nCovwO3auOPu+5sRvYstnt18IVNisZZoW/Qg== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/serial new file mode 100644 index 0000000000..7d802a3e71 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/serial @@ -0,0 +1 @@ +1002 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/openssl.cfg new file mode 100644 index 0000000000..c6acf751f5 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ +crlDistributionPoints=URI:http://localhost:8902/demoCA/crl/Sub_CA_2_Root_7.crl +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +#nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/README.txt b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/README.txt new file mode 100644 index 0000000000..645ae6037d --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/README.txt @@ -0,0 +1,13 @@ +Revoked certificates: + +- User 2 Sub CA 2 Root 8 + + +Start the OCSP responder: +openssl ocsp -index demoCA/index.txt -port 8889 -rsigner demoCA/cacert.pem -rkey demoCA/private/cakey.pem -CA demoCA/cacert.pem -text + + + + + + diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/cacert.pem new file mode 100644 index 0000000000..26368962e8 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/cacert.pem @@ -0,0 +1,66 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4097 (0x1001) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 8 + Validity + Not Before: Nov 20 15:55:33 2009 GMT + Not After : Nov 14 15:55:33 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 2 Root 8 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:e9:91:38:d8:c1:36:e5:c1:d0:32:e8:ae:02:11: + 97:e5:c5:07:8f:5b:46:3a:3c:d9:49:5e:9a:4b:51: + 4c:b7:7d:e9:d1:4f:a7:15:8c:c6:10:f6:fa:5f:a9: + 0b:1b:bc:de:56:f5:ad:a3:a0:40:f1:75:10:58:74: + 37:f9:b7:9f:76:ca:46:96:4c:1a:81:f4:a2:ce:88: + 8b:9e:00:6d:42:b3:d6:68:d1:67:d6:9f:b8:9c:3f: + 43:c7:36:bf:41:88:1b:e8:74:26:a0:51:5c:e2:ee: + 6d:9d:73:bb:0d:36:e1:5c:68:9f:21:3b:b2:aa:ed: + 39:1d:ae:fc:b4:ca:38:c2:fb + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 1B:AB:6B:0F:42:91:DC:1E:D4:7A:95:87:30:2D:CC:11:4F:35:B7:73 + X509v3 Authority Key Identifier: + keyid:D6:66:76:C9:05:FF:A9:50:88:96:60:DD:FB:C7:30:18:72:67:41:19 + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 8 + serial:B2:47:DE:6A:2A:4C:83:19 + + Authority Information Access: + OCSP - URI:http://localhost:8888 + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 89:f8:8d:a8:e5:0b:2a:fb:f3:6a:80:2c:26:a1:a7:36:7e:a0: + c5:61:65:9d:7e:d6:47:60:b4:f6:72:e9:6e:2c:d9:f8:7f:c8: + 7a:5d:75:98:ad:88:de:e7:1b:44:a3:96:37:84:c0:b3:20:98: + 3b:b5:f6:ee:70:9c:04:7a:6c:88:05:75:7f:12:cf:b9:76:e8: + c0:17:0c:5e:eb:10:38:1e:54:41:58:56:f6:3c:ec:07:a5:c0: + 74:24:34:af:b3:c7:b2:58:85:47:0f:6c:e4:a0:9f:c8:7b:5c: + 95:77:17:e5:ad:eb:c3:86:44:f7:81:ef:cb:58:12:1a:6a:c7: + 19:95 +-----BEGIN CERTIFICATE----- +MIIDOTCCAqKgAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA4MB4XDTA5MTEyMDE1NTUz +M1oXDTM0MTExNDE1NTUzM1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDIgUm9vdCA4MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDpkTjYwTblwdAy6K4CEZflxQePW0Y6PNlJXppLUUy3fenRT6cVjMYQ +9vpfqQsbvN5W9a2joEDxdRBYdDf5t592ykaWTBqB9KLOiIueAG1Cs9Zo0WfWn7ic +P0PHNr9BiBvodCagUVzi7m2dc7sNNuFcaJ8hO7Kq7Tkdrvy0yjjC+wIDAQABo4H6 +MIH3MB0GA1UdDgQWBBQbq2sPQpHcHtR6lYcwLcwRTzW3czCBkQYDVR0jBIGJMIGG +gBTWZnbJBf+pUIiWYN37xzAYcmdBGaFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA4ggkAskfeaipMgxkwMQYIKwYBBQUH +AQEEJTAjMCEGCCsGAQUFBzABhhVodHRwOi8vbG9jYWxob3N0Ojg4ODgwDwYDVR0T +AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQCJ+I2o5Qsq+/NqgCwmoac2fqDF +YWWdftZHYLT2culuLNn4f8h6XXWYrYje5xtEo5Y3hMCzIJg7tfbucJwEemyIBXV/ +Es+5dujAFwxe6xA4HlRBWFb2POwHpcB0JDSvs8eyWIVHD2zkoJ/Ie1yVdxflrevD +hkT3ge/LWBIaascZlQ== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/crl/DO_NOT_INSTALL_THIS_CRL b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/crl/DO_NOT_INSTALL_THIS_CRL new file mode 100644 index 0000000000..e69de29bb2 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 new file mode 100644 index 0000000000..f4e88754b5 Binary files /dev/null and b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/crl/Sub_CA_2_Root_8.crl differ diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/crlnumber new file mode 100644 index 0000000000..dd11724042 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/crlnumber @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/index.txt new file mode 100644 index 0000000000..cdace00f7e --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/index.txt @@ -0,0 +1,2 @@ +V 341114161332Z 1002 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 2 Root 8 +R 341114161602Z 091120161700Z,superseded 1003 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 2 Sub CA 2 Root 8 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/index.txt.attr new file mode 100644 index 0000000000..8f7e63a347 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/newcerts/1002.pem b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/newcerts/1002.pem new file mode 100644 index 0000000000..1107a4327f --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/newcerts/1002.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4098 (0x1002) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 2 Root 8 + Validity + Not Before: Nov 20 16:13:32 2009 GMT + Not After : Nov 14 16:13:32 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 2 Root 8 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:d2:f6:25:c0:95:4b:07:1e:a0:57:67:52:36:b3: + 3e:5d:32:7f:61:25:e9:dd:31:a1:67:6e:02:9f:4f: + ca:ff:82:50:64:2e:ed:4e:8d:09:73:48:91:e1:90: + ca:df:06:ab:f4:c3:3d:8b:7d:d1:6b:5f:f8:f8:d6: + c0:f4:81:59:7c:0e:53:32:a9:cd:e4:34:3c:20:a9: + 08:b6:c2:b3:b7:91:d2:db:46:06:09:55:ff:f9:f4: + 4e:2a:28:36:46:0e:04:f1:78:7d:a3:ff:ac:08:1b: + 21:99:f5:b4:5b:f6:be:fd:1a:89:26:4b:eb:b9:58: + fc:c2:5f:44:42:a9:00:76:ff + Exponent: 65537 (0x10001) + X509v3 extensions: + Authority Information Access: + OCSP - URI:http://localhost:8889 + + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 9D:91:CD:7F:70:3B:00:C1:2A:FD:2F:5D:64:C4:8F:EB:0E:37:25:1B + X509v3 Authority Key Identifier: + keyid:1B:AB:6B:0F:42:91:DC:1E:D4:7A:95:87:30:2D:CC:11:4F:35:B7:73 + + Signature Algorithm: sha1WithRSAEncryption + 2c:68:5e:5b:2e:d7:48:ca:2a:01:b4:a0:99:0e:06:2d:e8:23: + b3:66:31:97:cd:9e:73:61:35:af:9d:d9:2f:7c:e6:87:7f:2a: + ae:3e:b0:99:c9:20:10:30:e3:a0:5b:28:8b:57:f2:12:3a:87: + c1:7a:5e:c8:21:b9:ae:49:c1:aa:4f:1c:9e:a8:ae:0f:ad:a2: + 3e:aa:61:94:64:41:f8:d7:19:8d:a1:be:c0:15:04:25:2c:35: + 29:af:00:1e:40:7c:e7:d7:41:89:a7:ab:2d:dd:78:dd:c7:ba: + d0:1b:7b:68:fa:7e:a4:0f:4c:ab:02:6e:d2:ff:b8:5b:05:f6: + 47:29 +-----BEGIN CERTIFICATE----- +MIIC0jCCAjugAwIBAgICEAIwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDIgUm9vdCA4MB4XDTA5 +MTEyMDE2MTMzMloXDTM0MTExNDE2MTMzMlowbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAxIFN1YiBDQSAyIFJvb3QgODCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0vYlwJVLBx6gV2dSNrM+XTJ/YSXp3TGh +Z24Cn0/K/4JQZC7tTo0Jc0iR4ZDK3war9MM9i33Ra1/4+NbA9IFZfA5TMqnN5DQ8 +IKkItsKzt5HS20YGCVX/+fROKig2Rg4E8Xh9o/+sCBshmfW0W/a+/RqJJkvruVj8 +wl9EQqkAdv8CAwEAAaOBgzCBgDAxBggrBgEFBQcBAQQlMCMwIQYIKwYBBQUHMAGG +FWh0dHA6Ly9sb2NhbGhvc3Q6ODg4OTALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFJ2R +zX9wOwDBKv0vXWTEj+sONyUbMB8GA1UdIwQYMBaAFBuraw9Ckdwe1HqVhzAtzBFP +NbdzMA0GCSqGSIb3DQEBBQUAA4GBACxoXlsu10jKKgG0oJkOBi3oI7NmMZfNnnNh +Na+d2S985od/Kq4+sJnJIBAw46BbKItX8hI6h8F6Xsghua5JwapPHJ6org+toj6q +YZRkQfjXGY2hvsAVBCUsNSmvAB5AfOfXQYmnqy3deN3HutAbe2j6fqQPTKsCbtL/ +uFsF9kcp +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/newcerts/1003.pem b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/newcerts/1003.pem new file mode 100644 index 0000000000..53268ff52d --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/newcerts/1003.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4099 (0x1003) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 2 Root 8 + Validity + Not Before: Nov 20 16:16:02 2009 GMT + Not After : Nov 14 16:16:02 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 2 Sub CA 2 Root 8 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:b4:58:05:7c:f5:f2:48:af:35:03:82:62:af:d3: + ef:50:f0:0b:b1:a9:a1:9b:14:1c:54:a9:71:b4:f6: + e0:7d:8a:25:b3:21:e2:53:ab:a5:08:9e:ed:5a:ef: + 8b:4f:be:75:40:b0:10:05:eb:08:3b:94:c2:57:37: + 51:41:08:57:b9:1c:a5:2f:e9:cc:3c:a8:70:2b:eb: + 00:92:43:64:44:18:23:9f:85:5f:7f:a5:c9:30:b3: + 14:c0:2b:fc:94:a5:a6:ad:46:a8:37:12:20:ab:cf: + e0:02:74:5d:1f:2e:ec:1c:9f:27:1f:83:fc:c4:62: + d2:0b:6b:f4:65:21:1d:94:ff + Exponent: 65537 (0x10001) + X509v3 extensions: + Authority Information Access: + OCSP - URI:http://localhost:8889 + + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 1E:C7:A3:43:33:6B:EC:90:B5:66:81:64:D6:43:72:45:DB:D9:E4:57 + X509v3 Authority Key Identifier: + keyid:1B:AB:6B:0F:42:91:DC:1E:D4:7A:95:87:30:2D:CC:11:4F:35:B7:73 + + Signature Algorithm: sha1WithRSAEncryption + a8:66:0d:4b:6a:00:fc:31:e3:f5:8f:49:44:3d:60:26:76:2e: + 51:f8:41:35:3b:5b:7f:87:e3:00:d7:ae:85:bb:d9:81:a5:30: + db:6a:0a:a0:d2:e8:69:f5:47:d8:19:e5:2a:bd:c5:8e:99:f9: + 57:fc:b0:64:f5:43:bc:37:4a:8e:28:70:a4:6d:7d:da:2c:9e: + c1:55:8d:00:89:fe:f7:ef:c9:d9:8d:fe:01:3e:83:23:58:c3: + 3e:41:09:ab:5c:60:0e:9e:18:69:9e:99:7f:a2:cd:b7:95:5c: + ea:31:02:79:32:eb:1a:07:dc:75:98:80:8e:56:f2:0a:8f:0e: + cf:4f +-----BEGIN CERTIFICATE----- +MIIC0jCCAjugAwIBAgICEAMwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDIgUm9vdCA4MB4XDTA5 +MTEyMDE2MTYwMloXDTM0MTExNDE2MTYwMlowbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAyIFN1YiBDQSAyIFJvb3QgODCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAtFgFfPXySK81A4Jir9PvUPALsamhmxQc +VKlxtPbgfYolsyHiU6ulCJ7tWu+LT751QLAQBesIO5TCVzdRQQhXuRylL+nMPKhw +K+sAkkNkRBgjn4Vff6XJMLMUwCv8lKWmrUaoNxIgq8/gAnRdHy7sHJ8nH4P8xGLS +C2v0ZSEdlP8CAwEAAaOBgzCBgDAxBggrBgEFBQcBAQQlMCMwIQYIKwYBBQUHMAGG +FWh0dHA6Ly9sb2NhbGhvc3Q6ODg4OTALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFB7H +o0Mza+yQtWaBZNZDckXb2eRXMB8GA1UdIwQYMBaAFBuraw9Ckdwe1HqVhzAtzBFP +NbdzMA0GCSqGSIb3DQEBBQUAA4GBAKhmDUtqAPwx4/WPSUQ9YCZ2LlH4QTU7W3+H +4wDXroW72YGlMNtqCqDS6Gn1R9gZ5Sq9xY6Z+Vf8sGT1Q7w3So4ocKRtfdosnsFV +jQCJ/vfvydmN/gE+gyNYwz5BCatcYA6eGGmemX+izbeVXOoxAnky6xoH3HWYgI5W +8gqPDs9P +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/private/cakey.pem new file mode 100644 index 0000000000..e063b97262 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,B84323C471CC815A + +UrT9eGAJB4+hzdjcS7YBCJi6jCL9n9/vZC0fC6mjZRK/dw4CxLka0KapKUVd+pj/ +I+XG6JOqa5tmsHcp9OWaWpzyu9W5DJqjodTum6pNlig68GVVSs21u7q0mF5mA6OR +PmRu+iOe2oZO6kVaRnpdGBnbsUsvlsbayiY3nHjXeDPxyc+XGnIMjT7mBOO360iR +h6IEOyapRho8klyuOXLy8hHZuUyspm66Nq+czorGdv3nlEdSI4t4LPTcqJGUMiHb +hLYsCK9Zwu7RQWne3OmGjAspU37TB3F1YrWjnHFIKE6YSvtdYMwXosMbybdUZFwQ +w4dGUhIxCxWLDF99Qfnygi8HJOC1FiFcJslVem0Xi3M654sshGLCiA4jMjdUAEmL +R+rzjUNZEHqvO/bGm7zsEoLWQFWEYqQZguwxDScam9Sii/fcnEBcSERbEi3yjvlX +7L3q4j/7/PlpYuRVB+f21ZuoI8R6M+omwF1ZzuSQNMSvUMyhAgQ+yB/pFJbArU68 +4l7ks0wNcSlLyGzjsexrzU9UB8Y8avFOMGuRiWGt4Kh54hNxgaCRGp9ugoyEq5H5 ++QNB1x8tBJSe1YC4T06olH2xZTYCd5e9qTyjQrbnqTK4SEBDrOL+XSASkleH3vVH +SO1paXDjh9fSSTxPo1T8DnAadIcouVlUNdvO4WrtqO4Kbf0rDHbqzZDtrNYG3Hwd +w86nEo6J1AKrTKyXysOLdhuAhNr+hGx4ITT5HfV/H5BE3ba0/fmLxvenqTxBXrJc +wkEeORwtu1XWW1hxYKRi3lRgfi4OH/ciMwxU530mKZzIJTOdvsKPgw== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/serial new file mode 100644 index 0000000000..59c1122662 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/serial @@ -0,0 +1 @@ +1004 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/openssl.cfg new file mode 100644 index 0000000000..571237e7da --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +authorityInfoAccess = OCSP;URI:http://localhost:8889 +#crlDistributionPoints=URI:http://localhost:8902/demoCA/crl/Sub_CA_2_Root_7.crl +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +#nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/certs/ca_certs/Root_1.crt b/xmlsecurity/test_docs/certs/ca_certs/Root_1.crt new file mode 100644 index 0000000000..ff4f23a90f Binary files /dev/null and b/xmlsecurity/test_docs/certs/ca_certs/Root_1.crt differ diff --git a/xmlsecurity/test_docs/certs/ca_certs/Root_10.crt b/xmlsecurity/test_docs/certs/ca_certs/Root_10.crt new file mode 100644 index 0000000000..64f80334b1 Binary files /dev/null and b/xmlsecurity/test_docs/certs/ca_certs/Root_10.crt differ diff --git a/xmlsecurity/test_docs/certs/ca_certs/Root_11.crt b/xmlsecurity/test_docs/certs/ca_certs/Root_11.crt new file mode 100644 index 0000000000..bbf0819dd5 Binary files /dev/null and b/xmlsecurity/test_docs/certs/ca_certs/Root_11.crt differ diff --git a/xmlsecurity/test_docs/certs/ca_certs/Root_2.crt b/xmlsecurity/test_docs/certs/ca_certs/Root_2.crt new file mode 100644 index 0000000000..5f4bd15cd8 Binary files /dev/null and b/xmlsecurity/test_docs/certs/ca_certs/Root_2.crt differ diff --git a/xmlsecurity/test_docs/certs/ca_certs/Root_3.crt b/xmlsecurity/test_docs/certs/ca_certs/Root_3.crt new file mode 100644 index 0000000000..306aa56491 Binary files /dev/null and b/xmlsecurity/test_docs/certs/ca_certs/Root_3.crt differ diff --git a/xmlsecurity/test_docs/certs/ca_certs/Root_4.crt b/xmlsecurity/test_docs/certs/ca_certs/Root_4.crt new file mode 100644 index 0000000000..a4c1dd84db Binary files /dev/null and b/xmlsecurity/test_docs/certs/ca_certs/Root_4.crt differ diff --git a/xmlsecurity/test_docs/certs/ca_certs/Root_5.crt b/xmlsecurity/test_docs/certs/ca_certs/Root_5.crt new file mode 100644 index 0000000000..e9af2c3303 Binary files /dev/null and b/xmlsecurity/test_docs/certs/ca_certs/Root_5.crt differ diff --git a/xmlsecurity/test_docs/certs/ca_certs/Root_6.crt b/xmlsecurity/test_docs/certs/ca_certs/Root_6.crt new file mode 100644 index 0000000000..03f2ff0b31 Binary files /dev/null and b/xmlsecurity/test_docs/certs/ca_certs/Root_6.crt differ diff --git a/xmlsecurity/test_docs/certs/ca_certs/Root_7.crt b/xmlsecurity/test_docs/certs/ca_certs/Root_7.crt new file mode 100644 index 0000000000..96eb504595 Binary files /dev/null and b/xmlsecurity/test_docs/certs/ca_certs/Root_7.crt differ diff --git a/xmlsecurity/test_docs/certs/ca_certs/Root_8.crt b/xmlsecurity/test_docs/certs/ca_certs/Root_8.crt new file mode 100644 index 0000000000..c714844ad9 Binary files /dev/null and b/xmlsecurity/test_docs/certs/ca_certs/Root_8.crt differ 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 new file mode 100644 index 0000000000..d83ce86dea Binary files /dev/null and b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_1.crt differ 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 new file mode 100644 index 0000000000..c4857c541a Binary files /dev/null and b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_2.crt differ 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 new file mode 100644 index 0000000000..d39b18b572 Binary files /dev/null and b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_3.crt differ 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 new file mode 100644 index 0000000000..b881f8a12e Binary files /dev/null and b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_4.crt differ 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 new file mode 100644 index 0000000000..61391a8c25 Binary files /dev/null and b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_5.crt differ 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 new file mode 100644 index 0000000000..223d047ca9 Binary files /dev/null and b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_6.crt differ 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 new file mode 100644 index 0000000000..af6a360033 Binary files /dev/null and b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_7.crt differ 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 new file mode 100644 index 0000000000..05297a3277 Binary files /dev/null and b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_8.crt differ 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 new file mode 100644 index 0000000000..209059facd Binary files /dev/null and b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_1_Root_9.crt differ 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 new file mode 100644 index 0000000000..a981a091cc Binary files /dev/null and b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_2_Root_4.crt differ 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 new file mode 100644 index 0000000000..d73827e103 Binary files /dev/null and b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_2_Root_7.crt differ 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 new file mode 100644 index 0000000000..69da1318b0 Binary files /dev/null and b/xmlsecurity/test_docs/certs/ca_certs/Sub_CA_2_Root_8.crt differ diff --git a/xmlsecurity/test_docs/certs/crl/Root_10.crl b/xmlsecurity/test_docs/certs/crl/Root_10.crl new file mode 100644 index 0000000000..e7fee3ade8 Binary files /dev/null and b/xmlsecurity/test_docs/certs/crl/Root_10.crl differ diff --git a/xmlsecurity/test_docs/certs/crl/Root_11.crl b/xmlsecurity/test_docs/certs/crl/Root_11.crl new file mode 100644 index 0000000000..95e18ae6af Binary files /dev/null and b/xmlsecurity/test_docs/certs/crl/Root_11.crl differ diff --git a/xmlsecurity/test_docs/certs/crl/Root_3.crl b/xmlsecurity/test_docs/certs/crl/Root_3.crl new file mode 100644 index 0000000000..5978b2613d Binary files /dev/null and b/xmlsecurity/test_docs/certs/crl/Root_3.crl differ diff --git a/xmlsecurity/test_docs/certs/crl/Root_4.crl b/xmlsecurity/test_docs/certs/crl/Root_4.crl new file mode 100644 index 0000000000..10b370c149 Binary files /dev/null and b/xmlsecurity/test_docs/certs/crl/Root_4.crl differ diff --git a/xmlsecurity/test_docs/certs/crl/Root_9.crl b/xmlsecurity/test_docs/certs/crl/Root_9.crl new file mode 100644 index 0000000000..90bf8eba4a Binary files /dev/null and b/xmlsecurity/test_docs/certs/crl/Root_9.crl differ 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 new file mode 100644 index 0000000000..c9f5420293 Binary files /dev/null and b/xmlsecurity/test_docs/certs/crl/Sub_CA_1_Root_2.crl differ 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 new file mode 100644 index 0000000000..7fc03f255e Binary files /dev/null and b/xmlsecurity/test_docs/certs/crl/Sub_CA_1_Root_4.crl differ 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 new file mode 100644 index 0000000000..567b8b5d11 Binary files /dev/null and b/xmlsecurity/test_docs/certs/crl/Sub_CA_1_Root_9.crl differ 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 new file mode 100644 index 0000000000..a2ce79b3a0 Binary files /dev/null and b/xmlsecurity/test_docs/certs/crl/Sub_CA_2_Root_4.crl differ 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 new file mode 100644 index 0000000000..16abebe511 Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_10_Root_11.crt differ 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 new file mode 100644 index 0000000000..08f5040ced Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_11_Root_11.crt differ 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 new file mode 100644 index 0000000000..18bd2475cd Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_12_Root_11.crt differ 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 new file mode 100644 index 0000000000..c7c83cf19a Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_13_Root_11.crt differ 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 new file mode 100644 index 0000000000..3ff2118d28 Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_14_Root_11.crt differ 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 new file mode 100644 index 0000000000..0fcd6393ac Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_15_Root_11.crt differ 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 new file mode 100644 index 0000000000..9f28740601 Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_16_Root_11.crt differ 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 new file mode 100644 index 0000000000..49442c6df7 Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_17_Root_11.crt differ 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 new file mode 100644 index 0000000000..27109c5bb0 Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_18_Root_11.crt differ 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 new file mode 100644 index 0000000000..5cce769b44 Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_19_Root_11.crt differ 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 new file mode 100644 index 0000000000..09f2a54f44 Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_1_Root_11.crt differ 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 new file mode 100644 index 0000000000..c3810ab508 Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_1.crt differ 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 new file mode 100644 index 0000000000..1531d1e8d3 Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_10.crt differ 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 new file mode 100644 index 0000000000..3dab258778 Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_2.crt differ 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 new file mode 100644 index 0000000000..278b11b77e Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_3.crt differ 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 new file mode 100644 index 0000000000..fa6e84547f Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_4.crt differ 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 new file mode 100644 index 0000000000..863f6f613e Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_5.crt differ 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 new file mode 100644 index 0000000000..cae3959d17 Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_6.crt differ 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 new file mode 100644 index 0000000000..e5786dc6c0 Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_7.crt differ 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 new file mode 100644 index 0000000000..a63a9f8c95 Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_8.crt differ 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 new file mode 100644 index 0000000000..59a77df71e Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_1_Root_9.crt differ 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 new file mode 100644 index 0000000000..3b12b29c16 Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_2_Root_4.crt differ 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 new file mode 100644 index 0000000000..c11e716d7c Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_2_Root_7.crt differ 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 new file mode 100644 index 0000000000..026274f632 Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_1_Sub_CA_2_Root_8.crt differ 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 new file mode 100644 index 0000000000..4a026790e7 Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_20_Root_11.crt differ 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 new file mode 100644 index 0000000000..46b008eebf Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_21_Root_11.crt differ 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 new file mode 100644 index 0000000000..7c1c2cb29f Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_22_Root_11.crt differ 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 new file mode 100644 index 0000000000..cc6185cc93 Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_23_Root_11.crt differ 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 new file mode 100644 index 0000000000..fa646e4029 Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_24_Root_11.crt differ 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 new file mode 100644 index 0000000000..673db6cc92 Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_25_Root_11.crt differ 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 new file mode 100644 index 0000000000..e284dca9b5 Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_26_Root_11.crt differ 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 new file mode 100644 index 0000000000..5b2cda4613 Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_27_Root_11.crt differ 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 new file mode 100644 index 0000000000..532010b18c Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_28_Root_11.crt differ 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 new file mode 100644 index 0000000000..282aa47af3 Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_29_Root_11.crt differ 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 new file mode 100644 index 0000000000..26a51418fd Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_2_Root_11.crt differ 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 new file mode 100644 index 0000000000..8a00d30080 Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_1_Root_4.crt differ 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 new file mode 100644 index 0000000000..935da38c23 Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_1_Root_7.crt differ 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 new file mode 100644 index 0000000000..79ea4fbcfe Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_1_Root_8.crt differ 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 new file mode 100644 index 0000000000..011c4ae2a8 Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_2_Root_4.crt differ 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 new file mode 100644 index 0000000000..b142544288 Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_2_Root_7.crt differ 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 new file mode 100644 index 0000000000..8c8689e10e Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_2_Sub_CA_2_Root_8.crt differ 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 new file mode 100644 index 0000000000..ed39bea1ec Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_30_Root_11.crt differ 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 new file mode 100644 index 0000000000..7f9e136986 Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_31_Root_11.crt differ 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 new file mode 100644 index 0000000000..dc28470c8b Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_32_Root_11.crt differ 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 new file mode 100644 index 0000000000..df9d81d8d1 Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_33_Root_11.crt differ 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 new file mode 100644 index 0000000000..018da383d7 Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_34_Root_11.crt differ diff --git a/xmlsecurity/test_docs/certs/end_certs/User_35_Root_11.crt b/xmlsecurity/test_docs/certs/end_certs/User_35_Root_11.crt new file mode 100644 index 0000000000..0092d16c7a --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_35_Root_11.crt @@ -0,0 +1,64 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4130 (0x1022) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Nov 8 10:51:39 2010 GMT + Not After : Nov 8 10:51:39 2011 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 35 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:9b:36:00:64:f3:ce:93:97:62:19:fa:78:d9:6f: + 92:6a:b9:d2:9a:4e:06:2c:02:52:cd:93:50:84:28: + 19:42:a2:4a:34:e2:cd:e6:b0:39:7a:c8:4d:84:bc: + 71:51:ed:5d:6c:7e:f9:cc:01:5a:4b:73:50:a9:3b: + 5d:ad:cc:89:f7:dc:e0:dd:0a:ff:48:01:a9:34:19: + c0:6a:ee:4b:20:f4:cf:3c:94:c1:ae:88:0f:c9:42: + 1a:a6:47:31:fe:37:04:00:bb:ec:07:5f:cb:ee:70: + c4:c7:7c:6f:ee:03:19:76:de:0b:df:d0:48:91:67: + 55:9b:90:91:f4:ce:56:04:d5 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 91:47:AC:29:95:5D:EF:72:14:8F:82:45:07:E2:94:49:75:C6:7D:73 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DNS:alt.openoffice.org, IP Address:192.168.7.1, IP Address:13:0:0:0:0:0:0:17, email:my@other.address, Registered ID:1.2.3.4, othername:, 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 new file mode 100644 index 0000000000..879f4578c0 Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_3_Root_11.crt differ 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 new file mode 100644 index 0000000000..75a9c7c843 Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_4_Root_11.crt differ 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 new file mode 100644 index 0000000000..cf07f4aa2c Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_5_Root_11.crt differ 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 new file mode 100644 index 0000000000..993a09f957 Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_6_Root_11.crt differ 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 new file mode 100644 index 0000000000..a1cebacb3b Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_7_Root_11.crt differ 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 new file mode 100644 index 0000000000..12410ebc81 Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_8_Root_11.crt differ 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 new file mode 100644 index 0000000000..f7372d09f3 Binary files /dev/null and b/xmlsecurity/test_docs/certs/end_certs/User_9_Root_11.crt differ diff --git a/xmlsecurity/test_docs/certs/p12/Root_11.p12 b/xmlsecurity/test_docs/certs/p12/Root_11.p12 new file mode 100644 index 0000000000..7df592643e Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/Root_11.p12 differ diff --git a/xmlsecurity/test_docs/certs/p12/User_10_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_10_Root_11.p12 new file mode 100644 index 0000000000..048ca8e8f5 Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_10_Root_11.p12 differ diff --git a/xmlsecurity/test_docs/certs/p12/User_11_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_11_Root_11.p12 new file mode 100644 index 0000000000..4498cdb76e Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_11_Root_11.p12 differ diff --git a/xmlsecurity/test_docs/certs/p12/User_12_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_12_Root_11.p12 new file mode 100644 index 0000000000..d85e0b7d47 Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_12_Root_11.p12 differ diff --git a/xmlsecurity/test_docs/certs/p12/User_13_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_13_Root_11.p12 new file mode 100644 index 0000000000..ff666ff1e5 Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_13_Root_11.p12 differ diff --git a/xmlsecurity/test_docs/certs/p12/User_14_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_14_Root_11.p12 new file mode 100644 index 0000000000..55e0d6233e Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_14_Root_11.p12 differ diff --git a/xmlsecurity/test_docs/certs/p12/User_15_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_15_Root_11.p12 new file mode 100644 index 0000000000..baa32f26b7 Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_15_Root_11.p12 differ diff --git a/xmlsecurity/test_docs/certs/p12/User_16_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_16_Root_11.p12 new file mode 100644 index 0000000000..7b20ff98cf Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_16_Root_11.p12 differ diff --git a/xmlsecurity/test_docs/certs/p12/User_17_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_17_Root_11.p12 new file mode 100644 index 0000000000..6e980df49e Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_17_Root_11.p12 differ diff --git a/xmlsecurity/test_docs/certs/p12/User_18_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_18_Root_11.p12 new file mode 100644 index 0000000000..4d343d6e76 Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_18_Root_11.p12 differ diff --git a/xmlsecurity/test_docs/certs/p12/User_19_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_19_Root_11.p12 new file mode 100644 index 0000000000..aa5f27d2d9 Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_19_Root_11.p12 differ diff --git a/xmlsecurity/test_docs/certs/p12/User_1_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_1_Root_11.p12 new file mode 100644 index 0000000000..80e5bf47c0 Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_1_Root_11.p12 differ 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 new file mode 100644 index 0000000000..1e9a14cb8a Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_1.p12 differ 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 new file mode 100644 index 0000000000..d7096919be Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_10.p12 differ 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 new file mode 100644 index 0000000000..adc61fff40 Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_2.p12 differ 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 new file mode 100644 index 0000000000..9213427a16 Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_3.p12 differ 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 new file mode 100644 index 0000000000..005191d164 Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_4.p12 differ 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 new file mode 100644 index 0000000000..e4599b113a Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_5.p12 differ 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 new file mode 100644 index 0000000000..32b4926ad7 Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_6.p12 differ 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 new file mode 100644 index 0000000000..2c0ea4acbf Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_7.p12 differ 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 new file mode 100644 index 0000000000..b69a19e4e1 Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_8.p12 differ 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 new file mode 100644 index 0000000000..7897733c4e Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_1_Root_9.p12 differ 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 new file mode 100644 index 0000000000..99eb944528 Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_2_Root_4.p12 differ 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 new file mode 100644 index 0000000000..1aefff504e Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_2_Root_7.p12 differ 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 new file mode 100644 index 0000000000..6b6d5fd4e7 Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_1_Sub_CA_2_Root_8.p12 differ diff --git a/xmlsecurity/test_docs/certs/p12/User_20_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_20_Root_11.p12 new file mode 100644 index 0000000000..bebfdc88a6 Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_20_Root_11.p12 differ diff --git a/xmlsecurity/test_docs/certs/p12/User_21_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_21_Root_11.p12 new file mode 100644 index 0000000000..cbd6730a84 Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_21_Root_11.p12 differ diff --git a/xmlsecurity/test_docs/certs/p12/User_22_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_22_Root_11.p12 new file mode 100644 index 0000000000..ab2b651c1f Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_22_Root_11.p12 differ diff --git a/xmlsecurity/test_docs/certs/p12/User_23_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_23_Root_11.p12 new file mode 100644 index 0000000000..518388c5b4 Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_23_Root_11.p12 differ diff --git a/xmlsecurity/test_docs/certs/p12/User_24_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_24_Root_11.p12 new file mode 100644 index 0000000000..775b1359dc Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_24_Root_11.p12 differ diff --git a/xmlsecurity/test_docs/certs/p12/User_25_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_25_Root_11.p12 new file mode 100644 index 0000000000..f76a61869c Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_25_Root_11.p12 differ diff --git a/xmlsecurity/test_docs/certs/p12/User_26_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_26_Root_11.p12 new file mode 100644 index 0000000000..ef1273c724 Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_26_Root_11.p12 differ diff --git a/xmlsecurity/test_docs/certs/p12/User_27_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_27_Root_11.p12 new file mode 100644 index 0000000000..4208dc4316 Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_27_Root_11.p12 differ diff --git a/xmlsecurity/test_docs/certs/p12/User_28_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_28_Root_11.p12 new file mode 100644 index 0000000000..4826f2d045 Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_28_Root_11.p12 differ diff --git a/xmlsecurity/test_docs/certs/p12/User_29_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_29_Root_11.p12 new file mode 100644 index 0000000000..bc211718a5 Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_29_Root_11.p12 differ diff --git a/xmlsecurity/test_docs/certs/p12/User_2_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_2_Root_11.p12 new file mode 100644 index 0000000000..876151de3f Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_2_Root_11.p12 differ 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 new file mode 100644 index 0000000000..268eeb9387 Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_1_Root_4.p12 differ 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 new file mode 100644 index 0000000000..2fc86b9afd Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_1_Root_7.p12 differ 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 new file mode 100644 index 0000000000..80dd6a8b08 Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_1_Root_8.p12 differ 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 new file mode 100644 index 0000000000..821bb8ea50 Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_2_Root_4.p12 differ 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 new file mode 100644 index 0000000000..3671d176d9 Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_2_Root_7.p12 differ 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 new file mode 100644 index 0000000000..a4c63b7f23 Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_2_Sub_CA_2_Root_8.p12 differ diff --git a/xmlsecurity/test_docs/certs/p12/User_30_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_30_Root_11.p12 new file mode 100644 index 0000000000..99b0be699a Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_30_Root_11.p12 differ diff --git a/xmlsecurity/test_docs/certs/p12/User_31_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_31_Root_11.p12 new file mode 100644 index 0000000000..5dbaf524c3 Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_31_Root_11.p12 differ diff --git a/xmlsecurity/test_docs/certs/p12/User_32_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_32_Root_11.p12 new file mode 100644 index 0000000000..17e22f7a5b Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_32_Root_11.p12 differ diff --git a/xmlsecurity/test_docs/certs/p12/User_33_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_33_Root_11.p12 new file mode 100644 index 0000000000..5982532a97 Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_33_Root_11.p12 differ diff --git a/xmlsecurity/test_docs/certs/p12/User_34_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_34_Root_11.p12 new file mode 100644 index 0000000000..4c00b21d45 Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_34_Root_11.p12 differ diff --git a/xmlsecurity/test_docs/certs/p12/User_3_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_3_Root_11.p12 new file mode 100644 index 0000000000..bc476b2572 Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_3_Root_11.p12 differ diff --git a/xmlsecurity/test_docs/certs/p12/User_4_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_4_Root_11.p12 new file mode 100644 index 0000000000..0b9bd319b5 Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_4_Root_11.p12 differ diff --git a/xmlsecurity/test_docs/certs/p12/User_5_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_5_Root_11.p12 new file mode 100644 index 0000000000..99de803de3 Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_5_Root_11.p12 differ diff --git a/xmlsecurity/test_docs/certs/p12/User_6_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_6_Root_11.p12 new file mode 100644 index 0000000000..a663a92d9b Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_6_Root_11.p12 differ diff --git a/xmlsecurity/test_docs/certs/p12/User_7_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_7_Root_11.p12 new file mode 100644 index 0000000000..c3d4e7532f Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_7_Root_11.p12 differ diff --git a/xmlsecurity/test_docs/certs/p12/User_8_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_8_Root_11.p12 new file mode 100644 index 0000000000..9db9c0ad4a Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_8_Root_11.p12 differ diff --git a/xmlsecurity/test_docs/certs/p12/User_9_Root_11.p12 b/xmlsecurity/test_docs/certs/p12/User_9_Root_11.p12 new file mode 100644 index 0000000000..ccb03b327d Binary files /dev/null and b/xmlsecurity/test_docs/certs/p12/User_9_Root_11.p12 differ diff --git a/xmlsecurity/test_docs/documents/aia_ca_issuers.odt b/xmlsecurity/test_docs/documents/aia_ca_issuers.odt new file mode 100644 index 0000000000..8c34889df7 Binary files /dev/null and b/xmlsecurity/test_docs/documents/aia_ca_issuers.odt differ diff --git a/xmlsecurity/test_docs/documents/aia_ocsp.odt b/xmlsecurity/test_docs/documents/aia_ocsp.odt new file mode 100644 index 0000000000..6a1b48c6ae Binary files /dev/null and b/xmlsecurity/test_docs/documents/aia_ocsp.odt differ diff --git a/xmlsecurity/test_docs/documents/aia_ocsp_revoked_chain.odt b/xmlsecurity/test_docs/documents/aia_ocsp_revoked_chain.odt new file mode 100644 index 0000000000..248fcceddc Binary files /dev/null and b/xmlsecurity/test_docs/documents/aia_ocsp_revoked_chain.odt differ diff --git a/xmlsecurity/test_docs/documents/aia_ocsp_revoked_leaf.odt b/xmlsecurity/test_docs/documents/aia_ocsp_revoked_leaf.odt new file mode 100644 index 0000000000..2e0dbd6f7a Binary files /dev/null and b/xmlsecurity/test_docs/documents/aia_ocsp_revoked_leaf.odt differ diff --git a/xmlsecurity/test_docs/documents/aia_ocsp_revoked_leaf_chain.odt b/xmlsecurity/test_docs/documents/aia_ocsp_revoked_leaf_chain.odt new file mode 100644 index 0000000000..3519e4a818 Binary files /dev/null and b/xmlsecurity/test_docs/documents/aia_ocsp_revoked_leaf_chain.odt differ diff --git a/xmlsecurity/test_docs/documents/crl.odt b/xmlsecurity/test_docs/documents/crl.odt new file mode 100644 index 0000000000..06e412fa3c Binary files /dev/null and b/xmlsecurity/test_docs/documents/crl.odt differ diff --git a/xmlsecurity/test_docs/documents/crl_revoked_chain.odt b/xmlsecurity/test_docs/documents/crl_revoked_chain.odt new file mode 100644 index 0000000000..851fc87e76 Binary files /dev/null and b/xmlsecurity/test_docs/documents/crl_revoked_chain.odt differ diff --git a/xmlsecurity/test_docs/documents/crl_revoked_leaf.odt b/xmlsecurity/test_docs/documents/crl_revoked_leaf.odt new file mode 100644 index 0000000000..a97598d554 Binary files /dev/null and b/xmlsecurity/test_docs/documents/crl_revoked_leaf.odt differ diff --git a/xmlsecurity/test_docs/documents/crl_revoked_leaf_chain.odt b/xmlsecurity/test_docs/documents/crl_revoked_leaf_chain.odt new file mode 100644 index 0000000000..f82a02a454 Binary files /dev/null and b/xmlsecurity/test_docs/documents/crl_revoked_leaf_chain.odt differ diff --git a/xmlsecurity/test_docs/documents/crldp.odt b/xmlsecurity/test_docs/documents/crldp.odt new file mode 100644 index 0000000000..5cbf289de3 Binary files /dev/null and b/xmlsecurity/test_docs/documents/crldp.odt differ 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 new file mode 100644 index 0000000000..20c28d9252 Binary files /dev/null and b/xmlsecurity/test_docs/documents/crldp_no_intermediate_ca_revocation_info.odt differ diff --git a/xmlsecurity/test_docs/documents/crldp_no_root_revocation_info.odt b/xmlsecurity/test_docs/documents/crldp_no_root_revocation_info.odt new file mode 100644 index 0000000000..d3f59e6015 Binary files /dev/null and b/xmlsecurity/test_docs/documents/crldp_no_root_revocation_info.odt differ diff --git a/xmlsecurity/test_docs/documents/crldp_revoked_chain.odt b/xmlsecurity/test_docs/documents/crldp_revoked_chain.odt new file mode 100644 index 0000000000..8c6416b808 Binary files /dev/null and b/xmlsecurity/test_docs/documents/crldp_revoked_chain.odt differ diff --git a/xmlsecurity/test_docs/documents/crldp_revoked_leaf.odt b/xmlsecurity/test_docs/documents/crldp_revoked_leaf.odt new file mode 100644 index 0000000000..fce479cc66 Binary files /dev/null and b/xmlsecurity/test_docs/documents/crldp_revoked_leaf.odt differ diff --git a/xmlsecurity/test_docs/documents/crldp_revoked_leaf_chain.odt b/xmlsecurity/test_docs/documents/crldp_revoked_leaf_chain.odt new file mode 100644 index 0000000000..53d1e01e7a Binary files /dev/null and b/xmlsecurity/test_docs/documents/crldp_revoked_leaf_chain.odt differ diff --git a/xmlsecurity/test_docs/documents/dn_cyrillic_bmpstring.odt b/xmlsecurity/test_docs/documents/dn_cyrillic_bmpstring.odt new file mode 100644 index 0000000000..1f69a32482 Binary files /dev/null and b/xmlsecurity/test_docs/documents/dn_cyrillic_bmpstring.odt differ diff --git a/xmlsecurity/test_docs/documents/dn_latin_ext_greak_bmpstring.odt b/xmlsecurity/test_docs/documents/dn_latin_ext_greak_bmpstring.odt new file mode 100644 index 0000000000..53a29310e9 Binary files /dev/null and b/xmlsecurity/test_docs/documents/dn_latin_ext_greak_bmpstring.odt differ diff --git a/xmlsecurity/test_docs/documents/dn_multivalue_rdn.odt b/xmlsecurity/test_docs/documents/dn_multivalue_rdn.odt new file mode 100644 index 0000000000..4d34bc0f58 Binary files /dev/null and b/xmlsecurity/test_docs/documents/dn_multivalue_rdn.odt differ diff --git a/xmlsecurity/test_docs/documents/dn_quoting.odt b/xmlsecurity/test_docs/documents/dn_quoting.odt new file mode 100644 index 0000000000..ca17f6aab6 Binary files /dev/null and b/xmlsecurity/test_docs/documents/dn_quoting.odt differ diff --git a/xmlsecurity/test_docs/documents/dn_single_multivalue_rdn.odt b/xmlsecurity/test_docs/documents/dn_single_multivalue_rdn.odt new file mode 100644 index 0000000000..798f25a353 Binary files /dev/null and b/xmlsecurity/test_docs/documents/dn_single_multivalue_rdn.odt differ 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 new file mode 100644 index 0000000000..591f9aa4d6 Binary files /dev/null and b/xmlsecurity/test_docs/documents/dn_single_multivalue_rdn_with_quoting.odt differ diff --git a/xmlsecurity/test_docs/documents/incomplete_path.odt b/xmlsecurity/test_docs/documents/incomplete_path.odt new file mode 100644 index 0000000000..cb0763b0a1 Binary files /dev/null and b/xmlsecurity/test_docs/documents/incomplete_path.odt differ diff --git a/xmlsecurity/test_docs/documents/invalid_ooo2_x_doc1.odt b/xmlsecurity/test_docs/documents/invalid_ooo2_x_doc1.odt new file mode 100644 index 0000000000..f0555b1a2d Binary files /dev/null and b/xmlsecurity/test_docs/documents/invalid_ooo2_x_doc1.odt differ diff --git a/xmlsecurity/test_docs/documents/invalid_ooo2_x_doc2.odt b/xmlsecurity/test_docs/documents/invalid_ooo2_x_doc2.odt new file mode 100644 index 0000000000..b2e24fc617 Binary files /dev/null and b/xmlsecurity/test_docs/documents/invalid_ooo2_x_doc2.odt differ diff --git a/xmlsecurity/test_docs/documents/invalid_ooo2_x_macro1.odt b/xmlsecurity/test_docs/documents/invalid_ooo2_x_macro1.odt new file mode 100644 index 0000000000..640a80dced Binary files /dev/null and b/xmlsecurity/test_docs/documents/invalid_ooo2_x_macro1.odt differ diff --git a/xmlsecurity/test_docs/documents/invalid_ooo2_x_macro2.odt b/xmlsecurity/test_docs/documents/invalid_ooo2_x_macro2.odt new file mode 100644 index 0000000000..35847216be Binary files /dev/null and b/xmlsecurity/test_docs/documents/invalid_ooo2_x_macro2.odt differ diff --git a/xmlsecurity/test_docs/documents/invalid_ooo2_x_macro3.odt b/xmlsecurity/test_docs/documents/invalid_ooo2_x_macro3.odt new file mode 100644 index 0000000000..575f3a12d0 Binary files /dev/null and b/xmlsecurity/test_docs/documents/invalid_ooo2_x_macro3.odt differ diff --git a/xmlsecurity/test_docs/documents/invalid_ooo2_x_macro4.odt b/xmlsecurity/test_docs/documents/invalid_ooo2_x_macro4.odt new file mode 100644 index 0000000000..75a417cab6 Binary files /dev/null and b/xmlsecurity/test_docs/documents/invalid_ooo2_x_macro4.odt differ diff --git a/xmlsecurity/test_docs/documents/invalid_ooo2_x_macro5.odt b/xmlsecurity/test_docs/documents/invalid_ooo2_x_macro5.odt new file mode 100644 index 0000000000..f7d71762fd Binary files /dev/null and b/xmlsecurity/test_docs/documents/invalid_ooo2_x_macro5.odt differ diff --git a/xmlsecurity/test_docs/documents/invalid_ooo3_2_doc1.odt b/xmlsecurity/test_docs/documents/invalid_ooo3_2_doc1.odt new file mode 100644 index 0000000000..9984aa1bbb Binary files /dev/null and b/xmlsecurity/test_docs/documents/invalid_ooo3_2_doc1.odt differ diff --git a/xmlsecurity/test_docs/documents/invalid_ooo3_2_doc3.odt b/xmlsecurity/test_docs/documents/invalid_ooo3_2_doc3.odt new file mode 100644 index 0000000000..5ad7b68abb Binary files /dev/null and b/xmlsecurity/test_docs/documents/invalid_ooo3_2_doc3.odt differ diff --git a/xmlsecurity/test_docs/documents/invalid_ooo3_2_doc4.odt b/xmlsecurity/test_docs/documents/invalid_ooo3_2_doc4.odt new file mode 100644 index 0000000000..d126a8dff5 Binary files /dev/null and b/xmlsecurity/test_docs/documents/invalid_ooo3_2_doc4.odt differ diff --git a/xmlsecurity/test_docs/documents/invalid_ooo_3_2_doc2.odt b/xmlsecurity/test_docs/documents/invalid_ooo_3_2_doc2.odt new file mode 100644 index 0000000000..dd475c3549 Binary files /dev/null and b/xmlsecurity/test_docs/documents/invalid_ooo_3_2_doc2.odt differ diff --git a/xmlsecurity/test_docs/documents/ocsp_crl.odt b/xmlsecurity/test_docs/documents/ocsp_crl.odt new file mode 100644 index 0000000000..f8ab95c046 Binary files /dev/null and b/xmlsecurity/test_docs/documents/ocsp_crl.odt differ diff --git a/xmlsecurity/test_docs/documents/ocsp_crl_revoked_leaf.odt b/xmlsecurity/test_docs/documents/ocsp_crl_revoked_leaf.odt new file mode 100644 index 0000000000..4d7c5cd809 Binary files /dev/null and b/xmlsecurity/test_docs/documents/ocsp_crl_revoked_leaf.odt differ diff --git a/xmlsecurity/test_docs/documents/stateOrProvinceName.odt b/xmlsecurity/test_docs/documents/stateOrProvinceName.odt new file mode 100644 index 0000000000..0979ae5a9d Binary files /dev/null and b/xmlsecurity/test_docs/documents/stateOrProvinceName.odt differ diff --git a/xmlsecurity/test_docs/documents/valid_no_revocation.odt b/xmlsecurity/test_docs/documents/valid_no_revocation.odt new file mode 100644 index 0000000000..f7c9bbf5ed Binary files /dev/null and b/xmlsecurity/test_docs/documents/valid_no_revocation.odt differ diff --git a/xmlsecurity/test_docs/documents/valid_no_root_revocation_info.odt b/xmlsecurity/test_docs/documents/valid_no_root_revocation_info.odt new file mode 100644 index 0000000000..d26eb58f02 Binary files /dev/null and b/xmlsecurity/test_docs/documents/valid_no_root_revocation_info.odt differ 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 new file mode 100644 index 0000000000..5d6c053c2b Binary files /dev/null and b/xmlsecurity/test_docs/documents/valid_no_sub_ca_revocation_info.odt differ diff --git a/xmlsecurity/test_docs/documents/valid_ooo2_x_doc1.odt b/xmlsecurity/test_docs/documents/valid_ooo2_x_doc1.odt new file mode 100644 index 0000000000..cb6401c164 Binary files /dev/null and b/xmlsecurity/test_docs/documents/valid_ooo2_x_doc1.odt differ diff --git a/xmlsecurity/test_docs/documents/valid_ooo2_x_doc_macro.odt b/xmlsecurity/test_docs/documents/valid_ooo2_x_doc_macro.odt new file mode 100644 index 0000000000..09b63b40a3 Binary files /dev/null and b/xmlsecurity/test_docs/documents/valid_ooo2_x_doc_macro.odt differ 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 new file mode 100644 index 0000000000..e810d785d1 Binary files /dev/null and b/xmlsecurity/test_docs/documents/valid_ooo2_x_doc_unsigned_macro.odt differ diff --git a/xmlsecurity/test_docs/documents/valid_ooo3_0_doc1.odt b/xmlsecurity/test_docs/documents/valid_ooo3_0_doc1.odt new file mode 100644 index 0000000000..6c2bbd045a Binary files /dev/null and b/xmlsecurity/test_docs/documents/valid_ooo3_0_doc1.odt differ diff --git a/xmlsecurity/test_docs/documents/valid_ooo3_0_doc_macro.odt b/xmlsecurity/test_docs/documents/valid_ooo3_0_doc_macro.odt new file mode 100644 index 0000000000..b8b036cc8f Binary files /dev/null and b/xmlsecurity/test_docs/documents/valid_ooo3_0_doc_macro.odt differ 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 new file mode 100644 index 0000000000..6ba0ec52a9 Binary files /dev/null and b/xmlsecurity/test_docs/documents/valid_ooo3_0_doc_unsigned_macro.odt differ diff --git a/xmlsecurity/test_docs/documents/valid_ooo3_2_doc1.odt b/xmlsecurity/test_docs/documents/valid_ooo3_2_doc1.odt new file mode 100644 index 0000000000..de1c635c19 Binary files /dev/null and b/xmlsecurity/test_docs/documents/valid_ooo3_2_doc1.odt differ diff --git a/xmlsecurity/test_docs/documents/valid_ooo3_2_doc_macro.odt b/xmlsecurity/test_docs/documents/valid_ooo3_2_doc_macro.odt new file mode 100644 index 0000000000..f6575ec885 Binary files /dev/null and b/xmlsecurity/test_docs/documents/valid_ooo3_2_doc_macro.odt differ 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 new file mode 100644 index 0000000000..41f676f637 Binary files /dev/null and b/xmlsecurity/test_docs/documents/valid_ooo3_2_doc_unsigned_macro.odt differ diff --git a/xmlsecurity/test_docs/test_description.odt b/xmlsecurity/test_docs/test_description.odt new file mode 100644 index 0000000000..45bbb5b0d4 Binary files /dev/null and b/xmlsecurity/test_docs/test_description.odt differ diff --git a/xmlsecurity/test_docs/tools/README.txt b/xmlsecurity/test_docs/tools/README.txt new file mode 100644 index 0000000000..b253a78b69 --- /dev/null +++ b/xmlsecurity/test_docs/tools/README.txt @@ -0,0 +1,24 @@ +httpserv +============ +Simple http server for testing of Certificate Revocation Lists (CRL). + +Netbeans 6.7.1 project. httpserv.jar requires java 6. + +Run with + +java -jar httpserv/dist/httpserv.jar --accept portnumber + +portnumber: an arbitrary port number to which the server should listen. + +httpserv looks for the requested file relative to the current directory. For +example, you are in +$(SRC_ROOT)/xmlsecurity/$(INPATH)/httpserv/dist/javadoc, +a directory which contains the index.html. From there you run httpserv.jar: + +java -jar /httpserv.jar --accept 8000 + +now enter in the Browser: + +localhost:8000/index.html + + diff --git a/xmlsecurity/test_docs/tools/httpserv/build.xml b/xmlsecurity/test_docs/tools/httpserv/build.xml new file mode 100644 index 0000000000..3492d3aa61 --- /dev/null +++ b/xmlsecurity/test_docs/tools/httpserv/build.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + Builds, tests, and runs the project httpserv. + + + + + + + diff --git a/xmlsecurity/test_docs/tools/httpserv/manifest.mf b/xmlsecurity/test_docs/tools/httpserv/manifest.mf new file mode 100644 index 0000000000..328e8e5bc3 --- /dev/null +++ b/xmlsecurity/test_docs/tools/httpserv/manifest.mf @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +X-COMMENT: Main-Class will be added automatically by build + diff --git a/xmlsecurity/test_docs/tools/httpserv/nbproject/build-impl.xml b/xmlsecurity/test_docs/tools/httpserv/nbproject/build-impl.xml new file mode 100644 index 0000000000..9064a3305e --- /dev/null +++ b/xmlsecurity/test_docs/tools/httpserv/nbproject/build-impl.xml @@ -0,0 +1,700 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set src.dir + Must set test.src.dir + Must set build.dir + Must set dist.dir + Must set build.classes.dir + Must set dist.javadoc.dir + Must set build.test.classes.dir + Must set build.test.results.dir + Must set build.classes.excludes + Must set dist.jar + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + To run this application from the command line without Ant, try: + + + + + + + java -cp "${run.classpath.with.dist.jar}" ${main.class} + + + + + + + + + + + + + + + + + + + + + + + To run this application from the command line without Ant, try: + + java -jar "${dist.jar.resolved}" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set run.class + + + + Must select one file in the IDE or set run.class + + + + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set debug.class + + + + + Must select one file in the IDE or set debug.class + + + + + Must set fix.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + Some tests failed; see details above. + + + + + + + + + Must select some files in the IDE or set test.includes + + + + Some tests failed; see details above. + + + + + Must select one file in the IDE or set test.class + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set applet.url + + + + + + + + + Must select one file in the IDE or set applet.url + + + + + + + + + + + + + + + + + + + diff --git a/xmlsecurity/test_docs/tools/httpserv/nbproject/genfiles.properties b/xmlsecurity/test_docs/tools/httpserv/nbproject/genfiles.properties new file mode 100644 index 0000000000..d8139c8889 --- /dev/null +++ b/xmlsecurity/test_docs/tools/httpserv/nbproject/genfiles.properties @@ -0,0 +1,9 @@ +# x-no-translate +build.xml.data.CRC32=8071b819 +build.xml.script.CRC32=deb21e95 +build.xml.stylesheet.CRC32=958a1d3e@1.26.2.45 +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. +nbproject/build-impl.xml.data.CRC32=8071b819 +nbproject/build-impl.xml.script.CRC32=21d1be7e +nbproject/build-impl.xml.stylesheet.CRC32=5c621a33@1.26.2.45 diff --git a/xmlsecurity/test_docs/tools/httpserv/nbproject/project.properties b/xmlsecurity/test_docs/tools/httpserv/nbproject/project.properties new file mode 100644 index 0000000000..a0ec60ac7c --- /dev/null +++ b/xmlsecurity/test_docs/tools/httpserv/nbproject/project.properties @@ -0,0 +1,65 @@ +# x-no-translate +application.title=httpserv +application.vendor=jochen +build.classes.dir=${build.dir}/classes +build.classes.excludes=**/*.java,**/*.form +# This directory is removed when the project is cleaned: +build.dir=build +build.generated.dir=${build.dir}/generated +build.generated.sources.dir=${build.dir}/generated-sources +# Only compile against the classpath explicitly listed here: +build.sysclasspath=ignore +build.test.classes.dir=${build.dir}/test/classes +build.test.results.dir=${build.dir}/test/results +# Uncomment to specify the preferred debugger connection transport: +#debug.transport=dt_socket +debug.classpath=\ + ${run.classpath} +debug.test.classpath=\ + ${run.test.classpath} +# This directory is removed when the project is cleaned: +dist.dir=../../../${env.INPATH}/misc/httpserv +dist.jar=${dist.dir}/httpserv.jar +dist.javadoc.dir=${dist.dir}/javadoc +excludes= +includes=** +jar.compress=false +javac.classpath= +# Space-separated list of extra javac options +javac.compilerargs= +javac.deprecation=false +javac.source=1.5 +javac.target=1.5 +javac.test.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir}:\ + ${libs.junit.classpath}:\ + ${libs.junit_4.classpath} +javadoc.additionalparam= +javadoc.author=false +javadoc.encoding=${source.encoding} +javadoc.noindex=false +javadoc.nonavbar=false +javadoc.notree=false +javadoc.private=false +javadoc.splitindex=true +javadoc.use=true +javadoc.version=false +javadoc.windowtitle= +main.class=httpserv.Main +manifest.file=manifest.mf +meta.inf.dir=${src.dir}/META-INF +platform.active=default_platform +run.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir} +# Space-separated list of JVM arguments used when running the project +# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value +# or test-sys-prop.name=value to set system properties for unit tests): +run.jvmargs= +run.test.classpath=\ + ${javac.test.classpath}:\ + ${build.test.classes.dir} +source.encoding=UTF-8 +src.dir=src +test.src.dir=test diff --git a/xmlsecurity/test_docs/tools/httpserv/nbproject/project.xml b/xmlsecurity/test_docs/tools/httpserv/nbproject/project.xml new file mode 100644 index 0000000000..6fc771ca76 --- /dev/null +++ b/xmlsecurity/test_docs/tools/httpserv/nbproject/project.xml @@ -0,0 +1,15 @@ + + + org.netbeans.modules.java.j2seproject + + + httpserv + + + + + + + + + diff --git a/xmlsecurity/test_docs/tools/httpserv/src/httpserv/Main.java b/xmlsecurity/test_docs/tools/httpserv/src/httpserv/Main.java new file mode 100644 index 0000000000..1f9fd91d23 --- /dev/null +++ b/xmlsecurity/test_docs/tools/httpserv/src/httpserv/Main.java @@ -0,0 +1,190 @@ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +package httpserv; + +import com.sun.net.httpserver.Headers; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.net.InetSocketAddress; + +public class Main { + + /** + * @param args the command line arguments + */ + public static void main(String[] args) { + try { + + Option[] opts = new Option[2]; + opts[0] = new Option("--help", "-h", false); + opts[1] = new Option("--accept", "-a", true); + if (!parseOptions(args, opts)) { + return; + } + HttpServer server = HttpServer.create( + new InetSocketAddress((Integer) opts[1].value), 0); + server.createContext("/", new MyHandler()); + server.setExecutor(null); + server.start(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + static boolean parseOptions(String[] args, Option[] inout_options) { + if (args.length == 0) { + printUsage(); + return false; + } + + boolean bWrongArgs = true; + Option currentOpt = null; + + for (String s : args) { + // get the value for an option + if (currentOpt != null && currentOpt.bHasValue) { + //now we expect the value for the option + //check the type + try { + if (currentOpt.sLong.equals("--accept")) { + currentOpt.value = Integer.decode(s); + } + } catch (Exception e ) { + printUsage(); + return false; + } + currentOpt = null; + continue; + } else { + currentOpt = null; + } + + + // get the option + for (Option o : inout_options) { + if (s.equals(o.sLong) || s.equals(o.sShort)) { + bWrongArgs = false; + //special handling for --help + if (o.sLong.equals("--help")) { + printUsage(); + return false; + } + else + { + currentOpt = o; + break; + } + } + } + } + + if (bWrongArgs) { + printUsage(); + return false; + } + return true; + } + + static void printUsage() { + String usage = + "Usage: \n" + + "java -jar httpserv [options] \n" + + "\n" + + "Options are: \n" + + "-h --help \t this help \n" + + "-a --accept port \t the port number to which this server listens \n"; + System.out.println(usage); + } +} + +class MyHandler implements HttpHandler { + + public void handle(HttpExchange xchange) throws IOException { + try { + //First get the path to the file + String sRequestPath = xchange.getRequestURI().getPath(); + System.out.println("requested: " + sRequestPath); + File fileRequest = new File(new File(".").getCanonicalPath(), sRequestPath); + if (!fileRequest.exists()) { + throw new IOException("The file " + fileRequest + " does not exist!"); + } + else if (fileRequest.isDirectory()) { + throw new IOException(fileRequest + " is a directory!"); + } + + + //Read the file into a byte array + byte[] data = new byte[(int) fileRequest.length()]; + FileInputStream fr = new FileInputStream(fileRequest); + fr.read(data); + fr.close(); + + //set the Content-type header + Headers h = xchange.getResponseHeaders(); + String canonicalPath = fileRequest.getCanonicalPath(); + int lastIndex = canonicalPath.lastIndexOf("."); + String fileExtension = canonicalPath.substring(lastIndex + 1); + + if (fileExtension.equalsIgnoreCase("crl")) + { + h.set("Content-Type","application/pkix-crl"); + } + else if (fileExtension.equalsIgnoreCase("crt") + || fileExtension.equalsIgnoreCase("cer") + || fileExtension.equalsIgnoreCase("der")) + { + h.set("Content-Type", "application/x-x509-ca-cert"); + } + + //write out the requested file + xchange.sendResponseHeaders(200, data.length); + OutputStream os = xchange.getResponseBody(); + os.write(data); + os.close(); + System.out.println("delivered: " + fileRequest.toString()); + + } catch (Exception e) { + xchange.sendResponseHeaders(404, e.getMessage().length()); + OutputStream os = xchange.getResponseBody(); + os.write(e.getMessage().getBytes()); + os.close(); + System.out.println("Error: " + e.getMessage()); + } + } +} + +class Option { + + Option(String _sLong, String _sShort, boolean _bHasValue) { + sLong = _sLong; + sShort = _sShort; + bHasValue = _bHasValue; + } + String sLong; + String sShort; + boolean bHasValue; + Object value; +} + + diff --git a/xmlsecurity/uiconfig/ui/certdetails.ui b/xmlsecurity/uiconfig/ui/certdetails.ui new file mode 100644 index 0000000000..cc4ba21993 --- /dev/null +++ b/xmlsecurity/uiconfig/ui/certdetails.ui @@ -0,0 +1,119 @@ + + + + + + + + + + + + + + + + True + False + True + True + 6 + vertical + 12 + True + + + True + True + True + True + external + in + + + True + True + True + True + True + liststore3 + 0 + False + + + + + + True + 6 + Field + + + + 0 + + + + + + + True + 6 + Value + + + + 1 + + + + + + + The Details page of the View Certificate dialog displays detailed information about the certificate. + + + + + + + False + True + 0 + + + + + True + True + True + True + never + in + + + True + True + True + True + + + Use the value list box to view values and copy them to the clipboard. + + + + + + + False + True + 1 + + + + + The Details page of the View Certificate dialog displays detailed information about the certificate. + + + + diff --git a/xmlsecurity/uiconfig/ui/certgeneral.ui b/xmlsecurity/uiconfig/ui/certgeneral.ui new file mode 100644 index 0000000000..e0c0b48acd --- /dev/null +++ b/xmlsecurity/uiconfig/ui/certgeneral.ui @@ -0,0 +1,254 @@ + + + + + + True + False + 6 + vertical + 6 + + + True + False + 6 + + + True + False + xmlsecurity/res/certificate_40x56.png + + + False + True + 6 + 0 + + + + + True + False + Certificate Information + + + + + + False + True + 1 + + + + + The General page of the View Certificate dialog displays basic information about the certificate. + + + + + False + True + 6 + 0 + + + + + True + False + + + False + True + 1 + + + + + True + False + 36 + 36 + 108 + This certificate is validated. + 0 + + + + + + False + True + 2 + + + + + True + False + + + False + True + 3 + + + + + + True + False + 6 + 6 + + + True + False + Issued to: + 0 + + + + + + 0 + 0 + + + + + True + False + True + 0 + + + 1 + 0 + + + + + True + False + Issued by: + 0 + + + + + + 0 + 1 + + + + + True + False + 0 + + + 1 + 1 + + + + + True + False + Valid from: + 0 + + + + + + 0 + 2 + + + + + True + False + 6 + + + True + False + xmlsecurity/res/key_12.png + + + False + True + 0 + + + + + True + False + You have a private key that corresponds to this certificate. + + + False + True + 1 + + + + + 0 + 4 + 2 + + + + + True + False + Valid to: + 0 + + + + + + 0 + 3 + + + + + True + False + 0 + + + 1 + 2 + + + + + True + False + 0 + + + 1 + 3 + + + + + False + True + 4 + + + + diff --git a/xmlsecurity/uiconfig/ui/certpage.ui b/xmlsecurity/uiconfig/ui/certpage.ui new file mode 100644 index 0000000000..4e0579ac53 --- /dev/null +++ b/xmlsecurity/uiconfig/ui/certpage.ui @@ -0,0 +1,196 @@ + + + + + + + + + + + + + + True + False + True + True + 6 + vertical + 12 + + + + True + False + True + True + 6 + + + True + False + Certification path + True + signatures + 0 + + + 0 + 0 + + + + + View Certificate... + True + True + True + end + True + + + 0 + 2 + + + + + True + True + True + True + in + + + True + True + True + True + True + liststore3 + False + 0 + True + + + + + + True + 6 + + + + 0 + + + + + + + The Certificate Path page of the View Certificate dialog displays the location and the status of the certificate. + + + + + + + 0 + 1 + + + + + False + True + 0 + + + + + + True + False + True + True + 6 + + + True + False + Certification status + True + status + 0 + + + 0 + 0 + + + + + True + True + True + True + never + in + + + True + True + True + True + + + The Certificate Path page of the View Certificate dialog displays the location and the status of the certificate. + + + + + + + 0 + 1 + + + + + False + True + 1 + + + + + False + True + The certificate is OK. + + + False + True + 2 + + + + + False + True + The certificate could not be validated. + + + False + True + 3 + + + + + The Certificate Path page of the View Certificate dialog displays the location and the status of the certificate. + + + + diff --git a/xmlsecurity/uiconfig/ui/digitalsignaturesdialog.ui b/xmlsecurity/uiconfig/ui/digitalsignaturesdialog.ui new file mode 100644 index 0000000000..f701468e62 --- /dev/null +++ b/xmlsecurity/uiconfig/ui/digitalsignaturesdialog.ui @@ -0,0 +1,508 @@ + + + + + + + + + + + + + + + + + + + + + + + + False + 6 + Digital Signatures + True + dialog + + + False + vertical + 12 + + + False + end + + + _Help + True + True + True + True + + + False + True + 0 + True + + + + + _Close + True + True + True + True + True + True + + + False + True + 1 + + + + + False + True + end + 0 + + + + + + True + False + True + True + 6 + + + False + True + The following have signed the document content: + 0 + + + 0 + 0 + + + + + True + True + True + True + in + + + True + True + True + True + True + liststore3 + 0 + False + + + + + + True + 6 + + + + 0 + + + + + + + True + 6 + Signed by + + + + 1 + + + + + + + True + 6 + Digital ID issued by + + + + 2 + + + + + + + True + 6 + Date + + + + 3 + + + + + + + True + 6 + Description + + + + 4 + + + + + + + True + 6 + Signature type + + + + 5 + + + + + + + Lists the digital signatures for the current document. + + + + + + + 0 + 4 + + + + + True + False + 12 + True + end + + + View Certificate... + True + True + True + + + Opens the View Certificate dialog. + + + + + True + True + 0 + + + + + Sign Document... + True + True + True + True + + + Opens the Select Certificate dialog. + + + + + True + True + 1 + + + + + Remove + True + True + True + + + Removes the selected signature from the list. Removes all subsequent signatures as well, in case of PDF. + + + + + True + True + 2 + + + + + Start Certificate Manager... + True + True + True + + + True + True + 3 + + + + + 0 + 7 + + + + + + True + False + True + 12 + + + False + True + True + + + 0 + 0 + + + + + False + True + True + + + 1 + 0 + + + + + False + True + True + + + 2 + 0 + + + + + False + True + + + 3 + 0 + + + + + False + True + + + 4 + 0 + + + + + 0 + 3 + + + + + False + True + The following have signed the document macro: + 0 + + + 0 + 1 + + + + + False + True + The following have signed this package: + 0 + + + 0 + 2 + + + + + + True + False + 12 + + + False + True + True + The signatures in this document are valid + 0 + + + 1 + 0 + + + + + False + True + xmlsecurity/res/signet_11x16.png + + + 0 + 0 + + + + + False + True + True + The signatures in this document are invalid + 0 + + + 1 + 2 + + + + + False + True + True + At least one signature has problems: the document is only partially signed. + 0 + + + 1 + 1 + + + + + False + True + True + At least one signature has problems: the certificate could not be validated. + 0 + + + 1 + 3 + + + + + False + True + svx/res/caution_11x16.png + + + 0 + 2 + + + + + False + True + svx/res/caution_11x16.png + + + 0 + 1 + + + + + False + True + xmlsecurity/res/notcertificate_16.png + + + 0 + 3 + + + + + 0 + 5 + + + + + True + True + 1 + + + + + + help + close + + + + + + + Adds and removes digital signatures to and from your document. You can also use the dialog to view certificates. + + + + diff --git a/xmlsecurity/uiconfig/ui/macrosecuritydialog.ui b/xmlsecurity/uiconfig/ui/macrosecuritydialog.ui new file mode 100644 index 0000000000..06699d588f --- /dev/null +++ b/xmlsecurity/uiconfig/ui/macrosecuritydialog.ui @@ -0,0 +1,208 @@ + + + + + + False + 6 + Macro Security + True + 0 + 0 + dialog + + + + + + False + vertical + 12 + + + False + end + + + _Reset + True + True + True + True + + + False + True + 0 + + + + + _OK + True + True + True + True + True + True + + + False + True + 1 + + + + + _Cancel + True + True + True + True + + + False + True + 2 + + + + + _Help + True + True + True + True + + + False + True + 3 + True + + + + + False + True + end + 0 + + + + + True + True + True + True + True + True + + + + True + False + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + True + False + Security Level + + + False + + + + + + True + False + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + + True + False + Trusted Sources + + + 1 + False + + + + + False + True + 1 + + + + + + reset + ok + cancel + help + + + diff --git a/xmlsecurity/uiconfig/ui/securitylevelpage.ui b/xmlsecurity/uiconfig/ui/securitylevelpage.ui new file mode 100644 index 0000000000..5292a72fcf --- /dev/null +++ b/xmlsecurity/uiconfig/ui/securitylevelpage.ui @@ -0,0 +1,160 @@ + + + + + + + True + False + True + True + 6 + vertical + 6 + 12 + True + + + _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. + True + True + False + True + True + True + high + + + 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. + + + + + 1 + 3 + + + + + _Medium. +Confirmation required before executing macros from untrusted sources. + True + True + False + True + True + True + high + + + 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. + + + + + 1 + 2 + + + + + H_igh. +Only signed macros and macros from trusted file locations are executed. +Unsigned macros are disabled. + True + True + False + True + True + True + True + + + Only signed macros or macros from a trusted file location are allowed to run. Macros signed with untrusted certificates will require confirmation to run, when located in untrusted file locations. Trusted certificates and trusted file locations can be set on the Trusted Sources tab page. + + + + + 1 + 1 + + + + + _Very high. +Only macros from trusted file locations are allowed to run. +All other macros, regardless whether signed or not, are disabled. + True + True + False + True + True + True + high + + + Trusted file locations can be set on the Trusted Sources tab page. Any macro from a trusted file location is allowed to run. + + + + + 1 + 0 + + + + + False + True + center + center + res/lock.png + + + 0 + 0 + + + + + False + True + center + center + res/lock.png + + + 0 + 1 + + + + + False + True + center + center + res/lock.png + + + 0 + 2 + + + + + False + True + center + center + res/lock.png + + + 0 + 3 + + + + diff --git a/xmlsecurity/uiconfig/ui/securitytrustpage.ui b/xmlsecurity/uiconfig/ui/securitytrustpage.ui new file mode 100644 index 0000000000..267efa8f08 --- /dev/null +++ b/xmlsecurity/uiconfig/ui/securitytrustpage.ui @@ -0,0 +1,392 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + True + False + True + True + 6 + vertical + 12 + + + True + False + True + True + 0 + none + + + + True + False + True + True + 6 + 6 + 12 + 6 + + + True + False + True + 12 + end + + + _View... + True + True + True + True + + + Opens the View Certificate dialog for the selected certificate. + + + + + False + True + 0 + + + + + _Remove + True + True + True + True + + + Removes the selected certificate from the list of trusted certificates. + + + + + False + True + 1 + + + + + 1 + 1 + + + + + True + True + True + True + in + + + True + True + True + True + True + liststore3 + 0 + False + + + + + + True + 6 + Issued to + + + + 0 + + + + + + + True + 6 + Issued by + + + + 1 + + + + + + + True + 6 + Expiration date + + + + 2 + + + + + + + Lists the trusted certificates. + + + + + + + 1 + 0 + + + + + False + True + center + center + res/lock.png + + + 0 + 0 + + + + + + + + + + True + False + Trusted Certificates + + + + + + + + False + True + 0 + + + + + True + False + True + True + 0 + none + + + + True + False + True + True + 12 + 6 + 12 + 6 + + + True + False + Document macros are always executed if they have been opened from one of the following locations. + True + 56 + 56 + 0 + + + 1 + 0 + + + + + True + False + 12 + end + + + A_dd... + True + True + True + True + + + Opens a folder selection dialog. Select a folder from which all macros are allowed to execute. + + + + + False + True + 0 + + + + + _Remove + True + True + True + True + + + Removes the selected folder from the list of trusted file locations. + + + + + False + True + 1 + + + + + 1 + 2 + + + + + True + True + True + True + in + + + True + True + True + True + True + liststore2 + False + 0 + False + + + + + + True + 6 + + + + 0 + + + + + + + Document macros are only executed if they have been opened from one of the following locations. + + + + + + + 1 + 1 + + + + + False + True + center + center + res/lock.png + + + 0 + 0 + + + + + + + + + + + + + True + False + Trusted File Locations + + + + + + + + False + True + 1 + + + + + + + + + + + vertical + + + + + + diff --git a/xmlsecurity/uiconfig/ui/selectcertificatedialog.ui b/xmlsecurity/uiconfig/ui/selectcertificatedialog.ui new file mode 100644 index 0000000000..aae6bd4402 --- /dev/null +++ b/xmlsecurity/uiconfig/ui/selectcertificatedialog.ui @@ -0,0 +1,324 @@ + + + + + + + + + + + + + + + + + + False + 6 + Select Certificate + False + True + dialog + + + False + vertical + 12 + + + False + end + + + _OK + True + True + True + True + True + True + + + False + True + 0 + + + + + _Cancel + True + True + True + True + + + False + True + 1 + + + + + _Help + True + True + True + True + + + False + True + 2 + True + + + + + False + True + end + 0 + + + + + + True + False + True + True + 12 + 12 + + + False + Select the certificate you want to use for signing: + 0 + + + 0 + 0 + + + + + False + Select the certificate you want to use for encryption: + 0 + + + 0 + 1 + + + + + True + True + True + True + in + + + True + True + True + True + True + liststore3 + 0 + False + + + + + + True + 6 + Issued to + True + 0 + + + + 0 + + + + + + + True + 6 + Issued by + True + 1 + + + + 1 + + + + + + + True + 6 + Expiration date + True + 2 + + + + 2 + + + + + + + Select the certificate that you want to digitally sign the current document with. + + + + + + + 0 + 3 + + + + + True + True + True + True + gtk-find + + + Search for certificate by issuer name or email. + + + + + 0 + 2 + + + + + True + False + 12 + + + True + False + Description: + + + False + True + 0 + + + + + True + True + True + True + + + Type a purpose for the signature. + + + + + True + True + 1 + + + + + 0 + 5 + + + + + True + False + end + 12 + + + View Certificate... + True + True + True + end + + + Opens the View Certificate dialog where you can examine the selected certificate. + + + + + False + True + 0 + + + + + Reload Certificates + True + True + True + end + + + Reload the list of certificates. + + + + + False + True + 1 + + + + + 0 + 4 + + + + + True + True + 1 + + + + + + ok + cancel + help + + + + Select the certificate that you want to digitally sign the current document with. + + + + diff --git a/xmlsecurity/uiconfig/ui/viewcertdialog.ui b/xmlsecurity/uiconfig/ui/viewcertdialog.ui new file mode 100644 index 0000000000..12cf4b40e6 --- /dev/null +++ b/xmlsecurity/uiconfig/ui/viewcertdialog.ui @@ -0,0 +1,227 @@ + + + + + + False + 6 + View Certificate + False + True + 0 + 0 + dialog + + + + + + False + vertical + 12 + + + False + end + + + _OK + True + True + True + True + True + True + + + False + True + 0 + + + + + _Help + True + True + True + True + + + False + True + 2 + True + + + + + False + True + end + 0 + + + + + True + True + True + True + True + True + + + + True + False + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + True + False + General + + + False + + + + + + True + False + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + + True + False + Details + + + 1 + False + + + + + + True + False + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + + + + + True + False + Certification Path + + + 2 + False + + + + + False + True + 1 + + + + + + ok + help + + + diff --git a/xmlsecurity/util/xmlsecurity.component b/xmlsecurity/util/xmlsecurity.component new file mode 100644 index 0000000000..7dfe91a0d9 --- /dev/null +++ b/xmlsecurity/util/xmlsecurity.component @@ -0,0 +1,31 @@ + + + + + + + + + + + + diff --git a/xmlsecurity/util/xmlsecurity.component.dds b/xmlsecurity/util/xmlsecurity.component.dds new file mode 100644 index 0000000000..5dc5f67653 --- /dev/null +++ b/xmlsecurity/util/xmlsecurity.component.dds @@ -0,0 +1,7 @@ +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +com.sun.star.security.DocumentDigitalSignatures diff --git a/xmlsecurity/util/xsec_xmlsec.component b/xmlsecurity/util/xsec_xmlsec.component new file mode 100644 index 0000000000..f2b072949a --- /dev/null +++ b/xmlsecurity/util/xsec_xmlsec.component @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xmlsecurity/util/xsec_xmlsec.component.gpg b/xmlsecurity/util/xsec_xmlsec.component.gpg new file mode 100644 index 0000000000..c770a555ba --- /dev/null +++ b/xmlsecurity/util/xsec_xmlsec.component.gpg @@ -0,0 +1,7 @@ +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +com.sun.star.xml.security.SEInitializer_Gpg diff --git a/xmlsecurity/util/xsec_xmlsec.component.nss b/xmlsecurity/util/xsec_xmlsec.component.nss new file mode 100644 index 0000000000..3ff9557b92 --- /dev/null +++ b/xmlsecurity/util/xsec_xmlsec.component.nss @@ -0,0 +1,7 @@ +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +com.sun.star.xml.crypto.NSSInitializer diff --git a/xmlsecurity/util/xsec_xmlsec.component.nss_mscrypt b/xmlsecurity/util/xsec_xmlsec.component.nss_mscrypt new file mode 100644 index 0000000000..c713c1e83f --- /dev/null +++ b/xmlsecurity/util/xsec_xmlsec.component.nss_mscrypt @@ -0,0 +1,10 @@ +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +com.sun.star.xml.crypto.SecurityEnvironment +com.sun.star.xml.crypto.SEInitializer +com.sun.star.xml.crypto.XMLSecurityContext +com.sun.star.xml.crypto.XMLSignature diff --git a/xmlsecurity/workben/pdfverify.cxx b/xmlsecurity/workben/pdfverify.cxx new file mode 100644 index 0000000000..361e0ae4ae --- /dev/null +++ b/xmlsecurity/workben/pdfverify.cxx @@ -0,0 +1,216 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace com::sun::star; + +namespace +{ +/// Does PDF to PNG conversion using pdfium. +void generatePreview(std::string_view rPdfPath, std::string_view rPngPath) +{ + GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter(); + Graphic aGraphic; + OUString aInURL; + osl::FileBase::getFileURLFromSystemPath(OUString::fromUtf8(rPdfPath), aInURL); + SvFileStream aInStream(aInURL, StreamMode::READ); + if (rFilter.ImportGraphic(aGraphic, u"", aInStream, GRFILTER_FORMAT_DONTKNOW, nullptr, + GraphicFilterImportFlags::NONE) + != ERRCODE_NONE) + return; + + BitmapEx aBitmapEx = aGraphic.GetBitmapEx(); + OUString aOutURL; + osl::FileBase::getFileURLFromSystemPath(OUString::fromUtf8(rPngPath), aOutURL); + SvFileStream aOutStream(aOutURL, StreamMode::WRITE); + vcl::PngImageWriter aWriter(aOutStream); + aWriter.write(aBitmapEx); +} + +int pdfVerify(int nArgc, char** pArgv) +{ + if (nArgc < 2) + { + SAL_WARN("xmlsecurity.workben", "not enough parameters"); + return 1; + } + + // Initialize nss / mscrypto. + uno::Reference xComponentContext; + try + { + xComponentContext = cppu::defaultBootstrap_InitialComponentContext(); + } + catch (const uno::RuntimeException&) + { + TOOLS_WARN_EXCEPTION("xmlsecurity.workben", + "cppu::defaultBootstrap_InitialComponentContext() failed:"); + return 1; + } + uno::Reference xMultiComponentFactory + = xComponentContext->getServiceManager(); + uno::Reference 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 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 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 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 xSecurityEnvironment + = xSecurityContext->getSecurityEnvironment(); + uno::Sequence> 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: */ -- cgit v1.2.3