From 940b4d1848e8c70ab7642901a68594e8016caffc Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 27 Apr 2024 18:51:28 +0200 Subject: Adding upstream version 1:7.0.4. 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 | 62 + xmlsecurity/CppunitTest_xmlsecurity_signing.mk | 74 + xmlsecurity/Executable_pdfverify.mk | 35 + xmlsecurity/IwyuFilter_xmlsecurity.yaml | 132 + xmlsecurity/Library_xmlsecurity.mk | 104 + xmlsecurity/Library_xsec_xmlsec.mk | 153 + xmlsecurity/Makefile | 14 + xmlsecurity/Module_xmlsecurity.mk | 49 + xmlsecurity/README | 4 + xmlsecurity/UIConfig_xmlsec.mk | 24 + .../doc/OpenDocumentSignatures-TestIntegration.sxw | Bin 0 -> 14189 bytes .../doc/OpenDocumentSignatures-Workflow.sxd | Bin 0 -> 10310 bytes xmlsecurity/doc/OpenDocumentSignatures.sxw | Bin 0 -> 16195 bytes xmlsecurity/doc/XMLSecurityFramework.sxw | Bin 0 -> 187975 bytes xmlsecurity/inc/biginteger.hxx | 38 + xmlsecurity/inc/bitmaps.hlst | 24 + xmlsecurity/inc/certificate.hxx | 46 + xmlsecurity/inc/certificatechooser.hxx | 98 + xmlsecurity/inc/certificateviewer.hxx | 159 + xmlsecurity/inc/digitalsignaturesdialog.hxx | 124 + xmlsecurity/inc/documentsignaturehelper.hxx | 111 + xmlsecurity/inc/documentsignaturemanager.hxx | 138 + xmlsecurity/inc/framework/saxeventkeeperimpl.hxx | 294 ++ xmlsecurity/inc/framework/securityengine.hxx | 145 + xmlsecurity/inc/framework/signaturecreatorimpl.hxx | 99 + xmlsecurity/inc/framework/signatureengine.hxx | 119 + .../inc/framework/signatureverifierimpl.hxx | 91 + .../inc/framework/xmlsignaturetemplateimpl.hxx | 98 + xmlsecurity/inc/gpg/SEInitializer.hxx | 50 + xmlsecurity/inc/gpg/xmlsignature_gpgimpl.hxx | 80 + xmlsecurity/inc/macrosecurity.hxx | 131 + xmlsecurity/inc/pch/precompiled_xmlsecurity.cxx | 12 + xmlsecurity/inc/pch/precompiled_xmlsecurity.hxx | 196 + xmlsecurity/inc/pch/precompiled_xsec_xmlsec.cxx | 12 + xmlsecurity/inc/pch/precompiled_xsec_xmlsec.hxx | 143 + xmlsecurity/inc/pdfio/pdfdocument.hxx | 46 + xmlsecurity/inc/pdfsignaturehelper.hxx | 78 + xmlsecurity/inc/resourcemanager.hxx | 29 + xmlsecurity/inc/strings.hrc | 70 + xmlsecurity/inc/xmlsec-wrapper.h | 50 + xmlsecurity/inc/xmlsec/errorcallback.hxx | 33 + xmlsecurity/inc/xmlsec/saxhelper.hxx | 84 + .../inc/xmlsec/xmldocumentwrapper_xmlsecimpl.hxx | 211 + xmlsecurity/inc/xmlsec/xmlsec_init.hxx | 20 + xmlsecurity/inc/xmlsec/xmlstreamio.hxx | 37 + xmlsecurity/inc/xmlsecuritydllapi.h | 23 + xmlsecurity/inc/xmlsignaturehelper.hxx | 169 + xmlsecurity/inc/xmlsignaturehelper2.hxx | 58 + xmlsecurity/inc/xsecctl.hxx | 405 ++ xmlsecurity/inc/xsecxmlsecdllapi.h | 23 + xmlsecurity/qa/certext/SanCertExt.cxx | 260 ++ xmlsecurity/qa/certext/User_35_Root_11.crt | 64 + xmlsecurity/qa/create-certs/create-certs.sh | 185 + .../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/cert8.db | Bin 0 -> 65536 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-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 xmlsecurity/qa/unit/pdfsigning/data/key3.db | Bin 0 -> 16384 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/pdfsigning.cxx | 539 +++ 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/cert8.db | Bin 0 -> 65536 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/key3.db | Bin 0 -> 16384 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 xmlsecurity/qa/unit/signing/data/partial.docx | Bin 0 -> 17918 bytes xmlsecurity/qa/unit/signing/data/pubring.gpg | Bin 0 -> 3060 bytes xmlsecurity/qa/unit/signing/data/random_seed | 2 + xmlsecurity/qa/unit/signing/data/secring.gpg | Bin 0 -> 3832 bytes .../qa/unit/signing/data/signatureline.docx | Bin 0 -> 22877 bytes xmlsecurity/qa/unit/signing/data/signatureline.odt | Bin 0 -> 27142 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 xmlsecurity/qa/unit/signing/data/trustdb.gpg | Bin 0 -> 1360 bytes .../qa/unit/signing/data/untrustedGoodGPG.odt | Bin 0 -> 12274 bytes xmlsecurity/qa/unit/signing/signing.cxx | 1376 ++++++ xmlsecurity/qa/unit/xmlsecurity-dialogs-test.cxx | 63 + .../source/component/certificatecontainer.cxx | 171 + .../source/component/documentdigitalsignatures.cxx | 853 ++++ xmlsecurity/source/dialogs/certificatechooser.cxx | 330 ++ xmlsecurity/source/dialogs/certificateviewer.cxx | 364 ++ .../source/dialogs/digitalsignaturesdialog.cxx | 769 ++++ xmlsecurity/source/dialogs/macrosecurity.cxx | 442 ++ xmlsecurity/source/framework/buffernode.cxx | 886 ++++ xmlsecurity/source/framework/buffernode.hxx | 116 + xmlsecurity/source/framework/elementcollector.cxx | 137 + xmlsecurity/source/framework/elementcollector.hxx | 83 + xmlsecurity/source/framework/elementmark.cxx | 64 + xmlsecurity/source/framework/elementmark.hxx | 70 + .../source/framework/saxeventkeeperimpl.cxx | 1157 +++++ xmlsecurity/source/framework/securityengine.cxx | 67 + .../source/framework/signaturecreatorimpl.cxx | 178 + xmlsecurity/source/framework/signatureengine.cxx | 197 + .../source/framework/signatureverifierimpl.cxx | 134 + .../source/framework/xmlsignaturetemplateimpl.cxx | 123 + xmlsecurity/source/gpg/CertificateImpl.cxx | 270 ++ xmlsecurity/source/gpg/CertificateImpl.hxx | 103 + xmlsecurity/source/gpg/CipherContext.cxx | 26 + xmlsecurity/source/gpg/CipherContext.hxx | 29 + xmlsecurity/source/gpg/DigestContext.cxx | 27 + xmlsecurity/source/gpg/DigestContext.hxx | 27 + xmlsecurity/source/gpg/SEInitializer.cxx | 81 + xmlsecurity/source/gpg/SecurityEnvironment.cxx | 239 ++ xmlsecurity/source/gpg/SecurityEnvironment.hxx | 72 + xmlsecurity/source/gpg/XMLEncryption.cxx | 37 + xmlsecurity/source/gpg/XMLEncryption.hxx | 40 + xmlsecurity/source/gpg/XMLSecurityContext.cxx | 84 + xmlsecurity/source/gpg/XMLSecurityContext.hxx | 61 + xmlsecurity/source/gpg/xmlsignature_gpgimpl.cxx | 527 +++ .../source/helper/documentsignaturehelper.cxx | 592 +++ .../source/helper/documentsignaturemanager.cxx | 687 +++ xmlsecurity/source/helper/ooxmlsecexporter.cxx | 546 +++ xmlsecurity/source/helper/ooxmlsecexporter.hxx | 59 + xmlsecurity/source/helper/ooxmlsecparser.cxx | 293 ++ xmlsecurity/source/helper/ooxmlsecparser.hxx | 87 + xmlsecurity/source/helper/pdfsignaturehelper.cxx | 187 + xmlsecurity/source/helper/xmlsignaturehelper.cxx | 549 +++ xmlsecurity/source/helper/xmlsignaturehelper2.cxx | 113 + xmlsecurity/source/helper/xsecctl.cxx | 986 +++++ xmlsecurity/source/helper/xsecparser.cxx | 530 +++ xmlsecurity/source/helper/xsecparser.hxx | 162 + xmlsecurity/source/helper/xsecsign.cxx | 447 ++ xmlsecurity/source/helper/xsecverify.cxx | 537 +++ xmlsecurity/source/pdfio/pdfdocument.cxx | 393 ++ xmlsecurity/source/xmlsec/biginteger.cxx | 108 + .../xmlsec/certificateextension_certextn.cxx | 54 + .../xmlsec/certificateextension_certextn.hxx | 38 + .../xmlsec/certificateextension_xmlsecimpl.hxx | 59 + xmlsecurity/source/xmlsec/errorcallback.cxx | 68 + xmlsecurity/source/xmlsec/mscrypt/akmngr.cxx | 229 + xmlsecurity/source/xmlsec/mscrypt/akmngr.hxx | 59 + xmlsecurity/source/xmlsec/mscrypt/oid.hxx | 156 + .../xmlsec/mscrypt/sanextension_mscryptimpl.cxx | 135 + .../xmlsec/mscrypt/sanextension_mscryptimpl.hxx | 69 + .../mscrypt/securityenvironment_mscryptimpl.cxx | 1066 +++++ .../mscrypt/securityenvironment_mscryptimpl.hxx | 176 + .../xmlsec/mscrypt/seinitializer_mscryptimpl.cxx | 175 + .../xmlsec/mscrypt/seinitializer_mscryptimpl.hxx | 74 + .../xmlsec/mscrypt/x509certificate_mscryptimpl.cxx | 652 +++ .../xmlsec/mscrypt/x509certificate_mscryptimpl.hxx | 99 + .../mscrypt/xmlsecuritycontext_mscryptimpl.cxx | 156 + .../xmlsec/mscrypt/xmlsignature_mscryptimpl.cxx | 305 ++ xmlsecurity/source/xmlsec/nss/certerrors.h | 385 ++ xmlsecurity/source/xmlsec/nss/ciphercontext.cxx | 266 ++ xmlsecurity/source/xmlsec/nss/ciphercontext.hxx | 83 + xmlsecurity/source/xmlsec/nss/digestcontext.cxx | 94 + xmlsecurity/source/xmlsec/nss/digestcontext.hxx | 62 + xmlsecurity/source/xmlsec/nss/nssinitializer.cxx | 524 +++ xmlsecurity/source/xmlsec/nss/nssinitializer.hxx | 66 + xmlsecurity/source/xmlsec/nss/nssrenam.h | 44 + .../source/xmlsec/nss/sanextension_nssimpl.cxx | 162 + .../source/xmlsec/nss/sanextension_nssimpl.hxx | 68 + xmlsecurity/source/xmlsec/nss/secerror.cxx | 152 + xmlsecurity/source/xmlsec/nss/secerror.hxx | 35 + .../xmlsec/nss/securityenvironment_nssimpl.cxx | 937 ++++ .../xmlsec/nss/securityenvironment_nssimpl.hxx | 146 + .../source/xmlsec/nss/seinitializer_nssimpl.cxx | 145 + .../source/xmlsec/nss/seinitializer_nssimpl.hxx | 58 + .../source/xmlsec/nss/x509certificate_nssimpl.cxx | 536 +++ .../source/xmlsec/nss/x509certificate_nssimpl.hxx | 107 + .../xmlsec/nss/xmlsecuritycontext_nssimpl.cxx | 150 + .../source/xmlsec/nss/xmlsignature_nssimpl.cxx | 317 ++ xmlsecurity/source/xmlsec/saxhelper.cxx | 361 ++ .../xmlsec/xmldocumentwrapper_xmlsecimpl.cxx | 906 ++++ .../source/xmlsec/xmlelementwrapper_xmlsecimpl.cxx | 78 + .../source/xmlsec/xmlelementwrapper_xmlsecimpl.hxx | 82 + xmlsecurity/source/xmlsec/xmlsec_init.cxx | 69 + xmlsecurity/source/xmlsec/xmlstreamio.cxx | 243 ++ 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 | 104 + xmlsecurity/uiconfig/ui/certgeneral.ui | 248 ++ xmlsecurity/uiconfig/ui/certpage.ui | 180 + xmlsecurity/uiconfig/ui/digitalsignaturesdialog.ui | 497 +++ xmlsecurity/uiconfig/ui/macrosecuritydialog.ui | 206 + xmlsecurity/uiconfig/ui/securitylevelpage.ui | 143 + xmlsecurity/uiconfig/ui/securitytrustpage.ui | 379 ++ xmlsecurity/uiconfig/ui/selectcertificatedialog.ui | 282 ++ xmlsecurity/uiconfig/ui/viewcertdialog.ui | 224 + xmlsecurity/util/xmlsecurity.component | 30 + xmlsecurity/util/xsec_xmlsec.component | 54 + xmlsecurity/workben/pdfverify.cxx | 222 + 694 files changed, 54507 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/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 create mode 100644 xmlsecurity/UIConfig_xmlsec.mk create mode 100644 xmlsecurity/doc/OpenDocumentSignatures-TestIntegration.sxw create mode 100644 xmlsecurity/doc/OpenDocumentSignatures-Workflow.sxd create mode 100644 xmlsecurity/doc/OpenDocumentSignatures.sxw create mode 100644 xmlsecurity/doc/XMLSecurityFramework.sxw 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/pdfio/pdfdocument.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/xmlsignaturehelper2.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/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/cert8.db 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-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/key3.db 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/pdfsigning.cxx 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/cert8.db 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/key3.db 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/partial.docx create mode 100644 xmlsecurity/qa/unit/signing/data/pubring.gpg create mode 100644 xmlsecurity/qa/unit/signing/data/random_seed create mode 100644 xmlsecurity/qa/unit/signing/data/secring.gpg 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/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/trustdb.gpg 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/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/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/xmlsignaturehelper2.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/pdfio/pdfdocument.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/xsec_xmlsec.component 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 000000000..90b80207c --- /dev/null +++ b/xmlsecurity/AllLangMoTarget_xsc.mk @@ -0,0 +1,13 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +$(eval $(call gb_AllLangMoTarget_AllLangMoTarget,xsc)) + +$(eval $(call gb_AllLangMoTarget_set_polocation,xsc,xmlsecurity)) + +# vim: set noet sw=4 ts=4: diff --git a/xmlsecurity/CppunitTest_qa_certext.mk b/xmlsecurity/CppunitTest_qa_certext.mk new file mode 100644 index 000000000..faa5459d3 --- /dev/null +++ b/xmlsecurity/CppunitTest_qa_certext.mk @@ -0,0 +1,27 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +$(eval $(call gb_CppunitTest_CppunitTest,xmlsecurity_qa_certext)) + +$(eval $(call gb_CppunitTest_use_sdk_api,xmlsecurity_qa_certext)) + +$(eval $(call gb_CppunitTest_use_libraries,xmlsecurity_qa_certext,\ + cppu \ + neon \ + sal \ + svl \ + test \ + tl \ +)) + +$(eval $(call gb_CppunitTest_add_exception_objects,xmlsecurity_qa_certext,\ + xmlsecurity/qa/certext/SanCertExt \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/xmlsecurity/CppunitTest_xmlsecurity_dialogs_test.mk b/xmlsecurity/CppunitTest_xmlsecurity_dialogs_test.mk new file mode 100644 index 000000000..945c33af7 --- /dev/null +++ b/xmlsecurity/CppunitTest_xmlsecurity_dialogs_test.mk @@ -0,0 +1,68 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +#************************************************************************* +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +#************************************************************************* + +$(eval $(call gb_CppunitTest_CppunitScreenShot,xmlsecurity_dialogs_test)) + +$(eval $(call gb_CppunitTest_add_exception_objects,xmlsecurity_dialogs_test, \ + xmlsecurity/qa/unit/xmlsecurity-dialogs-test \ +)) + +$(eval $(call gb_CppunitTest_use_sdk_api,xmlsecurity_dialogs_test)) + +$(eval $(call gb_CppunitTest_set_include,desktop_dialogs_test,\ + -I$(SRCDIR)/xmlsecurity/inc \ + $$(INCLUDE) \ +)) + +$(eval $(call gb_CppunitTest_use_libraries,xmlsecurity_dialogs_test, \ + basegfx \ + comphelper \ + cppu \ + cppuhelper \ + drawinglayer \ + editeng \ + i18nlangtag \ + i18nutil \ + msfilter \ + oox \ + sal \ + salhelper \ + sax \ + sfx \ + sot \ + svl \ + svt \ + test \ + tl \ + tk \ + ucbhelper \ + unotest \ + utl \ + vcl \ + xo \ +)) + +$(eval $(call gb_CppunitTest_use_external,xmlsecurity_dialogs_test,boost_headers)) + +$(eval $(call gb_CppunitTest_use_sdk_api,xmlsecurity_dialogs_test)) + +$(eval $(call gb_CppunitTest_use_ure,xmlsecurity_dialogs_test)) +$(eval $(call gb_CppunitTest_use_vcl_non_headless_with_windows,xmlsecurity_dialogs_test)) + +$(eval $(call gb_CppunitTest_use_rdb,xmlsecurity_dialogs_test,services)) + +$(eval $(call gb_CppunitTest_use_configuration,xmlsecurity_dialogs_test)) + +$(eval $(call gb_CppunitTest_use_uiconfigs,xmlsecurity_dialogs_test,\ + xmlsec \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/xmlsecurity/CppunitTest_xmlsecurity_pdfsigning.mk b/xmlsecurity/CppunitTest_xmlsecurity_pdfsigning.mk new file mode 100644 index 000000000..2441d47e0 --- /dev/null +++ b/xmlsecurity/CppunitTest_xmlsecurity_pdfsigning.mk @@ -0,0 +1,62 @@ +# -*- 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 \ +)) + +$(eval $(call gb_CppunitTest_set_include,xmlsecurity_pdfsigning,\ + -I$(SRCDIR)/xmlsecurity/inc \ + $$(INCLUDE) \ +)) + +$(eval $(call gb_CppunitTest_use_sdk_api,xmlsecurity_pdfsigning)) + +$(eval $(call gb_CppunitTest_use_ure,xmlsecurity_pdfsigning)) +$(eval $(call gb_CppunitTest_use_vcl,xmlsecurity_pdfsigning)) + +$(eval $(call gb_CppunitTest_use_rdb,xmlsecurity_pdfsigning,services)) + +$(eval $(call gb_CppunitTest_use_configuration,xmlsecurity_pdfsigning)) + +ifeq ($(ENABLE_POPPLER),TRUE) +$(eval $(call gb_CppunitTest_use_executable,xmlsecurity_pdfsigning,xpdfimport)) +endif + +ifeq ($(OS),WNT) +# Initializing DocumentSignatureManager will require gpgme-w32spawn.exe in workdir/LinkTarget/Executable +$(eval $(call gb_CppunitTest_use_packages,xmlsecurity_pdfsigning,\ + $(call gb_Helper_optional,GPGMEPP,gpgmepp)\ +)) +endif + +# vim: set noet sw=4 ts=4: diff --git a/xmlsecurity/CppunitTest_xmlsecurity_signing.mk b/xmlsecurity/CppunitTest_xmlsecurity_signing.mk new file mode 100644 index 000000000..c748c644a --- /dev/null +++ b/xmlsecurity/CppunitTest_xmlsecurity_signing.mk @@ -0,0 +1,74 @@ +# -*- 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 \ + test \ + tl \ + unotest \ + utl \ + xmlsecurity \ +)) + +$(eval $(call gb_CppunitTest_use_externals,xmlsecurity_signing,\ + boost_headers \ + libxml2 \ +)) + +$(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_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 + +# vim: set noet sw=4 ts=4: diff --git a/xmlsecurity/Executable_pdfverify.mk b/xmlsecurity/Executable_pdfverify.mk new file mode 100644 index 000000000..ed8e9559f --- /dev/null +++ b/xmlsecurity/Executable_pdfverify.mk @@ -0,0 +1,35 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +$(eval $(call gb_Executable_Executable,pdfverify)) + +$(eval $(call gb_Executable_use_sdk_api,pdfverify)) + +$(eval $(call gb_Executable_use_external,pdfverify,boost_headers)) + +$(eval $(call gb_Executable_set_include,pdfverify,\ + $$(INCLUDE) \ + -I$(SRCDIR)/xmlsecurity/inc \ +)) + +$(eval $(call gb_Executable_use_libraries,pdfverify,\ + comphelper \ + cppu \ + cppuhelper \ + sal \ + tl \ + vcl \ + xmlsecurity \ +)) + +$(eval $(call gb_Executable_add_exception_objects,pdfverify,\ + xmlsecurity/workben/pdfverify \ +)) + +# vim:set noet sw=4 ts=4: diff --git a/xmlsecurity/IwyuFilter_xmlsecurity.yaml b/xmlsecurity/IwyuFilter_xmlsecurity.yaml new file mode 100644 index 000000000..21c6b38e5 --- /dev/null +++ b/xmlsecurity/IwyuFilter_xmlsecurity.yaml @@ -0,0 +1,132 @@ +--- +assumeFilename: xmlsecurity/source/xmlsec/xmlsec_init.cxx +blacklist: + xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx: + # complete type is needed + - com/sun/star/security/DocumentSignatureInformation.hpp + xmlsecurity/inc/xmlsignaturehelper2.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 + - xmlsignaturehelper2.hxx + xmlsecurity/inc/framework/securityengine.hxx: + # Base class needs complete type + - com/sun/star/xml/crypto/XXMLSignature.hpp + - com/sun/star/xml/crypto/sax/XReferenceResolvedBroadcaster.hpp + - com/sun/star/xml/crypto/sax/XSAXEventKeeper.hpp + xmlsecurity/inc/framework/signaturecreatorimpl.hxx: + # Base class needs complete type + - framework/signatureengine.hxx + - com/sun/star/xml/crypto/sax/XBlockerMonitor.hpp + - com/sun/star/xml/crypto/sax/XSignatureCreationResultBroadcaster.hpp + - com/sun/star/lang/XInitialization.hpp + - com/sun/star/lang/XServiceInfo.hpp + xmlsecurity/inc/framework/saxeventkeeperimpl.hxx: + # Base class needs complete type + - com/sun/star/xml/crypto/sax/XSecuritySAXEventKeeper.hpp + - com/sun/star/xml/crypto/sax/XReferenceResolvedBroadcaster.hpp + - com/sun/star/xml/crypto/sax/XSAXEventKeeperStatusChangeBroadcaster.hpp + - com/sun/star/xml/sax/XDocumentHandler.hpp + - com/sun/star/lang/XInitialization.hpp + - com/sun/star/lang/XServiceInfo.hpp + xmlsecurity/inc/framework/signatureverifierimpl.hxx: + # Base class needs complete type + - framework/signatureengine.hxx + - com/sun/star/xml/crypto/sax/XSignatureVerifyResultBroadcaster.hpp + - com/sun/star/lang/XServiceInfo.hpp + - com/sun/star/lang/XInitialization.hpp + xmlsecurity/inc/framework/xmlsignaturetemplateimpl.hxx: + # Base class needs complete type + - com/sun/star/xml/crypto/XXMLSignatureTemplate.hpp + - com/sun/star/lang/XServiceInfo.hpp + xmlsecurity/inc/gpg/SEInitializer.hxx: + # Base class needs complete type + - com/sun/star/xml/crypto/XSEInitializer.hpp + - com/sun/star/lang/XServiceInfo.hpp + xmlsecurity/inc/gpg/xmlsignature_gpgimpl.hxx: + # Base class needs complete type + - com/sun/star/xml/crypto/XXMLSignature.hpp + - com/sun/star/lang/XServiceInfo.hpp + xmlsecurity/inc/xmlsec/xmldocumentwrapper_xmlsecimpl.hxx: + # Base class needs complete type + - com/sun/star/xml/wrapper/XXMLDocumentWrapper.hpp + - com/sun/star/xml/csax/XCompressedDocumentHandler.hpp + - com/sun/star/lang/XServiceInfo.hpp + xmlsecurity/source/gpg/CipherContext.hxx: + # Base class needs complete type + - com/sun/star/xml/crypto/XCipherContext.hpp + xmlsecurity/source/gpg/DigestContext.hxx: + # Base class needs complete type + - com/sun/star/xml/crypto/XDigestContext.hpp + xmlsecurity/source/gpg/CertificateImpl.hxx: + # Base class needs complete type + - com/sun/star/security/XCertificate.hpp + - com/sun/star/lang/XUnoTunnel.hpp + - com/sun/star/lang/XServiceInfo.hpp + xmlsecurity/source/gpg/GpgComponentFactory.cxx: + # Silence warning due to incorrect include path + - com/sun/star/lang/XSingleServiceFactory.hpp + xmlsecurity/source/gpg/SecurityEnvironment.hxx: + # Base class needs complete type + - com/sun/star/xml/crypto/XSecurityEnvironment.hpp + - com/sun/star/lang/XUnoTunnel.hpp + xmlsecurity/source/gpg/XMLSecurityContext.hxx: + # Base class needs complete type + - com/sun/star/xml/crypto/XXMLSecurityContext.hpp + - com/sun/star/lang/XServiceInfo.hpp + xmlsecurity/source/gpg/XMLEncryption.hxx: + # Base class needs complete type + - com/sun/star/xml/crypto/XXMLEncryption.hpp + xmlsecurity/source/helper/ooxmlsecparser.hxx: + # Base class needs complete type + - com/sun/star/xml/sax/XDocumentHandler.hpp + - com/sun/star/lang/XInitialization.hpp + xmlsecurity/source/helper/xsecparser.hxx: + # Base class needs complete type + - com/sun/star/xml/sax/XDocumentHandler.hpp + - com/sun/star/lang/XInitialization.hpp + xmlsecurity/source/xmlsec/certificateextension_xmlsecimpl.hxx: + # Base class needs complete type + - com/sun/star/security/XCertificateExtension.hpp + xmlsecurity/source/xmlsec/xmlelementwrapper_xmlsecimpl.hxx: + # Base class needs complete type + - com/sun/star/lang/XServiceInfo.hpp + - com/sun/star/lang/XUnoTunnel.hpp + - com/sun/star/xml/wrapper/XXMLElementWrapper.hpp + xmlsecurity/source/xmlsec/errorcallback.cxx: + # Needed for xmlsec/errors.h + - xmlsec-wrapper.h + xmlsecurity/source/xmlsec/xmlstreamio.cxx: + # comphelper::ScopeGuard is in use but not noticed by IWYU + - comphelper/scopeguard.hxx + xmlsecurity/source/xmlsec/nss/sanextension_nssimpl.hxx: + # Base class needs complete type + - com/sun/star/security/XSanExtension.hpp + xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.hxx: + # Base class needs complete type + - com/sun/star/security/XCertificate.hpp + - com/sun/star/lang/XUnoTunnel.hpp + - com/sun/star/lang/XServiceInfo.hpp + xmlsecurity/source/xmlsec/nss/seinitializer_nssimpl.hxx: + # Base class needs complete type + - nssinitializer.hxx + - com/sun/star/xml/crypto/XSEInitializer.hpp + xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.hxx: + # Base class needs complete type + - com/sun/star/xml/crypto/XSecurityEnvironment.hpp + - com/sun/star/xml/crypto/XCertificateCreator.hpp + - com/sun/star/lang/XServiceInfo.hpp + - com/sun/star/lang/XUnoTunnel.hpp + xmlsecurity/source/xmlsec/nss/secerror.cxx: + # Used as array initializer + - certerrors.h + # Needed for macros used by certerrors.h + - nss.h + xmlsecurity/qa/unit/signing/signing.cxx: + # Don't replace URE header with impl. detail + - osl/thread.hxx diff --git a/xmlsecurity/Library_xmlsecurity.mk b/xmlsecurity/Library_xmlsecurity.mk new file mode 100644 index 000000000..823332d3e --- /dev/null +++ b/xmlsecurity/Library_xmlsecurity.mk @@ -0,0 +1,104 @@ +# -*- 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)) + +$(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 \ + $(if $(filter PDFIUM,$(BUILD_TYPE)),pdfium) \ +)) + +$(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 \ + svt \ + svxcore \ + tl \ + ucbhelper \ + utl \ + vcl \ + xo \ + i18nlangtag \ + xsec_xmlsec \ +)) + +$(eval $(call gb_Library_add_exception_objects,xmlsecurity,\ + xmlsecurity/source/component/certificatecontainer \ + xmlsecurity/source/component/documentdigitalsignatures \ + 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/xmlsignaturehelper2 \ + xmlsecurity/source/helper/xmlsignaturehelper \ + xmlsecurity/source/helper/xsecctl \ + xmlsecurity/source/helper/xsecparser \ + xmlsecurity/source/helper/xsecsign \ + xmlsecurity/source/helper/xsecverify \ + xmlsecurity/source/pdfio/pdfdocument \ +)) + +$(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))) +$(eval $(call gb_Library_add_defs,xmlsecurity,\ + -DXMLSEC_CRYPTO_NSS \ +)) +$(eval $(call gb_Library_use_externals,xmlsecurity,\ + nss3 \ + plc4 \ +)) +endif # BUILD_TYPE=DESKTOP +endif + +# vim: set noet sw=4 ts=4: diff --git a/xmlsecurity/Library_xsec_xmlsec.mk b/xmlsecurity/Library_xsec_xmlsec.mk new file mode 100644 index 000000000..bd2cb6abe --- /dev/null +++ b/xmlsecurity/Library_xsec_xmlsec.mk @@ -0,0 +1,153 @@ +# -*- 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)) + +$(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 \ + 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 \ + xmlsecurity/source/xmlsec/nss/ciphercontext \ + xmlsecurity/source/xmlsec/nss/digestcontext \ + xmlsecurity/source/xmlsec/nss/nssinitializer \ +)) + +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 \ +)) + +else + +$(eval $(call gb_Library_add_defs,xsec_xmlsec,\ + -DXMLSEC_CRYPTO_NSS \ +)) + +ifeq ($(SYSTEM_XMLSEC),) +$(eval $(call gb_Library_add_libs,xsec_xmlsec,\ + $(call gb_UnpackedTarball_get_dir,xmlsec)/src/nss/.libs/libxmlsec1-nss.a \ + $(call gb_UnpackedTarball_get_dir,xmlsec)/src/.libs/libxmlsec1.a \ +)) +endif + +$(eval $(call gb_Library_use_externals,xsec_xmlsec,\ + plc4 \ +)) + +$(eval $(call gb_Library_add_exception_objects,xsec_xmlsec,\ + 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 \ +)) + +endif + +# nss3 after static libs to appease --as-needed linkers +$(eval $(call gb_Library_use_externals,xsec_xmlsec,\ + nss3 \ +)) + +ifeq ($(OS),SOLARIS) +$(eval $(call gb_Library_add_libs,xsec_xmlsec,\ + -ldl \ +)) +endif + +# vim: set noet sw=4 ts=4: diff --git a/xmlsecurity/Makefile b/xmlsecurity/Makefile new file mode 100644 index 000000000..0997e6284 --- /dev/null +++ b/xmlsecurity/Makefile @@ -0,0 +1,14 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +module_directory:=$(dir $(realpath $(firstword $(MAKEFILE_LIST)))) + +include $(module_directory)/../solenv/gbuild/partial_build.mk + +# vim: set noet sw=4 ts=4: diff --git a/xmlsecurity/Module_xmlsecurity.mk b/xmlsecurity/Module_xmlsecurity.mk new file mode 100644 index 000000000..1ce7364d4 --- /dev/null +++ b/xmlsecurity/Module_xmlsecurity.mk @@ -0,0 +1,49 @@ +# -*- 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)) + +ifeq ($(ENABLE_NSS),TRUE) + +$(eval $(call gb_Module_add_targets,xmlsecurity,\ + Library_xmlsecurity \ + Library_xsec_xmlsec \ + UIConfig_xmlsec \ +)) + +$(eval $(call gb_Module_add_slowcheck_targets,xmlsecurity,\ + CppunitTest_xmlsecurity_signing \ + CppunitTest_xmlsecurity_pdfsigning \ +)) + +$(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))) + +$(eval $(call gb_Module_add_targets,xmlsecurity,\ + Executable_pdfverify \ +)) + +endif + +endif + +# vim: set noet sw=4 ts=4: diff --git a/xmlsecurity/README b/xmlsecurity/README new file mode 100644 index 000000000..52a479009 --- /dev/null +++ b/xmlsecurity/README @@ -0,0 +1,4 @@ +Stuff for document signing. + +This code provides dialogs, and infrastructure wrapping libxmlsec and gpgme that +implements document signing. diff --git a/xmlsecurity/UIConfig_xmlsec.mk b/xmlsecurity/UIConfig_xmlsec.mk new file mode 100644 index 000000000..06482e2a2 --- /dev/null +++ b/xmlsecurity/UIConfig_xmlsec.mk @@ -0,0 +1,24 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +$(eval $(call gb_UIConfig_UIConfig,xmlsec)) + +$(eval $(call gb_UIConfig_add_uifiles,xmlsec,\ + xmlsecurity/uiconfig/ui/certpage \ + xmlsecurity/uiconfig/ui/certdetails \ + xmlsecurity/uiconfig/ui/certgeneral \ + xmlsecurity/uiconfig/ui/digitalsignaturesdialog \ + xmlsecurity/uiconfig/ui/securitylevelpage \ + xmlsecurity/uiconfig/ui/securitytrustpage \ + xmlsecurity/uiconfig/ui/selectcertificatedialog \ + xmlsecurity/uiconfig/ui/macrosecuritydialog \ + xmlsecurity/uiconfig/ui/viewcertdialog \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/xmlsecurity/doc/OpenDocumentSignatures-TestIntegration.sxw b/xmlsecurity/doc/OpenDocumentSignatures-TestIntegration.sxw new file mode 100644 index 000000000..2973f08c8 Binary files /dev/null and b/xmlsecurity/doc/OpenDocumentSignatures-TestIntegration.sxw differ diff --git a/xmlsecurity/doc/OpenDocumentSignatures-Workflow.sxd b/xmlsecurity/doc/OpenDocumentSignatures-Workflow.sxd new file mode 100644 index 000000000..abc5f32c6 Binary files /dev/null and b/xmlsecurity/doc/OpenDocumentSignatures-Workflow.sxd differ diff --git a/xmlsecurity/doc/OpenDocumentSignatures.sxw b/xmlsecurity/doc/OpenDocumentSignatures.sxw new file mode 100644 index 000000000..9b453e0d8 Binary files /dev/null and b/xmlsecurity/doc/OpenDocumentSignatures.sxw differ diff --git a/xmlsecurity/doc/XMLSecurityFramework.sxw b/xmlsecurity/doc/XMLSecurityFramework.sxw new file mode 100644 index 000000000..c778e1c1e Binary files /dev/null and b/xmlsecurity/doc/XMLSecurityFramework.sxw differ diff --git a/xmlsecurity/inc/biginteger.hxx b/xmlsecurity/inc/biginteger.hxx new file mode 100644 index 000000000..d07ecf45d --- /dev/null +++ b/xmlsecurity/inc/biginteger.hxx @@ -0,0 +1,38 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_XMLSECURITY_INC_BIGINTEGER_HXX +#define INCLUDED_XMLSECURITY_INC_BIGINTEGER_HXX + +#include +#include + +#include + +#include "xsecxmlsecdllapi.h" + +namespace xmlsecurity +{ +XSECXMLSEC_DLLPUBLIC OUString bigIntegerToNumericString( const css::uno::Sequence< sal_Int8 >& serial ); +XSECXMLSEC_DLLPUBLIC css::uno::Sequence< sal_Int8 > numericStringToBigInteger ( const OUString& serialNumber ); +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/bitmaps.hlst b/xmlsecurity/inc/bitmaps.hlst new file mode 100644 index 000000000..52a9df754 --- /dev/null +++ b/xmlsecurity/inc/bitmaps.hlst @@ -0,0 +1,24 @@ +/* -*- 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/. + */ + +#ifndef INCLUDED_XMLSECURITY_INC_BITMAPS_HRC +#define INCLUDED_XMLSECURITY_INC_BITMAPS_HRC + +#define BMP_STATE_NOT_VALIDATED "xmlecurity/res/notcertificate_40x56.png" + +#define BMP_CERT_OK "xmlsecurity/res/certificate_16.png" +#define BMP_CERT_NOT_OK "xmlsecurity/res/notcertificate_16.png" + +#define BMP_SIG_VALID "xmlsecurity/res/signet_11x16.png" +#define BMP_SIG_INVALID "svx/res/caution_11x16.png" +#define BMP_SIG_NOT_VALIDATED "xmlsecurity/res/notcertificate_16.png" + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/xmlsecurity/inc/certificate.hxx b/xmlsecurity/inc/certificate.hxx new file mode 100644 index 000000000..a051d6983 --- /dev/null +++ b/xmlsecurity/inc/certificate.hxx @@ -0,0 +1,46 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_XMLSECURITY_INC_CERTIFICATE_H +#define INCLUDED_XMLSECURITY_INC_CERTIFICATE_H + +#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 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; +}; +} + +#endif // INCLUDED_XMLSECURITY_INC_CERTIFICATE_H + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/certificatechooser.hxx b/xmlsecurity/inc/certificatechooser.hxx new file mode 100644 index 000000000..437523370 --- /dev/null +++ b/xmlsecurity/inc/certificatechooser.hxx @@ -0,0 +1,98 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_XMLSECURITY_INC_CERTIFICATECHOOSER_HXX +#define INCLUDED_XMLSECURITY_INC_CERTIFICATECHOOSER_HXX + +#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: + 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; + + DECL_LINK(ViewButtonHdl, weld::Button&, void); + DECL_LINK(CertificateHighlightHdl, weld::TreeView&, void); + DECL_LINK(CertificateSelectHdl, weld::TreeView&, bool); + + void ImplShowCertificateDetails(); + void ImplInitialize(); + + static void HandleOneUsageBit(OUString& string, int& bits, int bit, const char *name); + +public: + CertificateChooser(weld::Window* pParent, + std::vector< css::uno::Reference< css::xml::crypto::XXMLSecurityContext > > const & rxSecurityContexts, + UserAction eAction); + virtual ~CertificateChooser() override; + + 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); +}; + +#endif // INCLUDED_XMLSECURITY_INC_CERTIFICATECHOOSER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/certificateviewer.hxx b/xmlsecurity/inc/certificateviewer.hxx new file mode 100644 index 000000000..719db4764 --- /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 . + */ + +#ifndef INCLUDED_XMLSECURITY_INC_CERTIFICATEVIEWER_HXX +#define INCLUDED_XMLSECURITY_INC_CERTIFICATEVIEWER_HXX + +#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 OString&, void); + +public: + CertificateViewer(weld::Window* pParent, const css::uno::Reference< css::xml::crypto::XSecurityEnvironment >& rxSecurityEnvironment, const css::uno::Reference< css::security::XCertificate >& rXCert, bool bCheckForPrivateKey, CertificateChooser* pParentChooser); + CertificateChooser* GetParentChooser() { return mpParentChooser; } +}; + +class CertificateViewerTP +{ +protected: + std::unique_ptr mxBuilder; + std::unique_ptr mxContainer; + CertificateViewer* mpDlg; + +public: + CertificateViewerTP(weld::Container* pParent, const OUString& rUIXMLDescription, + const OString& 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(const OUString& rTxt, bool bFixedWidthFont) + : maTxt(rTxt) + , 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 const & xCert, bool bValid) + : mxCert(xCert) + , mbValid(bValid) + { + } +}; + +class CertificateViewerCertPathTP : public CertificateViewerTP +{ +private: + CertificateViewer* mpParent; + bool mbFirstActivateDone; + + std::vector> maUserData; + + std::unique_ptr mxCertPathLB; + 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); + void ActivatePage(); +}; + + +#endif // INCLUDED_XMLSECURITY_INC_CERTIFICATEVIEWER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/digitalsignaturesdialog.hxx b/xmlsecurity/inc/digitalsignaturesdialog.hxx new file mode 100644 index 000000000..6497a6337 --- /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 . + */ + +#ifndef INCLUDED_XMLSECURITY_INC_DIGITALSIGNATURESDIALOG_HXX +#define INCLUDED_XMLSECURITY_INC_DIGITALSIGNATURESDIALOG_HXX + +#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 DigitalSignaturesDialog final : public weld::GenericDialogController +{ +private: + DocumentSignatureManager maSignatureManager; + bool mbVerifySignatures; + bool mbSignaturesChanged; + + OUString const m_sODFVersion; + //Signals if the document contains already a document signature. This is only + //important when we are signing macros and if the value is true. + bool const m_bHasDocumentSignature; + bool m_bWarningShowSignMacro; + + bool m_bAdESCompliant; + + std::unique_ptr 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_xAdESCompliantCB; + 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; + + DECL_LINK(AdESCompliantCheckBoxHdl, weld::ToggleButton&, void); + DECL_LINK(ViewButtonHdl, weld::Button&, void); + DECL_LINK(AddButtonHdl, weld::Button&, void); + DECL_LINK(RemoveButtonHdl, weld::Button&, void); + DECL_LINK(SignatureHighlightHdl, weld::TreeView&, void); + DECL_LINK(SignatureSelectHdl, weld::TreeView&, bool); + DECL_LINK(StartVerifySignatureHdl, LinkParamNone*, bool); + DECL_LINK(OKButtonHdl, weld::Button&, void); + DECL_LINK(CertMgrButtonHdl, weld::Button&, void); + + void ImplGetSignatureInformations(bool bUseTempStream, bool bCacheLastSignature); + void ImplFillSignaturesBox(); + void ImplShowSignaturesDetails(); + + css::uno::Reference 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, const OUString& sODFVersion, bool bHasDocumentSignature); + virtual ~DigitalSignaturesDialog() override; + + // Initialize the dialog and the security environment, returns TRUE on success + bool Init(); + + // Set the storage which should be signed or verified + void SetStorage( const css::uno::Reference < css::embed::XStorage >& rxStore ); + void SetSignatureStream( const css::uno::Reference < css::io::XStream >& rxStream ); + + // Execute the dialog... + short run() override; + + // Did signatures change? + bool SignaturesChanged() const { return mbSignaturesChanged; } +}; + +#endif // INCLUDED_XMLSECURITY_INC_DIGITALSIGNATURESDIALOG_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/documentsignaturehelper.hxx b/xmlsecurity/inc/documentsignaturehelper.hxx new file mode 100644 index 000000000..ccf71edd9 --- /dev/null +++ b/xmlsecurity/inc/documentsignaturehelper.hxx @@ -0,0 +1,111 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_XMLSECURITY_INC_DOCUMENTSIGNATUREHELPER_HXX +#define INCLUDED_XMLSECURITY_INC_DOCUMENTSIGNATUREHELPER_HXX + +#include +#include +#include + +#include + +namespace com { +namespace sun { +namespace star { +namespace io { + class XStream; } +namespace embed { + class XStorage; } +}}} + +namespace com::sun::star::xml::sax { class XDocumentHandler; } + +enum class DocumentSignatureMode +{ + Content, + Macros, + Package +}; + +enum class DocumentSignatureAlgorithm +{ + OOo2, + OOo3_0, + OOo3_2 +}; + +struct SignatureStreamHelper +{ + css::uno::Reference < css::embed::XStorage > xSignatureStorage; + css::uno::Reference < css::io::XStream > xSignatureStream; + /// If this is embed::StorageFormats::OFOPXML, then it's expected that xSignatureStream is an empty reference. + sal_Int32 nStorageFormat; + + SignatureStreamHelper() + : nStorageFormat(0) + { + } +}; + +namespace DocumentSignatureHelper +{ + SignatureStreamHelper OpenSignatureStream( + const css::uno::Reference < css::embed::XStorage >& rxStore, sal_Int32 nOpenMode, + DocumentSignatureMode eDocSigMode ); + + std::vector< OUString > CreateElementList( + const css::uno::Reference < css::embed::XStorage >& rxStore, + DocumentSignatureMode eMode, + const DocumentSignatureAlgorithm mode); + + bool isODFPre_1_2(const OUString & sODFVersion); + bool isOOo3_2_Signature(const SignatureInformation & sigInfo); + + DocumentSignatureAlgorithm getDocumentAlgorithm( + const OUString & sODFVersion, const SignatureInformation & sigInfo); + + bool CanSignWithGPG(const css::uno::Reference < css::embed::XStorage >& rxStore, + const OUString& sOdfVersion); + + bool checkIfAllFilesAreSigned( const ::std::vector< OUString > & sElementList, + const SignatureInformation & sigInfo, const DocumentSignatureAlgorithm alg); + + bool equalsReferenceUriManifestPath( + const OUString & rUri, const OUString & 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); +}; + +#endif // INCLUDED_XMLSECURITY_INC_DOCUMENTSIGNATUREHELPER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/documentsignaturemanager.hxx b/xmlsecurity/inc/documentsignaturemanager.hxx new file mode 100644 index 000000000..3d001966f --- /dev/null +++ b/xmlsecurity/inc/documentsignaturemanager.hxx @@ -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 . + */ + +#ifndef INCLUDED_XMLSECURITY_INC_DOCUMENTSIGNATUREMANAGER_HXX +#define INCLUDED_XMLSECURITY_INC_DOCUMENTSIGNATUREMANAGER_HXX + +#include "xmlsecuritydllapi.h" + +#include + +#include +#include "xmlsignaturehelper.hxx" +#include "documentsignaturehelper.hxx" + +#include + +namespace com +{ +namespace sun +{ +namespace star +{ +namespace beans +{ +struct PropertyValue; +} +namespace embed +{ +class XStorage; +} +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 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(const OUString& 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; + } + const css::uno::Reference& getStore() const { return mxStore; } + DocumentSignatureMode getSignatureMode() const { return meSignatureMode; } + SignatureInformations& getCurrentSignatureInformations() + { + return maCurrentSignatureInformations; + } +}; + +#endif // INCLUDED_XMLSECURITY_INC_DOCUMENTSIGNATUREMANAGER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/framework/saxeventkeeperimpl.hxx b/xmlsecurity/inc/framework/saxeventkeeperimpl.hxx new file mode 100644 index 000000000..e3edb8579 --- /dev/null +++ b/xmlsecurity/inc/framework/saxeventkeeperimpl.hxx @@ -0,0 +1,294 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_XMLSECURITY_INC_FRAMEWORK_SAXEVENTKEEPERIMPL_HXX +#define INCLUDED_XMLSECURITY_INC_FRAMEWORK_SAXEVENTKEEPERIMPL_HXX + +#include +#include +#include +#include +#include +#include +#include +#include + +class BufferNode; +class ElementMark; +class ElementCollector; + +#include +#include + +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( ); + +#endif + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/framework/securityengine.hxx b/xmlsecurity/inc/framework/securityengine.hxx new file mode 100644 index 000000000..980d61a65 --- /dev/null +++ b/xmlsecurity/inc/framework/securityengine.hxx @@ -0,0 +1,145 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_XMLSECURITY_INC_FRAMEWORK_SECURITYENGINE_HXX +#define INCLUDED_XMLSECURITY_INC_FRAMEWORK_SECURITYENGINE_HXX + +#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; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/framework/signaturecreatorimpl.hxx b/xmlsecurity/inc/framework/signaturecreatorimpl.hxx new file mode 100644 index 000000000..212feb25c --- /dev/null +++ b/xmlsecurity/inc/framework/signaturecreatorimpl.hxx @@ -0,0 +1,99 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_XMLSECURITY_INC_FRAMEWORK_SIGNATURECREATORIMPL_HXX +#define INCLUDED_XMLSECURITY_INC_FRAMEWORK_SIGNATURECREATORIMPL_HXX + +#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( ); + +#endif + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/framework/signatureengine.hxx b/xmlsecurity/inc/framework/signatureengine.hxx new file mode 100644 index 000000000..48e4ce5f3 --- /dev/null +++ b/xmlsecurity/inc/framework/signatureengine.hxx @@ -0,0 +1,119 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_XMLSECURITY_INC_FRAMEWORK_SIGNATUREENGINE_HXX +#define INCLUDED_XMLSECURITY_INC_FRAMEWORK_SIGNATUREENGINE_HXX + +#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; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/framework/signatureverifierimpl.hxx b/xmlsecurity/inc/framework/signatureverifierimpl.hxx new file mode 100644 index 000000000..37327fd5f --- /dev/null +++ b/xmlsecurity/inc/framework/signatureverifierimpl.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 . + */ + +#ifndef INCLUDED_XMLSECURITY_INC_FRAMEWORK_SIGNATUREVERIFIERIMPL_HXX +#define INCLUDED_XMLSECURITY_INC_FRAMEWORK_SIGNATUREVERIFIERIMPL_HXX + +#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( ); + +#endif + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/framework/xmlsignaturetemplateimpl.hxx b/xmlsecurity/inc/framework/xmlsignaturetemplateimpl.hxx new file mode 100644 index 000000000..4f10e5db2 --- /dev/null +++ b/xmlsecurity/inc/framework/xmlsignaturetemplateimpl.hxx @@ -0,0 +1,98 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_XMLSECURITY_INC_FRAMEWORK_XMLSIGNATURETEMPLATEIMPL_HXX +#define INCLUDED_XMLSECURITY_INC_FRAMEWORK_XMLSIGNATURETEMPLATEIMPL_HXX + +#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 ) ; +}; + +#endif // INCLUDED_XMLSECURITY_INC_FRAMEWORK_XMLSIGNATURETEMPLATEIMPL_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/gpg/SEInitializer.hxx b/xmlsecurity/inc/gpg/SEInitializer.hxx new file mode 100644 index 000000000..67ab7a531 --- /dev/null +++ b/xmlsecurity/inc/gpg/SEInitializer.hxx @@ -0,0 +1,50 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_XMLSECURITY_SOURCE_GPG_SEINITIALIZER_HXX +#define INCLUDED_XMLSECURITY_SOURCE_GPG_SEINITIALIZER_HXX + +#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; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/gpg/xmlsignature_gpgimpl.hxx b/xmlsecurity/inc/gpg/xmlsignature_gpgimpl.hxx new file mode 100644 index 000000000..39c8496f2 --- /dev/null +++ b/xmlsecurity/inc/gpg/xmlsignature_gpgimpl.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 . + */ + +#ifndef INCLUDED_XMLSECURITY_SOURCE_GPG_XMLSIGNATURE_GPGIMPL_HXX +#define INCLUDED_XMLSECURITY_SOURCE_GPG_XMLSIGNATURE_GPGIMPL_HXX + +#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 ) ; +} ; + +#endif // INCLUDED_XMLSECURITY_SOURCE_GPG_XMLSIGNATURE_GPGIMPL_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/macrosecurity.hxx b/xmlsecurity/inc/macrosecurity.hxx new file mode 100644 index 000000000..49ea1edcb --- /dev/null +++ b/xmlsecurity/inc/macrosecurity.hxx @@ -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 . + */ + +#ifndef INCLUDED_XMLSECURITY_INC_MACROSECURITY_HXX +#define INCLUDED_XMLSECURITY_INC_MACROSECURITY_HXX + +#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; + SvtSecurityOptions m_aSecOptions; + + 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 OString&, void); + DECL_LINK(OkBtnHdl, weld::Button&, void); +public: + MacroSecurity(weld::Window* pParent, + const css::uno::Reference& rxSecurityEnvironment); + + 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 OString& 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::ToggleButton&, void); +public: + MacroSecurityLevelTP(weld::Container* pParent, MacroSecurity* pDlg); + virtual void ClosePage() override; +}; + +class MacroSecurityTrustedSourcesTP : public MacroSecurityTP +{ +private: + css::uno::Sequence< 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(const OUString& rData); + +public: + MacroSecurityTrustedSourcesTP(weld::Container* pParent, MacroSecurity* pDlg); + + virtual void ActivatePage() override; + virtual void ClosePage() override; +}; + + +#endif // INCLUDED_XMLSECURITY_INC_MACROSECURITY_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/pch/precompiled_xmlsecurity.cxx b/xmlsecurity/inc/pch/precompiled_xmlsecurity.cxx new file mode 100644 index 000000000..16ace305f --- /dev/null +++ b/xmlsecurity/inc/pch/precompiled_xmlsecurity.cxx @@ -0,0 +1,12 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "precompiled_xmlsecurity.hxx" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/pch/precompiled_xmlsecurity.hxx b/xmlsecurity/inc/pch/precompiled_xmlsecurity.hxx new file mode 100644 index 000000000..b3a01d8a4 --- /dev/null +++ b/xmlsecurity/inc/pch/precompiled_xmlsecurity.hxx @@ -0,0 +1,196 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If 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 2020-04-25 20:56:05 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 +*/ + +#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 +#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 +#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 +#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 000000000..74123c2f1 --- /dev/null +++ b/xmlsecurity/inc/pch/precompiled_xsec_xmlsec.cxx @@ -0,0 +1,12 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "precompiled_xsec_xmlsec.hxx" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/pch/precompiled_xsec_xmlsec.hxx b/xmlsecurity/inc/pch/precompiled_xsec_xmlsec.hxx new file mode 100644 index 000000000..f0d938522 --- /dev/null +++ b/xmlsecurity/inc/pch/precompiled_xsec_xmlsec.hxx @@ -0,0 +1,143 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If 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 2020-04-25 20:56:06 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 +*/ + +#if PCH_LEVEL >= 1 +#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 +#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 +#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/pdfio/pdfdocument.hxx b/xmlsecurity/inc/pdfio/pdfdocument.hxx new file mode 100644 index 000000000..87fa1d512 --- /dev/null +++ b/xmlsecurity/inc/pdfio/pdfdocument.hxx @@ -0,0 +1,46 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#ifndef INCLUDED_XMLSECURITY_INC_PDFIO_PDFDOCUMENT_HXX +#define INCLUDED_XMLSECURITY_INC_PDFIO_PDFDOCUMENT_HXX + +#include + +namespace vcl +{ +namespace filter +{ +class PDFObjectElement; +class PDFDocument; +} +} +struct SignatureInformation; +class SvStream; + +namespace xmlsecurity +{ +namespace pdfio +{ +/** + * @param rInformation The actual result. + * @param rDocument the parsed document to see if the signature is partial. + * @return If we can determinate a result. + */ +XMLSECURITY_DLLPUBLIC bool ValidateSignature(SvStream& rStream, + vcl::filter::PDFObjectElement* pSignature, + SignatureInformation& rInformation, + vcl::filter::PDFDocument& rDocument, int nMDPPerm); + +} // namespace pdfio +} // namespace xmlsecurity + +#endif // INCLUDED_XMLSECURITY_INC_PDFIO_PDFDOCUMENT_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/pdfsignaturehelper.hxx b/xmlsecurity/inc/pdfsignaturehelper.hxx new file mode 100644 index 000000000..f23a371d2 --- /dev/null +++ b/xmlsecurity/inc/pdfsignaturehelper.hxx @@ -0,0 +1,78 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#ifndef INCLUDED_XMLSECURITY_INC_PDFSIGNATUREHELPER_HXX +#define INCLUDED_XMLSECURITY_INC_PDFSIGNATUREHELPER_HXX + +#include "xmlsecuritydllapi.h" + +#include + +namespace com +{ +namespace sun +{ +namespace star +{ +namespace io +{ +class XInputStream; +} +namespace security +{ +class XCertificate; +} +namespace security +{ +struct DocumentSignatureInformation; +} +namespace xml +{ +namespace crypto +{ +class XSecurityEnvironment; +} +} +} +} +} + +/// 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); + 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& 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); +}; + +#endif // INCLUDED_XMLSECURITY_INC_PDFSIGNATUREHELPER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/resourcemanager.hxx b/xmlsecurity/inc/resourcemanager.hxx new file mode 100644 index 000000000..3640db40a --- /dev/null +++ b/xmlsecurity/inc/resourcemanager.hxx @@ -0,0 +1,29 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_XMLSECURITY_SOURCE_DIALOGS_RESOURCEMANAGER_HXX +#define INCLUDED_XMLSECURITY_SOURCE_DIALOGS_RESOURCEMANAGER_HXX + +#include + +inline OUString XsResId(const char* pId) { return Translate::get(pId, Translate::Create("xsc")); } + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/strings.hrc b/xmlsecurity/inc/strings.hrc new file mode 100644 index 000000000..e16a3dd7b --- /dev/null +++ b/xmlsecurity/inc/strings.hrc @@ -0,0 +1,70 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_XMLSECURITY_INC_STRINGS_HRC +#define INCLUDED_XMLSECURITY_INC_STRINGS_HRC + +#define NC_(Context, String) reinterpret_cast(Context "\004" u8##String) + +#define STR_CERTIFICATE_NOT_VALIDATED NC_("STR_CERTIFICATE_NOT_VALIDATED", "The certificate could not be validated.") +#define STR_VERSION NC_("STR_VERSION", "Version") +#define STR_SERIALNUM NC_("STR_SERIALNUM", "Serial Number") +#define STR_ISSUER NC_("STR_ISSUER", "Issuer") +#define STR_VALIDFROM NC_("STR_VALIDFROM", "Valid From") +#define STR_VALIDTO NC_("STR_VALIDTO", "Valid to") +#define STR_SUBJECT NC_("STR_SUBJECT", "Subject") +#define STR_SUBJECT_PUBKEY_ALGO NC_("STR_SUBJECT_PUBKEY_ALGO", "Subject Algorithm") +#define STR_SUBJECT_PUBKEY_VAL NC_("STR_SUBJECT_PUBKEY_VAL", "Public Key") +#define STR_SIGNATURE_ALGO NC_("STR_SIGNATURE_ALGO", "Signature Algorithm") +#define STR_USE NC_("STR_USE", "Certificate Use") +#define STR_THUMBPRINT_SHA1 NC_("STR_THUMBPRINT_SHA1", "Thumbprint SHA1") +#define STR_THUMBPRINT_MD5 NC_("STR_THUMBPRINT_MD5", "Thumbprint MD5") + +#define STR_XMLSECDLG_OLD_ODF_FORMAT NC_("STR_XMLSECDLG_OLD_ODF_FORMAT", "This document contains signatures in ODF 1.1 (OpenOffice.org 2.x) format. " \ + "Signing documents in %PRODUCTNAME %PRODUCTVERSION requires ODF 1.2 format version. " \ + "Thus no signatures can be added or removed to this document.\n\n" \ + "Save document in ODF 1.2 format and add all desired signatures again.") +#define STR_XMLSECDLG_QUERY_REMOVEDOCSIGNBEFORESIGN NC_("STR_XMLSECDLG_QUERY_REMOVEDOCSIGNBEFORESIGN", "Adding or removing a macro signature will remove all document signatures.\n" \ + "Do you really want to continue?") +#define STR_XMLSECDLG_QUERY_REALLYREMOVE NC_("STR_XMLSECDLG_QUERY_REALLYREMOVE", "Document signature cannot be restored, once removed.\n" \ + "Do you really want to remove selected signature?") + +#define STR_XMLSECDLG_SIGNING_FAILED NC_("STR_XMLSECDLG_SIGNING_FAILED", "An error occurred while adding the signature.") +#define STR_XMLSECDLG_NO_CERT_MANAGER NC_("STR_XMLSECDLG_NO_CERT_MANAGER", "Could not find any certificate manager.") +#define STR_XMLSECDLG_NO_CERT_FOUND NC_("STR_XMLSECDLG_NO_CERT_FOUND", "Could not find the certificate.") + +#define RID_XMLSECWB_NO_MOZILLA_PROFILE NC_("RID_XMLSECWB_NO_MOZILLA_PROFILE", "Digital signatures functionality could not be used, because no Mozilla user profile was found. Please check the Mozilla installation.") + +#define STR_DIGITAL_SIGNATURE NC_("selectcertificatedialog|STR_DIGITAL_SIGNATURE", "Digital signature") +#define STR_NON_REPUDIATION NC_("selectcertificatedialog|STR_NON_REPUDIATION", "Non-repudiation") +#define STR_KEY_ENCIPHERMENT NC_("selectcertificatedialog|STR_KEY_ENCIPHERMENT", "Key encipherment") +#define STR_DATA_ENCIPHERMENT NC_("selectcertificatedialog|STR_DATA_ENCIPHERMENT", "Data encipherment") +#define STR_KEY_AGREEMENT NC_("selectcertificatedialog|STR_KEY_AGREEMENT", "Key Agreement") +#define STR_KEY_CERT_SIGN NC_("selectcertificatedialog|STR_KEY_CERT_SIGN", "Certificate signature verification") +#define STR_CRL_SIGN NC_("selectcertificatedialog|STR_CRL_SIGN", "CRL signature verification") +#define STR_ENCIPHER_ONLY NC_("selectcertificatedialog|STR_ENCIPHER_ONLY", "Only for encipherment") +#define STR_SIGN NC_("selectcertificatedialog|str_sign", "Sign") +#define STR_SELECTSIGN NC_("selectcertificatedialog|str_selectsign", "Select") +#define STR_ENCRYPT NC_("selectcertificatedialog|str_encrypt", "Encrypt") + +#define STR_BROKEN_MACRO_CERTIFICATE_DATA NC_("STR_BROKEN_MACRO_CERTIFICATE_DATA", "Macro security problem!\n\nBroken certificate data: %{data}") + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/xmlsec-wrapper.h b/xmlsecurity/inc/xmlsec-wrapper.h new file mode 100644 index 000000000..c060c8bf2 --- /dev/null +++ b/xmlsecurity/inc/xmlsec-wrapper.h @@ -0,0 +1,50 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_XMLSECURITY_INC_XMLSEC_WRAPPER_H +#define INCLUDED_XMLSECURITY_INC_XMLSEC_WRAPPER_H + +#include + +#include + +// Cf. xmlsec's configure.in: +#if SAL_TYPES_SIZEOFPOINTER != 4 && !defined SYSTEM_XMLSEC +#define XMLSEC_NO_SIZE_T +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef XMLSEC_CRYPTO_NSS +#include +#include +#include +#endif + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/xmlsec/errorcallback.hxx b/xmlsecurity/inc/xmlsec/errorcallback.hxx new file mode 100644 index 000000000..511d20ae1 --- /dev/null +++ b/xmlsecurity/inc/xmlsec/errorcallback.hxx @@ -0,0 +1,33 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_XMLSECURITY_SOURCE_XMLSEC_ERRORCALLBACK_HXX +#define INCLUDED_XMLSECURITY_SOURCE_XMLSEC_ERRORCALLBACK_HXX + +#include + +// Only used for logging +void setErrorRecorder(); +//ToDo +//void setErrorRecorder(const css::uno::Reference< css::xml::crypto::XXMLEncryptionTemplate >& xTemplate); +void clearErrorRecorder(); + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/xmlsec/saxhelper.hxx b/xmlsecurity/inc/xmlsec/saxhelper.hxx new file mode 100644 index 000000000..e1eed377d --- /dev/null +++ b/xmlsecurity/inc/xmlsec/saxhelper.hxx @@ -0,0 +1,84 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_XMLSECURITY_INC_XMLSEC_SAXHELPER_HXX +#define INCLUDED_XMLSECURITY_INC_XMLSEC_SAXHELPER_HXX + +#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( + const OUString& aName , + const css::uno::Sequence< + css::xml::csax::XMLAttribute >& aAttributes ) ; + + /// @throws css::xml::sax::SAXException + /// @throws css::uno::RuntimeException + void endElement( const OUString& aName ) ; + + /// @throws css::xml::sax::SAXException + /// @throws css::uno::RuntimeException + void characters( const OUString& aChars ) ; + + /// @throws css::xml::sax::SAXException + /// @throws css::uno::RuntimeException + void ignorableWhitespace( const OUString& aWhitespaces ) ; + + /// @throws css::xml::sax::SAXException + /// @throws css::uno::RuntimeException + void processingInstruction( + const OUString& aTarget , + const OUString& aData ) ; + +} ; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/xmlsec/xmldocumentwrapper_xmlsecimpl.hxx b/xmlsecurity/inc/xmlsec/xmldocumentwrapper_xmlsecimpl.hxx new file mode 100644 index 000000000..ed984cfa1 --- /dev/null +++ b/xmlsecurity/inc/xmlsec/xmldocumentwrapper_xmlsecimpl.hxx @@ -0,0 +1,211 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_XMLSECURITY_INC_XMLSEC_XMLDOCUMENTWRAPPER_XMLSECIMPL_HXX +#define INCLUDED_XMLSECURITY_INC_XMLSEC_XMLDOCUMENTWRAPPER_XMLSECIMPL_HXX + +#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; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/xmlsec/xmlsec_init.hxx b/xmlsecurity/inc/xmlsec/xmlsec_init.hxx new file mode 100644 index 000000000..6dc4de2a6 --- /dev/null +++ b/xmlsecurity/inc/xmlsec/xmlsec_init.hxx @@ -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/. + */ + +#ifndef INCLUDED_XMLSECURITY_SOURCE_XMLSEC_XMLSEC_INIT_HXX +#define INCLUDED_XMLSECURITY_SOURCE_XMLSEC_XMLSEC_INIT_HXX + +#include + +XSECXMLSEC_DLLPUBLIC void initXmlSec(); +XSECXMLSEC_DLLPUBLIC void deInitXmlSec(); + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/xmlsec/xmlstreamio.hxx b/xmlsecurity/inc/xmlsec/xmlstreamio.hxx new file mode 100644 index 000000000..26f8128db --- /dev/null +++ b/xmlsecurity/inc/xmlsec/xmlstreamio.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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_XMLSECURITY_SOURCE_XMLSEC_XMLSTREAMIO_HXX +#define INCLUDED_XMLSECURITY_SOURCE_XMLSEC_XMLSTREAMIO_HXX + +#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< css::xml::crypto::XUriBinding > const & aUriBinding +); +int xmlUnregisterStreamInputCallbacks() ; + +#endif // INCLUDED_XMLSECURITY_SOURCE_XMLSEC_XMLSTREAMIO_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/xmlsecuritydllapi.h b/xmlsecurity/inc/xmlsecuritydllapi.h new file mode 100644 index 000000000..f0540c799 --- /dev/null +++ b/xmlsecurity/inc/xmlsecuritydllapi.h @@ -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/. + */ + +#ifndef INCLUDED_XMLSECURITY_INC_XMLSECURITYDLLAPI_H +#define INCLUDED_XMLSECURITY_INC_XMLSECURITYDLLAPI_H + +#include + +#if defined(XMLSECURITY_DLLIMPLEMENTATION) +#define XMLSECURITY_DLLPUBLIC SAL_DLLPUBLIC_EXPORT +#else +#define XMLSECURITY_DLLPUBLIC SAL_DLLPUBLIC_IMPORT +#endif + +#endif // INCLUDED_XMLSECURITY_INC_XMLSECURITYDLLAPI_H + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/xmlsignaturehelper.hxx b/xmlsecurity/inc/xmlsignaturehelper.hxx new file mode 100644 index 000000000..2437686ea --- /dev/null +++ b/xmlsecurity/inc/xmlsignaturehelper.hxx @@ -0,0 +1,169 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_XMLSECURITY_INC_XMLSIGNATUREHELPER_HXX +#define INCLUDED_XMLSECURITY_INC_XMLSIGNATUREHELPER_HXX + +#include +#include +#include +#include +#include "xmlsecuritydllapi.h" +#include "xmlsignaturehelper.hxx" +#include "xsecctl.hxx" + +class DateTime; +class UriBindingHelper; + +namespace com { +namespace sun { +namespace 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, const OUString& sODFVersion ); + + // Argument for the Link is a uno::Reference< xml::sax::XAttributeList >* + // Return 1 to verify, 0 to skip. + // Default handler will verify all. + void SetStartVerifySignatureHdl( const Link& rLink ); + + // After signing/verifying, get information about signatures + SignatureInformation GetSignatureInformation( sal_Int32 nSecurityId ) const; + SignatureInformations GetSignatureInformations() const; + + // 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); +}; + +#endif // INCLUDED_XMLSECURITY_INC_XMLSIGNATUREHELPER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/xmlsignaturehelper2.hxx b/xmlsecurity/inc/xmlsignaturehelper2.hxx new file mode 100644 index 000000000..928ea19ed --- /dev/null +++ b/xmlsecurity/inc/xmlsignaturehelper2.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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_XMLSECURITY_INC_XMLSIGNATUREHELPER2_HXX +#define INCLUDED_XMLSECURITY_INC_XMLSIGNATUREHELPER2_HXX + +#include + +#include + +#include + +namespace com { +namespace sun { +namespace 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 ); +}; + +#endif // INCLUDED_XMLSECURITY_INC_XMLSIGNATUREHELPER2_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/xsecctl.hxx b/xmlsecurity/inc/xsecctl.hxx new file mode 100644 index 000000000..324f1c433 --- /dev/null +++ b/xmlsecurity/inc/xsecctl.hxx @@ -0,0 +1,405 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_XMLSECURITY_SOURCE_HELPER_XSECCTL_HXX +#define INCLUDED_XMLSECURITY_SOURCE_HELPER_XSECCTL_HXX + +#include + +#include +#include +#include + +#include +#include + +#include + +#include "xmlsignaturehelper2.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; } + +#define NS_XMLDSIG "http://www.w3.org/2000/09/xmldsig#" +#define NS_DC "http://purl.org/dc/elements/1.1/" +#define NS_XD "http://uri.etsi.org/01903/v1.3.2#" +#define NS_MDSSI "http://schemas.openxmlformats.org/package/2006/digital-signature" +#define NS_LOEXT "urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" + +#define ALGO_C14N "http://www.w3.org/TR/2001/REC-xml-c14n-20010315" +#define ALGO_RSASHA1 "http://www.w3.org/2000/09/xmldsig#rsa-sha1" +#define ALGO_RSASHA256 "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" +#define ALGO_RSASHA512 "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512" +#define ALGO_ECDSASHA1 "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1" +#define ALGO_ECDSASHA256 "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256" +#define ALGO_ECDSASHA512 "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512" +#define ALGO_XMLDSIGSHA1 "http://www.w3.org/2000/09/xmldsig#sha1" +#define ALGO_XMLDSIGSHA256 "http://www.w3.org/2001/04/xmlenc#sha256" +#define ALGO_XMLDSIGSHA512 "http://www.w3.org/2001/04/xmlenc#sha512" +#define ALGO_RELATIONSHIP "http://schemas.openxmlformats.org/package/2006/RelationshipTransform" + +class XMLDocumentWrapper_XmlSecImpl; +class SAXEventKeeperImpl; +class XMLSignatureHelper; +namespace svl::crypto { enum class SignatureMethodAlgorithm; } + +class InternalSignatureInformation +{ +public: + SignatureInformation signatureInfor; + + css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > xReferenceResolvedListener; + + ::std::vector< sal_Int32 > vKeeperIds; + + InternalSignatureInformation( + sal_Int32 nId, + css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > const & xListener) + :signatureInfor(nId) + { + xReferenceResolvedListener = xListener; + } + + void addReference( SignatureReferenceType type, sal_Int32 digestID, const OUString& uri, sal_Int32 keeperId, const OUString& rType ) + { + signatureInfor.vSignatureReferenceInfors.push_back( + SignatureReferenceInformation(type, digestID, uri, rType)); + vKeeperIds.push_back( keeperId ); + } +}; + +class XSecController final : public cppu::WeakImplHelper +< + css::xml::crypto::sax::XSAXEventKeeperStatusChangeListener, + css::xml::crypto::sax::XSignatureCreationResultListener, + css::xml::crypto::sax::XSignatureVerifyResultListener +> +/****** XSecController.hxx/CLASS XSecController ******************************* + * + * NAME + * XSecController -- the xml security framework controller + * + * FUNCTION + * Controls the whole xml security framework to create signatures or to + * verify signatures. + * + ******************************************************************************/ +{ + friend class XSecParser; + friend class OOXMLSecParser; + +private: + css::uno::Reference< css::uno::XComponentContext> mxCtx; + + /* + * used to buffer SAX events + */ + rtl::Reference 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(); + 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 setX509IssuerName( OUString const & ouX509IssuerName ); + void setX509SerialNumber( OUString const & ouX509SerialNumber ); + void setX509Certificate( OUString const & ouX509Certificate ); + 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 & ouDate ); + void setDescription(const OUString& rDescription); + void setCertDigest(const OUString& rCertDigest); + void setValidSignatureImage(const OUString& rValidSigImg); + void setInvalidSignatureImage(const OUString& rInvalidSigImg); + void setSignatureLineId(const OUString& rSignatureLineId); + +public: + void setSignatureBytes(const css::uno::Sequence& rBytes); + +private: + void setId( OUString const & ouId ); + void setPropertyId( OUString const & ouPropertyId ); + + css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > prepareSignatureToRead( + sal_Int32 nSecurityId ); + +public: + explicit XSecController(const css::uno::Reference& rxCtx); + 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; + + 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( const OUString& 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); +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/inc/xsecxmlsecdllapi.h b/xmlsecurity/inc/xsecxmlsecdllapi.h new file mode 100644 index 000000000..2f1d8d7c3 --- /dev/null +++ b/xmlsecurity/inc/xsecxmlsecdllapi.h @@ -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/. + */ + +#ifndef INCLUDED_XMLSECURITY_INC_XSECXMLSECDLLAPI_H +#define INCLUDED_XMLSECURITY_INC_XSECXMLSECDLLAPI_H + +#include + +#if defined(XSECXMLSEC_DLLIMPLEMENTATION) +#define XSECXMLSEC_DLLPUBLIC SAL_DLLPUBLIC_EXPORT +#else +#define XSECXMLSEC_DLLPUBLIC SAL_DLLPUBLIC_IMPORT +#endif + +#endif // INCLUDED_XMLSECURITY_INC_XSECXMLSECDLLAPI_H + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/qa/certext/SanCertExt.cxx b/xmlsecurity/qa/certext/SanCertExt.cxx new file mode 100644 index 000000000..c117f4c00 --- /dev/null +++ b/xmlsecurity/qa/certext/SanCertExt.cxx @@ -0,0 +1,260 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#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 000000000..0092d16c7 --- /dev/null +++ b/xmlsecurity/qa/certext/User_35_Root_11.crt @@ -0,0 +1,64 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4130 (0x1022) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Nov 8 10:51:39 2010 GMT + Not After : Nov 8 10:51:39 2011 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 35 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:9b:36:00:64:f3:ce:93:97:62:19:fa:78:d9:6f: + 92:6a:b9:d2:9a:4e:06:2c:02:52:cd:93:50:84:28: + 19:42:a2:4a:34:e2:cd:e6:b0:39:7a:c8:4d:84:bc: + 71:51:ed:5d:6c:7e:f9:cc:01:5a:4b:73:50:a9:3b: + 5d:ad:cc:89:f7:dc:e0:dd:0a:ff:48:01:a9:34:19: + c0:6a:ee:4b:20:f4:cf:3c:94:c1:ae:88:0f:c9:42: + 1a:a6:47:31:fe:37:04:00:bb:ec:07:5f:cb:ee:70: + c4:c7:7c:6f:ee:03:19:76:de:0b:df:d0:48:91:67: + 55:9b:90:91:f4:ce:56:04:d5 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 91:47:AC:29:95:5D:EF:72:14:8F:82:45:07:E2:94:49:75:C6:7D:73 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DNS:alt.openoffice.org, IP Address:192.168.7.1, IP Address:13:0:0:0:0:0:0:17, email:my@other.address, Registered ID:1.2.3.4, othername:, DirName:/C=DE/O=OpenOffice.org/OU=Development/CN=User 32 Root 11, URI:http://my.url.here/ + Signature Algorithm: sha1WithRSAEncryption + 6e:80:e6:1e:86:3d:d2:65:a6:17:fa:80:2d:2e:dc:85:32:05: + a1:69:82:e1:79:d1:dc:de:69:cd:9e:f0:cc:90:75:a9:45:ee: + 73:46:fe:29:69:c0:99:bb:fc:3a:db:c0:5f:69:c6:b7:ea:9a: + 63:b2:8e:29:2c:a5:5a:88:88:94:75:4b:ab:0a:72:f6:3a:aa: + 5d:6b:3a:5c:b6:9b:57:f5:c1:51:af:df:3c:a6:8a:a3:da:70: + 66:61:49:12:06:78:98:9f:bc:78:3c:43:6d:08:94:aa:32:b6: + f3:cc:af:0d:29:fe:96:47:7d:fe:4a:61:48:90:11:0b:bd:0f: + a0:fd +-----BEGIN CERTIFICATE----- +MIIDajCCAtOgAwIBAgICECIwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDExMDgxMDUx +MzlaFw0xMTExMDgxMDUxMzlaMGAxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxEDAOBgNVBAMTB1VzZXIgMzUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB +AJs2AGTzzpOXYhn6eNlvkmq50ppOBiwCUs2TUIQoGUKiSjTizeawOXrITYS8cVHt +XWx++cwBWktzUKk7Xa3Miffc4N0K/0gBqTQZwGruSyD0zzyUwa6ID8lCGqZHMf43 +BAC77Adfy+5wxMd8b+4DGXbeC9/QSJFnVZuQkfTOVgTVAgMBAAGjggExMIIBLTAL +BgNVHQ8EBAMCBeAwHQYDVR0OBBYEFJFHrCmVXe9yFI+CRQfilEl1xn1zMB8GA1Ud +IwQYMBaAFOhqu8KQ6mxwIj729kgbA+a+t6ZVMIHdBgNVHREEgdUwgdKCEmFsdC5v +cGVub2ZmaWNlLm9yZ4cEwKgHAYcQABMAAAAAAAAAAAAAAAAAF4EQbXlAb3RoZXIu +YWRkcmVzc4gDKgMEoB4GAyoDBKAXDBVzb21lIG90aGVyIGlkZW50aWZpZXKkWDBW +MQswCQYDVQQGEwJERTEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsT +C0RldmVsb3BtZW50MRgwFgYDVQQDEw9Vc2VyIDMyIFJvb3QgMTGGE2h0dHA6Ly9t +eS51cmwuaGVyZS8wDQYJKoZIhvcNAQEFBQADgYEAboDmHoY90mWmF/qALS7chTIF +oWmC4XnR3N5pzZ7wzJB1qUXuc0b+KWnAmbv8OtvAX2nGt+qaY7KOKSylWoiIlHVL +qwpy9jqqXWs6XLabV/XBUa/fPKaKo9pwZmFJEgZ4mJ+8eDxDbQiUqjK288yvDSn+ +lkd9/kphSJARC70PoP0= +-----END CERTIFICATE----- diff --git a/xmlsecurity/qa/create-certs/create-certs.sh b/xmlsecurity/qa/create-certs/create-certs.sh new file mode 100755 index 000000000..4a0298047 --- /dev/null +++ b/xmlsecurity/qa/create-certs/create-certs.sh @@ -0,0 +1,185 @@ +#!/bin/bash -e +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.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 +# + +root="$PWD" +algo="RSA" + +if [ -n "$1" ]; then + algo="$1" +fi + +if [ -d "$root/ca" ]; then + echo "'ca' directory already exists in $root, please remove it before running this script." + exit 1 +fi + +if [ -z "$SSLPASS" ]; then + # Unless specified otherwise, we'll use this as a password everywhere. + export SSLPASS="xmlsecurity" +fi + +# 1) Create the root pair. + +mkdir "$root/ca" + +cd "$root/ca" +mkdir certs crl newcerts private +chmod 700 private +touch index.txt +echo 1000 > serial + +sed "s|@ROOT@|$root|g" "$root/templates/root.cnf" > "$root/ca/openssl.cnf" + +# Create the root key. +cd "$root/ca" +openssl genrsa -aes256 -out private/ca.key.pem -passout env:SSLPASS 4096 +chmod 400 private/ca.key.pem + +# Create the root certificate. +cd "$root/ca" +openssl req -config openssl.cnf \ + -key private/ca.key.pem \ + -new -x509 -days 36500 -sha256 -extensions v3_ca \ + -out certs/ca.cert.pem \ + -passin env:SSLPASS \ + -subj "/C=UK/ST=England/O=Xmlsecurity ${algo} Test/CN=Xmlsecurity ${algo} Test Root CA" +chmod 444 certs/ca.cert.pem + +# 2) Create the intermediate pair. + +# Prepare the directory. +mkdir "$root/ca/intermediate" +cd "$root/ca/intermediate" +mkdir certs crl csr newcerts private +chmod 700 private +touch index.txt +echo 1000 > serial + +# crlnumber is used to keep track of certificate revocation lists. +echo 1000 > "$root/ca/intermediate/crlnumber" + +# Copy the intermediate CA configuration file. +sed "s|@ROOT@|$root|g" "$root/templates/intermediate.cnf" > "$root/ca/intermediate/openssl.cnf" + +# Create the intermediate key. + +cd "$root/ca" +openssl genrsa -aes256 \ + -out intermediate/private/intermediate.key.pem \ + -passout env:SSLPASS 4096 +chmod 400 intermediate/private/intermediate.key.pem + +# Create the intermediate certificate. + +# Intermediate key. +cd "$root/ca" +openssl req -config intermediate/openssl.cnf -new -sha256 \ + -key intermediate/private/intermediate.key.pem \ + -out intermediate/csr/intermediate.csr.pem \ + -passin env:SSLPASS \ + -subj "/C=UK/ST=England/O=Xmlsecurity ${algo} Test/CN=Xmlsecurity Intermediate Root CA" + +# The certificate itself. +openssl ca -batch -config openssl.cnf -extensions v3_intermediate_ca \ + -days 36500 -notext -md sha256 \ + -in intermediate/csr/intermediate.csr.pem \ + -passin env:SSLPASS \ + -out intermediate/certs/intermediate.cert.pem +chmod 444 intermediate/certs/intermediate.cert.pem + +# Create the certificate chain file. +cat intermediate/certs/intermediate.cert.pem \ + certs/ca.cert.pem > intermediate/certs/ca-chain.cert.pem +chmod 444 intermediate/certs/ca-chain.cert.pem + +# 3) Create the real certificate. + +for i in Alice Bob +do + # Create a key. + cd "$root/ca" + if [ "$algo" == "ECDSA" ]; then + openssl ecparam -name secp256r1 -genkey \ + -out intermediate/private/example-xmlsecurity-${i}.key.pem + else + openssl genrsa -aes256 \ + -out intermediate/private/example-xmlsecurity-${i}.key.pem \ + -passout env:SSLPASS 2048 + fi + chmod 400 intermediate/private/example-xmlsecurity-${i}.key.pem + + # Create a certificate signing request (CSR). + + cd "$root/ca" + openssl req -config intermediate/openssl.cnf \ + -key intermediate/private/example-xmlsecurity-${i}.key.pem \ + -new -sha256 -out intermediate/csr/example-xmlsecurity-${i}.csr.pem \ + -passin env:SSLPASS \ + -subj "/C=UK/ST=England/O=Xmlsecurity ${algo} Test/CN=Xmlsecurity ${algo} Test example ${i}" + + # To create a certificate, use the intermediate CA to sign the CSR. + cd "$root/ca" + # usr_cert: the cert will be used for signing. + openssl ca -batch -config intermediate/openssl.cnf \ + -extensions usr_cert -days 36500 -notext -md sha256 \ + -in intermediate/csr/example-xmlsecurity-${i}.csr.pem \ + -passin env:SSLPASS \ + -out intermediate/certs/example-xmlsecurity-${i}.cert.pem + chmod 444 intermediate/certs/example-xmlsecurity-${i}.cert.pem + + # Export it in PKCS#12 format. + if [ "$algo" == "ECDSA" ]; then + openssl pkcs12 -export \ + -out ./intermediate/private/example-xmlsecurity-${i}.cert.p12 \ + -passout env:SSLPASS \ + -inkey intermediate/private/example-xmlsecurity-${i}.key.pem \ + -passin env:SSLPASS \ + -in intermediate/certs/example-xmlsecurity-${i}.cert.pem \ + -certfile intermediate/certs/ca-chain.cert.pem + else + openssl pkcs12 -export \ + -out ./intermediate/private/example-xmlsecurity-${i}.cert.p12 \ + -passout env:SSLPASS \ + -inkey intermediate/private/example-xmlsecurity-${i}.key.pem \ + -passin env:SSLPASS \ + -in intermediate/certs/example-xmlsecurity-${i}.cert.pem \ + -certfile intermediate/certs/ca-chain.cert.pem \ + -CSP "Microsoft Enhanced RSA and AES Cryptographic Provider" + fi +done + +echo +echo "Authority certificate is at: <$root/ca/intermediate/certs/ca-chain.cert.pem>." +echo "To be able to import it in Windows, rename the '.pem' extension to '.cer'." +for i in Alice Bob +do + echo "Signing certificate is at <$root/ca/intermediate/private/example-xmlsecurity-${i}.cert.p12>." +done + +# vim:set shiftwidth=4 expandtab: diff --git a/xmlsecurity/qa/create-certs/templates/intermediate.cnf b/xmlsecurity/qa/create-certs/templates/intermediate.cnf new file mode 100644 index 000000000..c6fd12d0a --- /dev/null +++ b/xmlsecurity/qa/create-certs/templates/intermediate.cnf @@ -0,0 +1,132 @@ +# OpenSSL intermediate CA configuration file. +# Copy to `$root/ca/intermediate/openssl.cnf`. + +[ ca ] +# `man ca` +default_ca = CA_default + +[ CA_default ] +# Directory and file locations. +dir = @ROOT@/ca/intermediate +certs = $dir/certs +crl_dir = $dir/crl +new_certs_dir = $dir/newcerts +database = $dir/index.txt +serial = $dir/serial +RANDFILE = $dir/private/.rand + +# The root key and root certificate. +private_key = $dir/private/intermediate.key.pem +certificate = $dir/certs/intermediate.cert.pem + +# For certificate revocation lists. +crlnumber = $dir/crlnumber +crl = $dir/crl/intermediate.crl.pem +crl_extensions = crl_ext +default_crl_days = 30 + +# SHA-1 is deprecated, so use SHA-2 instead. +default_md = sha256 + +name_opt = ca_default +cert_opt = ca_default +default_days = 375 +preserve = no +policy = policy_loose + +[ policy_strict ] +# The root CA should only sign intermediate certificates that match. +# See the POLICY FORMAT section of `man ca`. +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +[ policy_loose ] +# Allow the intermediate CA to sign a more diverse range of certificates. +# See the POLICY FORMAT section of the `ca` man page. +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +[ req ] +# Options for the `req` tool (`man req`). +default_bits = 2048 +distinguished_name = req_distinguished_name +string_mask = utf8only + +# SHA-1 is deprecated, so use SHA-2 instead. +default_md = sha256 + +# Extension to add when the -x509 option is used. +x509_extensions = v3_ca + +[ req_distinguished_name ] +# See . +countryName = Country Name (2 letter code) +stateOrProvinceName = State or Province Name +localityName = Locality Name +0.organizationName = Organization Name +organizationalUnitName = Organizational Unit Name +commonName = Common Name +emailAddress = Email Address + +# Optionally, specify some defaults. +countryName_default = GB +stateOrProvinceName_default = England +localityName_default = +0.organizationName_default = Xmlsecurity Test +organizationalUnitName_default = +emailAddress_default = + +[ v3_ca ] +# Extensions for a typical CA (`man x509v3_config`). +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer +basicConstraints = critical, CA:true +keyUsage = critical, digitalSignature, cRLSign, keyCertSign + +[ v3_intermediate_ca ] +# Extensions for a typical intermediate CA (`man x509v3_config`). +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer +basicConstraints = critical, CA:true, pathlen:0 +keyUsage = critical, digitalSignature, cRLSign, keyCertSign + +[ usr_cert ] +# Extensions for client certificates (`man x509v3_config`). +basicConstraints = CA:FALSE +nsCertType = client, email +nsComment = "OpenSSL Generated Client Certificate" +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer +keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment +extendedKeyUsage = clientAuth, emailProtection + +[ server_cert ] +# Extensions for server certificates (`man x509v3_config`). +basicConstraints = CA:FALSE +nsCertType = server +nsComment = "OpenSSL Generated Server Certificate" +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer:always +keyUsage = critical, digitalSignature, keyEncipherment +extendedKeyUsage = serverAuth + +[ crl_ext ] +# Extension for CRLs (`man x509v3_config`). +authorityKeyIdentifier=keyid:always + +[ ocsp ] +# Extension for OCSP signing certificates (`man ocsp`). +basicConstraints = CA:FALSE +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer +keyUsage = critical, digitalSignature +extendedKeyUsage = critical, OCSPSigning diff --git a/xmlsecurity/qa/create-certs/templates/root.cnf b/xmlsecurity/qa/create-certs/templates/root.cnf new file mode 100644 index 000000000..1298d74d3 --- /dev/null +++ b/xmlsecurity/qa/create-certs/templates/root.cnf @@ -0,0 +1,132 @@ +# OpenSSL root CA configuration file. +# Copy to `$root/ca/openssl.cnf`. + +[ ca ] +# `man ca` +default_ca = CA_default + +[ CA_default ] +# Directory and file locations. +dir = @ROOT@/ca +certs = $dir/certs +crl_dir = $dir/crl +new_certs_dir = $dir/newcerts +database = $dir/index.txt +serial = $dir/serial +RANDFILE = $dir/private/.rand + +# The root key and root certificate. +private_key = $dir/private/ca.key.pem +certificate = $dir/certs/ca.cert.pem + +# For certificate revocation lists. +crlnumber = $dir/crlnumber +crl = $dir/crl/ca.crl.pem +crl_extensions = crl_ext +default_crl_days = 30 + +# SHA-1 is deprecated, so use SHA-2 instead. +default_md = sha256 + +name_opt = ca_default +cert_opt = ca_default +default_days = 375 +preserve = no +policy = policy_strict + +[ policy_strict ] +# The root CA should only sign intermediate certificates that match. +# See the POLICY FORMAT section of `man ca`. +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +[ policy_loose ] +# Allow the intermediate CA to sign a more diverse range of certificates. +# See the POLICY FORMAT section of the `ca` man page. +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +[ req ] +# Options for the `req` tool (`man req`). +default_bits = 2048 +distinguished_name = req_distinguished_name +string_mask = utf8only + +# SHA-1 is deprecated, so use SHA-2 instead. +default_md = sha256 + +# Extension to add when the -x509 option is used. +x509_extensions = v3_ca + +[ req_distinguished_name ] +# See . +countryName = Country Name (2 letter code) +stateOrProvinceName = State or Province Name +localityName = Locality Name +0.organizationName = Organization Name +organizationalUnitName = Organizational Unit Name +commonName = Common Name +emailAddress = Email Address + +# Optionally, specify some defaults. +countryName_default = GB +stateOrProvinceName_default = England +localityName_default = +0.organizationName_default = Xmlsecurity Test +organizationalUnitName_default = +emailAddress_default = + +[ v3_ca ] +# Extensions for a typical CA (`man x509v3_config`). +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer +basicConstraints = critical, CA:true +keyUsage = critical, digitalSignature, cRLSign, keyCertSign + +[ v3_intermediate_ca ] +# Extensions for a typical intermediate CA (`man x509v3_config`). +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer +basicConstraints = critical, CA:true, pathlen:0 +keyUsage = critical, digitalSignature, cRLSign, keyCertSign + +[ usr_cert ] +# Extensions for client certificates (`man x509v3_config`). +basicConstraints = CA:FALSE +nsCertType = client, email +nsComment = "OpenSSL Generated Client Certificate" +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer +keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment +extendedKeyUsage = clientAuth, emailProtection + +[ server_cert ] +# Extensions for server certificates (`man x509v3_config`). +basicConstraints = CA:FALSE +nsCertType = server +nsComment = "OpenSSL Generated Server Certificate" +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer:always +keyUsage = critical, digitalSignature, keyEncipherment +extendedKeyUsage = serverAuth + +[ crl_ext ] +# Extension for CRLs (`man x509v3_config`). +authorityKeyIdentifier=keyid:always + +[ ocsp ] +# Extension for OCSP signing certificates (`man ocsp`). +basicConstraints = CA:FALSE +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer +keyUsage = critical, digitalSignature +extendedKeyUsage = critical, OCSPSigning diff --git a/xmlsecurity/qa/unit/data/xmlsecurity-dialogs-test.txt b/xmlsecurity/qa/unit/data/xmlsecurity-dialogs-test.txt new file mode 100644 index 000000000..91af2a366 --- /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 VclBuilder +# + +# 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 000000000..10528c57f 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 000000000..04d995058 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 000000000..b30f5b038 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/cert8.db b/xmlsecurity/qa/unit/pdfsigning/data/cert8.db new file mode 100644 index 000000000..8354fd309 Binary files /dev/null and b/xmlsecurity/qa/unit/pdfsigning/data/cert8.db 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 000000000..b1aae07a2 --- /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 k0Uc0ljFcx/W7jkQiqGDMORIqePYYqynzH+bWuWGu31jZW9o9taytCjSJIXJT4WqVkUfaB7YKW2T fl15t1jzJBez38UEUduyRw+grrViCWrzd+nw4lLMMCsZ/MnUPqXk3UGBo86rbp7+qwVh/wABywhX gGFDsVez2vmJdD/KuyvUYfWGh9C1H/FzMwH/AANC30YFeMEliWY1J3JPUnCrsVehLrupeVPImjDT pBDeanLNcysVV/3a0UbMD1HE4FQNj+Zfnm8vbe0jvE9S4lSJP3MXV2Cj9n3w0r0vzh580vy3H6TD 6zqLrWO0U0oD0aRt+I/E4KS8t1L80vOF45Md0tnEekUCKKf7Jgz/AI4aQh7T8x/OdtIHGpPKO6Sq jqfbcV+7Glen+QvzAi8xh7S6jW31OJeZVa8JV6FkrUincf5gEJYf5r/MvzLaeY7+1065SO0t5TFG hjjahjAVt2Un7QONIQ9j+b/mGC0uBc8Lu7kKi2LIqRxgV5sQgUsTtQVxpbRXlr8ztUFzd3+vXplt IIqQWUSRqZJnI4gUUGgVWqSdsaVKtb/NTzTqEjC2mGn237MUAHKn+VIRyr8qYaVJ4/OfmxJPUXV7 st1o0zsu3+SxIxVm/kz82Lt7uKw18q8crBI74AIVY7D1AKLx9xSmCltmfnXzja+WdPWVk9e8uCVt betASPtMx/lWuBLyHUfzG84X8hY6g9up+zFbfugPkV+L7zkqQhG8zecrZlMmp38ZYVUSTS0I9gxx VlPlH81tXhvobTWpBdWcrBDcEBZI+RoGqoHIDvXfBSvT/MPmLTdB09r2/ei/ZiiXd5G/lUYEvIdb /NfzPfysLOQadbVPFIgGkp25SMK1/wBWmGkJGvnLzYr8xq93y8DM5G3+STTCrM/J/wCbN8LuKy19 llt5CEW+ACOhOwMgFFK+JpX54KW0L5u/MnzJBr+o2VhdLHZRSNAiiNGI4Dg/xEE/aBxpXn2FU/0X z15k0ayFlp9wsVuGL8TGjHk3U1YE4qkc80k80k0rcpZWLux7sxqT9+Ksm8leZ/Mdnd2ujaZOsUF5 dJzBjRjykKozVYE/ZGKvRdU8ya7Hqlx9Xk4W9q0gkjZE9JSgkMSOSpkLziKo4kbMvf7QVK/zs1Dj Y6bp6n+9kedx7RrxX7/UOIUvJcKqt3azWl1NbTDjLC7I491NMVTHVtdlvNJ0rTFJFvp0TAj+aWR2 Zm+hSB9+Kpc9tIltHcMKRysyR+/ALyPy+IYqpojO6ogq7EKo8SdhirL/AMznSHWLPSYyDHpNlBbU H83HkT9KlcQqVeTpYbbXI9RnHKHTY5Ltl8WjU+mv+ykKjFUs1HULvUb6a9u3MlxOxeRj4nsPYdAM Vekflh5Csbuy/TWrwCdJCRZW8gqnFTQyMv7VTsAdu/hgJVvz1+Wd/dawlx5esY0tXiHrRo0cSCUE g8VJWlVp0xBVLvLnknzd5f1m31m6tljtLLlJcuJozSIIQ+wJr8OKsCuJ5J55J5DWSVmdz4sxqcKp /wCUfI+qeZJJHhZbayhNJruQEqG68VA+01N+uKpDcpDHcypBIZYUdlilI4llBoGpU0qN6VxVl35a +T4tf1OS4vV5abZUMqbj1JGrxTbttU/24lXoH5jeXtGPk+6lS1hgkslV7aSNFQr8YBUcQNmBpTAF eG4VZj+YLX1zZ+XNQnq0U2mxpzO9ZUJMhr4kMpxCsZ0jUpdM1O21CJEkktnEipIOSkjxGKs51v8A MLy75n0+Ky1myubP05BIs1qY5iCAQfthKA13wUqK0P8ALjyTrkBm03WLiYJT1I/gV0r/ADIVBGNq xXz/AOY5dc8xTuGJs7VmgtF7cVNC/wDsyK/dhVW/LvymnmHWT9ZBOnWYElzSo5EmiR1HTlQ/QDiV en+ePLeiN5QvglnDAbSEy27xoqlGjFQAVHelMCXg2FDP9csNCh/LTTtSSzjTU71kia4oeZKFi7de /p7/ADwKwAAkgAVJ2AGFXrvnDyp5c0TyQ8wsYhqSxwwLPuWMrFVdutK05HAryIAkgAVJ2AGFX0Jo fkjy/psVlMtjENQto05XG5b1AtGbrSpNcFpTqSwsZLhbmS2ie5SnCZkUuKdKMRUdcCvFvzc1D6z5 taAH4bKGOL25MDIf+JgYQgse8r6b+kvMWnWRHJJp09Qf5Cnk/wDwoOFVXzn/AMpZq/8AzFy/8TOK pZZWdxe3kNnbrznuHWOJfFmNBirIPP8Ab29hq8GjW5rDpVtFAWH7UjVlkc+7NJviqF8j6f8AX/Nu l29OSicSuD04w/vDX6ExVD+aL/8ASHmLUbwGqy3EhjP+QG4p/wAKBiqJ0qyl/wAK65fqPhBtrZj/ AJLy+o3/AA0aYqkWKvpLy0LePy3pghI9BbSHi3QU9Mbn+ORSx24/N3ylDPJD/pEvpsV9SONSjUNK qS4qDhpbS3zJ+Y+k6r5V1aLTknWT00iZ5UVV/fOEK1DNuU5H6MaQ8hwq+grHSf0P5EayhXhPFYyN JTqZmjLOf+DOBL59woe2fk6sA8qOY6eo11J63jyCrQH/AGNMBUIT84PMUMGlpocTg3N2yvcqP2Ik PIV/1mAp8jiFLAtF0bye/GTWNfWJdibe3guGangXaMAfQDhV6LdebPysutHj0ee5WSwiRY4ozBc1 QIOKlW9PkGA71rgVjyflXpesWv6Q8t6sZLNyyxrcxOu6mh+OiHr/AJGNqwrzD5e1HQNRNhfhRLxE iOh5I6EkBlOx6qeowqivI9/eWXmeya1Yh5m9BlH7SyDjSnfxHviqRYq9j/JVYP8AD98wp65uyJPH gI04fiWwFQrfm35ihstCOlRuDeagQGUdVhVqsx/1iOI+nwxCl4vHG8jrHGpZ3IVVG5JOwAwqzv8A MtG07T/L2gE/HZWnqTAGoLvRSf8AgkamAKxvydYfX/NOmWtOStcI7jxSP943/CqcKvQ/zs1Dhp+n aeD/AH0rzuPaJeI/5OHAFLzvyhYi+8z6ZakVR7hGcHuiHmw/4FThV9HZFLsVfNXmLUP0jruoXoNV nnkdP9TkeP8AwtMkhlv5N6b9Y8yTXrCqWUB4nweU8B/wvLAVDHvPCBPN+rAGtbl2/wCCNf44VZd+ Tnlz1rubXZ1/d29YbSveRh8bD/VU0+n2wFQwXzFqH6R13UL0GqzzyOn+pyPH/haYVZB+XdbT9N61 0/RthJ6TeE0u0f38SMVYfir2PyH5Zhvvy4ms5/g/SrSyc6VKlSEjb/YtEGwFXlOsaNqOj3z2V/CY pkJoT9lh2ZT3Bwqvj8xa7Fpx02O/mSxIINuHIWh3I+R8MVdougatrV2LbTrdpn/bfoiDxdugGKst 8+6NaeWfLumaHA/q3FzK93ezUoWeNQi/7EczxGBWLeVtP/SPmLTrMiqSzp6g/wAhTyf/AIUHCr6R IBBBFQdiDkUvn/zv5NvfL2pSFY2fTJWLWtwBVQDvwY9mX8ckhKdK1/WdJMh028kthKKSBDs3gSDU VHY4qhyb/UbypMt3eXDdfikkdj95JxV6X5W/KeY6XdT6vSK+uYHjs4evoswoHen7Xt2Hv0FrTznV dI1HSbx7O/gaCdDSjDZh/Mp6MPcYVTHQPO3mLQYHt9PuALd25mGRVdQx7iu4+jFUv1jWtS1i+a91 GYzXDAKDQAKo6KoFAAMVegflb5HvRfR69qMRhhhBNlE4IZ2YU9Qqf2QDt49cBVIPzB8lXmianNdw RF9JuHLwyqKiMsa+m/8ALQ/Z8RhCsf0rXNX0mR5NNupLZpBSTgdmA6VB2NMVULi4vtQuzLPJJdXc zbsxLuxOwHc4q9R/Lj8ubm0uI9a1mP05o/is7NvtK3aSQdiOy/fgJVh/5l6h9c85X5BqluVt09vT UBv+H5YQqa/k3Yev5lmuyPhtLdiD/lyEKP8AheWAqEw/OnTb5ryx1FUZrNYjC7ipCPyLfF4cgdvl iFLza1urm1uEuLaVoZ4zWOWMlWU+xGFXvn5dvqMvlS1udQuJLm4uS8vOVizBC3FRU9qLX6cBSyXA qU/86n/y4f8AJHCqLsP0T+8/R/odvV+r8Pfjy4fTTAqhcf4b9d/rH1P16/vPU9LnX3rviqMs/qfo D6n6foVPH0ePCtd6cdsVS/8A51P/AJcP+SOFVaL9AfV5vR+qfV/h+scPT4dfh502+VcCqP8Azqf/ AC4f8kcKplb/AFf0E+rcPQp+79OnCntx2wKg9a/QP1T/AHNfVvqvb63w419uff5YqxeD/lUPrnh+ judf92U4Vr/l/BTChmGn/o76qn6O9H6p+x9X4+n9HD4cCVO//Q3Nfr/1fnT4PX4Vp7c8VU7T/D31 hPqn1T6xvw9L0ufQ1px36YqmGKqV19V+ryfWuH1en731acOP+Vy2pirCrr/lUPrt6v6P59/S+z9H p/DhQyHy9/hH0z+gPqdKfH9V9PnT/L4/F9+BKc4qgdX/AEJ9V/3MfVvqtf8Aj74cK/8APTbFWGXX /KmuX7z6pWv+6vVpX/nntTDuhN9B/wCVb/WF/RH6P+tVHCnD1a/5HP4/uxSyrAqyb0fSf1uPpUPq c6cePetdqYqwq+/5VH67ev8Ao71P2vSpx/5JfDhQnPl3/BFR+gfqPq039Dh61Pf/AHZ9+BKf4qlk 3+GfVf1vqXrcj6nP0uXKu/Ku9a4qiLD9E/vP0f6Hb1fq/D348uH00xVFNx4nlTjT4q9Ke+KpU3+E ufxfUOe/X0a++FUzg9D0U9Dj6NB6fp048e3Gm1MCr8Vf/9k= + + + + + + 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 TkKN4EZRn0cMg3DGRhPaQfYH5Ufmhpnn/QWu4kFtqdoVTUrKtQjNXi6E9UfiaeG47VPM6vSnDKun R12fCYHyYZr+v+a9A/MHzReaUJb6PWZrXQrO1PJ4rbUnsYJLG4KivGEmWX1jt0XMVoSzy55h1jy1 o6W8N1G8trbw2dx5h1BHnNvBJrt9bS3Vx8aclSOIEVYKGNWPGuKp/e+fPNkP6Ru7PXrG80Sz/RVu NWFoHiVNQcCfUJDHKB6cSfZAPGp5MeIpiqFh/NjzOl/osUlxbahaXlzfW1k9hEnr6qIGItpo4XlL JbyBWRpYuQD0agjYYqk+qeZPMXnXRrbSJtZs77T7ybQpNTms7TjHDcXl76c+m3EcksnIJxVjG/xU BWQUYYqyfydbectYEa2vnEE6D5i1OPWdO9KP1fqsd9OkFu4BYorwhWjBAAQjjsoxV6zirsVdirsV dirsVdirsVdirsVdirsVdirsVdirsVdirsVeJa1q8+sa9I8hLEv6cMS/FTfiFUDrvm+xwEIPI5Jy z5iT8GY2P5dzS24+tyLbsw+yBzYHwNCB9xzBnrBezucXZ5rc088/MTyN5y8r08yaFMCbFw8d1AwS SOpCguj7cW5UYVYU2O2Zum1OPL6JdWZwSxmw85/Mv8xde87SWy3oW3trSNVNrCW9Iz8QJZfi3+Jq 8a9F2zN0ukjhuurnYs3V58LGWSVYoozJI5oqKKkk5mW5Ucj3H8tv+cabm9SPUvOJe0t2o0elptMw Ir+9J/u+3w0r16Zp9V2oBtj382Rz1yeO/mn5a1Pyp581jRLS6ljsrecm1jjchRBKoliVgvFSRG68 tuuZWnPiwEurZHJI72zD/nGjX7u2/Muzt3pF9cilt7oooVZYihdKqNg6zIm4HStfertHHeI30bMk uLGQeY3e1+cPPXmvyr+eflbTb2/5eR/NML2kVs0UIEWoL8K0lCCU8naLYvT4jttnOOven63q9lo2 jX2r3zcLPTreW6uW7iOFC7U+hcVeJ+RT+a35h/lnY6/qHnKTy7d3+sm8sniggUDTouUYtRwEHPk9 WBflyAFQcVe3alq+k6XALjU72CxtyeImuZUhSvhycqMVVI9QsJIIp47mJ4JzSGVXUo5O1FYGh+jF VWWWKJDJK6xxr9p2IAHzJxVbLdW0Nu1zLKkduq82mdgqBf5ix2piqG0zXNF1VXbS9Qtr9YjSQ200 cwU+DcC1OmKvL/y31zWrv88vzM0271C5uNOsP0f9RspZpHgg9SEl/SjYlE5HrxG+KrPzj/MHzrbe c/Lf5c+SZYdP1zzErzy6xcIsot4I+ZPpxsGUtSJyag9KDc1Cqb+TfJ35u6D5jiuvMHnmPzJ5eaCQ XltNZRWciS0rG6MnqVUGtfjX5HFUV5X/ADVt9b/MPzV5VaGG2tfLi2ohvjOGNy1whdiFooUL0oCc VZ5HPBIzrHIrtGaSKpBKnwIHTFXevB63o+ovrU5elUcuPjx60xVC6lruiaX6f6T1C2sfWPGL6zNH DzPgvMrX6MVeXaNr+rz/APOT2saT+kriXRF8sx3UFh6ztaCVp7ceskXL0+RVj8QFaHFWZflz5f8A MGiafqMOteZn80TXF/LPBcyKEMETBQIBRpPs0rSoArsMVTufzL5ct79dPuNVs4b9jRbOS4iWYk+E ZYN+GKot72zS7js3njW7lVnity6iR1X7TKhPIgdyMVUdT1nR9JgE+qX1vYQMeKy3UqQoW8A0hUVx VXiurWW2W6imSS2ZfUWdWBjKUryDA0pTviqhpms6PqsTy6ZfW9/FG3CSS2lSZVb+UlCwBxVUt9S0 65ubi1trqGe5tCouoI5Fd4i1eIkVSSleJpXFVJdc0VtUOkrqFsdUVebWAmjNwFpXkYq86U9sVePe WrH9EfmgI9RmjSGF5uYlITjKUPBgGpVHryQjptXN3mlx4PS6HSwjizHi2p6rqnnDy5psBmuL6JqA lUiYSMxHYBa/jmqhp5yNAO2nqscRuQ8N/MbzzqPmiX6ulbfSojWK2B+0387+J8PDN3pdKMQv+J12 TVmZ8nml9ZJGkk0vwQxis0xBogrQFqV7mnjmeJNkMtcnv35J+QPJVppkWv2l1DrGpzAH6yu6wf5K I26tUfaI+Xvo+0NTkJ4SOGP3ubgkJC73+56xmrch8ffmzPb6/wCfNY1O3CtBJMIopFIZXW3jWAOp HUP6fIfPOp0cTDEAWI1AGya/84/eUJLj8w7bUfR5W2nRyTSsagAlSqEEd+bLt8/DKe0swGOupcqO S4E9+z1T/nJnypca3+WNzqVhVdX8tSprFjKn21+r/wB7T5RFn+ajOccdi35wfmDP5v8Ayg8p6XoZ C6t+ZE1raJGhJEahkN2CRvxjm4xv/kk4qiP+ci9FstD/AC68haNYrws9O8xaVa269+ENtOi196Df FWM/m1FoGm/n0dY/NXTbnUPIU9jFb+X7lVlktLacLGZPVSIgseYlJXc/EDxPZVH/AJo6X5K07yl+ WMXkpo38ty+bLWeyMMrTR/vXd3Cu5ZtnJ2JqOmKvRv8AnJH/AMkl5p/4wQ/9RUWKsW86S/lMPy08 gr+Yt1M1qlhayWOi27Sl7yX6rEvxRwfvGVOX8yip3PYqvPtJ1HylYfnp5Gv/ACH5c1byrZ6o89jq KX9s9pa3sZRSDArSPz48wX6AHg1K74q9K/K3/wBaC/Nf/t2f8mTirIPze/KGTznLpmvaHqR0Tzlo Lc9J1OnKMivL05loTx5dDQ0qdmBpiqQeRfzU1zUfMdx+VX5p6RHY+ZLq1kWC4gP+iajbtGwfjxPw s6K5qpoaMKIw44qw38uvyg/Le+/Or8wdGutEil0zQ209tKtjJMBAZIy7kEOGNWFfiJxVmP5D/wDk x/zd/wC24n/Ep8VU7idIP+csJZ3BKReUmdgOtFuKmlcVSD8k/wAuPL/5m6XqH5kef7X9N6rrl5Ol nBPJJ6Ntawt6axxorKNmBAr0AFO9VW/ys8l2Hk3/AJyf8w6JpskjaVH5dabT4JXaQwRTXVq/ohmJ JVHLcfbrU74qxPRPOeq+Uv8AnH/8wL/SZWt9SuvN13Y29yhIaL147fm6kdG9NW4nsd8Ves6T/wA4 u/lTF5YTTNV0w3+qyxA3+stNKLl7lhV5UblRfj3C0p413qqkH/OOeiRXl/qh155NQ8x/l/f3Pl7T tTd2/wB40LoqFeTA8GeUD/JIH7Ioq9n1Ty15WvL06vq2n2tzcwW7QfWruNJBHBUu4HqVVFPVj379 MVeRaRo9td+XbLSdPgMHlDzj5ymks7BR6UTaPHaS3jRxx/Dxt7mTT2fgKAo/Sh3VZZr3lvQ9O/MT y9HY2UVraeZLLUdH1m1t1EEc8EcAnhLiPj8UfB1VhQgOd8VQWjW+leTtd/MmTQ9Pt7G10vTLC7ht LeNYo+cVrcybqoFSxXc9TiqC1ryZpWlfkd+mLS2iPmPSdOTzCuslV+tPqECC9mnaY/GTK6sG33U8 em2Ks388/l/YeZ4knWT6pqsApb3YFQQDUJIvda9+o/DMvTas4tucXE1WkjlHdJ5tP+WvniORoW05 bnjsLiCeERv7gSvG4+lc2Y1uI9a+BdLLs3NE7C/ii9L/ACb168dW1F49Ph/bWoll+gISn/DZXk7Q gPp3cnD2fkP1bPSNO8g+VbHRLjRkskmtLyMx3pm+KSYEUPNtvmONKHpmtnqZylxXuHb48EYigHim vflV588k3cl35SE+o2HImKWzYrdIDtxkhXdzvTlHWvgvTNvi1uLKKnsfPk0S029hIr783vzUa2m0 i+E0YdfRlR7f05wOhUsEVwT0PfLo6LBfEK+baASKJK3y5+Xfn/zJMgi0dtPtW4lry9VoIwjCoZQ4 DuKfyKcGXV44DnZ8mWPT447my9u8leXdV8o6guh2ejLPpMpD3nmRp41lkZYCxLQVL09Y8ERdlWpJ JJJ0OfOckrLfKds5uLeC5t5bedBLBMjRyxsKqyOKMpHgQcpYvnX8nfyM86+X/wAzVuvMUVfKvlVb 2Pyi7TRSiQ3czUk9NHZ0PpyMzc1HxUpirP8A8/8AyZ5l816B5dtNAs/rtxYeYLO/u09SKLhbQxzL JJWV4waGRdhv7Yqs87+bPzRsta1bRofy7TzX5au1RNNuUu4IldXgX1YruGUSberz+IhRSgoeuKvO oP8AnHvzzbfkVa6LA8KecbHWh5isbL1VaOJwgiFqszHhXiOda8ee1afFiqO/MC6/5yB/MjyLeeWo vIyaCXSNtTmmvoGN00cisIbRWKBAzKHLO5HEFa16qq/nHyH+ZGj61+XXnbQdEj1288r6RFp2p6E0 0aSLIIDGzI5LK394wqlaEA0IxVu+8v8A50ecvzS8kebtY8uR6NoOi3U3+40XcE09tGwTlcTtyTmZ iAAsakqE3G9SqzLyD5M8y6V+cX5g+Yb+z9HR9c+o/ou69SJvV9CIrJ8CO0icT/OoxVF/mJ5h/N7Q tdtLryl5bg8zeXntqX1p66W11HcCRviR3O6shG3Bvo7qsR0Pyn+ZHnn819F8+eb9Bh8qaX5bhkSw 036wl1dTyyBgC8kYACKXruB02BqTiqy40b81fJn5z+ZvMPl/yuvmbRfNiWtJVu4bQ27wIIz6nqVP wnkaUoRTcGoCqy40T80fy6/NTzN5h8s+Wx5q8s+bmhuLi3huIraeC5So35g7c5XOykEEVIIxVf5G 8n/mve/nfceefOekQWOm3+jyWkdvDcQzragyL6dq9G5u/FS7uF41br2CqB8maZ+cP5QSaj5X0vyo fOXlWW5kudDvILuK1li9XrFN6gcj7Ir8NAakFq0CqZfll5H/ADUg/O/WPPHnKyggg1fRmgVrWaKS KCUz25itFUOZWKRQfE/DiWrv4qoHyz+Rmv6n+UvnPyh5hhGk3+ra/dappEzSRzKBxgMErei8lFdo mVgfiA7dMVTDTPPP/ORWmaNHoN1+Xi6nr1tEIIdcXUIEs5uACieRCRudmK81rvsvTFWX/kt+W955 G8rTwardLfeYNYu5NS1q6T7BuJgKomy1Vadabkk7dMVUfzCg80axrcOjzeXNQ1HyXEiT3w06fT0b UJqmltOLq7tHS3SgLqAfUOxooIZVF+Z7TzHr+hadqenaHcabrPl3VIdQsdIv5bNWuUijaGVFktZ7 qFPUguZUTm4o43AXfFVtsvmLX/Ntn5jvNCutL0zy9Z3P1DT7l7b67d312qqxVY5pIUSOJGRS8i8m c9FFSqldlB5kvfNHmhtS8n6rbaR5pt7Kw9Zp9IYwRxxSwzyTLHfu3ECav7sO1Adq7FVDyWHnzV/I 9v8Al3qGhTQTGOHS9V8xGW2axksISqS3EIEpuGkuIFosZjHFm3NBUqv/2Q== + + + + + + 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 000000000..cd87f71ec 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 000000000..9edccb47f Binary files /dev/null and b/xmlsecurity/qa/unit/pdfsigning/data/forcepoint16.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 000000000..8e5b21511 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 000000000..987169eee 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 000000000..f28566442 Binary files /dev/null and b/xmlsecurity/qa/unit/pdfsigning/data/good.pdf differ diff --git a/xmlsecurity/qa/unit/pdfsigning/data/key3.db b/xmlsecurity/qa/unit/pdfsigning/data/key3.db new file mode 100644 index 000000000..8ab32c28d Binary files /dev/null and b/xmlsecurity/qa/unit/pdfsigning/data/key3.db 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 000000000..ac152793c --- /dev/null +++ b/xmlsecurity/qa/unit/pdfsigning/data/name-bracket.pdf @@ -0,0 +1,2241 @@ +%PDF-1.7 +%öäüß +1 0 obj +<< +/Metadata 2 0 R +/Outlines 3 0 R +/OutputIntents [4 0 R] +/PageLabels 5 0 R +/Pages 6 0 R +/Type /Catalog +/Extensions << +/ESIC << +/BaseVersion /1.7 +/ExtensionLevel 2 +>> +/LTUd << +/BaseVersion /1.7 +/ExtensionLevel 1 +>> +>> +>> +endobj +7 0 obj +<< +/Author (Petras) +/CreationDate (D:20120616164408+03'00') +/Creator (PScript5.dll Version 5.2.2) +/ModDate (D:20120616164534+03'00') +/Producer (Acrobat Distiller 10.1.3 \(Windows\)) +/Title (Untitled - Notepad) +>> +endobj +2 0 obj +<< +/Type /Metadata +/Subtype /XML +/Length 8 0 R +>> +stream + + + + + + + + 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 000000000..9ae7e23bb 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 000000000..5d552421a 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 000000000..d870f896c 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 000000000..211a111cb 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 000000000..890f56217 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 000000000..58aadb492 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 000000000..5270151eb 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 000000000..ac1c5f37b 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 000000000..60675454f 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 000000000..db063f366 --- /dev/null +++ b/xmlsecurity/qa/unit/pdfsigning/data/tdf107149.pdf @@ -0,0 +1,97 @@ +%PDF-1.2 +%âãÏÓ +3 0 obj +<< +/Length 61 +>> +stream + BT + /F1 24 Tf + 1 0 0 1 260 254 Tm + (Hello Worl2)Tj + ET + +endstream +endobj xref +0 7 +0000000000 65535 f +0000000312 00000 n +0000000532 00000 n +0000000015 00000 n +0000000660 00000 n +0000000578 00000 n +0000000743 00000 n +trailer + +<< +/Root 6 0 R +/Size 7 +>> +1 0 obj +<< +/Resources 2 0 R +/Contents 3 0 R +/Parent 4 0 R +/Type /Page +/MediaBox [0 0 612 446] +>> +endobj +3 0 obj +<< +/Length 61 +>> +stream + BT + /F1 24 Tf + 1 0 0 1 260 254 Tm + (Hello World)Tj + ET + +endstream +endobj +2 0 obj +<< +/Font +<< +/F1 5 0 R +>> +>> +endobj +5 0 obj +<< +/Subtype /Type1 +/Name /F1 +/Type /Font +/BaseFont /Helvetica +>> +endobj +4 0 obj +<< +/Kids [1 0 R] +/Type /Pages +/MediaBox [0 0 612 446] +/Count 1 +>> +endobj +6 0 obj +<< +/Type /Catalog +/Pages 4 0 R +>> +endobj xref +0 7 +0000000000 65535 f +0000000015 00000 n +0000000235 00000 n +0000000121 00000 n +0000000363 00000 n +0000000281 00000 n +0000000446 00000 n +trailer + +<< +/Size 7 +>> +startxref +128 +%%EOF diff --git a/xmlsecurity/qa/unit/pdfsigning/data/tdf107782.pdf b/xmlsecurity/qa/unit/pdfsigning/data/tdf107782.pdf new file mode 100644 index 000000000..086e18eed 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 000000000..a736e5bb9 Binary files /dev/null and b/xmlsecurity/qa/unit/pdfsigning/data/tdf114460.pdf differ diff --git a/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx b/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx new file mode 100644 index 000000000..7659fe948 --- /dev/null +++ b/xmlsecurity/qa/unit/pdfsigning/pdfsigning.cxx @@ -0,0 +1,539 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.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 + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#endif + +using namespace com::sun::star; + +namespace +{ +char const DATA_DIRECTORY[] = "/xmlsecurity/qa/unit/pdfsigning/data/"; +} + +/// Testsuite for the PDF signing feature. +class PDFSigningTest : public test::BootstrapFixture +{ +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, + const OString& rExpectedSubFilter); + +public: + PDFSigningTest(); + void setUp() override; +}; + +PDFSigningTest::PDFSigningTest() {} + +void PDFSigningTest::setUp() +{ + test::BootstrapFixture::setUp(); + +#ifndef _WIN32 + // Set up cert8.db and key3.db in workdir/CppunitTest/ + OUString aSourceDir = m_directories.getURLFromSrc(DATA_DIRECTORY); + OUString aTargetDir + = m_directories.getURLFromWorkdir("/CppunitTest/xmlsecurity_pdfsigning.test.user/"); + osl::File::copy(aSourceDir + "cert8.db", aTargetDir + "cert8.db"); + osl::File::copy(aSourceDir + "key3.db", aTargetDir + "key3.db"); + OUString aTargetPath; + osl::FileBase::getSystemPathFromFileURL(aTargetDir, aTargetPath); + setenv("MOZILLA_CERTIFICATE_FOLDER", aTargetPath.toUtf8().getStr(), 1); +#endif +} + +std::vector PDFSigningTest::verify(const OUString& rURL, size_t nCount, + const OString& rExpectedSubFilter) +{ + uno::Reference xSEInitializer + = xml::crypto::SEInitializer::create(mxComponentContext); + uno::Reference xSecurityContext + = xSEInitializer->createSecurityContext(OUString()); + std::vector aRet; + + SvFileStream aStream(rURL, StreamMode::READ); + vcl::filter::PDFDocument aVerifyDocument; + CPPUNIT_ASSERT(aVerifyDocument.Read(aStream)); + std::vector aSignatures = aVerifyDocument.GetSignatureWidgets(); + CPPUNIT_ASSERT_EQUAL(nCount, aSignatures.size()); + for (size_t i = 0; i < aSignatures.size(); ++i) + { + SignatureInformation aInfo(i); + int nMDPPerm = aVerifyDocument.GetMDPPerm(); + xmlsecurity::pdfio::ValidateSignature(aStream, aSignatures[i], aInfo, aVerifyDocument, + nMDPPerm); + aRet.push_back(aInfo); + + if (!rExpectedSubFilter.isEmpty()) + { + vcl::filter::PDFObjectElement* pValue = aSignatures[i]->LookupObject("V"); + CPPUNIT_ASSERT(pValue); + auto pSubFilter + = dynamic_cast(pValue->Lookup("SubFilter")); + CPPUNIT_ASSERT(pSubFilter); + CPPUNIT_ASSERT_EQUAL(rExpectedSubFilter, pSubFilter->GetValue()); + } + } + + 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 : 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.pdfio.test", + "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.pdfio.test", + "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, /*rExpectedSubFilter=*/OString()); + + // 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) +{ + OUString aSourceDir = m_directories.getURLFromSrc(DATA_DIRECTORY); + OUString aInURL = aSourceDir + "no.pdf"; + OUString aTargetDir + = m_directories.getURLFromWorkdir("/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, "ETSI.CAdES.detached"); + // 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("/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) +{ + // 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); + CPPUNIT_ASSERT(aDocument.Read(aStream)); + std::vector aSignatures = aDocument.GetSignatureWidgets(); + CPPUNIT_ASSERT_EQUAL(static_cast(1), aSignatures.size()); + SignatureInformation aInfo(0); + int nMDPPerm = aDocument.GetMDPPerm(); + CPPUNIT_ASSERT(xmlsecurity::pdfio::ValidateSignature(aStream, aSignatures[0], aInfo, + aDocument, nMDPPerm)); + } + + // Remove the signature and write out the result as remove.pdf. + OUString aTargetDir + = m_directories.getURLFromWorkdir("/CppunitTest/xmlsecurity_pdfsigning.test.user/"); + OUString aOutURL = aTargetDir + "remove.pdf"; + { + CPPUNIT_ASSERT(aDocument.RemoveSignature(0)); + SvFileStream aOutStream(aOutURL, StreamMode::WRITE | StreamMode::TRUNC); + CPPUNIT_ASSERT(aDocument.Write(aOutStream)); + } + + // 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, /*rExpectedSubFilter=*/OString()); +} + +/// Test removing all signatures from a previously multi-signed file. +CPPUNIT_TEST_FIXTURE(PDFSigningTest, testPDFRemoveAll) +{ + // 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("/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) +{ + // 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, + /*rExpectedSubFilter=*/OString()); + // 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, + /*rExpectedSubFilter=*/OString()); +} + +/// 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("/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, + /*rExpectedSubFilter=*/OString()); +} + +/// Test a PAdES document, signed by LO on Linux. +CPPUNIT_TEST_FIXTURE(PDFSigningTest, testPDFPAdESGood) +{ + verify(m_directories.getURLFromSrc(DATA_DIRECTORY) + "good-pades.pdf", 1, + "ETSI.CAdES.detached"); +} + +/// Test a valid signature that does not cover the whole file. +CPPUNIT_TEST_FIXTURE(PDFSigningTest, testPartial) +{ + std::vector aInfos + = verify(m_directories.getURLFromSrc(DATA_DIRECTORY) + "partial.pdf", 1, + /*rExpectedSubFilter=*/OString()); + CPPUNIT_ASSERT(!aInfos.empty()); + SignatureInformation& rInformation = aInfos[0]; + CPPUNIT_ASSERT(rInformation.bPartialDocumentSignature); +} + +CPPUNIT_TEST_FIXTURE(PDFSigningTest, testPartialInBetween) +{ + std::vector aInfos + = verify(m_directories.getURLFromSrc(DATA_DIRECTORY) + "partial-in-between.pdf", 2, + /*rExpectedSubFilter=*/OString()); + 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::vector aInfos + = verify(m_directories.getURLFromSrc(DATA_DIRECTORY) + "bad-cert-p1.pdf", 1, + /*rExpectedSubFilter=*/OString()); + 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::vector aInfos + = verify(m_directories.getURLFromSrc(DATA_DIRECTORY) + "bad-cert-p3-stamp.pdf", 1, + /*rExpectedSubFilter=*/OString()); + 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) +{ + // Create a new signature. + OUString aSourceDir = m_directories.getURLFromSrc(DATA_DIRECTORY); + OUString aInURL = aSourceDir + "no.pdf"; + OUString aTargetDir + = m_directories.getURLFromWorkdir("/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, "ETSI.CAdES.detached"); + 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) +{ + const std::initializer_list aNames = { + // We failed to determine if this is good or bad. + "good-non-detached.pdf", + // Boolean value for dictionary key caused read error. + "dict-bool.pdf", + }; + + for (const auto& rName : aNames) + { + std::vector aInfos + = verify(m_directories.getURLFromSrc(DATA_DIRECTORY) + rName, 1, + /*rExpectedSubFilter=*/OString()); + 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. + "no-eof.pdf", + // ']' in a name token was mishandled. + "name-bracket.pdf", + // %%EOF at the end wasn't followed by a newline. + "noeol.pdf", + // File that's intentionally smaller than 1024 bytes. + "small.pdf", + "tdf107149.pdf", + // Nested parentheses were not handled. + "tdf114460.pdf", + // Valgrind was unhappy about this. + "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 (OUString(rName) == "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) +{ + // 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_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/qa/unit/signing/data/bad.docx b/xmlsecurity/qa/unit/signing/data/bad.docx new file mode 100644 index 000000000..86d0eda49 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 000000000..75c39d5d8 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 000000000..f3f056f2b 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 000000000..032ddbf7a 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 000000000..252ea26b0 Binary files /dev/null and b/xmlsecurity/qa/unit/signing/data/badStreamGPG.odt differ diff --git a/xmlsecurity/qa/unit/signing/data/cert8.db b/xmlsecurity/qa/unit/signing/data/cert8.db new file mode 100644 index 000000000..95e58ffe5 Binary files /dev/null and b/xmlsecurity/qa/unit/signing/data/cert8.db differ diff --git a/xmlsecurity/qa/unit/signing/data/encryptedGPG.odt b/xmlsecurity/qa/unit/signing/data/encryptedGPG.odt new file mode 100644 index 000000000..9490a0ce5 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 000000000..e738c2f6d 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 000000000..4f96d4bd8 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 000000000..8c6019d0a 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 000000000..4a506c1e1 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 000000000..a02af3016 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 000000000..f2b1a7109 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/key3.db b/xmlsecurity/qa/unit/signing/data/key3.db new file mode 100644 index 000000000..f449e60a6 Binary files /dev/null and b/xmlsecurity/qa/unit/signing/data/key3.db differ diff --git a/xmlsecurity/qa/unit/signing/data/multi.docx b/xmlsecurity/qa/unit/signing/data/multi.docx new file mode 100644 index 000000000..aba69508e 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 000000000..22cf7683a 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 000000000..5d552421a 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 000000000..4f96d4bd8 Binary files /dev/null and b/xmlsecurity/qa/unit/signing/data/notype-xades.odt differ diff --git a/xmlsecurity/qa/unit/signing/data/partial.docx b/xmlsecurity/qa/unit/signing/data/partial.docx new file mode 100644 index 000000000..3d6ca4685 Binary files /dev/null and b/xmlsecurity/qa/unit/signing/data/partial.docx differ diff --git a/xmlsecurity/qa/unit/signing/data/pubring.gpg b/xmlsecurity/qa/unit/signing/data/pubring.gpg new file mode 100644 index 000000000..007ea98af Binary files /dev/null and b/xmlsecurity/qa/unit/signing/data/pubring.gpg differ diff --git a/xmlsecurity/qa/unit/signing/data/random_seed b/xmlsecurity/qa/unit/signing/data/random_seed new file mode 100644 index 000000000..8e68109a8 --- /dev/null +++ b/xmlsecurity/qa/unit/signing/data/random_seed @@ -0,0 +1,2 @@ +°Á,A? ´ p£Ôj`\ÚGkV¿feTâ*ì;¼^hÌFÖ™¾3µ}‡²´iõÅsAØr¾‘9©B´h¡oWF€æÀ! !‹7(â;9µ±xÚ*L¯zY„¡8=ë#ç6æñÇï3ˆY&](^“浊4änZ?ålÿ.÷®ÔÓïØ‹}Öµ]¡5w6!Ç?ç¼l†ãÁ'%k©.^,IfÏVîVÏÓ ¥'_R!QºéUݪiDöUZ" ¦ö°­Z°$R^Mf“Øç— àï )_~»‰ñûw‡oʇÃ6–c©3ž/ CÌñ÷Åù*‰EÅ;BzQ"MÛúÖ¶QCú-é× Òí¾¼'…Ý•y ³$…ë_ ӛϟ!^s2zht¯LÇNÖ;¼©Íè¶\ûÁÅ«çÌ 0m冑øöG¼÷9õ‘M_­®“'ÕÆm‡(K·HÏ|‚ñôôŠ®ÌézšŸU ;0žAz|ñ½°§8‘òX‡=aÙHºX>cÂ4&›Å6¢ãÜkñÓ/TìCä–Æýš¿sÈÀÊ_‘O`ä %M–{UDš çù¸– “{Ô;[cV9Ä]!ýf@—û(p˜^ÝÐ[ÿî‡híÌáyòöséTäëotf(«Ž"™Î(×qN²©—c¤r ÚÓ½aµÔÐÜŸµ ‡Û›§õ·³*³?Œ>õYC6Å“øaŽ%'Ë]Ìi=g¯lR +/R°?uÿâñ âê7[ÄF (È \ No newline at end of file diff --git a/xmlsecurity/qa/unit/signing/data/secring.gpg b/xmlsecurity/qa/unit/signing/data/secring.gpg new file mode 100644 index 000000000..f7626df5a Binary files /dev/null and b/xmlsecurity/qa/unit/signing/data/secring.gpg differ diff --git a/xmlsecurity/qa/unit/signing/data/signatureline.docx b/xmlsecurity/qa/unit/signing/data/signatureline.docx new file mode 100644 index 000000000..e1dae6698 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 000000000..d3a3e4671 Binary files /dev/null and b/xmlsecurity/qa/unit/signing/data/signatureline.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 000000000..95162a627 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 000000000..ecff48709 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 000000000..58d1b2c77 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 000000000..f0356513c Binary files /dev/null and b/xmlsecurity/qa/unit/signing/data/tdf96097.odt differ diff --git a/xmlsecurity/qa/unit/signing/data/trustdb.gpg b/xmlsecurity/qa/unit/signing/data/trustdb.gpg new file mode 100644 index 000000000..1966b5374 Binary files /dev/null and b/xmlsecurity/qa/unit/signing/data/trustdb.gpg differ diff --git a/xmlsecurity/qa/unit/signing/data/untrustedGoodGPG.odt b/xmlsecurity/qa/unit/signing/data/untrustedGoodGPG.odt new file mode 100644 index 000000000..e1b36d544 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 000000000..8b90f862f --- /dev/null +++ b/xmlsecurity/qa/unit/signing/signing.cxx @@ -0,0 +1,1376 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.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 +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace com::sun::star; + +namespace +{ +char const DATA_DIRECTORY[] = "/xmlsecurity/qa/unit/signing/data/"; +} + +/// Testsuite for the document signing feature. +class SigningTest : public test::BootstrapFixture, public unotest::MacrosTest, public XmlTestTools +{ +protected: + uno::Reference mxComponent; + uno::Reference mxSEInitializer; + uno::Reference mxSecurityContext; + +#if HAVE_GPGCONF_SOCKETDIR + OString m_gpgconfCommandPrefix; +#endif + +public: + SigningTest(); + virtual void setUp() override; + virtual void tearDown() override; + void registerNamespaces(xmlXPathContextPtr& pXmlXpathCtx) override; + +protected: + void createDoc(const OUString& rURL); + void createCalc(const OUString& rURL); + uno::Reference + getCertificate(DocumentSignatureManager& rSignatureManager, + svl::crypto::SignatureMethodAlgorithm eAlgo); +#if HAVE_FEATURE_GPGVERIFY + SfxObjectShell* assertDocument(const ::CppUnit::SourceLine aSrcLine, + const OUString& rFilterName, const SignatureState nDocSign, + const SignatureState nMacroSign, const OUString& sVersion); +#endif +}; + +SigningTest::SigningTest() {} + +void SigningTest::setUp() +{ + test::BootstrapFixture::setUp(); + + OUString aSourceDir = m_directories.getURLFromSrc(DATA_DIRECTORY); + OUString aTargetDir + = m_directories.getURLFromWorkdir("CppunitTest/xmlsecurity_signing.test.user"); + + // Set up cert8.db in workdir/CppunitTest/ + osl::File::copy(aSourceDir + "cert8.db", aTargetDir + "/cert8.db"); + osl::File::copy(aSourceDir + "key3.db", aTargetDir + "/key3.db"); + + // Make gpg use our own defined setup & keys + osl::File::copy(aSourceDir + "pubring.gpg", aTargetDir + "/pubring.gpg"); + osl::File::copy(aSourceDir + "random_seed", aTargetDir + "/random_seed"); + osl::File::copy(aSourceDir + "secring.gpg", aTargetDir + "/secring.gpg"); + osl::File::copy(aSourceDir + "trustdb.gpg", aTargetDir + "/trustdb.gpg"); + + OUString aTargetPath; + osl::FileBase::getSystemPathFromFileURL(aTargetDir, aTargetPath); + + OUString mozCertVar("MOZILLA_CERTIFICATE_FOLDER"); + osl_setEnvironment(mozCertVar.pData, aTargetPath.pData); + OUString gpgHomeVar("GNUPGHOME"); + osl_setEnvironment(gpgHomeVar.pData, aTargetPath.pData); + +#if HAVE_GPGCONF_SOCKETDIR + auto const ldPath = std::getenv("LIBO_LD_PATH"); + m_gpgconfCommandPrefix + = ldPath == nullptr ? OString() : OStringLiteral("LD_LIBRARY_PATH=") + ldPath + " "; + OString path; + bool ok = aTargetPath.convertToString(&path, osl_getThreadTextEncoding(), + RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR + | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR); + // if conversion fails, at least provide a best-effort conversion in the message here, for + // context + CPPUNIT_ASSERT_MESSAGE(OUStringToOString(aTargetPath, RTL_TEXTENCODING_UTF8).getStr(), ok); + m_gpgconfCommandPrefix += "GNUPGHOME=" + path + " " GPGME_GPGCONF; + // HAVE_GPGCONF_SOCKETDIR is only defined in configure.ac for Linux for now, so (a) std::system + // behavior will conform to POSIX (and the relevant env var to set is named LD_LIBRARY_PATH), and + // (b) gpgconf --create-socketdir should return zero: + OString cmd = m_gpgconfCommandPrefix + " --create-socketdir"; + int res = std::system(cmd.getStr()); + CPPUNIT_ASSERT_EQUAL_MESSAGE(cmd.getStr(), 0, res); +#endif + + // Initialize crypto after setting up the environment variables. + mxDesktop.set(frame::Desktop::create(mxComponentContext)); + mxSEInitializer = xml::crypto::SEInitializer::create(mxComponentContext); + mxSecurityContext = mxSEInitializer->createSecurityContext(OUString()); +} + +void SigningTest::tearDown() +{ + if (mxComponent.is()) + mxComponent->dispose(); + +#if HAVE_GPGCONF_SOCKETDIR + // HAVE_GPGCONF_SOCKETDIR is only defined in configure.ac for Linux for now, so (a) std::system + // behavior will conform to POSIX, and (b) gpgconf --remove-socketdir should return zero: + OString cmd = m_gpgconfCommandPrefix + " --remove-socketdir"; + int res = std::system(cmd.getStr()); + CPPUNIT_ASSERT_EQUAL_MESSAGE(cmd.getStr(), 0, res); +#endif + + test::BootstrapFixture::tearDown(); +} + +void SigningTest::createDoc(const OUString& rURL) +{ + if (mxComponent.is()) + mxComponent->dispose(); + if (rURL.isEmpty()) + mxComponent = loadFromDesktop("private:factory/swriter", "com.sun.star.text.TextDocument"); + else + mxComponent = loadFromDesktop(rURL, "com.sun.star.text.TextDocument"); +} + +void SigningTest::createCalc(const OUString& rURL) +{ + if (mxComponent.is()) + mxComponent->dispose(); + if (rURL.isEmpty()) + mxComponent + = loadFromDesktop("private:factory/swriter", "com.sun.star.sheet.SpreadsheetDocument"); + else + mxComponent = loadFromDesktop(rURL, "com.sun.star.sheet.SpreadsheetDocument"); +} + +uno::Reference +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) + 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. + createDoc(""); + + utl::TempFile aTempFile; + aTempFile.EnableKillingFile(); + uno::Reference xStorable(mxComponent, uno::UNO_QUERY); + utl::MediaDescriptor aMediaDescriptor; + aMediaDescriptor["FilterName"] <<= OUString("writer8"); + xStorable->storeAsURL(aTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList()); + + DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content); + CPPUNIT_ASSERT(aManager.init()); + uno::Reference xStorage + = comphelper::OStorageHelper::GetStorageOfFormatFromURL( + ZIP_STORAGE_FORMAT_STRING, aTempFile.GetURL(), embed::ElementModes::READWRITE); + CPPUNIT_ASSERT(xStorage.is()); + aManager.setStore(xStorage); + aManager.getSignatureHelper().SetStorage(xStorage, "1.2"); + + // Then add a signature document. + uno::Reference 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. + createDoc(""); + + utl::TempFile aTempFile; + aTempFile.EnableKillingFile(); + uno::Reference xStorable(mxComponent, uno::UNO_QUERY); + utl::MediaDescriptor aMediaDescriptor; + aMediaDescriptor["FilterName"] <<= OUString("writer8"); + xStorable->storeAsURL(aTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList()); + + DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content); + CPPUNIT_ASSERT(aManager.init()); + uno::Reference xStorage + = comphelper::OStorageHelper::GetStorageOfFormatFromURL( + ZIP_STORAGE_FORMAT_STRING, aTempFile.GetURL(), embed::ElementModes::READWRITE); + CPPUNIT_ASSERT(xStorage.is()); + aManager.setStore(xStorage); + aManager.getSignatureHelper().SetStorage(xStorage, "1.2"); + + // Then add a signature. + uno::Reference xCertificate + = getCertificate(aManager, svl::crypto::SignatureMethodAlgorithm::ECDSA); + if (!xCertificate.is()) + return; + OUString aDescription; + sal_Int32 nSecurityId; + aManager.add(xCertificate, mxSecurityContext, aDescription, 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. + createDoc(""); + + utl::TempFile aTempFile; + aTempFile.EnableKillingFile(); + uno::Reference xStorable(mxComponent, uno::UNO_QUERY); + utl::MediaDescriptor aMediaDescriptor; + aMediaDescriptor["FilterName"] <<= OUString("MS Word 2007 XML"); + xStorable->storeAsURL(aTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList()); + + DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content); + CPPUNIT_ASSERT(aManager.init()); + uno::Reference xStorage + = comphelper::OStorageHelper::GetStorageOfFormatFromURL( + ZIP_STORAGE_FORMAT_STRING, aTempFile.GetURL(), embed::ElementModes::READWRITE); + CPPUNIT_ASSERT(xStorage.is()); + aManager.setStore(xStorage); + aManager.getSignatureHelper().SetStorage(xStorage, "1.2"); + + // Then add a document signature. + uno::Reference xCertificate + = getCertificate(aManager, svl::crypto::SignatureMethodAlgorithm::ECDSA); + if (!xCertificate.is()) + return; + OUString aDescription; + sal_Int32 nSecurityId; + aManager.add(xCertificate, mxSecurityContext, aDescription, 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. + createDoc(""); + + utl::TempFile aTempFile; + aTempFile.EnableKillingFile(); + uno::Reference xStorable(mxComponent, uno::UNO_QUERY); + utl::MediaDescriptor aMediaDescriptor; + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + xStorable->storeToURL(aTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList()); + + DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content); + CPPUNIT_ASSERT(aManager.init()); + std::unique_ptr pStream(utl::UcbStreamHelper::CreateStream( + aTempFile.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; + OUString aDescription; + sal_Int32 nSecurityId; + aManager.add(xCertificate, mxSecurityContext, aDescription, nSecurityId, + /*bAdESCompliant=*/true); + + // Read back the signature and make sure that it's valid. + aManager.read(/*bUseTempStream=*/false); + 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, testOOXMLDescription) +{ + // Create an empty document and store it to a tempfile, finally load it as a storage. + createDoc(""); + + utl::TempFile aTempFile; + aTempFile.EnableKillingFile(); + uno::Reference xStorable(mxComponent, uno::UNO_QUERY); + utl::MediaDescriptor aMediaDescriptor; + aMediaDescriptor["FilterName"] <<= OUString("MS Word 2007 XML"); + xStorable->storeAsURL(aTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList()); + + DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content); + CPPUNIT_ASSERT(aManager.init()); + uno::Reference xStorage + = comphelper::OStorageHelper::GetStorageOfFormatFromURL( + ZIP_STORAGE_FORMAT_STRING, aTempFile.GetURL(), embed::ElementModes::READWRITE); + CPPUNIT_ASSERT(xStorage.is()); + aManager.setStore(xStorage); + aManager.getSignatureHelper().SetStorage(xStorage, "1.2"); + + // Then add a document signature. + uno::Reference 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. + utl::TempFile aTempFile; + aTempFile.EnableKillingFile(); + OUString aURL = aTempFile.GetURL(); + CPPUNIT_ASSERT_EQUAL( + osl::File::RC::E_None, + osl::File::copy(m_directories.getURLFromSrc(DATA_DIRECTORY) + "partial.docx", aURL)); + // Load the test document as a storage and read its single signature. + DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content); + CPPUNIT_ASSERT(aManager.init()); + uno::Reference xStorage + = comphelper::OStorageHelper::GetStorageOfFormatFromURL(ZIP_STORAGE_FORMAT_STRING, aURL, + embed::ElementModes::READWRITE); + CPPUNIT_ASSERT(xStorage.is()); + aManager.setStore(xStorage); + aManager.getSignatureHelper().SetStorage(xStorage, "1.2"); + aManager.read(/*bUseTempStream=*/false); + std::vector& 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()); + utl::TempFile aTempFile; + aTempFile.EnableKillingFile(); + OUString aURL = aTempFile.GetURL(); + CPPUNIT_ASSERT_EQUAL( + osl::File::RC::E_None, + osl::File::copy(m_directories.getURLFromSrc(DATA_DIRECTORY) + "multi.docx", aURL)); + uno::Reference xStorage + = comphelper::OStorageHelper::GetStorageOfFormatFromURL(ZIP_STORAGE_FORMAT_STRING, aURL, + embed::ElementModes::READWRITE); + CPPUNIT_ASSERT(xStorage.is()); + aManager.setStore(xStorage); + aManager.getSignatureHelper().SetStorage(xStorage, "1.2"); + aManager.read(/*bUseTempStream=*/false); + std::vector& 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. + utl::TempFile aTempFile; + aTempFile.EnableKillingFile(); + OUString aURL = aTempFile.GetURL(); + CPPUNIT_ASSERT_EQUAL( + osl::File::RC::E_None, + osl::File::copy(m_directories.getURLFromSrc(DATA_DIRECTORY) + "partial.docx", aURL)); + // Load the test document as a storage and read its single signature. + DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content); + CPPUNIT_ASSERT(aManager.init()); + uno::Reference xStorage + = comphelper::OStorageHelper::GetStorageOfFormatFromURL(ZIP_STORAGE_FORMAT_STRING, aURL, + embed::ElementModes::READWRITE); + CPPUNIT_ASSERT(xStorage.is()); + aManager.setStore(xStorage); + aManager.getSignatureHelper().SetStorage(xStorage, "1.2"); + aManager.read(/*bUseTempStream=*/false); + std::vector& 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); + 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) +{ + createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "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::underlyingEnumValue(nActual)).getStr()), + (nActual == SignatureState::NOTVALIDATED || nActual == SignatureState::OK)); +} + +/// Test a typical broken ODF signature where one stream is corrupted. +CPPUNIT_TEST_FIXTURE(SigningTest, testODFBroken) +{ + createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "bad.odt"); + SfxBaseModel* pBaseModel = dynamic_cast(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) +{ + createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "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())); +} + +/// Test a typical OOXML where a number of (but not all) streams are signed. +CPPUNIT_TEST_FIXTURE(SigningTest, testOOXMLPartial) +{ + createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "partial.docx"); + SfxBaseModel* pBaseModel = dynamic_cast(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::underlyingEnumValue(nActual)).getStr()), + (nActual == SignatureState::NOTVALIDATED_PARTIAL_OK + || nActual == SignatureState::PARTIAL_OK)); +} + +/// Test a typical broken OOXML signature where one stream is corrupted. +CPPUNIT_TEST_FIXTURE(SigningTest, testOOXMLBroken) +{ + createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "bad.docx"); + SfxBaseModel* pBaseModel = dynamic_cast(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) +{ + createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "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(); + CPPUNIT_ASSERT_MESSAGE( + (OString::number(o3tl::underlyingEnumValue(nActual)).getStr()), + (nActual == SignatureState::NOTVALIDATED || nActual == SignatureState::OK)); +} + +/// Test a typical PDF where the signature is bad. +CPPUNIT_TEST_FIXTURE(SigningTest, testPDFBad) +{ + createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "bad.pdf"); + SfxBaseModel* pBaseModel = dynamic_cast(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + CPPUNIT_ASSERT_EQUAL(static_cast(SignatureState::BROKEN), + static_cast(pObjectShell->GetDocumentSignatureState())); +} + +CPPUNIT_TEST_FIXTURE(SigningTest, testPDFHideAndReplace) +{ + createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + + "hide-and-replace-shadow-file-signed-2.pdf"); + SfxBaseModel* pBaseModel = dynamic_cast(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + // 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) +{ + createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "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, test96097Calc) +{ + createCalc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "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::underlyingEnumValue(nActual)).getStr()), + (nActual == SignatureState::OK || nActual == SignatureState::NOTVALIDATED + || nActual == SignatureState::INVALID)); + + uno::Reference xDocStorable(mxComponent, uno::UNO_QUERY_THROW); + + // Save a copy + utl::TempFile aTempFileSaveCopy; + aTempFileSaveCopy.EnableKillingFile(); + uno::Sequence descSaveACopy(comphelper::InitPropertySequence( + { { "SaveACopy", uno::Any(true) }, { "FilterName", uno::Any(OUString("calc8")) } })); + xDocStorable->storeToURL(aTempFileSaveCopy.GetURL(), descSaveACopy); + + try + { + // Save As + utl::TempFile aTempFileSaveAs; + aTempFileSaveAs.EnableKillingFile(); + uno::Sequence descSaveAs( + comphelper::InitPropertySequence({ { "FilterName", uno::Any(OUString("calc8")) } })); + xDocStorable->storeAsURL(aTempFileSaveAs.GetURL(), descSaveAs); + } + catch (...) + { + CPPUNIT_FAIL("Fail to save as the document"); + } +} + +CPPUNIT_TEST_FIXTURE(SigningTest, test96097Doc) +{ + createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "tdf96097.odt"); + SfxBaseModel* pBaseModel = dynamic_cast(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + + SignatureState nActual = pObjectShell->GetScriptingSignatureState(); + CPPUNIT_ASSERT_MESSAGE((OString::number(o3tl::underlyingEnumValue(nActual)).getStr()), + (nActual == SignatureState::OK || nActual == SignatureState::NOTVALIDATED + || nActual == SignatureState::INVALID)); + + uno::Reference xDocStorable(mxComponent, uno::UNO_QUERY_THROW); + + // Save a copy + utl::TempFile aTempFileSaveCopy; + aTempFileSaveCopy.EnableKillingFile(); + uno::Sequence descSaveACopy(comphelper::InitPropertySequence( + { { "SaveACopy", uno::Any(true) }, { "FilterName", uno::Any(OUString("writer8")) } })); + xDocStorable->storeToURL(aTempFileSaveCopy.GetURL(), descSaveACopy); + + try + { + // Save As + utl::TempFile aTempFileSaveAs; + aTempFileSaveAs.EnableKillingFile(); + uno::Sequence descSaveAs( + comphelper::InitPropertySequence({ { "FilterName", uno::Any(OUString("writer8")) } })); + xDocStorable->storeAsURL(aTempFileSaveAs.GetURL(), descSaveAs); + } + catch (...) + { + CPPUNIT_FAIL("Fail to save as the document"); + } +} + +CPPUNIT_TEST_FIXTURE(SigningTest, testXAdESNotype) +{ + // Create a working copy. + utl::TempFile aTempFile; + aTempFile.EnableKillingFile(); + OUString aURL = aTempFile.GetURL(); + CPPUNIT_ASSERT_EQUAL( + osl::File::RC::E_None, + osl::File::copy(m_directories.getURLFromSrc(DATA_DIRECTORY) + "notype-xades.odt", aURL)); + + // Read existing signature. + DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content); + CPPUNIT_ASSERT(aManager.init()); + uno::Reference xStorage + = comphelper::OStorageHelper::GetStorageOfFormatFromURL( + ZIP_STORAGE_FORMAT_STRING, aTempFile.GetURL(), embed::ElementModes::READWRITE); + CPPUNIT_ASSERT(xStorage.is()); + aManager.setStore(xStorage); + aManager.getSignatureHelper().SetStorage(xStorage, "1.2"); + aManager.read(/*bUseTempStream=*/false); + + // Create a new signature. + uno::Reference 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[@URI='#idSignedProperties']", + "Type"); + + // New signature always has the Type attribute. + assertXPath(pXmlDoc, + "/odfds:document-signatures/dsig:Signature[2]/dsig:SignedInfo/" + "dsig:Reference[@URI='#idSignedProperties']", + "Type", "http://uri.etsi.org/01903#SignedProperties"); +} + +/// Creates a XAdES signature from scratch. +CPPUNIT_TEST_FIXTURE(SigningTest, testXAdES) +{ + // Create an empty document, store it to a tempfile and load it as a storage. + createDoc(OUString()); + + utl::TempFile aTempFile; + aTempFile.EnableKillingFile(); + uno::Reference xStorable(mxComponent, uno::UNO_QUERY); + utl::MediaDescriptor aMediaDescriptor; + aMediaDescriptor["FilterName"] <<= OUString("writer8"); + xStorable->storeAsURL(aTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList()); + + DocumentSignatureManager aManager(mxComponentContext, DocumentSignatureMode::Content); + CPPUNIT_ASSERT(aManager.init()); + uno::Reference xStorage + = comphelper::OStorageHelper::GetStorageOfFormatFromURL( + ZIP_STORAGE_FORMAT_STRING, aTempFile.GetURL(), embed::ElementModes::READWRITE); + CPPUNIT_ASSERT(xStorage.is()); + aManager.setStore(xStorage); + aManager.getSignatureHelper().SetStorage(xStorage, "1.2"); + + // Create a signature. + uno::Reference 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", + "Algorithm", ALGO_XMLDSIGSHA256); + + // Assert that the digest of the signing certificate is included. + assertXPath(pXmlDoc, "//xd:CertDigest", 1); + + // Assert that the Type attribute on the idSignedProperties reference is + // not missing. + assertXPath(pXmlDoc, + "/odfds:document-signatures/dsig:Signature/dsig:SignedInfo/" + "dsig:Reference[@URI='#idSignedProperties']", + "Type", "http://uri.etsi.org/01903#SignedProperties"); +} + +/// Works with an existing good XAdES signature. +CPPUNIT_TEST_FIXTURE(SigningTest, testXAdESGood) +{ + createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "good-xades.odt"); + SfxBaseModel* pBaseModel = dynamic_cast(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::underlyingEnumValue(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, + m_directories.getURLFromSrc(DATA_DIRECTORY) + "signatureline.docx", + embed::ElementModes::READ); + CPPUNIT_ASSERT(xStorage.is()); + + uno::Sequence xSignatureInfo + = xSignatures->verifyScriptingContentSignatures(xStorage, + uno::Reference()); + + // The signature should have a valid signature, and signature line with two valid images + CPPUNIT_ASSERT(xSignatureInfo[0].SignatureIsValid); + CPPUNIT_ASSERT_EQUAL(OUString("{DEE0514B-13E8-4674-A831-46E3CDB18BB4}"), + xSignatureInfo[0].SignatureLineId); + CPPUNIT_ASSERT(xSignatureInfo[0].ValidSignatureLineImage.is()); + CPPUNIT_ASSERT(xSignatureInfo[0].InvalidSignatureLineImage.is()); +} + +CPPUNIT_TEST_FIXTURE(SigningTest, testSignatureLineODF) +{ + createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "signatureline.odt"); + SfxBaseModel* pBaseModel = dynamic_cast(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + + uno::Sequence xSignatureInfo + = pObjectShell->GetDocumentSignatureInformation(false); + + CPPUNIT_ASSERT(xSignatureInfo[0].SignatureIsValid); + CPPUNIT_ASSERT_EQUAL(OUString("{41CF56EE-331B-4125-97D8-2F5669DD3AAC}"), + xSignatureInfo[0].SignatureLineId); + CPPUNIT_ASSERT(xSignatureInfo[0].ValidSignatureLineImage.is()); + CPPUNIT_ASSERT(xSignatureInfo[0].InvalidSignatureLineImage.is()); +} + +#if HAVE_FEATURE_GPGVERIFY +/// Test a typical ODF where all streams are GPG-signed. +CPPUNIT_TEST_FIXTURE(SigningTest, testODFGoodGPG) +{ + createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "goodGPG.odt"); + SfxBaseModel* pBaseModel = dynamic_cast(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::underlyingEnumValue(nActual)).getStr()), + SignatureState::OK, nActual); +} + +/// Test a typical ODF where all streams are GPG-signed, but we don't trust the signature. +CPPUNIT_TEST_FIXTURE(SigningTest, testODFUntrustedGoodGPG) +{ + createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "untrustedGoodGPG.odt"); + SfxBaseModel* pBaseModel = dynamic_cast(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::underlyingEnumValue(nActual)).getStr()), + SignatureState::NOTVALIDATED, nActual); +} + +/// Test a typical broken ODF signature where one stream is corrupted. +CPPUNIT_TEST_FIXTURE(SigningTest, testODFBrokenStreamGPG) +{ + createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "badStreamGPG.odt"); + SfxBaseModel* pBaseModel = dynamic_cast(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) +{ + createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "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 + createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "encryptedGPG.odt"); + SfxBaseModel* pBaseModel = dynamic_cast(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + + // ODF1.3 flavour + createDoc(m_directories.getURLFromSrc(DATA_DIRECTORY) + "encryptedGPG_odf13.odt"); + pBaseModel = dynamic_cast(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + + // export and import again + utl::TempFile aTempFile; + { + uno::Sequence props( + comphelper::InitPropertySequence({ { "FilterName", uno::Any(OUString("writer8")) } })); + uno::Reference xDocStorable(mxComponent, uno::UNO_QUERY); + xDocStorable->storeToURL(aTempFile.GetURL(), props); + } + validate(aTempFile.GetFileName(), test::ODF); + + createDoc(aTempFile.GetURL()); + pBaseModel = dynamic_cast(mxComponent.get()); + CPPUNIT_ASSERT(pBaseModel); + pObjectShell = pBaseModel->GetObjectShell(); + CPPUNIT_ASSERT(pObjectShell); + + aTempFile.EnableKillingFile(); +} + +#endif + +SfxObjectShell* SigningTest::assertDocument(const ::CppUnit::SourceLine aSrcLine, + const OUString& rFilterName, + const SignatureState nDocSign, + const SignatureState nMacroSign, + const OUString& sVersion) +{ + std::string sPos = aSrcLine.fileName() + ":" + OString::number(aSrcLine.lineNumber()).getStr(); + + SfxBaseModel* pBaseModel = dynamic_cast(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 aURL(m_directories.getURLFromSrc(DATA_DIRECTORY) + "tdf42316_odt12.ott"); + const OUString sLoadMessage = "loading failed: " + aURL; + + // load the template as-is to validate signatures + mxComponent = loadFromDesktop( + aURL, OUString(), comphelper::InitPropertySequence({ { "AsTemplate", uno::Any(false) } })); + CPPUNIT_ASSERT_MESSAGE(OUStringToOString(sLoadMessage, RTL_TEXTENCODING_UTF8).getStr(), + mxComponent.is()); + + // we are a template, and have a valid document and macro signature + assertDocument(CPPUNIT_SOURCELINE(), "writer8_template", SignatureState::OK, SignatureState::OK, + ODFVER_012_TEXT); + + // create new document from template + mxComponent->dispose(); + mxComponent = mxDesktop->loadComponentFromURL(aURL, "_default", 0, + uno::Sequence(0)); + CPPUNIT_ASSERT_MESSAGE(OUStringToOString(sLoadMessage, RTL_TEXTENCODING_UTF8).getStr(), + mxComponent.is()); + + // we are somehow a template (?), and have just a valid macro signature + assertDocument(CPPUNIT_SOURCELINE(), "writer8_template", SignatureState::NOSIGNATURES, + SignatureState::OK, ODFVER_012_TEXT); + + // save as new ODT document + utl::TempFile aTempFileSaveAsODT; + aTempFileSaveAsODT.EnableKillingFile(); + try + { + uno::Reference xDocStorable(mxComponent, uno::UNO_QUERY); + uno::Sequence descSaveAs( + comphelper::InitPropertySequence({ { "FilterName", uno::Any(OUString("writer8")) } })); + xDocStorable->storeAsURL(aTempFileSaveAsODT.GetURL(), descSaveAs); + } + catch (...) + { + CPPUNIT_FAIL("Failed to save ODT document"); + } + + // save as new OTT template + utl::TempFile aTempFileSaveAsOTT; + aTempFileSaveAsOTT.EnableKillingFile(); + try + { + uno::Reference xDocStorable(mxComponent, uno::UNO_QUERY); + uno::Sequence descSaveAs(comphelper::InitPropertySequence( + { { "FilterName", uno::Any(OUString("writer8_template")) } })); + xDocStorable->storeAsURL(aTempFileSaveAsOTT.GetURL(), descSaveAs); + } + catch (...) + { + CPPUNIT_FAIL("Failed to save OTT template"); + } + + // load the saved OTT template as-is to validate signatures + mxComponent->dispose(); + mxComponent + = loadFromDesktop(aTempFileSaveAsOTT.GetURL(), OUString(), + comphelper::InitPropertySequence({ { "AsTemplate", uno::Any(false) } })); + CPPUNIT_ASSERT_MESSAGE(OUStringToOString(sLoadMessage, RTL_TEXTENCODING_UTF8).getStr(), + mxComponent.is()); + + // the loaded document is a OTT with a valid macro signature + assertDocument(CPPUNIT_SOURCELINE(), "writer8_template", SignatureState::NOSIGNATURES, + SignatureState::OK, ODFVER_013_TEXT); + + // load saved ODT document + createDoc(aTempFileSaveAsODT.GetURL()); + + // the loaded document is a ODT with a macro signature + assertDocument(CPPUNIT_SOURCELINE(), "writer8", SignatureState::NOSIGNATURES, + SignatureState::OK, ODFVER_013_TEXT); + + // save as new OTT template + utl::TempFile aTempFileSaveAsODT_OTT; + aTempFileSaveAsODT_OTT.EnableKillingFile(); + try + { + uno::Reference xDocStorable(mxComponent, uno::UNO_QUERY); + uno::Sequence descSaveAs(comphelper::InitPropertySequence( + { { "FilterName", uno::Any(OUString("writer8_template")) } })); + xDocStorable->storeAsURL(aTempFileSaveAsODT_OTT.GetURL(), descSaveAs); + } + catch (...) + { + CPPUNIT_FAIL("Failed to save OTT template"); + } + + // load the template as-is to validate signatures + mxComponent->dispose(); + mxComponent + = loadFromDesktop(aTempFileSaveAsODT_OTT.GetURL(), OUString(), + comphelper::InitPropertySequence({ { "AsTemplate", uno::Any(false) } })); + CPPUNIT_ASSERT_MESSAGE(OUStringToOString(sLoadMessage, RTL_TEXTENCODING_UTF8).getStr(), + mxComponent.is()); + + // the loaded document is a OTT with a valid macro signature + assertDocument(CPPUNIT_SOURCELINE(), "writer8_template", SignatureState::NOSIGNATURES, + SignatureState::OK, ODFVER_013_TEXT); +} + +/// Test if a macro signature from an OTT 1.0 is dropped for ODT 1.2 +CPPUNIT_TEST_FIXTURE(SigningTest, testDropMacroTemplateSignature) +{ + const OUString aURL(m_directories.getURLFromSrc(DATA_DIRECTORY) + "tdf42316.ott"); + const OUString sLoadMessage = "loading failed: " + aURL; + + // load the template as-is to validate signatures + mxComponent = loadFromDesktop( + aURL, OUString(), comphelper::InitPropertySequence({ { "AsTemplate", uno::Any(false) } })); + CPPUNIT_ASSERT_MESSAGE(OUStringToOString(sLoadMessage, RTL_TEXTENCODING_UTF8).getStr(), + mxComponent.is()); + + // we are a template, and have a non-invalid macro signature + assertDocument(CPPUNIT_SOURCELINE(), "writer8_template", SignatureState::NOSIGNATURES, + SignatureState::NOTVALIDATED, OUString()); + + // create new document from template + mxComponent->dispose(); + mxComponent = mxDesktop->loadComponentFromURL(aURL, "_default", 0, + uno::Sequence(0)); + CPPUNIT_ASSERT_MESSAGE(OUStringToOString(sLoadMessage, RTL_TEXTENCODING_UTF8).getStr(), + mxComponent.is()); + + // we are somehow a template (?), and have just a valid macro signature + assertDocument(CPPUNIT_SOURCELINE(), "writer8_template", SignatureState::NOSIGNATURES, + SignatureState::NOTVALIDATED, OUString()); + + // save as new ODT document + utl::TempFile aTempFileSaveAs; + aTempFileSaveAs.EnableKillingFile(); + try + { + uno::Reference xDocStorable(mxComponent, uno::UNO_QUERY); + uno::Sequence descSaveAs( + comphelper::InitPropertySequence({ { "FilterName", uno::Any(OUString("writer8")) } })); + xDocStorable->storeAsURL(aTempFileSaveAs.GetURL(), descSaveAs); + } + catch (...) + { + CPPUNIT_FAIL("Failed to save ODT document"); + } + + // load saved document + createDoc(aTempFileSaveAs.GetURL()); + + // the loaded document is a 1.2 ODT without any signatures + assertDocument(CPPUNIT_SOURCELINE(), "writer8", SignatureState::NOSIGNATURES, + SignatureState::NOSIGNATURES, ODFVER_013_TEXT); + + // load the template as-is to validate signatures + mxComponent->dispose(); + mxComponent = loadFromDesktop( + aURL, OUString(), comphelper::InitPropertySequence({ { "AsTemplate", uno::Any(false) } })); + CPPUNIT_ASSERT_MESSAGE(OUStringToOString(sLoadMessage, RTL_TEXTENCODING_UTF8).getStr(), + mxComponent.is()); + + // we are a template, and have a non-invalid macro signature + assertDocument(CPPUNIT_SOURCELINE(), "writer8_template", SignatureState::NOSIGNATURES, + SignatureState::NOTVALIDATED, OUString()); + + // save as new OTT template + utl::TempFile aTempFileSaveAsOTT; + aTempFileSaveAsOTT.EnableKillingFile(); + try + { + uno::Reference xDocStorable(mxComponent, uno::UNO_QUERY); + uno::Sequence descSaveAs(comphelper::InitPropertySequence( + { { "FilterName", uno::Any(OUString("writer8_template")) } })); + xDocStorable->storeAsURL(aTempFileSaveAsOTT.GetURL(), descSaveAs); + } + catch (...) + { + CPPUNIT_FAIL("Failed to save OTT template"); + } + + // load the template as-is to validate signatures + mxComponent->dispose(); + mxComponent + = loadFromDesktop(aTempFileSaveAsOTT.GetURL(), OUString(), + comphelper::InitPropertySequence({ { "AsTemplate", uno::Any(false) } })); + CPPUNIT_ASSERT_MESSAGE(OUStringToOString(sLoadMessage, RTL_TEXTENCODING_UTF8).getStr(), + mxComponent.is()); + + // the loaded document is a 1.2 OTT without any signatures + assertDocument(CPPUNIT_SOURCELINE(), "writer8_template", SignatureState::NOSIGNATURES, + SignatureState::NOSIGNATURES, ODFVER_013_TEXT); +} + +namespace +{ +class Resetter +{ +private: + std::function m_Func; + +public: + Resetter(std::function const& rFunc) + : m_Func(rFunc) + { + } + ~Resetter() + { + try + { + m_Func(); + } + catch (...) // has to be reliable + { + fprintf(stderr, "resetter failed with exception\n"); + abort(); + } + } +}; +} + +/// 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 aURL(m_directories.getURLFromSrc(DATA_DIRECTORY) + "tdf42316.ott"); + const OUString sLoadMessage = "loading failed: " + aURL; + + // load the template as-is to validate signatures + mxComponent = loadFromDesktop( + aURL, OUString(), comphelper::InitPropertySequence({ { "AsTemplate", uno::Any(false) } })); + CPPUNIT_ASSERT_MESSAGE(OUStringToOString(sLoadMessage, RTL_TEXTENCODING_UTF8).getStr(), + mxComponent.is()); + + // we are a template, and have a non-invalid macro signature + assertDocument(CPPUNIT_SOURCELINE(), "writer8_template", SignatureState::NOSIGNATURES, + SignatureState::NOTVALIDATED, OUString()); + + // create new document from template + mxComponent->dispose(); + mxComponent = mxDesktop->loadComponentFromURL(aURL, "_default", 0, + uno::Sequence(0)); + CPPUNIT_ASSERT_MESSAGE(OUStringToOString(sLoadMessage, RTL_TEXTENCODING_UTF8).getStr(), + mxComponent.is()); + + // we are somehow a template (?), and have just a valid macro signature + assertDocument(CPPUNIT_SOURCELINE(), "writer8_template", SignatureState::NOSIGNATURES, + SignatureState::NOTVALIDATED, OUString()); + + // save as new ODT document + utl::TempFile aTempFileSaveAsODT; + aTempFileSaveAsODT.EnableKillingFile(); + try + { + uno::Reference xDocStorable(mxComponent, uno::UNO_QUERY); + uno::Sequence descSaveAs( + comphelper::InitPropertySequence({ { "FilterName", uno::Any(OUString("writer8")) } })); + xDocStorable->storeAsURL(aTempFileSaveAsODT.GetURL(), descSaveAs); + } + catch (...) + { + CPPUNIT_FAIL("Failed to save ODT document"); + } + + // save as new OTT template + utl::TempFile aTempFileSaveAsOTT; + aTempFileSaveAsOTT.EnableKillingFile(); + try + { + uno::Reference xDocStorable(mxComponent, uno::UNO_QUERY); + uno::Sequence descSaveAs(comphelper::InitPropertySequence( + { { "FilterName", uno::Any(OUString("writer8_template")) } })); + xDocStorable->storeAsURL(aTempFileSaveAsOTT.GetURL(), descSaveAs); + } + catch (...) + { + CPPUNIT_FAIL("Failed to save OTT template"); + } + + // load the saved OTT template as-is to validate signatures + mxComponent->dispose(); + mxComponent + = loadFromDesktop(aTempFileSaveAsOTT.GetURL(), OUString(), + comphelper::InitPropertySequence({ { "AsTemplate", uno::Any(false) } })); + CPPUNIT_ASSERT_MESSAGE(OUStringToOString(sLoadMessage, RTL_TEXTENCODING_UTF8).getStr(), + mxComponent.is()); + + // the loaded document is a OTT with a non-invalid macro signature + assertDocument(CPPUNIT_SOURCELINE(), "writer8_template", SignatureState::NOSIGNATURES, + SignatureState::NOTVALIDATED, OUString()); + + // load saved ODT document + createDoc(aTempFileSaveAsODT.GetURL()); + + // the loaded document is a ODT with a non-invalid macro signature + assertDocument(CPPUNIT_SOURCELINE(), "writer8", SignatureState::NOSIGNATURES, + SignatureState::NOTVALIDATED, OUString()); + + // save as new OTT template + utl::TempFile aTempFileSaveAsODT_OTT; + aTempFileSaveAsODT_OTT.EnableKillingFile(); + try + { + uno::Reference xDocStorable(mxComponent, uno::UNO_QUERY); + uno::Sequence descSaveAs(comphelper::InitPropertySequence( + { { "FilterName", uno::Any(OUString("writer8_template")) } })); + xDocStorable->storeAsURL(aTempFileSaveAsODT_OTT.GetURL(), descSaveAs); + } + catch (...) + { + CPPUNIT_FAIL("Failed to save OTT template"); + } + + // load the template as-is to validate signatures + mxComponent->dispose(); + mxComponent + = loadFromDesktop(aTempFileSaveAsODT_OTT.GetURL(), OUString(), + comphelper::InitPropertySequence({ { "AsTemplate", uno::Any(false) } })); + CPPUNIT_ASSERT_MESSAGE(OUStringToOString(sLoadMessage, RTL_TEXTENCODING_UTF8).getStr(), + mxComponent.is()); + + // the loaded document is a OTT with a non-invalid macro signature + assertDocument(CPPUNIT_SOURCELINE(), "writer8_template", SignatureState::NOSIGNATURES, + SignatureState::NOTVALIDATED, OUString()); +} + +#endif + +void SigningTest::registerNamespaces(xmlXPathContextPtr& pXmlXpathCtx) +{ + xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("odfds"), + BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:digitalsignature:1.0")); + xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("dsig"), + BAD_CAST("http://www.w3.org/2000/09/xmldsig#")); + xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("xd"), BAD_CAST("http://uri.etsi.org/01903/v1.3.2#")); +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/qa/unit/xmlsecurity-dialogs-test.cxx b/xmlsecurity/qa/unit/xmlsecurity-dialogs-test.cxx new file mode 100644 index 000000000..f7f47c8da --- /dev/null +++ b/xmlsecurity/qa/unit/xmlsecurity-dialogs-test.cxx @@ -0,0 +1,63 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.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("xmlsecurity/qa/unit/data/xmlsecurity-dialogs-test.txt"); +} + +CPPUNIT_TEST_SUITE_REGISTRATION(XmlsecurityDialogsTest); + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/component/certificatecontainer.cxx b/xmlsecurity/source/component/certificatecontainer.cxx new file mode 100644 index 000000000..7e9db3558 --- /dev/null +++ b/xmlsecurity/source/component/certificatecontainer.cxx @@ -0,0 +1,171 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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, const OUString& certificate_name, Map& _certMap); + /// @throws css::uno::RuntimeException + bool isTemporaryCertificate(const OUString& url, const OUString& certificate_name); + /// @throws css::uno::RuntimeException + bool isCertificateTrust(const OUString& url, const OUString& 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, const OUString & 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, const OUString & certificate_name ) +{ + return searchMap( url, certificate_name, certMap); +} + +bool +CertificateContainer::isCertificateTrust ( const OUString & url, const OUString & 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( ) +{ + Sequence< OUString > aRet { "com.sun.star.security.CertificateContainer" }; + return aRet; +} + +namespace +{ +struct Instance +{ + explicit Instance(css::uno::Reference const& context) + : instance(new CertificateContainer(context)) + { + } + + rtl::Reference instance; +}; + +struct Singleton + : public rtl::StaticWithArg, + Singleton> +{ +}; +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +com_sun_star_security_CertificateContainer_get_implementation( + css::uno::XComponentContext* context, css::uno::Sequence const&) +{ + return cppu::acquire(Singleton::get(context).instance.get()); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/component/documentdigitalsignatures.cxx b/xmlsecurity/source/component/documentdigitalsignatures.cxx new file mode 100644 index 000000000..d149bf5e3 --- /dev/null +++ b/xmlsecurity/source/component/documentdigitalsignatures.cxx @@ -0,0 +1,853 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +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 +{ +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( + 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; + } +}; + +} + +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()) + { + 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; + DigitalSignaturesDialog aSignaturesDialog( + Application::GetFrameWeld(mxParentWindow), mxCtx, eMode, bReadOnly, m_sODFVersion, + m_bHasDocumentSignature); + bool bInit = aSignaturesDialog.Init(); + SAL_WARN_IF( !bInit, "xmlsecurity.comp", "Error initializing security context!" ); + if ( bInit ) + { + aSignaturesDialog.SetStorage(rxStorage); + + aSignaturesDialog.SetSignatureStream( xSignStream ); + if (aSignaturesDialog.run() == RET_OK) + { + if (aSignaturesDialog.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 uno::Sequence(0); + + 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 Sequence< css::security::DocumentSignatureInformation >(0); + + + 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.ouGpgCertificate.isEmpty()) // X.509 + { + if (!rInfo.ouX509Certificate.isEmpty()) + rSigInfo.Signer = xSecEnv->createCertificateFromAscii(rInfo.ouX509Certificate); + if (!rSigInfo.Signer.is()) + rSigInfo.Signer = xSecEnv->getCertificate( + rInfo.ouX509IssuerName, + xmlsecurity::numericStringToBigInteger(rInfo.ouX509SerialNumber)); + + // 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, Sequence>()); + } + catch (SecurityException&) + { + OSL_FAIL("Verification of certificate failed"); + rSigInfo.CertificateStatus = css::security::CertificateValidity::INVALID; + } + } + else if (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("")); + 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< css::security::XCertificate >& Author ) +{ + OUString sSerialNum = xmlsecurity::bigIntegerToNumericString( Author->getSerialNumber() ); + + Sequence< SvtSecurityOptions::Certificate > aTrustedAuthors = SvtSecurityOptions().GetTrustedAuthors(); + + return std::any_of(aTrustedAuthors.begin(), aTrustedAuthors.end(), + [&Author, &sSerialNum](const SvtSecurityOptions::Certificate& rAuthor) { + return ( rAuthor[0] == Author->getIssuerName() ) + && ( rAuthor[1] == sSerialNum ); + }); +} + +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(Application::GetFrameWeld(mxParentWindow), xSecContexts, eAction); + + uno::Sequence< Reference< css::security::XCertificate > > xCerts(1); + xCerts[0] = Reference< css::security::XCertificate >(nullptr); + + if (aChooser.run() != RET_OK) + return xCerts; + + 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 aSecOpts; + + SvtSecurityOptions::Certificate aNewCert( 3 ); + aNewCert[ 0 ] = Author->getIssuerName(); + aNewCert[ 1 ] = xmlsecurity::bigIntegerToNumericString( Author->getSerialNumber() ); + + OUStringBuffer aStrBuffer; + ::comphelper::Base64::encode(aStrBuffer, Author->getEncoded()); + aNewCert[ 2 ] = aStrBuffer.makeStringAndClear(); + + + Sequence< SvtSecurityOptions::Certificate > aTrustedAuthors = aSecOpts.GetTrustedAuthors(); + sal_Int32 nCnt = aTrustedAuthors.getLength(); + aTrustedAuthors.realloc( nCnt + 1 ); + aTrustedAuthors[ nCnt ] = aNewCert; + + aSecOpts.SetTrustedAuthors( aTrustedAuthors ); +} + +void DocumentDigitalSignatures::addLocationToTrustedSources( const OUString& Location ) +{ + SvtSecurityOptions aSecOpt; + + Sequence< OUString > aSecURLs = aSecOpt.GetSecureURLs(); + sal_Int32 nCnt = aSecURLs.getLength(); + aSecURLs.realloc( nCnt + 1 ); + aSecURLs[ nCnt ] = Location; + + aSecOpt.SetSecureURLs( aSecURLs ); +} + +sal_Bool DocumentDigitalSignatures::signDocumentWithCertificate( + css::uno::Reference const & xCertificate, + css::uno::Reference const & xStorage, + css::uno::Reference const & xStream) +{ + return signWithCertificateImpl(xCertificate, xStorage, xStream, DocumentSignatureMode::Content); +} + +sal_Bool DocumentDigitalSignatures::signPackageWithCertificate( + css::uno::Reference const& xCertificate, + css::uno::Reference const& xStorage, + css::uno::Reference const& xStream) +{ + return signWithCertificateImpl(xCertificate, xStorage, xStream, DocumentSignatureMode::Package); +} + +sal_Bool DocumentDigitalSignatures::signScriptingContentWithCertificate( + css::uno::Reference const& xCertificate, + css::uno::Reference const& xStorage, + css::uno::Reference const& xStream) +{ + return signWithCertificateImpl(xCertificate, xStorage, xStream, DocumentSignatureMode::Macros); +} + +bool DocumentDigitalSignatures::signWithCertificateImpl( + 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); + + Reference 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 000000000..f0ba29b08 --- /dev/null +++ b/xmlsecurity/source/dialogs/certificatechooser.cxx @@ -0,0 +1,330 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +using namespace comphelper; +using namespace css; + +CertificateChooser::CertificateChooser(weld::Window* _pParent, + std::vector< css::uno::Reference< css::xml::crypto::XXMLSecurityContext > > const & rxSecurityContexts, + UserAction eAction) + : GenericDialogController(_pParent, "xmlsec/ui/selectcertificatedialog.ui", "SelectCertificateDialog") + , mvUserData() + , meAction(eAction) + , m_xFTSign(m_xBuilder->weld_label("sign")) + , m_xFTEncrypt(m_xBuilder->weld_label("encrypt")) + , m_xCertLB(m_xBuilder->weld_tree_view("signatures")) + , m_xViewBtn(m_xBuilder->weld_button("viewcert")) + , m_xOKBtn(m_xBuilder->weld_button("ok")) + , m_xFTDescription(m_xBuilder->weld_label("description-label")) + , m_xDescriptionED(m_xBuilder->weld_entry("description")) +{ + auto nControlWidth = m_xCertLB->get_approximate_digit_width() * 105; + m_xCertLB->set_size_request(nControlWidth, m_xCertLB->get_height_rows(12)); + + std::vector aWidths; + aWidths.push_back(30*nControlWidth/100); + aWidths.push_back(30*nControlWidth/100); + aWidths.push_back(10*nControlWidth/100); + aWidths.push_back(20*nControlWidth/100); + m_xCertLB->set_column_fixed_widths(aWidths); + m_xCertLB->connect_changed( LINK( this, CertificateChooser, CertificateHighlightHdl ) ); + m_xCertLB->connect_row_activated( LINK( this, CertificateChooser, CertificateSelectHdl ) ); + m_xViewBtn->connect_clicked( LINK( this, CertificateChooser, ViewButtonHdl ) ); + + mxSecurityContexts = 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, const char *pResId) +{ + if (bits & bit) + { + if (!string.isEmpty()) + string += ", "; + string += XsResId(pResId); + bits &= ~bit; + } +} + +OUString CertificateChooser::UsageInClearText(int bits) +{ + OUString result; + + HandleOneUsageBit(result, bits, 0x80, STR_DIGITAL_SIGNATURE); + HandleOneUsageBit(result, bits, 0x40, STR_NON_REPUDIATION); + HandleOneUsageBit(result, bits, 0x20, STR_KEY_ENCIPHERMENT); + HandleOneUsageBit(result, bits, 0x10, STR_DATA_ENCIPHERMENT); + HandleOneUsageBit(result, bits, 0x08, STR_KEY_AGREEMENT); + HandleOneUsageBit(result, bits, 0x04, STR_KEY_CERT_SIGN); + HandleOneUsageBit(result, bits, 0x02, STR_CRL_SIGN); + HandleOneUsageBit(result, bits, 0x01, STR_ENCIPHER_ONLY); + + // Check for mystery leftover bits + if (bits != 0) + { + if (!result.isEmpty()) + result += ", "; + result += "0x" + OUString::number(bits, 16); + } + + return result; +} + +void CertificateChooser::ImplInitialize() +{ + if ( mbInitialized ) + return; + + SvtUserOptions aUserOpts; + + switch (meAction) + { + case UserAction::Sign: + m_xFTSign->show(); + m_xOKBtn->set_label(XsResId(STR_SIGN)); + msPreferredKey = aUserOpts.GetSigningKey(); + break; + + case UserAction::SelectSign: + m_xFTSign->show(); + m_xOKBtn->set_label(XsResId(STR_SELECTSIGN)); + msPreferredKey = aUserOpts.GetSigningKey(); + break; + + case UserAction::Encrypt: + m_xFTEncrypt->show(); + m_xFTDescription->hide(); + m_xDescriptionED->hide(); + m_xCertLB->set_selection_mode(SelectionMode::Multiple); + m_xOKBtn->set_label(XsResId(STR_ENCRYPT)); + msPreferredKey = aUserOpts.GetEncryptionKey(); + break; + + } + + for (auto &secContext : mxSecurityContexts) + { + if (!secContext.is()) + continue; + auto secEnvironment = secContext->getSecurityEnvironment(); + if (!secEnvironment.is()) + continue; + + uno::Sequence< uno::Reference< security::XCertificate > > xCerts; + try + { + if ( meAction == UserAction::Sign || meAction == UserAction::SelectSign) + xCerts = secEnvironment->getPersonalCertificates(); + else + xCerts = secEnvironment->getAllCertificates(); + } + catch (security::NoPasswordException&) + { + } + + for( sal_Int32 nCert = xCerts.getLength(); nCert; ) + { + uno::Reference< security::XCertificate > xCert = xCerts[ --nCert ]; + // Check if we have a private key for this... + long nCertificateCharacters = secEnvironment->getCertificateCharacters(xCert); + + if (!(nCertificateCharacters & security::CertificateCharacters::HAS_PRIVATE_KEY)) + { + ::comphelper::removeElementAt( xCerts, nCert ); + } + } + + + // fill list of certificates; the first entry will be selected + for ( const auto& xCert : std::as_const(xCerts) ) + { + std::shared_ptr userData = std::make_shared(); + userData->xCertificate = xCert; + userData->xSecurityContext = secContext; + userData->xSecurityEnvironment = secEnvironment; + mvUserData.push_back(userData); + + OUString sIssuer = xmlsec::GetContentPart( xCert->getIssuerName(), xCert->getCertificateKind()); + + m_xCertLB->append(); + int nRow = m_xCertLB->n_children() - 1; + m_xCertLB->set_text(nRow, xmlsec::GetContentPart(xCert->getSubjectName(), xCert->getCertificateKind()), 0); + m_xCertLB->set_text(nRow, sIssuer, 1); + m_xCertLB->set_text(nRow, xmlsec::GetCertificateKind(xCert->getCertificateKind()), 2); + m_xCertLB->set_text(nRow, utl::GetDateString(xCert->getNotValidAfter()), 3); + m_xCertLB->set_text(nRow, UsageInClearText(xCert->getCertificateUsage()), 4); + OUString sId(OUString::number(reinterpret_cast(userData.get()))); + m_xCertLB->set_id(nRow, sId); + +#if HAVE_FEATURE_GPGME + // only GPG has preferred keys + if ( !sIssuer.isEmpty() && !msPreferredKey.isEmpty() ) { + if ( sIssuer == msPreferredKey ) + { + if ( meAction == UserAction::Sign || meAction == UserAction::SelectSign ) + m_xCertLB->select(nRow); + else if ( meAction == UserAction::Encrypt && + aUserOpts.GetEncryptToSelf() ) + mxEncryptToSelf = xCert; + } + } +#endif + } + } + + // enable/disable buttons + CertificateHighlightHdl(*m_xCertLB); + mbInitialized = true; +} + +uno::Sequence > 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 = reinterpret_cast(m_xCertLB->get_id(rEntry).toInt64()); + 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 = reinterpret_cast(m_xCertLB->get_id(nSel).toInt64()); + 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 = reinterpret_cast(m_xCertLB->get_id(nSel).toInt64()); + 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(); +} + +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 = reinterpret_cast(m_xCertLB->get_id(nSel).toInt64()); + + if (!userData->xSecurityEnvironment.is() || !userData->xCertificate.is()) + return; + + CertificateViewer aViewer(m_xDialog.get(), userData->xSecurityEnvironment, userData->xCertificate, true, this); + aViewer.run(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/dialogs/certificateviewer.cxx b/xmlsecurity/source/dialogs/certificateviewer.cxx new file mode 100644 index 000000000..da924838c --- /dev/null +++ b/xmlsecurity/source/dialogs/certificateviewer.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 +#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 OString&, rPage, void) +{ + if (rPage == "path") + mxPathId->ActivatePage(); +} + +CertificateViewerTP::CertificateViewerTP(weld::Container* pParent, const OUString& rUIXMLDescription, + const OString& rID, CertificateViewer* pDlg) + : mxBuilder(Application::CreateBuilder(pParent, rUIXMLDescription)) + , mxContainer(mxBuilder->weld_container(rID)) + , mpDlg(pDlg) +{ +} + +CertificateViewerGeneralTP::CertificateViewerGeneralTP(weld::Container* pParent, CertificateViewer* pDlg) + : CertificateViewerTP(pParent, "xmlsec/ui/certgeneral.ui", "CertGeneral", pDlg) + , m_xCertImg(mxBuilder->weld_image("certimage")) + , m_xHintNotTrustedFT(mxBuilder->weld_label("hintnotrust")) + , m_xIssuedToLabelFT(mxBuilder->weld_label("issued_to")) + , m_xIssuedToFT(mxBuilder->weld_label("issued_to_value")) + , m_xIssuedByLabelFT(mxBuilder->weld_label("issued_by")) + , m_xIssuedByFT(mxBuilder->weld_label("issued_by_value")) + , m_xValidFromDateFT(mxBuilder->weld_label("valid_from_value")) + , m_xValidToDateFT(mxBuilder->weld_label("valid_to_value")) + , m_xKeyImg(mxBuilder->weld_image("keyimage")) + , m_xHintCorrespPrivKeyFT(mxBuilder->weld_label("privatekey")) +{ + //Verify the certificate + sal_Int32 certStatus = mpDlg->mxSecurityEnvironment->verifyCertificate(mpDlg->mxCert, + Sequence >()); + + 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) + { + 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(OUString::number(reinterpret_cast(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); + std::vector aWidths; + aWidths.push_back(nWidth / 2); + m_xElementsLB->set_column_fixed_widths(aWidths); + + // 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 = reinterpret_cast(m_xElementsLB->get_id(nEntry).toInt64()); + 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")) + , 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 ) ); +} + +void CertificateViewerCertPathTP::ActivatePage() +{ + if ( !mbFirstActivateDone ) + { + 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())) + { + CertPath_UserData* pData = reinterpret_cast(mxCertPathLB->get_id(*xIter).toInt64()); + CertificateViewer aViewer(mpDlg->getDialog(), mpDlg->mxSecurityEnvironment, + pData->mxCert, false, nullptr); + aViewer.run(); + } +} + +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 = reinterpret_cast(mxCertPathLB->get_id(*xIter).toInt64()); + 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) +{ + OUString sImage = bValid ? OUStringLiteral(BMP_CERT_OK) : OUStringLiteral(BMP_CERT_NOT_OK); + maUserData.emplace_back(std::make_unique(rxCert, bValid)); + OUString sId(OUString::number(reinterpret_cast(maUserData.back().get()))); + mxCertPathLB->insert(pParent, -1, &rName, &sId, nullptr, nullptr, &sImage, false, nullptr); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx b/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx new file mode 100644 index 000000000..ef67c7167 --- /dev/null +++ b/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx @@ -0,0 +1,769 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +#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: + sal_Int16 m_nODF; + + virtual void ImplCommit() override; + + public: + virtual void Notify( const css::uno::Sequence< OUString >& aPropertyNames ) override; + SaveODFItem(); + //See group ODF in Common.xcs + bool isLessODF1_2() const + { + return m_nODF < 3; + } + }; + + void SaveODFItem::ImplCommit() {} + void SaveODFItem::Notify( const css::uno::Sequence< OUString >& ) {} + + SaveODFItem::SaveODFItem(): utl::ConfigItem("Office.Common/Save"), m_nODF(0) + { + OUString sDef("ODF/DefaultVersion"); + Sequence< css::uno::Any > aValues = GetProperties( Sequence(&sDef,1) ); + if ( aValues.getLength() != 1) + throw uno::RuntimeException( + "[xmlsecurity] Could not open property Office.Common/Save/ODF/DefaultVersion", + nullptr); + + sal_Int16 nTmp = 0; + if ( !(aValues[0] >>= nTmp) ) + throw uno::RuntimeException( + "[xmlsecurity]SaveODFItem::SaveODFItem(): Wrong Type!", + nullptr ); + + m_nODF = nTmp; + } +} + +DigitalSignaturesDialog::DigitalSignaturesDialog( + weld::Window* pParent, + const uno::Reference< uno::XComponentContext >& rxCtx, DocumentSignatureMode eMode, + bool bReadOnly, const OUString& sODFVersion, bool bHasDocumentSignature) + : GenericDialogController(pParent, "xmlsec/ui/digitalsignaturesdialog.ui", "DigitalSignaturesDialog") + , maSignatureManager(rxCtx, eMode) + , m_sODFVersion (sODFVersion) + , m_bHasDocumentSignature(bHasDocumentSignature) + , m_bWarningShowSignMacro(false) + , m_xHintDocFT(m_xBuilder->weld_label("dochint")) + , m_xHintBasicFT(m_xBuilder->weld_label("macrohint")) + , m_xHintPackageFT(m_xBuilder->weld_label("packagehint")) + , m_xSignaturesLB(m_xBuilder->weld_tree_view("signatures")) + , m_xSigsValidImg(m_xBuilder->weld_image("validimg")) + , m_xSigsValidFI(m_xBuilder->weld_label("validft")) + , m_xSigsInvalidImg(m_xBuilder->weld_image("invalidimg")) + , m_xSigsInvalidFI(m_xBuilder->weld_label("invalidft")) + , m_xSigsNotvalidatedImg(m_xBuilder->weld_image("notvalidatedimg")) + , m_xSigsNotvalidatedFI(m_xBuilder->weld_label("notvalidatedft")) + , m_xSigsOldSignatureImg(m_xBuilder->weld_image("oldsignatureimg")) + , m_xSigsOldSignatureFI(m_xBuilder->weld_label("oldsignatureft")) + , m_xAdESCompliantCB(m_xBuilder->weld_check_button("adescompliant")) + , m_xViewBtn(m_xBuilder->weld_button("view")) + , m_xAddBtn(m_xBuilder->weld_button("sign")) + , m_xRemoveBtn(m_xBuilder->weld_button("remove")) + , m_xStartCertMgrBtn(m_xBuilder->weld_button("start_certmanager")) + , m_xCloseBtn(m_xBuilder->weld_button("close")) +{ + m_bAdESCompliant = !DocumentSignatureHelper::isODFPre_1_2(m_sODFVersion); + + auto nControlWidth = m_xSignaturesLB->get_approximate_digit_width() * 105; + m_xSignaturesLB->set_size_request(nControlWidth, m_xSignaturesLB->get_height_rows(10)); + + // Give the first column 6 percent, try to distribute the rest equally. + std::vector aWidths; + aWidths.push_back(6*nControlWidth/100); + auto nColWidth = (nControlWidth - aWidths[0]) / 4; + aWidths.push_back(nColWidth); + aWidths.push_back(nColWidth); + aWidths.push_back(nColWidth); + m_xSignaturesLB->set_column_fixed_widths(aWidths); + + mbVerifySignatures = true; + mbSignaturesChanged = false; + + m_xSignaturesLB->connect_changed( LINK( this, DigitalSignaturesDialog, SignatureHighlightHdl ) ); + m_xSignaturesLB->connect_row_activated( LINK( this, DigitalSignaturesDialog, SignatureSelectHdl ) ); + + m_xAdESCompliantCB->connect_toggled( LINK( this, DigitalSignaturesDialog, AdESCompliantCheckBoxHdl ) ); + m_xAdESCompliantCB->set_active(m_bAdESCompliant); + + m_xViewBtn->connect_clicked( LINK( this, DigitalSignaturesDialog, ViewButtonHdl ) ); + m_xViewBtn->set_sensitive(false); + + m_xAddBtn->connect_clicked( LINK( this, DigitalSignaturesDialog, AddButtonHdl ) ); + if ( bReadOnly ) + m_xAddBtn->set_sensitive(false); + + m_xRemoveBtn->connect_clicked( LINK( this, DigitalSignaturesDialog, RemoveButtonHdl ) ); + m_xRemoveBtn->set_sensitive(false); + + m_xStartCertMgrBtn->connect_clicked( LINK( this, DigitalSignaturesDialog, CertMgrButtonHdl ) ); + + m_xCloseBtn->connect_clicked( LINK( this, DigitalSignaturesDialog, OKButtonHdl) ); + + switch( maSignatureManager.getSignatureMode() ) + { + case DocumentSignatureMode::Content: + m_xHintDocFT->show(); + break; + case DocumentSignatureMode::Macros: + m_xHintBasicFT->show(); + break; + case DocumentSignatureMode::Package: + m_xHintPackageFT->show(); + break; + } +} + +DigitalSignaturesDialog::~DigitalSignaturesDialog() +{ +} + +bool DigitalSignaturesDialog::Init() +{ + bool bInit = maSignatureManager.init(); + + SAL_WARN_IF( !bInit, "xmlsecurity.dialogs", "Error initializing security context!" ); + + if ( bInit ) + { + maSignatureManager.getSignatureHelper().SetStartVerifySignatureHdl( LINK( this, DigitalSignaturesDialog, StartVerifySignatureHdl ) ); + } + + return bInit; +} + +void DigitalSignaturesDialog::SetStorage( const css::uno::Reference < css::embed::XStorage >& rxStore ) +{ + if (!rxStore.is()) + { + // PDF supports AdES. + m_bAdESCompliant = true; + m_xAdESCompliantCB->set_active(m_bAdESCompliant); + return; + } + + maSignatureManager.setStore(rxStore); + maSignatureManager.getSignatureHelper().SetStorage( maSignatureManager.getStore(), m_sODFVersion); +} + +void DigitalSignaturesDialog::SetSignatureStream( const css::uno::Reference < css::io::XStream >& rxStream ) +{ + maSignatureManager.setSignatureStream(rxStream); +} + +bool DigitalSignaturesDialog::canAddRemove() +{ + //FIXME: this func needs some cleanup, such as real split between + //'canAdd' and 'canRemove' case + bool ret = true; + + uno::Reference xNameAccess = maSignatureManager.getStore(); + if (xNameAccess.is() && xNameAccess->hasByName("[Content_Types].xml")) + // It's always possible to append an OOXML signature. + return ret; + + if (!maSignatureManager.getStore().is()) + // It's always possible to append a PDF signature. + return ret; + + OSL_ASSERT(maSignatureManager.getStore().is()); + bool bDoc1_1 = DocumentSignatureHelper::isODFPre_1_2(m_sODFVersion); + SaveODFItem item; + bool bSave1_1 = item.isLessODF1_2(); + + // see specification + //cvs: specs/www/appwide/security/Electronic_Signatures_and_Security.sxw + //Paragraph 'Behavior with regard to ODF 1.2' + //For both, macro and document + if ( (!bSave1_1 && bDoc1_1) || (bSave1_1 && bDoc1_1) ) + { + //#4 + std::unique_ptr xBox(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Warning, VclButtonsType::Ok, + XsResId(STR_XMLSECDLG_OLD_ODF_FORMAT))); + xBox->run(); + ret = false; + } + + //As of OOo 3.2 the document signature includes in macrosignatures.xml. That is + //adding a macro signature will break an existing document signature. + //The sfx2 will remove the documentsignature when the user adds a macro signature + if (maSignatureManager.getSignatureMode() == DocumentSignatureMode::Macros + && ret) + { + if (m_bHasDocumentSignature && !m_bWarningShowSignMacro) + { + //The warning says that the document signatures will be removed if the user + //continues. He can then either press 'OK' or 'NO' + //It the user presses 'Add' or 'Remove' several times then, then the warning + //is shown every time until the user presses 'OK'. From then on, the warning + //is not displayed anymore as long as the signatures dialog is alive. + std::unique_ptr xBox(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Question, VclButtonsType::YesNo, + XsResId(STR_XMLSECDLG_QUERY_REMOVEDOCSIGNBEFORESIGN))); + if (xBox->run() == RET_NO) + ret = false; + else + m_bWarningShowSignMacro = true; + + } + } + return ret; +} + +bool DigitalSignaturesDialog::canAdd() +{ + return canAddRemove(); +} + +bool DigitalSignaturesDialog::canRemove() +{ + bool bRet = true; + + if ( maSignatureManager.getSignatureMode() == DocumentSignatureMode::Content ) + { + std::unique_ptr 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()); +} + +short DigitalSignaturesDialog::run() +{ + // 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; + + return GenericDialogController::run(); +} + +IMPL_LINK_NOARG(DigitalSignaturesDialog, SignatureHighlightHdl, weld::TreeView&, void) +{ + bool bSel = m_xSignaturesLB->get_selected_index() != -1; + m_xViewBtn->set_sensitive( bSel ); + if ( m_xAddBtn->get_sensitive() ) // not read only + m_xRemoveBtn->set_sensitive( bSel ); +} + +IMPL_LINK_NOARG(DigitalSignaturesDialog, OKButtonHdl, weld::Button&, void) +{ + if (mbSignaturesChanged) + maSignatureManager.write(m_bAdESCompliant); + + m_xDialog->response(RET_OK); +} + +IMPL_LINK_NOARG(DigitalSignaturesDialog, SignatureSelectHdl, weld::TreeView&, bool) +{ + ImplShowSignaturesDetails(); + return true; +} + +IMPL_LINK_NOARG(DigitalSignaturesDialog, AdESCompliantCheckBoxHdl, weld::ToggleButton&, void) +{ + m_bAdESCompliant = m_xAdESCompliantCB->get_active(); +} + +IMPL_LINK_NOARG(DigitalSignaturesDialog, ViewButtonHdl, weld::Button&, void) +{ + ImplShowSignaturesDetails(); +} + +IMPL_LINK_NOARG(DigitalSignaturesDialog, AddButtonHdl, weld::Button&, void) +{ + if( ! canAdd()) + return; + try + { + std::vector> xSecContexts; + xSecContexts.push_back(maSignatureManager.getSecurityContext()); + // Gpg signing is only possible with ODF >= 1.2 documents + if (DocumentSignatureHelper::CanSignWithGPG(maSignatureManager.getStore(), m_sODFVersion)) + xSecContexts.push_back(maSignatureManager.getGpgSecurityContext()); + + CertificateChooser aChooser(m_xDialog.get(), 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& ) + { + OSL_FAIL( "Exception while 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) + { + try + { + sal_uInt16 nSelected = m_xSignaturesLB->get_id(nEntry).toUInt32(); + maSignatureManager.remove(nSelected); + + mbSignaturesChanged = true; + + ImplFillSignaturesBox(); + } + catch ( uno::Exception& ) + { + OSL_FAIL( "Exception while removing a signature!" ); + // Don't keep invalid entries... + ImplGetSignatureInformations(/*bUseTempStream=*/true, /*bCacheLastSignature=*/true); + ImplFillSignaturesBox(); + } + } +} + +IMPL_LINK_NOARG(DigitalSignaturesDialog, CertMgrButtonHdl, weld::Button&, void) +{ +#ifdef _WIN32 + // FIXME: call GpgME::dirInfo("bindir") somewhere in + // SecurityEnvironmentGpg or whatnot + // FIXME: perhaps poke GpgME for uiserver, and hope it returns something useful? + static const OUStringLiteral aGUIServers[] = { "Gpg4win\\kleopatra.exe", + "Gpg4win\\bin\\kleopatra.exe", + "GNU\\GnuPG\\kleopatra.exe", + "GNU\\GnuPG\\launch-gpa.exe", + "GNU\\GnuPG\\gpa.exe", + "GnuPG\\bin\\gpa.exe", + "GNU\\GnuPG\\bin\\kleopatra.exe", + "GNU\\GnuPG\\bin\\launch-gpa.exe", + "GNU\\GnuPG\\bin\\gpa.exe", + }; + static const OUString aPath = [] { + OUString sRet; + PWSTR sPath = nullptr; + HRESULT hr + = SHGetKnownFolderPath(FOLDERID_ProgramFilesX86, KF_FLAG_DEFAULT, nullptr, &sPath); + if (SUCCEEDED(hr)) + { + sRet = o3tl::toU(sPath); + CoTaskMemFree(sPath); + } + return sRet; + }(); + if (aPath.isEmpty()) + return; +#else + static const OUStringLiteral aGUIServers[] = { "kleopatra", "seahorse", "gpa", "kgpg" }; + const char* cPath = getenv("PATH"); + if (!cPath) + return; + OUString aPath(cPath, strlen(cPath), osl_getThreadTextEncoding()); +#endif + + OUString sFoundGUIServer, sExecutable; + + for ( auto const &rServer : aGUIServers ) + { + osl::FileBase::RC searchError = osl::File::searchFileURL(rServer, aPath, sFoundGUIServer ); + if (searchError == osl::FileBase::E_None) + { + osl::File::getSystemPathFromFileURL( sFoundGUIServer, sExecutable ); + break; + } + + } + + if ( !sExecutable.isEmpty() ) + { + uno::Reference< uno::XComponentContext > xContext = + ::comphelper::getProcessComponentContext(); + uno::Reference< css::system::XSystemShellExecute > xSystemShell( + css::system::SystemShellExecute::create(xContext) ); + + xSystemShell->execute( sExecutable, OUString(), + css::system::SystemShellExecuteFlags::DEFAULTS ); + } + else + { + std::unique_ptr xInfoBox(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Info, VclButtonsType::Ok, + XsResId(STR_XMLSECDLG_NO_CERT_MANAGER))); + xInfoBox->run(); + } +} + +IMPL_LINK_NOARG(DigitalSignaturesDialog, StartVerifySignatureHdl, LinkParamNone*, bool) +{ + return mbVerifySignatures; +} + +void DigitalSignaturesDialog::ImplFillSignaturesBox() +{ + m_xSignaturesLB->clear(); + + size_t nInfos = maSignatureManager.getCurrentSignatureInformations().size(); + size_t nValidSigs = 0, nValidCerts = 0; + bool bAllNewSignatures = true; + bool bSomePartial = false; + + if( nInfos ) + { + for( size_t n = 0; n < nInfos; ++n ) + { + DocumentSignatureAlgorithm mode = DocumentSignatureHelper::getDocumentAlgorithm( + m_sODFVersion, maSignatureManager.getCurrentSignatureInformations()[n]); + std::vector< OUString > aElementsToBeVerified; + if (maSignatureManager.getStore().is()) + aElementsToBeVerified = DocumentSignatureHelper::CreateElementList(maSignatureManager.getStore(), maSignatureManager.getSignatureMode(), mode); + + const SignatureInformation& rInfo = maSignatureManager.getCurrentSignatureInformations()[n]; + uno::Reference< css::security::XCertificate > xCert = getCertificate(rInfo); + + OUString aSubject; + OUString aIssuer; + OUString aDateTimeStr; + OUString aDescription; + OUString aType; + + bool bCertValid = false; + if( xCert.is() ) + { + //check the validity of the cert + try { + sal_Int32 certResult = getSecurityEnvironmentForCertificate(xCert)->verifyCertificate(xCert, + Sequence >()); + + 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.ouCertDigest.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, 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.ouX509Certificate.isEmpty()) + xCert = xSecEnv->createCertificateFromAscii(rInfo.ouX509Certificate); + 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()) + xCert = xSecEnv->getCertificate( rInfo.ouX509IssuerName, xmlsecurity::numericStringToBigInteger( rInfo.ouX509SerialNumber ) ); + if (!xCert.is() && xGpgSecEnv.is()) + xCert = xGpgSecEnv->getCertificate( rInfo.ouGpgKeyID, xmlsecurity::numericStringToBigInteger("") ); + + 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) +{ + if (xCert->getCertificateKind() == CertificateKind_OPENPGP) + return maSignatureManager.getGpgSecurityEnvironment(); + else if (xCert->getCertificateKind() == CertificateKind_X509) + return maSignatureManager.getSecurityEnvironment(); + + throw RuntimeException("Unknown certificate kind"); +} + +//If bUseTempStream is true then the temporary signature stream is used. +//Otherwise the real signature stream is used. +void DigitalSignaturesDialog::ImplGetSignatureInformations(bool bUseTempStream, bool bCacheLastSignature) +{ + maSignatureManager.read(bUseTempStream, bCacheLastSignature); + mbVerifySignatures = false; +} + +void DigitalSignaturesDialog::ImplShowSignaturesDetails() +{ + int nEntry = m_xSignaturesLB->get_selected_index(); + if (nEntry != -1) + { + sal_uInt16 nSelected = m_xSignaturesLB->get_id(nEntry).toUInt32(); + const SignatureInformation& rInfo = maSignatureManager.getCurrentSignatureInformations()[ nSelected ]; + uno::Reference xCert = getCertificate(rInfo); + + if ( xCert.is() ) + { + uno::Reference xSecEnv = getSecurityEnvironmentForCertificate(xCert); + CertificateViewer aViewer(m_xDialog.get(), xSecEnv, xCert, false, nullptr); + aViewer.run(); + } + else + { + std::unique_ptr xInfoBox(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Info, VclButtonsType::Ok, + XsResId(STR_XMLSECDLG_NO_CERT_FOUND))); + xInfoBox->run(); + } + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/dialogs/macrosecurity.cxx b/xmlsecurity/source/dialogs/macrosecurity.cxx new file mode 100644 index 000000000..1596e327d --- /dev/null +++ b/xmlsecurity/source/dialogs/macrosecurity.cxx @@ -0,0 +1,442 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +using namespace comphelper; +using namespace ::com::sun::star; + + +IMPL_LINK_NOARG(MacroSecurity, OkBtnHdl, weld::Button&, void) +{ + m_xLevelTP->ClosePage(); + m_xTrustSrcTP->ClosePage(); + m_xDialog->response(RET_OK); +} + +MacroSecurity::MacroSecurity(weld::Window* pParent, + const css::uno::Reference& rxSecurityEnvironment) + : GenericDialogController(pParent, "xmlsec/ui/macrosecuritydialog.ui", "MacroSecurityDialog") + , m_xSecurityEnvironment(rxSecurityEnvironment) + , m_xTabCtrl(m_xBuilder->weld_notebook("tabcontrol")) + , m_xOkBtn(m_xBuilder->weld_button("ok")) + , m_xResetBtn(m_xBuilder->weld_button("reset")) +{ + m_xTabCtrl->connect_enter_page(LINK(this, MacroSecurity, ActivatePageHdl)); + + m_xLevelTP.reset(new MacroSecurityLevelTP(m_xTabCtrl->get_page("SecurityLevelPage"), this)); + m_xTrustSrcTP.reset(new MacroSecurityTrustedSourcesTP(m_xTabCtrl->get_page("SecurityTrustPage"), this)); + + m_xTabCtrl->set_current_page("SecurityLevelPage"); + m_xOkBtn->connect_clicked(LINK(this, MacroSecurity, OkBtnHdl)); +} + +IMPL_LINK(MacroSecurity, ActivatePageHdl, const OString&, rPage, void) +{ + if (rPage == "SecurityLevelPage") + m_xLevelTP->ActivatePage(); + else if (rPage == "SecurityTrustPage") + m_xTrustSrcTP->ActivatePage(); +} + +MacroSecurityTP::MacroSecurityTP(weld::Container* pParent, const OUString& rUIXMLDescription, + const OString& rID, MacroSecurity* pDlg) + : m_xBuilder(Application::CreateBuilder(pParent, rUIXMLDescription)) + , m_xContainer(m_xBuilder->weld_container(rID)) + , m_pDlg(pDlg) +{ +} + +void MacroSecurityTP::ActivatePage() +{ +} + +MacroSecurityTP::~MacroSecurityTP() +{ +} + +MacroSecurityLevelTP::MacroSecurityLevelTP(weld::Container* pParent, MacroSecurity* pDlg) + : MacroSecurityTP(pParent, "xmlsec/ui/securitylevelpage.ui", "SecurityLevelPage", pDlg) + , m_xVeryHighRB(m_xBuilder->weld_radio_button("vhigh")) + , m_xHighRB(m_xBuilder->weld_radio_button("high")) + , m_xMediumRB(m_xBuilder->weld_radio_button("med")) + , m_xLowRB(m_xBuilder->weld_radio_button("low")) + , m_xVHighImg(m_xBuilder->weld_widget("vhighimg")) + , m_xHighImg(m_xBuilder->weld_widget("highimg")) + , m_xMedImg(m_xBuilder->weld_widget("medimg")) + , m_xLowImg(m_xBuilder->weld_widget("lowimg")) +{ + m_xLowRB->connect_toggled( LINK( this, MacroSecurityLevelTP, RadioButtonHdl ) ); + m_xMediumRB->connect_toggled( LINK( this, MacroSecurityLevelTP, RadioButtonHdl ) ); + m_xHighRB->connect_toggled( LINK( this, MacroSecurityLevelTP, RadioButtonHdl ) ); + m_xVeryHighRB->connect_toggled( LINK( this, MacroSecurityLevelTP, RadioButtonHdl ) ); + + int nPrefWidth(std::max({m_xVeryHighRB->get_preferred_size().Width(), + m_xHighRB->get_preferred_size().Width(), + m_xMediumRB->get_preferred_size().Width(), + m_xLowRB->get_preferred_size().Width()})); + int nMaxWidth = m_xLowRB->get_approximate_digit_width() * 60; + if (nPrefWidth > nMaxWidth) + { + m_xLowRB->set_label_line_wrap(true); + m_xLowRB->set_size_request(nMaxWidth, -1); + m_xMediumRB->set_label_line_wrap(true); + m_xMediumRB->set_size_request(nMaxWidth, -1); + m_xHighRB->set_label_line_wrap(true); + m_xHighRB->set_size_request(nMaxWidth, -1); + m_xVeryHighRB->set_label_line_wrap(true); + m_xVeryHighRB->set_size_request(nMaxWidth, -1); + } + + mnCurLevel = static_cast(m_pDlg->m_aSecOptions.GetMacroSecurityLevel()); + bool bReadonly = m_pDlg->m_aSecOptions.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::ToggleButton&, 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() +{ + m_pDlg->m_aSecOptions.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(const OUString& 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) + { + 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][0], + xmlsecurity::numericStringToBigInteger(m_aTrustedAuthors[nSelected][1])); + } + catch (...) + { + TOOLS_WARN_EXCEPTION("xmlsecurity.dialogs", "matching certificate not found for: " << m_aTrustedAuthors[nSelected][0]); + } + + if (!xCert.is()) + { + try + { + xCert = m_pDlg->m_xSecurityEnvironment->createCertificateFromAscii(m_aTrustedAuthors[nSelected][2]); + } + catch (...) + { + TOOLS_WARN_EXCEPTION("xmlsecurity.dialogs", "certificate data couldn't be parsed: " << m_aTrustedAuthors[nSelected][2]); + } + } + + 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][2]); + } +} + +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(); + ::comphelper::removeElementAt( m_aTrustedAuthors, 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 = ui::dialogs::FolderPicker::create(xContext); + + 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) + { + 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.getLength(); + + if ( nEntries && m_pDlg->m_xSecurityEnvironment.is() ) + { + for( sal_uInt32 nEntry = 0 ; nEntry < nEntries ; ++nEntry ) + { + css::uno::Sequence< OUString >& rEntry = m_aTrustedAuthors[ nEntry ]; + + try + { + // create from RawData + uno::Reference< css::security::XCertificate > xCert = m_pDlg->m_xSecurityEnvironment->createCertificateFromAscii(rEntry[2]); + 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[2]); + OUString sData = rEntry[2]; + 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; + aWidths.push_back(nColWidth * 2); + aWidths.push_back(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 = m_pDlg->m_aSecOptions.GetTrustedAuthors(); + mbAuthorsReadonly = m_pDlg->m_aSecOptions.IsReadOnly( SvtSecurityOptions::EOption::MacroTrustedAuthors ); + m_xTrustCertROFI->set_visible(mbAuthorsReadonly); + + FillCertLB(true); + + const css::uno::Sequence< OUString > aSecureURLs = m_pDlg->m_aSecOptions.GetSecureURLs(); + mbURLsReadonly = m_pDlg->m_aSecOptions.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 ) + { + css::uno::Sequence< OUString > aSecureURLs( nEntryCnt ); + for (sal_Int32 i = 0; i < nEntryCnt; ++i) + { + OUString aURL(m_xTrustFileLocLB->get_text(i)); + osl::FileBase::getFileURLFromSystemPath( aURL, aURL ); + aSecureURLs[ i ] = aURL; + } + + m_pDlg->m_aSecOptions.SetSecureURLs( aSecureURLs ); + } + // Trusted Path could not be removed (#i33584#) + // don't forget to remove the old saved SecureURLs + else + m_pDlg->m_aSecOptions.SetSecureURLs( css::uno::Sequence< OUString >() ); + + m_pDlg->m_aSecOptions.SetTrustedAuthors( m_aTrustedAuthors ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/framework/buffernode.cxx b/xmlsecurity/source/framework/buffernode.cxx new file mode 100644 index 000000000..0a0a58421 --- /dev/null +++ b/xmlsecurity/source/framework/buffernode.cxx @@ -0,0 +1,886 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "elementmark.hxx" +#include "elementcollector.hxx" +#include "buffernode.hxx" +#include +#include +#include + +BufferNode::BufferNode( const css::uno::Reference< css::xml::wrapper::XXMLElementWrapper >& xXMLElement ) + :m_pParent(nullptr), + m_pBlocker(nullptr), + m_bAllReceived(false), + m_xXMLElement(xXMLElement) +{ +} + +bool BufferNode::isECOfBeforeModifyIncluded(sal_Int32 nIgnoredSecurityId) const +/****** BufferNode/isECOfBeforeModifyIncluded ******************************** + * + * NAME + * isECOfBeforeModifyIncluded -- checks whether there is some + * ElementCollector on this BufferNode, that has BEFORE-MODIFY priority. + * + * SYNOPSIS + * bExist = isECOfBeforeModifyIncluded(nIgnoredSecurityId); + * + * FUNCTION + * checks each ElementCollector on this BufferNode, if all following + * conditions are satisfied, then returns true: + * 1. the ElementCollector's priority is BEFOREMODIFY; + * 2. the ElementCollector's securityId can't be ignored. + * otherwise, returns false. + * + * INPUTS + * nIgnoredSecurityId - the security Id to be ignored. If it equals + * to UNDEFINEDSECURITYID, then no security Id + * will be ignored. + * + * RESULT + * bExist - true if a match found, false otherwise + ******************************************************************************/ +{ + return std::any_of(m_vElementCollectors.cbegin(), m_vElementCollectors.cend(), + [nIgnoredSecurityId](const ElementCollector* pElementCollector) { + return (nIgnoredSecurityId == css::xml::crypto::sax::ConstOfSecurityId::UNDEFINEDSECURITYID || + pElementCollector->getSecurityId() != nIgnoredSecurityId) && + (pElementCollector->getPriority() == css::xml::crypto::sax::ElementMarkPriority_BEFOREMODIFY); + }); +} + +void BufferNode::setReceivedAll() +/****** BufferNode/setReceiveAll ********************************************* + * + * NAME + * setReceivedAll -- indicates that the element in this BufferNode has + * been completely buffered. + * + * SYNOPSIS + * setReceivedAll(); + * + * FUNCTION + * sets the all-received flag and launches ElementCollector's notify + * process. + * + * INPUTS + * empty + * + * RESULT + * empty + ******************************************************************************/ +{ + m_bAllReceived = true; + elementCollectorNotify(); +} + + +void BufferNode::addElementCollector(const ElementCollector* pElementCollector) +/****** BufferNode/addElementCollector *************************************** + * + * NAME + * addElementCollector -- adds a new ElementCollector to this BufferNode. + * + * SYNOPSIS + * addElementCollector(pElementCollector); + * + * FUNCTION + * see NAME + * + * INPUTS + * pElementCollector - the ElementCollector to be added + * + * RESULT + * empty + ******************************************************************************/ +{ + m_vElementCollectors.push_back( pElementCollector ); + const_cast(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=").append(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=").append(OUString::number(ii->getSecurityId())).append(") "); + } + + 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()) + { + 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 000000000..e3cabd97e --- /dev/null +++ b/xmlsecurity/source/framework/buffernode.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 . + */ + +#ifndef INCLUDED_XMLSECURITY_SOURCE_FRAMEWORK_BUFFERNODE_HXX +#define INCLUDED_XMLSECURITY_SOURCE_FRAMEWORK_BUFFERNODE_HXX + +#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< std::unique_ptr > m_vChildren; + + /* all ElementCollector holding this BufferNode */ + std::vector< const ElementCollector* > m_vElementCollectors; + + /* + * the blocker holding this BufferNode, one BufferNode can have one + * blocker at most + */ + ElementMark* m_pBlocker; + + /* + * whether the element has completely buffered by the document wrapper + * component + */ + bool m_bAllReceived; + + /* the XMLElementWrapper of the buffered element */ + css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > m_xXMLElement; + +private: + bool isECInSubTreeIncluded(sal_Int32 nIgnoredSecurityId) const; + bool isECOfBeforeModifyInAncestorIncluded(sal_Int32 nIgnoredSecurityId) const; + bool isBlockerInSubTreeIncluded(sal_Int32 nIgnoredSecurityId) const; + const BufferNode* getNextChild(const BufferNode* pChild) const; + +public: + explicit BufferNode( + const css::uno::Reference< css::xml::wrapper::XXMLElementWrapper >& xXMLElement); + + bool isECOfBeforeModifyIncluded(sal_Int32 nIgnoredSecurityId) const; + void setReceivedAll(); + bool isAllReceived() const { return m_bAllReceived;} + void addElementCollector(const ElementCollector* pElementCollector); + void removeElementCollector(const ElementCollector* pElementCollector); + ElementMark* getBlocker() const { return m_pBlocker;} + void setBlocker(const ElementMark* pBlocker); + OUString printChildren() const; + bool hasAnything() const; + bool hasChildren() const; + std::vector< std::unique_ptr< BufferNode> > const & getChildren() const; + std::vector< std::unique_ptr< BufferNode> > releaseChildren(); + const BufferNode* getFirstChild() const; + void addChild(std::unique_ptr 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< css::xml::wrapper::XXMLElementWrapper >& getXMLElement() const { return m_xXMLElement;} + void setXMLElement(const css::uno::Reference< + css::xml::wrapper::XXMLElementWrapper >& xXMLElement); + void notifyBranch(); + void elementCollectorNotify(); +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/framework/elementcollector.cxx b/xmlsecurity/source/framework/elementcollector.cxx new file mode 100644 index 000000000..7801d6328 --- /dev/null +++ b/xmlsecurity/source/framework/elementcollector.cxx @@ -0,0 +1,137 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "elementmark.hxx" +#include "elementcollector.hxx" +#include +#include + +ElementCollector::ElementCollector( + sal_Int32 nBufferId, + css::xml::crypto::sax::ElementMarkPriority nPriority, + bool bToModify, + const css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener >& xReferenceResolvedListener) + :ElementMark(css::xml::crypto::sax::ConstOfSecurityId::UNDEFINEDSECURITYID, nBufferId), + m_nPriority(nPriority), + m_bToModify(bToModify), + m_bAbleToNotify(false), + m_bNotified(false), + m_xReferenceResolvedListener(xReferenceResolvedListener) +/****** ElementCollector/ElementCollector ************************************* + * + * NAME + * ElementCollector -- constructor method + * + * SYNOPSIS + * ElementCollector(nSecurityId, nBufferId, nPriority, bToModify + * xReferenceResolvedListener); + * + * FUNCTION + * construct an ElementCollector object. + * + * INPUTS + * nSecurityId - represents which security entity the buffer node is + * related with. Either a signature or an encryption is + * a security entity. + * nBufferId - the id of the element buffered in the document + * wrapper component. The document wrapper component + * uses this id to search the particular buffered + * element. + * nPriority - the priority value. ElementCollector with lower + * priority value can't notify until all ElementCollectors + * with higher priority value have notified. + * bToModify - A flag representing whether this ElementCollector + * notification will cause the modification of its working + * element. + * xReferenceResolvedListener + * - the listener that this ElementCollector notifies to. + ******************************************************************************/ +{ + m_type = css::xml::crypto::sax::ElementMarkType_ELEMENTCOLLECTOR; +} + + +void ElementCollector::notifyListener() +/****** ElementCollector/notifyListener *************************************** + * + * NAME + * notifyListener -- enable the ability to notify the listener + * + * SYNOPSIS + * notifyListener(); + * + * FUNCTION + * enable the ability to notify the listener and try to notify then. + ******************************************************************************/ +{ + m_bAbleToNotify = true; + doNotify(); +} + +void ElementCollector::setReferenceResolvedListener( + const css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener >& xReferenceResolvedListener) +/****** ElementCollector/setReferenceResolvedListener ************************* + * + * NAME + * setReferenceResolvedListener -- configures a listener for the buffer + * node in this object + * + * SYNOPSIS + * setReferenceResolvedListener(xReferenceResolvedListener); + * + * FUNCTION + * configures a new listener and try to notify then. + * + * INPUTS + * xReferenceResolvedListener - the new listener + ******************************************************************************/ +{ + m_xReferenceResolvedListener = xReferenceResolvedListener; + doNotify(); +} + +void ElementCollector::doNotify() +/****** ElementCollector/doNotify ********************************************* + * + * NAME + * doNotify -- tries to notify the listener + * + * SYNOPSIS + * doNotify(); + * + * FUNCTION + * notifies the listener when all below conditions are satisfied: + * the listener has not been notified; + * the notify right is granted; + * the listener has already been configured; + * the security id has already been configure + ******************************************************************************/ +{ + if (!m_bNotified && + m_bAbleToNotify && + m_xReferenceResolvedListener.is() && + m_nSecurityId != css::xml::crypto::sax::ConstOfSecurityId::UNDEFINEDSECURITYID) + { + m_bNotified = true; + m_xReferenceResolvedListener->referenceResolved(m_nBufferId); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/framework/elementcollector.hxx b/xmlsecurity/source/framework/elementcollector.hxx new file mode 100644 index 000000000..8af12f246 --- /dev/null +++ b/xmlsecurity/source/framework/elementcollector.hxx @@ -0,0 +1,83 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_XMLSECURITY_SOURCE_FRAMEWORK_ELEMENTCOLLECTOR_HXX +#define INCLUDED_XMLSECURITY_SOURCE_FRAMEWORK_ELEMENTCOLLECTOR_HXX + +#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, + const css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener >& xReferenceResolvedListener); + + css::xml::crypto::sax::ElementMarkPriority getPriority() const { return m_nPriority;} + bool getModify() const { return m_bToModify;} + void notifyListener(); + void setReferenceResolvedListener( + const css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener >& referenceResolvedListener); + void doNotify(); +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/framework/elementmark.cxx b/xmlsecurity/source/framework/elementmark.cxx new file mode 100644 index 000000000..71444d7cd --- /dev/null +++ b/xmlsecurity/source/framework/elementmark.cxx @@ -0,0 +1,64 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include "elementmark.hxx" + +ElementMark::ElementMark(sal_Int32 nSecurityId, sal_Int32 nBufferId) + :m_pBufferNode(nullptr), + m_nSecurityId(nSecurityId), + m_nBufferId(nBufferId), + m_type(css::xml::crypto::sax::ElementMarkType_ELEMENTMARK) +/****** ElementMark/ElementMark *********************************************** + * + * NAME + * ElementMark -- constructor method + * + * SYNOPSIS + * ElementMark(nSecurityId, nBufferId); + * + * FUNCTION + * construct an ElementMark object. + * + * INPUTS + * nSecurityId - represents which security entity the buffer node is + * related with. Either a signature or an encryption is + * a security entity. + * nBufferId - the id of the element buffered in the document + * wrapper component. The document wrapper component + * uses this id to search the particular buffered + * element. + ******************************************************************************/ +{ +} + + +void ElementMark::setBufferNode(const BufferNode* pBufferNode) +{ + m_pBufferNode = const_cast(pBufferNode); +} + + +void ElementMark::setSecurityId(sal_Int32 nSecurityId) +{ + m_nSecurityId = nSecurityId; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/framework/elementmark.hxx b/xmlsecurity/source/framework/elementmark.hxx new file mode 100644 index 000000000..e035cc1a5 --- /dev/null +++ b/xmlsecurity/source/framework/elementmark.hxx @@ -0,0 +1,70 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_XMLSECURITY_SOURCE_FRAMEWORK_ELEMENTMARK_HXX +#define INCLUDED_XMLSECURITY_SOURCE_FRAMEWORK_ELEMENTMARK_HXX + +#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;} +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/framework/saxeventkeeperimpl.cxx b/xmlsecurity/source/framework/saxeventkeeperimpl.cxx new file mode 100644 index 000000000..cde39d929 --- /dev/null +++ b/xmlsecurity/source/framework/saxeventkeeperimpl.cxx @@ -0,0 +1,1157 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +#define IMPLEMENTATION_NAME "com.sun.star.xml.security.framework.SAXEventKeeperImpl" + +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) + { + 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("[").append(m_xXMLDocument->getNodeName(pParent->getXMLElement())).append("]"); + } + + rc.append(":EC=").append(pBufferNode->printChildren()).append(" BR="); + + ElementMark * pBlocker = pBufferNode->getBlocker(); + if (pBlocker != nullptr) + { + rc.append(OUString::number( pBlocker->getBufferId() )).append("(SecId=") + .append(OUString::number( pBlocker->getSecurityId() )).append(") "); + } + 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()); + + sal_Int32 nIndex = 0; + for( const auto& i : vChildren ) + { + aChildrenCollection[nIndex] = i->getXMLElement(); + nIndex++; + } + + 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()) + { + 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); + + for ( int i = 0; igetNameByIndex(static_cast(i)); + aAttributes[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) + { + 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) + { + 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 IMPLEMENTATION_NAME; +} + +css::uno::Sequence< OUString > SAXEventKeeperImpl_getSupportedServiceNames( ) +{ + css::uno::Sequence aRet { "com.sun.star.xml.crypto.sax.SAXEventKeeper" }; + return aRet; +} + +/* XServiceInfo */ +OUString SAL_CALL SAXEventKeeperImpl::getImplementationName( ) +{ + return SAXEventKeeperImpl_getImplementationName(); +} + +sal_Bool SAL_CALL SAXEventKeeperImpl::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL SAXEventKeeperImpl::getSupportedServiceNames( ) +{ + return SAXEventKeeperImpl_getSupportedServiceNames(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/framework/securityengine.cxx b/xmlsecurity/source/framework/securityengine.cxx new file mode 100644 index 000000000..e276163d4 --- /dev/null +++ b/xmlsecurity/source/framework/securityengine.cxx @@ -0,0 +1,67 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include + + +SecurityEngine::SecurityEngine() + :m_nIdOfTemplateEC(-1), + m_nNumOfResolvedReferences(0), + m_nIdOfKeyEC(-1), + m_bMissionDone(false), + m_nSecurityId(-1), + m_nStatus(css::xml::crypto::SecurityOperationStatus_UNKNOWN) +{ +} + +/* XReferenceResolvedListener */ +void SAL_CALL SecurityEngine::referenceResolved( sal_Int32 /*referenceId*/) +{ + m_nNumOfResolvedReferences++; + tryToPerform(); +} + +/* XKeyCollector */ +void SAL_CALL SecurityEngine::setKeyId( sal_Int32 id ) +{ + m_nIdOfKeyEC = id; + tryToPerform(); +} + +/* XMissionTaker */ +sal_Bool SAL_CALL SecurityEngine::endMission( ) +{ + bool rc = m_bMissionDone; + + if (!rc) + { + clearUp( ); + + notifyResultListener(); + m_bMissionDone = true; + } + + m_xResultListener = nullptr; + m_xSAXEventKeeper = nullptr; + + return rc; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/framework/signaturecreatorimpl.cxx b/xmlsecurity/source/framework/signaturecreatorimpl.cxx new file mode 100644 index 000000000..a3d8cd458 --- /dev/null +++ b/xmlsecurity/source/framework/signaturecreatorimpl.cxx @@ -0,0 +1,178 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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; + +#define IMPLEMENTATION_NAME "com.sun.star.xml.security.framework.SignatureCreatorImpl" + +SignatureCreatorImpl::SignatureCreatorImpl() + : SignatureCreatorImpl_Base(), 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.get()), 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 IMPLEMENTATION_NAME; +} + +css::uno::Sequence< OUString > SignatureCreatorImpl_getSupportedServiceNames( ) +{ + css::uno::Sequence aRet { "com.sun.star.xml.crypto.sax.SignatureCreator" }; + return aRet; +} + +/* XServiceInfo */ +OUString SAL_CALL SignatureCreatorImpl::getImplementationName( ) +{ + return SignatureCreatorImpl_getImplementationName(); +} + +sal_Bool SAL_CALL SignatureCreatorImpl::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL SignatureCreatorImpl::getSupportedServiceNames( ) +{ + return SignatureCreatorImpl_getSupportedServiceNames(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/framework/signatureengine.cxx b/xmlsecurity/source/framework/signatureengine.cxx new file mode 100644 index 000000000..095b2d04d --- /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()) + { + 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 + + +#define IMPLEMENTATION_NAME "com.sun.star.xml.security.framework.SignatureVerifierImpl" + +SignatureVerifierImpl::SignatureVerifierImpl() + : SignatureVerifierImpl_Base() +{ +} + +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.get()), 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 IMPLEMENTATION_NAME; +} + +css::uno::Sequence< OUString > SignatureVerifierImpl_getSupportedServiceNames( ) +{ + css::uno::Sequence aRet { "com.sun.star.xml.crypto.sax.SignatureVerifier" }; + return aRet; +} + +/* XServiceInfo */ +OUString SAL_CALL SignatureVerifierImpl::getImplementationName( ) +{ + return SignatureVerifierImpl_getImplementationName(); +} + +sal_Bool SAL_CALL SignatureVerifierImpl::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +css::uno::Sequence< OUString > SAL_CALL SignatureVerifierImpl::getSupportedServiceNames( ) +{ + return SignatureVerifierImpl_getSupportedServiceNames(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/framework/xmlsignaturetemplateimpl.cxx b/xmlsecurity/source/framework/xmlsignaturetemplateimpl.cxx new file mode 100644 index 000000000..de6cf54cd --- /dev/null +++ b/xmlsecurity/source/framework/xmlsignaturetemplateimpl.cxx @@ -0,0 +1,123 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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() +{ + sal_Int32 length = targets.size(); + css::uno::Sequence< css::uno::Reference< css::xml::wrapper::XXMLElementWrapper > > aTargets (length); + + sal_Int32 i; + + for (i=0; i& 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 000000000..525706e26 --- /dev/null +++ b/xmlsecurity/source/gpg/CertificateImpl.cxx @@ -0,0 +1,270 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.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() : + m_pKey() +{ +} + +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; +} + +/* XUnoTunnel */ +sal_Int64 SAL_CALL CertificateImpl::getSomething(const Sequence< sal_Int8 >& aIdentifier) +{ + if( isUnoTunnelId(aIdentifier) ) { + return sal::static_int_cast(reinterpret_cast(this)); + } + return 0 ; +} + +/* XUnoTunnel extension */ + +namespace +{ + class CertificateImplUnoTunnelId : public rtl::Static< UnoTunnelIdInit, CertificateImplUnoTunnelId > {}; +} + +const Sequence< sal_Int8>& CertificateImpl::getUnoTunnelId() { + return CertificateImplUnoTunnelId::get().getSeq(); +} + +void CertificateImpl::setCertificate(GpgME::Context* ctx, const GpgME::Key& key) +{ + m_pKey = key; + + // extract key data, store into m_aBits + GpgME::Data data_out; + ctx->setArmor(false); // caller will base64-encode anyway + GpgME::Error err = ctx->exportPublicKeys( + key.primaryFingerprint(), + data_out +#if GPGME_CAN_EXPORT_MINIMAL_KEY + , officecfg::Office::Common::Security::OpenPGP::MinimalKeyExport::get() +#endif + ); + + 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 000000000..cb947f0f4 --- /dev/null +++ b/xmlsecurity/source/gpg/CertificateImpl.hxx @@ -0,0 +1,103 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_XMLSECURITY_SOURCE_GPG_X509CERTIFICATE_HXX +#define INCLUDED_XMLSECURITY_SOURCE_GPG_X509CERTIFICATE_HXX + +#include + +#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::XUnoTunnel, + css::lang::XServiceInfo >, + public xmlsecurity::Certificate +{ +private: + GpgME::Key m_pKey; + css::uno::Sequence< sal_Int8 > m_aBits; + +public: + CertificateImpl(); + virtual ~CertificateImpl() override; + + //Methods from XCertificate + virtual sal_Int16 SAL_CALL getVersion() override; + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSerialNumber() override; + + virtual OUString SAL_CALL getIssuerName() override; + virtual OUString SAL_CALL getSubjectName() override; + + virtual css::util::DateTime SAL_CALL getNotValidBefore() override; + virtual css::util::DateTime SAL_CALL getNotValidAfter() override; + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getIssuerUniqueID() override; + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSubjectUniqueID() override; + + virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificateExtension > > SAL_CALL getExtensions() override; + + virtual css::uno::Reference< css::security::XCertificateExtension > SAL_CALL findCertificateExtension(const css::uno::Sequence< sal_Int8 >& oid) override; + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getEncoded() override; + + virtual OUString SAL_CALL getSubjectPublicKeyAlgorithm() override; + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSubjectPublicKeyValue() override; + + virtual OUString SAL_CALL getSignatureAlgorithm() override; + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSHA1Thumbprint() override; + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getMD5Thumbprint() override; + + virtual sal_Int32 SAL_CALL getCertificateUsage() override; + + //Methods from XUnoTunnel + virtual sal_Int64 SAL_CALL getSomething(const css::uno::Sequence< sal_Int8 >& aIdentifier) override; + + static const css::uno::Sequence< sal_Int8 >& getUnoTunnelId(); + + /// @see xmlsecurity::Certificate::getSHA256Thumbprint(). + virtual css::uno::Sequence 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; +} ; + +#endif // INCLUDED_XMLSECURITY_SOURCE_GPG_X509CERTIFICATE_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/gpg/CipherContext.cxx b/xmlsecurity/source/gpg/CipherContext.cxx new file mode 100644 index 000000000..1b16c909d --- /dev/null +++ b/xmlsecurity/source/gpg/CipherContext.cxx @@ -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/. + */ + +#include "CipherContext.hxx" + +using namespace css; +using namespace css::uno; +using namespace css::lang; + +Sequence< sal_Int8 > SAL_CALL CipherContext::convertWithCipherContext( const Sequence< sal_Int8 >& /*aData*/ ) +{ + return Sequence(); +} + +uno::Sequence< sal_Int8 > 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 000000000..4e4e04cce --- /dev/null +++ b/xmlsecurity/source/gpg/CipherContext.hxx @@ -0,0 +1,29 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_XMLSECURITY_SOURCE_GPG_CIPHERCONTEXT_HXX +#define INCLUDED_XMLSECURITY_SOURCE_GPG_CIPHERCONTEXT_HXX + +#include + +#include + +class CipherContext : public cppu::WeakImplHelper< css::xml::crypto::XCipherContext > +{ +private: + +public: + // XCipherContext + virtual css::uno::Sequence< ::sal_Int8 > SAL_CALL convertWithCipherContext(const css::uno::Sequence< ::sal_Int8 >& aData) override; + virtual css::uno::Sequence< ::sal_Int8 > SAL_CALL finalizeCipherContextAndDispose() override; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/gpg/DigestContext.cxx b/xmlsecurity/source/gpg/DigestContext.cxx new file mode 100644 index 000000000..a1bb22ad8 --- /dev/null +++ b/xmlsecurity/source/gpg/DigestContext.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 "DigestContext.hxx" + +using namespace css; +using namespace css::uno; +using namespace css::lang; + + +void SAL_CALL DigestContext::updateDigest(const Sequence< sal_Int8 >& /*aData*/) +{ +} + +uno::Sequence< sal_Int8 > SAL_CALL DigestContext::finalizeDigestAndDispose() +{ + return Sequence(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/gpg/DigestContext.hxx b/xmlsecurity/source/gpg/DigestContext.hxx new file mode 100644 index 000000000..99fa264ef --- /dev/null +++ b/xmlsecurity/source/gpg/DigestContext.hxx @@ -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/. + */ + +#ifndef INCLUDED_XMLSECURITY_SOURCE_GPG_DIGESTCONTEXT_HXX +#define INCLUDED_XMLSECURITY_SOURCE_GPG_DIGESTCONTEXT_HXX + +#include + +#include + +class DigestContext : public cppu::WeakImplHelper< css::xml::crypto::XDigestContext > +{ +public: + // XDigestContext + virtual void SAL_CALL updateDigest( const css::uno::Sequence< ::sal_Int8 >& aData ) override; + virtual css::uno::Sequence< ::sal_Int8 > SAL_CALL finalizeDigestAndDispose() override; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/gpg/SEInitializer.cxx b/xmlsecurity/source/gpg/SEInitializer.cxx new file mode 100644 index 000000000..cb502e8c9 --- /dev/null +++ b/xmlsecurity/source/gpg/SEInitializer.cxx @@ -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/. + */ + +#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< XXMLSecurityContext > SAL_CALL SEInitializerGpg::createSecurityContext( const OUString& ) +{ + try + { + /* Build XML Security Context */ + Reference< XXMLSecurityContext > xSecCtx(new XMLSecurityContextGpg()); + + Reference< XSecurityEnvironment > xSecEnv(new SecurityEnvironmentGpg()); + sal_Int32 n = xSecCtx->addSecurityEnvironment(xSecEnv); + //originally the SecurityEnvironment with the internal slot was set as default + xSecCtx->setDefaultSecurityEnvironmentIndex( n ); + return xSecCtx; + } + catch( const uno::Exception& ) + { + return nullptr; + } +} + +void SAL_CALL SEInitializerGpg::freeSecurityContext( const uno::Reference< XXMLSecurityContext >& ) +{ +} + +/* XServiceInfo */ +sal_Bool SAL_CALL SEInitializerGpg::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +uno::Sequence< OUString > SAL_CALL SEInitializerGpg::getSupportedServiceNames() +{ + return {"com.sun.star.xml.crypto.GPGSEInitializer"}; +} + +OUString SAL_CALL SEInitializerGpg::getImplementationName() +{ + return "com.sun.star.xml.security.SEInitializer_Gpg"; +} + +extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface* +com_sun_star_xml_security_SEInitializer_Gpg_get_implementation( + uno::XComponentContext* /*pCtx*/, uno::Sequence const& /*rSeq*/) +{ + return cppu::acquire(new SEInitializerGpg()); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/gpg/SecurityEnvironment.cxx b/xmlsecurity/source/gpg/SecurityEnvironment.cxx new file mode 100644 index 000000000..290529bc8 --- /dev/null +++ b/xmlsecurity/source/gpg/SecurityEnvironment.cxx @@ -0,0 +1,239 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.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 + +#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("gpgme-w32spawn.exe"); + if (!accessUrl(aPathUrl)) + { + sPath = "$BRAND_BASE_DIR/" LIBO_LIBEXEC_FOLDER "/gpgme-w32spawn.exe"; + rtl::Bootstrap::expandMacros(sPath); + aPathUrl.SetURL(sPath); + if (accessUrl(aPathUrl)) + { + aPathUrl.removeSegment(); + GpgME::setGlobalFlag("w32-inst-dir", + aPathUrl.getFSysPath(FSysStyle::Dos).toUtf8().getStr()); + } + } + return true; + }(); +#endif + GpgME::Error err = GpgME::checkEngine(GpgME::OpenPGP); + if (err) + throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol."); + + m_ctx.reset( GpgME::Context::createForProtocol(GpgME::OpenPGP) ); + if (m_ctx == nullptr) + throw RuntimeException("The GpgME library failed to initialize for the OpenPGP protocol."); + m_ctx->setArmor(false); +} + +SecurityEnvironmentGpg::~SecurityEnvironmentGpg() +{ +} + +/* XUnoTunnel */ +sal_Int64 SAL_CALL SecurityEnvironmentGpg::getSomething( const Sequence< sal_Int8 >& aIdentifier ) +{ + if( isUnoTunnelId(aIdentifier) ) { + return sal::static_int_cast(reinterpret_cast(this)); + } + return 0 ; +} + +/* XUnoTunnel extension */ + +namespace +{ + class theSecurityEnvironmentUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theSecurityEnvironmentUnoTunnelId > {}; +} + +const Sequence< sal_Int8>& SecurityEnvironmentGpg::getUnoTunnelId() { + return theSecurityEnvironmentUnoTunnelId::get().getSeq(); +} + +OUString SecurityEnvironmentGpg::getSecurityEnvironmentInformation() +{ + return OUString(); +} + +Sequence< Reference < XCertificate > > SecurityEnvironmentGpg::getCertificatesImpl( bool bPrivateOnly ) +{ + CertificateImpl* xCert; + std::vector< GpgME::Key > keyList; + std::vector< CertificateImpl* > certsList; + + m_ctx->setKeyListMode(GPGME_KEYLIST_MODE_LOCAL); + GpgME::Error err = m_ctx->startKeyListing("", bPrivateOnly ); + while (!err) { + GpgME::Key k = m_ctx->nextKey(err); + if (err) + break; + if (!k.isRevoked() && !k.isExpired() && !k.isDisabled() && !k.isInvalid()) { + // We can't create CertificateImpl here as CertificateImpl::setCertificate uses GpgME API + // which interrupts our key listing here. So first get the keys from GpgME, then create the CertificateImpls + keyList.push_back(k); + } + } + m_ctx->endKeyListing(); + + for (auto const& key : keyList) { + xCert = new CertificateImpl(); + xCert->setCertificate(m_ctx.get(),key); + certsList.push_back(xCert); + } + + Sequence< Reference< XCertificate > > xCertificateSequence(certsList.size()); + int i = 0; + for (auto const& cert : certsList) { + xCertificateSequence[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*/ ) +{ + CertificateImpl* xCert=nullptr; + + //xmlChar* pSignatureValue=xmlNodeGetContent(cur); + OString ostr = OUStringToOString( keyId , RTL_TEXTENCODING_UTF8 ); + const xmlChar* strKeyId = reinterpret_cast(ostr.getStr()); + if(xmlSecBase64Decode(strKeyId, const_cast(strKeyId), xmlStrlen(strKeyId)) < 0) + throw RuntimeException("Base64 decode failed"); + + m_ctx->setKeyListMode(GPGME_KEYLIST_MODE_LOCAL); + GpgME::Error err = m_ctx->startKeyListing("", false); + while (!err) { + GpgME::Key k = m_ctx->nextKey(err); + if (err) + break; + if (!k.isInvalid() && strcmp(k.primaryFingerprint(), reinterpret_cast(strKeyId)) == 0) { + 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) +{ + const CertificateImpl* xCert; + Reference< XUnoTunnel > xCertTunnel(aCert, UNO_QUERY_THROW) ; + xCert = reinterpret_cast(sal::static_int_cast(xCertTunnel->getSomething(CertificateImpl::getUnoTunnelId()))) ; + if (xCert == nullptr) + throw RuntimeException(); + + // we only listed private keys anyway, up in + // SecurityEnvironmentGpg::getPersonalCertificates + return CertificateCharacters::HAS_PRIVATE_KEY; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/gpg/SecurityEnvironment.hxx b/xmlsecurity/source/gpg/SecurityEnvironment.hxx new file mode 100644 index 000000000..c815e0e1f --- /dev/null +++ b/xmlsecurity/source/gpg/SecurityEnvironment.hxx @@ -0,0 +1,72 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_XMLSECURITY_SOURCE_GPG_SECURITYENVIRONMENT_HXX +#define INCLUDED_XMLSECURITY_SOURCE_GPG_SECURITYENVIRONMENT_HXX + +#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, + css::lang::XUnoTunnel > +{ + 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; + + //Methods from XUnoTunnel + virtual sal_Int64 SAL_CALL getSomething( const css::uno::Sequence< sal_Int8 >& aIdentifier ) override; + + static const css::uno::Sequence< sal_Int8 >& getUnoTunnelId() ; + + virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificate > > SAL_CALL getPersonalCertificates() override; + + /** We reinterpret the first parameter (originally issuerName) as keyId. We have no other way to identify a gpg key. */ + virtual css::uno::Reference< css::security::XCertificate > SAL_CALL getCertificate( const OUString& keyId, const css::uno::Sequence< sal_Int8 >& serialNumber ) override; + + virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificate > > SAL_CALL buildCertificatePath( + const css::uno::Reference< css::security::XCertificate >& beginCert ) override; + + virtual css::uno::Reference< css::security::XCertificate > SAL_CALL createCertificateFromRaw( + const css::uno::Sequence< sal_Int8 >& rawCertificate ) override; + virtual css::uno::Reference< css::security::XCertificate > SAL_CALL createCertificateFromAscii( + const OUString& asciiCertificate ) override; + + GpgME::Context& getGpgContext() { return *m_ctx; } + virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificate > > SAL_CALL getAllCertificates() override; + +private: + css::uno::Sequence< css::uno::Reference< css::security::XCertificate > > getCertificatesImpl( bool bPrivateOnly ); +} ; + +#endif // INCLUDED_XMLSECURITY_SOURCE_GPG_SECURITYENVIRONMENT_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/gpg/XMLEncryption.cxx b/xmlsecurity/source/gpg/XMLEncryption.cxx new file mode 100644 index 000000000..65083ff68 --- /dev/null +++ b/xmlsecurity/source/gpg/XMLEncryption.cxx @@ -0,0 +1,37 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "XMLEncryption.hxx" + +using namespace css::uno; +using namespace css::lang; +using namespace css::xml::wrapper; +using namespace css::xml::crypto; + +XMLEncryptionGpg::XMLEncryptionGpg() { +} + +XMLEncryptionGpg::~XMLEncryptionGpg() { +} + +/* XXMLEncryption */ +Reference< XXMLEncryptionTemplate > SAL_CALL XMLEncryptionGpg::encrypt(const Reference< XXMLEncryptionTemplate >& /*aTemplate*/, + const Reference< XSecurityEnvironment >& /*aEnvironment*/) +{ + return nullptr; +} + +/* XXMLEncryption */ +Reference< XXMLEncryptionTemplate > SAL_CALL XMLEncryptionGpg::decrypt(const Reference< XXMLEncryptionTemplate >& /*aTemplate*/, + const Reference< XXMLSecurityContext >& /*aSecurityCtx*/) +{ + return nullptr; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/gpg/XMLEncryption.hxx b/xmlsecurity/source/gpg/XMLEncryption.hxx new file mode 100644 index 000000000..168128b40 --- /dev/null +++ b/xmlsecurity/source/gpg/XMLEncryption.hxx @@ -0,0 +1,40 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_XMLSECURITY_SOURCE_GPG_XMLENCRYPTION_HXX +#define INCLUDED_XMLSECURITY_SOURCE_GPG_XMLENCRYPTION_HXX + +#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; +}; + +#endif // INCLUDED_XMLSECURITY_SOURCE_GPG_XMLENCRYPTION_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/gpg/XMLSecurityContext.cxx b/xmlsecurity/source/gpg/XMLSecurityContext.cxx new file mode 100644 index 000000000..d27e55282 --- /dev/null +++ b/xmlsecurity/source/gpg/XMLSecurityContext.cxx @@ -0,0 +1,84 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.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 + +using namespace css::uno; +using namespace css::lang; +using namespace css::xml::crypto; + +XMLSecurityContextGpg::XMLSecurityContextGpg() + : m_nDefaultEnvIndex(-1) +{ +} + +XMLSecurityContextGpg::~XMLSecurityContextGpg() +{ +} + +sal_Int32 SAL_CALL XMLSecurityContextGpg::addSecurityEnvironment( + const Reference< XSecurityEnvironment >& aSecurityEnvironment) +{ + if(!aSecurityEnvironment.is()) + throw RuntimeException("Invalid SecurityEnvironment given!"); + + m_vSecurityEnvironments.push_back(aSecurityEnvironment); + return m_vSecurityEnvironments.size() - 1 ; +} + + +sal_Int32 SAL_CALL XMLSecurityContextGpg::getSecurityEnvironmentNumber() +{ + return m_vSecurityEnvironments.size(); +} + +Reference< XSecurityEnvironment > SAL_CALL XMLSecurityContextGpg::getSecurityEnvironmentByIndex(sal_Int32 index) +{ + if (index < 0 || index >= static_cast(m_vSecurityEnvironments.size())) + throw RuntimeException("Invalid index"); + + return m_vSecurityEnvironments[index]; +} + +Reference< XSecurityEnvironment > SAL_CALL XMLSecurityContextGpg::getSecurityEnvironment() +{ + if (m_nDefaultEnvIndex < 0 || m_nDefaultEnvIndex >= static_cast(m_vSecurityEnvironments.size())) + throw RuntimeException("Invalid index"); + + return getSecurityEnvironmentByIndex(m_nDefaultEnvIndex); +} + +sal_Int32 SAL_CALL XMLSecurityContextGpg::getDefaultSecurityEnvironmentIndex() +{ + return m_nDefaultEnvIndex ; +} + +void SAL_CALL XMLSecurityContextGpg::setDefaultSecurityEnvironmentIndex(sal_Int32 nDefaultEnvIndex) +{ + m_nDefaultEnvIndex = nDefaultEnvIndex; +} + +/* XServiceInfo */ +OUString SAL_CALL XMLSecurityContextGpg::getImplementationName() { + return "com.sun.star.xml.security.gpg.XMLSecurityContext_GpgImpl"; +} + +/* XServiceInfo */ +sal_Bool SAL_CALL XMLSecurityContextGpg::supportsService( const OUString& serviceName) { + return cppu::supportsService(this, serviceName); +} + +/* XServiceInfo */ +Sequence< OUString > SAL_CALL XMLSecurityContextGpg::getSupportedServiceNames() { + return { OUString("com.sun.star.xml.crypto.XMLSecurityContext") }; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/gpg/XMLSecurityContext.hxx b/xmlsecurity/source/gpg/XMLSecurityContext.hxx new file mode 100644 index 000000000..3ca399f2b --- /dev/null +++ b/xmlsecurity/source/gpg/XMLSecurityContext.hxx @@ -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/. + */ + +#ifndef INCLUDED_XMLSECURITY_SOURCE_GPG_XMLSECURITYCONTEXT_HXX +#define INCLUDED_XMLSECURITY_SOURCE_GPG_XMLSECURITYCONTEXT_HXX + +#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 ; +} ; + +#endif // INCLUDED_XMLSECURITY_SOURCE_GPG_XMLSECURITYCONTEXT_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/gpg/xmlsignature_gpgimpl.cxx b/xmlsecurity/source/gpg/xmlsignature_gpgimpl.cxx new file mode 100644 index 000000000..3b4e138ae --- /dev/null +++ b/xmlsecurity/source/gpg/xmlsignature_gpgimpl.cxx @@ -0,0 +1,527 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#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); + if(xmlSecBase64Decode(pKey, reinterpret_cast(pKey), xmlStrlen(pKey)) < 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); + int nSigSize = xmlSecBase64Decode(pSignatureValue, reinterpret_cast(pSignatureValue), xmlStrlen(pSignatureValue)); + if( nSigSize < 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); + int nKeyLen = xmlSecBase64Decode(pKeyPacket, reinterpret_cast(pKeyPacket), xmlStrlen(pKeyPacket)); + if( nKeyLen < 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/documentsignaturehelper.cxx b/xmlsecurity/source/helper/documentsignaturehelper.cxx new file mode 100644 index 000000000..482ae6cc4 --- /dev/null +++ b/xmlsecurity/source/helper/documentsignaturehelper.cxx @@ -0,0 +1,592 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace css::xml::sax; + +namespace +{ +OUString getElement(OUString const & version, ::sal_Int32 * index) +{ + while (*index < version.getLength() && version[*index] == '0') { + ++*index; + } + return version.getToken(0, '.', *index); +} + + +// Return 1 if version1 is greater than version 2, 0 if they are equal +//and -1 if version1 is less version 2 +int compareVersions( + OUString const & version1, OUString const & version2) +{ + for (::sal_Int32 i1 = 0, i2 = 0; i1 >= 0 || i2 >= 0;) { + OUString e1(getElement(version1, &i1)); + OUString e2(getElement(version2, &i2)); + if (e1.getLength() < e2.getLength()) { + return -1; + } else if (e1.getLength() > e2.getLength()) { + return 1; + } else if (e1 < e2) { + return -1; + } else if (e1 > e2) { + return 1; + } + } + return 0; +} +} + +static void ImplFillElementList( + std::vector< OUString >& rList, const Reference < css::embed::XStorage >& rxStore, + const OUString& rRootStorageName, const bool bRecursive, + const DocumentSignatureAlgorithm mode) +{ + const Sequence< OUString > aElements = rxStore->getElementNames(); + + for ( const auto& rName : aElements ) + { + if (rName == "[Content_Types].xml") + // OOXML + continue; + + // If the user enabled validating according to OOo 3.0 + // then mimetype and all content of META-INF must be excluded. + if (mode != DocumentSignatureAlgorithm::OOo3_2 + && (rName == "META-INF" || rName == "mimetype")) + { + continue; + } + else + { + OUString sEncName = ::rtl::Uri::encode( + rName, rtl_UriCharClassRelSegment, + rtl_UriEncodeStrict, RTL_TEXTENCODING_UTF8); + if (sEncName.isEmpty() && !rName.isEmpty()) + throw css::uno::RuntimeException("Failed to encode element name of XStorage", nullptr); + + if ( rxStore->isStreamElement( rName ) ) + { + //Exclude documentsignatures.xml! + if (rName == + DocumentSignatureHelper::GetDocumentContentSignatureDefaultStreamName()) + continue; + OUString aFullName( rRootStorageName + sEncName ); + rList.push_back(aFullName); + } + else if ( bRecursive && rxStore->isStorageElement( rName ) ) + { + Reference < css::embed::XStorage > xSubStore = rxStore->openStorageElement( rName, css::embed::ElementModes::READ ); + OUString aFullRootName( rRootStorageName + sEncName + "/" ); + ImplFillElementList(rList, xSubStore, aFullRootName, bRecursive, mode); + } + } + } +} + + +bool DocumentSignatureHelper::isODFPre_1_2(const OUString & sVersion) +{ + //The property version exists only if the document is at least version 1.2 + //That is, if the document has version 1.1 and sVersion is empty. + //The constant is defined in comphelper/documentconstants.hxx + return compareVersions(sVersion, ODFVER_012_TEXT) == -1; +} + +bool DocumentSignatureHelper::isOOo3_2_Signature(const SignatureInformation & sigInfo) +{ + return std::any_of(sigInfo.vSignatureReferenceInfors.cbegin(), + sigInfo.vSignatureReferenceInfors.cend(), + [](const SignatureReferenceInformation& info) { return info.ouURI == "META-INF/manifest.xml"; }); +} + +DocumentSignatureAlgorithm +DocumentSignatureHelper::getDocumentAlgorithm( + const OUString & sODFVersion, const SignatureInformation & sigInfo) +{ + OSL_ASSERT(!sODFVersion.isEmpty()); + DocumentSignatureAlgorithm mode = DocumentSignatureAlgorithm::OOo3_2; + if (!isOOo3_2_Signature(sigInfo)) + { + if (isODFPre_1_2(sODFVersion)) + mode = DocumentSignatureAlgorithm::OOo2; + else + mode = DocumentSignatureAlgorithm::OOo3_0; + } + return mode; +} + +//The function creates a list of files which are to be signed or for which +//the signature is to be validated. The strings are UTF8 encoded URIs which +//contain '/' as path separators. +// +//The algorithm how document signatures are created and validated has +//changed over time. The change affects only which files within the document +//are changed. Document signatures created by OOo 2.x only used particular files. Since +//OOo 3.0 everything except "mimetype" and "META-INF" are signed. As of OOo 3.2 everything +//except META-INF/documentsignatures.xml is signed. +//Signatures are validated according to the algorithm which was then used for validation. +//That is, when validating a signature which was created by OOo 3.0, then mimetype and +//META-INF are not used. +// +//When a signature is created then we always use the latest algorithm. That is, we use +//that of OOo 3.2 +std::vector< OUString > +DocumentSignatureHelper::CreateElementList( + const Reference < css::embed::XStorage >& rxStore, + DocumentSignatureMode eMode, + const DocumentSignatureAlgorithm mode) +{ + std::vector< OUString > aElements; + OUString aSep( "/" ); + + switch ( eMode ) + { + case DocumentSignatureMode::Content: + { + if (mode == DocumentSignatureAlgorithm::OOo2) //that is, ODF 1.0, 1.1 + { + // 1) Main content + ImplFillElementList(aElements, rxStore, OUString(), false, mode); + + // 2) Pictures... + OUString aSubStorageName( "Pictures" ); + try + { + Reference < css::embed::XStorage > xSubStore = rxStore->openStorageElement( aSubStorageName, css::embed::ElementModes::READ ); + ImplFillElementList(aElements, xSubStore, aSubStorageName+aSep, true, mode); + } + catch(css::io::IOException& ) + { + ; // Doesn't have to exist... + } + // 3) OLE... + aSubStorageName = "ObjectReplacements"; + try + { + Reference < css::embed::XStorage > xSubStore = rxStore->openStorageElement( aSubStorageName, css::embed::ElementModes::READ ); + ImplFillElementList(aElements, xSubStore, aSubStorageName+aSep, true, mode); + xSubStore.clear(); + + // Object folders... + 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, rName+aSep, true, mode); + } + } + } + catch( css::io::IOException& ) + { + ; // Doesn't have to exist... + } + } + else + { + // Everything except META-INF + ImplFillElementList(aElements, rxStore, OUString(), 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, 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, 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, aSubStorageName+aSep, true, mode); + } + catch( css::io::IOException& ) + { + ; // Doesn't have to exist... + } + } + break; + case DocumentSignatureMode::Package: + { + // Everything except META-INF + ImplFillElementList(aElements, rxStore, OUString(), 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; + } + uno::Sequence& rDefaults = aContentTypeInfo[0]; + 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 == "/" + 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("." + 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(); + + aHelper.xSignatureStream = aHelper.xSignatureStorage->openStreamElement( aSIGStreamName, nOpenMode ); + } + } + catch(css::io::IOException& ) + { + // Doesn't have to exist... + SAL_WARN_IF( nOpenMode != css::embed::ElementModes::READ, "xmlsecurity.helper", "Error creating signature stream..." ); + } + } + else if(rxStore->hasByName("[Content_Types].xml")) + { + try + { + if (rxStore->hasByName("_xmlsignatures") && (nOpenMode & embed::ElementModes::TRUNCATE)) + // Truncate, then all signatures will be written -> remove previous ones. + rxStore->removeElement("_xmlsignatures"); + + aHelper.xSignatureStorage = rxStore->openStorageElement("_xmlsignatures", nSubStorageOpenMode); + aHelper.nStorageFormat = embed::StorageFormats::OFOPXML; + } + catch (const io::IOException&) + { + TOOLS_WARN_EXCEPTION_IF(nOpenMode != css::embed::ElementModes::READ, "xmlsecurity.helper", "DocumentSignatureHelper::OpenSignatureStream:"); + } + } + + return aHelper; +} + +/** Check whether the current file can be signed with GPG (only ODF >= 1.2 can currently) */ +bool DocumentSignatureHelper::CanSignWithGPG( + const Reference < css::embed::XStorage >& rxStore, + const OUString& sOdfVersion) +{ + if (!rxStore.is()) + return false; + + if (rxStore->hasByName("META-INF")) // ODF + { + return !isODFPre_1_2(sOdfVersion); + } + + return false; +} + + + +//sElementList contains all files which are expected to be signed. Only those files must me signed, +//no more, no less. +//The DocumentSignatureAlgorithm indicates if the document was created with OOo 2.x. Then +//the uri s in the Reference elements in the signature, were not properly encoded. +// For example: +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( + const OUString & rUri, const OUString & 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(rUri.getToken( 0, '/', nIndex )); + + std::vector vPathSegments; + for (sal_Int32 nIndex = 0; nIndex >= 0; ) + vPathSegments.push_back(rPath.getToken( 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 SvXMLAttributeList()); + pAttributeList->AddAttribute("Algorithm", ALGO_XMLDSIGSHA256); + xDocumentHandler->startElement("DigestMethod", uno::Reference(pAttributeList.get())); + xDocumentHandler->endElement("DigestMethod"); +} + +void DocumentSignatureHelper::writeSignedProperties( + const uno::Reference& xDocumentHandler, + const SignatureInformation& signatureInfo, + const OUString& sDate, const bool bWriteSignatureLineData) +{ + { + rtl::Reference pAttributeList(new SvXMLAttributeList()); + pAttributeList->AddAttribute("Id", "idSignedProperties"); + xDocumentHandler->startElement("xd:SignedProperties", uno::Reference(pAttributeList.get())); + } + + xDocumentHandler->startElement("xd:SignedSignatureProperties", uno::Reference(new SvXMLAttributeList())); + xDocumentHandler->startElement("xd:SigningTime", uno::Reference(new SvXMLAttributeList())); + xDocumentHandler->characters(sDate); + xDocumentHandler->endElement("xd:SigningTime"); + xDocumentHandler->startElement("xd:SigningCertificate", uno::Reference(new SvXMLAttributeList())); + xDocumentHandler->startElement("xd:Cert", uno::Reference(new SvXMLAttributeList())); + xDocumentHandler->startElement("xd:CertDigest", uno::Reference(new SvXMLAttributeList())); + writeDigestMethod(xDocumentHandler); + + xDocumentHandler->startElement("DigestValue", uno::Reference(new SvXMLAttributeList())); + // TODO: this is empty for gpg signatures currently + //assert(!signatureInfo.ouCertDigest.isEmpty()); + xDocumentHandler->characters(signatureInfo.ouCertDigest); + xDocumentHandler->endElement("DigestValue"); + + xDocumentHandler->endElement("xd:CertDigest"); + xDocumentHandler->startElement("xd:IssuerSerial", uno::Reference(new SvXMLAttributeList())); + xDocumentHandler->startElement("X509IssuerName", uno::Reference(new SvXMLAttributeList())); + xDocumentHandler->characters(signatureInfo.ouX509IssuerName); + xDocumentHandler->endElement("X509IssuerName"); + xDocumentHandler->startElement("X509SerialNumber", uno::Reference(new SvXMLAttributeList())); + xDocumentHandler->characters(signatureInfo.ouX509SerialNumber); + xDocumentHandler->endElement("X509SerialNumber"); + xDocumentHandler->endElement("xd:IssuerSerial"); + xDocumentHandler->endElement("xd:Cert"); + xDocumentHandler->endElement("xd:SigningCertificate"); + xDocumentHandler->startElement("xd:SignaturePolicyIdentifier", uno::Reference(new SvXMLAttributeList())); + xDocumentHandler->startElement("xd:SignaturePolicyImplied", uno::Reference(new SvXMLAttributeList())); + xDocumentHandler->endElement("xd:SignaturePolicyImplied"); + xDocumentHandler->endElement("xd:SignaturePolicyIdentifier"); + + if (bWriteSignatureLineData && !signatureInfo.ouSignatureLineId.isEmpty() + && signatureInfo.aValidSignatureImage.is() && signatureInfo.aInvalidSignatureImage.is()) + { + rtl::Reference pAttributeList(new SvXMLAttributeList()); + pAttributeList->AddAttribute( + "xmlns:loext", "urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0"); + xDocumentHandler->startElement( + "loext:SignatureLine", + Reference(pAttributeList.get())); + + { + // Write SignatureLineId element + xDocumentHandler->startElement( + "loext:SignatureLineId", + Reference(new SvXMLAttributeList())); + xDocumentHandler->characters(signatureInfo.ouSignatureLineId); + xDocumentHandler->endElement("loext:SignatureLineId"); + } + + { + // Write SignatureLineValidImage element + xDocumentHandler->startElement( + "loext:SignatureLineValidImage", + Reference(new SvXMLAttributeList())); + + OUString aGraphicInBase64; + Graphic aGraphic(signatureInfo.aValidSignatureImage); + if (!XOutBitmap::GraphicToBase64(aGraphic, aGraphicInBase64, false)) + SAL_WARN("xmlsecurity.helper", "could not convert graphic to base64"); + + xDocumentHandler->characters(aGraphicInBase64); + xDocumentHandler->endElement("loext:SignatureLineValidImage"); + } + + { + // Write SignatureLineInvalidImage element + xDocumentHandler->startElement( + "loext:SignatureLineInvalidImage", + Reference(new SvXMLAttributeList())); + OUString aGraphicInBase64; + Graphic aGraphic(signatureInfo.aInvalidSignatureImage); + if (!XOutBitmap::GraphicToBase64(aGraphic, aGraphicInBase64, false)) + SAL_WARN("xmlsecurity.helper", "could not convert graphic to base64"); + xDocumentHandler->characters(aGraphicInBase64); + xDocumentHandler->endElement("loext:SignatureLineInvalidImage"); + } + + xDocumentHandler->endElement("loext:SignatureLine"); + } + + xDocumentHandler->endElement("xd:SignedSignatureProperties"); + + xDocumentHandler->endElement("xd:SignedProperties"); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/helper/documentsignaturemanager.cxx b/xmlsecurity/source/helper/documentsignaturemanager.cxx new file mode 100644 index 000000000..79d2cdf26 --- /dev/null +++ b/xmlsecurity/source/helper/documentsignaturemanager.cxx @@ -0,0 +1,687 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +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(const OUString& rURI) +{ + SAL_WARN_IF(!mxStore.is(), "xmlsecurity.helper", "empty storage reference"); + + bool bIsXML = false; + bool bPropsAvailable = false; + const OUString sPropFullPath("FullPath"); + const OUString sPropMediaType("MediaType"); + const OUString sPropDigest("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. + sal_Int32 nSep = rURI.lastIndexOf('.'); + if (nSep != -1) + { + OUString aExt = rURI.copy(nSep + 1); + if (aExt.equalsIgnoreAsciiCase("XML")) + bIsXML = true; + } + } + return bIsXML; +} + +//If bTempStream is true, then a temporary stream is return. If it is false then, the actual +//signature stream is used. +//Every time the user presses Add a new temporary stream is created. +//We keep the temporary stream as member because ImplGetSignatureInformations +//will later access the stream to create DocumentSignatureInformation objects +//which are stored in maCurrentSignatureInformations. +SignatureStreamHelper DocumentSignatureManager::ImplOpenSignatureStream(sal_Int32 nStreamOpenMode, + bool bTempStream) +{ + SignatureStreamHelper aHelper; + if (mxStore.is() && mxStore->hasByName("[Content_Types].xml")) + aHelper.nStorageFormat = embed::StorageFormats::OFOPXML; + + if (bTempStream) + { + if (nStreamOpenMode & embed::ElementModes::TRUNCATE) + { + //We write always into a new temporary stream. + mxTempSignatureStream.set(io::TempFile::create(mxContext), uno::UNO_QUERY_THROW); + if (aHelper.nStorageFormat != embed::StorageFormats::OFOPXML) + aHelper.xSignatureStream = mxTempSignatureStream; + else + { + mxTempSignatureStorage = comphelper::OStorageHelper::GetStorageOfFormatFromStream( + ZIP_STORAGE_FORMAT_STRING, mxTempSignatureStream); + aHelper.xSignatureStorage = mxTempSignatureStorage; + } + } + else + { + //When we read from the temp stream, then we must have previously + //created one. + SAL_WARN_IF(!mxTempSignatureStream.is(), "xmlsecurity.helper", + "empty temp. signature stream reference"); + } + aHelper.xSignatureStream = mxTempSignatureStream; + if (aHelper.nStorageFormat == embed::StorageFormats::OFOPXML) + aHelper.xSignatureStorage = mxTempSignatureStorage; + } + else + { + //No temporary stream + if (!mxSignatureStream.is()) + { + //We may not have a dedicated stream for writing the signature + //So we take one directly from the storage + //Or DocumentDigitalSignatures::showDocumentContentSignatures was called, + //in which case Add/Remove is not allowed. This is done, for example, if the + //document is readonly + aHelper = DocumentSignatureHelper::OpenSignatureStream(mxStore, nStreamOpenMode, + meSignatureMode); + } + else + { + aHelper.xSignatureStream = mxSignatureStream; + } + } + + if (nStreamOpenMode & embed::ElementModes::TRUNCATE) + { + if (aHelper.xSignatureStream.is() + && aHelper.nStorageFormat != embed::StorageFormats::OFOPXML) + { + uno::Reference 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(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(); + + 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; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/helper/ooxmlsecexporter.cxx b/xmlsecurity/source/helper/ooxmlsecexporter.cxx new file mode 100644 index 000000000..fe4d0df89 --- /dev/null +++ b/xmlsecurity/source/helper/ooxmlsecexporter.cxx @@ -0,0 +1,546 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.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 + +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 isOOXMLBlacklist(const OUString& rStreamName); + /// Should we intentionally not sign this relation type? + static bool isOOXMLRelationBlacklist(const OUString& rRelationName); + + const uno::Reference& getDocumentHandler() const + { + return m_xDocumentHandler; + } + + 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::isOOXMLBlacklist(const OUString& rStreamName) +{ + static const std::initializer_list vBlacklist + = { "/%5BContent_Types%5D.xml", "/docProps/app.xml", "/docProps/core.xml", + // Don't attempt to sign other signatures for now. + "/_xmlsignatures" }; + // Just check the prefix, as we don't care about the content type part of the stream name. + return std::any_of(vBlacklist.begin(), vBlacklist.end(), [&](const OUStringLiteral& rLiteral) { + return rStreamName.startsWith(rLiteral); + }); +} + +bool OOXMLSecExporter::Impl::isOOXMLRelationBlacklist(const OUString& rRelationName) +{ + static const std::initializer_list vBlacklist = { + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties", + "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties", + "http://schemas.openxmlformats.org/package/2006/relationships/digital-signature/origin" + }; + return std::find(vBlacklist.begin(), vBlacklist.end(), rRelationName) != vBlacklist.end(); +} + +void OOXMLSecExporter::Impl::writeSignedInfo() +{ + m_xDocumentHandler->startElement( + "SignedInfo", uno::Reference(new SvXMLAttributeList())); + + writeCanonicalizationMethod(); + writeSignatureMethod(); + writeSignedInfoReferences(); + + m_xDocumentHandler->endElement("SignedInfo"); +} + +void OOXMLSecExporter::Impl::writeCanonicalizationMethod() +{ + rtl::Reference pAttributeList(new SvXMLAttributeList()); + pAttributeList->AddAttribute("Algorithm", ALGO_C14N); + m_xDocumentHandler->startElement( + "CanonicalizationMethod", uno::Reference(pAttributeList.get())); + m_xDocumentHandler->endElement("CanonicalizationMethod"); +} + +void OOXMLSecExporter::Impl::writeCanonicalizationTransform() +{ + rtl::Reference pAttributeList(new SvXMLAttributeList()); + pAttributeList->AddAttribute("Algorithm", ALGO_C14N); + m_xDocumentHandler->startElement( + "Transform", uno::Reference(pAttributeList.get())); + m_xDocumentHandler->endElement("Transform"); +} + +void OOXMLSecExporter::Impl::writeSignatureMethod() +{ + rtl::Reference pAttributeList(new SvXMLAttributeList()); + + if (m_rInformation.eAlgorithmID == svl::crypto::SignatureMethodAlgorithm::ECDSA) + pAttributeList->AddAttribute("Algorithm", ALGO_ECDSASHA256); + else + pAttributeList->AddAttribute("Algorithm", ALGO_RSASHA256); + + m_xDocumentHandler->startElement( + "SignatureMethod", uno::Reference(pAttributeList.get())); + 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 SvXMLAttributeList()); + if (rReference.ouURI != "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.get())); + } + if (rReference.ouURI == "idSignedProperties") + { + m_xDocumentHandler->startElement( + "Transforms", + uno::Reference(new SvXMLAttributeList())); + writeCanonicalizationTransform(); + m_xDocumentHandler->endElement("Transforms"); + } + + DocumentSignatureHelper::writeDigestMethod(m_xDocumentHandler); + m_xDocumentHandler->startElement( + "DigestValue", uno::Reference(new SvXMLAttributeList())); + m_xDocumentHandler->characters(rReference.ouDigestValue); + m_xDocumentHandler->endElement("DigestValue"); + m_xDocumentHandler->endElement("Reference"); + } + } +} + +void OOXMLSecExporter::Impl::writeSignatureValue() +{ + m_xDocumentHandler->startElement( + "SignatureValue", uno::Reference(new SvXMLAttributeList())); + m_xDocumentHandler->characters(m_rInformation.ouSignatureValue); + m_xDocumentHandler->endElement("SignatureValue"); +} + +void OOXMLSecExporter::Impl::writeKeyInfo() +{ + m_xDocumentHandler->startElement( + "KeyInfo", uno::Reference(new SvXMLAttributeList())); + m_xDocumentHandler->startElement( + "X509Data", uno::Reference(new SvXMLAttributeList())); + m_xDocumentHandler->startElement( + "X509Certificate", uno::Reference(new SvXMLAttributeList())); + m_xDocumentHandler->characters(m_rInformation.ouX509Certificate); + m_xDocumentHandler->endElement("X509Certificate"); + m_xDocumentHandler->endElement("X509Data"); + m_xDocumentHandler->endElement("KeyInfo"); +} + +void OOXMLSecExporter::Impl::writePackageObject() +{ + rtl::Reference pAttributeList(new SvXMLAttributeList()); + pAttributeList->AddAttribute("Id", "idPackageObject"); + m_xDocumentHandler->startElement( + "Object", uno::Reference(pAttributeList.get())); + + writeManifest(); + writePackageObjectSignatureProperties(); + + m_xDocumentHandler->endElement("Object"); +} + +void OOXMLSecExporter::Impl::writeManifest() +{ + m_xDocumentHandler->startElement( + "Manifest", uno::Reference(new SvXMLAttributeList())); + const SignatureReferenceInformations& rReferences = m_rInformation.vSignatureReferenceInfors; + for (const SignatureReferenceInformation& rReference : rReferences) + { + if (rReference.nType != SignatureReferenceType::SAMEDOCUMENT) + { + if (OOXMLSecExporter::Impl::isOOXMLBlacklist(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 SvXMLAttributeList()); + pAttributeList->AddAttribute("Algorithm", ALGO_RELATIONSHIP); + m_xDocumentHandler->startElement( + "Transform", uno::Reference(pAttributeList.get())); + } + + 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::isOOXMLRelationBlacklist(aType)) + continue; + + rtl::Reference pAttributeList(new SvXMLAttributeList()); + pAttributeList->AddAttribute("xmlns:mdssi", NS_MDSSI); + pAttributeList->AddAttribute("SourceId", aId); + m_xDocumentHandler->startElement( + "mdssi:RelationshipReference", + uno::Reference(pAttributeList.get())); + m_xDocumentHandler->endElement("mdssi:RelationshipReference"); + } + + m_xDocumentHandler->endElement("Transform"); +} + +void OOXMLSecExporter::Impl::writePackageObjectSignatureProperties() +{ + m_xDocumentHandler->startElement( + "SignatureProperties", uno::Reference(new SvXMLAttributeList())); + { + rtl::Reference pAttributeList(new SvXMLAttributeList()); + pAttributeList->AddAttribute("Id", "idSignatureTime"); + pAttributeList->AddAttribute("Target", "#idPackageSignature"); + m_xDocumentHandler->startElement( + "SignatureProperty", uno::Reference(pAttributeList.get())); + } + { + rtl::Reference pAttributeList(new SvXMLAttributeList()); + pAttributeList->AddAttribute("xmlns:mdssi", NS_MDSSI); + m_xDocumentHandler->startElement( + "mdssi:SignatureTime", uno::Reference(pAttributeList.get())); + } + m_xDocumentHandler->startElement( + "mdssi:Format", uno::Reference(new SvXMLAttributeList())); + m_xDocumentHandler->characters("YYYY-MM-DDThh:mm:ssTZD"); + m_xDocumentHandler->endElement("mdssi:Format"); + + m_xDocumentHandler->startElement( + "mdssi:Value", uno::Reference(new SvXMLAttributeList())); + if (!m_rInformation.ouDateTime.isEmpty()) + m_aSignatureTimeValue = m_rInformation.ouDateTime; + else + { + m_aSignatureTimeValue = utl::toISO8601(m_rInformation.stDateTime); + // Ignore sub-seconds. + sal_Int32 nCommaPos = m_aSignatureTimeValue.indexOf(','); + if (nCommaPos != -1) + { + m_aSignatureTimeValue = m_aSignatureTimeValue.copy(0, nCommaPos); + m_aSignatureTimeValue += "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 SvXMLAttributeList()); + pAttributeList->AddAttribute("URI", rReference.ouURI); + m_xDocumentHandler->startElement( + "Reference", uno::Reference(pAttributeList.get())); + + // 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 SvXMLAttributeList())); + + writeRelationshipTransform(aURI); + writeCanonicalizationTransform(); + + m_xDocumentHandler->endElement("Transforms"); + } + + DocumentSignatureHelper::writeDigestMethod(m_xDocumentHandler); + m_xDocumentHandler->startElement( + "DigestValue", uno::Reference(new SvXMLAttributeList())); + m_xDocumentHandler->characters(rReference.ouDigestValue); + m_xDocumentHandler->endElement("DigestValue"); + m_xDocumentHandler->endElement("Reference"); +} + +void OOXMLSecExporter::Impl::writeOfficeObject() +{ + { + rtl::Reference pAttributeList(new SvXMLAttributeList()); + pAttributeList->AddAttribute("Id", "idOfficeObject"); + m_xDocumentHandler->startElement( + "Object", uno::Reference(pAttributeList.get())); + } + m_xDocumentHandler->startElement( + "SignatureProperties", uno::Reference(new SvXMLAttributeList())); + { + rtl::Reference pAttributeList(new SvXMLAttributeList()); + pAttributeList->AddAttribute("Id", "idOfficeV1Details"); + pAttributeList->AddAttribute("Target", "#idPackageSignature"); + m_xDocumentHandler->startElement( + "SignatureProperty", uno::Reference(pAttributeList.get())); + } + writeSignatureInfo(); + m_xDocumentHandler->endElement("SignatureProperty"); + m_xDocumentHandler->endElement("SignatureProperties"); + m_xDocumentHandler->endElement("Object"); +} + +void OOXMLSecExporter::Impl::writeSignatureInfo() +{ + rtl::Reference pAttributeList(new SvXMLAttributeList()); + pAttributeList->AddAttribute("xmlns", "http://schemas.microsoft.com/office/2006/digsig"); + m_xDocumentHandler->startElement( + "SignatureInfoV1", uno::Reference(pAttributeList.get())); + + m_xDocumentHandler->startElement( + "SetupID", uno::Reference(new SvXMLAttributeList())); + m_xDocumentHandler->characters(m_rInformation.ouSignatureLineId); + m_xDocumentHandler->endElement("SetupID"); + m_xDocumentHandler->startElement( + "SignatureText", uno::Reference(new SvXMLAttributeList())); + m_xDocumentHandler->endElement("SignatureText"); + m_xDocumentHandler->startElement( + "SignatureImage", uno::Reference(new SvXMLAttributeList())); + m_xDocumentHandler->endElement("SignatureImage"); + m_xDocumentHandler->startElement( + "SignatureComments", uno::Reference(new SvXMLAttributeList())); + m_xDocumentHandler->characters(m_rInformation.ouDescription); + m_xDocumentHandler->endElement("SignatureComments"); + // Just hardcode something valid according to [MS-OFFCRYPTO]. + m_xDocumentHandler->startElement( + "WindowsVersion", uno::Reference(new SvXMLAttributeList())); + m_xDocumentHandler->characters("6.1"); + m_xDocumentHandler->endElement("WindowsVersion"); + m_xDocumentHandler->startElement( + "OfficeVersion", uno::Reference(new SvXMLAttributeList())); + m_xDocumentHandler->characters("16.0"); + m_xDocumentHandler->endElement("OfficeVersion"); + m_xDocumentHandler->startElement( + "ApplicationVersion", uno::Reference(new SvXMLAttributeList())); + m_xDocumentHandler->characters("16.0"); + m_xDocumentHandler->endElement("ApplicationVersion"); + m_xDocumentHandler->startElement( + "Monitors", uno::Reference(new SvXMLAttributeList())); + m_xDocumentHandler->characters("1"); + m_xDocumentHandler->endElement("Monitors"); + m_xDocumentHandler->startElement( + "HorizontalResolution", uno::Reference(new SvXMLAttributeList())); + m_xDocumentHandler->characters("1280"); + m_xDocumentHandler->endElement("HorizontalResolution"); + m_xDocumentHandler->startElement( + "VerticalResolution", uno::Reference(new SvXMLAttributeList())); + m_xDocumentHandler->characters("800"); + m_xDocumentHandler->endElement("VerticalResolution"); + m_xDocumentHandler->startElement( + "ColorDepth", uno::Reference(new SvXMLAttributeList())); + m_xDocumentHandler->characters("32"); + m_xDocumentHandler->endElement("ColorDepth"); + m_xDocumentHandler->startElement( + "SignatureProviderId", uno::Reference(new SvXMLAttributeList())); + m_xDocumentHandler->characters("{00000000-0000-0000-0000-000000000000}"); + m_xDocumentHandler->endElement("SignatureProviderId"); + m_xDocumentHandler->startElement( + "SignatureProviderUrl", uno::Reference(new SvXMLAttributeList())); + m_xDocumentHandler->endElement("SignatureProviderUrl"); + m_xDocumentHandler->startElement( + "SignatureProviderDetails", + uno::Reference(new SvXMLAttributeList())); + m_xDocumentHandler->characters( + "9"); // This is what MSO 2016 writes, though [MS-OFFCRYPTO] doesn't document what the value means. + m_xDocumentHandler->endElement("SignatureProviderDetails"); + m_xDocumentHandler->startElement( + "SignatureType", uno::Reference(new SvXMLAttributeList())); + m_xDocumentHandler->characters("2"); + m_xDocumentHandler->endElement("SignatureType"); + + m_xDocumentHandler->endElement("SignatureInfoV1"); +} + +void OOXMLSecExporter::Impl::writePackageSignature() +{ + m_xDocumentHandler->startElement( + "Object", uno::Reference(new SvXMLAttributeList())); + { + rtl::Reference pAttributeList(new SvXMLAttributeList()); + pAttributeList->AddAttribute("xmlns:xd", NS_XD); + pAttributeList->AddAttribute("Target", "#idPackageSignature"); + m_xDocumentHandler->startElement( + "xd:QualifyingProperties", + uno::Reference(pAttributeList.get())); + } + + 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 SvXMLAttributeList()); + pAttributeList->AddAttribute("Id", "idValidSigLnImg"); + m_xDocumentHandler->startElement( + "Object", uno::Reference(pAttributeList.get())); + 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()) + { + rtl::Reference pAttributeList(new SvXMLAttributeList()); + pAttributeList->AddAttribute("Id", "idInvalidSigLnImg"); + m_xDocumentHandler->startElement( + "Object", uno::Reference(pAttributeList.get())); + 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"); + } +} + +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() +{ + rtl::Reference pAttributeList(new SvXMLAttributeList()); + pAttributeList->AddAttribute("xmlns", NS_XMLDSIG); + pAttributeList->AddAttribute("Id", "idPackageSignature"); + m_pImpl->getDocumentHandler()->startElement( + "Signature", uno::Reference(pAttributeList.get())); + + m_pImpl->writeSignedInfo(); + m_pImpl->writeSignatureValue(); + m_pImpl->writeKeyInfo(); + m_pImpl->writePackageObject(); + m_pImpl->writeOfficeObject(); + m_pImpl->writePackageSignature(); + m_pImpl->writeSignatureLineImages(); + + m_pImpl->getDocumentHandler()->endElement("Signature"); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/helper/ooxmlsecexporter.hxx b/xmlsecurity/source/helper/ooxmlsecexporter.hxx new file mode 100644 index 000000000..5d94da2fd --- /dev/null +++ b/xmlsecurity/source/helper/ooxmlsecexporter.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/. + */ + +#ifndef INCLUDED_XMLSECURITY_SOURCE_HELPER_OOXMLSECEXPORTER_HXX +#define INCLUDED_XMLSECURITY_SOURCE_HELPER_OOXMLSECEXPORTER_HXX + +#include + +#include + +namespace com +{ +namespace sun +{ +namespace star +{ +namespace embed +{ +class XStorage; +} +namespace uno +{ +class XComponentContext; +} +namespace xml +{ +namespace 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(); +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/helper/ooxmlsecparser.cxx b/xmlsecurity/source/helper/ooxmlsecparser.cxx new file mode 100644 index 000000000..c22e8c226 --- /dev/null +++ b/xmlsecurity/source/helper/ooxmlsecparser.cxx @@ -0,0 +1,293 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.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 + +using namespace com::sun::star; + +OOXMLSecParser::OOXMLSecParser(XMLSignatureHelper& rXMLSignatureHelper, XSecController* pXSecController) + : m_pXSecController(pXSecController) + ,m_bInDigestValue(false) + ,m_bInSignatureValue(false) + ,m_bInX509Certificate(false) + ,m_bInMdssiValue(false) + ,m_bInSignatureComments(false) + ,m_bInX509IssuerName(false) + ,m_bInX509SerialNumber(false) + ,m_bInCertDigest(false) + ,m_bInValidSignatureImage(false) + ,m_bInInvalidSignatureImage(false) + ,m_bInSignatureLineId(false) + ,m_bReferenceUnresolved(false) + ,m_rXMLSignatureHelper(rXMLSignatureHelper) +{ +} + +OOXMLSecParser::~OOXMLSecParser() +{ +} + +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) +{ + OUString aId = xAttribs->getValueByName("Id"); + if (!aId.isEmpty()) + m_pXSecController->collectToVerify(aId); + + if (rName == "Signature") + { + m_rXMLSignatureHelper.StartVerifySignatureElement(); + m_pXSecController->addSignature(); + if (!aId.isEmpty()) + m_pXSecController->setId(aId); + } + else if (rName == "SignatureMethod") + { + OUString ouAlgorithm = xAttribs->getValueByName("Algorithm"); + if (ouAlgorithm == ALGO_ECDSASHA1 || ouAlgorithm == ALGO_ECDSASHA256 + || ouAlgorithm == ALGO_ECDSASHA512) + m_pXSecController->setSignatureMethod(svl::crypto::SignatureMethodAlgorithm::ECDSA); + } + else if (rName == "Reference") + { + OUString aURI = xAttribs->getValueByName("URI"); + if (aURI.startsWith("#")) + m_pXSecController->addReference(aURI.copy(1), xml::crypto::DigestID::SHA1, OUString()); + else + { + m_aReferenceURI = aURI; + m_bReferenceUnresolved = true; + } + } + else if (rName == "Transform") + { + if (m_bReferenceUnresolved) + { + OUString aAlgorithm = xAttribs->getValueByName("Algorithm"); + if (aAlgorithm == ALGO_RELATIONSHIP) + { + m_pXSecController->addStreamReference(m_aReferenceURI, /*isBinary=*/false, /*nDigestID=*/xml::crypto::DigestID::SHA256); + m_bReferenceUnresolved = false; + } + } + } + else if (rName == "DigestValue" && !m_bInCertDigest) + { + m_aDigestValue.clear(); + m_bInDigestValue = true; + } + else if (rName == "SignatureValue") + { + m_aSignatureValue.clear(); + m_bInSignatureValue = true; + } + else if (rName == "X509Certificate") + { + m_aX509Certificate.clear(); + m_bInX509Certificate = true; + } + else if (rName == "mdssi:Value") + { + m_aMdssiValue.clear(); + m_bInMdssiValue = true; + } + else if (rName == "SignatureComments") + { + m_aSignatureComments.clear(); + m_bInSignatureComments = true; + } + else if (rName == "X509IssuerName") + { + m_aX509IssuerName.clear(); + m_bInX509IssuerName = true; + } + else if (rName == "X509SerialNumber") + { + m_aX509SerialNumber.clear(); + m_bInX509SerialNumber = true; + } + else if (rName == "xd:CertDigest") + { + m_aCertDigest.clear(); + m_bInCertDigest = true; + } + else if (rName == "Object") + { + OUString sId = xAttribs->getValueByName("Id"); + if (sId == "idValidSigLnImg") + { + m_aValidSignatureImage.clear(); + m_bInValidSignatureImage = true; + } + else if (sId == "idInvalidSigLnImg") + { + m_aInvalidSignatureImage.clear(); + m_bInInvalidSignatureImage = true; + } + else + { + SAL_INFO("xmlsecurity.ooxml", "Unknown 'Object' child element: " << rName); + } + } + else if (rName == "SetupID") + { + m_aSignatureLineId.clear(); + m_bInSignatureLineId = true; + } + else + { + SAL_INFO("xmlsecurity.ooxml", "Unknown xml element: " << rName); + } + + if (m_xNextHandler.is()) + m_xNextHandler->startElement(rName, xAttribs); +} + +void SAL_CALL OOXMLSecParser::endElement(const OUString& rName) +{ + if (rName == "SignedInfo") + m_pXSecController->setReferenceCount(); + else if (rName == "Reference") + { + if (m_bReferenceUnresolved) + { + // No transform algorithm found, assume binary. + m_pXSecController->addStreamReference(m_aReferenceURI, /*isBinary=*/true, /*nDigestID=*/xml::crypto::DigestID::SHA256); + m_bReferenceUnresolved = false; + } + m_pXSecController->setDigestValue(xml::crypto::DigestID::SHA256, m_aDigestValue); + } + else if (rName == "DigestValue" && !m_bInCertDigest) + m_bInDigestValue = false; + else if (rName == "SignatureValue") + { + m_pXSecController->setSignatureValue(m_aSignatureValue); + m_bInSignatureValue = false; + } + else if (rName == "X509Certificate") + { + m_pXSecController->setX509Certificate(m_aX509Certificate); + m_bInX509Certificate = false; + } + else if (rName == "mdssi:Value") + { + m_pXSecController->setDate(m_aMdssiValue); + m_bInMdssiValue = false; + } + else if (rName == "SignatureComments") + { + m_pXSecController->setDescription(m_aSignatureComments); + m_bInSignatureComments = false; + } + else if (rName == "X509IssuerName") + { + m_pXSecController->setX509IssuerName(m_aX509IssuerName); + m_bInX509IssuerName = false; + } + else if (rName == "X509SerialNumber") + { + m_pXSecController->setX509SerialNumber(m_aX509SerialNumber); + m_bInX509SerialNumber = false; + } + else if (rName == "xd:CertDigest") + { + m_pXSecController->setCertDigest(m_aCertDigest); + m_bInCertDigest = false; + } + else if (rName == "Object") + { + if (m_bInValidSignatureImage) + { + m_pXSecController->setValidSignatureImage(m_aValidSignatureImage); + m_bInValidSignatureImage = false; + } + else if (m_bInInvalidSignatureImage) + { + m_pXSecController->setInvalidSignatureImage(m_aInvalidSignatureImage); + m_bInInvalidSignatureImage = false; + } + } + else if (rName == "SetupID") + { + m_pXSecController->setSignatureLineId(m_aSignatureLineId); + m_bInSignatureLineId = false; + } + + if (m_xNextHandler.is()) + m_xNextHandler->endElement(rName); +} + +void SAL_CALL OOXMLSecParser::characters(const OUString& rChars) +{ + if (m_bInDigestValue && !m_bInCertDigest) + m_aDigestValue += rChars; + else if (m_bInSignatureValue) + m_aSignatureValue += rChars; + else if (m_bInX509Certificate) + m_aX509Certificate += rChars; + else if (m_bInMdssiValue) + m_aMdssiValue += rChars; + else if (m_bInSignatureComments) + m_aSignatureComments += rChars; + else if (m_bInX509IssuerName) + m_aX509IssuerName += rChars; + else if (m_bInX509SerialNumber) + m_aX509SerialNumber += rChars; + else if (m_bInCertDigest) + m_aCertDigest += rChars; + else if (m_bInValidSignatureImage) + m_aValidSignatureImage += rChars; + else if (m_bInInvalidSignatureImage) + m_aInvalidSignatureImage += rChars; + else if (m_bInSignatureLineId) + m_aSignatureLineId += 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 000000000..d3c199147 --- /dev/null +++ b/xmlsecurity/source/helper/ooxmlsecparser.hxx @@ -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/. + */ + +#ifndef INCLUDED_XMLSECURITY_SOURCE_HELPER_OOXMLSECPARSER_HXX +#define INCLUDED_XMLSECURITY_SOURCE_HELPER_OOXMLSECPARSER_HXX + +#include +#include + +#include + +class XSecController; +class XMLSignatureHelper; + +/// Parses an OOXML digital signature. +class OOXMLSecParser: public cppu::WeakImplHelper + < + css::xml::sax::XDocumentHandler, + css::lang::XInitialization + > +{ + XSecController* m_pXSecController; + css::uno::Reference m_xNextHandler; + + bool m_bInDigestValue; + OUString m_aDigestValue; + bool m_bInSignatureValue; + OUString m_aSignatureValue; + bool m_bInX509Certificate; + OUString m_aX509Certificate; + bool m_bInMdssiValue; + OUString m_aMdssiValue; + bool m_bInSignatureComments; + OUString m_aSignatureComments; + bool m_bInX509IssuerName; + OUString m_aX509IssuerName; + bool m_bInX509SerialNumber; + OUString m_aX509SerialNumber; + bool m_bInCertDigest; + OUString m_aCertDigest; + bool m_bInValidSignatureImage; + OUString m_aValidSignatureImage; + bool m_bInInvalidSignatureImage; + OUString m_aInvalidSignatureImage; + bool m_bInSignatureLineId; + OUString m_aSignatureLineId; + + /// Last seen . + OUString m_aReferenceURI; + /// Already called addStreamReference() for this reference. + bool m_bReferenceUnresolved; + XMLSignatureHelper& m_rXMLSignatureHelper; + +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; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/helper/pdfsignaturehelper.cxx b/xmlsecurity/source/helper/pdfsignaturehelper.cxx new file mode 100644 index 000000000..b0795cb8f --- /dev/null +++ b/xmlsecurity/source/helper/pdfsignaturehelper.cxx @@ -0,0 +1,187 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.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 + +using namespace ::com::sun::star; + +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)); + vcl::filter::PDFDocument aDocument; + if (!aDocument.Read(*pStream)) + { + SAL_WARN("xmlsecurity.helper", "failed to read the document"); + return false; + } + + std::vector aSignatures = aDocument.GetSignatureWidgets(); + if (aSignatures.empty()) + return true; + + m_aSignatureInfos.clear(); + + int nMDPPerm = aDocument.GetMDPPerm(); + + for (size_t i = 0; i < aSignatures.size(); ++i) + { + SignatureInformation aInfo(i); + + if (!xmlsecurity::pdfio::ValidateSignature(*pStream, aSignatures[i], aInfo, aDocument, + nMDPPerm)) + 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()); + + for (size_t i = 0; i < m_aSignatureInfos.size(); ++i) + { + const SignatureInformation& rInternal = m_aSignatureInfos[i]; + security::DocumentSignatureInformation& rExternal = aRet[i]; + rExternal.SignatureIsValid + = rInternal.nStatus == xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED; + if (!rInternal.ouX509Certificate.isEmpty()) + rExternal.Signer = xSecEnv->createCertificateFromAscii(rInternal.ouX509Certificate); + 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& 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; + } + + 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 000000000..6ec834053 --- /dev/null +++ b/xmlsecurity/source/helper/xmlsignaturehelper.cxx @@ -0,0 +1,549 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +#define NS_DOCUMENTSIGNATURES "http://openoffice.org/2004/documentsignatures" +#define NS_DOCUMENTSIGNATURES_ODF_1_2 "urn:oasis:names:tc:opendocument:xmlns:digitalsignature:1.0" +#define OOXML_SIGNATURE_ORIGIN "http://schemas.openxmlformats.org/package/2006/relationships/digital-signature/origin" +#define OOXML_SIGNATURE_SIGNATURE "http://schemas.openxmlformats.org/package/2006/relationships/digital-signature/signature" + +using namespace ::com::sun::star; +using namespace ::com::sun::star::graphic; +using namespace ::com::sun::star::uno; + +XMLSignatureHelper::XMLSignatureHelper( const uno::Reference< uno::XComponentContext >& rxCtx) + : mxCtx(rxCtx), mbODFPre1_2(false) +{ + mpXSecController = new XSecController(rxCtx); + mbError = false; +} + +XMLSignatureHelper::~XMLSignatureHelper() +{ +} + +void XMLSignatureHelper::SetStorage( + const Reference < css::embed::XStorage >& rxStorage, + const OUString& sODFVersion) +{ + SAL_WARN_IF( mxUriBinding.is(), "xmlsecurity.helper", "SetStorage - UriBinding already set!" ); + mxUriBinding = new UriBindingHelper( rxStorage ); + SAL_WARN_IF(!rxStorage.is(), "xmlsecurity.helper", "SetStorage - empty storage!"); + mbODFPre1_2 = DocumentSignatureHelper::isODFPre_1_2(sODFVersion); +} + + +void XMLSignatureHelper::SetStartVerifySignatureHdl( const Link& 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 + */ + SvXMLAttributeList *pAttributeList = new SvXMLAttributeList(); + OUString sNamespace; + if (mbODFPre1_2) + sNamespace = NS_DOCUMENTSIGNATURES; + else + sNamespace = NS_DOCUMENTSIGNATURES_ODF_1_2; + + pAttributeList->AddAttribute( + "xmlns", + sNamespace); + + xSaxWriter->startDocument(); + xSaxWriter->startElement( + "document-signatures", + uno::Reference< css::xml::sax::XAttributeList > (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 ParserInputSrouce + 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 ); + + // parser the stream + try + { + xParser->parseStream( aParserInput ); + } + catch( uno::Exception& ) + { + 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, "origin.sigs.rels", mxCtx); + + for (sal_Int32 i = 0; i < aRelationsInfo.getLength(); ++i) + { + const uno::Sequence& rRelation = aRelationsInfo[i]; + auto aRelation = comphelper::sequenceToContainer< std::vector >(rRelation); + if (std::any_of(aRelation.begin(), aRelation.end(), lcl_isSignatureType)) + { + std::vector::iterator it = std::find_if(aRelation.begin(), aRelation.end(), [](const beans::StringPair& rPair) { return rPair.First == "Target"; }); + if (it != aRelation.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"); + } + + 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, ".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; + } + + // Append rels and sigs to defaults, if it's not there already. + uno::Sequence& rDefaults = aContentTypeInfo[0]; + auto aDefaults = comphelper::sequenceToContainer< std::vector >(rDefaults); + if (std::none_of(rDefaults.begin(), rDefaults.end(), [](const beans::StringPair& rPair) { return rPair.First == "rels"; })) + aDefaults.emplace_back("rels", "application/vnd.openxmlformats-package.relationships+xml"); + + if (std::none_of(rDefaults.begin(), rDefaults.end(), [](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 = aContentTypeInfo[1]; + auto aOverrides = comphelper::sequenceToContainer< std::vector >(rOverrides); + aOverrides.erase(std::remove_if(aOverrides.begin(), aOverrides.end(), [](const beans::StringPair& rPair) + { + return rPair.First.startsWith("/_xmlsignatures/sig"); + }), aOverrides.end()); + + // Add our signature overrides. + for (int i = 1; i <= nSignatureCount; ++i) + aOverrides.emplace_back("/_xmlsignatures/sig" + OUString::number(i) + ".xml", "application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml"); + + rOverrides = comphelper::containerToSequence(aOverrides); + uno::Reference 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(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/helper/xmlsignaturehelper2.cxx b/xmlsecurity/source/helper/xmlsignaturehelper2.cxx new file mode 100644 index 000000000..1a7a33459 --- /dev/null +++ b/xmlsecurity/source/helper/xmlsignaturehelper2.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/xsecctl.cxx b/xmlsecurity/source/helper/xsecctl.cxx new file mode 100644 index 000000000..cac30006b --- /dev/null +++ b/xmlsecurity/source/helper/xsecctl.cxx @@ -0,0 +1,986 @@ +/* -*- 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 +#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( const css::uno::Reference& rxCtx ) + : mxCtx(rxCtx) + , m_nNextSecurityId(1) + , m_bIsPreviousNodeInitializable(false) + , m_bIsSAXEventKeeperConnected(false) + , m_bIsCollectingElement(false) + , m_bIsBlocking(false) + , m_eStatusOfSecurityComponents(InitializationState::UNINITIALIZED) + , m_bIsSAXEventKeeperSticky(false) + , m_nReservedSignatureId(0) + , m_bVerifyCurrentSignature(false) +{ +} + +XSecController::~XSecController() +{ +} + + +/* + * private methods + */ +int XSecController::findSignatureInfor( sal_Int32 nSecurityId) const +/****** XSecController/findSignatureInfor ************************************* + * + * NAME + * findSignatureInfor -- find SignatureInformation struct for a particular + * signature + * + * SYNOPSIS + * index = findSignatureInfor( nSecurityId ); + * + * INPUTS + * nSecurityId - the signature's id + * + * RESULT + * index - the index of the signature, or -1 when no such signature + * existing + ******************************************************************************/ +{ + int i; + int size = m_vInternalSignatureInformations.size(); + + for (i=0; i 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. + */ + { + css::uno::Sequence arg(1); + arg[0] <<= uno::Reference(m_xXMLDocumentWrapper.get()); + 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(static_cast(m_xSAXEventKeeper.get()), css::uno::UNO_QUERY); + + /* + * 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); + + css::uno::Sequence aArgs( 1 ); + aArgs[0] <<= xSEKHandler; + xInitialization->initialize(aArgs); + } + 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 ) + { + if (m_bIsSAXEventKeeperConnected) + { + 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( 1 ); + aArgs[0] <<= 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 SvXMLAttributeList()); + pAttributeList->AddAttribute("Id", "idUnsignedProperties"); + xDocumentHandler->startElement("xd:UnsignedProperties", uno::Reference(pAttributeList.get())); + } + + { + xDocumentHandler->startElement("xd:UnsignedSignatureProperties", uno::Reference(new SvXMLAttributeList())); + + { + xDocumentHandler->startElement("xd:CertificateValues", uno::Reference(new SvXMLAttributeList())); + + { + for (const auto& i: signatureInfo.maEncapsulatedX509Certificates) + { + xDocumentHandler->startElement("xd:EncapsulatedX509Certificate", uno::Reference(new SvXMLAttributeList())); + xDocumentHandler->characters(i); + xDocumentHandler->endElement("xd:EncapsulatedX509Certificate"); + } + } + + xDocumentHandler->endElement("xd:CertificateValues"); + } + + xDocumentHandler->endElement("xd:UnsignedSignatureProperties"); + } + + xDocumentHandler->endElement("xd:UnsignedProperties"); +} + +} + +void XSecController::exportSignature( + const css::uno::Reference& 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; + SvXMLAttributeList *pAttributeList; + + /* + * Write Signature element + */ + pAttributeList = new SvXMLAttributeList(); + pAttributeList->AddAttribute( + "xmlns", + NS_XMLDSIG); + + if (!signatureInfo.ouSignatureId.isEmpty()) + { + pAttributeList->AddAttribute( + "Id", + signatureInfo.ouSignatureId); + } + + xDocumentHandler->startElement( "Signature", css::uno::Reference< css::xml::sax::XAttributeList > (pAttributeList)); + { + /* Write SignedInfo element */ + xDocumentHandler->startElement( + "SignedInfo", + css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList())); + { + /* Write CanonicalizationMethod element */ + pAttributeList = new SvXMLAttributeList(); + pAttributeList->AddAttribute( + "Algorithm", + ALGO_C14N); + xDocumentHandler->startElement( "CanonicalizationMethod", css::uno::Reference< css::xml::sax::XAttributeList > (pAttributeList) ); + xDocumentHandler->endElement( "CanonicalizationMethod" ); + + /* Write SignatureMethod element */ + pAttributeList = new SvXMLAttributeList(); + + // TODO: actually roundtrip this value from parsing documentsignatures.xml - entirely + // broken to assume this would in any way relate to the 1st reference's digest algo + + // Assume that all Reference elements use the same DigestMethod:Algorithm, and that the + // SignatureMethod:Algorithm should be the corresponding one. + pAttributeList->AddAttribute( + "Algorithm", + getSignatureURI(signatureInfo.eAlgorithmID, vReferenceInfors[0].nDigestID)); + xDocumentHandler->startElement( "SignatureMethod", css::uno::Reference< css::xml::sax::XAttributeList > (pAttributeList) ); + xDocumentHandler->endElement( "SignatureMethod" ); + + /* Write Reference element */ + int j; + int refNum = vReferenceInfors.size(); + + for(j=0; jAddAttribute( + "URI", + refInfor.ouURI); + } + else + /* + * same-document reference + */ + { + pAttributeList->AddAttribute( + "URI", + "#" + refInfor.ouURI); + + if (bXAdESCompliantIfODF && refInfor.ouURI == "idSignedProperties" && !refInfor.ouType.isEmpty()) + { + // The reference which points to the SignedProperties + // shall have this specific type. + pAttributeList->AddAttribute("Type", + refInfor.ouType); + } + } + + xDocumentHandler->startElement( "Reference", css::uno::Reference< css::xml::sax::XAttributeList > (pAttributeList) ); + { + /* Write Transforms element */ + if (refInfor.nType == SignatureReferenceType::XMLSTREAM) + /* + * xml stream, so c14n transform is needed + */ + { + xDocumentHandler->startElement( + "Transforms", + css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList())); + { + pAttributeList = new SvXMLAttributeList(); + pAttributeList->AddAttribute( + "Algorithm", + ALGO_C14N); + xDocumentHandler->startElement( + "Transform", + css::uno::Reference< css::xml::sax::XAttributeList > (pAttributeList) ); + xDocumentHandler->endElement( "Transform" ); + } + xDocumentHandler->endElement( "Transforms" ); + } + + /* Write DigestMethod element */ + pAttributeList = new SvXMLAttributeList(); + pAttributeList->AddAttribute( + "Algorithm", + getDigestURI(refInfor.nDigestID)); + xDocumentHandler->startElement( + "DigestMethod", + css::uno::Reference< css::xml::sax::XAttributeList > (pAttributeList) ); + xDocumentHandler->endElement( "DigestMethod" ); + + /* Write DigestValue element */ + xDocumentHandler->startElement( + "DigestValue", + css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList())); + xDocumentHandler->characters( refInfor.ouDigestValue ); + xDocumentHandler->endElement( "DigestValue" ); + } + xDocumentHandler->endElement( "Reference" ); + } + } + xDocumentHandler->endElement( "SignedInfo" ); + + /* Write SignatureValue element */ + xDocumentHandler->startElement( + "SignatureValue", + css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList())); + xDocumentHandler->characters( signatureInfo.ouSignatureValue ); + xDocumentHandler->endElement( "SignatureValue" ); + + /* Write KeyInfo element */ + xDocumentHandler->startElement( + "KeyInfo", + css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList())); + { + // GPG or X509 key? + if (!signatureInfo.ouGpgCertificate.isEmpty()) + { + pAttributeList = new SvXMLAttributeList(); + pAttributeList->AddAttribute("xmlns:loext", NS_LOEXT); + /* Write PGPData element */ + xDocumentHandler->startElement( + "PGPData", + css::uno::Reference< css::xml::sax::XAttributeList > (pAttributeList)); + { + /* Write keyid element */ + xDocumentHandler->startElement( + "PGPKeyID", + css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList())); + xDocumentHandler->characters( signatureInfo.ouCertDigest ); + xDocumentHandler->endElement( "PGPKeyID" ); + + /* Write PGPKeyPacket element */ + if (!signatureInfo.ouGpgCertificate.isEmpty()) + { + xDocumentHandler->startElement( + "PGPKeyPacket", + css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList())); + xDocumentHandler->characters( signatureInfo.ouGpgCertificate ); + xDocumentHandler->endElement( "PGPKeyPacket" ); + } + + /* Write PGPOwner element */ + xDocumentHandler->startElement( + "loext:PGPOwner", + css::uno::Reference< css::xml::sax::XAttributeList >(new SvXMLAttributeList())); + xDocumentHandler->characters( signatureInfo.ouGpgOwner ); + xDocumentHandler->endElement( "loext:PGPOwner" ); + } + xDocumentHandler->endElement( "PGPData" ); + } + else + { + /* Write X509Data element */ + xDocumentHandler->startElement( + "X509Data", + css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList())); + { + /* Write X509IssuerSerial element */ + xDocumentHandler->startElement( + "X509IssuerSerial", + css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList())); + { + /* Write X509IssuerName element */ + xDocumentHandler->startElement( + "X509IssuerName", + css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList())); + xDocumentHandler->characters( signatureInfo.ouX509IssuerName ); + xDocumentHandler->endElement( "X509IssuerName" ); + + /* Write X509SerialNumber element */ + xDocumentHandler->startElement( + "X509SerialNumber", + css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList())); + xDocumentHandler->characters( signatureInfo.ouX509SerialNumber ); + xDocumentHandler->endElement( "X509SerialNumber" ); + } + xDocumentHandler->endElement( "X509IssuerSerial" ); + + /* Write X509Certificate element */ + if (!signatureInfo.ouX509Certificate.isEmpty()) + { + xDocumentHandler->startElement( + "X509Certificate", + css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList())); + xDocumentHandler->characters( signatureInfo.ouX509Certificate ); + xDocumentHandler->endElement( "X509Certificate" ); + } + } + xDocumentHandler->endElement( "X509Data" ); + } + } + xDocumentHandler->endElement( "KeyInfo" ); + + OUString sDate; + + /* Write Object element */ + xDocumentHandler->startElement( + "Object", + css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList())); + { + /* Write SignatureProperties element */ + xDocumentHandler->startElement( + "SignatureProperties", + css::uno::Reference< css::xml::sax::XAttributeList > (new SvXMLAttributeList())); + { + /* Write SignatureProperty element */ + pAttributeList = new SvXMLAttributeList(); + pAttributeList->AddAttribute( + "Id", + signatureInfo.ouPropertyId); + pAttributeList->AddAttribute( + "Target", + "#" + signatureInfo.ouSignatureId); + xDocumentHandler->startElement( + "SignatureProperty", + css::uno::Reference< css::xml::sax::XAttributeList > (pAttributeList)); + { + /* Write timestamp element */ + + pAttributeList = new SvXMLAttributeList(); + pAttributeList->AddAttribute( + "xmlns:dc", + NS_DC); + + xDocumentHandler->startElement( + "dc:date", + css::uno::Reference< css::xml::sax::XAttributeList > (pAttributeList)); + + OUStringBuffer buffer; + //If the xml signature was already contained in the document, + //then we use the original date and time string, rather than the + //converted one. This avoids writing a different string due to + //e.g. rounding issues and thus breaking the signature. + if (!signatureInfo.ouDateTime.isEmpty()) + buffer = signatureInfo.ouDateTime; + else + { + buffer = utl::toISO8601(signatureInfo.stDateTime); + // xsd:dateTime must use period as separator for fractional seconds, while + // utl::toISO8601 uses comma (as allowed, and even recommended, by ISO8601). + buffer.replace(',', '.'); + } + sDate = buffer.makeStringAndClear(); + xDocumentHandler->characters( sDate ); + + xDocumentHandler->endElement( + "dc:date"); + } + xDocumentHandler->endElement( "SignatureProperty" ); + } + + // Write signature description. + if (!signatureInfo.ouDescription.isEmpty()) + { + // SignatureProperty element. + pAttributeList = new SvXMLAttributeList(); + pAttributeList->AddAttribute("Id", signatureInfo.ouDescriptionPropertyId); + pAttributeList->AddAttribute("Target", "#" + signatureInfo.ouSignatureId); + xDocumentHandler->startElement("SignatureProperty", uno::Reference(pAttributeList)); + + { + // Description element. + pAttributeList = new SvXMLAttributeList(); + pAttributeList->AddAttribute("xmlns:dc", NS_DC); + + xDocumentHandler->startElement("dc:description", uno::Reference(pAttributeList)); + xDocumentHandler->characters(signatureInfo.ouDescription); + xDocumentHandler->endElement("dc:description"); + } + + xDocumentHandler->endElement("SignatureProperty"); + } + + xDocumentHandler->endElement( "SignatureProperties" ); + } + xDocumentHandler->endElement( "Object" ); + + // In XAdES, write another Object element for the QualifyingProperties + if (bXAdESCompliantIfODF) + { + pAttributeList = new SvXMLAttributeList(); + pAttributeList->AddAttribute("xmlns:xd", NS_XD); + xDocumentHandler->startElement( + "Object", + css::uno::Reference< css::xml::sax::XAttributeList > (pAttributeList)); + { + pAttributeList = new SvXMLAttributeList(); + pAttributeList->AddAttribute("Target", "#" + signatureInfo.ouSignatureId); + xDocumentHandler->startElement( + "xd:QualifyingProperties", + css::uno::Reference< css::xml::sax::XAttributeList > (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(); +} + +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 + + +XSecParser::XSecParser(XMLSignatureHelper& rXMLSignatureHelper, + XSecController* pXSecController) + : m_bInX509IssuerName(false) + , m_bInX509SerialNumber(false) + , m_bInX509Certificate(false) + , m_bInGpgCertificate(false) + , m_bInGpgKeyID(false) + , m_bInGpgOwner(false) + , m_bInCertDigest(false) + , m_bInEncapsulatedX509Certificate(false) + , m_bInSigningTime(false) + , m_bInDigestValue(false) + , m_bInSignatureValue(false) + , m_bInDate(false) + , m_bInDescription(false) + , m_bInSignatureLineId(false) + , m_bInSignatureLineValidImage(false) + , m_bInSignatureLineInvalidImage(false) + , m_pXSecController(pXSecController) + , m_bReferenceUnresolved(false) + , m_nReferenceDigestID(css::xml::crypto::DigestID::SHA1) + , m_rXMLSignatureHelper(rXMLSignatureHelper) +{ +} + +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( ) +{ + m_bInX509IssuerName = false; + m_bInX509SerialNumber = false; + m_bInX509Certificate = false; + m_bInGpgCertificate = false; + m_bInGpgKeyID = false; + m_bInGpgOwner = false; + m_bInSignatureValue = false; + m_bInDigestValue = false; + m_bInDate = false; + m_bInDescription = false; + + 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& aName, + const css::uno::Reference< css::xml::sax::XAttributeList >& xAttribs ) +{ + try + { + OUString ouIdAttr = getIdAttr(xAttribs); + if (!ouIdAttr.isEmpty()) + { + m_pXSecController->collectToVerify( ouIdAttr ); + } + + if ( aName == "Signature" ) + { + m_rXMLSignatureHelper.StartVerifySignatureElement(); + m_pXSecController->addSignature(); + if (!ouIdAttr.isEmpty()) + { + m_pXSecController->setId( ouIdAttr ); + } + } + else if (aName == "SignatureMethod") + { + OUString ouAlgorithm = xAttribs->getValueByName("Algorithm"); + if (ouAlgorithm == ALGO_ECDSASHA1 || ouAlgorithm == ALGO_ECDSASHA256 + || ouAlgorithm == ALGO_ECDSASHA512) + m_pXSecController->setSignatureMethod(svl::crypto::SignatureMethodAlgorithm::ECDSA); + } + else if ( aName == "Reference" ) + { + OUString ouUri = xAttribs->getValueByName("URI"); + SAL_WARN_IF( ouUri.isEmpty(), "xmlsecurity.helper", "URI is empty" ); + // Remember the type of this reference. + OUString ouType = xAttribs->getValueByName("Type"); + if (ouUri.startsWith("#")) + { + /* + * remove the first character '#' from the attribute value + */ + m_pXSecController->addReference( ouUri.copy(1), m_nReferenceDigestID, ouType ); + } + else + { + /* + * remember the uri + */ + m_currentReferenceURI = ouUri; + m_bReferenceUnresolved = true; + } + } + else if (aName == "DigestMethod") + { + OUString ouAlgorithm = xAttribs->getValueByName("Algorithm"); + + SAL_WARN_IF( ouAlgorithm.isEmpty(), "xmlsecurity.helper", "no Algorithm in Reference" ); + if (!ouAlgorithm.isEmpty()) + { + 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_nReferenceDigestID = css::xml::crypto::DigestID::SHA1; + else if (ouAlgorithm == ALGO_XMLDSIGSHA256) + m_nReferenceDigestID = css::xml::crypto::DigestID::SHA256; + else if (ouAlgorithm == ALGO_XMLDSIGSHA512) + m_nReferenceDigestID = css::xml::crypto::DigestID::SHA512; + else + m_nReferenceDigestID = 0; + } + } + else if (aName == "Transform") + { + if ( m_bReferenceUnresolved ) + { + OUString ouAlgorithm = xAttribs->getValueByName("Algorithm"); + + if (ouAlgorithm == ALGO_C14N) + /* + * a xml stream + */ + { + m_pXSecController->addStreamReference( m_currentReferenceURI, false, m_nReferenceDigestID ); + m_bReferenceUnresolved = false; + } + } + } + else if (aName == "X509IssuerName") + { + m_ouX509IssuerName.clear(); + m_bInX509IssuerName = true; + } + else if (aName == "X509SerialNumber") + { + m_ouX509SerialNumber.clear(); + m_bInX509SerialNumber = true; + } + else if (aName == "X509Certificate") + { + m_ouX509Certificate.clear(); + m_bInX509Certificate = true; + } + else if (aName == "PGPData") + { + m_pXSecController->switchGpgSignature(); + } + else if (aName == "PGPKeyID") + { + m_ouGpgKeyID.clear(); + m_bInGpgKeyID = true; + } + else if (aName == "PGPKeyPacket") + { + m_ouGpgCertificate.clear(); + m_bInGpgCertificate = true; + } + else if (aName == "loext:PGPOwner") + { + m_ouGpgOwner.clear(); + m_bInGpgOwner = true; + } + else if (aName == "SignatureValue") + { + m_ouSignatureValue.clear(); + m_bInSignatureValue = true; + } + else if (aName == "DigestValue" && !m_bInCertDigest) + { + m_ouDigestValue.clear(); + m_bInDigestValue = true; + } + else if (aName == "xd:CertDigest") + { + m_ouCertDigest.clear(); + m_bInCertDigest = true; + } + // FIXME: Existing code here in xmlsecurity uses "xd" as the namespace prefix for XAdES, + // while the sample document attached to tdf#76142 uses "xades". So accept either here. Of + // course this is idiotic and wrong, the right thing would be to use a proper way to parse + // XML that would handle namespaces correctly. I have no idea how substantial re-plumbing of + // this code that would require. + else if (aName == "xd:EncapsulatedX509Certificate" || aName == "xades:EncapsulatedX509Certificate") + { + m_ouEncapsulatedX509Certificate.clear(); + m_bInEncapsulatedX509Certificate = true; + } + else if (aName == "xd:SigningTime" || aName == "xades:SigningTime") + { + m_ouDate.clear(); + m_bInSigningTime = true; + } + else if ( aName == "SignatureProperty" ) + { + if (!ouIdAttr.isEmpty()) + { + m_pXSecController->setPropertyId( ouIdAttr ); + } + } + else if (aName == "dc:date") + { + if (m_ouDate.isEmpty()) + m_bInDate = true; + } + else if (aName == "dc:description") + { + m_ouDescription.clear(); + m_bInDescription = true; + } + else if (aName == "loext:SignatureLineId") + { + m_ouSignatureLineId.clear(); + m_bInSignatureLineId = true; + } + else if (aName == "loext:SignatureLineValidImage") + { + m_ouSignatureLineValidImage.clear(); + m_bInSignatureLineValidImage = true; + } + else if (aName == "loext:SignatureLineInvalidImage") + { + m_ouSignatureLineInvalidImage.clear(); + m_bInSignatureLineInvalidImage = true; + } + + if (m_xNextHandler.is()) + { + m_xNextHandler->startElement(aName, 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& aName ) +{ + try + { + if (aName == "DigestValue" && !m_bInCertDigest) + { + m_bInDigestValue = false; + } + else if ( aName == "Reference" ) + { + if ( m_bReferenceUnresolved ) + /* + * it must be an octet stream + */ + { + m_pXSecController->addStreamReference( m_currentReferenceURI, true, m_nReferenceDigestID ); + m_bReferenceUnresolved = false; + } + + m_pXSecController->setDigestValue( m_nReferenceDigestID, m_ouDigestValue ); + } + else if ( aName == "SignedInfo" ) + { + m_pXSecController->setReferenceCount(); + } + else if ( aName == "SignatureValue" ) + { + m_pXSecController->setSignatureValue( m_ouSignatureValue ); + m_bInSignatureValue = false; + } + else if (aName == "X509IssuerName") + { + m_pXSecController->setX509IssuerName( m_ouX509IssuerName ); + m_bInX509IssuerName = false; + } + else if (aName == "X509SerialNumber") + { + m_pXSecController->setX509SerialNumber( m_ouX509SerialNumber ); + m_bInX509SerialNumber = false; + } + else if (aName == "X509Certificate") + { + m_pXSecController->setX509Certificate( m_ouX509Certificate ); + m_bInX509Certificate = false; + } + else if (aName == "PGPKeyID") + { + m_pXSecController->setGpgKeyID( m_ouGpgKeyID ); + m_bInGpgKeyID = false; + } + else if (aName == "PGPKeyPacket") + { + m_pXSecController->setGpgCertificate( m_ouGpgCertificate ); + m_bInGpgCertificate = false; + } + else if (aName == "loext:PGPOwner") + { + m_pXSecController->setGpgOwner( m_ouGpgOwner ); + m_bInGpgOwner = false; + } + else if (aName == "xd:CertDigest") + { + m_pXSecController->setCertDigest( m_ouCertDigest ); + m_bInCertDigest = false; + } + else if (aName == "xd:EncapsulatedX509Certificate" || aName == "xades:EncapsulatedX509Certificate") + { + m_pXSecController->addEncapsulatedX509Certificate( m_ouEncapsulatedX509Certificate ); + m_bInEncapsulatedX509Certificate = false; + } + else if (aName == "xd:SigningTime" || aName == "xades:SigningTime") + { + m_pXSecController->setDate( m_ouDate ); + m_bInSigningTime = false; + } + else if (aName == "dc:date") + { + if (m_bInDate) + { + m_pXSecController->setDate( m_ouDate ); + m_bInDate = false; + } + } + else if (aName == "dc:description") + { + m_pXSecController->setDescription( m_ouDescription ); + m_bInDescription = false; + } + else if (aName == "loext:SignatureLineId") + { + m_pXSecController->setSignatureLineId( m_ouSignatureLineId ); + m_bInSignatureLineId = false; + } + else if (aName == "loext:SignatureLineValidImage") + { + m_pXSecController->setValidSignatureImage( m_ouSignatureLineValidImage ); + m_bInSignatureLineValidImage = false; + } + else if (aName == "loext:SignatureLineInvalidImage") + { + m_pXSecController->setInvalidSignatureImage( m_ouSignatureLineInvalidImage ); + m_bInSignatureLineInvalidImage = false; + } + + if (m_xNextHandler.is()) + { + m_xNextHandler->endElement(aName); + } + } + 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()); + } +} + +void SAL_CALL XSecParser::characters( const OUString& aChars ) +{ + if (m_bInX509IssuerName) + { + m_ouX509IssuerName += aChars; + } + else if (m_bInX509SerialNumber) + { + m_ouX509SerialNumber += aChars; + } + else if (m_bInX509Certificate) + { + m_ouX509Certificate += aChars; + } + else if (m_bInGpgCertificate) + { + m_ouGpgCertificate += aChars; + } + else if (m_bInGpgKeyID) + { + m_ouGpgKeyID += aChars; + } + else if (m_bInGpgOwner) + { + m_ouGpgOwner += aChars; + } + else if (m_bInSignatureValue) + { + m_ouSignatureValue += aChars; + } + else if (m_bInDigestValue && !m_bInCertDigest) + { + m_ouDigestValue += aChars; + } + else if (m_bInDate) + { + m_ouDate += aChars; + } + else if (m_bInDescription) + { + m_ouDescription += aChars; + } + else if (m_bInCertDigest) + { + m_ouCertDigest += aChars; + } + else if (m_bInEncapsulatedX509Certificate) + { + m_ouEncapsulatedX509Certificate += aChars; + } + else if (m_bInSigningTime) + { + m_ouDate += aChars; + } + else if (m_bInSignatureLineId) + { + m_ouSignatureLineId += aChars; + } + else if (m_bInSignatureLineValidImage) + { + m_ouSignatureLineValidImage += aChars; + } + else if (m_bInSignatureLineInvalidImage) + { + m_ouSignatureLineInvalidImage += aChars; + } + + if (m_xNextHandler.is()) + { + m_xNextHandler->characters(aChars); + } +} + +void SAL_CALL XSecParser::ignorableWhitespace( const OUString& aWhitespaces ) +{ + if (m_xNextHandler.is()) + { + m_xNextHandler->ignorableWhitespace( aWhitespaces ); + } +} + +void SAL_CALL XSecParser::processingInstruction( const OUString& aTarget, const OUString& aData ) +{ + if (m_xNextHandler.is()) + { + m_xNextHandler->processingInstruction(aTarget, aData); + } +} + +void SAL_CALL XSecParser::setDocumentLocator( const css::uno::Reference< css::xml::sax::XLocator >& xLocator ) +{ + if (m_xNextHandler.is()) + { + m_xNextHandler->setDocumentLocator( xLocator ); + } +} + +/* + * XInitialization + */ +void SAL_CALL XSecParser::initialize( + const css::uno::Sequence< css::uno::Any >& aArguments ) +{ + aArguments[0] >>= m_xNextHandler; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/helper/xsecparser.hxx b/xmlsecurity/source/helper/xsecparser.hxx new file mode 100644 index 000000000..d9b079aa3 --- /dev/null +++ b/xmlsecurity/source/helper/xsecparser.hxx @@ -0,0 +1,162 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_XMLSECURITY_SOURCE_HELPER_XSECPARSER_HXX +#define INCLUDED_XMLSECURITY_SOURCE_HELPER_XSECPARSER_HXX + +#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; +private: + /* + * the following members are used to reserve the signature information, + * including X509IssuerName, X509SerialNumber, and X509Certificate,etc. + */ + OUString m_ouX509IssuerName; + OUString m_ouX509SerialNumber; + OUString m_ouX509Certificate; + OUString m_ouGpgCertificate; + OUString m_ouGpgKeyID; + OUString m_ouGpgOwner; + OUString m_ouCertDigest; + OUString m_ouEncapsulatedX509Certificate; + OUString m_ouDigestValue; + OUString m_ouSignatureValue; + OUString m_ouDate; + /// Characters of a element, as just read from XML. + OUString m_ouDescription; + OUString m_ouSignatureLineId; + OUString m_ouSignatureLineValidImage; + OUString m_ouSignatureLineInvalidImage; + + /* + * whether inside a particular element + */ + bool m_bInX509IssuerName; + bool m_bInX509SerialNumber; + bool m_bInX509Certificate; + bool m_bInGpgCertificate; + bool m_bInGpgKeyID; + bool m_bInGpgOwner; + bool m_bInCertDigest; + bool m_bInEncapsulatedX509Certificate; + bool m_bInSigningTime; + bool m_bInDigestValue; + bool m_bInSignatureValue; + bool m_bInDate; + bool m_bInDescription; + bool m_bInSignatureLineId; + bool m_bInSignatureLineValidImage; + bool m_bInSignatureLineInvalidImage; + + /* + * the XSecController collaborating with XSecParser + */ + XSecController* m_pXSecController; + + /* + * the next XDocumentHandler on the SAX chain + */ + css::uno::Reference< + css::xml::sax::XDocumentHandler > m_xNextHandler; + + /* + * this string is used to remember the current handled reference's URI, + * + * because it can be decided whether a stream reference is xml based or binary based + * only after the Transforms element is read in, so we have to reserve the reference's + * URI when the startElement event is met. + */ + OUString m_currentReferenceURI; + bool m_bReferenceUnresolved; + + // Relevant for ODF. The digest algorithm selected by the current DigestMethod element's + // Algorithm attribute in the current Reference element. From css::xml::crypto::DigestID. + sal_Int32 m_nReferenceDigestID; + XMLSignatureHelper& m_rXMLSignatureHelper; + +private: + 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; +}; + +#endif + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/helper/xsecsign.cxx b/xmlsecurity/source/helper/xsecsign.cxx new file mode 100644 index 000000000..b9648ed64 --- /dev/null +++ b/xmlsecurity/source/helper/xsecsign.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 + +namespace com::sun::star::graphic { class XGraphic; } + +using namespace css; +using namespace css::uno; +using namespace css::graphic; + +/* protected: for signature generation */ +OUString XSecController::createId() +{ + sal_uInt8 aSeq[16]; + rtl_createUuid( aSeq, nullptr, true ); + + char str[68]="ID_"; + int length = 3; + for (sal_uInt8 i : aSeq) + { + length += sprintf(str+length, "%04x", i); + } + + return OUString::createFromAscii(str); +} + +css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > XSecController::prepareSignatureToWrite( + InternalSignatureInformation& internalSignatureInfor, + sal_Int32 nStorageFormat, + bool bXAdESCompliantIfODF) +{ + sal_Int32 nSecurityId = internalSignatureInfor.signatureInfor.nSecurityId; + SignatureReferenceInformations& vReferenceInfors = internalSignatureInfor.signatureInfor.vSignatureReferenceInfors; + + sal_Int32 nIdOfSignatureElementCollector; + + nIdOfSignatureElementCollector = + m_xSAXEventKeeper->addSecurityElementCollector( css::xml::crypto::sax::ElementMarkPriority_AFTERMODIFY, true ); + + m_xSAXEventKeeper->setSecurityId(nIdOfSignatureElementCollector, nSecurityId); + + rtl::Reference xSignatureCreator(new SignatureCreatorImpl); + + css::uno::Sequence args(5); + args[0] <<= OUString::number(nSecurityId); + args[1] <<= uno::Reference(static_cast(m_xSAXEventKeeper.get()), uno::UNO_QUERY); + args[2] <<= OUString::number(nIdOfSignatureElementCollector); + + //for nss, the internal module is used for signing, which needs to be improved later + args[3] <<= m_xSecurityContext->getSecurityEnvironment(); + + args[4] <<= 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.get()); + + int size = vReferenceInfors.size(); + sal_Int32 nReferenceCount = 0; + + for(int i=0; isetSecurityId(keeperId, nSecurityId); + m_xSAXEventKeeper->addReferenceResolvedListener( keeperId, xSignatureCreator.get()); + 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.ouPropertyId = createId(); + internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, digestID, internalSignatureInfor.signatureInfor.ouPropertyId, -1, OUString() ); + size++; + + if (bXAdESCompliantIfODF) + { + // We write a new reference, so it's possible to use the correct type URI. + internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, digestID, "idSignedProperties", -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 + { + internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, digestID, "idPackageObject", -1, OUString()); + size++; + internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, digestID, "idOfficeObject", -1, OUString()); + size++; + internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, digestID, "idSignedProperties", -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(static_cast(m_xSAXEventKeeper.get()),css::uno::UNO_QUERY); + + 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(static_cast(m_xSAXEventKeeper.get()), uno::UNO_QUERY); + + for (InternalSignatureInformation & rInformation : m_vInternalSignatureInformations) + { + // Prepare the signature creator. + rInformation.xReferenceResolvedListener = prepareSignatureToWrite(rInformation, embed::StorageFormats::OFOPXML, false); + + exportOOXMLSignature(xRootStorage, xSEKHandler, rInformation.signatureInfor); + } + + m_bIsSAXEventKeeperSticky = false; + chainOff(); + + bRet = true; + } + catch(const uno::Exception&) + { + } + + m_xSAXEventKeeper->setNextHandler(nullptr); + m_bIsSAXEventKeeperSticky = false; + } + + return bRet; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/helper/xsecverify.cxx b/xmlsecurity/source/helper/xsecverify.cxx new file mode 100644 index 000000000..c826971b1 --- /dev/null +++ b/xmlsecurity/source/helper/xsecverify.cxx @@ -0,0 +1,537 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +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(5); + args[0] <<= OUString::number(nSecurityId); + args[1] <<= uno::Reference(static_cast(m_xSAXEventKeeper.get()), uno::UNO_QUERY); + args[2] <<= OUString::number(nIdOfSignatureElementCollector); + args[3] <<= m_xSecurityContext; + args[4] <<= 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()) + { + 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 +} + +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() ) + { + 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::setX509IssuerName( OUString const & ouX509IssuerName ) +{ + if (m_vInternalSignatureInformations.empty()) + { + SAL_INFO("xmlsecurity.helper","XSecController::setX509IssuerName: no signature"); + return; + } + InternalSignatureInformation &isi = m_vInternalSignatureInformations.back(); + isi.signatureInfor.ouX509IssuerName = ouX509IssuerName; +} + +void XSecController::setX509SerialNumber( OUString const & ouX509SerialNumber ) +{ + if (m_vInternalSignatureInformations.empty()) + { + SAL_INFO("xmlsecurity.helper","XSecController::setX509SerialNumber: no signature"); + return; + } + InternalSignatureInformation &isi = m_vInternalSignatureInformations.back(); + isi.signatureInfor.ouX509SerialNumber = ouX509SerialNumber; +} + +void XSecController::setX509Certificate( OUString const & ouX509Certificate ) +{ + if (m_vInternalSignatureInformations.empty()) + { + SAL_INFO("xmlsecurity.helper","XSecController::setX509Certificate: no signature"); + return; + } + InternalSignatureInformation &isi = m_vInternalSignatureInformations.back(); + isi.signatureInfor.ouX509Certificate = ouX509Certificate; +} + +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 & ouDate ) +{ + if (m_vInternalSignatureInformations.empty()) + { + SAL_INFO("xmlsecurity.helper","XSecController::setDate: no signature"); + return; + } + InternalSignatureInformation &isi = m_vInternalSignatureInformations.back(); + (void)utl::ISO8601parseDateTime( ouDate, isi.signatureInfor.stDateTime); + isi.signatureInfor.ouDateTime = ouDate; +} + +void XSecController::setDescription(const OUString& rDescription) +{ + if (m_vInternalSignatureInformations.empty()) + return; + + InternalSignatureInformation& rInformation = m_vInternalSignatureInformations.back(); + rInformation.signatureInfor.ouDescription = rDescription; +} + +void XSecController::setSignatureBytes(const uno::Sequence& rBytes) +{ + if (m_vInternalSignatureInformations.empty()) + return; + + InternalSignatureInformation& rInformation = m_vInternalSignatureInformations.back(); + rInformation.signatureInfor.aSignatureBytes = rBytes; +} + +void XSecController::setCertDigest(const OUString& rCertDigest) +{ + if (m_vInternalSignatureInformations.empty()) + return; + + InternalSignatureInformation& rInformation = m_vInternalSignatureInformations.back(); + rInformation.signatureInfor.ouCertDigest = rCertDigest; +} + +namespace { +Reference lcl_getGraphicFromString(const OUString& 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( 1 ); + aArgs[ 0 ].Name = "InputStream"; + aArgs[ 0 ].Value <<= xInputStream; + xGraphic = xGraphicProvider->queryGraphic(aArgs); + + return xGraphic; +} +} + +void XSecController::setValidSignatureImage(const OUString& rValidSigImg) +{ + if (m_vInternalSignatureInformations.empty() || rValidSigImg.isEmpty()) + return; + + InternalSignatureInformation& rInformation = m_vInternalSignatureInformations.back(); + rInformation.signatureInfor.aValidSignatureImage = lcl_getGraphicFromString(rValidSigImg); +} + +void XSecController::setInvalidSignatureImage(const OUString& rInvalidSigImg) +{ + if (m_vInternalSignatureInformations.empty() || rInvalidSigImg.isEmpty()) + 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; +} + +void XSecController::setPropertyId( OUString const & ouPropertyId ) +{ + if (m_vInternalSignatureInformations.empty()) + { + SAL_INFO("xmlsecurity.helper","XSecController::setPropertyId: no signature"); + return; + } + InternalSignatureInformation &isi = m_vInternalSignatureInformations.back(); + + if (isi.signatureInfor.ouPropertyId.isEmpty()) + { + // ID attribute is for the date. + isi.signatureInfor.ouPropertyId = ouPropertyId; + } + else + { + // ID attribute is for the description. + isi.signatureInfor.ouDescriptionPropertyId = ouPropertyId; + } +} + +/* public: for signature verify */ +void XSecController::collectToVerify( const OUString& 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. + */ + { + 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/pdfio/pdfdocument.cxx b/xmlsecurity/source/pdfio/pdfdocument.cxx new file mode 100644 index 000000000..8c8421f6a --- /dev/null +++ b/xmlsecurity/source/pdfio/pdfdocument.cxx @@ -0,0 +1,393 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.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 + +#if HAVE_FEATURE_PDFIUM +#include +#endif + +using namespace com::sun::star; + +namespace +{ +/// Turns an array of floats into offset + length pairs. +bool GetByteRangesFromPDF(vcl::filter::PDFArrayElement& rArray, + std::vector>& rByteRanges) +{ + size_t nByteRangeOffset = 0; + const std::vector& rByteRangeElements = rArray.GetElements(); + for (size_t i = 0; i < rByteRangeElements.size(); ++i) + { + auto pNumber = dynamic_cast(rByteRangeElements[i]); + if (!pNumber) + { + SAL_WARN("xmlsecurity.pdfio", + "ValidateSignature: signature offset and length has to be a number"); + return false; + } + + if (i % 2 == 0) + { + nByteRangeOffset = pNumber->GetValue(); + continue; + } + size_t nByteRangeLength = pNumber->GetValue(); + rByteRanges.emplace_back(nByteRangeOffset, nByteRangeLength); + } + + return true; +} + +/// Determines the last position that is covered by a signature. +bool GetEOFOfSignature(vcl::filter::PDFObjectElement* pSignature, size_t& rEOF) +{ + vcl::filter::PDFObjectElement* pValue = pSignature->LookupObject("V"); + if (!pValue) + { + return false; + } + + auto pByteRange = dynamic_cast(pValue->Lookup("ByteRange")); + if (!pByteRange || pByteRange->GetElements().size() < 2) + { + return false; + } + + std::vector> aByteRanges; + if (!GetByteRangesFromPDF(*pByteRange, aByteRanges)) + { + return false; + } + + rEOF = aByteRanges[1].first + aByteRanges[1].second; + return true; +} + +/// Checks if there are unsigned incremental updates between the signatures or after the last one. +bool IsCompleteSignature(SvStream& rStream, vcl::filter::PDFDocument& rDocument, + vcl::filter::PDFObjectElement* pSignature) +{ + std::set aSignedEOFs; + for (const auto& i : rDocument.GetSignatureWidgets()) + { + size_t nEOF = 0; + if (!GetEOFOfSignature(i, nEOF)) + { + return false; + } + + aSignedEOFs.insert(nEOF); + } + + size_t nSignatureEOF = 0; + if (!GetEOFOfSignature(pSignature, nSignatureEOF)) + { + return false; + } + + const std::vector& rAllEOFs = rDocument.GetEOFs(); + bool bFoundOwn = false; + for (const auto& rEOF : rAllEOFs) + { + if (rEOF == nSignatureEOF) + { + bFoundOwn = true; + continue; + } + + if (!bFoundOwn) + { + continue; + } + + if (aSignedEOFs.find(rEOF) == aSignedEOFs.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(); +} + +#if HAVE_FEATURE_PDFIUM + +/** + * 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(); + vcl::pdf::PDFiumDocument aPdfDocument( + FPDF_LoadMemDocument(rStream.GetData(), rStream.GetSize(), /*password=*/nullptr)); + + int nPageCount = aPdfDocument.getPageCount(); + for (int nPage = 0; nPage < nPageCount; ++nPage) + { + std::unique_ptr pPdfPage(aPdfDocument.openPage(nPage)); + if (!pPdfPage) + { + return; + } + + PageChecksum aPageChecksum; + aPageChecksum.m_nPageContent = pPdfPage->getChecksum(nMDPPerm); + for (int i = 0; i < FPDFPage_GetAnnotCount(pPdfPage->getPointer()); ++i) + { + FPDF_ANNOTATION pAnnotation = FPDFPage_GetAnnot(pPdfPage->getPointer(), i); + int nType = FPDFAnnot_GetSubtype(pAnnotation); + switch (nType) + { + case FPDF_ANNOT_UNKNOWN: + case FPDF_ANNOT_FREETEXT: + case FPDF_ANNOT_STAMP: + case FPDF_ANNOT_REDACT: + { + basegfx::B2DRectangle aB2DRectangle; + FS_RECTF aRect; + if (FPDFAnnot_GetRect(pAnnotation, &aRect)) + { + aB2DRectangle = basegfx::B2DRectangle(aRect.left, aRect.top, aRect.right, + aRect.bottom); + } + aPageChecksum.m_aAnnotations.push_back(aB2DRectangle); + break; + } + default: + break; + } + FPDFPage_CloseAnnot(pAnnotation); + } + rPageChecksums.push_back(aPageChecksum); + } +} +#endif + +/** + * 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, vcl::filter::PDFObjectElement* pSignature, int nMDPPerm) +{ + size_t nSignatureEOF = 0; + if (!GetEOFOfSignature(pSignature, nSignatureEOF)) + { + return false; + } + +#if HAVE_FEATURE_PDFIUM + 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; +#else + (void)rStream; + (void)nMDPPerm; + return true; +#endif +} +} + +namespace xmlsecurity::pdfio +{ +bool ValidateSignature(SvStream& rStream, vcl::filter::PDFObjectElement* pSignature, + SignatureInformation& rInformation, vcl::filter::PDFDocument& rDocument, + int nMDPPerm) +{ + vcl::filter::PDFObjectElement* pValue = pSignature->LookupObject("V"); + if (!pValue) + { + SAL_WARN("xmlsecurity.pdfio", "ValidateSignature: no value"); + return false; + } + + auto pContents = dynamic_cast(pValue->Lookup("Contents")); + if (!pContents) + { + SAL_WARN("xmlsecurity.pdfio", "ValidateSignature: no contents"); + return false; + } + + auto pByteRange = dynamic_cast(pValue->Lookup("ByteRange")); + if (!pByteRange || pByteRange->GetElements().size() < 2) + { + SAL_WARN("xmlsecurity.pdfio", "ValidateSignature: no byte range or too few elements"); + return false; + } + + auto pSubFilter = dynamic_cast(pValue->Lookup("SubFilter")); + const bool bNonDetached = pSubFilter && pSubFilter->GetValue() == "adbe.pkcs7.sha1"; + if (!pSubFilter + || (pSubFilter->GetValue() != "adbe.pkcs7.detached" && !bNonDetached + && pSubFilter->GetValue() != "ETSI.CAdES.detached")) + { + if (!pSubFilter) + SAL_WARN("xmlsecurity.pdfio", "ValidateSignature: missing sub-filter"); + else + SAL_WARN("xmlsecurity.pdfio", "ValidateSignature: unsupported sub-filter: '" + << pSubFilter->GetValue() << "'"); + return false; + } + + // Reason / comment / description is optional. + auto pReason = dynamic_cast(pValue->Lookup("Reason")); + if (pReason) + { + // See appendUnicodeTextString() for the export equivalent of this. + std::vector aReason = vcl::filter::PDFDocument::DecodeHexString(pReason); + OUStringBuffer aBuffer; + sal_uInt16 nByte = 0; + for (size_t i = 0; i < aReason.size(); ++i) + { + if (i % 2 == 0) + nByte = aReason[i]; + else + { + sal_Unicode nUnicode; + nUnicode = (nByte << 8); + nUnicode |= aReason[i]; + aBuffer.append(nUnicode); + } + } + + if (!aBuffer.isEmpty()) + rInformation.ouDescription = aBuffer.makeStringAndClear(); + } + + // Date: used only when the time of signing is not available in the + // signature. + auto pM = dynamic_cast(pValue->Lookup("M")); + if (pM) + { + // Example: "D:20161027100104". + const OString& rM = pM->GetValue(); + if (rM.startsWith("D:") && rM.getLength() >= 16) + { + rInformation.stDateTime.Year = rM.copy(2, 4).toInt32(); + rInformation.stDateTime.Month = rM.copy(6, 2).toInt32(); + rInformation.stDateTime.Day = rM.copy(8, 2).toInt32(); + rInformation.stDateTime.Hours = rM.copy(10, 2).toInt32(); + rInformation.stDateTime.Minutes = rM.copy(12, 2).toInt32(); + rInformation.stDateTime.Seconds = rM.copy(14, 2).toInt32(); + } + } + + // Build a list of offset-length pairs, representing the signed bytes. + std::vector> aByteRanges; + if (!GetByteRangesFromPDF(*pByteRange, aByteRanges)) + { + return false; + } + + // Detect if the byte ranges don't cover everything, but the signature itself. + if (aByteRanges.size() < 2) + { + SAL_WARN("xmlsecurity.pdfio", "ValidateSignature: expected 2 byte ranges"); + return false; + } + if (aByteRanges[0].first != 0) + { + SAL_WARN("xmlsecurity.pdfio", "ValidateSignature: first range start is not 0"); + return false; + } + // 2 is the leading "<" and the trailing ">" around the hex string. + size_t nSignatureLength = static_cast(pContents->GetValue().getLength()) + 2; + if (aByteRanges[1].first != (aByteRanges[0].second + nSignatureLength)) + { + SAL_WARN("xmlsecurity.pdfio", + "ValidateSignature: second range start is not the end of the signature"); + return false; + } + rInformation.bPartialDocumentSignature = !IsCompleteSignature(rStream, rDocument, pSignature); + if (!IsValidSignature(rStream, pSignature, nMDPPerm)) + { + SAL_WARN("xmlsecurity.pdfio", "ValidateSignature: invalid incremental update detected"); + return false; + } + + // At this point there is no obviously missing info to validate the + // signature. + std::vector aSignature = vcl::filter::PDFDocument::DecodeHexString(pContents); + if (aSignature.empty()) + { + SAL_WARN("xmlsecurity.pdfio", "ValidateSignature: empty contents"); + return false; + } + + return svl::crypto::Signing::Verify(rStream, aByteRanges, bNonDetached, aSignature, + rInformation); +} + +} // namespace xmlsecurity::pdfio + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/biginteger.cxx b/xmlsecurity/source/xmlsec/biginteger.cxx new file mode 100644 index 000000000..0bfcbd326 --- /dev/null +++ b/xmlsecurity/source/xmlsec/biginteger.cxx @@ -0,0 +1,108 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +using namespace ::com::sun::star::uno ; + +namespace xmlsecurity +{ +Sequence< sal_Int8 > numericStringToBigInteger ( const OUString& 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( length ) ; + for( xmlSecSize i = 0 ; i < length ; i ++ ) + { + integer[i] = *( bnInteger + i ) ; + } + + 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 000000000..b7b5f1e9d --- /dev/null +++ b/xmlsecurity/source/xmlsec/certificateextension_certextn.cxx @@ -0,0 +1,54 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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" + +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) +{ + unsigned int i ; + if( value != nullptr && vlen != 0 ) { + css::uno::Sequence< sal_Int8 > extnv( vlen ) ; + for( i = 0; i < vlen ; i ++ ) + extnv[i] = *( value + i ) ; + + m_xExtnValue = extnv ; + } else { + m_xExtnValue = css::uno::Sequence(); + } + + if( id != nullptr && idlen != 0 ) { + css::uno::Sequence< sal_Int8 > extnId( idlen ) ; + for( i = 0; i < idlen ; i ++ ) + extnId[i] = *( id + i ) ; + + m_xExtnId = extnId ; + } 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 000000000..bb1ca1439 --- /dev/null +++ b/xmlsecurity/source/xmlsec/certificateextension_certextn.hxx @@ -0,0 +1,38 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_XMLSECURITY_SOURCE_XMLSEC_CERTIFICATEEXTENSION_CERTEXTN_HXX +#define INCLUDED_XMLSECURITY_SOURCE_XMLSEC_CERTIFICATEEXTENSION_CERTEXTN_HXX + +#include +#include + +struct CertificateExtension_CertExtn +{ + bool m_critical; + css::uno::Sequence< sal_Int8 > m_xExtnId; + css::uno::Sequence< sal_Int8 > m_xExtnValue; + + CertificateExtension_CertExtn(); + void setCertExtn(unsigned char const * value, unsigned int vlen, unsigned char const * id, unsigned int idlen, bool critical); +}; + +#endif // INCLUDED_XMLSECURITY_SOURCE_XMLSEC_CERTIFICATEEXTENSION_CERTEXTN_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/certificateextension_xmlsecimpl.hxx b/xmlsecurity/source/xmlsec/certificateextension_xmlsecimpl.hxx new file mode 100644 index 000000000..11e9a0470 --- /dev/null +++ b/xmlsecurity/source/xmlsec/certificateextension_xmlsecimpl.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 . + */ + +#ifndef INCLUDED_XMLSECURITY_SOURCE_XMLSEC_CERTIFICATEEXTENSION_XMLSECIMPL_HXX +#define INCLUDED_XMLSECURITY_SOURCE_XMLSEC_CERTIFICATEEXTENSION_XMLSECIMPL_HXX + +#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); + } +}; + +#endif // INCLUDED_XMLSECURITY_SOURCE_XMLSEC_CERTIFICATEEXTENSION_XMLSECIMPL_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/errorcallback.cxx b/xmlsecurity/source/xmlsec/errorcallback.cxx new file mode 100644 index 000000000..a535ffa77 --- /dev/null +++ b/xmlsecurity/source/xmlsec/errorcallback.cxx @@ -0,0 +1,68 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#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 000000000..ec3cecd4a --- /dev/null +++ b/xmlsecurity/source/xmlsec/mscrypt/akmngr.cxx @@ -0,0 +1,229 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#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 000000000..04b94244b --- /dev/null +++ b/xmlsecurity/source/xmlsec/mscrypt/akmngr.hxx @@ -0,0 +1,59 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_XMLSECURITY_SOURCE_XMLSEC_MSCRYPT_AKMNGR_HXX +#define INCLUDED_XMLSECURITY_SOURCE_XMLSEC_MSCRYPT_AKMNGR_HXX + +#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 +) ; + +} + +#endif // INCLUDED_XMLSECURITY_SOURCE_XMLSEC_MSCRYPT_AKMNGR_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/xmlsecurity/source/xmlsec/mscrypt/oid.hxx b/xmlsecurity/source/xmlsec/mscrypt/oid.hxx new file mode 100644 index 000000000..26986aff7 --- /dev/null +++ b/xmlsecurity/source/xmlsec/mscrypt/oid.hxx @@ -0,0 +1,156 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_XMLSECURITY_SOURCE_XMLSEC_MSCRYPT_OID_HXX +#define INCLUDED_XMLSECURITY_SOURCE_XMLSEC_MSCRYPT_OID_HXX + +#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); + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/mscrypt/sanextension_mscryptimpl.cxx b/xmlsecurity/source/xmlsec/mscrypt/sanextension_mscryptimpl.cxx new file mode 100644 index 000000000..8c58ffada --- /dev/null +++ b/xmlsecurity/source/xmlsec/mscrypt/sanextension_mscryptimpl.cxx @@ -0,0 +1,135 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#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( pOtherName->Value.cbData ) ; + for( unsigned int n = 0; n < static_cast(pOtherName->Value.cbData) ; n ++ ) + otherName[n] = *( pOtherName->Value.pbData + n ) ; + + 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( pEntry->IPAddress.cbData ) ; + for( unsigned int n = 0; n < pEntry->IPAddress.cbData ; n ++ ) + ipAddress[n] = *( pEntry->IPAddress.pbData + n ) ; + + arrCertAltNameEntry[i].Value <<= ipAddress; + break; + } + case CERT_ALT_NAME_REGISTERED_ID : + arrCertAltNameEntry[i].Type = ExtAltNameType_REGISTERED_ID; + arrCertAltNameEntry[i].Value <<= OUString::createFromAscii(pEntry->pszRegisteredID); + break; + } + } + m_Entries = ::comphelper::arrayToSequence< css::security::CertAltNameEntry >(arrCertAltNameEntry.get(), subjectName->cAltEntry); + } + + return m_Entries; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/mscrypt/sanextension_mscryptimpl.hxx b/xmlsecurity/source/xmlsec/mscrypt/sanextension_mscryptimpl.hxx new file mode 100644 index 000000000..9f005a886 --- /dev/null +++ b/xmlsecurity/source/xmlsec/mscrypt/sanextension_mscryptimpl.hxx @@ -0,0 +1,69 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_XMLSECURITY_SOURCE_XMLSEC_MSCRYPT_SANEXTENSION_MSCRYPTIMPL_HXX +#define INCLUDED_XMLSECURITY_SOURCE_XMLSEC_MSCRYPT_SANEXTENSION_MSCRYPTIMPL_HXX + +#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 ) ; +} ; + +#endif // INCLUDED_XMLSECURITY_SOURCE_XMLSEC_MSCRYPT_SANEXTENSION_MSCRYPTIMPL_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.cxx b/xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.cxx new file mode 100644 index 000000000..01b27fb97 --- /dev/null +++ b/xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.cxx @@ -0,0 +1,1066 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +using namespace ::com::sun::star; +using namespace ::com::sun::star::lang ; +using ::com::sun::star::lang::XMultiServiceFactory ; +using ::com::sun::star::lang::XSingleServiceFactory ; + +using ::com::sun::star::xml::crypto::XSecurityEnvironment ; +using ::com::sun::star::security::XCertificate ; + +static X509Certificate_MSCryptImpl* MswcryCertContextToXCert( PCCERT_CONTEXT cert ) ; + +namespace { + +struct CertErrorToString{ + DWORD error; + char const * name; +}; + +} + +CertErrorToString const arErrStrings[] = +{ + { 0x00000000, "CERT_TRUST_NO_ERROR"}, + { 0x00000001, "CERT_TRUST_IS_NOT_TIME_VALID"}, + { 0x00000002, "CERT_TRUST_IS_NOT_TIME_NESTED"}, + { 0x00000004, "CERT_TRUST_IS_REVOKED" }, + { 0x00000008, "CERT_TRUST_IS_NOT_SIGNATURE_VALID" }, + { 0x00000010, "CERT_TRUST_IS_NOT_SIGNATURE_VALID"}, + { 0x00000020, "CERT_TRUST_IS_UNTRUSTED_ROOT"}, + { 0x00000040, "CERT_TRUST_REVOCATION_STATUS_UNKNOWN"}, + { 0x00000080, "CERT_TRUST_IS_CYCLIC"}, + { 0x00000100, "CERT_TRUST_INVALID_EXTENSION"}, + { 0x00000200, "CERT_TRUST_INVALID_POLICY_CONSTRAINTS"}, + { 0x00000400, "CERT_TRUST_INVALID_BASIC_CONSTRAINTS"}, + { 0x00000800, "CERT_TRUST_INVALID_NAME_CONSTRAINTS"}, + { 0x00001000, "CERT_TRUST_HAS_NOT_SUPPORTED_NAME_CONSTRAINT"}, + { 0x00002000, "CERT_TRUST_HAS_NOT_DEFINED_NAME_CONSTRAINT"}, + { 0x00004000, "CERT_TRUST_HAS_NOT_PERMITTED_NAME_CONSTRAINT"}, + { 0x00008000, "CERT_TRUST_HAS_EXCLUDED_NAME_CONSTRAINT"}, + { 0x01000000, "CERT_TRUST_IS_OFFLINE_REVOCATION"}, + { 0x02000000, "CERT_TRUST_NO_ISSUANCE_CHAIN_POLICY"}, + { 0x04000000, "CERT_TRUST_IS_EXPLICIT_DISTRUST"}, + { 0x08000000, "CERT_TRUST_HAS_NOT_SUPPORTED_CRITICAL_EXT"}, + //Chain errors + { 0x00010000, "CERT_TRUST_IS_PARTIAL_CHAIN"}, + { 0x00020000, "CERT_TRUST_CTL_IS_NOT_TIME_VALID"}, + { 0x00040000, "CERT_TRUST_CTL_IS_NOT_SIGNATURE_VALID"}, + { 0x00080000, "CERT_TRUST_CTL_IS_NOT_VALID_FOR_USAGE"} +}; + +static void traceTrustStatus(DWORD err) +{ + if (err == 0) + SAL_INFO("xmlsecurity.xmlsec", " " << arErrStrings[0].name); + for (std::size_t i = 1; i < SAL_N_ELEMENTS(arErrStrings); i++) + { + if (arErrStrings[i].error & err) + SAL_INFO("xmlsecurity.xmlsec", " " << arErrStrings[i].name); + } +} + +SecurityEnvironment_MSCryptImpl::SecurityEnvironment_MSCryptImpl( const uno::Reference< uno::XComponentContext >& xContext ) : m_hProv( NULL ) , 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 != NULL ) { + CryptReleaseContext( m_hProv, 0 ) ; + m_hProv = NULL ; + } + + 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() { + uno::Sequence seqServiceNames { "com.sun.star.xml.crypto.SecurityEnvironment" }; + return seqServiceNames ; +} + +/* XUnoTunnel */ +UNO3_GETIMPLEMENTATION_IMPL(SecurityEnvironment_MSCryptImpl); + +HCRYPTPROV SecurityEnvironment_MSCryptImpl::getCryptoProvider() { + return m_hProv ; +} + +void SecurityEnvironment_MSCryptImpl::setCryptoProvider( HCRYPTPROV aProv ) { + if( m_hProv != NULL ) { + CryptReleaseContext( m_hProv, 0 ) ; + m_hProv = NULL ; + } + + if( aProv != NULL ) { + 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 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 ; + X509Certificate_MSCryptImpl* xcert ; + std::vector< X509Certificate_MSCryptImpl* > certsList ; + PCCERT_CONTEXT pCertContext = nullptr; + + //firstly, we try to find private keys in given key store. + if( m_hKeyStore != nullptr ) { + pCertContext = CertEnumCertificatesInStore( m_hKeyStore, pCertContext ); + while (pCertContext) + { + xcert = MswcryCertContextToXCert( pCertContext ) ; + if( xcert != nullptr ) + 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 != nullptr ) + 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 ) ; + + for( const auto& rXCert : certsList ) { + certSeq[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 ; + X509Certificate_MSCryptImpl *xcert = nullptr ; + PCCERT_CONTEXT pCertContext = nullptr ; + HCERTSTORE hCertStore = nullptr ; + CRYPT_INTEGER_BLOB cryptSerialNumber ; + CERT_INFO certInfo ; + + // for correct encoding + sal_uInt16 encoding ; + rtl_Locale *pLocale = nullptr ; + osl_getProcessLocale( &pLocale ) ; + encoding = osl_getTextEncodingFromLocale( 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); + } else { + xcert = nullptr ; + } + + 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 ; + const X509Certificate_MSCryptImpl* xcert ; + + CERT_ENHKEY_USAGE enhKeyUsage ; + CERT_USAGE_MATCH certUsage ; + CERT_CHAIN_PARA chainPara ; + + enhKeyUsage.cUsageIdentifier = 0 ; + enhKeyUsage.rgpszUsageIdentifier = nullptr ; + certUsage.dwType = USAGE_MATCH_TYPE_AND ; + certUsage.Usage = enhKeyUsage ; + chainPara.cbSize = sizeof( CERT_CHAIN_PARA ) ; + chainPara.RequestedUsage = certUsage ; + + uno::Reference< XUnoTunnel > xCertTunnel( begin, uno::UNO_QUERY_THROW ) ; + xcert = reinterpret_cast(xCertTunnel->getSomething( X509Certificate_MSCryptImpl::getUnoTunnelId() )); + 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 , + NULL , + 0 , + nullptr + ) ; + if (hCollectionStore != nullptr) + { + CertAddStoreToCollection ( + hCollectionStore , + m_hCertStore , + CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG , + 0) ; + CertAddStoreToCollection ( + hCollectionStore , + m_hCertStore , + 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 ; + X509Certificate_MSCryptImpl* pCert ; + + pCertChain = pChainContext->rgpChain[0] ; + if( pCertChain->cElement ) { + uno::Sequence< uno::Reference< XCertificate > > xCertChain( pCertChain->cElement ) ; + + 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 != nullptr ) + xCertChain[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 ) { + X509Certificate_MSCryptImpl* xcert ; + + if( rawCertificate.getLength() > 0 ) { + xcert = new X509Certificate_MSCryptImpl() ; + xcert->setRawCert( rawCertificate ) ; + } else { + xcert = nullptr ; + } + + 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 = xmlSecBase64Decode( chCert, chCert, xmlStrlen( chCert ) ) ; + + uno::Sequence< sal_Int8 > rawCert( certSize ) ; + for( xmlSecSize i = 0 ; i < certSize ; i ++ ) + rawCert[i] = *( chCert + i ) ; + + xmlFree( chCert ) ; + + return createCertificateFromRaw( rawCert ) ; +} + + +static HCERTSTORE getCertStoreForIntermediatCerts( + const uno::Sequence< uno::Reference< css::security::XCertificate > >& seqCerts) +{ + HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, NULL, 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; +} + +//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 = 0; + PCCERT_CHAIN_CONTEXT pChainContext = nullptr; + PCCERT_CONTEXT pCertContext = nullptr; + + uno::Reference< XUnoTunnel > xCertTunnel( aCert, uno::UNO_QUERY_THROW ) ; + + SAL_INFO("xmlsecurity.xmlsec", "Start verification of certificate: " << aCert->getSubjectName()); + + auto xcert = reinterpret_cast + (xCertTunnel->getSomething( X509Certificate_MSCryptImpl::getUnoTunnelId() )); + 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 , + NULL , + 0 , + nullptr + ) ; + if (hCollectionStore != nullptr) + { + CertAddStoreToCollection ( + hCollectionStore , + m_hCertStore , + CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG , + 0) ; + CertAddStoreToCollection ( + hCollectionStore , + m_hCertStore , + 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)) + + { + //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 + { + 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", "CertGetCertificateChaine 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 X509Certificate_MSCryptImpl* xcert ; + + uno::Reference< XUnoTunnel > xCertTunnel( aCert, uno::UNO_QUERY_THROW ) ; + xcert = reinterpret_cast(xCertTunnel->getSomething( X509Certificate_MSCryptImpl::getUnoTunnelId() )); + 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 X509Certificate_MSCryptImpl* MswcryCertContextToXCert( PCCERT_CONTEXT cert ) +{ + X509Certificate_MSCryptImpl* xcert ; + + if( cert != nullptr ) { + xcert = new X509Certificate_MSCryptImpl() ; + xcert->setMswcryCert( cert ) ; + } else { + xcert = nullptr ; + } + + 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 000000000..7064cda13 --- /dev/null +++ b/xmlsecurity/source/xmlsec/mscrypt/securityenvironment_mscryptimpl.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 . + */ + +#ifndef INCLUDED_XMLSECURITY_SOURCE_XMLSEC_MSCRYPT_SECURITYENVIRONMENT_MSCRYPTIMPL_HXX +#define INCLUDED_XMLSECURITY_SOURCE_XMLSEC_MSCRYPT_SECURITYENVIRONMENT_MSCRYPTIMPL_HXX + +#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 + +#include + + +class SecurityEnvironment_MSCryptImpl : public ::cppu::WeakImplHelper< + css::xml::crypto::XSecurityEnvironment , + css::lang::XServiceInfo, + css::lang::XUnoTunnel > +{ + private: + //crypto provider and key container + HCRYPTPROV m_hProv ; + LPCTSTR m_pszContainer ; + + //Key store + HCERTSTORE m_hKeyStore ; + + //Certificate store + HCERTSTORE m_hCertStore ; + + // i120675, save the store handles + HCERTSTORE m_hMySystemStore; + HCERTSTORE m_hRootSystemStore; + HCERTSTORE m_hTrustSystemStore; + HCERTSTORE m_hCaSystemStore; + + //Enable default system cryptography setting + bool m_bEnableDefault ; + + //Service manager + css::uno::Reference< css::lang::XMultiServiceFactory > m_xServiceManager ; + + public: + explicit SecurityEnvironment_MSCryptImpl( const css::uno::Reference< css::uno::XComponentContext >& xContext ) ; + virtual ~SecurityEnvironment_MSCryptImpl() override; + + //Methods from XSecurityEnvironment + virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificate > > SAL_CALL getPersonalCertificates() override; + virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificate > > SAL_CALL getAllCertificates() override + { return css::uno::Sequence< css::uno::Reference< css::security::XCertificate > >(); } + + virtual css::uno::Reference< css::security::XCertificate > SAL_CALL getCertificate( + const OUString& issuerName, + const css::uno::Sequence< sal_Int8 >& serialNumber ) override; + + /// @throws css::uno::SecurityException + /// @throws css::uno::RuntimeException + virtual css::uno::Reference< css::security::XCertificate > getCertificate( + const OUString& issuerName, + const OUString& serialNumber ) ; + + virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificate > > SAL_CALL buildCertificatePath( + const css::uno::Reference< css::security::XCertificate >& beginCert ) override; + + virtual css::uno::Reference< css::security::XCertificate > SAL_CALL createCertificateFromRaw( + const css::uno::Sequence< sal_Int8 >& rawCertificate ) override; + + virtual css::uno::Reference< css::security::XCertificate > SAL_CALL createCertificateFromAscii( + const OUString& asciiCertificate ) override; + + virtual ::sal_Int32 SAL_CALL verifyCertificate( + const css::uno::Reference< css::security::XCertificate >& xCert, + const css::uno::Sequence< css::uno::Reference< + css::security::XCertificate > >& intermediateCertificates) override; + + virtual ::sal_Int32 SAL_CALL getCertificateCharacters( + const css::uno::Reference< css::security::XCertificate >& xCert ) override; + + virtual OUString SAL_CALL getSecurityEnvironmentInformation( ) override; + + + //Methods from XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + + virtual sal_Bool SAL_CALL supportsService( + const OUString& ServiceName + ) override; + + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; + + //Methods from XUnoTunnel + UNO3_GETIMPLEMENTATION_DECL(SecurityEnvironment_MSCryptImpl) + + /// @throws css::uno::Exception + /// @throws css::uno::RuntimeException + HCRYPTPROV getCryptoProvider() ; + /// @throws css::uno::Exception + /// @throws css::uno::RuntimeException + void setCryptoProvider( HCRYPTPROV aProv ) ; + + /// @throws css::uno::Exception + /// @throws css::uno::RuntimeException + LPCTSTR getKeyContainer() ; + /// @throws css::uno::Exception + /// @throws css::uno::RuntimeException + void setKeyContainer( LPCTSTR aKeyContainer ) ; + + /// @throws css::uno::Exception + /// @throws css::uno::RuntimeException + HCERTSTORE getCryptoSlot() ; + /// @throws css::uno::Exception + /// @throws css::uno::RuntimeException + void setCryptoSlot( HCERTSTORE aKeyStore ) ; + + /// @throws css::uno::Exception + /// @throws css::uno::RuntimeException + HCERTSTORE getCertDb() ; + /// @throws css::uno::Exception + /// @throws css::uno::RuntimeException + void setCertDb( HCERTSTORE aCertDb ) ; + + /// @throws css::uno::Exception + /// @throws css::uno::RuntimeException + void enableDefaultCrypt( bool enable ) ; + /// @throws css::uno::Exception + /// @throws css::uno::RuntimeException + bool defaultEnabled() ; + + /// @throws css::uno::Exception + /// @throws css::uno::RuntimeException + xmlSecKeysMngrPtr createKeysManager() ; + + /// @throws css::uno::Exception + /// @throws css::uno::RuntimeException + static void destroyKeysManager(xmlSecKeysMngrPtr pKeysMngr) ; +} ; + +#endif // INCLUDED_XMLSECURITY_SOURCE_XMLSEC_MSCRYPT_SECURITYENVIRONMENT_MSCRYPTIMPL_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/mscrypt/seinitializer_mscryptimpl.cxx b/xmlsecurity/source/xmlsec/mscrypt/seinitializer_mscryptimpl.cxx new file mode 100644 index 000000000..00b6e12f7 --- /dev/null +++ b/xmlsecurity/source/xmlsec/mscrypt/seinitializer_mscryptimpl.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 "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 = OString(sCertDB.getStr(), sCertDB.getLength(), RTL_TEXTENCODING_ASCII_US); + n_pCertStore = sCertDir.getStr(); + n_hStoreHandle = CertOpenSystemStoreW( NULL, o3tl::toW(sCertDB.getStr())) ; + if( n_hStoreHandle == nullptr ) + { + return nullptr; + } + } + else + { + n_pCertStore = nullptr ; + n_hStoreHandle = nullptr ; + } + + xmlSecMSCngAppInit(n_pCertStore); + + try { + /* Build Security Environment */ + uno::Reference< cssxc::XSecurityEnvironment > xSecEnv = cssxc::SecurityEnvironment::create( mxContext ); + + /* Setup key slot and certDb */ + uno::Reference< cssl::XUnoTunnel > xSecEnvTunnel( xSecEnv, uno::UNO_QUERY_THROW ); + SecurityEnvironment_MSCryptImpl* pSecEnv = reinterpret_cast(xSecEnvTunnel->getSomething( SecurityEnvironment_MSCryptImpl::getUnoTunnelId() )); + 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( xEnvTunnel.is() ) + { + SecurityEnvironment_MSCryptImpl* pSecEnv = ( SecurityEnvironment_MSCryptImpl* )xEnvTunnel->getSomething( SecurityEnvironment_MSCryptImpl::getUnoTunnelId() ) ; + 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() +{ + uno::Sequence aRet { "com.sun.star.xml.crypto.SEInitializer" }; + return aRet; +} + +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 000000000..145124a97 --- /dev/null +++ b/xmlsecurity/source/xmlsec/mscrypt/seinitializer_mscryptimpl.hxx @@ -0,0 +1,74 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_XMLSECURITY_SOURCE_XMLSEC_MSCRYPT_SEINITIALIZER_MSCRYPTIMPL_HXX +#define INCLUDED_XMLSECURITY_SOURCE_XMLSEC_MSCRYPT_SEINITIALIZER_MSCRYPTIMPL_HXX + +#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; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx b/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx new file mode 100644 index 000000000..0e619b280 --- /dev/null +++ b/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx @@ -0,0 +1,652 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 "sanextension_mscryptimpl.hxx" + +#include "oid.hxx" + +#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, const OUString& sTypeName) +{ + std::pair< sal_Int32, sal_Int32 > retVal; + bool bInEscape = false; + bool bInValue = false; + bool bFound = false; + sal_Int32 nTypeNameStart = 0; + sal_Int32 length = rRawString.getLength(); + + for (sal_Int32 i = 0; i < length; i++) + { + sal_Unicode c = rRawString[i]; + + if (c == '=') + { + if (! bInValue) + { + OUString sType = rRawString.copy(nTypeNameStart, i - nTypeNameStart); + sType = sType.trim(); + if (sType.equalsIgnoreAsciiCase(sTypeName)) + { + bFound = true; + break; + } + } + } + else if (c == '"') + { + if (!bInEscape) + { + //If this is the quote is the first of the couple which enclose the + //whole value, because the value contains special characters + //then we just drop it. That is, this character must be followed by + //a character which is not '"'. + if ( i + 1 < length && rRawString[i+1] == '"') + bInEscape = true; + else + bInValue = !bInValue; //value is enclosed in " " + } + else + { + //This quote is escaped by a preceding quote and therefore is + //part of the value + bInEscape = false; + } + } + else if (c == ',' || c == '+') + { + //The comma separate the attribute value pairs. + //If the comma is not part of a value (the value would then be enclosed in '"'), + //then we have reached the end of the value + if (!bInValue) + { + //The next char is the start of the new type + nTypeNameStart = i + 1; + } + } + } + + //Found the Type Name, but there can still be spaces after the last comma + //and the beginning of the type. + if (bFound) + { + while (true) + { + sal_Unicode c = rRawString[nTypeNameStart]; + if (c != ' ' && c != '\t') + //found + break; + nTypeNameStart ++; + } + // search end (one after last letter) + sal_Int32 nTypeNameEnd = nTypeNameStart; + nTypeNameEnd++; + while (true) + { + sal_Unicode c = rRawString[nTypeNameEnd]; + if (c == ' ' || c == '\t' || c == '=') + break; + nTypeNameEnd++; + } + retVal = std::make_pair(nTypeNameStart, nTypeNameEnd); + } + else + { + retVal = std::make_pair(-1, -1); + } + return retVal; +} + + +/* + MS Crypto uses the 'S' tag (equal to the 'ST' tag in NSS), but the NSS can't recognise + it, so the 'S' tag should be changed to 'ST' tag. However I am not sure if this is necessary + anymore, because we provide always the signers certificate when signing. So libmlsec can find + the private key based on the provided certificate (X509Certificate element) and does not need + the issuer name (X509IssuerName element). The issuer name in the xml signature has also no + effect for the signature nor the certificate validation. + In many RFCs, for example 4519, on speaks of 'ST'. However, the certificate does not contain + strings for type names. Instead it uses OIDs. + */ + +static OUString replaceTagSWithTagST(OUString const & oldDN) +{ + std::pair pairIndex = findTypeInDN(oldDN, "S"); + + if (pairIndex.first != -1) + { + return oldDN.copy(0, pairIndex.first)+"ST"+oldDN.copy(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 ) ; + for( unsigned int i = 0 ; i < m_pCertContext->pCertInfo->SerialNumber.cbData ; i ++ ) + serial[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 ) ; + for( unsigned int i = 0 ; i < m_pCertContext->pCertInfo->IssuerUniqueId.cbData; i ++ ) + issuerUid[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 ) ; + for( unsigned int i = 0 ; i < m_pCertContext->pCertInfo->SubjectUniqueId.cbData; i ++ ) + subjectUid[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 ) { + CertificateExtension_XmlSecImpl* xExtn ; + Sequence< Reference< XCertificateExtension > > xExtns( m_pCertContext->pCertInfo->cExtension ) ; + + 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 ) ; + + xExtns[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 ) { + CertificateExtension_XmlSecImpl* xExtn ; + + xExtn = nullptr ; + 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 ) ; + + for( unsigned int i = 0 ; i < m_pCertContext->cbCertEncoded ; i ++ ) + rawCert[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() ) ; + } +} + +/* XUnoTunnel */ +UNO3_GETIMPLEMENTATION_IMPL(X509Certificate_MSCryptImpl); + +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 ) ; + for( unsigned int i = 0 ; i < cbData ; i ++ ) + { + thumbprint[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 ) ; + for( unsigned int i = 0 ; i < publicKey.cbData ; i++ ) + { + key[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() }; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.hxx b/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.hxx new file mode 100644 index 000000000..225d5f6bd --- /dev/null +++ b/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.hxx @@ -0,0 +1,99 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_XMLSECURITY_SOURCE_XMLSEC_MSCRYPT_X509CERTIFICATE_MSCRYPTIMPL_HXX +#define INCLUDED_XMLSECURITY_SOURCE_XMLSEC_MSCRYPT_X509CERTIFICATE_MSCRYPTIMPL_HXX + +#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 + +class X509Certificate_MSCryptImpl : public ::cppu::WeakImplHelper< + css::security::XCertificate , + css::lang::XUnoTunnel, + css::lang::XServiceInfo > , public xmlsecurity::Certificate +{ + private: + const CERT_CONTEXT* m_pCertContext ; + + public: + X509Certificate_MSCryptImpl() ; + virtual ~X509Certificate_MSCryptImpl() override; + + //Methods from XCertificate + virtual sal_Int16 SAL_CALL getVersion() override; + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSerialNumber() override; + virtual OUString SAL_CALL getIssuerName() override; + virtual OUString SAL_CALL getSubjectName() override; + virtual css::util::DateTime SAL_CALL getNotValidBefore() override; + virtual css::util::DateTime SAL_CALL getNotValidAfter() override; + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getIssuerUniqueID() override; + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSubjectUniqueID() override; + virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificateExtension > > SAL_CALL getExtensions() override; + virtual css::uno::Reference< css::security::XCertificateExtension > SAL_CALL findCertificateExtension( const css::uno::Sequence< sal_Int8 >& oid ) override; + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getEncoded() override; + virtual OUString SAL_CALL getSubjectPublicKeyAlgorithm() override; + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSubjectPublicKeyValue() override; + virtual OUString SAL_CALL getSignatureAlgorithm() override; + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSHA1Thumbprint() override; + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getMD5Thumbprint() override; + virtual css::security::CertificateKind SAL_CALL getCertificateKind() override; + + + virtual sal_Int32 SAL_CALL getCertificateUsage( ) override; + + //Methods from XUnoTunnel + UNO3_GETIMPLEMENTATION_DECL(X509Certificate_MSCryptImpl) + + /// @see xmlsecurity::Certificate::getSHA256Thumbprint(). + virtual css::uno::Sequence 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; +} ; + +#endif // INCLUDED_XMLSECURITY_SOURCE_XMLSEC_MSCRYPT_X509CERTIFICATE_MSCRYPTIMPL_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/mscrypt/xmlsecuritycontext_mscryptimpl.cxx b/xmlsecurity/source/xmlsec/mscrypt/xmlsecuritycontext_mscryptimpl.cxx new file mode 100644 index 000000000..2f33df7c9 --- /dev/null +++ b/xmlsecurity/source/xmlsec/mscrypt/xmlsecuritycontext_mscryptimpl.cxx @@ -0,0 +1,156 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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::lang::XMultiServiceFactory ; +using ::com::sun::star::lang::XSingleServiceFactory ; + +using ::com::sun::star::xml::crypto::XSecurityEnvironment ; +using ::com::sun::star::xml::crypto::XXMLSecurityContext ; + +namespace { + +class XMLSecurityContext_MSCryptImpl : public ::cppu::WeakImplHelper< + css::xml::crypto::XXMLSecurityContext , + css::lang::XServiceInfo > +{ + private: + //xmlSecKeysMngrPtr m_pKeysMngr ; + css::uno::Reference< css::xml::crypto::XSecurityEnvironment > m_xSecurityEnvironment ; + + public: + XMLSecurityContext_MSCryptImpl(); + + //Methods from XXMLSecurityContext + virtual sal_Int32 SAL_CALL addSecurityEnvironment( + const css::uno::Reference< css::xml::crypto::XSecurityEnvironment >& aSecurityEnvironment + ) override; + + virtual ::sal_Int32 SAL_CALL getSecurityEnvironmentNumber( ) override; + + virtual css::uno::Reference< + css::xml::crypto::XSecurityEnvironment > SAL_CALL + getSecurityEnvironmentByIndex( ::sal_Int32 index ) override; + + virtual css::uno::Reference< + css::xml::crypto::XSecurityEnvironment > SAL_CALL + getSecurityEnvironment( ) override; + + virtual ::sal_Int32 SAL_CALL getDefaultSecurityEnvironmentIndex( ) override; + + virtual void SAL_CALL setDefaultSecurityEnvironmentIndex( sal_Int32 nDefaultEnvIndex ) override; + + + //Methods from XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + + virtual sal_Bool SAL_CALL supportsService( + const OUString& ServiceName + ) override; + + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; +}; + +} + +XMLSecurityContext_MSCryptImpl::XMLSecurityContext_MSCryptImpl() +{ +} + +sal_Int32 SAL_CALL XMLSecurityContext_MSCryptImpl::addSecurityEnvironment( + const css::uno::Reference< css::xml::crypto::XSecurityEnvironment >& aSecurityEnvironment) +{ + if( !aSecurityEnvironment.is() ) + { + throw uno::RuntimeException() ; + } + + m_xSecurityEnvironment = aSecurityEnvironment; + + return 0; +} + + +sal_Int32 SAL_CALL XMLSecurityContext_MSCryptImpl::getSecurityEnvironmentNumber( ) +{ + return 1; +} + +css::uno::Reference< css::xml::crypto::XSecurityEnvironment > SAL_CALL + XMLSecurityContext_MSCryptImpl::getSecurityEnvironmentByIndex( sal_Int32 index ) +{ + if (index != 0) + { + throw uno::RuntimeException() ; + } + return m_xSecurityEnvironment; +} + +css::uno::Reference< css::xml::crypto::XSecurityEnvironment > SAL_CALL + XMLSecurityContext_MSCryptImpl::getSecurityEnvironment( ) +{ + return m_xSecurityEnvironment; +} + +sal_Int32 SAL_CALL XMLSecurityContext_MSCryptImpl::getDefaultSecurityEnvironmentIndex( ) +{ + return 0; +} + +void SAL_CALL XMLSecurityContext_MSCryptImpl::setDefaultSecurityEnvironmentIndex( sal_Int32 /*nDefaultEnvIndex*/ ) +{ + //dummy +} + +/* XServiceInfo */ +OUString SAL_CALL XMLSecurityContext_MSCryptImpl::getImplementationName() { + return "com.sun.star.xml.crypto.XMLSecurityContext" ; +} + +/* XServiceInfo */ +sal_Bool SAL_CALL XMLSecurityContext_MSCryptImpl::supportsService( const OUString& serviceName) { + return cppu::supportsService(this, serviceName); +} + +/* XServiceInfo */ +uno::Sequence< OUString > SAL_CALL XMLSecurityContext_MSCryptImpl::getSupportedServiceNames() { + uno::Sequence seqServiceNames { "com.sun.star.xml.crypto.XMLSecurityContext" }; + return seqServiceNames ; +} + +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 000000000..dcbad0348 --- /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 "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::lang::XMultiServiceFactory ; +using ::com::sun::star::lang::XSingleServiceFactory ; + +using ::com::sun::star::xml::wrapper::XXMLElementWrapper ; +using ::com::sun::star::xml::wrapper::XXMLDocumentWrapper ; +using ::com::sun::star::xml::crypto::XSecurityEnvironment ; +using ::com::sun::star::xml::crypto::XXMLSignature ; +using ::com::sun::star::xml::crypto::XXMLSignatureTemplate ; +using ::com::sun::star::xml::crypto::XXMLSecurityContext ; +using ::com::sun::star::xml::crypto::XUriBinding ; + +namespace { + +class XMLSignature_MSCryptImpl : public ::cppu::WeakImplHelper< + css::xml::crypto::XXMLSignature , + css::lang::XServiceInfo > +{ + public: + explicit XMLSignature_MSCryptImpl(); + + //Methods from XXMLSignature + virtual css::uno::Reference< css::xml::crypto::XXMLSignatureTemplate > SAL_CALL generate( + const css::uno::Reference< css::xml::crypto::XXMLSignatureTemplate >& aTemplate , + const css::uno::Reference< css::xml::crypto::XSecurityEnvironment >& aEnvironment + ) override; + + virtual css::uno::Reference< css::xml::crypto::XXMLSignatureTemplate > SAL_CALL validate( + const css::uno::Reference< css::xml::crypto::XXMLSignatureTemplate >& aTemplate , + const css::uno::Reference< css::xml::crypto::XXMLSecurityContext >& aContext + ) override; + + //Methods from XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + + virtual sal_Bool SAL_CALL supportsService( + const OUString& ServiceName + ) override; + + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; +} ; + +} + +XMLSignature_MSCryptImpl::XMLSignature_MSCryptImpl() { +} + +/* XXMLSignature */ +Reference< XXMLSignatureTemplate > +SAL_CALL XMLSignature_MSCryptImpl::generate( + const Reference< XXMLSignatureTemplate >& aTemplate , + const Reference< XSecurityEnvironment >& aEnvironment +) +{ + xmlSecKeysMngrPtr pMngr = nullptr ; + xmlSecDSigCtxPtr pDsigCtx = nullptr ; + xmlNodePtr pNode = nullptr ; + + if( !aTemplate.is() ) + throw RuntimeException() ; + + if( !aEnvironment.is() ) + throw RuntimeException() ; + + //Get Keys Manager + Reference< XUnoTunnel > xSecTunnel( aEnvironment , UNO_QUERY_THROW ) ; + SecurityEnvironment_MSCryptImpl* pSecEnv = reinterpret_cast(xSecTunnel->getSomething( SecurityEnvironment_MSCryptImpl::getUnoTunnelId() )); + if( pSecEnv == nullptr ) + throw RuntimeException() ; + + //Get the xml node + Reference< XXMLElementWrapper > xElement = aTemplate->getTemplate() ; + if( !xElement.is() ) { + throw RuntimeException() ; + } + + Reference< XUnoTunnel > xNodTunnel( xElement , UNO_QUERY_THROW ) ; + XMLElementWrapper_XmlSecImpl* pElement = reinterpret_cast(xNodTunnel->getSomething( XMLElementWrapper_XmlSecImpl::getUnoTunnelId() )); + if( pElement == nullptr ) { + throw RuntimeException() ; + } + + pNode = pElement->getNativeElement() ; + + //Get the stream/URI binding + Reference< XUriBinding > xUriBinding = aTemplate->getBinding() ; + if( xUriBinding.is() ) { + //Register the stream input callbacks into libxml2 + if( xmlRegisterStreamInputCallbacks( xUriBinding ) < 0 ) + throw RuntimeException() ; + } + + setErrorRecorder( ); + + pMngr = pSecEnv->createKeysManager(); + if( !pMngr ) { + throw RuntimeException() ; + } + + //Create Signature context + pDsigCtx = xmlSecDSigCtxCreate( pMngr ) ; + if( pDsigCtx == nullptr ) + { + //throw XMLSignatureException() ; + SecurityEnvironment_MSCryptImpl::destroyKeysManager( pMngr ); + clearErrorRecorder(); + return aTemplate; + } + + //Sign the template + if( xmlSecDSigCtxSign( pDsigCtx , pNode ) == 0 ) + { + if (pDsigCtx->status == xmlSecDSigStatusSucceeded) + aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED); + else + aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_UNKNOWN); + } + else + { + aTemplate->setStatus(css::xml::crypto::SecurityOperationStatus_UNKNOWN); + } + + + xmlSecDSigCtxDestroy( pDsigCtx ) ; + SecurityEnvironment_MSCryptImpl::destroyKeysManager( pMngr ); + + //Unregistered the stream/URI binding + if( xUriBinding.is() ) + xmlUnregisterStreamInputCallbacks() ; + + clearErrorRecorder(); + return aTemplate ; +} + +/* XXMLSignature */ +Reference< XXMLSignatureTemplate > +SAL_CALL XMLSignature_MSCryptImpl::validate( + const Reference< XXMLSignatureTemplate >& aTemplate , + const Reference< XXMLSecurityContext >& aSecurityCtx +) { + xmlSecKeysMngrPtr pMngr = nullptr ; + xmlSecDSigCtxPtr pDsigCtx = nullptr ; + xmlNodePtr pNode = nullptr ; + + if( !aTemplate.is() ) + throw RuntimeException() ; + + if( !aSecurityCtx.is() ) + throw RuntimeException() ; + + //Get Keys Manager + Reference< XSecurityEnvironment > xSecEnv + = aSecurityCtx->getSecurityEnvironmentByIndex( + aSecurityCtx->getDefaultSecurityEnvironmentIndex()); + Reference< XUnoTunnel > xSecTunnel( xSecEnv , UNO_QUERY_THROW ) ; + SecurityEnvironment_MSCryptImpl* pSecEnv = reinterpret_cast(xSecTunnel->getSomething( SecurityEnvironment_MSCryptImpl::getUnoTunnelId() )); + if( pSecEnv == nullptr ) + throw RuntimeException() ; + + //Get the xml node + Reference< XXMLElementWrapper > xElement = aTemplate->getTemplate() ; + if( !xElement.is() ) + throw RuntimeException() ; + + Reference< XUnoTunnel > xNodTunnel( xElement , UNO_QUERY_THROW ) ; + XMLElementWrapper_XmlSecImpl* pElement = reinterpret_cast(xNodTunnel->getSomething( XMLElementWrapper_XmlSecImpl::getUnoTunnelId() )); + 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; + + //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; + } + } + + 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() { + Sequence seqServiceNames { "com.sun.star.xml.crypto.XMLSignature" }; + return seqServiceNames ; +} + +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 000000000..e8b7b3873 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/certerrors.h @@ -0,0 +1,385 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +{SEC_ERROR_IO, "An I/O error occurred during security authorization."}, + +{SEC_ERROR_LIBRARY_FAILURE, "security library failure."}, + +{SEC_ERROR_BAD_DATA, "security library: received bad data."}, + +{SEC_ERROR_OUTPUT_LEN, "security library: output length error."}, + +{SEC_ERROR_INPUT_LEN, "security library has experienced an input length error."}, + +{SEC_ERROR_INVALID_ARGS, "security library: invalid arguments."}, + +{SEC_ERROR_INVALID_ALGORITHM, "security library: invalid algorithm."}, + +{SEC_ERROR_INVALID_AVA, "security library: invalid AVA."}, + +{SEC_ERROR_INVALID_TIME, "Improperly formatted time string."}, + +{SEC_ERROR_BAD_DER, "security library: improperly formatted DER-encoded message."}, + +{SEC_ERROR_BAD_SIGNATURE, "Peer's certificate has an invalid signature."}, + +{SEC_ERROR_EXPIRED_CERTIFICATE, "Peer's Certificate has expired."}, + +{SEC_ERROR_REVOKED_CERTIFICATE, "Peer's Certificate has been revoked."}, + +{SEC_ERROR_UNKNOWN_ISSUER, "Peer's Certificate issuer is not recognized."}, + +{SEC_ERROR_BAD_KEY, "Peer's public key is invalid."}, + +{SEC_ERROR_BAD_PASSWORD, "The security password entered is incorrect."}, + +{SEC_ERROR_RETRY_PASSWORD, "New password entered incorrectly. Please try again."}, + +{SEC_ERROR_NO_NODELOCK, "security library: no nodelock."}, + +{SEC_ERROR_BAD_DATABASE, "security library: bad database."}, + +{SEC_ERROR_NO_MEMORY, "security library: memory allocation failure."}, + +{SEC_ERROR_UNTRUSTED_ISSUER, "Peer's certificate issuer has been marked as not trusted by the user."}, + +{SEC_ERROR_UNTRUSTED_CERT, "Peer's certificate has been marked as not trusted by the user."}, + +{SEC_ERROR_DUPLICATE_CERT, "Certificate already exists in your database."}, + +{SEC_ERROR_DUPLICATE_CERT_NAME, "Downloaded certificate's name duplicates one already in your database."}, + +{SEC_ERROR_ADDING_CERT, "Error adding certificate to database."}, + +{SEC_ERROR_FILING_KEY, "Error refiling the key for this certificate."}, + +{SEC_ERROR_NO_KEY, "The private key for this certificate cannot be found in key database"}, + +{SEC_ERROR_CERT_VALID, "This certificate is valid."}, + +{SEC_ERROR_CERT_NOT_VALID, "This certificate is not valid."}, + +{SEC_ERROR_CERT_NO_RESPONSE, "Cert Library: No Response"}, + +{SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE, "The certificate issuer's certificate has expired. Check your system date and time."}, + +{SEC_ERROR_CRL_EXPIRED, "The CRL for the certificate's issuer has expired. Update it or check your system date and time."}, + +{SEC_ERROR_CRL_BAD_SIGNATURE, "The CRL for the certificate's issuer has an invalid signature."}, + +{SEC_ERROR_CRL_INVALID, "New CRL has an invalid format."}, + +{SEC_ERROR_EXTENSION_VALUE_INVALID, "Certificate extension value is invalid."}, + +{SEC_ERROR_EXTENSION_NOT_FOUND, "Certificate extension not found."}, + +{SEC_ERROR_CA_CERT_INVALID, "Issuer certificate is invalid."}, + +{SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID, "Certificate path length constraint is invalid."}, + +{SEC_ERROR_CERT_USAGES_INVALID, "Certificate usages field is invalid."}, + +{SEC_INTERNAL_ONLY, "**Internal ONLY module**"}, + +{SEC_ERROR_INVALID_KEY, "The key does not support the requested operation."}, + +{SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION, "Certificate contains unknown critical extension."}, + +{SEC_ERROR_OLD_CRL, "New CRL is not later than the current one."}, + +{SEC_ERROR_NO_EMAIL_CERT, "Not encrypted or signed: you do not yet have an email certificate."}, + +{SEC_ERROR_NO_RECIPIENT_CERTS_QUERY, "Not encrypted: you do not have certificates for each of the recipients."}, + +{SEC_ERROR_NOT_A_RECIPIENT, "Cannot decrypt: you are not a recipient, or matching certificate and \ +private key not found."}, + +{SEC_ERROR_PKCS7_KEYALG_MISMATCH, "Cannot decrypt: key encryption algorithm does not match your certificate."}, + +{SEC_ERROR_PKCS7_BAD_SIGNATURE, "Signature verification failed: no signer found, too many signers found, \ +or improper or corrupted data."}, + +{SEC_ERROR_UNSUPPORTED_KEYALG, "Unsupported or unknown key algorithm."}, + +{SEC_ERROR_DECRYPTION_DISALLOWED, "Cannot decrypt: encrypted using a disallowed algorithm or key size."}, + + +/* Fortezza Alerts */ +{XP_SEC_FORTEZZA_BAD_CARD, "Fortezza card has not been properly initialized. \ +Please remove it and return it to your issuer."}, + +{XP_SEC_FORTEZZA_NO_CARD, "No Fortezza cards Found"}, + +{XP_SEC_FORTEZZA_NONE_SELECTED, "No Fortezza card selected"}, + +{XP_SEC_FORTEZZA_MORE_INFO, "Please select a personality to get more info on"}, + +{XP_SEC_FORTEZZA_PERSON_NOT_FOUND, "Personality not found"}, + +{XP_SEC_FORTEZZA_NO_MORE_INFO, "No more information on that Personality"}, + +{XP_SEC_FORTEZZA_BAD_PIN, "Invalid Pin"}, + +{XP_SEC_FORTEZZA_PERSON_ERROR, "Couldn't initialize Fortezza personalities."}, +/* end fortezza alerts. */ + +{SEC_ERROR_NO_KRL, "No KRL for this site's certificate has been found."}, + +{SEC_ERROR_KRL_EXPIRED, "The KRL for this site's certificate has expired."}, + +{SEC_ERROR_KRL_BAD_SIGNATURE, "The KRL for this site's certificate has an invalid signature."}, + +{SEC_ERROR_REVOKED_KEY, "The key for this site's certificate has been revoked."}, + +{SEC_ERROR_KRL_INVALID, "New KRL has an invalid format."}, + +{SEC_ERROR_NEED_RANDOM, "security library: need random data."}, + +{SEC_ERROR_NO_MODULE, "security library: no security module can perform the requested operation."}, + +{SEC_ERROR_NO_TOKEN, "The security card or token does not exist, needs to be initialized, or has been removed."}, + +{SEC_ERROR_READ_ONLY, "security library: read-only database."}, + +{SEC_ERROR_NO_SLOT_SELECTED, "No slot or token was selected."}, + +{SEC_ERROR_CERT_NICKNAME_COLLISION, "A certificate with the same nickname already exists."}, + +{SEC_ERROR_KEY_NICKNAME_COLLISION, "A key with the same nickname already exists."}, + +{SEC_ERROR_SAFE_NOT_CREATED, "error while creating safe object"}, + +{SEC_ERROR_BAGGAGE_NOT_CREATED, "error while creating baggage object"}, + +{XP_JAVA_REMOVE_PRINCIPAL_ERROR, "Couldn't remove the principal"}, + +{XP_JAVA_DELETE_PRIVILEGE_ERROR, "Couldn't delete the privilege"}, + +{XP_JAVA_CERT_NOT_EXISTS_ERROR, "This principal doesn't have a certificate"}, + +{SEC_ERROR_BAD_EXPORT_ALGORITHM, "Required algorithm is not allowed."}, + +{SEC_ERROR_EXPORTING_CERTIFICATES, "Error attempting to export certificates."}, + +{SEC_ERROR_IMPORTING_CERTIFICATES, "Error attempting to import certificates."}, + +{SEC_ERROR_PKCS12_DECODING_PFX, "Unable to import. Decoding error. File not valid."}, + +{SEC_ERROR_PKCS12_INVALID_MAC, "Unable to import. Invalid MAC. Incorrect password or corrupt file."}, + +{SEC_ERROR_PKCS12_UNSUPPORTED_MAC_ALGORITHM, "Unable to import. MAC algorithm not supported."}, + +{SEC_ERROR_PKCS12_UNSUPPORTED_TRANSPORT_MODE, "Unable to import. Only password integrity and privacy modes supported."}, + +{SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE, "Unable to import. File structure is corrupt."}, + +{SEC_ERROR_PKCS12_UNSUPPORTED_PBE_ALGORITHM, "Unable to import. Encryption algorithm not supported."}, + +{SEC_ERROR_PKCS12_UNSUPPORTED_VERSION, "Unable to import. File version not supported."}, + +{SEC_ERROR_PKCS12_PRIVACY_PASSWORD_INCORRECT, "Unable to import. Incorrect privacy password."}, + +{SEC_ERROR_PKCS12_CERT_COLLISION, "Unable to import. Same nickname already exists in database."}, + +{SEC_ERROR_USER_CANCELLED, "The user pressed cancel."}, + +{SEC_ERROR_PKCS12_DUPLICATE_DATA, "Not imported, already in database."}, + +{SEC_ERROR_MESSAGE_SEND_ABORTED, "Message not sent."}, + +{SEC_ERROR_INADEQUATE_KEY_USAGE, "Certificate key usage inadequate for attempted operation."}, + +{SEC_ERROR_INADEQUATE_CERT_TYPE, "Certificate type not approved for application."}, + +{SEC_ERROR_CERT_ADDR_MISMATCH, "Address in signing certificate does not match address in message headers."}, + +{SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY, "Unable to import. Error attempting to import private key."}, + +{SEC_ERROR_PKCS12_IMPORTING_CERT_CHAIN, "Unable to import. Error attempting to import certificate chain."}, + +{SEC_ERROR_PKCS12_UNABLE_TO_LOCATE_OBJECT_BY_NAME, "Unable to export. Unable to locate certificate or key by nickname."}, + +{SEC_ERROR_PKCS12_UNABLE_TO_EXPORT_KEY, "Unable to export. Private Key could not be located and exported."}, + +{SEC_ERROR_PKCS12_UNABLE_TO_WRITE, "Unable to export. Unable to write the export file."}, + +{SEC_ERROR_PKCS12_UNABLE_TO_READ, "Unable to import. Unable to read the import file."}, + +{SEC_ERROR_PKCS12_KEY_DATABASE_NOT_INITIALIZED, "Unable to export. Key database corrupt or deleted."}, + +{SEC_ERROR_KEYGEN_FAIL, "Unable to generate public/private key pair."}, + +{SEC_ERROR_INVALID_PASSWORD, "Password entered is invalid. Please pick a different one."}, + +{SEC_ERROR_RETRY_OLD_PASSWORD, "Old password entered incorrectly. Please try again."}, + +{SEC_ERROR_BAD_NICKNAME, "Certificate nickname already in use."}, + +{SEC_ERROR_NOT_FORTEZZA_ISSUER, "Peer FORTEZZA chain has a non-FORTEZZA Certificate."}, + +{SEC_ERROR_CANNOT_MOVE_SENSITIVE_KEY, "A sensitive key cannot be moved to the slot where it is needed."}, + +{SEC_ERROR_JS_INVALID_MODULE_NAME, "Invalid module name."}, + +{SEC_ERROR_JS_INVALID_DLL, "Invalid module path/filename"}, + +{SEC_ERROR_JS_ADD_MOD_FAILURE, "Unable to add module"}, + +{SEC_ERROR_JS_DEL_MOD_FAILURE, "Unable to delete module"}, + +{SEC_ERROR_OLD_KRL, "New KRL is not later than the current one."}, + +{SEC_ERROR_CKL_CONFLICT, "New CKL has different issuer than current CKL. Delete current CKL."}, + +{SEC_ERROR_CERT_NOT_IN_NAME_SPACE, "The Certifying Authority for this certificate is not permitted to issue a \ +certificate with this name."}, + +{SEC_ERROR_KRL_NOT_YET_VALID, "The key revocation list for this certificate is not yet valid."}, + +{SEC_ERROR_CRL_NOT_YET_VALID, "The certificate revocation list for this certificate is not yet valid."}, + +{SEC_ERROR_UNKNOWN_CERT, "The requested certificate could not be found."}, + +{SEC_ERROR_UNKNOWN_SIGNER, "The signer's certificate could not be found."}, + +{SEC_ERROR_CERT_BAD_ACCESS_LOCATION, "The location for the certificate status server has invalid format."}, + +{SEC_ERROR_OCSP_UNKNOWN_RESPONSE_TYPE, "The OCSP response cannot be fully decoded; it is of an unknown type."}, + +{SEC_ERROR_OCSP_BAD_HTTP_RESPONSE, "The OCSP server returned unexpected/invalid HTTP data."}, + +{SEC_ERROR_OCSP_MALFORMED_REQUEST, "The OCSP server found the request to be corrupted or improperly formed."}, + +{SEC_ERROR_OCSP_SERVER_ERROR, "The OCSP server experienced an internal error."}, + +{SEC_ERROR_OCSP_TRY_SERVER_LATER, "The OCSP server suggests trying again later."}, + +{SEC_ERROR_OCSP_REQUEST_NEEDS_SIG, "The OCSP server requires a signature on this request."}, + +{SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST, "The OCSP server has refused this request as unauthorized."}, + +{SEC_ERROR_OCSP_UNKNOWN_RESPONSE_STATUS, "The OCSP server returned an unrecognizable status."}, + +{SEC_ERROR_OCSP_UNKNOWN_CERT, "The OCSP server has no status for the certificate."}, + +{SEC_ERROR_OCSP_NOT_ENABLED, "You must enable OCSP before performing this operation."}, + +{SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER, "You must set the OCSP default responder before performing this operation."}, + +{SEC_ERROR_OCSP_MALFORMED_RESPONSE, "The response from the OCSP server was corrupted or improperly formed."}, + +{SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE, "The signer of the OCSP response is not authorized to give status for \ +this certificate."}, + +{SEC_ERROR_OCSP_FUTURE_RESPONSE, "The OCSP response is not yet valid (contains a date in the future},."}, + +{SEC_ERROR_OCSP_OLD_RESPONSE, "The OCSP response contains out-of-date information."}, + +{SEC_ERROR_DIGEST_NOT_FOUND, "The CMS or PKCS #7 Digest was not found in signed message."}, + +{SEC_ERROR_UNSUPPORTED_MESSAGE_TYPE, "The CMS or PKCS #7 Message type is unsupported."}, + +{SEC_ERROR_MODULE_STUCK, "PKCS #11 module could not be removed because it is still in use."}, + +{SEC_ERROR_BAD_TEMPLATE, "Could not decode ASN.1 data. Specified template was invalid."}, + +{SEC_ERROR_CRL_NOT_FOUND, "No matching CRL was found."}, + +{SEC_ERROR_REUSED_ISSUER_AND_SERIAL, "You are attempting to import a cert with the same issuer/serial as \ +an existing cert, but that is not the same cert."}, + +{SEC_ERROR_BUSY, "NSS could not shutdown. Objects are still in use."}, + +{SEC_ERROR_EXTRA_INPUT, "DER-encoded message contained extra unused data."}, + +{SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE, "Unsupported elliptic curve."}, + +{SEC_ERROR_UNSUPPORTED_EC_POINT_FORM, "Unsupported elliptic curve point form."}, + +{SEC_ERROR_UNRECOGNIZED_OID, "Unrecognized Object Identifier."}, + +{SEC_ERROR_OCSP_INVALID_SIGNING_CERT, "Invalid OCSP signing certificate in OCSP response."}, + +{SEC_ERROR_REVOKED_CERTIFICATE_CRL, "Certificate is revoked in issuer's certificate revocation list."}, + +{SEC_ERROR_REVOKED_CERTIFICATE_OCSP, "Issuer's OCSP responder reports certificate is revoked."}, + +{SEC_ERROR_CRL_INVALID_VERSION, "Issuer's Certificate Revocation List has an unknown version number."}, + +{SEC_ERROR_CRL_V1_CRITICAL_EXTENSION, "Issuer's V1 Certificate Revocation List has a critical extension."}, + +{SEC_ERROR_CRL_UNKNOWN_CRITICAL_EXTENSION, "Issuer's V2 Certificate Revocation List has an unknown critical extension."}, + +{SEC_ERROR_UNKNOWN_OBJECT_TYPE, "Unknown object type specified."}, + +{SEC_ERROR_INCOMPATIBLE_PKCS11, "PKCS #11 driver violates the spec in an incompatible way."}, + +{SEC_ERROR_NO_EVENT, "No new slot event is available at this time."}, + +{SEC_ERROR_CRL_ALREADY_EXISTS, "CRL already exists."}, + +{SEC_ERROR_NOT_INITIALIZED, "NSS is not initialized."}, + +{SEC_ERROR_TOKEN_NOT_LOGGED_IN, "The operation failed because the PKCS#11 token is not logged in."}, + +{SEC_ERROR_OCSP_RESPONDER_CERT_INVALID, "Configured OCSP responder's certificate is invalid."}, + +{SEC_ERROR_OCSP_BAD_SIGNATURE, "OCSP response has an invalid signature."}, + +{SEC_ERROR_OUT_OF_SEARCH_LIMITS, "Cert validation search is out of search limits"}, + +{SEC_ERROR_INVALID_POLICY_MAPPING, "Policy mapping contains anypolicy"}, + +{SEC_ERROR_POLICY_VALIDATION_FAILED, "Cert chain fails policy validation"}, + +{SEC_ERROR_UNKNOWN_AIA_LOCATION_TYPE, "Unknown location type in cert AIA extension"}, + +{SEC_ERROR_BAD_HTTP_RESPONSE, "Server returned bad HTTP response"}, + +{SEC_ERROR_BAD_LDAP_RESPONSE, "Server returned bad LDAP response"}, + +{SEC_ERROR_FAILED_TO_ENCODE_DATA, "Failed to encode data with ASN1 encoder"}, + +{SEC_ERROR_BAD_INFO_ACCESS_LOCATION, "Bad information access location in cert extension"}, + +{SEC_ERROR_LIBPKIX_INTERNAL, "Libpkix internal error occurred during cert validation."}, + +#if ( NSS_VMAJOR > 3 ) || ( NSS_VMAJOR == 3 && NSS_VMINOR > 12 ) || ( NSS_VMAJOR == 3 && NSS_VMINOR == 12 && NSS_VPATCH > 2 ) +// following 3 errors got first used in NSS 3.12.3 +// they were in the header even in 3.12.2 but there was missing the mapping in pk11err.c +// see also https://bugzilla.mozilla.org/show_bug.cgi?id=453364 + +{SEC_ERROR_PKCS11_GENERAL_ERROR, "A PKCS #11 module returned CKR_GENERAL_ERROR, indicating that an unrecoverable error has occurred."}, + +{SEC_ERROR_PKCS11_FUNCTION_FAILED, "A PKCS #11 module returned CKR_FUNCTION_FAILED, indicating that the requested function could not be performed. Trying the same operation again might succeed."}, + +{SEC_ERROR_PKCS11_DEVICE_ERROR, "A PKCS #11 module returned CKR_DEVICE_ERROR, indicating that a problem has occurred with the token or slot."}, + +#endif + +#if ( NSS_VMAJOR > 3 ) || ( NSS_VMAJOR == 3 && NSS_VMINOR > 12 ) || ( NSS_VMAJOR == 3 && NSS_VMINOR == 12 && NSS_VPATCH > 3 ) +// following 2 errors got added in NSS 3.12.4 + +{SEC_ERROR_BAD_INFO_ACCESS_METHOD, "Unknown information access method in certificate extension."}, + +{SEC_ERROR_CRL_IMPORT_FAILED, "Error attempting to import a CRL."}, + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/ciphercontext.cxx b/xmlsecurity/source/xmlsec/nss/ciphercontext.cxx new file mode 100644 index 000000000..104414f81 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/ciphercontext.cxx @@ -0,0 +1,266 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +using namespace ::com::sun::star; + +uno::Reference< xml::crypto::XCipherContext > OCipherContext::Create( CK_MECHANISM_TYPE nNSSCipherID, const uno::Sequence< ::sal_Int8 >& aKey, const uno::Sequence< ::sal_Int8 >& aInitializationVector, bool bEncryption, bool bW3CPadding ) +{ + ::rtl::Reference< OCipherContext > xResult = new OCipherContext; + + xResult->m_pSlot = PK11_GetBestSlot( nNSSCipherID, nullptr ); + if ( xResult->m_pSlot ) + { + SECItem aKeyItem = { siBuffer, const_cast< unsigned char* >( reinterpret_cast< const unsigned char* >( aKey.getConstArray() ) ), sal::static_int_cast( aKey.getLength() ) }; + xResult->m_pSymKey = PK11_ImportSymKey( xResult->m_pSlot, nNSSCipherID, PK11_OriginDerive, bEncryption ? CKA_ENCRYPT : CKA_DECRYPT, &aKeyItem, nullptr ); + if ( xResult->m_pSymKey ) + { + SECItem aIVItem = { siBuffer, const_cast< unsigned char* >( reinterpret_cast< const unsigned char* >( aInitializationVector.getConstArray() ) ), sal::static_int_cast( aInitializationVector.getLength() ) }; + xResult->m_pSecParam = PK11_ParamFromIV( nNSSCipherID, &aIVItem ); + if ( xResult->m_pSecParam ) + { + xResult->m_pContext = PK11_CreateContextBySymKey( nNSSCipherID, bEncryption ? CKA_ENCRYPT : CKA_DECRYPT, xResult->m_pSymKey, xResult->m_pSecParam); + if ( xResult->m_pContext ) + { + xResult->m_bEncryption = bEncryption; + xResult->m_bW3CPadding = bW3CPadding; + xResult->m_bPadding = bW3CPadding || ( PK11_GetPadMechanism( nNSSCipherID ) == nNSSCipherID ); + xResult->m_nBlockSize = PK11_GetBlockSize( nNSSCipherID, xResult->m_pSecParam ); + if ( xResult->m_nBlockSize <= SAL_MAX_INT8 ) + return xResult.get(); + } + } + } + } + + return uno::Reference< xml::crypto::XCipherContext >(); +} + +void OCipherContext::Dispose() +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + 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 ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( m_bBroken ) + throw uno::RuntimeException(); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + uno::Sequence< sal_Int8 > aToConvert; + if ( aData.hasElements() ) + { + sal_Int32 nOldLastBlockLen = m_aLastBlock.getLength(); + OSL_ENSURE( nOldLastBlockLen <= m_nBlockSize, "Unexpected last block size!" ); + + sal_Int32 nAvailableData = nOldLastBlockLen + aData.getLength(); + sal_Int32 nToConvertLen; + if ( m_bEncryption || !m_bW3CPadding ) + { + if ( nAvailableData % m_nBlockSize == 0 ) + nToConvertLen = nAvailableData; + else if ( nAvailableData < m_nBlockSize ) + nToConvertLen = 0; + else + nToConvertLen = nAvailableData - nAvailableData % m_nBlockSize; + } + else + { + // decryption with W3C padding needs at least one block for finalizing + if ( nAvailableData < m_nBlockSize * 2 ) + nToConvertLen = 0; + else + nToConvertLen = nAvailableData - nAvailableData % m_nBlockSize - m_nBlockSize; + } + + aToConvert.realloc( nToConvertLen ); + if ( nToConvertLen == 0 ) + { + m_aLastBlock.realloc( nOldLastBlockLen + aData.getLength() ); + memcpy( m_aLastBlock.getArray() + nOldLastBlockLen, aData.getConstArray(), aData.getLength() ); + // aToConvert stays empty + } + else if ( nToConvertLen < nOldLastBlockLen ) + { + memcpy( aToConvert.getArray(), m_aLastBlock.getConstArray(), nToConvertLen ); + memcpy( m_aLastBlock.getArray(), m_aLastBlock.getConstArray() + nToConvertLen, nOldLastBlockLen - nToConvertLen ); + m_aLastBlock.realloc( nOldLastBlockLen - nToConvertLen + aData.getLength() ); + memcpy( m_aLastBlock.getArray() + nOldLastBlockLen - nToConvertLen, aData.getConstArray(), aData.getLength() ); + } + else + { + memcpy( aToConvert.getArray(), m_aLastBlock.getConstArray(), nOldLastBlockLen ); + if ( nToConvertLen > nOldLastBlockLen ) + memcpy( aToConvert.getArray() + nOldLastBlockLen, aData.getConstArray(), nToConvertLen - nOldLastBlockLen ); + m_aLastBlock.realloc( nAvailableData - nToConvertLen ); + memcpy( m_aLastBlock.getArray(), aData.getConstArray() + nToConvertLen - nOldLastBlockLen, nAvailableData - nToConvertLen ); + } + } + + uno::Sequence< sal_Int8 > aResult; + OSL_ENSURE( aToConvert.getLength() % m_nBlockSize == 0, "Unexpected size of the data to encrypt!" ); + if ( aToConvert.hasElements() ) + { + int nResultLen = 0; + aResult.realloc( aToConvert.getLength() + m_nBlockSize ); + if ( PK11_CipherOp( m_pContext, reinterpret_cast< unsigned char* >( aResult.getArray() ), &nResultLen, aResult.getLength(), reinterpret_cast< const unsigned char* >( aToConvert.getConstArray() ), aToConvert.getLength() ) != SECSuccess ) + { + m_bBroken = true; + Dispose(); + throw uno::RuntimeException(); + } + + m_nConverted += aToConvert.getLength(); + aResult.realloc( nResultLen ); + } + + return aResult; +} + +uno::Sequence< ::sal_Int8 > SAL_CALL OCipherContext::finalizeCipherContextAndDispose() +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( m_bBroken ) + throw uno::RuntimeException(); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + OSL_ENSURE( m_nBlockSize <= SAL_MAX_INT8, "Unexpected block size!" ); + OSL_ENSURE( m_nConverted % m_nBlockSize == 0, "Unexpected amount of bytes is already converted!" ); + sal_Int32 nSizeForPadding = ( m_nConverted + m_aLastBlock.getLength() ) % m_nBlockSize; + + // if it is decryption, the amount of data should be rounded to the block size even in case of padding + if ( ( !m_bPadding || !m_bEncryption ) && nSizeForPadding ) + throw uno::RuntimeException("The data should contain complete blocks only." ); + + if ( m_bW3CPadding && m_bEncryption ) + { + // in this case the last block should be smaller than standard block + // it will be increased with the padding + OSL_ENSURE( m_aLastBlock.getLength() < m_nBlockSize, "Unexpected size of cashed incomplete last block!" ); + + // W3CPadding handling for encryption + sal_Int32 nPaddingSize = m_nBlockSize - nSizeForPadding; + sal_Int32 nOldLastBlockLen = m_aLastBlock.getLength(); + m_aLastBlock.realloc( nOldLastBlockLen + nPaddingSize ); + + if ( nPaddingSize > 1 ) + { + rtlRandomPool aRandomPool = rtl_random_createPool(); + rtl_random_getBytes( aRandomPool, m_aLastBlock.getArray() + nOldLastBlockLen, nPaddingSize - 1 ); + rtl_random_destroyPool ( aRandomPool ); + } + m_aLastBlock[m_aLastBlock.getLength() - 1] = static_cast< sal_Int8 >( nPaddingSize ); + } + + // finally should the last block be smaller than two standard blocks + OSL_ENSURE( m_aLastBlock.getLength() < m_nBlockSize * 2 , "Unexpected size of cashed incomplete last block!" ); + + uno::Sequence< sal_Int8 > aResult; + if ( m_aLastBlock.hasElements() ) + { + int nPrefResLen = 0; + aResult.realloc( m_aLastBlock.getLength() + m_nBlockSize ); + if ( PK11_CipherOp( m_pContext, reinterpret_cast< unsigned char* >( aResult.getArray() ), &nPrefResLen, aResult.getLength(), reinterpret_cast< const unsigned char* >( m_aLastBlock.getConstArray() ), m_aLastBlock.getLength() ) != SECSuccess ) + { + m_bBroken = true; + Dispose(); + throw uno::RuntimeException(); + } + + aResult.realloc( nPrefResLen ); + m_aLastBlock.realloc( 0 ); + } + + sal_Int32 nPrefixLen = aResult.getLength(); + aResult.realloc( nPrefixLen + m_nBlockSize * 2 ); + unsigned nFinalLen = 0; + if ( PK11_DigestFinal( m_pContext, reinterpret_cast< unsigned char* >( aResult.getArray() + nPrefixLen ), &nFinalLen, aResult.getLength() - nPrefixLen ) != SECSuccess ) + { + m_bBroken = true; + Dispose(); + throw uno::RuntimeException(); + } + + aResult.realloc( nPrefixLen + nFinalLen ); + + if ( m_bW3CPadding && !m_bEncryption ) + { + // W3CPadding handling for decryption + // aResult should have enough data, since we let m_aLastBlock be big enough in case of decryption + OSL_ENSURE( aResult.getLength() >= m_nBlockSize, "Not enough data to handle the padding!" ); + + sal_Int8 nBytesToRemove = aResult[aResult.getLength() - 1]; + if ( nBytesToRemove <= 0 || nBytesToRemove > aResult.getLength() ) + { + m_bBroken = true; + Dispose(); + throw uno::RuntimeException(); + } + + aResult.realloc( aResult.getLength() - nBytesToRemove ); + } + + Dispose(); + + return aResult; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/ciphercontext.hxx b/xmlsecurity/source/xmlsec/nss/ciphercontext.hxx new file mode 100644 index 000000000..1d4a99c30 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/ciphercontext.hxx @@ -0,0 +1,83 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_XMLSECURITY_SOURCE_XMLSEC_NSS_CIPHERCONTEXT_HXX +#define INCLUDED_XMLSECURITY_SOURCE_XMLSEC_NSS_CIPHERCONTEXT_HXX + +#include + +#include +#include +#include +#include + +class OCipherContext : public cppu::WeakImplHelper< css::xml::crypto::XCipherContext > +{ +private: + ::osl::Mutex m_aMutex; + + PK11SlotInfo* m_pSlot; + PK11SymKey* m_pSymKey; + SECItem* m_pSecParam; + PK11Context* m_pContext; + + sal_Int32 m_nBlockSize; + css::uno::Sequence< sal_Int8 > m_aLastBlock; + + bool m_bEncryption; + bool m_bPadding; + bool m_bW3CPadding; + sal_Int64 m_nConverted; + + bool m_bDisposed; + bool m_bBroken; + + void Dispose(); + + OCipherContext() + : m_pSlot( nullptr ) + , m_pSymKey( nullptr ) + , m_pSecParam( nullptr ) + , m_pContext( nullptr ) + , m_nBlockSize( 0 ) + , m_bEncryption( false ) + , m_bPadding( false ) + , m_bW3CPadding( false ) + , m_nConverted( 0 ) + , m_bDisposed( false ) + , m_bBroken( false ) + {} + +public: + + virtual ~OCipherContext() override + { + Dispose(); + } + + static css::uno::Reference< css::xml::crypto::XCipherContext > Create( CK_MECHANISM_TYPE nNSSCipherID, const css::uno::Sequence< ::sal_Int8 >& aKey, const css::uno::Sequence< ::sal_Int8 >& aInitializationVector, bool bEncryption, bool bW3CPadding ); + + // XCipherContext + virtual css::uno::Sequence< ::sal_Int8 > SAL_CALL convertWithCipherContext( const css::uno::Sequence< ::sal_Int8 >& aData ) override; + virtual css::uno::Sequence< ::sal_Int8 > SAL_CALL finalizeCipherContextAndDispose( ) override; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/digestcontext.cxx b/xmlsecurity/source/xmlsec/nss/digestcontext.cxx new file mode 100644 index 000000000..40d871ac6 --- /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 ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( m_bBroken ) + throw uno::RuntimeException(); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + if ( !m_b1KData || m_nDigested < 1024 ) + { + 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() +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( m_bBroken ) + throw uno::RuntimeException(); + + if ( m_bDisposed ) + throw lang::DisposedException(); + + uno::Sequence< sal_Int8 > aResult( m_nDigestLength ); + unsigned int nResultLen = 0; + if ( PK11_DigestFinal( m_pContext, reinterpret_cast< unsigned char* >( aResult.getArray() ), &nResultLen, aResult.getLength() ) != SECSuccess ) + { + PK11_DestroyContext( m_pContext, PR_TRUE ); + m_pContext = nullptr; + m_bBroken = true; + throw uno::RuntimeException(); + } + + PK11_DestroyContext( m_pContext, PR_TRUE ); + m_pContext = nullptr; + m_bDisposed = true; + + aResult.realloc( nResultLen ); + return aResult; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/digestcontext.hxx b/xmlsecurity/source/xmlsec/nss/digestcontext.hxx new file mode 100644 index 000000000..2f41862a8 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/digestcontext.hxx @@ -0,0 +1,62 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_XMLSECURITY_SOURCE_XMLSEC_NSS_DIGESTCONTEXT_HXX +#define INCLUDED_XMLSECURITY_SOURCE_XMLSEC_NSS_DIGESTCONTEXT_HXX + +#include + +#include +#include +#include + +class ODigestContext : public cppu::WeakImplHelper< css::xml::crypto::XDigestContext > +{ +private: + ::osl::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; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/nssinitializer.cxx b/xmlsecurity/source/xmlsec/nss/nssinitializer.cxx new file mode 100644 index 000000000..d64ea10a0 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/nssinitializer.cxx @@ -0,0 +1,524 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 "digestcontext.hxx" +#include "ciphercontext.hxx" + +#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::unique_ptr m_pTempFileDatabaseDirectory; + +public: + OUString getTempDatabasePath() + { + if (!m_pTempFileDatabaseDirectory) + { + m_pTempFileDatabaseDirectory.reset(new utl::TempFile(nullptr, true)); + m_pTempFileDatabaseDirectory->EnableKillingFile(); + } + return m_pTempFileDatabaseDirectory->GetFileName(); + } + + void reset() + { + if (m_pTempFileDatabaseDirectory) + { + m_pTempFileDatabaseDirectory.reset(); + } + } +}; + +salhelper::SingletonRef* getInitNSSPrivate() +{ + static salhelper::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) + { + 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; + } +} + +OString getMozillaCurrentProfile( const css::uno::Reference< css::uno::XComponentContext > &rxContext ) +{ + // 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); + return pEnv; + } + + // second, try to get saved user-preference + try + { + OUString sUserSetCertPath = + officecfg::Office::Common::Security::Scripting::CertDir::get().value_or(OUString()); + + if (!sUserSetCertPath.isEmpty()) + { + SAL_INFO( + "xmlsecurity.xmlsec", + "Using Mozilla profile from /org.openoffice.Office.Common/" + "Security/Scripting/CertDir: " << sUserSetCertPath); + return OUStringToOString(sUserSetCertPath, osl_getThreadTextEncoding()); + } + } + catch (const uno::Exception &) + { + TOOLS_WARN_EXCEPTION("xmlsecurity.xmlsec", "getMozillaCurrentProfile:"); + } + + // third, dig around to see if there's one 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 (int i=0; igetDefaultProfile(productTypes[i]); + + if (!profile.isEmpty()) + { + OUString sProfilePath = xMozillaBootstrap->getProfilePath( productTypes[i], profile ); + SAL_INFO( + "xmlsecurity.xmlsec", + "Using Mozilla profile " << sProfilePath); + return OUStringToOString(sProfilePath, osl_getThreadTextEncoding()); + } + } + } + + SAL_INFO("xmlsecurity.xmlsec", "No Mozilla profile found"); + return OString(); +} + +#endif + +//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 = getMozillaCurrentProfile(rxContext); +#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 + 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 + if (!SECMOD_HasRootCerts()) +#endif + { + deleteRootsModule(); + +#if defined SYSTEM_NSS + 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)) + { + 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( + const css::uno::Reference< css::uno::XComponentContext > &rxContext) + :m_xContext( rxContext ) +{ +} + +ONSSInitializer::~ONSSInitializer() +{ +} + +bool ONSSInitializer::initNSS( const css::uno::Reference< css::uno::XComponentContext > &rxContext ) +{ + static bool gbInitialized = [&rxContext]() + { + bool bNSSInit = false; + bool bInitialized = nsscrypto_initialize( rxContext, bNSSInit ); + if (bNSSInit) + atexit(nsscrypto_finalize); + return bInitialized; + }(); + return gbInitialized; +} + +css::uno::Reference< css::xml::crypto::XDigestContext > SAL_CALL ONSSInitializer::getDigestContext( ::sal_Int32 nDigestID, const css::uno::Sequence< css::beans::NamedValue >& aParams ) +{ + SECOidTag nNSSDigestID = SEC_OID_UNKNOWN; + sal_Int32 nDigestLength = 0; + bool b1KData = false; + if ( nDigestID == css::xml::crypto::DigestID::SHA256 + || nDigestID == css::xml::crypto::DigestID::SHA256_1K ) + { + nNSSDigestID = SEC_OID_SHA256; + nDigestLength = 32; + b1KData = ( nDigestID == css::xml::crypto::DigestID::SHA256_1K ); + } + else if ( nDigestID == css::xml::crypto::DigestID::SHA1 + || nDigestID == css::xml::crypto::DigestID::SHA1_1K ) + { + nNSSDigestID = SEC_OID_SHA1; + nDigestLength = 20; + b1KData = ( nDigestID == css::xml::crypto::DigestID::SHA1_1K ); + } + else if ( nDigestID == css::xml::crypto::DigestID::SHA512 + || nDigestID == css::xml::crypto::DigestID::SHA512_1K ) + { + nNSSDigestID = SEC_OID_SHA512; + nDigestLength = 64; + b1KData = ( nDigestID == css::xml::crypto::DigestID::SHA512_1K ); + } + else + throw css::lang::IllegalArgumentException("Unexpected digest requested.", css::uno::Reference< css::uno::XInterface >(), 1 ); + + if ( aParams.hasElements() ) + throw css::lang::IllegalArgumentException("Unexpected arguments provided for digest creation.", css::uno::Reference< css::uno::XInterface >(), 2 ); + + css::uno::Reference< css::xml::crypto::XDigestContext > xResult; + if( initNSS( m_xContext ) ) + { + PK11Context* pContext = PK11_CreateDigestContext( nNSSDigestID ); + if ( pContext && PK11_DigestBegin( pContext ) == SECSuccess ) + xResult = new ODigestContext( pContext, nDigestLength, b1KData ); + } + + return xResult; +} + +css::uno::Reference< css::xml::crypto::XCipherContext > SAL_CALL ONSSInitializer::getCipherContext( ::sal_Int32 nCipherID, const css::uno::Sequence< ::sal_Int8 >& aKey, const css::uno::Sequence< ::sal_Int8 >& aInitializationVector, sal_Bool bEncryption, const css::uno::Sequence< css::beans::NamedValue >& aParams ) +{ + CK_MECHANISM_TYPE nNSSCipherID = 0; + bool bW3CPadding = false; + if ( nCipherID != css::xml::crypto::CipherID::AES_CBC_W3C_PADDING ) + throw css::lang::IllegalArgumentException("Unexpected cipher requested.", css::uno::Reference< css::uno::XInterface >(), 1 ); + + nNSSCipherID = CKM_AES_CBC; + bW3CPadding = true; + + if ( aKey.getLength() != 16 && aKey.getLength() != 24 && aKey.getLength() != 32 ) + throw css::lang::IllegalArgumentException("Unexpected key length.", css::uno::Reference< css::uno::XInterface >(), 2 ); + + if ( aParams.hasElements() ) + throw css::lang::IllegalArgumentException("Unexpected arguments provided for cipher creation.", css::uno::Reference< css::uno::XInterface >(), 5 ); + + css::uno::Reference< css::xml::crypto::XCipherContext > xResult; + if( initNSS( m_xContext ) ) + { + if ( aInitializationVector.getLength() != PK11_GetIVLength( nNSSCipherID ) ) + throw css::lang::IllegalArgumentException("Unexpected length of initialization vector.", css::uno::Reference< css::uno::XInterface >(), 3 ); + + xResult = OCipherContext::Create( nNSSCipherID, aKey, aInitializationVector, bEncryption, bW3CPadding ); + } + + return xResult; +} + +/* XServiceInfo */ +OUString SAL_CALL ONSSInitializer::getImplementationName() +{ + return "com.sun.star.xml.crypto.NSSInitializer"; +} + +sal_Bool SAL_CALL ONSSInitializer::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +cssu::Sequence< OUString > SAL_CALL ONSSInitializer::getSupportedServiceNames( ) +{ + return { NSS_SERVICE_NAME }; +} + +#ifndef XMLSEC_CRYPTO_NSS +extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface* +com_sun_star_xml_crypto_NSSInitializer_get_implementation( + uno::XComponentContext* pCtx, uno::Sequence const& /*rSeq*/) +{ + return cppu::acquire(new ONSSInitializer(pCtx)); +} +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/nssinitializer.hxx b/xmlsecurity/source/xmlsec/nss/nssinitializer.hxx new file mode 100644 index 000000000..7e1b7ff50 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/nssinitializer.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 . + */ + +#ifndef INCLUDED_XMLSECURITY_SOURCE_XMLSEC_NSS_NSSINITIALIZER_HXX +#define INCLUDED_XMLSECURITY_SOURCE_XMLSEC_NSS_NSSINITIALIZER_HXX + +#include +#include + +#include + +namespace com::sun::star::uno { class XComponentContext; } + +#define NSS_SERVICE_NAME "com.sun.star.xml.crypto.NSSInitializer" + +class ONSSInitializer : public cppu::WeakImplHelper +< + css::xml::crypto::XNSSInitializer, + css::lang::XServiceInfo +> +{ +protected: + css::uno::Reference< css::uno::XComponentContext > m_xContext; + + ONSSInitializer() + {} + +public: + explicit ONSSInitializer(const css::uno::Reference &rxContext); + virtual ~ONSSInitializer() override; + + static bool initNSS( const css::uno::Reference< css::uno::XComponentContext > &rxContext ); + + /* 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; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/nssrenam.h b/xmlsecurity/source/xmlsec/nss/nssrenam.h new file mode 100644 index 000000000..411f279e0 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/nssrenam.h @@ -0,0 +1,44 @@ +/* -*- 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. + */ + +#ifndef INCLUDED_XMLSECURITY_SOURCE_XMLSEC_NSS_NSSRENAM_H +#define INCLUDED_XMLSECURITY_SOURCE_XMLSEC_NSS_NSSRENAM_H + +#define CERT_NewTempCertificate __CERT_NewTempCertificate +#define PK11_GetKeyData __PK11_GetKeyData +#define CERT_DecodeDERCertificate __CERT_DecodeDERCertificate + +#endif // INCLUDED_XMLSECURITY_SOURCE_XMLSEC_NSS_NSSRENAM_H + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/sanextension_nssimpl.cxx b/xmlsecurity/source/xmlsec/nss/sanextension_nssimpl.cxx new file mode 100644 index 000000000..5827c5f92 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/sanextension_nssimpl.cxx @@ -0,0 +1,162 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 ) ; + for( unsigned int r = 0; r < current->name.OthName.name.len ; r ++ ) + otherName[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 ) ; + for( unsigned int r = 0; r < current->name.other.len ; r ++ ) + ipAddress[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; + OString oid("OID."); + if (oidString.match(oid)) + objID = oidString.copy(oid.getLength()); + else + objID = oidString; + return objID; + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/sanextension_nssimpl.hxx b/xmlsecurity/source/xmlsec/nss/sanextension_nssimpl.hxx new file mode 100644 index 000000000..857aa6cc4 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/sanextension_nssimpl.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 . + */ + +#ifndef INCLUDED_XMLSECURITY_SOURCE_XMLSEC_NSS_SANEXTENSION_NSSIMPL_HXX +#define INCLUDED_XMLSECURITY_SOURCE_XMLSEC_NSS_SANEXTENSION_NSSIMPL_HXX + +#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 ; +} ; + +#endif // INCLUDED_XMLSECURITY_SOURCE_XMLSEC_NSS_SANEXTENSION_NSSIMPL_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/secerror.cxx b/xmlsecurity/source/xmlsec/nss/secerror.cxx new file mode 100644 index 000000000..b7e623ce0 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/secerror.cxx @@ -0,0 +1,152 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include +#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 000000000..9de7f5af7 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/secerror.hxx @@ -0,0 +1,35 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_XMLSECURITY_SOURCE_XMLSEC_NSS_SECERROR_HXX +#define INCLUDED_XMLSECURITY_SOURCE_XMLSEC_NSS_SECERROR_HXX + +#include + +#include +#include + +const char * +getCertError(PRErrorCode errNum); + +void +printChainFailure(CERTVerifyLog *log); +#endif // INCLUDED_XMLSECURITY_SOURCE_XMLSEC_NSS_SECERROR_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.cxx b/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.cxx new file mode 100644 index 000000000..5b0291642 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.cxx @@ -0,0 +1,937 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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::xml::crypto::XSecurityEnvironment ; +using ::com::sun::star::security::XCertificate ; + +namespace std +{ +template <> struct default_delete +{ + void operator()(PRArenaPool* ptr) { PORT_FreeArena(ptr, PR_FALSE); } +}; +} + +static X509Certificate_NssImpl* NssCertToXCert( CERTCertificate* cert ) ; +static X509Certificate_NssImpl* NssPrivKeyToXCert( SECKEYPrivateKey* ) ; + +namespace { + +struct UsageDescription +{ + SECCertificateUsage usage; + char const* description; + + UsageDescription() + : usage( certificateUsageCheckAllUsages ) + , description( nullptr ) + {} + + UsageDescription( SECCertificateUsage i_usage, char const* i_description ) + : usage( i_usage ) + , description( i_description ) + {} +}; + +} + +static char* GetPasswordFunction( PK11SlotInfo* pSlot, PRBool bRetry, void* /*arg*/ ) +{ + uno::Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() ); + uno::Reference < task::XInteractionHandler2 > xInteractionHandler( + task::InteractionHandler::createWithParent(xContext, nullptr) ); + + task::PasswordRequestMode eMode = bRetry ? task::PasswordRequestMode_PASSWORD_REENTER : task::PasswordRequestMode_PASSWORD_ENTER; + ::comphelper::DocPasswordRequest* pPasswordRequest = new ::comphelper::DocPasswordRequest( + ::comphelper::DocPasswordRequestType::Standard, eMode, OUString::createFromAscii(PK11_GetTokenName(pSlot)) ); + + uno::Reference< task::XInteractionRequest > xRequest( pPasswordRequest ); + xInteractionHandler->handle( xRequest ); + + 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 ) , m_tSymKeyList() { + 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; +} + +/* XUnoTunnel */ +sal_Int64 SAL_CALL SecurityEnvironment_NssImpl::getSomething( const Sequence< sal_Int8 >& aIdentifier ) +{ + if( isUnoTunnelId(aIdentifier) ) { + return sal::static_int_cast(reinterpret_cast(this)); + } + return 0 ; +} + +/* XUnoTunnel extension */ + +namespace +{ + class theSecurityEnvironment_NssImplUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theSecurityEnvironment_NssImplUnoTunnelId > {}; +} + +const Sequence< sal_Int8>& SecurityEnvironment_NssImpl::getUnoTunnelId() { + return theSecurityEnvironment_NssImplUnoTunnelId::get().getSeq(); +} + +OUString SecurityEnvironment_NssImpl::getSecurityEnvironmentInformation() +{ + OUStringBuffer buff; + for (auto& slot : m_Slots) + { + buff.append(OUString::createFromAscii(PK11_GetTokenName(slot))); + buff.append("\n"); + } + return buff.makeStringAndClear(); +} + +void SecurityEnvironment_NssImpl::addCryptoSlot( PK11SlotInfo* aSlot) +{ + PK11_ReferenceSlot(aSlot); + m_Slots.push_back(aSlot); +} + +//Could we have multiple cert dbs? +void SecurityEnvironment_NssImpl::setCertDb( CERTCertDBHandle* aCertDb ) { + m_pHandler = aCertDb ; +} + +void SecurityEnvironment_NssImpl::adoptSymKey( PK11SymKey* aSymKey ) { + if( aSymKey != nullptr ) { + //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 + osl::MutexGuard guard(m_mutex); + + m_Slots.clear(); + m_tSymKeyList.clear(); + + PK11SlotList * soltList = PK11_GetAllTokens( CKM_INVALID_MECHANISM, PR_FALSE, PR_FALSE, nullptr ) ; + if( soltList != nullptr ) + { + for (PK11SlotListElement* soltEle = soltList->head ; soltEle != nullptr; soltEle = soltEle->next) + { + PK11SlotInfo * pSlot = soltEle->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); + PK11_FreeSlot( pSlot ) ; + pSlot = nullptr; + + if (pSymKey != nullptr) + { + adoptSymKey( pSymKey ) ; + PK11_FreeSymKey( pSymKey ) ; + pSymKey = nullptr; + } + + }// end of if(pSlot != NULL) + }// end of for + }// end of if( soltList != NULL ) +} + +Sequence< Reference < XCertificate > > +SecurityEnvironment_NssImpl::getPersonalCertificates() +{ + sal_Int32 length ; + X509Certificate_NssImpl* xcert ; + std::vector< X509Certificate_NssImpl* > certsList ; + + updateSlots(); + //firstly, we try to find private keys in slot + for (auto& slot : m_Slots) + { + SECKEYPrivateKeyList* priKeyList ; + + if( PK11_NeedLogin(slot ) ) { + SECStatus nRet = PK11_Authenticate(slot, PR_TRUE, nullptr); + //PK11_Authenticate may fail in case the a slot has not been initialized. + //this is the case if the user has a new profile, so that they have never + //added a personal certificate. + if( nRet != SECSuccess && PORT_GetError() != SEC_ERROR_IO) { + throw NoPasswordException(); + } + } + + priKeyList = PK11_ListPrivateKeysInSlot(slot) ; + if( priKeyList != nullptr ) + { + for (SECKEYPrivateKeyListNode* curPri = PRIVKEY_LIST_HEAD(priKeyList); + !PRIVKEY_LIST_END( curPri, priKeyList ) && curPri != nullptr; + curPri = PRIVKEY_LIST_NEXT(curPri)) + { + xcert = NssPrivKeyToXCert( curPri->key ) ; + if( xcert != nullptr ) + certsList.push_back( xcert ) ; + } + SECKEY_DestroyPrivateKeyList( priKeyList ) ; + } + + + } + + length = certsList.size() ; + if( length != 0 ) { + int i = 0; + Sequence< Reference< XCertificate > > certSeq( length ) ; + + for( const auto& rXCert : certsList ) { + certSeq[i] = rXCert ; + ++i; + } + + return certSeq ; + } + + return Sequence< Reference < XCertificate > > (); +} + +Reference< XCertificate > SecurityEnvironment_NssImpl::getCertificate( const OUString& issuerName, const Sequence< sal_Int8 >& serialNumber ) +{ + X509Certificate_NssImpl* xcert = nullptr; + + if( m_pHandler != nullptr ) { + 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 ) ; + } else { + xcert = nullptr ; + } + + PL_strfree( chIssuer ) ; + CERT_DestroyName( nmIssuer ) ; + //SECITEM_FreeItem( derIssuer, PR_FALSE ) ; + CERT_DestroyCertificate( cert ) ; + } else { + xcert = nullptr ; + } + + return xcert ; +} + +Sequence< Reference < XCertificate > > SecurityEnvironment_NssImpl::buildCertificatePath( const Reference< XCertificate >& begin ) { + // Remember the signing certificate. + m_xSigningCertificate = begin; + + const X509Certificate_NssImpl* xcert ; + const CERTCertificate* cert ; + CERTCertList* certChain ; + + Reference< XUnoTunnel > xCertTunnel( begin, UNO_QUERY_THROW ) ; + xcert = reinterpret_cast( + sal::static_int_cast(xCertTunnel->getSomething( X509Certificate_NssImpl::getUnoTunnelId() ))) ; + if( xcert == nullptr ) { + throw RuntimeException() ; + } + + cert = xcert->getNssCert() ; + if( cert != nullptr ) { + int64 timeboundary ; + + //Get the system clock time + timeboundary = PR_Now() ; + + certChain = CERT_GetCertChainFromCert( const_cast(cert), timeboundary, certUsageAnyCA ) ; + } else { + certChain = nullptr ; + } + + if( certChain != nullptr ) { + std::vector> aCertChain; + + for (CERTCertListNode* node = CERT_LIST_HEAD(certChain); !CERT_LIST_END(node, certChain); node = CERT_LIST_NEXT(node)) { + X509Certificate_NssImpl* pCert = new X509Certificate_NssImpl(); + if( pCert == nullptr ) { + CERT_DestroyCertList( certChain ) ; + throw RuntimeException() ; + } + + pCert->setCert( node->cert ) ; + + aCertChain.push_back(pCert); + } + + CERT_DestroyCertList( certChain ) ; + + return comphelper::containerToSequence(aCertChain); + } + + return Sequence< Reference < XCertificate > >(); +} + +X509Certificate_NssImpl* SecurityEnvironment_NssImpl::createAndAddCertificateFromPackage( + const css::uno::Sequence& raDERCertificate, + OUString const & 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) + return nullptr; + + PK11SlotInfo* pSlot = PK11_GetInternalKeySlot(); + + if (!pSlot) + return nullptr; + + aStatus = PK11_ImportCert(pSlot, pCERTCertificate, CK_INVALID_HANDLE, nullptr, PR_FALSE); + + if (aStatus != SECSuccess) + return nullptr; + + aStatus = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), pCERTCertificate, &aTrust); + + if (aStatus != SECSuccess) + return nullptr; + + + PK11_FreeSlot(pSlot); + + X509Certificate_NssImpl* pX509Certificate = new X509Certificate_NssImpl(); + pX509Certificate->setCert(pCERTCertificate); + return pX509Certificate; +} + +X509Certificate_NssImpl* SecurityEnvironment_NssImpl::createX509CertificateFromDER(const css::uno::Sequence& aDerCertificate) +{ + X509Certificate_NssImpl* pX509Certificate = nullptr; + + 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()) ) ; + int certSize = xmlSecBase64Decode( chCert, reinterpret_cast(chCert), xmlStrlen( chCert ) ) ; + if (certSize > 0) + { + Sequence< sal_Int8 > rawCert(certSize) ; + for (int i = 0 ; i < certSize; ++i) + rawCert[i] = *( chCert + i ) ; + + xmlFree( chCert ) ; + + return createCertificateFromRaw( rawCert ) ; + } + else + { + return nullptr; + } +} + +sal_Int32 SecurityEnvironment_NssImpl :: +verifyCertificate( const Reference< csss::XCertificate >& aCert, + const Sequence< Reference< csss::XCertificate > >& intermediateCerts ) +{ + sal_Int32 validity = csss::CertificateValidity::INVALID; + const X509Certificate_NssImpl* xcert ; + const CERTCertificate* cert ; + ::std::vector vecTmpNSSCertificates; + Reference< XUnoTunnel > xCertTunnel( aCert, UNO_QUERY_THROW ) ; + + SAL_INFO("xmlsecurity.xmlsec", "Start verification of certificate: " << aCert->getSubjectName()); + + xcert = reinterpret_cast( + sal::static_int_cast(xCertTunnel->getSomething( X509Certificate_NssImpl::getUnoTunnelId() ))) ; + 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 != nullptr ) + { + + //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 = SAL_N_ELEMENTS(arUsages); + for (int i = 0; i < numUsages; i++) + { + SAL_INFO("xmlsecurity.xmlsec", "Testing usage " << i+1 << + " of " << numUsages << ": " << + arUsages[i].description << + " (0x" << std::hex << static_cast(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."); + } + } + + } + else + { + validity = css::security::CertificateValidity::INVALID ; + } + + //Destroying the temporary certificates + for (auto& tmpCert : vecTmpNSSCertificates) + { + SAL_INFO("xmlsecurity.xmlsec", "Destroying temporary certificate"); + CERT_DestroyCertificate(tmpCert); + } + return validity ; +} + +sal_Int32 SecurityEnvironment_NssImpl::getCertificateCharacters( + const css::uno::Reference< css::security::XCertificate >& aCert ) { + sal_Int32 characters ; + const X509Certificate_NssImpl* xcert ; + const CERTCertificate* cert ; + + Reference< XUnoTunnel > xCertTunnel( aCert, UNO_QUERY_THROW ) ; + xcert = reinterpret_cast( + sal::static_int_cast(xCertTunnel->getSomething( X509Certificate_NssImpl::getUnoTunnelId() ))) ; + 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 ; +} + +X509Certificate_NssImpl* NssCertToXCert( CERTCertificate* cert ) +{ + X509Certificate_NssImpl* xcert ; + + if( cert != nullptr ) { + xcert = new X509Certificate_NssImpl() ; + xcert->setCert( cert ) ; + } else { + xcert = nullptr ; + } + + return xcert ; +} + +X509Certificate_NssImpl* NssPrivKeyToXCert( SECKEYPrivateKey* priKey ) +{ + X509Certificate_NssImpl* xcert ; + + if( priKey != nullptr ) { + CERTCertificate* cert = PK11_GetCertFromPrivateKey( priKey ) ; + + if( cert != nullptr ) { + xcert = NssCertToXCert( cert ) ; + } else { + xcert = nullptr ; + } + + CERT_DestroyCertificate( cert ) ; + } else { + xcert = nullptr ; + } + + return xcert ; +} + +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 (auto pCertificate = dynamic_cast(m_xSigningCertificate.get())) + { + SECKEYPrivateKey* pPrivateKey = SECKEY_CopyPrivateKey(pCertificate->getPrivateKey()); + if (pPrivateKey) + { + xmlSecKeyDataPtr pKeyData = xmlSecNssPKIAdoptKey(pPrivateKey, nullptr); + xmlSecKeyPtr pKey = xmlSecKeyCreate(); + xmlSecKeySetValue(pKey, pKeyData); + xmlSecNssAppDefaultKeysMngrAdoptKey(pKeysMngr, pKey); + } + else + { + SAL_WARN("xmlsecurity.xmlsec", "Can't get the private key from the certificate."); + } + } + + return pKeysMngr; +} + +void SecurityEnvironment_NssImpl::destroyKeysManager(xmlSecKeysMngrPtr pKeysMngr) { + if( pKeysMngr != nullptr ) { + xmlSecKeysMngrDestroy( pKeysMngr ) ; + } +} + +SECKEYPrivateKey* SecurityEnvironment_NssImpl::insertPrivateKey(css::uno::Sequence 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(); + + X509Certificate_NssImpl* pX509Certificate = createAndAddCertificateFromPackage(raDERCertificate, "TCu,TCu,TCu"); + if (!pX509Certificate) + return uno::Reference(); + + return pX509Certificate; +} + +uno::Reference SecurityEnvironment_NssImpl::addDERCertificateToTheDatabase( + uno::Sequence const & raDERCertificate, OUString const & raTrustString) +{ + X509Certificate_NssImpl* pX509Certificate = createAndAddCertificateFromPackage(raDERCertificate, raTrustString); + return pX509Certificate; +} + +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 000000000..117e2c294 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.hxx @@ -0,0 +1,146 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_XMLSECURITY_SOURCE_XMLSEC_NSS_SECURITYENVIRONMENT_NSSIMPL_HXX +#define INCLUDED_XMLSECURITY_SOURCE_XMLSEC_NSS_SECURITYENVIRONMENT_NSSIMPL_HXX + +#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, + css::lang::XUnoTunnel > +{ +private: + + std::vector< PK11SlotInfo* > m_Slots; + /// The last used certificate which has the private key for signing. + css::uno::Reference m_xSigningCertificate; + + osl::Mutex m_mutex; + + CERTCertDBHandle* m_pHandler ; + std::vector< PK11SymKey* > m_tSymKeyList ; + + public: + SecurityEnvironment_NssImpl(); + virtual ~SecurityEnvironment_NssImpl() override; + + //Methods from XSecurityEnvironment + + //Methods from XServiceInfo + virtual OUString SAL_CALL getImplementationName() override ; + + virtual sal_Bool SAL_CALL supportsService( + const OUString& ServiceName + ) override ; + + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override ; + + virtual ::sal_Int32 SAL_CALL verifyCertificate( + const css::uno::Reference< + css::security::XCertificate >& xCert, + const css::uno::Sequence< + css::uno::Reference< css::security::XCertificate > > & + intermediateCerts) override ; + + virtual ::sal_Int32 SAL_CALL getCertificateCharacters( const css::uno::Reference< css::security::XCertificate >& xCert ) override ; + + virtual OUString SAL_CALL getSecurityEnvironmentInformation( ) override; + + //Methods from XUnoTunnel + virtual sal_Int64 SAL_CALL getSomething( const css::uno::Sequence< sal_Int8 >& aIdentifier ) override; + + static const css::uno::Sequence< sal_Int8 >& getUnoTunnelId() ; + + /// @throws css::uno::Exception + /// @throws css::uno::RuntimeException + void setCertDb( CERTCertDBHandle* aCertDb ) ; + + /// @throws css::uno::Exception + /// @throws css::uno::RuntimeException + void adoptSymKey( PK11SymKey* aSymKey ) ; + + virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificate > > SAL_CALL getPersonalCertificates() override ; + virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificate > > SAL_CALL getAllCertificates() override + { return css::uno::Sequence< css::uno::Reference< css::security::XCertificate > >(); } + + virtual css::uno::Reference< css::security::XCertificate > SAL_CALL getCertificate( const OUString& issuerName, const css::uno::Sequence< sal_Int8 >& serialNumber ) override ; + + virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificate > > SAL_CALL buildCertificatePath( const css::uno::Reference< css::security::XCertificate >& beginCert ) override ; + + virtual css::uno::Reference< css::security::XCertificate > SAL_CALL createCertificateFromRaw( const css::uno::Sequence< sal_Int8 >& rawCertificate ) override ; + virtual css::uno::Reference< css::security::XCertificate > SAL_CALL createCertificateFromAscii( const OUString& asciiCertificate ) override ; + + // Methods of XCertificateCreator + css::uno::Reference 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 X509Certificate_NssImpl* createAndAddCertificateFromPackage( + const css::uno::Sequence& raDerCertificate, + OUString const & raString); + static SECKEYPrivateKey* insertPrivateKey(css::uno::Sequence const & raPrivateKey); + + static X509Certificate_NssImpl* createX509CertificateFromDER(const css::uno::Sequence& raDerCertificate); + + /// @throws css::uno::Exception + /// @throws css::uno::RuntimeException + void addCryptoSlot( PK11SlotInfo* aSlot ) ; +} ; + +#endif // INCLUDED_XMLSECURITY_SOURCE_XMLSEC_NSS_SECURITYENVIRONMENT_NSSIMPL_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/seinitializer_nssimpl.cxx b/xmlsecurity/source/xmlsec/nss/seinitializer_nssimpl.cxx new file mode 100644 index 000000000..3e59efa48 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/seinitializer_nssimpl.cxx @@ -0,0 +1,145 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 "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 ); + uno::Reference< lang::XUnoTunnel > xSecEnvTunnel(xSecEnv, uno::UNO_QUERY_THROW); + SecurityEnvironment_NssImpl* pSecEnv = reinterpret_cast( + sal::static_int_cast( + xSecEnvTunnel->getSomething(SecurityEnvironment_NssImpl::getUnoTunnelId() ))) ; + 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 000000000..ec6742529 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/seinitializer_nssimpl.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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_XMLSECURITY_SOURCE_XMLSEC_NSS_SEINITIALIZER_NSSIMPL_HXX +#define INCLUDED_XMLSECURITY_SOURCE_XMLSEC_NSS_SEINITIALIZER_NSSIMPL_HXX + +#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; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx b/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx new file mode 100644 index 000000000..1a323d33f --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.cxx @@ -0,0 +1,536 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 "x509certificate_nssimpl.hxx" + +#include + +#include "sanextension_nssimpl.hxx" +#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 ; + +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 ) { + Sequence< sal_Int8 > serial( m_pCert->serialNumber.len ) ; + for( unsigned int i = 0 ; i < m_pCert->serialNumber.len ; i ++ ) + serial[i] = *( m_pCert->serialNumber.data + i ) ; + + return serial ; + } 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 ) { + 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 ) { + 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 ) { + Sequence< sal_Int8 > issuerUid( m_pCert->issuerID.len ) ; + for( unsigned int i = 0 ; i < m_pCert->issuerID.len ; i ++ ) + issuerUid[i] = *( m_pCert->issuerID.data + i ) ; + + return issuerUid ; + } 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 ) { + Sequence< sal_Int8 > subjectUid( m_pCert->subjectID.len ) ; + for( unsigned int i = 0 ; i < m_pCert->subjectID.len ; i ++ ) + subjectUid[i] = *( m_pCert->subjectID.data + i ) ; + + return subjectUid ; + } 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 ++ ) ; + Sequence< Reference< XCertificateExtension > > xExtns( len ) ; + + for( extns = m_pCert->extensions, len = 0; *extns != nullptr; extns ++, len ++ ) { + const SECItem id = (*extns)->id; + OString oidString(CERT_GetOidString(&id)); + + bool crit; + if( (*extns)->critical.data == nullptr ) + crit = false ; + else + crit = (*extns)->critical.data[0] == 0xFF; + + // remove "OID." prefix if existing + OString objID; + OString oid("OID."); + if (oidString.match(oid)) + objID = oidString.copy(oid.getLength()); + else + objID = oidString; + + unsigned char* value = (*extns)->value.data; + unsigned int vlen = (*extns)->value.len; + unsigned char* objid = reinterpret_cast(const_cast(objID.getStr())); + unsigned int objidlen = objID.getLength(); + + if (objID == "2.5.29.17") + { + SanExtensionImpl* pExtn = new SanExtensionImpl; + pExtn->setCertExtn(value, vlen, objid, objidlen, crit); + xExtns[len] = pExtn ; + } + else + { + CertificateExtension_XmlSecImpl* pExtn = new CertificateExtension_XmlSecImpl; + pExtn->setCertExtn(value, vlen, objid, objidlen, crit); + xExtns[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 ) { + Sequence< sal_Int8 > rawCert( m_pCert->derCert.len ) ; + + for( unsigned int i = 0 ; i < m_pCert->derCert.len ; i ++ ) + rawCert[i] = *( m_pCert->derCert.data + i ) ; + + return rawCert ; + } 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 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 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; + } + return nullptr; +} + +/* XUnoTunnel */ +sal_Int64 SAL_CALL X509Certificate_NssImpl::getSomething( const Sequence< sal_Int8 >& aIdentifier ) { + if( isUnoTunnelId(aIdentifier) ) { + return sal::static_int_cast(reinterpret_cast(this)); + } + return 0 ; +} + +/* XUnoTunnel extension */ + +namespace +{ + class theX509Certificate_NssImplUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theX509Certificate_NssImplUnoTunnelId > {}; +} + +const Sequence< sal_Int8>& X509Certificate_NssImpl::getUnoTunnelId() { + return theX509Certificate_NssImplUnoTunnelId::get().getSeq(); +} + +static OUString getAlgorithmDescription(SECAlgorithmID const *aid) +{ + SECOidTag tag; + tag = SECOID_GetAlgorithmTag(aid); + + const char *pDesc = SECOID_FindOIDTagDescription(tag); + + return OUString::createFromAscii( pDesc ) ; +} + +static css::uno::Sequence< sal_Int8 > getThumbprint(CERTCertificate const *pCert, SECOidTag id) +{ + if( pCert != nullptr ) + { + SECStatus rv; + unsigned char fingerprint[32]; + int length = 0; + switch (id) + { + case SEC_OID_MD5: + length = MD5_LENGTH; + break; + case SEC_OID_SHA1: + length = SHA1_LENGTH; + break; + case SEC_OID_SHA256: + length = SHA256_LENGTH; + break; + default: + break; + } + + memset(fingerprint, 0, sizeof fingerprint); + rv = PK11_HashBuf(id, fingerprint, pCert->derCert.data, pCert->derCert.len); + if(rv == SECSuccess) + { + Sequence< sal_Int8 > thumbprint( length ) ; + for( int i = 0 ; i < length ; i ++ ) + thumbprint[i] = fingerprint[i]; + + return thumbprint; + } + } + 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) + { + Sequence< sal_Int8 > key( spk.len ) ; + for( unsigned int i = 0 ; i < spk.len ; i ++ ) + { + key[i] = *( spk.data + i ) ; + } + + return key ; + } + } + + 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); +} + +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); +} + +CertificateKind SAL_CALL X509Certificate_NssImpl::getCertificateKind() +{ + return CertificateKind_X509; +} + +sal_Int32 SAL_CALL X509Certificate_NssImpl::getCertificateUsage( ) +{ + SECStatus rv; + SECItem tmpitem; + sal_Int32 usage; + + rv = CERT_FindKeyUsageExtension(m_pCert, &tmpitem); + if ( rv == 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 */ +Sequence SAL_CALL X509Certificate_NssImpl::getSupportedServiceNames() { return { OUString() }; } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.hxx b/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.hxx new file mode 100644 index 000000000..35cd393f2 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/x509certificate_nssimpl.hxx @@ -0,0 +1,107 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_XMLSECURITY_SOURCE_XMLSEC_NSS_X509CERTIFICATE_NSSIMPL_HXX +#define INCLUDED_XMLSECURITY_SOURCE_XMLSEC_NSS_X509CERTIFICATE_NSSIMPL_HXX + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +class X509Certificate_NssImpl : public ::cppu::WeakImplHelper< + css::security::XCertificate , + css::lang::XUnoTunnel, + css::lang::XServiceInfo > , public xmlsecurity::Certificate +{ + private: + CERTCertificate* m_pCert; + + public: + X509Certificate_NssImpl() ; + virtual ~X509Certificate_NssImpl() override ; + + //Methods from XCertificate + virtual sal_Int16 SAL_CALL getVersion( ) override ; + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSerialNumber( ) override ; + + virtual OUString SAL_CALL getIssuerName( ) override ; + virtual OUString SAL_CALL getSubjectName( ) override ; + + virtual css::util::DateTime SAL_CALL getNotValidBefore( ) override ; + virtual css::util::DateTime SAL_CALL getNotValidAfter( ) override ; + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getIssuerUniqueID( ) override ; + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSubjectUniqueID( ) override ; + + virtual css::uno::Sequence< css::uno::Reference< css::security::XCertificateExtension > > SAL_CALL getExtensions( ) override ; + + virtual css::uno::Reference< css::security::XCertificateExtension > SAL_CALL findCertificateExtension( const css::uno::Sequence< sal_Int8 >& oid ) override ; + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getEncoded( ) override ; + + virtual OUString SAL_CALL getSubjectPublicKeyAlgorithm() override ; + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSubjectPublicKeyValue() override ; + + virtual OUString SAL_CALL getSignatureAlgorithm() override ; + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getSHA1Thumbprint() override ; + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getMD5Thumbprint() override ; + virtual css::security::CertificateKind SAL_CALL getCertificateKind() override; + + virtual sal_Int32 SAL_CALL getCertificateUsage( ) override ; + + //Methods from XUnoTunnel + virtual sal_Int64 SAL_CALL getSomething( const css::uno::Sequence< sal_Int8 >& aIdentifier ) override; + + /// @see xmlsecurity::Certificate::getSHA256Thumbprint(). + virtual css::uno::Sequence getSHA256Thumbprint() override; + + /// @see xmlsecurity::Certificate::getSignatureMethodAlgorithm(). + virtual svl::crypto::SignatureMethodAlgorithm getSignatureMethodAlgorithm() override; + + static const css::uno::Sequence< sal_Int8 >& getUnoTunnelId() ; + + //Helper methods + void setCert( CERTCertificate* cert ) ; + const CERTCertificate* getNssCert() const ; + + /// @throws css::uno::RuntimeException + void setRawCert( const css::uno::Sequence< sal_Int8 >& rawCert ) ; + SECKEYPrivateKey* getPrivateKey(); + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override; + virtual css::uno::Sequence SAL_CALL getSupportedServiceNames() override; +} ; + +#endif // INCLUDED_XMLSECURITY_SOURCE_XMLSEC_NSS_X509CERTIFICATE_NSSIMPL_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/nss/xmlsecuritycontext_nssimpl.cxx b/xmlsecurity/source/xmlsec/nss/xmlsecuritycontext_nssimpl.cxx new file mode 100644 index 000000000..2566a40ac --- /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 + +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 || index >= static_cast(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 || m_nDefaultEnvIndex >= static_cast(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() { + uno::Sequence seqServiceNames { "com.sun.star.xml.crypto.XMLSecurityContext" }; + return seqServiceNames ; +} + +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 000000000..32e4335a5 --- /dev/null +++ b/xmlsecurity/source/xmlsec/nss/xmlsignature_nssimpl.cxx @@ -0,0 +1,317 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 "securityenvironment_nssimpl.hxx" + +#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() ; + } + + Reference< XUnoTunnel > xNodTunnel( xElement , UNO_QUERY_THROW ) ; + XMLElementWrapper_XmlSecImpl* pElement = + reinterpret_cast( + sal::static_int_cast( + xNodTunnel->getSomething( XMLElementWrapper_XmlSecImpl::getUnoTunnelId() ))); + if( pElement == nullptr ) { + throw RuntimeException() ; + } + + pNode = pElement->getNativeElement() ; + + //Get the stream/URI binding + Reference< XUriBinding > xUriBinding = aTemplate->getBinding() ; + if( xUriBinding.is() ) { + //Register the stream input callbacks into libxml2 + if( xmlRegisterStreamInputCallbacks( xUriBinding ) < 0 ) + throw RuntimeException() ; + } + + //Get Keys Manager + Reference< XUnoTunnel > xSecTunnel( aEnvironment , UNO_QUERY_THROW ) ; + + // the key manager should be retrieved from SecurityEnvironment, instead of SecurityContext + + SecurityEnvironment_NssImpl* pSecEnv = + reinterpret_cast( + sal::static_int_cast( + xSecTunnel->getSomething( SecurityEnvironment_NssImpl::getUnoTunnelId() ))); + 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() ; + + Reference< XUnoTunnel > xNodTunnel( xElement , UNO_QUERY_THROW ) ; + XMLElementWrapper_XmlSecImpl* pElement = + reinterpret_cast( + sal::static_int_cast( + xNodTunnel->getSomething( XMLElementWrapper_XmlSecImpl::getUnoTunnelId() ))); + 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 + Reference< XUnoTunnel > xSecTunnel( aEnvironment , UNO_QUERY_THROW ) ; + SecurityEnvironment_NssImpl* pSecEnv = + reinterpret_cast( + sal::static_int_cast( + xSecTunnel->getSomething( SecurityEnvironment_NssImpl::getUnoTunnelId() ))); + 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; + + //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; + } + } + + 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 000000000..f34766666 --- /dev/null +++ b/xmlsecurity/source/xmlsec/saxhelper.cxx @@ -0,0 +1,361 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +#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( const OUString& 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( const OUString& 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( + const OUString& 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( const OUString& 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( const OUString& 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( const OUString& 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( + const OUString& aTarget, + const OUString& aData ) +{ + xmlChar* target = nullptr ; + xmlChar* data = nullptr ; + + target = ous_to_xmlstr( aTarget ) ; + data = ous_to_xmlstr( aData ) ; + + m_pSaxHandler->processingInstruction( m_pParserCtxt , target , data ) ; + + if( target != nullptr ) + { + xmlFree( target ) ; + target = nullptr ; + } + + if( data != nullptr ) + { + xmlFree( data ) ; + data = nullptr ; + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/xmldocumentwrapper_xmlsecimpl.cxx b/xmlsecurity/source/xmlsec/xmldocumentwrapper_xmlsecimpl.cxx new file mode 100644 index 000000000..2d98e44d0 --- /dev/null +++ b/xmlsecurity/source/xmlsec/xmldocumentwrapper_xmlsecimpl.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 "xmlelementwrapper_xmlsecimpl.hxx" + +#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("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. + ******************************************************************************/ +{ + SvXMLAttributeList* pAttributeList = new SvXMLAttributeList(); + uno::Reference < css::xml::sax::XAttributeList > xAttrList(pAttributeList); + + 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), + xAttrList); + } + + xHandler2->startElement( + OUString::fromUtf8(sNodeName), + xAttrList); +} + +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()) + { + uno::Reference< css::lang::XUnoTunnel > xNodTunnel( xXMLElement, uno::UNO_QUERY_THROW ) ; + XMLElementWrapper_XmlSecImpl* pElement + = reinterpret_cast( + sal::static_int_cast( + xNodTunnel->getSomething( + XMLElementWrapper_XmlSecImpl::getUnoTunnelId() ))) ; + + 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( ) +{ + XMLElementWrapper_XmlSecImpl* pElement = new XMLElementWrapper_XmlSecImpl(m_pCurrentElement); + return uno::Reference< css::xml::wrapper::XXMLElementWrapper >(pElement); +} + +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) + { + 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); + + for (int i = 0; i < nLength; ++i) + { + aAttributes[i].sName = xAttribs->getNameByIndex(static_cast(i)); + aAttributes[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( ) +{ + uno::Sequence aRet{ "com.sun.star.xml.wrapper.XMLDocumentWrapper" }; + return aRet; +} + +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 000000000..01f8df702 --- /dev/null +++ b/xmlsecurity/source/xmlsec/xmlelementwrapper_xmlsecimpl.cxx @@ -0,0 +1,78 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 +#include + +namespace com::sun::star::uno { class XComponentContext; } + +using namespace com::sun::star; + +XMLElementWrapper_XmlSecImpl::XMLElementWrapper_XmlSecImpl(const xmlNodePtr pNode) + : m_pElement( pNode ) +{ +} + +/* XUnoTunnel */ +uno::Sequence< sal_Int8 > XMLElementWrapper_XmlSecImpl::getUnoTunnelId() +{ + static ::cppu::OImplementationId implId; + + return implId.getImplementationId(); +} + +sal_Int64 SAL_CALL XMLElementWrapper_XmlSecImpl::getSomething( const uno::Sequence< sal_Int8 >& aIdentifier ) +{ + if (isUnoTunnelId(aIdentifier)) + { + return reinterpret_cast < sal_Int64 > ( this ); + } + + return 0; +} + +/* 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( ) +{ + uno::Sequence aRet { "com.sun.star.xml.wrapper.XMLElementWrapper" }; + return aRet; +} + +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 000000000..d17e2f49c --- /dev/null +++ b/xmlsecurity/source/xmlsec/xmlelementwrapper_xmlsecimpl.hxx @@ -0,0 +1,82 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_XMLSECURITY_SOURCE_XMLSEC_XMLELEMENTWRAPPER_XMLSECIMPL_HXX +#define INCLUDED_XMLSECURITY_SOURCE_XMLSEC_XMLELEMENTWRAPPER_XMLSECIMPL_HXX + +#include +#include +#include +#include + +#include +#include + +class XMLElementWrapper_XmlSecImpl : public cppu::WeakImplHelper +< + css::xml::wrapper::XXMLElementWrapper, + css::lang::XUnoTunnel, + css::lang::XServiceInfo +> +/****** XMLElementWrapper_XmlSecImpl.hxx/CLASS XMLElementWrapper_XmlSecImpl *** + * + * NAME + * XMLElementWrapper_XmlSecImpl -- Class to wrap a libxml2 node + * + * FUNCTION + * Used as a wrapper class to transfer a libxml2 node structure + * between different UNO components. + ******************************************************************************/ +{ +private: + /* the libxml2 node wrapped by this object */ + xmlNodePtr const m_pElement; + +public: + explicit XMLElementWrapper_XmlSecImpl(const xmlNodePtr pNode); + + /* XXMLElementWrapper */ + + /* css::lang::XUnoTunnel */ + virtual sal_Int64 SAL_CALL getSomething( const css::uno::Sequence< sal_Int8 >& aIdentifier ) override; + /// @throws css::uno::RuntimeException + static css::uno::Sequence < sal_Int8 > getUnoTunnelId(); + + /* css::lang::XServiceInfo */ + virtual OUString SAL_CALL getImplementationName( ) override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; + +public: + /* + * NAME + * getNativeElement -- Retrieves the libxml2 node wrapped by this object + * + * SYNOPSIS + * pNode = getNativeElement(); + * + * RESULT + * pNode - the libxml2 node wrapped by this object + */ + xmlNodePtr getNativeElement( ) const { return m_pElement;} +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/xmlsec_init.cxx b/xmlsecurity/source/xmlsec/xmlsec_init.cxx new file mode 100644 index 000000000..7e8c58dde --- /dev/null +++ b/xmlsecurity/source/xmlsec/xmlsec_init.cxx @@ -0,0 +1,69 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.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 +#else +#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(); + } +#else + if( xmlSecNssInit() < 0 ) { + xmlSecShutdown(); + throw RuntimeException(); + } +#endif + + //Enable external stream handlers + if( xmlEnableStreamInputCallbacks() < 0 ) { +#ifdef XMLSEC_CRYPTO_MSCRYPTO + xmlSecMSCngShutdown(); +#else + xmlSecNssShutdown(); +#endif + xmlSecShutdown() ; + throw RuntimeException() ; + } +} + +XSECXMLSEC_DLLPUBLIC void deInitXmlSec() +{ + xmlDisableStreamInputCallbacks(); +#ifdef XMLSEC_CRYPTO_MSCRYPTO + xmlSecMSCngShutdown(); +#else + xmlSecNssShutdown(); +#endif + xmlSecShutdown(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/source/xmlsec/xmlstreamio.cxx b/xmlsecurity/source/xmlsec/xmlstreamio.cxx new file mode 100644 index 000000000..1000252b1 --- /dev/null +++ b/xmlsecurity/source/xmlsec/xmlstreamio.cxx @@ -0,0 +1,243 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this 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 + +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)); + } + } + 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() ; + 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 ) ; + } + } + + 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() ; + } + } + + return 0 ; +} + +} + +int xmlEnableStreamInputCallbacks() +{ + if (!g_bInputCallbacksEnabled) + { + //Register the callbacks into xmlSec + //In order to make the xmlsec io finding the callbacks firstly, + //I put the callbacks at the very beginning. + + //Cleanup the older callbacks. + //Notes: all none default callbacks will lose. + xmlSecIOCleanupCallbacks() ; + + // Make sure that errors are reported via SAL_WARN(). + setErrorRecorder(); + comphelper::ScopeGuard g([] { clearErrorRecorder(); }); + + // Newer xmlsec wants the callback order in the opposite direction. + if (xmlSecCheckVersionExt(1, 2, 26, xmlSecCheckVersionABICompatible)) + { + //Register the default callbacks. + //Notes: the error will cause xmlsec working problems. + int cbs = xmlSecIORegisterDefaultCallbacks() ; + if( cbs < 0 ) { + return -1 ; + } + + //Register my classbacks. + cbs = xmlSecIORegisterCallbacks( + xmlStreamMatch, + xmlStreamOpen, + xmlStreamRead, + xmlStreamClose ) ; + if( cbs < 0 ) { + return -1 ; + } + } + else + { + //Register my classbacks. + int cbs = xmlSecIORegisterCallbacks( + xmlStreamMatch, + xmlStreamOpen, + xmlStreamRead, + xmlStreamClose ) ; + if( cbs < 0 ) { + return -1 ; + } + + //Register the default callbacks. + //Notes: the error will cause xmlsec working problems. + cbs = xmlSecIORegisterDefaultCallbacks() ; + if( cbs < 0 ) { + return -1 ; + } + } + + g_bInputCallbacksEnabled = true; + } + + return 0 ; +} + +int xmlRegisterStreamInputCallbacks( + css::uno::Reference< css::xml::crypto::XUriBinding > const & aUriBinding +) { + if (!g_bInputCallbacksEnabled) + { + if( xmlEnableStreamInputCallbacks() < 0 ) + return -1 ; + } + + if (!g_bInputCallbacksRegistered) + g_bInputCallbacksRegistered = true; + + m_xUriBinding = aUriBinding ; + + return 0 ; +} + +int xmlUnregisterStreamInputCallbacks() +{ + if (g_bInputCallbacksRegistered) + { + //Clear the uri-stream binding + m_xUriBinding.clear() ; + + //disable the registered flag + g_bInputCallbacksRegistered = false; + } + + return 0 ; +} + +void xmlDisableStreamInputCallbacks() { + xmlUnregisterStreamInputCallbacks() ; + g_bInputCallbacksEnabled = false; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmlsecurity/test_docs/CAs/README.txt b/xmlsecurity/test_docs/CAs/README.txt new file mode 100644 index 000000000..b454f1faf --- /dev/null +++ b/xmlsecurity/test_docs/CAs/README.txt @@ -0,0 +1,383 @@ +This folder contains the directory structures needed by openssl to create +and manager certificates. + + + +################################################################################ + +Root 1 +====== +Valid root CA certificate. +Provides CRL = NO +Provides CRL via HTTP = NO +Provides OCSP = NO + +Sub CA 1 Root 1 +=============== +Valid intermediate CA certificate. +Provides CRL = NO +Provides CRL via HTTP = NO +Provides OCSP = NO +CRLDP = NO +AIA = NO + +User 1 Sub CA 1 Root 1 +====================== +Valid end certificate. +CRLDP = NO +AIA = NO + +################################################################################ + +Root 2 +====== +Valid root CA certificate. +Provides CRL = NO +Provides CRL via HTTP = NO +Provides OCSP = NO + +Sub CA 1 Root 2 +=============== +Valid intermediate CA certificate. +Provides CRL = YES +Provides CRL via HTTP = NO +Provides OCSP = NO +CRLDP = NO +AIA = NO + +User 1 Sub CA 1 Root 2 +====================== +Valid end certificate. +CRLDP = NO +AIA = NO + +################################################################################ + +Root 3 +====== +Valid root CA certificate. +Provides CRL = YES +Provides CRL via HTTP = NO +Provides OCSP = NO + +Sub CA 1 Root 3 +=============== +Valid intermediate CA certificate. +Provides CRL = NO +Provides CRL via HTTP = NO +Provides OCSP = NO +CRLDP = NO +AIA = NO + +User 1 Sub CA 1 Root 3 +====================== +Valid end certificate. +CRLDP = NO +AIA = NO + +################################################################################ + +Root 4 +====== +Valid root CA certificate. +Provides CRL = YES +Provides CRL via HTTP = NO +Provides OCSP = NO + +Revoked certificates: + +- Sub CA 2 Root 4 + + +Sub CA 1 Root 4 +=============== +Valid intermediate CA certificate. +Provides CRL = YES +Provides CRL via HTTP = NO +Provides OCSP = NO +CRLDP = NO +AIA = NO + +Revoked certificates: + +- User 2 Sub CA 1 Root 4 + + +User 1 Sub CA 1 Root 4 +====================== +Valid end certificate. +CRLDP = NO +AIA = NO + +User 2 Sub CA 1 Root 4 +====================== +Revoked end certificate. +CRLDP = NO +AIA = NO + +Sub CA 2 Root 4 +=============== +Revoked intermediate CA certificate. Reason = keyCompromise +Provides CRL = YES +Provides CRL via HTTP = NO +Provides OCSP = NO +CRLDP = NO +AIA = NO + +Revoked certificates: + +- User 2 Sub CA 2 Root 4 + +User 1 Sub CA 2 Root 4 +====================== +Valid end certificate. Issuer is revoked. +CRLDP = NO +AIA = NO + +User 2 Sub CA 2 Root 4 +====================== +Revoked end certificate. Reason = keyCompromise. Issuer is revoked. +CRLDP = NO +AIA = NO + +################################################################################ + +Root 5 +====== +Valid root CA certificate. +Provides CRL = NO +Provides CRL via HTTP = NO +Provides OCSP = NO + +Sub CA 1 Root 5 +=============== +Valid intermediate CA certificate. +Provides CRL = NO +Provides CRL via HTTP = YES +Provides OCSP = NO +CRLDP = URL=http://localhost:8901/demoCA/crl/Root_5.crl +AIA = NO + +User 1 Sub CA 1 Root 5 +====================== +Valid end certificate. +CRLDP = URL=http://localhost:8902/demoCA/crl/Sub_CA_1_Root_5.crl +AIA = NO + + +################################################################################ + +Root 6 +====== +Valid root CA certificate. +Provides CRL = NO +Provides CRL via HTTP = YES +Provides OCSP = NO + +Sub CA 1 Root 6 +=============== +Valid intermediate CA certificate. +Provides CRL = NO +Provides CRL via HTTP = NO +Provides OCSP = NO +CRLDP = URL=http://localhost:8901/demoCA/crl/Root_6.crl +AIA = NO + +User 1 Sub CA 1 Root 6 +====================== +Valid end certificate. +CRLDP = URL=http://localhost:8902/demoCA/crl/Sub_CA_1_Root_6.crl +AIA = NO + +################################################################################ + +Root 7 +====== +Valid root CA certificate. +Provides CRL = NO +Provides CRL via HTTP = YES +Provides OCSP = NO + +Revoked certificates: + +- Sub CA 2 Root 7 + + +Sub CA 1 Root 7 +=============== +Valid intermediate CA certificate. +Provides CRL = NO +Provides CRL via HTTP = YES +Provides OCSP = NO +CRLDP = URL=http://localhost:8901/demoCA/crl/Root_7.crl +AIA = NO + +Revoked certificates: + +- User 2 Sub CA 1 Root 7 + + +User 1 Sub CA 1 Root 7 +====================== +Valid end certificate. +CRLDP = URL=http://localhost:8902/demoCA/crl/Sub_CA_1_Root_7.crl +AIA = NO + +User 2 Sub CA 1 Root 7 +====================== +Revoked end certificate. Reason = CACompromise. +CRLDP = URL=http://localhost:8902/demoCA/crl/Sub_CA_1_Root_7.crl +AIA = NO + +Sub CA 2 Root 7 +=============== +Revoked intermediate CA certificate. Reason = keyCompromise +Provides CRL = NO +Provides CRL via HTTP = YES +Provides OCSP = NO +CRLDP = URL=http://localhost:8901/demoCA/crl/Root_7.crl +AIA = NO + +Revoked certificates: + +- User 2 Sub CA 2 Root 7 + +User 1 Sub CA 2 Root 7 +====================== +Valid end certificate. Issuer is revoked. +CRLDP = URL=http://localhost:8902/demoCA/crl/Sub_CA_2_Root_7.crl +AIA = NO + +User 2 Sub CA 2 Root 7 +====================== +Revoked end certificate. Reason = CACompromise. Issuer is revoked. +CRLDP = URL=http://localhost:8902/demoCA/crl/Sub_CA_2_Root_7.crl +AIA = NO + +################################################################################ + +Root 8 +====== +Valid root CA certificate. +Provides CRL = NO +Provides CRL via HTTP = NO +Provides OCSP = YES + +Revoked certificates: + +- Sub CA 2 Root 8 + + +Sub CA 1 Root 8 +=============== +Valid intermediate CA certificate. +Provides CRL = NO +Provides CRL via HTTP = NO +Provides OCSP = YES +CRLDP = +AIA = OCSP;URI:http://localhost:8888 + +Revoked certificates: + +- User 2 Sub CA 1 Root 8 + + +User 1 Sub CA 1 Root 8 +====================== +Valid end certificate. +CRLDP = NO +AIA = OCSP;URI:http://localhost:8889 + +User 2 Sub CA 1 Root 8 +====================== +Revoked end certificate. Reason = superseded. +CRLDP = NO +AIA = OCSP;URI:http://localhost:8889 + +Sub CA 2 Root 8 +=============== +Revoked intermediate CA certificate. Reason = superseded. +Provides CRL = NO +Provides CRL via HTTP = NO +Provides OCSP = YES +CRLDP = NO +AIA = OCSP;URI:http://localhost:8888 + +Revoked certificates: + +- User 2 Sub CA 2 Root 8 + +User 1 Sub CA 2 Root 8 +====================== +Valid end certificate. Issuer is revoked. +CRLDP = NO +AIA = OCSP;URI:http://localhost:8889 + +User 2 Sub CA 2 Root 8 +====================== +Revoked end certificate. Reason = superseded. Issuer is revoked. +CRLDP = NO +AIA = OCSP;URI:http://localhost:8889 + +################################################################################ + +Root 9 +====== +Valid root CA certificate. (Not installed.) +Provides CRL = YES +Provides CRL via HTTP = NO +Provides OCSP = NO + +Sub CA 1 Root 9 +=============== +Valid intermediate CA certificate. +Provides CRL = YES +Provides CRL via HTTP = NO +Provides OCSP = NO +CRLDP = NO +AIA = NO + +User 1 Sub CA 1 Root 9 +====================== +Valid end certificate. +CRLDP = NO +AIA = NO + +################################################################################ + +Root 10 +====== +Valid root CA certificate. +Provides CRL = YES +Provides CRL via HTTP = NO +Provides OCSP = NO + +Sub CA 1 Root 10 +=============== +Valid intermediate CA certificate. (Not installed.) +Provides CRL = NO +Provides CRL via HTTP = YES +Provides OCSP = NO +CRLDP = NO +AIA = NO + +User 1 Sub CA 1 Root 10 +====================== +Valid end certificate. +CRLDP = URI:http://localhost:8902/demoCA/crl/Sub_CA_1_Root_10.crl +AIA = caIssuers;URI:http://localhost:8910/demoCA/Sub_CA_1_Root_10.crt + +################################################################################ + +Root 11 +====== +Valid root CA certificate. +Provides CRL = YES +Provides CRL via HTTP = NO +Provides OCSP = NO + +User x Root 11 +====================== +All certificate issues by Root 11 are valid end certificate. Currently there are +31 certificates. + diff --git a/xmlsecurity/test_docs/CAs/Root_1/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Root_1/demoCA/cacert.pem new file mode 100644 index 000000000..091052e3a --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_1/demoCA/cacert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDBDCCAm2gAwIBAgIJAJWwBSvtwjktMA0GCSqGSIb3DQEBBQUAMF8xCzAJBgNV +BAYTAkRFMRAwDgYDVQQIEwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9y +ZzEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgMTAeFw0wOTEx +MTgxNDU1NDFaFw0zNDExMTIxNDU1NDFaMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw +gYkCgYEAvrD6NFWcOQQVxIuXw5Pzpy667PZbBP80ow2Bbnj+RFCI/LbgfQTsC8Bw +eSlQGX7IqMHkCTuWNJw7CoNeOLFhRMtm0DEKnEkZlM0t6kpFshbs12jZu9okcnII +F5uIoKxx/thbD5AbC1Q74vZr6XOXY5Sc+k9Ic6Jwhe9ZyEt6SUsCAwEAAaOBxzCB +xDAdBgNVHQ4EFgQUD/rG69/OuLuzqT5Cprrs0pPKR6QwgZEGA1UdIwSBiTCBhoAU +D/rG69/OuLuzqT5Cprrs0pPKR6ShY6RhMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgMYIJAJWwBSvtwjktMA8GA1UdEwEB/wQF +MAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAqORur4HQGdQOQCaiyZR5u0+9mM/0w79y +r8Cmt+H8WB5BBeDgCyOcmaZjF0eEoRBF/ZhtlO54i4CH/yb/Pl6gGlxfGZL9iLu0 +tv4HRIIibnoi0N7Z0r/dhJcrTHo4Ha8EARhAqxoNUSlGVBsaKUfjW9RyCjv4Akyi +WUSwsmtd/sY= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_1/demoCA/crl/DO_NOT_CREATE_A_CRL b/xmlsecurity/test_docs/CAs/Root_1/demoCA/crl/DO_NOT_CREATE_A_CRL new file mode 100644 index 000000000..e69de29bb diff --git a/xmlsecurity/test_docs/CAs/Root_1/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Root_1/demoCA/crlnumber new file mode 100644 index 000000000..83b33d238 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_1/demoCA/crlnumber @@ -0,0 +1 @@ +1000 diff --git a/xmlsecurity/test_docs/CAs/Root_1/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Root_1/demoCA/index.txt new file mode 100644 index 000000000..9a6e64301 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_1/demoCA/index.txt @@ -0,0 +1 @@ +V 341112150713Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 1 Root 1 diff --git a/xmlsecurity/test_docs/CAs/Root_1/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Root_1/demoCA/index.txt.attr new file mode 100644 index 000000000..8f7e63a34 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_1/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Root_1/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Root_1/demoCA/newcerts/1000.pem new file mode 100644 index 000000000..be26aa5d8 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_1/demoCA/newcerts/1000.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 1 + Validity + Not Before: Nov 18 15:07:13 2009 GMT + Not After : Nov 12 15:07:13 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 1 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:d9:3a:8d:64:95:87:76:76:e8:61:c3:e9:65:f4: + a6:b7:0c:77:0e:4b:10:e8:14:a3:e1:84:69:7c:8e: + 97:d2:7d:01:ad:b2:dc:5c:cd:c6:91:a1:f3:93:7c: + 54:36:64:e3:ca:22:ca:00:cb:c6:91:ab:6b:26:88: + 69:60:9a:61:d7:59:17:db:93:7d:09:36:da:28:cb: + ec:2d:a4:26:bb:1a:42:20:b8:08:b2:0f:b9:77:a6: + 80:71:cf:13:f5:37:a2:90:4d:ab:e8:97:49:d2:80: + 94:8f:b1:9d:5a:b4:9f:de:ff:fa:b6:d6:e0:45:5f: + cc:d4:10:1e:32:46:7b:ba:55 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 37:71:74:81:44:DD:1E:B1:60:96:41:B7:4B:38:C4:B7:79:1B:CF:8A + X509v3 Authority Key Identifier: + keyid:0F:FA:C6:EB:DF:CE:B8:BB:B3:A9:3E:42:A6:BA:EC:D2:93:CA:47:A4 + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 1 + serial:95:B0:05:2B:ED:C2:39:2D + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 18:f6:02:5e:75:04:5f:eb:3b:07:41:85:c0:9e:08:29:58:3d: + b5:6f:c2:aa:24:0d:93:1d:17:fc:be:d6:43:ac:43:d7:4d:a0: + 2c:40:fd:3d:d5:7e:91:46:25:49:62:ba:e9:7f:67:c2:fc:8a: + c3:a0:37:bf:ec:f9:54:bf:61:10:35:dd:5b:bb:da:7c:70:54: + 32:13:b9:ae:7d:ea:a5:7d:aa:55:3e:ef:0a:ef:12:fd:c3:f6: + e5:25:98:97:34:02:64:fd:88:79:b3:e2:f4:fc:ff:e7:d3:98: + f1:d9:d5:18:d9:b4:62:ae:99:88:61:2e:ff:02:6a:13:35:fe: + 37:c7 +-----BEGIN CERTIFICATE----- +MIIDBjCCAm+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCAxMB4XDTA5MTExODE1MDcx +M1oXDTM0MTExMjE1MDcxM1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCAxMIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDZOo1klYd2duhhw+ll9Ka3DHcOSxDoFKPhhGl8jpfSfQGtstxczcaR +ofOTfFQ2ZOPKIsoAy8aRq2smiGlgmmHXWRfbk30JNtooy+wtpCa7GkIguAiyD7l3 +poBxzxP1N6KQTavol0nSgJSPsZ1atJ/e//q21uBFX8zUEB4yRnu6VQIDAQABo4HH +MIHEMB0GA1UdDgQWBBQ3cXSBRN0esWCWQbdLOMS3eRvPijCBkQYDVR0jBIGJMIGG +gBQP+sbr3864u7OpPkKmuuzSk8pHpKFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCAxggkAlbAFK+3COS0wDwYDVR0TAQH/ +BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQAY9gJedQRf6zsHQYXAnggpWD21b8Kq +JA2THRf8vtZDrEPXTaAsQP091X6RRiVJYrrpf2fC/IrDoDe/7PlUv2EQNd1bu9p8 +cFQyE7mufeqlfapVPu8K7xL9w/blJZiXNAJk/Yh5s+L0/P/n05jx2dUY2bRirpmI +YS7/AmoTNf43xw== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_1/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Root_1/demoCA/private/cakey.pem new file mode 100644 index 000000000..6d38b24e6 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_1/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,2D2CC3782F59A842 + +901JcMMdeCfHjfY05bkyLIsgMxwu4SFJPXZH75ebFtJQpkQQf5WNhSlo3sgKJ5MF +GZeqQw4w9CmN+CNqQENZOOGrVKxT+sFtWIgSLVk4hrLzPtsT7domHc1yUKfpBH/w +xo/bsL5wZPqcsxSdlmd4FA0PKzW/rhyYvRxF0oKQx2PVnJKT29WbhwlYurI3+2gG +pS+N6f7awWjmgyqYvFuFo7DWhERDDL/Bi/sJ7qFinijtfp1CkVG1XWFZ8Tu9ij+t +KPT3fpWbh4sV0V1ZGng7EPb4c+p/+GHvKsGM9N5kuyxufllNzAeIy6hfTR3mxn0i +Ep4CoufMi0JwNEfgwBB+o47k1hVoBTn0ofXc2iP6iQWsoC5ZoPPGLLklWK3Tur7P +kpng8UECTxV2s6J3nYkAoHfy+TzK+nssFPpE8zDmaprpeTj9oh3KrPTn0IdoPHcx +oI3yqWqDK9uErJBBCAjLF0SPJWAsmp0HsJaGnj5ErVe0yy3jBxVWogVDSWkoWU0W ++umK1pSQrS1A/oKErsnbhPi8XAD/gd4etEaKdcY538QKgE2tdPvhLoAeXxslyOfG +UiPohtmcm2Mva7vT0Iu1MGKplw76DxmmM1Rpf3+u7Kwf/+K6bMOSBGZQJhjE2AuZ +aPyHX8gCNlZfqB6eeuWdbqIHhTN5dS2Bba3QquvS84Vgb3O2ck+vdjmdPEeetvA7 +7S4WZYHBRmz1ZHwdfSvwyBkdTRP5YrUhrIthbqy2NjcP9TkpQmJaDIlWXsGY738q +zTsjCkcnS06x0/JvHe1I8IAib+MFsmGI7Dw25fzgY3ReS4wZRZdU0A== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Root_1/demoCA/serial b/xmlsecurity/test_docs/CAs/Root_1/demoCA/serial new file mode 100644 index 000000000..dd1172404 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_1/demoCA/serial @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Root_1/openssl.cfg b/xmlsecurity/test_docs/CAs/Root_1/openssl.cfg new file mode 100644 index 000000000..0dd15bd9e --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_1/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Root_10/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Root_10/demoCA/cacert.pem new file mode 100644 index 000000000..72e6c66e2 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_10/demoCA/cacert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDBzCCAnCgAwIBAgIJAL/ID7vZoDprMA0GCSqGSIb3DQEBBQUAMGAxCzAJBgNV +BAYTAkRFMRAwDgYDVQQIEwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9y +ZzEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxEDAOBgNVBAMTB1Jvb3QgMTAwHhcNMDkx +MTIzMTUwNzA0WhcNMzQxMTE3MTUwNzA0WjBgMQswCQYDVQQGEwJERTEQMA4GA1UE +CBMHSGFtYnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0Rl +dmVsb3BtZW50MRAwDgYDVQQDEwdSb290IDEwMIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQC5qE1pk/tI2i60IrVhlwS77j7jAyktxRuwKJqBECd2ZD2/goO8wcwD +R/wfrh+zuLWRwFb57PF1O7ig+WNhQk3GDhXhMbuB82Bwjb/n5phKDWHsAIqDRbH4 +vpl/7sWYXvE46zf41PpQPgudOtqpeL1ENFoHKZOJthkBc4Yx6HTUSQIDAQABo4HI +MIHFMB0GA1UdDgQWBBTIp6OAIHRsb+wReva+JhA3MYewejCBkgYDVR0jBIGKMIGH +gBTIp6OAIHRsb+wReva+JhA3MYeweqFkpGIwYDELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMIIJAL/ID7vZoDprMA8GA1UdEwEB +/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAroDDzqZQL+7NeQuePohejcGfFR/0 +vtbQ3AYViQ2JS42gQpaNaMNcVCvO0nUwLHldLNVdQsn9P0ultu6KcUKkBbY4/2Xp +er6RMQWsrKVLnszgIi2gk1NiNwZ+N9RISJvElaQuIciZs+8sM6LOPybVTArMjxEo +U3VqHTViFfOvWC0= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_10/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Root_10/demoCA/crlnumber new file mode 100644 index 000000000..dd1172404 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_10/demoCA/crlnumber @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Root_10/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Root_10/demoCA/index.txt new file mode 100644 index 000000000..2db3924ce --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_10/demoCA/index.txt @@ -0,0 +1 @@ +V 341117151448Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 1 Root 10 diff --git a/xmlsecurity/test_docs/CAs/Root_10/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Root_10/demoCA/index.txt.attr new file mode 100644 index 000000000..8f7e63a34 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_10/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Root_10/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Root_10/demoCA/newcerts/1000.pem new file mode 100644 index 000000000..1f27b97b3 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_10/demoCA/newcerts/1000.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 10 + Validity + Not Before: Nov 23 15:14:48 2009 GMT + Not After : Nov 17 15:14:48 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 10 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:e4:d5:66:14:88:9f:79:41:50:b0:d1:a0:1b:98: + bf:b0:21:34:30:36:70:58:6f:8b:58:f1:b9:58:3a: + ce:29:6b:65:b6:11:f7:0d:c8:a6:c3:be:db:0f:2a: + 4e:c7:42:df:c9:0e:13:c0:00:0f:af:b5:71:c4:bc: + dd:82:fc:4a:27:c0:ee:af:ba:e1:7b:67:de:6b:bb: + ac:4c:fe:88:01:1a:73:4e:f5:32:15:3a:d0:cb:6b: + 97:84:1b:6c:d0:d6:91:a8:a4:5a:87:2a:69:61:36: + 1d:42:cc:16:d0:03:9c:c6:90:5c:61:20:8b:b1:be: + b6:54:24:5b:6f:1f:a9:5a:6f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 11:63:A1:BE:8B:E3:56:07:E6:A3:9F:23:39:72:7D:E3:22:B6:53:39 + X509v3 Authority Key Identifier: + keyid:C8:A7:A3:80:20:74:6C:6F:EC:11:7A:F6:BE:26:10:37:31:87:B0:7A + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 10 + serial:BF:C8:0F:BB:D9:A0:3A:6B + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 6b:0f:75:6d:56:b0:4e:45:19:65:ad:50:ef:4e:87:6c:95:5d: + 05:39:5a:43:5c:b4:51:25:9a:ec:f4:93:d1:f0:f6:91:dd:a3: + 77:95:0c:74:3c:a9:7c:c2:f6:62:ce:bf:58:5f:66:1f:d0:55: + ca:d8:2d:c4:1e:29:3a:ad:55:2c:9d:2c:8f:8e:9e:ce:ac:17: + 7e:1b:d1:16:d9:12:76:5c:2d:3f:9d:70:66:aa:39:34:f0:ec: + 31:4b:4b:5a:14:0c:c5:5b:3c:c8:47:02:90:cb:77:d7:4f:88: + 10:a7:80:3d:ca:19:5c:b5:04:c9:f0:e1:1b:5a:5f:fb:61:b2: + 14:b5 +-----BEGIN CERTIFICATE----- +MIIDCTCCAnKgAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMDAeFw0wOTExMjMxNTE0 +NDhaFw0zNDExMTcxNTE0NDhaMGkxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxGTAXBgNVBAMTEFN1YiBDQSAxIFJvb3QgMTAwgZ8wDQYJKoZIhvcNAQEBBQAD +gY0AMIGJAoGBAOTVZhSIn3lBULDRoBuYv7AhNDA2cFhvi1jxuVg6zilrZbYR9w3I +psO+2w8qTsdC38kOE8AAD6+1ccS83YL8SifA7q+64Xtn3mu7rEz+iAEac071MhU6 +0Mtrl4QbbNDWkaikWocqaWE2HULMFtADnMaQXGEgi7G+tlQkW28fqVpvAgMBAAGj +gcgwgcUwHQYDVR0OBBYEFBFjob6L41YH5qOfIzlyfeMitlM5MIGSBgNVHSMEgYow +gYeAFMino4AgdGxv7BF69r4mEDcxh7B6oWSkYjBgMQswCQYDVQQGEwJERTEQMA4G +A1UECBMHSGFtYnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsT +C0RldmVsb3BtZW50MRAwDgYDVQQDEwdSb290IDEwggkAv8gPu9mgOmswDwYDVR0T +AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBrD3VtVrBORRllrVDvTodslV0F +OVpDXLRRJZrs9JPR8PaR3aN3lQx0PKl8wvZizr9YX2Yf0FXK2C3EHik6rVUsnSyP +jp7OrBd+G9EW2RJ2XC0/nXBmqjk08OwxS0taFAzFWzzIRwKQy3fXT4gQp4A9yhlc +tQTJ8OEbWl/7YbIUtQ== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_10/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Root_10/demoCA/private/cakey.pem new file mode 100644 index 000000000..f75ccc08e --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_10/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,78CCF9A24E7B5044 + +ppKSX6K7DHnU4EvbmBAIzWDJ35yGppjzNdWRKpB7rkGW60dW0Cw0Jmbxf1dfbUC+ +UTWtxE+i0x159jF7jGobPvLFQnAg1ZPUUIgeXJt+fqf/OghY4i8x82BdSlaKJ293 +GgwR9m1N1I2/6ydob+9KwzJhOPhmylyUyRJVAx/OF86E9G4nxtuJA1c1nzSBgwR5 +7uHU0LiY5A42iTDiMmu7Jw4vj6Cy81P88hmyoVzo4JQG8YFuJyLz2ei+DJ3/572z +BCefqDKmlmI2vvayZW1jgpLDlTwmqiIGUDBBipN4vDmqZAdEbv/9BjLkS4Svy3PU +xaFs1tFQzv8ivGpyPWU5naoTKhmMhOEAKpEi6YqWbcD/qKn1pRrYSyVyD9zNXHEK +QrXjTP+D/DMSHNJTo5WI4kxvwSZtPI97vaCTmxkrjnIXDPD5L4v9dJUdejnngsqn +cHB/C/05dR0RLEp5CHrl0hwGiIY1IgQXmGHY2HEUyQYttyJ5jdY0pdnn9n0eQxHr +9Mg3WneWC42XHw0pyqEsgiMmr8SjaF42MSrMB6y4WEVtBstn03LTdFnRIFTgZ5Mj +l/O2mSk+YUBR4CYTUTRaWpzCAZmFVy98I8KQgrhi8t96wrRe0+9tB1uC5PoDNR5P +CcgsmiEPeqolPZwOmnDdij+DcIiT43Sx2vDYGfDtqc+kur/O6noYyX8Kf7wzcpan +V4gHTCEOrlcRiEcVIxAQFDpB8CERG9fJvnBdZE9Gjepz6OatRpE/2kDZMelwRcEx +V5zeE1qNS51gdq2dE0qYkdyU1yfbNUouqtFy/z1sXU6Q5nR1r21jFQ== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Root_10/demoCA/serial b/xmlsecurity/test_docs/CAs/Root_10/demoCA/serial new file mode 100644 index 000000000..dd1172404 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_10/demoCA/serial @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Root_10/openssl.cfg b/xmlsecurity/test_docs/CAs/Root_10/openssl.cfg new file mode 100644 index 000000000..f48e3d5a3 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_10/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Root_7.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/cacert.pem new file mode 100644 index 000000000..8cfffd9a6 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/cacert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDBzCCAnCgAwIBAgIJAI3gSU2IIGPLMA0GCSqGSIb3DQEBBQUAMGAxCzAJBgNV +BAYTAkRFMRAwDgYDVQQIEwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9y +ZzEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxEDAOBgNVBAMTB1Jvb3QgMTEwHhcNMTAw +MTE0MTEzNzA1WhcNMzUwMTA4MTEzNzA2WjBgMQswCQYDVQQGEwJERTEQMA4GA1UE +CBMHSGFtYnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0Rl +dmVsb3BtZW50MRAwDgYDVQQDEwdSb290IDExMIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDKGrq6yC3tyctcBo+iz31MF2yvDiQ7YFgez8TswNvb3USOPOUPsCaB +ufVN6ULSqmGi5BzFIW7CVAj5L+iCrrwMtPyG86fKbvgdWmLepz5a4S1y+vydnQ0B +rJCNdxmLdQK+l/P7jzrH5xhcR62DPQ2lLabvmixvylHv4H6cFjJ98wIDAQABo4HI +MIHFMB0GA1UdDgQWBBToarvCkOpscCI+9vZIGwPmvremVTCBkgYDVR0jBIGKMIGH +gBToarvCkOpscCI+9vZIGwPmvremVaFkpGIwYDELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMYIJAI3gSU2IIGPLMA8GA1UdEwEB +/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAZRXdBfSqhY+xELs28/gjsZ4/mUvu +LKL3PruRCNqUgIOznEdxsQXsmLIQhEPZ4a4jd31srFD2j5gJmZ8KdeFXII9NRvIX +RpRcrl2uclHXWbIC7s6xiATDWumrL2nXB5bU4qYMZ0ybytXprIwkzqRFXUrEHcYm +OXJCSKayIviQ6G0= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Root_11/demoCA/crlnumber new file mode 100644 index 000000000..83b33d238 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/crlnumber @@ -0,0 +1 @@ +1000 diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Root_11/demoCA/index.txt new file mode 100644 index 000000000..f6c52e5ac --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/index.txt @@ -0,0 +1,35 @@ +V 350108161110Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\xC5\xB9\xC5\xBA\xC5\xBB\xC5\xBC\xC5\xBD\xC5\xBE \xEF\xAC\xB3 j\xCE\xAC\xCE\xAD\xCE\xAE +V 350108161614Z 1001 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\xC5\xB9\xC5\xBA\xC5\xBB\xC5\xBC\xC5\xBD\xC5\xBE \xEF\xAD\x86 j\xCE\xAC\xCE\xAD\xCE\xAE +V 350112144417Z 1002 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x04\x0F\x04\x10\x04\x11\x04\x12\x04\x13\x04\x14 +V 350112153942Z 1003 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x01y\x01z\x01{\x00 \x03\xA6\x03\xA7\x03\xA8\x03\xA9 +V 350112160038Z 1004 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00"\x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00s\x00" +V 350112160547Z 1005 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00"\x00"\x00d\x00o\x00u\x00b\x00l\x00e\x00 \x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00s\x00"\x00" +V 350112160921Z 1006 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00"\x00"\x00t\x00w\x00o\x00 \x00s\x00t\x00a\x00r\x00t\x00i\x00n\x00g\x00 \x00o\x00n\x00e\x00 \x00e\x00n\x00d\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00" +V 350112161153Z 1007 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00"\x00s\x00t\x00a\x00r\x00t\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e +V 350112161405Z 1008 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00e\x00n\x00d\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00" +V 350112161631Z 1009 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00"\x00q\x00u\x00o\x00t\x00e +V 350112161857Z 100A unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00d\x00o\x00u\x00b\x00l\x00e\x00 \x00"\x00"\x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00q\x00u\x00o\x00t\x00e +V 350113090237Z 100B unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00p\x00a\x00r\x00t\x00i\x00a\x00l\x00l\x00y\x00 \x00"\x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00" +V 350113094852Z 100C unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00"\x00U\x00s\x00e\x00r\x00 \x001\x001\x00,\x00 \x00s\x00t\x00a\x00r\x00t\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e +V 350113095110Z 100D unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00U\x00s\x00e\x00r\x00 \x001\x002\x00,\x00 \x00e\x00n\x00d\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00" +V 350113095308Z 100E unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00"\x00U\x00s\x00e\x00r\x00 \x001\x003\x00,\x00 \x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00s\x00" +V 350113095502Z 100F unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00U\x00s\x00e\x00r\x00 \x001\x004\x00 \x00"\x00,\x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00q\x00u\x00o\x00t\x00e\x00" +V 350113095752Z 1010 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00\\x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00s\x00\ +V 350113095922Z 1011 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00\\x00\\x00d\x00o\x00u\x00b\x00l\x00e\x00 \x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00s\x00\\x00\ +V 350113100207Z 1012 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00\\x00\\x00t\x00w\x00o\x00 \x00s\x00t\x00a\x00r\x00t\x00i\x00n\x00g\x00 \x00o\x00n\x00e\x00 \x00e\x00n\x00d\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00\ +V 350113100436Z 1013 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00\\x00s\x00t\x00a\x00r\x00t\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e +V 350113100550Z 1014 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00e\x00n\x00d\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00\ +V 350113100707Z 1015 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00\\x00q\x00u\x00o\x00t\x00e +V 350113100950Z 1016 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00d\x00o\x00u\x00b\x00l\x00e\x00 \x00\\x00\\x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00q\x00u\x00o\x00t\x00e +V 350113101153Z 1017 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00p\x00a\x00r\x00t\x00i\x00a\x00l\x00l\x00y\x00 \x00\\x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00\ +V 350113101338Z 1018 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00\\x00U\x00s\x00e\x00r\x00 \x002\x003\x00,\x00 \x00s\x00t\x00a\x00r\x00t\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e +V 350113101450Z 1019 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00U\x00s\x00e\x00r\x00 \x002\x004\x00,\x00 \x00e\x00n\x00d\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00\ +V 350113101610Z 101A unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00\\x00U\x00s\x00e\x00r\x00 \x002\x005\x00,\x00 \x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00\ +V 350113101745Z 101B unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00U\x00s\x00e\x00r\x00 \x002\x006\x00\\x00,\x00 \x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00q\x00u\x00o\x00t\x00e +V 350113101913Z 101C unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=comma, comma, comma , +V 350113102047Z 101D unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=equal CN=User 28 +V 350113102213Z 101E unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 29+OU=ooo +V 350113102601Z 101F unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00U\x00s\x00e\x00r\x00 \x003\x000\x00<\x00 \x00>\x00#\x00;\x00 \x00"\x00+\x00" +V 350113102847Z 1020 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00U\x00s\x00e\x00r\x00 \x003\x001\x00 \x00\\x00"\x00a\x00,\x00b\x00"\x00+\x00C\x00N\x00=\x00U\x00S\x00,\x00 \x00>\x00 \x00\\x00\\x00d\x00e\x00 \x00< +V 350113104059Z 1021 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=\x00U\x00s\x00e\x00r\x00 \x001\x004\x00 \x00"\x00,\x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00q\x00u\x00o\x00t\x00e +V 111108105139Z 1022 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 35 diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Root_11/demoCA/index.txt.attr new file mode 100644 index 000000000..8f7e63a34 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1000.pem new file mode 100644 index 000000000..6efde26f7 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1000.pem @@ -0,0 +1,57 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 14 16:11:10 2010 GMT + Not After : Jan 8 16:11:10 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\xC5\xB9\xC5\xBA\xC5\xBB\xC5\xBC\xC5\xBD\xC5\xBE \xEF\xAC\xB3 j\xCE\xAC\xCE\xAD\xCE\xAE + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:c5:8e:23:dc:00:60:ab:13:ac:00:15:c8:2f:13: + 04:4a:05:15:38:1e:ea:43:cb:68:8e:e3:08:cc:a4: + bb:ef:78:3e:4a:d3:3c:89:50:95:c4:16:6f:a4:89: + 97:4a:07:ad:17:b4:96:1e:54:87:82:ed:22:a4:15: + f7:cf:09:83:b7:4d:ee:75:70:8c:71:5a:b8:e7:4d: + 27:b4:f8:eb:19:67:8f:58:3f:4c:5f:b3:ca:aa:bd: + 5b:95:d7:b4:ba:d4:bc:0e:69:01:52:b9:8a:2d:55: + 83:9e:4d:3f:01:0c:f1:d7:bd:c9:82:54:d2:71:d6: + 51:9c:55:4c:a3:82:43:35:2f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + CA:DF:DA:1A:F7:9C:D8:41:19:34:69:EA:67:74:68:CA:A3:24:0F:9F + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + Signature Algorithm: sha1WithRSAEncryption + 28:3a:db:4b:fd:15:4c:bb:ea:74:b4:53:4f:75:2a:92:3c:78: + b6:86:aa:39:bc:b0:67:3a:5a:00:f1:1e:74:5c:c7:2b:19:4f: + f4:c0:4d:ff:01:4c:b2:0f:b5:49:14:c3:9a:96:ce:61:b6:c7: + 37:82:44:75:76:fc:bd:5d:74:f9:22:ae:f2:36:cb:20:b7:e3: + c8:c8:01:ae:d5:01:f6:5e:b4:cb:ca:76:fe:72:98:f3:0a:c3: + ac:76:fa:41:67:b4:5c:92:67:fa:ca:17:02:80:00:d8:b6:d5: + 01:03:89:25:97:96:60:86:0c:0b:d8:64:94:c9:77:43:28:06: + f9:4e +-----BEGIN CERTIFICATE----- +MIIClzCCAgCgAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTQxNjEx +MTBaFw0zNTAxMDgxNjExMTBaMHExCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxITAfBgNVBAMUGMW5xbrFu8W8xb3FviDvrLMgas6szq3OrjCBnzANBgkqhkiG +9w0BAQEFAAOBjQAwgYkCgYEAxY4j3ABgqxOsABXILxMESgUVOB7qQ8tojuMIzKS7 +73g+StM8iVCVxBZvpImXSgetF7SWHlSHgu0ipBX3zwmDt03udXCMcVq4500ntPjr +GWePWD9MX7PKqr1blde0utS8DmkBUrmKLVWDnk0/AQzx173JglTScdZRnFVMo4JD +NS8CAwEAAaNPME0wCwYDVR0PBAQDAgXgMB0GA1UdDgQWBBTK39oa95zYQRk0aepn +dGjKoyQPnzAfBgNVHSMEGDAWgBToarvCkOpscCI+9vZIGwPmvremVTANBgkqhkiG +9w0BAQUFAAOBgQAoOttL/RVMu+p0tFNPdSqSPHi2hqo5vLBnOloA8R50XMcrGU/0 +wE3/AUyyD7VJFMOals5htsc3gkR1dvy9XXT5Iq7yNssgt+PIyAGu1QH2XrTLynb+ +cpjzCsOsdvpBZ7Rckmf6yhcCgADYttUBA4kll5ZghgwL2GSUyXdDKAb5Tg== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1002.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1002.pem new file mode 100644 index 000000000..037410ad7 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1002.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4098 (0x1002) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 18 14:44:17 2010 GMT + Not After : Jan 12 14:44:17 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x04\x0F\x04\x10\x04\x11\x04\x12\x04\x13\x04\x14 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:b4:d3:fd:a0:56:2b:d9:72:66:e3:fc:4b:5b:70: + fb:9c:23:10:0b:b9:8a:c4:d1:dd:1d:37:cd:20:f4: + 9d:52:c3:8f:80:14:26:c4:3e:dc:3d:af:38:86:70: + 2f:e1:54:1c:a6:5e:b6:6a:2d:73:b4:2d:88:7c:ed: + eb:63:34:bf:ef:d0:a8:e0:00:ea:f0:24:50:68:3b: + ff:03:4a:22:e0:eb:5c:a4:e8:65:e4:c7:e7:38:e9: + ce:0c:44:3e:36:08:fe:82:d8:50:b9:13:43:3b:17: + 77:09:ef:7b:cc:9f:b4:7d:5d:f7:ab:8e:ab:c0:11: + bc:7a:07:ea:98:51:c0:27:1f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 49:1F:9A:43:D9:43:B9:89:0C:00:D9:90:C8:BC:9C:67:CD:8D:3E:C6 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 2 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 03:bc:24:ba:71:8b:4f:cc:3a:60:5a:04:13:15:4e:b0:79:e7: + 94:6c:9b:3b:4c:5d:d8:26:75:f5:94:04:71:5a:3e:b9:8c:5f: + b5:3d:e0:bb:8b:64:71:8f:0d:9a:99:b8:ff:ec:14:c0:c0:ca: + 63:5a:4e:1d:75:77:7a:2f:fb:12:90:25:44:ba:d8:2f:03:39: + 86:ef:88:4a:cc:69:79:0b:ff:a6:66:83:45:08:17:0b:0c:05: + f9:25:7c:6a:30:05:b3:61:df:1a:fe:2c:ca:49:e9:73:bd:b3: + 11:6b:bf:04:b0:a6:46:76:21:40:95:5c:78:b3:aa:4b:fd:03: + ee:51 +-----BEGIN CERTIFICATE----- +MIICszCCAhygAwIBAgICEAIwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTgxNDQ0 +MTdaFw0zNTAxMTIxNDQ0MTdaMGUxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxFTATBgNVBAMeDAQPBBAEEQQSBBMEFDCBnzANBgkqhkiG9w0BAQEFAAOBjQAw +gYkCgYEAtNP9oFYr2XJm4/xLW3D7nCMQC7mKxNHdHTfNIPSdUsOPgBQmxD7cPa84 +hnAv4VQcpl62ai1ztC2IfO3rYzS/79Co4ADq8CRQaDv/A0oi4OtcpOhl5MfnOOnO +DEQ+Ngj+gthQuRNDOxd3Ce97zJ+0fV33q46rwBG8egfqmFHAJx8CAwEAAaN3MHUw +CwYDVR0PBAQDAgXgMB0GA1UdDgQWBBRJH5pD2UO5iQwA2ZDIvJxnzY0+xjAfBgNV +HSMEGDAWgBToarvCkOpscCI+9vZIGwPmvremVTAmBgNVHREEHzAdpBswGTEXMBUG +A1UEAxMOVXNlciAyIFJvb3QgMTEwDQYJKoZIhvcNAQEFBQADgYEAA7wkunGLT8w6 +YFoEExVOsHnnlGybO0xd2CZ19ZQEcVo+uYxftT3gu4tkcY8Nmpm4/+wUwMDKY1pO +HXV3ei/7EpAlRLrYLwM5hu+ISsxpeQv/pmaDRQgXCwwF+SV8ajAFs2HfGv4syknp +c72zEWu/BLCmRnYhQJVceLOqS/0D7lE= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1003.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1003.pem new file mode 100644 index 000000000..95589b227 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1003.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4099 (0x1003) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 18 15:39:42 2010 GMT + Not After : Jan 12 15:39:42 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x01y\x01z\x01{\x00 \x03\xA6\x03\xA7\x03\xA8\x03\xA9 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:d6:d8:62:3c:69:c9:dd:93:b3:e9:65:63:89:03: + 4e:f8:8a:e1:8b:9d:92:c6:43:ca:8e:af:fd:6e:9c: + c7:66:31:48:f4:ce:5e:be:38:c5:6c:1b:48:c9:61: + f5:78:8a:e9:74:ac:a8:98:9c:83:f9:b0:74:e3:25: + 7c:5a:bb:df:5f:73:ef:fc:a0:dc:6a:ac:07:a2:b8: + 52:ea:7a:42:ba:9f:74:3c:00:cc:26:46:ba:90:5d: + 45:78:02:57:e7:47:9f:8e:94:9c:5a:31:ab:f3:ff: + bc:9f:7f:d9:b0:a6:f6:86:70:a6:9d:52:ff:c8:19: + 47:88:75:78:6a:73:d5:97:e9 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + E3:01:F6:1E:51:6D:FC:DB:BF:82:A9:12:21:4B:E2:46:FF:E8:EE:FF + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 1 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 68:f0:88:18:d5:98:63:da:42:39:47:bf:51:22:f6:0b:8e:46: + b0:8c:83:b0:4d:07:a4:e3:a9:66:76:4d:41:23:1a:6b:dc:d8: + d1:85:b1:bf:4f:f9:e6:01:4a:36:a9:a3:26:2d:0b:33:cc:36: + 97:c6:40:b6:77:26:1c:06:f2:1b:fa:0a:ef:5c:61:8d:0d:9c: + 3c:d3:0f:db:dd:60:69:8c:24:c6:70:bc:f8:3b:38:19:90:7a: + f3:4f:7e:7c:b7:69:b6:0f:55:e1:4b:da:77:cd:b1:fe:5f:f1: + c1:8a:f8:3d:26:10:3d:40:6f:83:17:0a:d8:dd:da:a1:27:10: + a1:73 +-----BEGIN CERTIFICATE----- +MIICtzCCAiCgAwIBAgICEAMwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTgxNTM5 +NDJaFw0zNTAxMTIxNTM5NDJaMGkxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxGTAXBgNVBAMeEAF5AXoBewAgA6YDpwOoA6kwgZ8wDQYJKoZIhvcNAQEBBQAD +gY0AMIGJAoGBANbYYjxpyd2Ts+llY4kDTviK4YudksZDyo6v/W6cx2YxSPTOXr44 +xWwbSMlh9XiK6XSsqJicg/mwdOMlfFq7319z7/yg3GqsB6K4Uup6QrqfdDwAzCZG +upBdRXgCV+dHn46UnFoxq/P/vJ9/2bCm9oZwpp1S/8gZR4h1eGpz1ZfpAgMBAAGj +dzB1MAsGA1UdDwQEAwIF4DAdBgNVHQ4EFgQU4wH2HlFt/Nu/gqkSIUviRv/o7v8w +HwYDVR0jBBgwFoAU6Gq7wpDqbHAiPvb2SBsD5r63plUwJgYDVR0RBB8wHaQbMBkx +FzAVBgNVBAMTDlVzZXIgMSBSb290IDExMA0GCSqGSIb3DQEBBQUAA4GBAGjwiBjV +mGPaQjlHv1Ei9guORrCMg7BNB6TjqWZ2TUEjGmvc2NGFsb9P+eYBSjapoyYtCzPM +NpfGQLZ3JhwG8hv6Cu9cYY0NnDzTD9vdYGmMJMZwvPg7OBmQevNPfny3abYPVeFL +2nfNsf5f8cGK+D0mED1Ab4MXCtjd2qEnEKFz +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1004.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1004.pem new file mode 100644 index 000000000..6f57ca684 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1004.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4100 (0x1004) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 18 16:00:38 2010 GMT + Not After : Jan 12 16:00:38 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00"\x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00s\x00" + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:c9:ff:37:16:4d:7a:ad:59:bd:f2:c4:dc:4f:79: + 6a:f6:21:c7:ef:cd:af:f1:39:34:24:92:f4:46:d3: + 8b:43:31:55:11:3e:22:2b:85:19:38:ed:0b:35:3c: + 73:fc:b9:17:e8:73:99:21:a2:20:30:b4:e9:11:c6: + 7a:61:fa:fa:fe:eb:c8:30:c4:73:5f:77:f2:fc:42: + b7:10:29:ac:9e:8a:c2:df:25:9b:44:17:05:a3:39: + d9:1b:58:62:fb:2c:86:07:f7:f0:28:7b:5a:38:1b: + 6a:de:88:fb:ad:32:f4:53:e2:a1:c5:0f:68:db:64: + ae:39:2a:5e:02:d0:b5:38:07 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 86:2F:46:D0:A9:F9:3F:22:BD:57:83:51:35:F9:67:11:A2:00:AB:33 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 3 Root 11 + Signature Algorithm: sha1WithRSAEncryption + bb:f6:61:ae:30:94:3a:4a:d6:d5:cb:b5:50:bb:ca:0e:ab:9f: + 09:e9:78:d4:2f:20:fe:18:4e:d8:61:db:97:28:a9:d9:dc:e5: + 06:f8:6c:41:c2:5a:95:53:47:7e:a7:73:c9:45:4f:6b:30:fc: + fd:17:9a:7b:a9:d8:27:57:a9:fd:8d:e7:7e:4b:3e:98:11:42: + 00:39:1a:55:4b:3d:a5:de:75:3c:43:5a:33:10:d3:cf:4e:04: + 0a:71:d4:93:2b:0b:2b:15:82:7b:04:46:9b:50:da:18:84:66: + 31:75:36:5b:09:eb:82:5d:7d:e1:35:a3:a4:6c:b2:ac:c8:fa: + bd:5f +-----BEGIN CERTIFICATE----- +MIICyzCCAjSgAwIBAgICEAQwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTgxNjAw +MzhaFw0zNTAxMTIxNjAwMzhaMH0xCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxLTArBgNVBAMeJAAiAGUAbgBjAGwAbwBzAGkAbgBnACAAcQB1AG8AdABlAHMA +IjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAyf83Fk16rVm98sTcT3lq9iHH +782v8Tk0JJL0RtOLQzFVET4iK4UZOO0LNTxz/LkX6HOZIaIgMLTpEcZ6Yfr6/uvI +MMRzX3fy/EK3ECmsnorC3yWbRBcFoznZG1hi+yyGB/fwKHtaOBtq3oj7rTL0U+Kh +xQ9o22SuOSpeAtC1OAcCAwEAAaN3MHUwCwYDVR0PBAQDAgXgMB0GA1UdDgQWBBSG +L0bQqfk/Ir1Xg1E1+WcRogCrMzAfBgNVHSMEGDAWgBToarvCkOpscCI+9vZIGwPm +vremVTAmBgNVHREEHzAdpBswGTEXMBUGA1UEAxMOVXNlciAzIFJvb3QgMTEwDQYJ +KoZIhvcNAQEFBQADgYEAu/ZhrjCUOkrW1cu1ULvKDqufCel41C8g/hhO2GHblyip +2dzlBvhsQcJalVNHfqdzyUVPazD8/Reae6nYJ1ep/Y3nfks+mBFCADkaVUs9pd51 +PENaMxDTz04ECnHUkysLKxWCewRGm1DaGIRmMXU2Wwnrgl194TWjpGyyrMj6vV8= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1005.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1005.pem new file mode 100644 index 000000000..3a2f7522d --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1005.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4101 (0x1005) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 18 16:05:47 2010 GMT + Not After : Jan 12 16:05:47 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00"\x00"\x00d\x00o\x00u\x00b\x00l\x00e\x00 \x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00s\x00"\x00" + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:de:4d:31:93:c5:1b:7c:2b:85:86:da:89:3d:06: + 6f:6d:44:a5:de:6c:6a:06:28:b0:96:7b:40:34:01: + af:e4:b1:f4:93:f1:25:78:b0:43:ea:92:2a:87:60: + e8:be:7e:c9:b6:02:f8:14:93:1b:b8:5f:cb:2c:24: + e2:80:24:f0:5c:6d:77:f2:dc:ef:90:d6:d1:78:22: + 53:f0:7f:45:ad:f2:1a:9d:25:08:13:c8:62:6b:9e: + 88:79:3d:9e:b4:0a:05:11:79:7d:a1:b2:46:89:f3: + 45:ce:f3:22:2e:17:ab:e1:a9:b1:04:93:3b:f3:ca: + e6:60:c0:fd:91:7f:34:80:65 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + C1:6E:6A:FB:5A:B1:0C:67:07:C8:7E:F1:8D:86:F6:D0:27:56:6D:73 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 4 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 61:72:4b:33:1d:60:91:08:19:4f:ff:ec:8e:9e:83:71:d7:00: + 96:0a:b5:82:b7:8c:a6:3f:70:64:36:ac:25:a7:f1:a9:83:f1: + 63:f8:29:06:fa:58:86:8a:fd:25:9e:77:38:dd:c7:3b:cd:68: + 91:8e:f4:57:42:c9:6b:88:87:ec:24:57:38:84:fb:c0:d9:bc: + 6c:1c:6e:9d:9d:b9:da:cc:7e:fe:f9:bd:29:be:14:26:6f:63: + 1f:6f:6a:f1:dd:fd:d2:03:69:f2:36:e1:35:e0:57:72:d5:e3: + 09:ee:6a:08:45:b4:73:e9:d1:18:c2:38:1d:86:53:53:6d:bf: + f0:1e +-----BEGIN CERTIFICATE----- +MIIC3jCCAkegAwIBAgICEAUwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTgxNjA1 +NDdaFw0zNTAxMTIxNjA1NDdaMIGPMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MT8wPQYDVQQDHjYAIgAiAGQAbwB1AGIAbABlACAAZQBuAGMAbABvAHMAaQBu +AGcAIABxAHUAbwB0AGUAcwAiACIwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB +AN5NMZPFG3wrhYbaiT0Gb21Epd5sagYosJZ7QDQBr+Sx9JPxJXiwQ+qSKodg6L5+ +ybYC+BSTG7hfyywk4oAk8Fxtd/Lc75DW0XgiU/B/Ra3yGp0lCBPIYmueiHk9nrQK +BRF5faGyRonzRc7zIi4Xq+GpsQSTO/PK5mDA/ZF/NIBlAgMBAAGjdzB1MAsGA1Ud +DwQEAwIF4DAdBgNVHQ4EFgQUwW5q+1qxDGcHyH7xjYb20CdWbXMwHwYDVR0jBBgw +FoAU6Gq7wpDqbHAiPvb2SBsD5r63plUwJgYDVR0RBB8wHaQbMBkxFzAVBgNVBAMT +DlVzZXIgNCBSb290IDExMA0GCSqGSIb3DQEBBQUAA4GBAGFySzMdYJEIGU//7I6e +g3HXAJYKtYK3jKY/cGQ2rCWn8amD8WP4KQb6WIaK/SWedzjdxzvNaJGO9FdCyWuI +h+wkVziE+8DZvGwcbp2dudrMfv75vSm+FCZvYx9vavHd/dIDafI24TXgV3LV4wnu +aghFtHPp0RjCOB2GU1Ntv/Ae +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1006.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1006.pem new file mode 100644 index 000000000..cb72b8d16 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1006.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4102 (0x1006) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 18 16:09:21 2010 GMT + Not After : Jan 12 16:09:21 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00"\x00"\x00t\x00w\x00o\x00 \x00s\x00t\x00a\x00r\x00t\x00i\x00n\x00g\x00 \x00o\x00n\x00e\x00 \x00e\x00n\x00d\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00" + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:d1:a4:91:c7:28:84:f8:54:63:09:1f:bc:2e:4e: + a3:be:54:01:42:2e:f7:ef:4f:b8:46:a9:35:b1:b3: + 29:0e:8b:f7:b5:fa:b7:71:5b:33:03:ac:e6:b5:f6: + ba:f5:ba:21:72:ed:7d:ea:f0:f1:2c:55:2a:a9:c6: + d8:54:ef:12:f0:f5:37:ca:57:b2:3c:ce:7c:5a:57: + 86:68:a2:51:82:80:bd:58:a5:04:1c:e8:cf:f6:5b: + 4e:d2:6a:79:63:eb:ac:52:7c:61:8c:fe:0a:6b:b2: + f6:16:9c:94:ae:a6:f6:69:b9:d5:0b:26:0d:01:7f: + 62:d2:58:c2:02:53:25:63:0d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 45:DF:D7:35:D1:13:E4:8F:E3:0D:E3:7E:A9:9A:5D:56:00:64:4E:43 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 5 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 9d:bd:dc:dc:8e:a8:e8:e4:15:cb:14:c1:6a:ab:d8:ab:e6:e5: + 4f:f5:a8:8b:2c:ab:80:e2:31:f9:89:d8:12:ba:9c:4f:b3:f5: + bb:7e:ee:8b:df:58:d3:b2:ee:f8:c5:46:c3:5d:2e:a9:35:d0: + 7a:1e:80:18:14:4d:78:6e:f1:c8:9a:51:db:86:3e:2c:04:4a: + 0a:2f:f1:7a:01:e3:1b:31:d7:1d:f1:32:c4:04:db:b9:7e:c4: + fd:b0:c1:41:3f:8a:b3:88:4f:4a:9c:a6:38:11:2a:4a:0f:8b: + d0:9a:8a:2c:33:fe:7f:42:b5:93:8d:54:df:de:2b:b1:08:5c: + d9:0d +-----BEGIN CERTIFICATE----- +MIIC6DCCAlGgAwIBAgICEAYwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTgxNjA5 +MjFaFw0zNTAxMTIxNjA5MjFaMIGZMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MUkwRwYDVQQDHkAAIgAiAHQAdwBvACAAcwB0AGEAcgB0AGkAbgBnACAAbwBu +AGUAIABlAG4AZABpAG4AZwAgAHEAdQBvAHQAZQAiMIGfMA0GCSqGSIb3DQEBAQUA +A4GNADCBiQKBgQDRpJHHKIT4VGMJH7wuTqO+VAFCLvfvT7hGqTWxsykOi/e1+rdx +WzMDrOa19rr1uiFy7X3q8PEsVSqpxthU7xLw9TfKV7I8znxaV4ZoolGCgL1YpQQc +6M/2W07Sanlj66xSfGGM/gprsvYWnJSupvZpudULJg0Bf2LSWMICUyVjDQIDAQAB +o3cwdTALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFEXf1zXRE+SP4w3jfqmaXVYAZE5D +MB8GA1UdIwQYMBaAFOhqu8KQ6mxwIj729kgbA+a+t6ZVMCYGA1UdEQQfMB2kGzAZ +MRcwFQYDVQQDEw5Vc2VyIDUgUm9vdCAxMTANBgkqhkiG9w0BAQUFAAOBgQCdvdzc +jqjo5BXLFMFqq9ir5uVP9aiLLKuA4jH5idgSupxPs/W7fu6L31jTsu74xUbDXS6p +NdB6HoAYFE14bvHImlHbhj4sBEoKL/F6AeMbMdcd8TLEBNu5fsT9sMFBP4qziE9K +nKY4ESpKD4vQmoosM/5/QrWTjVTf3iuxCFzZDQ== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1007.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1007.pem new file mode 100644 index 000000000..ce9b36d12 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1007.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4103 (0x1007) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 18 16:11:53 2010 GMT + Not After : Jan 12 16:11:53 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00"\x00s\x00t\x00a\x00r\x00t\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:d1:99:9c:20:2e:65:ee:0f:ce:cb:8a:d8:70:c8: + 04:3c:ac:2f:14:7c:6c:8f:5e:95:36:f8:53:74:5b: + 88:bf:a1:43:73:04:ab:3a:42:b4:7c:2c:3c:3b:63: + 7e:ef:82:c5:bb:b1:28:9b:8b:b7:29:72:3d:30:08: + e9:a2:d7:4b:08:e2:2e:e6:d4:9f:75:29:31:23:be: + b4:30:5d:94:30:41:38:a1:d5:34:bc:69:f5:d8:8d: + c6:08:cc:28:4a:92:22:2b:19:89:f5:ad:7c:49:89: + b3:63:c6:e5:6c:86:d7:62:05:1b:97:db:2d:fb:c2: + 47:e5:51:a6:f0:50:6f:e3:53 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 5F:DA:34:F6:6F:BA:9E:12:99:DC:02:2A:4C:3E:8C:0D:14:A1:9B:2B + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 6 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 24:af:11:b6:1a:5c:d1:bf:70:93:85:c0:2e:10:96:4d:b7:ad: + 4e:d7:c4:7e:87:a1:3b:20:d7:bf:04:07:cc:91:13:0c:ad:66: + 08:d6:2e:b6:d0:aa:d0:45:0e:c0:92:3d:7c:a6:82:19:04:3c: + 9a:b3:5e:e8:fe:9e:5c:d6:17:75:73:e3:3c:64:0c:ae:5d:92: + 2a:eb:0e:ef:04:f5:ce:a5:7f:1f:2f:1d:05:a0:70:f4:24:80: + c3:38:35:2d:e5:ac:a7:11:4a:3e:a2:b2:d1:14:91:ba:b0:d8: + 5f:be:80:8a:34:2c:72:fb:00:47:88:47:9e:34:65:12:ad:9f: + ff:99 +-----BEGIN CERTIFICATE----- +MIICxTCCAi6gAwIBAgICEAcwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTgxNjEx +NTNaFw0zNTAxMTIxNjExNTNaMHcxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxJzAlBgNVBAMeHgAiAHMAdABhAHIAdABpAG4AZwAgAHEAdQBvAHQAZTCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0ZmcIC5l7g/Oy4rYcMgEPKwvFHxsj16V +NvhTdFuIv6FDcwSrOkK0fCw8O2N+74LFu7Eom4u3KXI9MAjpotdLCOIu5tSfdSkx +I760MF2UMEE4odU0vGn12I3GCMwoSpIiKxmJ9a18SYmzY8blbIbXYgUbl9st+8JH +5VGm8FBv41MCAwEAAaN3MHUwCwYDVR0PBAQDAgXgMB0GA1UdDgQWBBRf2jT2b7qe +EpncAipMPowNFKGbKzAfBgNVHSMEGDAWgBToarvCkOpscCI+9vZIGwPmvremVTAm +BgNVHREEHzAdpBswGTEXMBUGA1UEAxMOVXNlciA2IFJvb3QgMTEwDQYJKoZIhvcN +AQEFBQADgYEAJK8Rthpc0b9wk4XALhCWTbetTtfEfoehOyDXvwQHzJETDK1mCNYu +ttCq0EUOwJI9fKaCGQQ8mrNe6P6eXNYXdXPjPGQMrl2SKusO7wT1zqV/Hy8dBaBw +9CSAwzg1LeWspxFKPqKy0RSRurDYX76AijQscvsAR4hHnjRlEq2f/5k= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1008.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1008.pem new file mode 100644 index 000000000..8d6f2bd25 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1008.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4104 (0x1008) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 18 16:14:05 2010 GMT + Not After : Jan 12 16:14:05 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00e\x00n\x00d\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00" + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:a6:a8:3f:60:a7:9a:3b:20:c9:2c:8c:4f:cd:11: + 1f:0d:a9:2a:2c:eb:12:80:0c:55:8a:4d:06:ef:b2: + 5f:2e:47:be:0d:10:22:8a:15:57:29:4a:90:63:f9: + 1c:13:85:47:c7:c9:b9:76:09:10:a9:b1:94:5c:8d: + c9:f4:01:26:43:e4:d4:98:d6:00:1a:d4:cd:2a:d1: + cd:7e:4c:4e:ab:18:78:5a:fb:b2:ec:a3:87:a1:0e: + 84:3f:70:cf:ca:02:24:c8:d7:1b:83:a3:ac:a5:f0: + 10:c5:de:b7:a2:6c:0b:0c:9d:ab:32:a3:1a:c9:ae: + 9b:48:a8:65:cd:50:db:0b:cf + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 91:32:56:26:62:63:A1:32:B0:BC:D0:91:F1:D8:F2:94:CB:10:F1:91 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 7 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 4c:d5:2f:ab:fb:83:f8:11:c9:d2:df:aa:dc:e9:b8:38:2e:53: + e1:3a:5b:bb:0a:bf:72:f7:47:b5:57:de:82:8a:e6:bb:7d:62: + af:1b:9c:8e:4a:f5:cf:0b:ac:e9:06:16:ca:59:f1:7f:d7:45: + c0:88:84:ee:f4:c7:8b:e0:39:aa:c7:b7:95:b9:fe:a2:4a:3a: + 41:df:d0:02:bf:6f:54:30:9a:9a:0a:a6:04:5f:f4:17:52:d6: + c2:39:43:5e:b9:a3:86:0f:3d:ad:eb:a3:81:f4:cc:90:29:17: + dc:46:5e:6b:9c:f6:70:0f:b2:0f:dc:0f:9c:9f:09:6c:fa:31: + 6c:01 +-----BEGIN CERTIFICATE----- +MIICwTCCAiqgAwIBAgICEAgwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTgxNjE0 +MDVaFw0zNTAxMTIxNjE0MDVaMHMxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxIzAhBgNVBAMeGgBlAG4AZABpAG4AZwAgAHEAdQBvAHQAZQAiMIGfMA0GCSqG +SIb3DQEBAQUAA4GNADCBiQKBgQCmqD9gp5o7IMksjE/NER8NqSos6xKADFWKTQbv +sl8uR74NECKKFVcpSpBj+RwThUfHybl2CRCpsZRcjcn0ASZD5NSY1gAa1M0q0c1+ +TE6rGHha+7Lso4ehDoQ/cM/KAiTI1xuDo6yl8BDF3reibAsMnasyoxrJrptIqGXN +UNsLzwIDAQABo3cwdTALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFJEyViZiY6EysLzQ +kfHY8pTLEPGRMB8GA1UdIwQYMBaAFOhqu8KQ6mxwIj729kgbA+a+t6ZVMCYGA1Ud +EQQfMB2kGzAZMRcwFQYDVQQDEw5Vc2VyIDcgUm9vdCAxMTANBgkqhkiG9w0BAQUF +AAOBgQBM1S+r+4P4EcnS36rc6bg4LlPhOlu7Cr9y90e1V96Ciua7fWKvG5yOSvXP +C6zpBhbKWfF/10XAiITu9MeL4Dmqx7eVuf6iSjpB39ACv29UMJqaCqYEX/QXUtbC +OUNeuaOGDz2t66OB9MyQKRfcRl5rnPZwD7IP3A+cnwls+jFsAQ== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1009.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1009.pem new file mode 100644 index 000000000..c1a94dae5 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1009.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4105 (0x1009) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 18 16:16:31 2010 GMT + Not After : Jan 12 16:16:31 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00"\x00q\x00u\x00o\x00t\x00e + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:b4:3b:c7:b0:6c:b5:f2:b3:a5:79:89:54:de:af: + 03:3c:0e:c9:57:15:8e:73:2a:48:83:18:59:ce:b4: + 12:fb:5c:92:28:69:75:18:f9:0f:24:15:95:38:b2: + 4c:81:07:90:97:3b:d7:3a:ab:a6:92:5a:9f:5a:1f: + fe:14:ac:4d:b5:5e:6a:a6:0f:98:55:08:07:09:07: + a5:fb:79:9e:a0:2d:73:99:92:ad:6e:bc:75:36:d0: + b5:f1:1c:91:3a:d4:49:8a:60:1e:a7:01:2f:bc:d9: + cd:b4:f4:70:b4:38:d1:3c:d3:ee:00:df:b3:83:45: + 63:5c:5d:28:47:bc:b1:b9:57 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + D6:18:38:7B:14:4B:D6:72:42:A9:53:E2:1D:BE:81:88:26:DB:0A:06 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 8 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 98:f3:ac:db:7b:a0:00:d2:58:be:74:21:ff:09:29:4c:0c:1a: + 7a:1f:dd:e2:f3:f4:9a:52:5d:da:ac:10:30:f9:b8:93:10:60: + 46:bf:48:47:bd:af:87:a1:d9:c6:46:81:b3:0d:a4:f8:ba:ca: + 17:7c:f2:f9:46:03:62:7f:32:6b:f0:7c:75:a4:05:44:cb:10: + 42:36:ce:12:c0:b9:e5:5f:e0:7b:c6:c8:39:5c:0c:50:30:a0: + f6:fe:e1:a2:e6:00:b3:fc:86:56:11:66:d8:41:81:e3:4e:15: + e5:68:9d:1c:b0:c4:4f:ab:86:75:55:fa:39:58:3f:7c:68:03: + e0:76 +-----BEGIN CERTIFICATE----- +MIICwTCCAiqgAwIBAgICEAkwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTgxNjE2 +MzFaFw0zNTAxMTIxNjE2MzFaMHMxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxIzAhBgNVBAMeGgBtAGkAZABkAGwAZQAgACIAcQB1AG8AdABlMIGfMA0GCSqG +SIb3DQEBAQUAA4GNADCBiQKBgQC0O8ewbLXys6V5iVTerwM8DslXFY5zKkiDGFnO +tBL7XJIoaXUY+Q8kFZU4skyBB5CXO9c6q6aSWp9aH/4UrE21XmqmD5hVCAcJB6X7 +eZ6gLXOZkq1uvHU20LXxHJE61EmKYB6nAS+82c209HC0ONE80+4A37ODRWNcXShH +vLG5VwIDAQABo3cwdTALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFNYYOHsUS9ZyQqlT +4h2+gYgm2woGMB8GA1UdIwQYMBaAFOhqu8KQ6mxwIj729kgbA+a+t6ZVMCYGA1Ud +EQQfMB2kGzAZMRcwFQYDVQQDEw5Vc2VyIDggUm9vdCAxMTANBgkqhkiG9w0BAQUF +AAOBgQCY86zbe6AA0li+dCH/CSlMDBp6H93i8/SaUl3arBAw+biTEGBGv0hHva+H +odnGRoGzDaT4usoXfPL5RgNifzJr8Hx1pAVEyxBCNs4SwLnlX+B7xsg5XAxQMKD2 +/uGi5gCz/IZWEWbYQYHjThXlaJ0csMRPq4Z1Vfo5WD98aAPgdg== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100A.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100A.pem new file mode 100644 index 000000000..a3a79bf83 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100A.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4106 (0x100a) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 18 16:18:57 2010 GMT + Not After : Jan 12 16:18:57 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00d\x00o\x00u\x00b\x00l\x00e\x00 \x00"\x00"\x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00q\x00u\x00o\x00t\x00e + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:e5:3f:d4:e1:d6:26:2a:c9:40:1d:34:3c:1e:e8: + f4:54:67:6b:6c:a5:b7:fe:04:bb:cb:0e:c0:2d:26: + 61:c1:81:80:9d:da:1b:fd:d3:7a:7a:57:78:c5:f6: + e6:4b:ad:2d:a2:8d:49:b3:ac:18:ca:1c:25:67:44: + 7c:8e:b5:ab:ec:f7:a8:da:b7:37:ed:77:76:b2:8f: + bb:15:b2:e3:45:5f:b2:2a:aa:27:b7:f1:bc:37:8f: + b7:b4:c5:ff:45:fd:67:04:25:47:2c:1a:a7:63:1e: + 97:f6:ac:d7:39:cf:ef:24:63:a1:87:9b:36:97:92: + fa:d9:4d:a9:fa:dd:c9:fb:75 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 62:F1:43:E3:B1:7B:98:0D:69:A4:8F:CF:32:F7:6D:E6:88:D6:23:90 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 9 Root 11 + Signature Algorithm: sha1WithRSAEncryption + ab:46:88:13:e8:02:63:4e:f2:a0:5a:48:7e:35:a4:c2:f8:55: + 33:cb:ef:45:55:30:81:a1:9e:c2:c7:43:cd:19:23:1f:df:3f: + 8b:b8:7e:69:5e:98:06:b1:47:dd:e5:05:e2:3a:19:cf:af:e3: + dd:7b:75:e5:53:b0:bc:4e:58:40:bf:3b:d2:9c:7f:9e:b1:66: + f8:3f:58:c4:5f:ab:be:1f:03:fb:89:47:a4:25:8a:1e:10:e0: + 20:33:70:07:13:92:32:e1:bf:92:6a:d5:89:03:2c:ad:e1:85: + 8c:b3:1d:ee:0c:35:70:2f:aa:e5:e0:77:97:b0:9b:a3:0d:22: + 6f:dc +-----BEGIN CERTIFICATE----- +MIIC0jCCAjugAwIBAgICEAowDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTgxNjE4 +NTdaFw0zNTAxMTIxNjE4NTdaMIGDMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MTMwMQYDVQQDHioAZABvAHUAYgBsAGUAIAAiACIAbQBpAGQAZABsAGUAIABx +AHUAbwB0AGUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOU/1OHWJirJQB00 +PB7o9FRna2ylt/4Eu8sOwC0mYcGBgJ3aG/3TenpXeMX25kutLaKNSbOsGMocJWdE +fI61q+z3qNq3N+13drKPuxWy40VfsiqqJ7fxvDePt7TF/0X9ZwQlRywap2Mel/as +1znP7yRjoYebNpeS+tlNqfrdyft1AgMBAAGjdzB1MAsGA1UdDwQEAwIF4DAdBgNV +HQ4EFgQUYvFD47F7mA1ppI/PMvdt5ojWI5AwHwYDVR0jBBgwFoAU6Gq7wpDqbHAi +Pvb2SBsD5r63plUwJgYDVR0RBB8wHaQbMBkxFzAVBgNVBAMTDlVzZXIgOSBSb290 +IDExMA0GCSqGSIb3DQEBBQUAA4GBAKtGiBPoAmNO8qBaSH41pML4VTPL70VVMIGh +nsLHQ80ZIx/fP4u4fmlemAaxR93lBeI6Gc+v4917deVTsLxOWEC/O9Kcf56xZvg/ +WMRfq74fA/uJR6Qlih4Q4CAzcAcTkjLhv5Jq1YkDLK3hhYyzHe4MNXAvquXgd5ew +m6MNIm/c +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100B.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100B.pem new file mode 100644 index 000000000..75684732d --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100B.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4107 (0x100b) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 09:02:37 2010 GMT + Not After : Jan 13 09:02:37 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00p\x00a\x00r\x00t\x00i\x00a\x00l\x00l\x00y\x00 \x00"\x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00" + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:ae:9f:8e:b8:88:8e:ed:53:aa:2a:2c:ed:f1:6c: + 99:47:9f:ab:8b:4e:8e:d8:2e:c2:78:2c:54:f9:29: + 14:27:b9:6a:3c:33:3f:06:51:ba:76:15:0a:16:60: + db:f2:f0:db:af:5b:38:be:18:42:b4:31:02:ba:6f: + 19:00:57:be:d0:f3:7c:6b:34:36:e8:7c:45:77:0d: + f5:d0:7c:0e:23:64:7c:59:02:5c:54:15:71:82:be: + 98:3f:c9:2d:f0:9e:d5:f0:32:02:44:61:5b:2f:71: + 16:13:9a:b3:2b:28:ff:d5:d8:3d:00:9c:eb:ec:b7: + 04:e2:b6:15:42:45:e5:ef:3f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 8C:2C:B6:8B:82:43:DC:41:EC:AC:D4:75:E8:DA:D8:3F:A9:A0:F5:31 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 10 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 48:a6:51:46:5b:44:a5:be:18:ed:8f:d4:c6:d2:3c:86:8f:e7: + e5:f4:a2:5d:51:aa:00:9b:bc:d8:b1:d3:f4:24:a0:a1:0d:80: + 2e:7e:62:26:ee:8c:4b:bd:79:0c:39:bd:6e:af:db:92:b6:03: + b1:b0:49:95:a7:59:28:54:30:33:fc:7e:2f:0f:a2:ce:90:27: + 29:b9:d8:3f:99:36:e9:81:9f:f5:fa:cb:f9:f2:05:b5:48:60: + 4d:50:4d:1e:ba:45:fd:f1:99:84:a6:79:0b:6b:76:eb:73:9d: + 5c:47:27:be:0d:23:0b:97:cc:9d:5a:80:fa:9b:ff:66:e7:37: + 60:a4 +-----BEGIN CERTIFICATE----- +MIIC3zCCAkigAwIBAgICEAswDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkwOTAy +MzdaFw0zNTAxMTMwOTAyMzdaMIGPMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MT8wPQYDVQQDHjYAcABhAHIAdABpAGEAbABsAHkAIAAiAGUAbgBjAGwAbwBz +AGkAbgBnACAAcQB1AG8AdABlACIwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB +AK6fjriIju1Tqios7fFsmUefq4tOjtguwngsVPkpFCe5ajwzPwZRunYVChZg2/Lw +269bOL4YQrQxArpvGQBXvtDzfGs0Nuh8RXcN9dB8DiNkfFkCXFQVcYK+mD/JLfCe +1fAyAkRhWy9xFhOasyso/9XYPQCc6+y3BOK2FUJF5e8/AgMBAAGjeDB2MAsGA1Ud +DwQEAwIF4DAdBgNVHQ4EFgQUjCy2i4JD3EHsrNR16NrYP6mg9TEwHwYDVR0jBBgw +FoAU6Gq7wpDqbHAiPvb2SBsD5r63plUwJwYDVR0RBCAwHqQcMBoxGDAWBgNVBAMT +D1VzZXIgMTAgUm9vdCAxMTANBgkqhkiG9w0BAQUFAAOBgQBIplFGW0Slvhjtj9TG +0jyGj+fl9KJdUaoAm7zYsdP0JKChDYAufmIm7oxLvXkMOb1ur9uStgOxsEmVp1ko +VDAz/H4vD6LOkCcpudg/mTbpgZ/1+sv58gW1SGBNUE0eukX98ZmEpnkLa3brc51c +Rye+DSMLl8ydWoD6m/9m5zdgpA== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100C.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100C.pem new file mode 100644 index 000000000..115190ca6 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100C.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4108 (0x100c) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 09:48:52 2010 GMT + Not After : Jan 13 09:48:52 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00"\x00U\x00s\x00e\x00r\x00 \x001\x001\x00,\x00 \x00s\x00t\x00a\x00r\x00t\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:e2:8b:a9:94:06:b0:cb:e7:1b:a3:fd:7c:70:d1: + 66:e6:2d:aa:c7:ec:2e:e3:08:c3:39:3f:48:47:fd: + 09:67:2d:16:17:87:c0:e3:4d:c1:cc:6b:3f:c4:7b: + 74:d5:71:70:d6:74:8a:a2:17:fd:39:78:f8:c7:b3: + 42:54:ac:f7:07:d7:6f:55:da:03:15:11:e0:c2:d8: + 95:d2:87:c3:9c:3d:94:96:9d:01:81:5d:61:43:aa: + 4c:92:d5:68:aa:6c:73:88:52:7b:ee:9b:76:65:0d: + 2a:ae:3d:83:71:41:44:8b:23:7d:a6:f9:3c:81:56: + 6c:9b:52:96:87:c8:97:18:8d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 48:89:BE:3C:AA:C9:5A:38:6B:CA:FA:C8:B2:BB:F7:E1:44:4B:7B:08 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 11 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 23:c9:5b:f5:9f:59:ff:97:0b:79:35:2d:32:db:b7:4b:b1:c9: + 2b:1e:cf:88:7b:b4:4e:f0:ed:13:a3:64:85:8f:d6:70:b5:ed: + 2a:57:92:a0:b4:14:96:48:7a:aa:a4:19:59:df:d9:a9:0f:86: + a3:e5:ec:b5:67:ef:c3:ee:23:dd:c3:3e:24:86:6c:09:03:59: + ab:93:d6:c7:0a:4c:ef:c5:4a:be:d6:ff:0f:2e:81:8e:18:d5: + 44:21:3a:0e:86:04:aa:86:8a:38:1e:d6:07:75:d0:08:be:ef: + 29:7d:d2:fc:85:8d:0c:d3:bd:ea:47:be:40:bb:fa:2f:29:fc: + c6:d8 +-----BEGIN CERTIFICATE----- +MIIC2TCCAkKgAwIBAgICEAwwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkwOTQ4 +NTJaFw0zNTAxMTMwOTQ4NTJaMIGJMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MTkwNwYDVQQDHjAAIgBVAHMAZQByACAAMQAxACwAIABzAHQAYQByAHQAaQBu +AGcAIABxAHUAbwB0AGUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOKLqZQG +sMvnG6P9fHDRZuYtqsfsLuMIwzk/SEf9CWctFheHwONNwcxrP8R7dNVxcNZ0iqIX +/Tl4+MezQlSs9wfXb1XaAxUR4MLYldKHw5w9lJadAYFdYUOqTJLVaKpsc4hSe+6b +dmUNKq49g3FBRIsjfab5PIFWbJtSlofIlxiNAgMBAAGjeDB2MAsGA1UdDwQEAwIF +4DAdBgNVHQ4EFgQUSIm+PKrJWjhryvrIsrv34URLewgwHwYDVR0jBBgwFoAU6Gq7 +wpDqbHAiPvb2SBsD5r63plUwJwYDVR0RBCAwHqQcMBoxGDAWBgNVBAMTD1VzZXIg +MTEgUm9vdCAxMTANBgkqhkiG9w0BAQUFAAOBgQAjyVv1n1n/lwt5NS0y27dLsckr +Hs+Ie7RO8O0To2SFj9Zwte0qV5KgtBSWSHqqpBlZ39mpD4aj5ey1Z+/D7iPdwz4k +hmwJA1mrk9bHCkzvxUq+1v8PLoGOGNVEIToOhgSqhoo4HtYHddAIvu8pfdL8hY0M +073qR75Au/ovKfzG2A== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100D.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100D.pem new file mode 100644 index 000000000..95e419a17 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100D.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4109 (0x100d) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 09:51:10 2010 GMT + Not After : Jan 13 09:51:10 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00U\x00s\x00e\x00r\x00 \x001\x002\x00,\x00 \x00e\x00n\x00d\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00" + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:bf:4f:93:6b:6b:86:76:30:31:3b:0e:eb:b7:a6: + b9:a3:3e:84:ea:d5:31:50:5a:df:f4:3f:67:11:5a: + a5:28:23:58:37:67:a5:5c:72:6d:f2:fc:80:81:55: + 78:86:28:e9:60:c2:0a:d0:17:3c:3a:e9:a8:01:71: + 64:b8:27:f4:42:e0:d7:69:f5:4e:ef:14:07:69:fd: + de:7b:af:c8:a4:0c:9c:56:00:8b:76:67:d1:ba:a9: + e7:40:63:77:da:44:d3:89:5c:a7:5a:ea:d5:f3:9b: + 15:43:f3:08:2d:bc:8a:bf:4a:5b:57:01:f0:c7:97: + fe:b0:93:b2:1b:79:a0:4e:ad + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 0A:A2:A6:09:88:23:56:82:9E:60:8B:79:23:61:CA:BF:D4:F7:ED:A9 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 12 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 64:3e:b6:a6:5e:0d:6f:b3:e7:f6:c7:1f:4a:48:96:4c:fe:13: + 3c:4a:7b:e7:46:51:56:45:66:02:e4:79:1a:7f:15:a4:e9:5b: + f7:4c:68:cf:cf:b0:7b:e2:ba:57:37:23:c6:cd:ba:75:85:e8: + eb:d5:ca:a2:6d:9a:75:84:4b:7b:47:38:58:bc:0a:4b:cc:2c: + 2a:0d:eb:7e:ac:36:6f:0b:a5:26:b7:d3:0b:0f:e7:cc:26:db: + bb:01:48:5b:38:49:f5:3e:2d:75:c0:d6:11:ad:3e:a0:b6:8a: + 8e:7f:4d:10:2c:7b:d7:03:0d:de:da:6b:e0:07:06:90:73:1f: + dd:f1 +-----BEGIN CERTIFICATE----- +MIIC1TCCAj6gAwIBAgICEA0wDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkwOTUx +MTBaFw0zNTAxMTMwOTUxMTBaMIGFMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MTUwMwYDVQQDHiwAVQBzAGUAcgAgADEAMgAsACAAZQBuAGQAaQBuAGcAIABx +AHUAbwB0AGUAIjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAv0+Ta2uGdjAx +Ow7rt6a5oz6E6tUxUFrf9D9nEVqlKCNYN2elXHJt8vyAgVV4hijpYMIK0Bc8Oumo +AXFkuCf0QuDXafVO7xQHaf3ee6/IpAycVgCLdmfRuqnnQGN32kTTiVynWurV85sV +Q/MILbyKv0pbVwHwx5f+sJOyG3mgTq0CAwEAAaN4MHYwCwYDVR0PBAQDAgXgMB0G +A1UdDgQWBBQKoqYJiCNWgp5gi3kjYcq/1PftqTAfBgNVHSMEGDAWgBToarvCkOps +cCI+9vZIGwPmvremVTAnBgNVHREEIDAepBwwGjEYMBYGA1UEAxMPVXNlciAxMiBS +b290IDExMA0GCSqGSIb3DQEBBQUAA4GBAGQ+tqZeDW+z5/bHH0pIlkz+EzxKe+dG +UVZFZgLkeRp/FaTpW/dMaM/PsHviulc3I8bNunWF6OvVyqJtmnWES3tHOFi8CkvM +LCoN636sNm8LpSa30wsP58wm27sBSFs4SfU+LXXA1hGtPqC2io5/TRAse9cDDd7a +a+AHBpBzH93x +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100E.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100E.pem new file mode 100644 index 000000000..f91766a0a --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100E.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4110 (0x100e) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 09:53:08 2010 GMT + Not After : Jan 13 09:53:08 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00"\x00U\x00s\x00e\x00r\x00 \x001\x003\x00,\x00 \x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00s\x00" + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:e0:b2:b3:77:34:32:23:3c:45:ce:1f:5f:9a:60: + c5:59:af:2f:bf:73:8e:be:3d:88:8d:97:4f:fe:8a: + 00:b9:71:7f:07:3a:1e:6a:5b:37:8a:ff:58:8f:f1: + b3:e5:0b:9d:35:58:57:6d:da:d1:15:cd:52:7f:e2: + 15:25:16:d4:d6:1e:71:a6:f3:f7:c5:6d:01:64:fc: + 20:d4:4e:6a:f2:f9:b9:2a:36:f8:ae:e6:17:a8:f9: + 8e:7c:bb:75:e5:24:39:ad:4c:18:c8:bb:07:22:cd: + d1:a6:52:93:7f:24:5f:90:dd:0f:64:07:70:42:67: + 39:9b:1f:ea:5e:bb:cd:df:ab + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 75:49:D0:1F:A0:B3:A2:C6:F2:7F:CF:16:A3:4C:4B:DF:D6:4C:07:9D + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 13 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 5d:60:60:06:aa:8a:2d:ee:20:2a:ee:fb:b5:99:8c:ed:d8:67: + 28:30:d8:26:a7:e0:1c:6e:5d:e1:4c:5e:c8:f9:02:e2:2e:c4: + 1e:58:e9:84:bc:d7:79:4e:d5:c5:ea:ba:74:aa:4e:30:9d:2b: + 98:c8:0b:fe:7f:eb:fb:e9:24:5f:f8:17:27:a9:ce:7c:ff:4b: + 88:15:3e:25:18:71:73:bf:b6:bf:c5:51:6b:1d:db:32:1d:ae: + 00:bf:ed:a5:65:99:16:43:8d:d2:6d:27:53:fc:65:9a:91:94: + 7b:44:c8:58:a1:f1:2b:95:86:0b:2d:2d:94:10:6f:5e:be:f8: + 7b:8e +-----BEGIN CERTIFICATE----- +MIIC3zCCAkigAwIBAgICEA4wDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkwOTUz +MDhaFw0zNTAxMTMwOTUzMDhaMIGPMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MT8wPQYDVQQDHjYAIgBVAHMAZQByACAAMQAzACwAIABlAG4AYwBsAG8AcwBp +AG4AZwAgAHEAdQBvAHQAZQBzACIwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB +AOCys3c0MiM8Rc4fX5pgxVmvL79zjr49iI2XT/6KALlxfwc6HmpbN4r/WI/xs+UL +nTVYV23a0RXNUn/iFSUW1NYecabz98VtAWT8INROavL5uSo2+K7mF6j5jny7deUk +Oa1MGMi7ByLN0aZSk38kX5DdD2QHcEJnOZsf6l67zd+rAgMBAAGjeDB2MAsGA1Ud +DwQEAwIF4DAdBgNVHQ4EFgQUdUnQH6Czosbyf88Wo0xL39ZMB50wHwYDVR0jBBgw +FoAU6Gq7wpDqbHAiPvb2SBsD5r63plUwJwYDVR0RBCAwHqQcMBoxGDAWBgNVBAMT +D1VzZXIgMTMgUm9vdCAxMTANBgkqhkiG9w0BAQUFAAOBgQBdYGAGqoot7iAq7vu1 +mYzt2GcoMNgmp+Acbl3hTF7I+QLiLsQeWOmEvNd5TtXF6rp0qk4wnSuYyAv+f+v7 +6SRf+Bcnqc58/0uIFT4lGHFzv7a/xVFrHdsyHa4Av+2lZZkWQ43SbSdT/GWakZR7 +RMhYofErlYYLLS2UEG9evvh7jg== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100F.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100F.pem new file mode 100644 index 000000000..34a9b97c5 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/100F.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4111 (0x100f) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 09:55:02 2010 GMT + Not After : Jan 13 09:55:02 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00U\x00s\x00e\x00r\x00 \x001\x004\x00 \x00"\x00,\x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00q\x00u\x00o\x00t\x00e\x00" + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:d7:b7:68:39:6e:80:18:83:2e:d7:0a:e5:f1:3f: + 27:80:68:59:a8:05:ac:7f:d9:6e:5d:7f:1c:58:86: + b7:74:b5:51:3d:64:09:4a:a0:ff:e7:10:0e:bc:8a: + f0:d1:54:18:0a:ed:68:0a:a2:33:e5:9f:f0:3d:7f: + 24:9c:46:34:ba:45:8f:05:59:51:2d:fb:32:1d:79: + 51:37:1a:4b:f8:6e:c5:49:c0:49:9e:ef:2b:ae:aa: + 03:fa:ff:55:08:69:85:0d:b4:06:53:ee:20:4e:74: + 6c:ca:b8:98:8d:64:8f:b5:99:a9:06:37:32:ca:ca: + eb:31:16:ce:97:e8:17:0d:9d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + A7:D8:65:FB:E9:A1:F6:A4:16:76:1C:2E:5B:F3:1B:8E:08:B1:1D:7F + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 14 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 35:54:0f:d2:d3:ec:9e:a6:ea:e6:51:69:27:a3:f1:ae:ea:ef: + f9:da:ca:2a:50:f1:9e:2a:7c:74:43:d6:7f:91:ad:5a:5c:e2: + da:f3:cb:27:a2:78:99:75:0b:9e:e9:3a:bd:3e:31:14:6a:06: + b7:3f:59:d1:0a:67:03:a4:32:63:cd:b1:b6:5c:68:bb:bb:e2: + 23:a6:ff:8e:55:e5:92:a6:a8:b3:87:3d:25:21:9c:2a:6f:ab: + 09:ad:f5:e6:e6:d8:37:62:f2:30:ac:51:da:f4:9c:1d:06:f6: + f3:73:2f:6a:3b:7f:53:0d:c0:2e:ad:cc:6e:81:fe:ce:e3:53: + 0e:23 +-----BEGIN CERTIFICATE----- +MIIC1zCCAkCgAwIBAgICEA8wDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkwOTU1 +MDJaFw0zNTAxMTMwOTU1MDJaMIGHMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MTcwNQYDVQQDHi4AVQBzAGUAcgAgADEANAAgACIALABtAGkAZABkAGwAZQAg +AHEAdQBvAHQAZQAiMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDXt2g5boAY +gy7XCuXxPyeAaFmoBax/2W5dfxxYhrd0tVE9ZAlKoP/nEA68ivDRVBgK7WgKojPl +n/A9fyScRjS6RY8FWVEt+zIdeVE3Gkv4bsVJwEme7yuuqgP6/1UIaYUNtAZT7iBO +dGzKuJiNZI+1makGNzLKyusxFs6X6BcNnQIDAQABo3gwdjALBgNVHQ8EBAMCBeAw +HQYDVR0OBBYEFKfYZfvpofakFnYcLlvzG44IsR1/MB8GA1UdIwQYMBaAFOhqu8KQ +6mxwIj729kgbA+a+t6ZVMCcGA1UdEQQgMB6kHDAaMRgwFgYDVQQDEw9Vc2VyIDE0 +IFJvb3QgMTEwDQYJKoZIhvcNAQEFBQADgYEANVQP0tPsnqbq5lFpJ6Pxrurv+drK +KlDxnip8dEPWf5GtWlzi2vPLJ6J4mXULnuk6vT4xFGoGtz9Z0QpnA6QyY82xtlxo +u7viI6b/jlXlkqaos4c9JSGcKm+rCa315ubYN2LyMKxR2vScHQb283Mvajt/Uw3A +Lq3MboH+zuNTDiM= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1010.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1010.pem new file mode 100644 index 000000000..ae0a41747 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1010.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4112 (0x1010) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 09:57:52 2010 GMT + Not After : Jan 13 09:57:52 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00\\x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00s\x00\ + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:a1:cc:00:2b:07:2b:e7:ac:80:29:cb:40:37:e3: + 1f:a3:c5:13:86:16:63:6b:cc:b8:c1:aa:54:fd:57: + 0f:de:4c:69:2f:e5:5f:f0:a9:bb:25:74:48:ee:36: + 77:6b:08:b5:95:a9:00:aa:15:31:9e:d8:f6:25:53: + 78:9d:bc:2b:8f:7a:19:32:12:8c:13:60:7d:76:1e: + 4e:b1:e4:51:c7:43:c0:e6:ee:d9:61:df:85:90:a0: + 95:3c:a2:81:83:3d:22:f6:8d:42:ee:69:fa:5c:ae: + 1c:b5:52:02:fb:ec:a6:12:2f:bb:fb:6c:a8:61:95: + 08:6c:d2:e5:1e:90:61:a6:27 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 2F:C9:F6:94:E6:1E:91:13:CE:75:A1:17:FD:1D:93:7E:45:CE:4D:67 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 15 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 19:d0:dc:4c:c8:59:f0:7a:14:f2:51:54:e5:9e:5a:b3:27:0b: + d7:36:0f:74:38:07:26:65:1a:b5:94:1a:1f:b2:b7:3d:ee:b1: + 90:05:83:41:6a:98:5f:25:b4:cb:5c:49:12:24:35:d6:97:cf: + 50:2e:0a:17:41:0b:75:e9:6a:a4:fb:bb:c2:cc:c1:94:64:03: + 81:c4:25:d2:3f:3e:8f:d1:29:44:db:a9:3c:7f:0c:2c:6d:48: + 38:cb:8f:56:82:9c:d3:f3:f3:20:1f:45:19:8e:ea:91:9c:c1: + 25:cf:20:1d:bb:70:7e:b9:a0:c5:34:78:93:5f:2b:d9:fd:d5: + de:ad +-----BEGIN CERTIFICATE----- +MIICzDCCAjWgAwIBAgICEBAwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkwOTU3 +NTJaFw0zNTAxMTMwOTU3NTJaMH0xCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxLTArBgNVBAMeJABcAGUAbgBjAGwAbwBzAGkAbgBnACAAcQB1AG8AdABlAHMA +XDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAocwAKwcr56yAKctAN+Mfo8UT +hhZja8y4wapU/VcP3kxpL+Vf8Km7JXRI7jZ3awi1lakAqhUxntj2JVN4nbwrj3oZ +MhKME2B9dh5OseRRx0PA5u7ZYd+FkKCVPKKBgz0i9o1C7mn6XK4ctVIC++ymEi+7 ++2yoYZUIbNLlHpBhpicCAwEAAaN4MHYwCwYDVR0PBAQDAgXgMB0GA1UdDgQWBBQv +yfaU5h6RE851oRf9HZN+Rc5NZzAfBgNVHSMEGDAWgBToarvCkOpscCI+9vZIGwPm +vremVTAnBgNVHREEIDAepBwwGjEYMBYGA1UEAxMPVXNlciAxNSBSb290IDExMA0G +CSqGSIb3DQEBBQUAA4GBABnQ3EzIWfB6FPJRVOWeWrMnC9c2D3Q4ByZlGrWUGh+y +tz3usZAFg0FqmF8ltMtcSRIkNdaXz1AuChdBC3XpaqT7u8LMwZRkA4HEJdI/Po/R +KUTbqTx/DCxtSDjLj1aCnNPz8yAfRRmO6pGcwSXPIB27cH65oMU0eJNfK9n91d6t +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1011.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1011.pem new file mode 100644 index 000000000..21222706f --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1011.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4113 (0x1011) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 09:59:22 2010 GMT + Not After : Jan 13 09:59:22 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00\\x00\\x00d\x00o\x00u\x00b\x00l\x00e\x00 \x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00s\x00\\x00\ + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:a4:e3:64:10:9f:0a:e4:35:bb:e3:e1:f0:28:86: + 8a:f2:6e:d3:f8:44:ac:58:7b:f5:dd:1c:71:17:bf: + 3e:14:29:55:f0:5c:c9:ed:36:c0:7f:e7:cc:7c:a3: + c4:9a:13:4f:7d:6c:b3:1e:ab:24:ba:1a:ff:48:96: + 67:a5:ca:e5:75:30:24:70:3a:94:d2:92:db:29:2b: + 69:1f:1d:a4:da:37:91:57:03:79:d7:0a:c7:a9:09: + 14:a8:70:60:b5:a3:62:4f:b8:bf:0a:22:0a:9c:83: + 3a:4d:1a:47:06:97:f1:4a:38:78:95:45:10:9e:44: + 90:fb:6e:13:ba:3a:1b:b7:4b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + A5:32:FD:E7:0D:90:82:17:34:E1:AD:2A:48:5D:78:27:2B:C9:2A:B8 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 16 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 96:ee:46:fc:41:4f:55:0d:bc:46:27:5a:3c:09:7c:17:6c:e3: + 9e:3a:85:eb:3b:e2:f7:a5:ab:b5:ae:aa:44:81:d7:b7:29:39: + b8:20:40:1e:36:da:a8:03:8b:3a:96:c3:2e:ba:cd:81:b9:af: + a0:a5:95:b0:3b:55:c1:85:9d:3d:c2:d0:7b:a4:d0:0e:16:7c: + 26:ba:85:e5:96:f0:f9:cc:28:c4:ed:83:e8:6f:30:a8:22:7a: + 7e:3b:99:d6:b2:3d:a2:90:1e:c9:9b:70:0a:af:04:d9:7c:46: + 52:e2:5a:d3:57:d6:18:a9:e9:55:ee:00:e8:10:a1:84:ed:ca: + 2b:bf +-----BEGIN CERTIFICATE----- +MIIC3zCCAkigAwIBAgICEBEwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkwOTU5 +MjJaFw0zNTAxMTMwOTU5MjJaMIGPMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MT8wPQYDVQQDHjYAXABcAGQAbwB1AGIAbABlACAAZQBuAGMAbABvAHMAaQBu +AGcAIABxAHUAbwB0AGUAcwBcAFwwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB +AKTjZBCfCuQ1u+Ph8CiGivJu0/hErFh79d0ccRe/PhQpVfBcye02wH/nzHyjxJoT +T31ssx6rJLoa/0iWZ6XK5XUwJHA6lNKS2ykraR8dpNo3kVcDedcKx6kJFKhwYLWj +Yk+4vwoiCpyDOk0aRwaX8Uo4eJVFEJ5EkPtuE7o6G7dLAgMBAAGjeDB2MAsGA1Ud +DwQEAwIF4DAdBgNVHQ4EFgQUpTL95w2Qghc04a0qSF14JyvJKrgwHwYDVR0jBBgw +FoAU6Gq7wpDqbHAiPvb2SBsD5r63plUwJwYDVR0RBCAwHqQcMBoxGDAWBgNVBAMT +D1VzZXIgMTYgUm9vdCAxMTANBgkqhkiG9w0BAQUFAAOBgQCW7kb8QU9VDbxGJ1o8 +CXwXbOOeOoXrO+L3pau1rqpEgde3KTm4IEAeNtqoA4s6lsMuus2Bua+gpZWwO1XB +hZ09wtB7pNAOFnwmuoXllvD5zCjE7YPobzCoInp+O5nWsj2ikB7Jm3AKrwTZfEZS +4lrTV9YYqelV7gDoEKGE7corvw== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1012.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1012.pem new file mode 100644 index 000000000..b75551711 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1012.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4114 (0x1012) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 10:02:07 2010 GMT + Not After : Jan 13 10:02:07 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00\\x00\\x00t\x00w\x00o\x00 \x00s\x00t\x00a\x00r\x00t\x00i\x00n\x00g\x00 \x00o\x00n\x00e\x00 \x00e\x00n\x00d\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00\ + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:e9:8c:31:90:52:8d:ef:c6:6a:10:17:7d:37:a3: + ef:00:34:19:dd:a4:1a:f6:cc:37:b0:19:c8:9d:f6: + 9f:f8:3d:15:c9:cf:73:ab:0a:42:f2:54:5b:cc:12: + fb:64:35:54:c9:50:36:18:6c:b6:b0:cf:d6:1e:30: + 0b:0d:fa:f3:25:99:d7:49:20:dd:cc:04:d7:bb:07: + 00:b9:b9:87:8c:75:e5:28:a6:74:a9:b4:96:36:b8: + 15:62:84:0c:7a:a2:f3:07:9c:5c:8f:7a:22:3d:ba: + a4:06:69:f6:ce:d2:36:a0:62:e1:ae:67:aa:23:24: + ac:1d:53:ac:bf:b6:30:74:f7 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + C0:28:3E:BA:44:88:99:A0:80:67:AA:3E:B6:D4:12:A7:35:DA:A6:BB + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 17 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 06:5b:fb:65:55:34:ca:2c:1a:c2:2d:2a:97:1b:a1:68:f6:0c: + 13:18:03:44:f9:0d:37:a1:8c:b1:f7:bc:b7:74:a8:aa:c1:e7: + 36:e7:b9:e0:64:79:76:63:98:7b:1d:d8:80:8c:d9:26:61:a8: + e7:07:96:60:e9:8a:24:78:cb:9c:f3:35:15:c9:d9:0c:2e:68: + 68:48:9c:df:6b:56:3f:aa:47:34:36:b0:ef:0e:d2:e0:ee:a9: + a9:6a:27:93:60:27:5f:42:76:9c:e0:aa:74:6c:b9:aa:de:fe: + 86:98:5a:3d:73:c5:15:38:c8:ff:09:8e:ed:da:06:74:fb:67: + 92:51 +-----BEGIN CERTIFICATE----- +MIIC6TCCAlKgAwIBAgICEBIwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDAy +MDdaFw0zNTAxMTMxMDAyMDdaMIGZMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MUkwRwYDVQQDHkAAXABcAHQAdwBvACAAcwB0AGEAcgB0AGkAbgBnACAAbwBu +AGUAIABlAG4AZABpAG4AZwAgAHEAdQBvAHQAZQBcMIGfMA0GCSqGSIb3DQEBAQUA +A4GNADCBiQKBgQDpjDGQUo3vxmoQF303o+8ANBndpBr2zDewGcid9p/4PRXJz3Or +CkLyVFvMEvtkNVTJUDYYbLawz9YeMAsN+vMlmddJIN3MBNe7BwC5uYeMdeUopnSp +tJY2uBVihAx6ovMHnFyPeiI9uqQGafbO0jagYuGuZ6ojJKwdU6y/tjB09wIDAQAB +o3gwdjALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFMAoPrpEiJmggGeqPrbUEqc12qa7 +MB8GA1UdIwQYMBaAFOhqu8KQ6mxwIj729kgbA+a+t6ZVMCcGA1UdEQQgMB6kHDAa +MRgwFgYDVQQDEw9Vc2VyIDE3IFJvb3QgMTEwDQYJKoZIhvcNAQEFBQADgYEABlv7 +ZVU0yiwawi0qlxuhaPYMExgDRPkNN6GMsfe8t3SoqsHnNue54GR5dmOYex3YgIzZ +JmGo5weWYOmKJHjLnPM1FcnZDC5oaEic32tWP6pHNDaw7w7S4O6pqWonk2AnX0J2 +nOCqdGy5qt7+hphaPXPFFTjI/wmO7doGdPtnklE= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1013.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1013.pem new file mode 100644 index 000000000..2b48a29b0 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1013.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4115 (0x1013) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 10:04:36 2010 GMT + Not After : Jan 13 10:04:36 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00\\x00s\x00t\x00a\x00r\x00t\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:bb:73:a4:4e:45:8e:80:b1:65:b6:d8:3b:96:c8: + 3b:c4:2e:40:98:2a:a9:0d:2e:75:29:df:dd:28:8f: + dc:65:4e:2f:8b:24:55:f4:5b:95:5e:d8:29:c8:31: + aa:53:41:a6:1b:2a:cc:8d:67:b6:d8:5f:56:7d:bd: + 0e:17:88:9b:28:b8:fc:54:ff:0e:1f:d9:59:f7:6f: + 99:46:76:86:69:87:f7:07:51:f6:1a:76:91:37:40: + 96:de:5a:0e:c1:20:7f:b5:1b:79:c2:63:13:50:dc: + f0:35:11:2c:4a:30:e0:68:8f:dc:51:4c:2b:61:ba: + a5:e6:ad:72:8b:c4:e1:2d:73 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 31:AE:51:BD:37:3E:EB:D6:98:7D:BD:DF:45:0C:92:4E:73:58:35:AA + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 18 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 51:34:24:4b:78:89:95:5d:43:15:3e:62:fc:40:a0:34:a5:6e: + 83:b5:ee:f0:93:ae:8a:27:97:9c:66:54:c9:aa:f5:9b:96:88: + 43:25:76:b6:0d:06:36:6c:0e:08:5f:15:45:c6:cc:d1:62:18: + 6b:fa:cd:af:53:7c:7c:97:30:13:a7:03:ac:db:04:25:bb:22: + 7d:49:70:30:69:9f:c8:22:94:32:40:83:d3:d1:9d:1c:2a:64: + cf:a9:42:0c:ce:0c:b8:3d:63:33:bb:e1:85:45:a7:79:89:ac: + 0c:1b:b5:a4:e0:1d:4d:99:d6:68:9b:c2:67:97:9c:9d:2c:57: + 12:fe +-----BEGIN CERTIFICATE----- +MIICxjCCAi+gAwIBAgICEBMwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDA0 +MzZaFw0zNTAxMTMxMDA0MzZaMHcxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxJzAlBgNVBAMeHgBcAHMAdABhAHIAdABpAG4AZwAgAHEAdQBvAHQAZTCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAu3OkTkWOgLFlttg7lsg7xC5AmCqpDS51 +Kd/dKI/cZU4viyRV9FuVXtgpyDGqU0GmGyrMjWe22F9Wfb0OF4ibKLj8VP8OH9lZ +92+ZRnaGaYf3B1H2GnaRN0CW3loOwSB/tRt5wmMTUNzwNREsSjDgaI/cUUwrYbql +5q1yi8ThLXMCAwEAAaN4MHYwCwYDVR0PBAQDAgXgMB0GA1UdDgQWBBQxrlG9Nz7r +1ph9vd9FDJJOc1g1qjAfBgNVHSMEGDAWgBToarvCkOpscCI+9vZIGwPmvremVTAn +BgNVHREEIDAepBwwGjEYMBYGA1UEAxMPVXNlciAxOCBSb290IDExMA0GCSqGSIb3 +DQEBBQUAA4GBAFE0JEt4iZVdQxU+YvxAoDSlboO17vCTroonl5xmVMmq9ZuWiEMl +drYNBjZsDghfFUXGzNFiGGv6za9TfHyXMBOnA6zbBCW7In1JcDBpn8gilDJAg9PR +nRwqZM+pQgzODLg9YzO74YVFp3mJrAwbtaTgHU2Z1mibwmeXnJ0sVxL+ +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1014.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1014.pem new file mode 100644 index 000000000..a2027e9d8 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1014.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4116 (0x1014) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 10:05:50 2010 GMT + Not After : Jan 13 10:05:50 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00e\x00n\x00d\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00\ + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:ca:cc:98:77:0c:10:dd:0e:87:a2:da:b6:e6:97: + 91:36:71:54:de:2b:f8:de:18:b7:23:eb:e5:e3:57: + ae:cf:0b:6d:86:0f:63:f0:c4:4e:2a:66:48:33:c4: + e3:0b:2c:f5:e6:e5:e5:0f:f8:e0:a1:bc:11:06:a1: + 19:16:ec:44:77:a6:db:7d:d6:78:29:1f:57:f1:9d: + 3c:b4:3a:2b:3b:94:64:6d:e3:ce:b3:fa:d8:28:e2: + ed:76:9a:97:41:64:7c:0d:48:b8:1d:6a:56:e3:f9: + 4c:88:e9:1a:3c:b8:af:7a:13:67:19:59:36:46:79: + 52:72:ea:51:80:65:be:e2:0f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + D2:D8:8D:EE:39:D7:EA:15:23:00:7C:9D:48:1C:51:17:F8:80:86:CE + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 19 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 6e:05:c4:48:32:4a:62:6f:a3:8c:23:af:47:dd:d4:c7:c1:91: + 17:7e:cd:36:73:39:a3:7b:c9:ae:da:f6:e1:bd:82:d6:72:17: + 78:20:a2:27:ad:f5:d2:3f:10:66:e0:d8:ba:10:00:c3:76:5b: + de:36:cb:2a:91:25:89:08:0e:2a:6a:81:d0:a7:49:70:42:f3: + 94:a3:bf:6c:6b:b9:fa:fd:f9:d4:1f:6f:75:27:b9:0d:d3:d2: + fd:5d:0d:dc:f5:34:29:a2:3a:2f:04:ab:48:41:6d:d7:2b:fd: + 42:02:99:3c:cf:aa:6b:98:66:17:83:39:4a:6f:47:36:ad:db: + 22:6e +-----BEGIN CERTIFICATE----- +MIICwjCCAiugAwIBAgICEBQwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDA1 +NTBaFw0zNTAxMTMxMDA1NTBaMHMxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxIzAhBgNVBAMeGgBlAG4AZABpAG4AZwAgAHEAdQBvAHQAZQBcMIGfMA0GCSqG +SIb3DQEBAQUAA4GNADCBiQKBgQDKzJh3DBDdDoei2rbml5E2cVTeK/jeGLcj6+Xj +V67PC22GD2PwxE4qZkgzxOMLLPXm5eUP+OChvBEGoRkW7ER3ptt91ngpH1fxnTy0 +Ois7lGRt486z+tgo4u12mpdBZHwNSLgdalbj+UyI6Ro8uK96E2cZWTZGeVJy6lGA +Zb7iDwIDAQABo3gwdjALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFNLYje451+oVIwB8 +nUgcURf4gIbOMB8GA1UdIwQYMBaAFOhqu8KQ6mxwIj729kgbA+a+t6ZVMCcGA1Ud +EQQgMB6kHDAaMRgwFgYDVQQDEw9Vc2VyIDE5IFJvb3QgMTEwDQYJKoZIhvcNAQEF +BQADgYEAbgXESDJKYm+jjCOvR93Ux8GRF37NNnM5o3vJrtr24b2C1nIXeCCiJ631 +0j8QZuDYuhAAw3Zb3jbLKpEliQgOKmqB0KdJcELzlKO/bGu5+v351B9vdSe5DdPS +/V0N3PU0KaI6LwSrSEFt1yv9QgKZPM+qa5hmF4M5Sm9HNq3bIm4= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1015.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1015.pem new file mode 100644 index 000000000..d9d3f941e --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1015.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4117 (0x1015) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 10:07:07 2010 GMT + Not After : Jan 13 10:07:07 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00\\x00q\x00u\x00o\x00t\x00e + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:f0:7c:07:f6:13:52:ce:13:cf:8a:5f:7f:5f:3c: + d4:93:c8:a0:43:1f:e2:fc:3f:62:63:be:b5:17:e0: + 32:b0:d0:c2:9a:35:9e:3b:29:30:b4:13:78:18:ae: + 80:ba:fb:f3:fc:81:ad:aa:47:18:eb:fc:d1:76:de: + b6:cf:55:65:5e:3e:15:93:8e:9c:39:4e:a3:ae:1d: + c0:49:22:dc:25:09:33:95:0d:b5:62:7c:96:0b:05: + b6:10:ae:ee:f8:18:24:9f:d4:ed:b3:4c:a9:4d:f2: + be:6c:66:37:b9:17:cb:14:df:52:b4:a8:de:63:0d: + 4f:78:58:16:ab:f2:3f:f6:a9 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 41:CC:3D:88:34:10:21:13:A2:34:24:B6:4E:F9:33:3C:B3:FA:56:BC + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 20 Root 11 + Signature Algorithm: sha1WithRSAEncryption + a7:17:c3:92:37:10:ee:9a:12:65:32:82:56:93:82:fa:0e:40: + 9f:ae:30:6a:b1:6f:85:18:7f:ff:9c:30:49:b7:56:bf:a3:86: + d7:dd:5d:79:d1:7f:9a:95:b6:bd:1d:43:cc:2c:aa:7a:40:c4: + de:17:02:22:74:ec:a9:cd:8d:93:f6:6c:98:7e:bb:6a:68:70: + 66:d4:a0:8f:1a:7a:8e:9e:38:35:aa:87:6a:e5:db:80:69:51: + 51:68:46:4f:3d:da:17:df:6f:22:60:77:95:55:d3:12:1b:11: + c1:6f:c1:96:78:00:47:61:af:53:c0:37:44:6b:92:67:7f:14: + 79:80 +-----BEGIN CERTIFICATE----- +MIICwjCCAiugAwIBAgICEBUwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDA3 +MDdaFw0zNTAxMTMxMDA3MDdaMHMxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxIzAhBgNVBAMeGgBtAGkAZABkAGwAZQAgAFwAcQB1AG8AdABlMIGfMA0GCSqG +SIb3DQEBAQUAA4GNADCBiQKBgQDwfAf2E1LOE8+KX39fPNSTyKBDH+L8P2JjvrUX +4DKw0MKaNZ47KTC0E3gYroC6+/P8ga2qRxjr/NF23rbPVWVePhWTjpw5TqOuHcBJ +ItwlCTOVDbVifJYLBbYQru74GCSf1O2zTKlN8r5sZje5F8sU31K0qN5jDU94WBar +8j/2qQIDAQABo3gwdjALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFEHMPYg0ECETojQk +tk75Mzyz+la8MB8GA1UdIwQYMBaAFOhqu8KQ6mxwIj729kgbA+a+t6ZVMCcGA1Ud +EQQgMB6kHDAaMRgwFgYDVQQDEw9Vc2VyIDIwIFJvb3QgMTEwDQYJKoZIhvcNAQEF +BQADgYEApxfDkjcQ7poSZTKCVpOC+g5An64warFvhRh//5wwSbdWv6OG191dedF/ +mpW2vR1DzCyqekDE3hcCInTsqc2Nk/ZsmH67amhwZtSgjxp6jp44NaqHauXbgGlR +UWhGTz3aF99vImB3lVXTEhsRwW/BlngAR2GvU8A3RGuSZ38UeYA= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1016.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1016.pem new file mode 100644 index 000000000..9f4e006f0 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1016.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4118 (0x1016) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 10:09:50 2010 GMT + Not After : Jan 13 10:09:50 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00d\x00o\x00u\x00b\x00l\x00e\x00 \x00\\x00\\x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00q\x00u\x00o\x00t\x00e + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:cd:22:93:9a:93:18:34:2f:50:e0:cc:23:f4:60: + bc:96:60:d5:a5:f9:da:45:9a:5b:a3:0a:fb:71:25: + 4c:bd:60:84:19:f5:93:28:c1:5d:b9:8d:05:05:4d: + 01:85:aa:9e:5b:08:9c:01:f8:32:90:fe:ef:7f:eb: + cb:b3:8b:b2:c8:d1:79:d6:47:a3:d8:df:f1:d0:56: + 04:04:bd:41:72:fc:98:75:10:d2:9b:b5:bc:55:a1: + fa:19:01:67:93:09:48:0a:67:ec:4d:12:47:37:6f: + c2:53:0e:c9:7a:30:ec:1d:9d:a5:e2:64:d8:92:4d: + ed:ec:b2:bb:10:96:76:28:47 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + DC:FF:9A:2B:49:51:1E:FB:A7:3A:90:94:1B:E0:3E:34:89:13:48:EE + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 21 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 16:aa:a6:b7:0e:e3:d2:ba:7e:9b:59:f6:cc:ce:5d:4d:2a:f2: + 95:60:46:24:dd:ea:e8:08:e6:60:9c:33:82:8c:34:a2:d8:38: + fb:75:fe:31:79:10:78:7d:93:44:3b:00:90:83:a4:15:52:8d: + 3a:b4:9c:c0:6f:95:2c:4f:d8:b3:3b:cf:69:ab:3c:41:3a:43: + 1b:0a:8b:b0:b4:aa:8b:bf:6f:96:e2:65:4a:00:3a:49:bc:9a: + a1:cd:13:b1:24:93:f6:44:cd:d3:71:91:da:4f:dd:75:3d:68: + 5c:6b:49:14:8a:23:b5:b6:4f:b6:41:d0:a7:16:7c:67:4c:b3: + 0a:88 +-----BEGIN CERTIFICATE----- +MIIC0zCCAjygAwIBAgICEBYwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDA5 +NTBaFw0zNTAxMTMxMDA5NTBaMIGDMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MTMwMQYDVQQDHioAZABvAHUAYgBsAGUAIABcAFwAbQBpAGQAZABsAGUAIABx +AHUAbwB0AGUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM0ik5qTGDQvUODM +I/RgvJZg1aX52kWaW6MK+3ElTL1ghBn1kyjBXbmNBQVNAYWqnlsInAH4MpD+73/r +y7OLssjRedZHo9jf8dBWBAS9QXL8mHUQ0pu1vFWh+hkBZ5MJSApn7E0SRzdvwlMO +yXow7B2dpeJk2JJN7eyyuxCWdihHAgMBAAGjeDB2MAsGA1UdDwQEAwIF4DAdBgNV +HQ4EFgQU3P+aK0lRHvunOpCUG+A+NIkTSO4wHwYDVR0jBBgwFoAU6Gq7wpDqbHAi +Pvb2SBsD5r63plUwJwYDVR0RBCAwHqQcMBoxGDAWBgNVBAMTD1VzZXIgMjEgUm9v +dCAxMTANBgkqhkiG9w0BAQUFAAOBgQAWqqa3DuPSun6bWfbMzl1NKvKVYEYk3ero +COZgnDOCjDSi2Dj7df4xeRB4fZNEOwCQg6QVUo06tJzAb5UsT9izO89pqzxBOkMb +CouwtKqLv2+W4mVKADpJvJqhzROxJJP2RM3TcZHaT911PWhca0kUiiO1tk+2QdCn +FnxnTLMKiA== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1017.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1017.pem new file mode 100644 index 000000000..7bb12fa78 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1017.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4119 (0x1017) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 10:11:53 2010 GMT + Not After : Jan 13 10:11:53 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00p\x00a\x00r\x00t\x00i\x00a\x00l\x00l\x00y\x00 \x00\\x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00\ + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:e7:c9:bb:89:11:2f:2c:39:bc:d3:f5:d9:86:d4: + 8e:d7:20:11:81:75:30:25:7e:2b:29:70:61:83:38: + 24:d1:0f:cc:0b:88:71:29:06:05:a5:53:d2:00:2f: + 12:0c:7d:42:e6:47:33:de:cc:f8:7b:2a:5d:d9:cb: + 69:24:91:38:bf:0c:1a:12:cf:1e:f9:44:c2:1c:e8: + 6f:ea:ab:8b:92:4c:93:8c:69:61:b9:57:b3:1d:d0: + 03:3e:13:9d:30:bd:b2:b9:d9:c7:9b:4d:18:45:b0: + 19:19:15:58:4c:bd:5a:a1:59:4f:f0:1f:99:26:3b: + 4e:76:c6:bb:21:3c:94:bc:d9 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 43:E4:70:39:E3:91:80:2A:C3:BC:1A:F4:A3:51:4B:99:C5:20:93:A6 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 22 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 28:ce:8c:f0:bf:56:c6:a4:02:df:dd:1d:75:dc:cf:62:a0:92: + 58:64:91:8c:bb:96:3c:52:d5:66:6c:31:7e:1c:d9:a8:e5:1c: + a6:9f:5e:26:3f:69:71:c6:d7:5d:02:4f:a7:42:a5:85:fa:38: + 01:43:36:54:75:4c:51:a2:99:5d:72:05:9a:9b:fc:5e:83:9b: + a0:ef:11:b1:a4:dd:a5:50:2f:d0:14:dd:04:0f:8b:93:7e:4b: + 3e:24:04:45:d0:98:46:49:74:9f:d7:b4:68:09:dc:b6:ac:35: + 3f:5d:f9:ee:77:a4:35:46:75:a4:6a:d6:c1:53:4f:d2:0c:38: + 3c:df +-----BEGIN CERTIFICATE----- +MIIC3zCCAkigAwIBAgICEBcwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDEx +NTNaFw0zNTAxMTMxMDExNTNaMIGPMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MT8wPQYDVQQDHjYAcABhAHIAdABpAGEAbABsAHkAIABcAGUAbgBjAGwAbwBz +AGkAbgBnACAAcQB1AG8AdABlAFwwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB +AOfJu4kRLyw5vNP12YbUjtcgEYF1MCV+KylwYYM4JNEPzAuIcSkGBaVT0gAvEgx9 +QuZHM97M+HsqXdnLaSSROL8MGhLPHvlEwhzob+qri5JMk4xpYblXsx3QAz4TnTC9 +srnZx5tNGEWwGRkVWEy9WqFZT/AfmSY7TnbGuyE8lLzZAgMBAAGjeDB2MAsGA1Ud +DwQEAwIF4DAdBgNVHQ4EFgQUQ+RwOeORgCrDvBr0o1FLmcUgk6YwHwYDVR0jBBgw +FoAU6Gq7wpDqbHAiPvb2SBsD5r63plUwJwYDVR0RBCAwHqQcMBoxGDAWBgNVBAMT +D1VzZXIgMjIgUm9vdCAxMTANBgkqhkiG9w0BAQUFAAOBgQAozozwv1bGpALf3R11 +3M9ioJJYZJGMu5Y8UtVmbDF+HNmo5Rymn14mP2lxxtddAk+nQqWF+jgBQzZUdUxR +opldcgWam/xeg5ug7xGxpN2lUC/QFN0ED4uTfks+JARF0JhGSXSf17RoCdy2rDU/ +Xfnud6Q1RnWkatbBU0/SDDg83w== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1018.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1018.pem new file mode 100644 index 000000000..d134dc5f3 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1018.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4120 (0x1018) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 10:13:38 2010 GMT + Not After : Jan 13 10:13:38 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00\\x00U\x00s\x00e\x00r\x00 \x002\x003\x00,\x00 \x00s\x00t\x00a\x00r\x00t\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:b9:e3:64:f8:02:be:98:47:de:c6:f4:22:14:4f: + 22:fe:17:8c:14:7f:b8:27:44:51:9d:5a:79:33:b4: + d0:21:27:b0:ed:f9:9f:3d:54:ef:ba:3a:d8:89:2a: + ca:a8:8f:f3:f6:a7:6b:5f:0a:58:2d:a0:e3:05:3a: + 26:a6:1e:b6:89:a1:e1:71:11:e7:16:93:29:69:f8: + 14:a2:e3:d7:4e:e5:60:40:d7:40:c5:37:d6:95:7c: + 4f:35:fd:a8:82:7f:90:32:1d:99:e7:8a:b9:93:a4: + f3:23:0a:a5:f9:56:31:73:d8:e3:cb:d6:0e:2f:2b: + ee:8e:b5:ca:eb:63:82:1c:0b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 80:A8:F7:13:E3:E8:F8:A6:60:94:21:C1:FE:54:54:89:AC:4B:DF:45 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 23 Root 11 + Signature Algorithm: sha1WithRSAEncryption + be:31:bd:4a:56:80:64:f0:1e:ea:77:4a:f3:e3:ec:f0:ad:27: + cc:05:01:fa:d2:12:7c:8e:85:5b:37:54:9c:4f:96:2d:1c:81: + e4:21:3d:4b:d9:86:1a:6c:29:5e:88:f2:ae:04:f1:70:87:25: + b9:9a:4a:ef:dd:21:f9:17:33:ee:a1:eb:38:fb:c4:73:72:70: + 0c:67:58:96:95:8c:2c:5a:4a:31:28:50:52:64:65:5c:63:60: + de:24:df:a0:e9:0d:c0:b6:d6:4c:51:a7:5a:e8:dd:f6:ff:49: + e6:6f:7f:86:38:5d:c7:f9:eb:55:f1:b2:89:3b:cd:41:f7:5d: + a8:b0 +-----BEGIN CERTIFICATE----- +MIIC2TCCAkKgAwIBAgICEBgwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDEz +MzhaFw0zNTAxMTMxMDEzMzhaMIGJMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MTkwNwYDVQQDHjAAXABVAHMAZQByACAAMgAzACwAIABzAHQAYQByAHQAaQBu +AGcAIABxAHUAbwB0AGUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALnjZPgC +vphH3sb0IhRPIv4XjBR/uCdEUZ1aeTO00CEnsO35nz1U77o62IkqyqiP8/ana18K +WC2g4wU6JqYetomh4XER5xaTKWn4FKLj107lYEDXQMU31pV8TzX9qIJ/kDIdmeeK +uZOk8yMKpflWMXPY48vWDi8r7o61yutjghwLAgMBAAGjeDB2MAsGA1UdDwQEAwIF +4DAdBgNVHQ4EFgQUgKj3E+Po+KZglCHB/lRUiaxL30UwHwYDVR0jBBgwFoAU6Gq7 +wpDqbHAiPvb2SBsD5r63plUwJwYDVR0RBCAwHqQcMBoxGDAWBgNVBAMTD1VzZXIg +MjMgUm9vdCAxMTANBgkqhkiG9w0BAQUFAAOBgQC+Mb1KVoBk8B7qd0rz4+zwrSfM +BQH60hJ8joVbN1ScT5YtHIHkIT1L2YYabCleiPKuBPFwhyW5mkrv3SH5FzPuoes4 ++8RzcnAMZ1iWlYwsWkoxKFBSZGVcY2DeJN+g6Q3AttZMUada6N32/0nmb3+GOF3H ++etV8bKJO81B912osA== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1019.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1019.pem new file mode 100644 index 000000000..66c3f15bf --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1019.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4121 (0x1019) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 10:14:50 2010 GMT + Not After : Jan 13 10:14:50 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00U\x00s\x00e\x00r\x00 \x002\x004\x00,\x00 \x00e\x00n\x00d\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00\ + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:9c:cd:78:e7:11:1d:61:d4:0c:c6:87:c9:28:47: + 84:23:6b:86:c3:38:37:62:5a:9a:4b:50:fc:b7:f3: + d9:4b:1b:20:ff:06:42:bb:22:33:c5:22:12:2c:bb: + e6:c8:08:69:0e:af:e9:22:45:9f:ef:2c:26:46:d7: + 1b:36:db:70:58:32:bc:3d:d7:7d:64:27:44:54:6c: + 89:12:88:d7:31:3d:3f:5c:96:cb:69:9f:b1:a9:e0: + 9a:de:50:b7:ad:d8:29:bf:bc:3c:21:e9:a2:79:21: + 46:81:ea:90:df:44:0c:6c:bb:f8:47:c8:e9:79:d1: + 8d:40:1b:5d:d3:75:9b:e4:0b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 81:14:09:35:7F:F6:7A:83:6B:19:C2:22:24:92:E6:D4:EF:52:1C:0B + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 24 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 7c:65:0b:e2:cd:ca:00:e8:40:0f:37:70:a1:89:54:5d:03:06: + 2c:60:56:dc:2f:b7:01:ac:75:58:f6:82:8f:91:63:e2:91:d1: + 17:7b:bd:63:b9:9c:4e:46:86:3e:a6:f5:a6:56:ac:90:2a:f4: + d8:a0:6c:02:15:6e:d9:f6:2a:f8:9a:c4:48:bd:cd:54:82:55: + c6:d5:52:76:09:e3:3d:17:8d:5c:46:16:ae:9e:56:df:9f:c3: + 05:15:6f:ae:d0:b5:76:67:48:2d:5a:3c:59:da:1b:13:c3:84: + 5e:2a:57:8d:86:9a:f1:8a:5d:01:47:93:44:62:af:65:03:e1: + df:10 +-----BEGIN CERTIFICATE----- +MIIC1TCCAj6gAwIBAgICEBkwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDE0 +NTBaFw0zNTAxMTMxMDE0NTBaMIGFMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MTUwMwYDVQQDHiwAVQBzAGUAcgAgADIANAAsACAAZQBuAGQAaQBuAGcAIABx +AHUAbwB0AGUAXDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAnM145xEdYdQM +xofJKEeEI2uGwzg3YlqaS1D8t/PZSxsg/wZCuyIzxSISLLvmyAhpDq/pIkWf7ywm +RtcbNttwWDK8Pdd9ZCdEVGyJEojXMT0/XJbLaZ+xqeCa3lC3rdgpv7w8IemieSFG +geqQ30QMbLv4R8jpedGNQBtd03Wb5AsCAwEAAaN4MHYwCwYDVR0PBAQDAgXgMB0G +A1UdDgQWBBSBFAk1f/Z6g2sZwiIkkubU71IcCzAfBgNVHSMEGDAWgBToarvCkOps +cCI+9vZIGwPmvremVTAnBgNVHREEIDAepBwwGjEYMBYGA1UEAxMPVXNlciAyNCBS +b290IDExMA0GCSqGSIb3DQEBBQUAA4GBAHxlC+LNygDoQA83cKGJVF0DBixgVtwv +twGsdVj2go+RY+KR0Rd7vWO5nE5Ghj6m9aZWrJAq9NigbAIVbtn2KviaxEi9zVSC +VcbVUnYJ4z0XjVxGFq6eVt+fwwUVb67QtXZnSC1aPFnaGxPDhF4qV42GmvGKXQFH +k0Rir2UD4d8Q +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101A.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101A.pem new file mode 100644 index 000000000..ba352d83d --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101A.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4122 (0x101a) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 10:16:10 2010 GMT + Not After : Jan 13 10:16:10 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00\\x00U\x00s\x00e\x00r\x00 \x002\x005\x00,\x00 \x00e\x00n\x00c\x00l\x00o\x00s\x00i\x00n\x00g\x00 \x00q\x00u\x00o\x00t\x00e\x00\ + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:ad:20:4a:85:d2:a8:2a:f8:0e:4c:b5:2d:72:a5: + 1d:0e:b1:8a:76:2c:b0:bf:7a:48:b8:57:29:cb:40: + c5:8a:e8:0e:d3:f6:f9:b1:90:a6:4a:bb:82:45:fd: + c2:ff:03:fa:fc:4a:5d:93:0b:52:a2:17:10:b1:7e: + 13:1d:9d:28:26:e3:44:bd:fd:26:da:b2:7b:47:e1: + c4:35:ea:53:1b:94:76:cc:f2:f6:c1:86:f2:18:46: + e1:71:c0:5d:e5:8f:0a:10:7a:ea:61:af:d0:ba:28: + 22:13:77:0f:7d:9e:e0:0a:f0:92:ce:dd:b3:5d:a6: + df:c1:eb:a8:29:57:e6:71:65 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + C3:EE:4A:7E:AC:46:2D:BA:42:F7:33:1F:E7:49:FA:21:D3:BC:DD:49 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 25 Root 11 + Signature Algorithm: sha1WithRSAEncryption + bf:63:34:12:e3:4b:83:4e:e5:c5:08:c3:b3:ea:be:38:33:38: + 3c:99:c3:ca:08:84:05:d4:21:53:7a:7d:43:86:c2:63:e2:d3: + 7c:21:3c:72:fa:c6:f3:bf:2b:10:5e:ca:4b:2c:2c:1c:e3:10: + eb:7c:ff:b1:20:b2:47:1b:b3:3e:77:b6:74:fb:83:85:ac:b8: + c9:5b:ca:8a:14:2f:e4:81:6e:04:6f:c8:37:c0:9f:c0:41:0f: + b4:6e:21:82:69:51:e8:68:09:72:c4:8c:72:db:47:0b:a5:52: + d7:e7:b3:5d:10:9c:ed:14:af:1c:fd:0b:11:a3:fd:f9:b9:2d: + 48:b5 +-----BEGIN CERTIFICATE----- +MIIC3TCCAkagAwIBAgICEBowDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDE2 +MTBaFw0zNTAxMTMxMDE2MTBaMIGNMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MT0wOwYDVQQDHjQAXABVAHMAZQByACAAMgA1ACwAIABlAG4AYwBsAG8AcwBp +AG4AZwAgAHEAdQBvAHQAZQBcMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCt +IEqF0qgq+A5MtS1ypR0OsYp2LLC/eki4VynLQMWK6A7T9vmxkKZKu4JF/cL/A/r8 +Sl2TC1KiFxCxfhMdnSgm40S9/SbasntH4cQ16lMblHbM8vbBhvIYRuFxwF3ljwoQ +euphr9C6KCITdw99nuAK8JLO3bNdpt/B66gpV+ZxZQIDAQABo3gwdjALBgNVHQ8E +BAMCBeAwHQYDVR0OBBYEFMPuSn6sRi26QvczH+dJ+iHTvN1JMB8GA1UdIwQYMBaA +FOhqu8KQ6mxwIj729kgbA+a+t6ZVMCcGA1UdEQQgMB6kHDAaMRgwFgYDVQQDEw9V +c2VyIDI1IFJvb3QgMTEwDQYJKoZIhvcNAQEFBQADgYEAv2M0EuNLg07lxQjDs+q+ +ODM4PJnDygiEBdQhU3p9Q4bCY+LTfCE8cvrG878rEF7KSywsHOMQ63z/sSCyRxuz +Pne2dPuDhay4yVvKihQv5IFuBG/IN8CfwEEPtG4hgmlR6GgJcsSMcttHC6VS1+ez +XRCc7RSvHP0LEaP9+bktSLU= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101B.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101B.pem new file mode 100644 index 000000000..4c03562a8 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101B.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4123 (0x101b) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 10:17:45 2010 GMT + Not After : Jan 13 10:17:45 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00U\x00s\x00e\x00r\x00 \x002\x006\x00\\x00,\x00 \x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00q\x00u\x00o\x00t\x00e + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:ec:4c:2b:ba:b1:e5:ba:83:e8:64:6c:67:fe:f9: + 84:9a:71:68:0b:10:b0:2e:2c:21:d8:6d:c8:cc:de: + 82:76:15:b8:74:a0:4b:3c:39:f0:ee:3a:08:6c:0e: + 0c:36:51:ed:44:04:ca:2b:76:30:6f:85:d4:f6:f0: + 7e:53:2b:17:90:6a:7b:79:e0:c2:00:f2:5f:dd:19: + 8f:09:7a:a2:c8:85:95:24:e0:41:39:ec:75:e1:c7: + 03:ba:6d:e9:81:48:8b:36:38:e0:99:3e:58:04:e3: + 03:8d:e4:3b:95:98:0a:23:96:f1:96:50:06:5d:71: + 6f:02:e1:c5:cd:e0:5c:c4:7b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 1D:A3:64:F0:93:51:C2:F2:1A:BB:D0:2D:20:95:5E:19:94:4C:72:BB + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 26 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 8c:c1:56:7d:d9:a8:f7:af:4b:57:4a:a5:2a:32:11:12:e0:d8: + 0e:10:39:8f:17:53:25:f5:c6:57:55:e4:f0:16:f2:11:cc:af: + cc:44:6b:23:6f:8e:2a:df:ee:ff:f0:d4:3f:0a:85:7e:19:de: + f8:cf:69:be:8b:59:ad:3c:be:3c:d7:32:ac:ba:82:91:28:23: + 71:ba:b5:29:05:e4:98:ee:2b:bb:56:04:7f:8b:69:c5:f9:4c: + 1b:0b:2e:3a:46:41:8e:da:16:68:9f:c7:57:71:8e:97:0d:b0: + a1:92:ae:7c:75:46:ef:b4:6d:8e:e7:53:07:23:a4:e1:e0:f0: + e7:3b +-----BEGIN CERTIFICATE----- +MIIC1TCCAj6gAwIBAgICEBswDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDE3 +NDVaFw0zNTAxMTMxMDE3NDVaMIGFMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MTUwMwYDVQQDHiwAVQBzAGUAcgAgADIANgBcACwAIABtAGkAZABkAGwAZQAg +AHEAdQBvAHQAZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA7EwrurHluoPo +ZGxn/vmEmnFoCxCwLiwh2G3IzN6CdhW4dKBLPDnw7joIbA4MNlHtRATKK3Ywb4XU +9vB+UysXkGp7eeDCAPJf3RmPCXqiyIWVJOBBOex14ccDum3pgUiLNjjgmT5YBOMD +jeQ7lZgKI5bxllAGXXFvAuHFzeBcxHsCAwEAAaN4MHYwCwYDVR0PBAQDAgXgMB0G +A1UdDgQWBBQdo2Twk1HC8hq70C0glV4ZlExyuzAfBgNVHSMEGDAWgBToarvCkOps +cCI+9vZIGwPmvremVTAnBgNVHREEIDAepBwwGjEYMBYGA1UEAxMPVXNlciAyNiBS +b290IDExMA0GCSqGSIb3DQEBBQUAA4GBAIzBVn3ZqPevS1dKpSoyERLg2A4QOY8X +UyX1xldV5PAW8hHMr8xEayNvjirf7v/w1D8KhX4Z3vjPab6LWa08vjzXMqy6gpEo +I3G6tSkF5JjuK7tWBH+LacX5TBsLLjpGQY7aFmifx1dxjpcNsKGSrnx1Ru+0bY7n +UwcjpOHg8Oc7 +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101C.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101C.pem new file mode 100644 index 000000000..c403402f3 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101C.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4124 (0x101c) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 10:19:13 2010 GMT + Not After : Jan 13 10:19:13 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=comma, comma, comma , + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:af:2e:02:1a:b8:ed:7e:6e:27:2f:6e:ca:dc:57: + 11:17:88:37:38:37:26:d0:fb:d0:ee:ad:f3:a8:ad: + f5:8a:53:04:6a:82:a7:31:b5:e6:ce:88:24:fa:22: + 75:84:1b:a8:8c:fd:7f:63:0c:fc:13:41:82:60:a3: + 19:33:3d:d3:18:6e:09:c5:c7:e7:e9:9e:49:dd:f4: + 77:ef:f1:06:91:9a:c5:57:68:e5:0f:59:19:8d:53: + ff:cb:ae:11:33:48:5c:eb:72:e8:2f:67:ae:94:42: + d3:5b:2e:31:e3:6f:a7:5e:5e:9c:ea:2c:d2:c3:af: + 66:10:34:32:e5:2d:3f:55:c1 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + A1:FB:82:9C:27:AD:83:67:5E:8C:CC:A2:BA:32:3C:30:26:74:F4:CE + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 27 Root 11 + Signature Algorithm: sha1WithRSAEncryption + c6:72:8b:f8:57:9e:b7:bf:b1:f3:99:41:1c:8c:47:a1:93:d8: + 62:8e:2d:68:6c:db:12:02:86:e0:66:65:c1:7c:c4:83:35:4c: + 16:53:fd:34:c1:3c:60:15:fc:3d:3b:90:07:68:ca:af:a1:10: + 39:c4:6b:15:a6:1a:71:51:20:ea:35:84:ef:8f:ac:51:bc:d7: + 84:d8:35:71:44:8e:8c:4f:59:76:3d:b3:5f:5c:26:9e:bc:ee: + 09:40:13:3b:38:85:02:56:7d:97:db:4d:3d:b5:a1:66:cf:df: + 19:7a:2f:71:b7:a4:12:c3:9b:df:83:f9:a8:8a:00:68:e4:3a: + ee:25 +-----BEGIN CERTIFICATE----- +MIICvTCCAiagAwIBAgICEBwwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDE5 +MTNaFw0zNTAxMTMxMDE5MTNaMG4xCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxHjAcBgNVBAMTFWNvbW1hLCBjb21tYSwgY29tbWEgLDCBnzANBgkqhkiG9w0B +AQEFAAOBjQAwgYkCgYEAry4CGrjtfm4nL27K3FcRF4g3ODcm0PvQ7q3zqK31ilME +aoKnMbXmzogk+iJ1hBuojP1/Ywz8E0GCYKMZMz3TGG4Jxcfn6Z5J3fR37/EGkZrF +V2jlD1kZjVP/y64RM0hc63LoL2eulELTWy4x42+nXl6c6izSw69mEDQy5S0/VcEC +AwEAAaN4MHYwCwYDVR0PBAQDAgXgMB0GA1UdDgQWBBSh+4KcJ62DZ16MzKK6Mjww +JnT0zjAfBgNVHSMEGDAWgBToarvCkOpscCI+9vZIGwPmvremVTAnBgNVHREEIDAe +pBwwGjEYMBYGA1UEAxMPVXNlciAyNyBSb290IDExMA0GCSqGSIb3DQEBBQUAA4GB +AMZyi/hXnre/sfOZQRyMR6GT2GKOLWhs2xIChuBmZcF8xIM1TBZT/TTBPGAV/D07 +kAdoyq+hEDnEaxWmGnFRIOo1hO+PrFG814TYNXFEjoxPWXY9s19cJp687glAEzs4 +hQJWfZfbTT21oWbP3xl6L3G3pBLDm9+D+aiKAGjkOu4l +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101D.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101D.pem new file mode 100644 index 000000000..2790a2abd --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101D.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4125 (0x101d) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 10:20:47 2010 GMT + Not After : Jan 13 10:20:47 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=equal CN=User 28 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:ae:df:12:64:ab:d9:2f:ee:21:64:b5:08:c5:c8: + 8f:a1:ad:0e:b9:28:91:69:74:13:a5:aa:49:fe:fa: + 02:9d:37:db:0a:3b:26:6a:20:25:3d:f9:2d:b2:3b: + 39:c8:c6:e3:a7:aa:a1:0b:b2:1b:58:43:e6:3c:3f: + 67:fe:bb:bd:9b:b5:d9:de:e9:ed:76:ab:fd:f5:c8: + 15:b2:fb:a6:3f:23:ef:9f:5f:71:43:b3:be:55:1e: + 85:5f:13:b1:6b:9d:42:d7:30:a8:d2:9b:fe:71:7a: + c7:d3:60:7a:cf:e2:83:75:83:b8:1c:d3:ef:ee:94: + 3f:14:63:aa:7c:15:4e:42:1d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 3B:2D:2B:5F:2E:E6:32:23:AE:47:B7:30:25:CB:ED:B0:6D:0C:30:E4 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 28 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 5b:cf:de:92:f8:ac:39:fb:0a:81:70:5b:17:d0:0d:0d:85:5e: + 2e:7d:be:d1:1a:ad:1d:99:a4:a6:f0:48:5a:7b:04:39:e2:93: + ff:80:84:f6:a1:e6:8a:52:12:55:46:c0:57:84:d9:c3:13:92: + 61:d7:41:af:39:09:57:05:25:01:90:68:7c:7c:5c:85:c6:f2: + fe:0e:37:e3:58:68:f9:32:fc:41:2c:35:36:f4:cf:ea:55:2d: + 52:7c:fb:37:32:35:cf:82:eb:fc:f1:39:f1:51:f1:e1:5b:d6: + 58:e1:7f:d4:50:ce:cf:07:f2:e5:f5:e2:dd:fe:55:3f:64:07: + 90:4f +-----BEGIN CERTIFICATE----- +MIICuDCCAiGgAwIBAgICEB0wDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDIw +NDdaFw0zNTAxMTMxMDIwNDdaMGkxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxGTAXBgNVBAMTEGVxdWFsIENOPVVzZXIgMjgwgZ8wDQYJKoZIhvcNAQEBBQAD +gY0AMIGJAoGBAK7fEmSr2S/uIWS1CMXIj6GtDrkokWl0E6WqSf76Ap032wo7Jmog +JT35LbI7OcjG46eqoQuyG1hD5jw/Z/67vZu12d7p7Xar/fXIFbL7pj8j759fcUOz +vlUehV8TsWudQtcwqNKb/nF6x9Nges/ig3WDuBzT7+6UPxRjqnwVTkIdAgMBAAGj +eDB2MAsGA1UdDwQEAwIF4DAdBgNVHQ4EFgQUOy0rXy7mMiOuR7cwJcvtsG0MMOQw +HwYDVR0jBBgwFoAU6Gq7wpDqbHAiPvb2SBsD5r63plUwJwYDVR0RBCAwHqQcMBox +GDAWBgNVBAMTD1VzZXIgMjggUm9vdCAxMTANBgkqhkiG9w0BAQUFAAOBgQBbz96S ++Kw5+wqBcFsX0A0NhV4ufb7RGq0dmaSm8EhaewQ54pP/gIT2oeaKUhJVRsBXhNnD +E5Jh10GvOQlXBSUBkGh8fFyFxvL+DjfjWGj5MvxBLDU29M/qVS1SfPs3MjXPguv8 +8TnxUfHhW9ZY4X/UUM7PB/Ll9eLd/lU/ZAeQTw== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101E.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101E.pem new file mode 100644 index 000000000..f12a0c1c0 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101E.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4126 (0x101e) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 10:22:13 2010 GMT + Not After : Jan 13 10:22:13 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 29+OU=ooo + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:ae:12:dc:26:fe:7f:b8:3f:47:a2:dc:83:a1:70: + 6d:ab:db:e5:3c:28:d5:18:32:2c:8d:ee:85:c6:f9: + f4:8b:31:34:71:de:91:79:fb:56:b4:9c:af:3e:b1: + c6:de:06:3f:32:fc:45:9d:9b:dd:15:0f:b5:c3:98: + ab:8c:1e:3d:63:7c:2a:c5:b9:38:3d:50:6c:81:9e: + f0:b3:5b:41:1a:ec:15:b2:7f:2b:b4:d4:42:aa:ca: + e6:89:b0:c6:58:bd:2d:38:f3:4d:85:c3:08:d7:45: + 48:42:d7:fe:ee:7a:c0:22:41:c0:c6:cb:77:7c:22: + 43:07:35:dc:88:7c:49:3a:9b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + E0:19:7F:AC:F8:6A:42:7E:84:CA:8C:84:45:75:4E:9D:A1:D1:2A:72 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 29 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 85:c9:ea:82:e2:ac:f6:b3:15:51:11:bd:69:81:31:8f:ee:d3: + f9:f4:8e:d5:27:34:20:89:76:eb:8a:5b:02:69:9b:97:89:d7: + 6b:aa:03:7f:b5:40:f9:ac:54:ce:8f:30:fd:3e:78:72:91:96: + dc:a6:bd:64:42:f8:e4:18:1a:e3:b5:db:08:fe:1e:fc:3d:a2: + 55:21:ad:0f:1a:87:df:f2:65:87:4d:91:52:c1:46:c1:c0:7c: + cc:81:79:97:dc:2e:41:cc:ae:8c:8e:79:4e:02:49:7c:c5:b0: + 3e:8e:d9:f0:aa:6b:a6:2f:e7:d2:21:5b:7f:57:e8:f7:f6:00: + 3c:ad +-----BEGIN CERTIFICATE----- +MIICtjCCAh+gAwIBAgICEB4wDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDIy +MTNaFw0zNTAxMTMxMDIyMTNaMGcxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxFzAVBgNVBAMTDlVzZXIgMjkrT1U9b29vMIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQCuEtwm/n+4P0ei3IOhcG2r2+U8KNUYMiyN7oXG+fSLMTRx3pF5+1a0 +nK8+scbeBj8y/EWdm90VD7XDmKuMHj1jfCrFuTg9UGyBnvCzW0Ea7BWyfyu01EKq +yuaJsMZYvS04802FwwjXRUhC1/7uesAiQcDGy3d8IkMHNdyIfEk6mwIDAQABo3gw +djALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFOAZf6z4akJ+hMqMhEV1Tp2h0SpyMB8G +A1UdIwQYMBaAFOhqu8KQ6mxwIj729kgbA+a+t6ZVMCcGA1UdEQQgMB6kHDAaMRgw +FgYDVQQDEw9Vc2VyIDI5IFJvb3QgMTEwDQYJKoZIhvcNAQEFBQADgYEAhcnqguKs +9rMVURG9aYExj+7T+fSO1Sc0IIl264pbAmmbl4nXa6oDf7VA+axUzo8w/T54cpGW +3Ka9ZEL45Bga47XbCP4e/D2iVSGtDxqH3/Jlh02RUsFGwcB8zIF5l9wuQcyujI55 +TgJJfMWwPo7Z8Kprpi/n0iFbf1fo9/YAPK0= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101F.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101F.pem new file mode 100644 index 000000000..1393b9ed3 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/101F.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4127 (0x101f) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 10:26:01 2010 GMT + Not After : Jan 13 10:26:01 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00U\x00s\x00e\x00r\x00 \x003\x000\x00<\x00 \x00>\x00#\x00;\x00 \x00"\x00+\x00" + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:cf:40:99:4d:a5:5d:73:2a:78:72:9c:32:94:15: + 1e:01:40:b4:68:8f:b8:4e:38:aa:b9:82:96:5a:5c: + 03:d5:db:09:42:46:d8:2d:f0:da:f8:1a:f0:85:10: + f2:cb:1f:be:50:b7:ae:6f:22:80:f2:bf:14:73:84: + da:30:b9:54:26:0d:72:1c:55:99:50:c6:78:a3:37: + 15:b2:9c:03:22:dc:ea:8b:f5:07:32:f3:d9:76:64: + 92:a3:4f:73:12:e2:43:79:0e:e6:44:17:99:79:49: + 73:65:da:03:3d:be:db:e3:4f:ae:6c:d0:6c:e6:4a: + d3:83:45:5d:83:18:d5:cc:29 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + D9:EA:10:1D:D3:F5:30:AD:30:0E:80:73:14:22:1A:26:35:90:DC:67 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 30 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 42:3a:02:d5:7b:23:9f:cc:5b:b8:d4:c8:e8:0c:e3:0d:8a:17: + 65:b6:87:ce:c9:dc:f7:84:95:e0:17:ea:11:8b:15:30:e1:a2: + 42:6c:4e:f0:31:fa:fd:ff:03:37:d4:ec:4c:1d:29:8d:07:8a: + c8:de:0b:d6:df:d7:2e:12:8a:00:a0:ca:be:48:af:17:36:63: + 8e:f2:cf:80:8b:a1:e2:33:ef:42:db:91:d3:8e:4b:02:55:5e: + f7:79:11:5c:6d:ef:64:8b:53:a6:af:f5:0f:e2:75:7a:d6:85: + f6:60:d5:7e:d6:8c:0e:37:84:a9:50:2b:c7:e6:63:bf:1d:14: + aa:bf +-----BEGIN CERTIFICATE----- +MIICyDCCAjGgAwIBAgICEB8wDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDI2 +MDFaFw0zNTAxMTMxMDI2MDFaMHkxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxKTAnBgNVBAMeIABVAHMAZQByACAAMwAwADwAIAA+ACMAOwAgACIAKwAiMIGf +MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDPQJlNpV1zKnhynDKUFR4BQLRoj7hO +OKq5gpZaXAPV2wlCRtgt8Nr4GvCFEPLLH75Qt65vIoDyvxRzhNowuVQmDXIcVZlQ +xnijNxWynAMi3OqL9Qcy89l2ZJKjT3MS4kN5DuZEF5l5SXNl2gM9vtvjT65s0Gzm +StODRV2DGNXMKQIDAQABo3gwdjALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFNnqEB3T +9TCtMA6AcxQiGiY1kNxnMB8GA1UdIwQYMBaAFOhqu8KQ6mxwIj729kgbA+a+t6ZV +MCcGA1UdEQQgMB6kHDAaMRgwFgYDVQQDEw9Vc2VyIDMwIFJvb3QgMTEwDQYJKoZI +hvcNAQEFBQADgYEAQjoC1Xsjn8xbuNTI6AzjDYoXZbaHzsnc94SV4BfqEYsVMOGi +QmxO8DH6/f8DN9TsTB0pjQeKyN4L1t/XLhKKAKDKvkivFzZjjvLPgIuh4jPvQtuR +045LAlVe93kRXG3vZItTpq/1D+J1etaF9mDVftaMDjeEqVArx+Zjvx0Uqr8= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1020.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1020.pem new file mode 100644 index 000000000..40e90d4cb --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1020.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4128 (0x1020) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 10:28:47 2010 GMT + Not After : Jan 13 10:28:47 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00U\x00s\x00e\x00r\x00 \x003\x001\x00 \x00\\x00"\x00a\x00,\x00b\x00"\x00+\x00C\x00N\x00=\x00U\x00S\x00,\x00 \x00>\x00 \x00\\x00\\x00d\x00e\x00 \x00< + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:ac:02:18:e0:1c:54:bb:76:97:2e:d3:67:78:b7: + 14:78:46:83:7c:e9:5c:2b:2f:25:bb:bf:90:c0:52: + ea:2c:79:d6:9d:af:b5:f8:86:a2:bf:56:9b:0f:33: + ed:ef:d2:2c:57:c6:0a:25:b3:f7:9b:a1:7a:3b:75: + 0b:18:86:23:64:2a:23:b0:60:f1:d8:05:b4:a6:7b: + 77:21:30:b4:0d:f1:af:e1:fb:d6:88:a8:5b:5d:7e: + a2:bf:ce:20:f6:c0:7a:89:f2:0f:33:47:6d:49:0f: + 3d:59:27:f9:95:c0:3b:a3:1c:18:a1:2d:95:09:e8: + d2:95:ac:10:92:fc:db:84:e3 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + F8:BA:7E:78:BC:70:33:D3:45:68:37:59:3A:06:AC:65:B1:15:74:F0 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 31 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 0f:a8:53:f0:56:76:df:a8:b3:5b:d1:e8:98:62:8f:a6:13:96: + c3:6b:ca:3f:e1:09:37:54:6f:ac:15:4b:74:0c:6c:3f:fe:de: + 36:58:a2:9d:a0:1f:18:97:2c:1d:bc:c6:df:ee:aa:5b:d3:da: + 2f:51:02:7a:ba:a9:7e:4d:cf:47:16:0b:f1:b1:e1:28:2b:fe: + a4:9d:50:96:cd:c5:45:09:35:50:93:9b:97:a9:23:2a:5e:f0: + 2e:16:18:3f:50:7a:83:59:c5:6c:79:99:d3:ea:12:ef:15:a9: + b0:93:1e:4b:26:6c:63:13:7f:d3:5a:0c:4d:0b:f4:51:21:98: + 4f:81 +-----BEGIN CERTIFICATE----- +MIIC5TCCAk6gAwIBAgICECAwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDI4 +NDdaFw0zNTAxMTMxMDI4NDdaMIGVMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MUUwQwYDVQQDHjwAVQBzAGUAcgAgADMAMQAgAFwAIgBhACwAYgAiACsAQwBO +AD0AVQBTACwAIAA+ACAAXABcAGQAZQAgADwwgZ8wDQYJKoZIhvcNAQEBBQADgY0A +MIGJAoGBAKwCGOAcVLt2ly7TZ3i3FHhGg3zpXCsvJbu/kMBS6ix51p2vtfiGor9W +mw8z7e/SLFfGCiWz95uhejt1CxiGI2QqI7Bg8dgFtKZ7dyEwtA3xr+H71oioW11+ +or/OIPbAeonyDzNHbUkPPVkn+ZXAO6McGKEtlQno0pWsEJL824TjAgMBAAGjeDB2 +MAsGA1UdDwQEAwIF4DAdBgNVHQ4EFgQU+Lp+eLxwM9NFaDdZOgasZbEVdPAwHwYD +VR0jBBgwFoAU6Gq7wpDqbHAiPvb2SBsD5r63plUwJwYDVR0RBCAwHqQcMBoxGDAW +BgNVBAMTD1VzZXIgMzEgUm9vdCAxMTANBgkqhkiG9w0BAQUFAAOBgQAPqFPwVnbf +qLNb0eiYYo+mE5bDa8o/4Qk3VG+sFUt0DGw//t42WKKdoB8YlywdvMbf7qpb09ov +UQJ6uql+Tc9HFgvxseEoK/6knVCWzcVFCTVQk5uXqSMqXvAuFhg/UHqDWcVseZnT +6hLvFamwkx5LJmxjE3/TWgxNC/RRIZhPgQ== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1021.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1021.pem new file mode 100644 index 000000000..443c07462 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1021.pem @@ -0,0 +1,61 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4129 (0x1021) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Jan 19 10:40:59 2010 GMT + Not After : Jan 13 10:40:59 2035 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=\x00U\x00s\x00e\x00r\x00 \x001\x004\x00 \x00"\x00,\x00m\x00i\x00d\x00d\x00l\x00e\x00 \x00q\x00u\x00o\x00t\x00e + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:da:7a:30:0d:63:da:74:05:ef:3e:d2:f4:2b:1b: + 50:e3:64:67:98:7d:2f:83:e7:77:7b:b8:72:9b:c8: + 9e:65:de:cc:2a:7b:76:c2:08:05:7a:ce:88:3e:ed: + b5:75:89:36:d2:4a:bb:3b:66:ac:57:2b:15:99:c9: + d4:74:ca:f5:eb:ff:80:b7:9f:6b:48:2f:3b:a7:51: + c4:12:af:96:ca:ac:b9:ea:23:fd:93:f7:7d:5b:d1: + ab:7c:24:1e:fe:48:dc:33:de:45:d6:8c:86:5a:b9: + 56:3c:e4:a9:f1:8c:d7:41:01:da:04:2a:7d:06:c3: + 5b:a4:cc:5f:6c:ef:7c:4e:ef + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 49:E2:AE:12:D7:EF:C3:B5:02:65:DD:CF:B2:62:E6:25:ED:3D:10:9C + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DirName:/CN=User 14 Root 11 + Signature Algorithm: sha1WithRSAEncryption + 8b:ca:d2:93:cb:d1:cc:a9:67:a3:be:75:cf:ca:cd:22:78:cc: + 7c:f9:f1:2c:94:2c:60:bd:0f:18:16:26:fe:de:0d:19:5a:87: + de:34:8c:1f:eb:89:37:74:63:d4:d9:cd:59:35:06:24:a5:6f: + f2:c6:69:f4:b5:37:6d:ae:8b:d3:5d:5e:43:8f:36:7d:f8:0c: + 30:3f:74:3d:e2:85:89:75:58:36:0f:df:72:17:47:22:c6:fd: + 47:e3:d6:73:d1:40:89:e8:9a:ba:53:14:5c:3a:de:a9:85:a8: + 8f:b0:27:81:4d:87:ef:bb:6b:bf:8c:8a:71:9b:94:1d:30:d5: + 12:ed +-----BEGIN CERTIFICATE----- +MIIC1TCCAj6gAwIBAgICECEwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDAxMTkxMDQw +NTlaFw0zNTAxMTMxMDQwNTlaMIGFMQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFt +YnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsTC0RldmVsb3Bt +ZW50MTUwMwYDVQQDHiwAVQBzAGUAcgAgADEANAAgACIALABtAGkAZABkAGwAZQAg +AHEAdQBvAHQAZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA2nowDWPadAXv +PtL0KxtQ42RnmH0vg+d3e7hym8ieZd7MKnt2wggFes6IPu21dYk20kq7O2asVysV +mcnUdMr16/+At59rSC87p1HEEq+Wyqy56iP9k/d9W9GrfCQe/kjcM95F1oyGWrlW +POSp8YzXQQHaBCp9BsNbpMxfbO98Tu8CAwEAAaN4MHYwCwYDVR0PBAQDAgXgMB0G +A1UdDgQWBBRJ4q4S1+/DtQJl3c+yYuYl7T0QnDAfBgNVHSMEGDAWgBToarvCkOps +cCI+9vZIGwPmvremVTAnBgNVHREEIDAepBwwGjEYMBYGA1UEAxMPVXNlciAxNCBS +b290IDExMA0GCSqGSIb3DQEBBQUAA4GBAIvK0pPL0cypZ6O+dc/KzSJ4zHz58SyU +LGC9DxgWJv7eDRlah940jB/riTd0Y9TZzVk1BiSlb/LGafS1N22ui9NdXkOPNn34 +DDA/dD3ihYl1WDYP33IXRyLG/Ufj1nPRQInomrpTFFw63qmFqI+wJ4FNh++7a7+M +inGblB0w1RLt +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1022.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1022.pem new file mode 100644 index 000000000..690260575 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/newcerts/1022.pem @@ -0,0 +1,64 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4130 (0x1022) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Nov 8 10:51:39 2010 GMT + Not After : Nov 8 10:51:39 2011 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 35 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:9b:36:00:64:f3:ce:93:97:62:19:fa:78:d9:6f: + 92:6a:b9:d2:9a:4e:06:2c:02:52:cd:93:50:84:28: + 19:42:a2:4a:34:e2:cd:e6:b0:39:7a:c8:4d:84:bc: + 71:51:ed:5d:6c:7e:f9:cc:01:5a:4b:73:50:a9:3b: + 5d:ad:cc:89:f7:dc:e0:dd:0a:ff:48:01:a9:34:19: + c0:6a:ee:4b:20:f4:cf:3c:94:c1:ae:88:0f:c9:42: + 1a:a6:47:31:fe:37:04:00:bb:ec:07:5f:cb:ee:70: + c4:c7:7c:6f:ee:03:19:76:de:0b:df:d0:48:91:67: + 55:9b:90:91:f4:ce:56:04:d5 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 91:47:AC:29:95:5D:EF:72:14:8F:82:45:07:E2:94:49:75:C6:7D:73 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DNS:alt.openoffice.org, IP Address:192.168.7.1, IP Address:13:0:0:0:0:0:0:17, email:my@other.address, Registered ID:1.2.3.4, othername:, DirName:/C=DE/O=OpenOffice.org/OU=Development/CN=User 32 Root 11, URI:http://my.url.here/ + Signature Algorithm: sha1WithRSAEncryption + 6e:80:e6:1e:86:3d:d2:65:a6:17:fa:80:2d:2e:dc:85:32:05: + a1:69:82:e1:79:d1:dc:de:69:cd:9e:f0:cc:90:75:a9:45:ee: + 73:46:fe:29:69:c0:99:bb:fc:3a:db:c0:5f:69:c6:b7:ea:9a: + 63:b2:8e:29:2c:a5:5a:88:88:94:75:4b:ab:0a:72:f6:3a:aa: + 5d:6b:3a:5c:b6:9b:57:f5:c1:51:af:df:3c:a6:8a:a3:da:70: + 66:61:49:12:06:78:98:9f:bc:78:3c:43:6d:08:94:aa:32:b6: + f3:cc:af:0d:29:fe:96:47:7d:fe:4a:61:48:90:11:0b:bd:0f: + a0:fd +-----BEGIN CERTIFICATE----- +MIIDajCCAtOgAwIBAgICECIwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMTAeFw0xMDExMDgxMDUx +MzlaFw0xMTExMDgxMDUxMzlaMGAxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxEDAOBgNVBAMTB1VzZXIgMzUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB +AJs2AGTzzpOXYhn6eNlvkmq50ppOBiwCUs2TUIQoGUKiSjTizeawOXrITYS8cVHt +XWx++cwBWktzUKk7Xa3Miffc4N0K/0gBqTQZwGruSyD0zzyUwa6ID8lCGqZHMf43 +BAC77Adfy+5wxMd8b+4DGXbeC9/QSJFnVZuQkfTOVgTVAgMBAAGjggExMIIBLTAL +BgNVHQ8EBAMCBeAwHQYDVR0OBBYEFJFHrCmVXe9yFI+CRQfilEl1xn1zMB8GA1Ud +IwQYMBaAFOhqu8KQ6mxwIj729kgbA+a+t6ZVMIHdBgNVHREEgdUwgdKCEmFsdC5v +cGVub2ZmaWNlLm9yZ4cEwKgHAYcQABMAAAAAAAAAAAAAAAAAF4EQbXlAb3RoZXIu +YWRkcmVzc4gDKgMEoB4GAyoDBKAXDBVzb21lIG90aGVyIGlkZW50aWZpZXKkWDBW +MQswCQYDVQQGEwJERTEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsT +C0RldmVsb3BtZW50MRgwFgYDVQQDEw9Vc2VyIDMyIFJvb3QgMTGGE2h0dHA6Ly9t +eS51cmwuaGVyZS8wDQYJKoZIhvcNAQEFBQADgYEAboDmHoY90mWmF/qALS7chTIF +oWmC4XnR3N5pzZ7wzJB1qUXuc0b+KWnAmbv8OtvAX2nGt+qaY7KOKSylWoiIlHVL +qwpy9jqqXWs6XLabV/XBUa/fPKaKo9pwZmFJEgZ4mJ+8eDxDbQiUqjK288yvDSn+ +lkd9/kphSJARC70PoP0= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Root_11/demoCA/private/cakey.pem new file mode 100644 index 000000000..fb0dd164e --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,F268674FF1377D42 + +kJQy9qJMCqZyDVs3+ZKQnh22enecltKSYzd0S1dIN1chgQ0RzLEiWBHmHCVP/yB0 +YoKrQ07FUR/uSLqTbyhAl+KDVcNvqrj/NeWs0n8zqN0ZF6wQtxtDrWFWmHNAvQXU +2kO1CvjYiruapgwmVDDJV1qf25byenQv9LMyQMD6EPU1XqFeamklidALdkb7DylA +WL6EIg4vhh96ZaG6PwLcB9rho0QRrXrLS6SHiklNBN5fHUWOfDyhXJ7K4HvzH1SS +/EtqgyKKxH5irTRdoJg2OaDBAahyW93CneEnFdufDgzvCdrsg79Z2GFz7TDJEfW4 +rnoqoXTdei1Ah+t1BC4uXXAU8DR0xusnJi0qJDJ7ETRBhROlNhTRF8TAHll+5dIf +9772GwVT+hADZn1qJgmhPiN4f8Fx33k5NOcwb0X/0Z1mzULrwm1P6lng0DsusDo0 +dr/wFyRjWZEWhMcL/sIO1BwVTBPcE8CACnXutehs44DBWd91EQ4+PWNq7oPtHFw8 +09d30h4aJJZF/SGRi+f/czFyZF4WS2Q+UWmNNKJX8wCGQqzUb02kVwMEWHiNFiEo +V8xI3JXVmKHDWlgdoIz9kVe//3AfY5y+52cYLdqaNW8IsgWZC8SC9Lk9j5uaNZ/I +leNppt4ID7mfYPqjEXEKleC+1ncwFwdVl/zaa/fM78sWqDYrLZC47DToLfoQ9Gez +3dj3554iHTe61Jd7JsK85pYsrIHAeYppOpqzLyQmCu3twBl3uGD7KXxvdZRt8foE +Vrg/QSIB4E6gfSBP0UrXzsnga8tjVyqRW2vAvt0uLn945ducapf9oQ== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Root_11/demoCA/serial b/xmlsecurity/test_docs/CAs/Root_11/demoCA/serial new file mode 100644 index 000000000..b70608fe8 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/demoCA/serial @@ -0,0 +1 @@ +1023 diff --git a/xmlsecurity/test_docs/CAs/Root_11/openssl.cfg b/xmlsecurity/test_docs/CAs/Root_11/openssl.cfg new file mode 100644 index 000000000..dd84cb906 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_11/openssl.cfg @@ -0,0 +1,298 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert +utf8 = yes +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask =pkix + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 +commonName_default =User 14 \",middle quote + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +#nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move +subjectAltName=DNS:alt.openoffice.org,IP:192.168.7.1,IP:13::17,email:my@other.address,RID:1.2.3.4,otherName:1.2.3.4;UTF8:some other identifier,dirName:dir_sect,URI:http://my.url.here/ +# Copy subject details +# issuerAltName=issuer:copy + + +[dir_sect] +C=DE +O=OpenOffice.org +OU=Development +CN=User 32 Root 11 + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Root_7.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Root_2/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Root_2/demoCA/cacert.pem new file mode 100644 index 000000000..e64badeef --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_2/demoCA/cacert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDBDCCAm2gAwIBAgIJAKKvFYnsc1SGMA0GCSqGSIb3DQEBBQUAMF8xCzAJBgNV +BAYTAkRFMRAwDgYDVQQIEwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9y +ZzEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgMjAeFw0wOTEx +MTgxNTQ2NTJaFw0zNDExMTIxNTQ2NTJaMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgMjCBnzANBgkqhkiG9w0BAQEFAAOBjQAw +gYkCgYEAsJSDLnSsoNY1U8hS0g5cmu7ihp+nvDvx8C75Wav80KumG9gcS3icmSOm +vPVqUmJq5o9CKM8z4vJR7D3e+Wf7S7XHMdL0uXuQi+QQCB1aMAWMxo7xnoWAXZrS +LG1BWUjD9sdKCHuQfFQv9ke3cA2dGZFSMsUD73JYoo0RD72ftFkCAwEAAaOBxzCB +xDAdBgNVHQ4EFgQUX7xM2usKDLUjQ14kMid5QfWCowIwgZEGA1UdIwSBiTCBhoAU +X7xM2usKDLUjQ14kMid5QfWCowKhY6RhMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgMoIJAKKvFYnsc1SGMA8GA1UdEwEB/wQF +MAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAqfEPhXASt24n8P9mDKisEn2EIYmJKLaY +AVwXLPXUOiMlqrfPRKpseQII4WmDCRxMa6bKCwf4pKUWIpTpDhRZCUespaLz1AcU +ntv+HTXq1ECK+akK33fsh5qMvokfzZM+Q0zCiFV/c2aTTGSM5mV3/q810RUlNQY3 +1y+AN+6fRqE= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_2/demoCA/crl/DO_NOT_CREATE_A_CRL b/xmlsecurity/test_docs/CAs/Root_2/demoCA/crl/DO_NOT_CREATE_A_CRL new file mode 100644 index 000000000..e69de29bb diff --git a/xmlsecurity/test_docs/CAs/Root_2/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Root_2/demoCA/crlnumber new file mode 100644 index 000000000..83b33d238 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_2/demoCA/crlnumber @@ -0,0 +1 @@ +1000 diff --git a/xmlsecurity/test_docs/CAs/Root_2/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Root_2/demoCA/index.txt new file mode 100644 index 000000000..3e79e22d7 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_2/demoCA/index.txt @@ -0,0 +1 @@ +V 341112155538Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 1 Root 2 diff --git a/xmlsecurity/test_docs/CAs/Root_2/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Root_2/demoCA/index.txt.attr new file mode 100644 index 000000000..8f7e63a34 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_2/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Root_2/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Root_2/demoCA/newcerts/1000.pem new file mode 100644 index 000000000..36a8eb3c0 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_2/demoCA/newcerts/1000.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 2 + Validity + Not Before: Nov 18 15:55:38 2009 GMT + Not After : Nov 12 15:55:38 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 2 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:f0:7a:16:4c:ab:06:b2:af:27:9c:7d:3f:86:da: + de:7a:c3:01:67:77:56:49:09:ed:ed:31:72:83:e8: + 75:9c:4c:ce:f9:97:b6:63:3c:e2:ca:83:80:92:03: + 9c:96:e2:de:72:79:c1:cf:3e:3f:b9:0d:b4:87:c7: + 75:e6:56:8d:aa:f8:77:47:11:4e:fe:07:b0:1d:64: + 06:73:4b:6f:d4:ac:da:0f:05:87:b1:f1:98:a9:f5: + 8a:a1:a8:ed:17:9c:26:b8:da:92:63:d2:53:87:e6: + fc:ed:44:de:94:56:90:3e:a2:a1:67:08:cb:38:d4: + cf:17:3b:7e:ff:7a:97:c0:7b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 8C:F3:2C:30:A2:E8:62:50:70:BC:FC:71:A0:41:FA:E0:58:B4:4D:B8 + X509v3 Authority Key Identifier: + keyid:5F:BC:4C:DA:EB:0A:0C:B5:23:43:5E:24:32:27:79:41:F5:82:A3:02 + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 2 + serial:A2:AF:15:89:EC:73:54:86 + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 52:83:16:ab:0e:43:2d:b3:e4:0f:6c:c1:63:d4:86:ac:e7:1e: + ee:7b:ee:9b:0c:ff:4f:e0:59:d5:e4:27:af:68:bf:a7:f5:2a: + a3:c9:e3:2b:8d:b7:31:26:f6:04:80:4e:f2:a5:bf:da:63:5e: + 8c:d6:c6:b2:46:a0:46:10:2f:84:9f:02:76:f3:c8:33:05:62: + 0c:5f:2d:cc:06:23:53:9f:d9:f8:46:e4:2e:5c:da:05:fc:bf: + db:45:b4:ac:8d:8b:b5:4b:60:7b:7b:26:34:7f:b1:4b:41:96: + 41:26:70:7a:9d:78:a2:9b:e0:de:62:a2:04:86:9f:ed:7c:a6: + 20:eb +-----BEGIN CERTIFICATE----- +MIIDBjCCAm+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCAyMB4XDTA5MTExODE1NTUz +OFoXDTM0MTExMjE1NTUzOFowaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCAyMIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDwehZMqwayryecfT+G2t56wwFnd1ZJCe3tMXKD6HWcTM75l7ZjPOLK +g4CSA5yW4t5yecHPPj+5DbSHx3XmVo2q+HdHEU7+B7AdZAZzS2/UrNoPBYex8Zip +9YqhqO0XnCa42pJj0lOH5vztRN6UVpA+oqFnCMs41M8XO37/epfAewIDAQABo4HH +MIHEMB0GA1UdDgQWBBSM8ywwouhiUHC8/HGgQfrgWLRNuDCBkQYDVR0jBIGJMIGG +gBRfvEza6woMtSNDXiQyJ3lB9YKjAqFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCAyggkAoq8ViexzVIYwDwYDVR0TAQH/ +BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBSgxarDkMts+QPbMFj1Ias5x7ue+6b +DP9P4FnV5CevaL+n9SqjyeMrjbcxJvYEgE7ypb/aY16M1sayRqBGEC+EnwJ288gz +BWIMXy3MBiNTn9n4RuQuXNoF/L/bRbSsjYu1S2B7eyY0f7FLQZZBJnB6nXiim+De +YqIEhp/tfKYg6w== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_2/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Root_2/demoCA/private/cakey.pem new file mode 100644 index 000000000..7ef7ef0a5 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_2/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,52B792B2B0E03BD6 + +GIFY+N2q5LMcrtTplZUToF0/nuplr7ASLAe7lEcDLTTHeBTO+w4ScB62Dl6veeEU +3/pPevG+V3HIA5ukywX334DuWjL3bFIsPg8a3NKKn0nTpmwqHqXZ53kbSMHIiu6v +MkvGeVLLxLhnCsqQ8HI2ccuxGSXLA0rqlnrZTOtvQpw9ohpCM3CX1GeekLc83bL/ +4HHmw8nNL+OCH4l9g3Y8XpN3ySRgl+lWmoKxl9s2Mn7jFoaqSXuuH3wIu9D2kJxS +qfVs/fo12j8RWXSIMpiCJFCOx1v+zzX7dJ0cyim83WF2OHsOW03UYnWzgk44iz4d +/WVWJuRU3gEwpN3CDdhzBZuYw9DmaG8HLHYT15CSdkQrfHeFM3Axcoju7b887JX7 +sOHU6h4ebMVhAswAXKGlTKOY2PO1GE9cKoa2jxnB2z8Dhe8rxzuvWyr5BfXrS3KT +lM6pjxZSoGMcmG7FtDgU/aAIn+DPR/rdB7tfZwP3GoVV+n3jRi8LU5I3wbi4z70o +bwXMb7zN13WHFszZgPX4tHD3jjyLwk7rFmMJ17L3K6eOAlGg8o+FBgoqYFQo05sY +2SElOibX8RIj9m9lerNLOxB5ty2VDUSaytJ0b1gPTXAdsaryq7tKFxIrNKpiJ1qk +snQSJyr2JwRqBLRwkXZV5CliWwZJGGJsC9I5fAMuuW6qkDhsSQ1fIJsGn/SbbiZj +lnZVY/33vHMltbwEgY4GuQWm29VYJwLWk925BY/nQ5fWPARYsap04JIwtperrZKj +XETzTrnTje6sVl32aCLdYlwsVbh04zRwUFharCz5vtDdVeHrfsBDKA== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Root_2/demoCA/serial b/xmlsecurity/test_docs/CAs/Root_2/demoCA/serial new file mode 100644 index 000000000..dd1172404 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_2/demoCA/serial @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Root_2/openssl.cfg b/xmlsecurity/test_docs/CAs/Root_2/openssl.cfg new file mode 100644 index 000000000..0dd15bd9e --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_2/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Root_3/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Root_3/demoCA/cacert.pem new file mode 100644 index 000000000..55be15521 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_3/demoCA/cacert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDBDCCAm2gAwIBAgIJAJVv8OMrvnb5MA0GCSqGSIb3DQEBBQUAMF8xCzAJBgNV +BAYTAkRFMRAwDgYDVQQIEwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9y +ZzEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgMzAeFw0wOTEx +MjAwNzM2MTVaFw0zNDExMTQwNzM2MTVaMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgMzCBnzANBgkqhkiG9w0BAQEFAAOBjQAw +gYkCgYEA3L6zaGhxFC+Mf55dzotmPKxdZndlxSVVOVI93JrxKVfn8mYOCZEjdb9Q +65vgLxGXMC9LCiF6SfT8dIfav1hUugmLaLzBesPu6h4kHN33/7Asj8BzY5I57uvF +sMLNL5hHFRRqtBqHvmO2G8zjHPluObnBzaQNCbdZxYODeh1GFpECAwEAAaOBxzCB +xDAdBgNVHQ4EFgQUaf8w7B80mmc6ayDS33/1BQTt+RwwgZEGA1UdIwSBiTCBhoAU +af8w7B80mmc6ayDS33/1BQTt+RyhY6RhMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgM4IJAJVv8OMrvnb5MA8GA1UdEwEB/wQF +MAMBAf8wDQYJKoZIhvcNAQEFBQADgYEABPdAJer/8FoOAMWszhfz/BEjF97TTFs1 +KqSEiuymswG706weo9tcnP8u81AITQPSWZE1ALQN5L35Zvg6ubJsNM3+VSoQ6hZj +G9oWAJzFN7DhIqs3Xb13eBH/0yqAdTuFB5uLcJdR3GIXGFvcU/5FZBpYnORVqvg4 +irKv2VvyCR0= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_3/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Root_3/demoCA/crlnumber new file mode 100644 index 000000000..dd1172404 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_3/demoCA/crlnumber @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Root_3/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Root_3/demoCA/index.txt new file mode 100644 index 000000000..dd9a47ee6 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_3/demoCA/index.txt @@ -0,0 +1 @@ +V 341114074039Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 1 Root 3 diff --git a/xmlsecurity/test_docs/CAs/Root_3/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Root_3/demoCA/index.txt.attr new file mode 100644 index 000000000..8f7e63a34 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_3/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Root_3/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Root_3/demoCA/newcerts/1000.pem new file mode 100644 index 000000000..c14880b58 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_3/demoCA/newcerts/1000.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 3 + Validity + Not Before: Nov 20 07:40:39 2009 GMT + Not After : Nov 14 07:40:39 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 3 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:9e:87:1f:af:f0:a0:1c:f4:9e:f8:c3:e7:ee:d3: + cb:a8:e2:54:98:ba:dd:7e:dc:6e:14:e1:7e:7f:5b: + 1e:ef:53:3d:89:76:ea:e2:b3:6c:08:0d:e8:c8:4d: + 24:40:ff:92:f3:5b:51:f7:90:ac:69:37:29:90:f5: + e8:95:6f:67:d1:10:cd:7b:dd:65:38:d6:25:ec:63: + 39:ba:2e:ea:13:58:8e:7a:82:8e:10:d1:7b:77:7a: + 08:d5:82:66:62:a4:83:39:ad:f5:83:d5:2f:5c:bc: + 23:6e:c8:78:8b:38:9f:eb:a3:67:ba:43:fa:e4:07: + 3f:90:72:db:0c:f9:49:0e:0d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 1B:2D:E0:A2:26:7F:0D:BA:38:7E:EC:06:81:81:0F:12:74:4C:5A:4D + X509v3 Authority Key Identifier: + keyid:69:FF:30:EC:1F:34:9A:67:3A:6B:20:D2:DF:7F:F5:05:04:ED:F9:1C + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 3 + serial:95:6F:F0:E3:2B:BE:76:F9 + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 6f:ac:53:9d:16:6e:95:ed:97:60:ed:c8:a8:96:ab:24:c5:1e: + d5:d7:26:98:fb:b5:aa:ef:da:a4:91:6a:82:55:ec:21:a2:08: + 24:c7:0c:a7:58:0c:06:69:3d:04:7d:08:f1:0b:77:41:ad:1c: + 13:c2:bd:17:c9:9e:ff:df:64:69:8b:58:f1:bc:40:bd:cf:e4: + 57:29:bc:5e:93:84:61:56:4c:e6:c1:3a:2c:6e:71:ea:5d:67: + c0:54:be:4f:2f:27:a8:59:8d:29:94:ba:c6:6c:ff:ed:25:3d: + 0b:fa:93:c9:45:f4:d5:a3:3d:be:8a:f1:9d:c4:92:d5:5c:d2: + 77:7c +-----BEGIN CERTIFICATE----- +MIIDBjCCAm+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCAzMB4XDTA5MTEyMDA3NDAz +OVoXDTM0MTExNDA3NDAzOVowaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCAzMIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQCehx+v8KAc9J74w+fu08uo4lSYut1+3G4U4X5/Wx7vUz2Jduris2wI +DejITSRA/5LzW1H3kKxpNymQ9eiVb2fREM173WU41iXsYzm6LuoTWI56go4Q0Xt3 +egjVgmZipIM5rfWD1S9cvCNuyHiLOJ/ro2e6Q/rkBz+QctsM+UkODQIDAQABo4HH +MIHEMB0GA1UdDgQWBBQbLeCiJn8Nujh+7AaBgQ8SdExaTTCBkQYDVR0jBIGJMIGG +gBRp/zDsHzSaZzprINLff/UFBO35HKFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCAzggkAlW/w4yu+dvkwDwYDVR0TAQH/ +BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBvrFOdFm6V7Zdg7ciolqskxR7V1yaY ++7Wq79qkkWqCVewhoggkxwynWAwGaT0EfQjxC3dBrRwTwr0XyZ7/32Rpi1jxvEC9 +z+RXKbxek4RhVkzmwTosbnHqXWfAVL5PLyeoWY0plLrGbP/tJT0L+pPJRfTVoz2+ +ivGdxJLVXNJ3fA== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_3/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Root_3/demoCA/private/cakey.pem new file mode 100644 index 000000000..445d86f99 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_3/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,24B61B9BC2D90894 + +pJUmVTVcjD3b4WKoSDJHrxHYOJ5/6P0FyQRYaJhnDXpcC5cQywl7yuD3HpRh3cXT +Y5k6d1E64St3I/IDImdbiEEDbjlSG9gfFf9vYeP/Xlpaja0Y9Q2ePnQvJY47HB7+ +qkrt6b+3yIW024wHi83dzaeYeNUJaY1jGsra2TzGk/+hYrf6yvnyehEAsy5WChof +bfaQ29RrGTlzf6IpSRpiHUL7nVl+eHfbGLX4Ih8aEFXpcnoWtpY8FgQ5+bJxMeR4 +R2ge0c3G0VIBXBRRUoGsU0ZcRLdxYUFcDGZse50ZboUwvROfPCimowcyWKluV9yj +l4+e3glYcwGHRqHYArsLDUV2hzHHEJ1IKn4E+oExqQSGgDQgUDN0kjlRPPxWQb29 +6dZSHW4VXW609Q10FKbPuCocgQ2Ut2bNGWqXsiNNTr39iB0r/hA/V4bKy3G8ogsH +AQFp6D9LaFlt9ZFA49Y4WoPzSY9J2C4eFJzQ+jhCpeapzQ54BWNTYMQe+SJHkp1O +PWVovUrRbTDesIUeY1UJuSnbDotOc6vzEAsP+FIL2qUySUGG/CPyAf3R4FyahwjL +bgU5kmpzBKsgqRYrO2yfLz5/3/e9xUGfHVi8lbI5f21NQKesqHY2xS2NmGvakzbe +ZvD3bhythAR5L0Pp+tiiHE1LUAbcKp90aFPeaONDpUtrRU21gqqvEKnnubCvnjmE +l6GrH2WKSgxJbQ3GGqNaDg1ivB8XXyjx7guvBzpA0Pe2YCYMa0RI27GywNkv+RsR +eo3ox2QhUpvPxUl3ijwOPN3EFXrq0gdlYQJBWW3GLlX4Q71KJF+jUQ== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Root_3/demoCA/serial b/xmlsecurity/test_docs/CAs/Root_3/demoCA/serial new file mode 100644 index 000000000..dd1172404 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_3/demoCA/serial @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Root_3/openssl.cfg b/xmlsecurity/test_docs/CAs/Root_3/openssl.cfg new file mode 100644 index 000000000..51e520525 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_3/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Root_4/README.txt b/xmlsecurity/test_docs/CAs/Root_4/README.txt new file mode 100644 index 000000000..b9fb278a2 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_4/README.txt @@ -0,0 +1,4 @@ +Revoked certificates: + +- Sub CA 2 Root 4 + diff --git a/xmlsecurity/test_docs/CAs/Root_4/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Root_4/demoCA/cacert.pem new file mode 100644 index 000000000..45b4ce8a5 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_4/demoCA/cacert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDBDCCAm2gAwIBAgIJAKKTRnQ7puOtMA0GCSqGSIb3DQEBBQUAMF8xCzAJBgNV +BAYTAkRFMRAwDgYDVQQIEwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9y +ZzEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgNDAeFw0wOTEx +MjAwODM1MDRaFw0zNDExMTQwODM1MDRaMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgNDCBnzANBgkqhkiG9w0BAQEFAAOBjQAw +gYkCgYEA2k+jPArotoY09an0BpF3RYIPP/5RN04E4S+Ulp/ipttaVxtAC0ojJSlp +0PGp/vIodFT9pkBb0nq56LHjFLj+lyW5tKAR+4B+VVvzwJhUBD8qHjYJE30vWZ88 +3+3I+GmXDzy962kQxrb4J6dBwGImoqhBTXWOxGnPjXxtovzYmMECAwEAAaOBxzCB +xDAdBgNVHQ4EFgQUuo2hl9zEOR+QtVFrEBnyRg2pZY4wgZEGA1UdIwSBiTCBhoAU +uo2hl9zEOR+QtVFrEBnyRg2pZY6hY6RhMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgNIIJAKKTRnQ7puOtMA8GA1UdEwEB/wQF +MAMBAf8wDQYJKoZIhvcNAQEFBQADgYEARdHX1KRJ/DE1zOkbjINPX4pFjTMIIfKd +ncEBM7Po20it75Hbl8bHoxwCrjOu+9L1xaTCWcunyqv26yrjVpORPHPODLMc2W8x +FQm39hL6a0RjqurDlhcrjor3HD7hQ+GjEUDAX6Pk9RDxN+uMHvF5/5WCEhSn2aLT +IozGu5SmZys= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_4/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Root_4/demoCA/crlnumber new file mode 100644 index 000000000..dd1172404 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_4/demoCA/crlnumber @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Root_4/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Root_4/demoCA/index.txt new file mode 100644 index 000000000..f07b3377d --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_4/demoCA/index.txt @@ -0,0 +1,2 @@ +V 341114083727Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 1 Root 4 +R 341114092227Z 091120092718Z,keyCompromise 1001 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 2 Root 4 diff --git a/xmlsecurity/test_docs/CAs/Root_4/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Root_4/demoCA/index.txt.attr new file mode 100644 index 000000000..8f7e63a34 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_4/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Root_4/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Root_4/demoCA/newcerts/1000.pem new file mode 100644 index 000000000..391037118 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_4/demoCA/newcerts/1000.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 4 + Validity + Not Before: Nov 20 08:37:27 2009 GMT + Not After : Nov 14 08:37:27 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 4 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:da:b0:21:94:89:b0:00:89:cb:69:59:9b:0d:fe: + 1f:b9:a0:a8:44:92:55:5f:0b:d5:e5:08:63:bd:47: + 6b:11:4d:b1:a8:12:6f:c1:cf:cb:9e:ae:e2:c1:03: + 68:46:59:0b:96:7c:21:45:9b:14:81:d8:f1:83:70: + 6b:3d:b4:56:65:49:87:1d:ab:e2:08:6a:49:66:0e: + 59:b4:da:7a:3f:72:23:b8:1f:fb:78:f5:f0:2d:c4: + fe:d9:94:6e:2e:c3:6e:95:ba:38:60:d1:0b:fa:16: + c7:02:71:ef:3e:71:72:63:26:56:35:1e:8b:ec:47: + 87:25:6e:bc:90:d0:8b:37:2d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 96:9A:2D:06:F6:76:4F:83:68:7B:9C:69:C4:18:BB:4A:EB:46:38:E4 + X509v3 Authority Key Identifier: + keyid:BA:8D:A1:97:DC:C4:39:1F:90:B5:51:6B:10:19:F2:46:0D:A9:65:8E + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 4 + serial:A2:93:46:74:3B:A6:E3:AD + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 45:77:ba:6b:b6:a7:2a:0f:6b:38:90:9f:0a:18:11:c7:54:7b: + c9:3b:9a:93:90:96:f0:04:0a:56:87:30:e0:f5:d8:84:40:39: + 90:85:ca:e7:38:1b:d8:df:2f:bd:73:91:13:cb:a6:c9:b0:7a: + f7:59:77:6b:9a:d5:86:78:06:dc:40:14:ce:ea:43:a8:ae:ed: + a2:03:64:51:3a:47:7a:9f:df:2d:65:49:56:a5:39:cf:28:2a: + ac:ab:fd:e1:93:fd:3e:56:e8:eb:7a:11:a8:f7:f9:1a:a1:83: + 1f:92:f7:da:4e:c6:d9:67:dd:67:ff:be:6f:e5:24:e1:6e:cc: + 94:3c +-----BEGIN CERTIFICATE----- +MIIDBjCCAm+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA0MB4XDTA5MTEyMDA4Mzcy +N1oXDTM0MTExNDA4MzcyN1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA0MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDasCGUibAAictpWZsN/h+5oKhEklVfC9XlCGO9R2sRTbGoEm/Bz8ue +ruLBA2hGWQuWfCFFmxSB2PGDcGs9tFZlSYcdq+IIaklmDlm02no/ciO4H/t49fAt +xP7ZlG4uw26Vujhg0Qv6FscCce8+cXJjJlY1HovsR4clbryQ0Is3LQIDAQABo4HH +MIHEMB0GA1UdDgQWBBSWmi0G9nZPg2h7nGnEGLtK60Y45DCBkQYDVR0jBIGJMIGG +gBS6jaGX3MQ5H5C1UWsQGfJGDalljqFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA0ggkAopNGdDum460wDwYDVR0TAQH/ +BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBFd7prtqcqD2s4kJ8KGBHHVHvJO5qT +kJbwBApWhzDg9diEQDmQhcrnOBvY3y+9c5ETy6bJsHr3WXdrmtWGeAbcQBTO6kOo +ru2iA2RROkd6n98tZUlWpTnPKCqsq/3hk/0+VujrehGo9/kaoYMfkvfaTsbZZ91n +/75v5SThbsyUPA== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_4/demoCA/newcerts/1001.pem b/xmlsecurity/test_docs/CAs/Root_4/demoCA/newcerts/1001.pem new file mode 100644 index 000000000..9d951ee26 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_4/demoCA/newcerts/1001.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4097 (0x1001) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 4 + Validity + Not Before: Nov 20 09:22:27 2009 GMT + Not After : Nov 14 09:22:27 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 2 Root 4 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:e5:8d:27:4e:09:53:08:61:c6:23:25:9e:dd:9c: + 07:bf:81:38:5c:5c:10:8f:e4:12:2f:4e:2e:b1:a1: + cf:21:46:53:bf:e8:5e:de:17:3a:9d:f7:e8:ef:3e: + 9c:b4:29:37:4c:31:35:15:dc:98:e0:93:9c:ce:6a: + d6:e1:35:19:6b:d4:1d:3b:81:86:b1:e7:ff:1f:b8: + 34:a9:f9:de:4d:b8:62:ac:3b:d4:58:8e:5c:76:b5: + 07:7f:32:8a:3a:90:73:71:d5:da:f1:79:39:14:ed: + 1b:f1:8a:3e:be:48:bc:07:ec:f9:7c:03:14:fc:e7: + 55:a3:65:81:c7:6c:70:0b:ff + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 69:DE:B6:99:C4:95:F7:5A:FA:41:6B:4C:F6:C3:6D:89:AA:37:31:9D + X509v3 Authority Key Identifier: + keyid:BA:8D:A1:97:DC:C4:39:1F:90:B5:51:6B:10:19:F2:46:0D:A9:65:8E + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 4 + serial:A2:93:46:74:3B:A6:E3:AD + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + bc:cf:43:eb:72:b1:71:a7:94:8e:cd:5b:fc:d8:21:31:83:db: + a9:de:c7:5b:14:e5:7b:90:43:e6:05:df:db:6e:95:5f:24:ac: + 0c:a1:8a:ac:c6:cf:f2:03:cd:a0:30:ae:d3:a9:41:07:c9:b1: + be:4b:e0:fc:a2:76:09:07:75:6a:fa:e4:2f:a3:3a:cd:81:68: + ab:f6:06:c4:32:08:25:6e:e8:e7:36:9c:1a:f7:42:73:f8:b0: + d8:42:3e:85:c2:11:23:10:d6:6a:e4:8f:53:cb:8b:8b:1b:5a: + 4d:6d:9d:34:45:26:52:d2:ee:6d:8f:23:ff:00:92:f5:99:62: + 4c:41 +-----BEGIN CERTIFICATE----- +MIIDBjCCAm+gAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA0MB4XDTA5MTEyMDA5MjIy +N1oXDTM0MTExNDA5MjIyN1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDIgUm9vdCA0MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDljSdOCVMIYcYjJZ7dnAe/gThcXBCP5BIvTi6xoc8hRlO/6F7eFzqd +9+jvPpy0KTdMMTUV3Jjgk5zOatbhNRlr1B07gYax5/8fuDSp+d5NuGKsO9RYjlx2 +tQd/Moo6kHNx1drxeTkU7Rvxij6+SLwH7Pl8AxT851WjZYHHbHAL/wIDAQABo4HH +MIHEMB0GA1UdDgQWBBRp3raZxJX3WvpBa0z2w22JqjcxnTCBkQYDVR0jBIGJMIGG +gBS6jaGX3MQ5H5C1UWsQGfJGDalljqFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA0ggkAopNGdDum460wDwYDVR0TAQH/ +BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQC8z0PrcrFxp5SOzVv82CExg9up3sdb +FOV7kEPmBd/bbpVfJKwMoYqsxs/yA82gMK7TqUEHybG+S+D8onYJB3Vq+uQvozrN +gWir9gbEMgglbujnNpwa90Jz+LDYQj6FwhEjENZq5I9Ty4uLG1pNbZ00RSZS0u5t +jyP/AJL1mWJMQQ== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_4/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Root_4/demoCA/private/cakey.pem new file mode 100644 index 000000000..003d2f3b5 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_4/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,26D3AA1ECCD64EF2 + +Smy62JNi1/1qKZI1q2lF13336vwJWfw+ii4g/ZwMJWuwTWUGXWZ1o9B9pZFo78KM +pMlasoCwAoI3lepMIwxtSRMgstxacJ4QRVPdevo7Qq6+++qNXdkqq9pYM19dsOiu +UNpbPXVvKQZnvm0ZFCjqiylvjCaQVQRScdwu9cJyq2qIQ1laXQoW2fPYBb8KSsCO +B5E76zAGdRlzEglT9Qkjbi2dQWxWpMHFfWZydFJnNbuh7O+RxCSOJN3jXlDRGPag +IwL4mFX8dElCwWhNpdd1pXF2ZXQ2S6Ke1MoOXRvJ7XVvEfnGyHpHQRdNB0M9gJCf +3ynJ0UUiCvXJs/6NEcOZzZ+R38XfMvsOcG1jNuh2KE5hW3cGbQMV2TPZMHjGE/qn +EhX+vzIOhRUPTUQjrjmV/lgioL4pMKFBXyfr2tkNLVOfzQtIXVfgxF1ooVmZFGKR +fAmHRbXKSrGWPJkX75bdlVnQ15qz5dU7PkIohGwGojOHuTWLXzKtOuLs7KMmH/i1 +5MhxcoXbI4R+hX/oj2Es4MKYFcSI0MID9Z5Se6z/yaz++5P9OrEGrXydg4W5YSuc +Q+MovUuqNoDH+Mo0z2P2DL4OxcIkBYoUVFOnIL2v5thRgbdWk05m0OBWYnvue9MG +CiuA49Lqg0H2ViZrDCyGDQNBkDkW7AKHYhVe3afHSDENX+wsgB1oj1bMvWNLQfCB +2IOYjv+of7tNOvIH6AuaJDqF2TYOm4ipcjSD/SEuKfrOgXlq6702tRhL4aAfHa6K +o1yrUfAxLwqN/TjSDNfOIUr5ro24tYnUaUnYPpn/zwZ5WfitZ4RGBg== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Root_4/demoCA/serial b/xmlsecurity/test_docs/CAs/Root_4/demoCA/serial new file mode 100644 index 000000000..7d802a3e7 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_4/demoCA/serial @@ -0,0 +1 @@ +1002 diff --git a/xmlsecurity/test_docs/CAs/Root_4/openssl.cfg b/xmlsecurity/test_docs/CAs/Root_4/openssl.cfg new file mode 100644 index 000000000..51e520525 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_4/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Root_5/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Root_5/demoCA/cacert.pem new file mode 100644 index 000000000..631deb24d --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_5/demoCA/cacert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDBDCCAm2gAwIBAgIJAPA9tqmpnKNOMA0GCSqGSIb3DQEBBQUAMF8xCzAJBgNV +BAYTAkRFMRAwDgYDVQQIEwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9y +ZzEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgNTAeFw0wOTEx +MjAxMDEwMzdaFw0zNDExMTQxMDEwMzdaMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgNTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw +gYkCgYEAwbqFK0+BWGylCl9gJj/eVuuNBcSgVetgx0cXwMRPHiwFZ8ilxPJm4kd0 +k2WDKHox5Ol8T0pU4n3fA5VmxjcfGnx03R8rFTn5deetrKQzyWUjz7EIl4mZYSvK +hwlbg5ZB4FJDYUoC/3eVHdQq2jUvRaQad1TvdBmvIMbDaYmTT3cCAwEAAaOBxzCB +xDAdBgNVHQ4EFgQUwdGg1FsLnX4xYfk5EJ8xEODSBrUwgZEGA1UdIwSBiTCBhoAU +wdGg1FsLnX4xYfk5EJ8xEODSBrWhY6RhMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgNYIJAPA9tqmpnKNOMA8GA1UdEwEB/wQF +MAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAeX2QYyrs9an5ObWjzauPCzr8hx6k8dF3 +YXU8f/JCf/fKG5u5WQZmmu0YZXMSaDyzqS3rKupDSm4kbfB9l9oTkgZszueI29pd +C/QIh8vUTiAlV5zxR4ypqmBg489W/uXdQPicuFhGFYX9EWjuGhwk8dL0dcUCufwX +UBYBlUiceFU= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_5/demoCA/crl/DO_NOT_CREATE_A_CRL b/xmlsecurity/test_docs/CAs/Root_5/demoCA/crl/DO_NOT_CREATE_A_CRL new file mode 100644 index 000000000..e69de29bb diff --git a/xmlsecurity/test_docs/CAs/Root_5/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Root_5/demoCA/crlnumber new file mode 100644 index 000000000..83b33d238 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_5/demoCA/crlnumber @@ -0,0 +1 @@ +1000 diff --git a/xmlsecurity/test_docs/CAs/Root_5/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Root_5/demoCA/index.txt new file mode 100644 index 000000000..d910b9acc --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_5/demoCA/index.txt @@ -0,0 +1 @@ +V 341114113023Z 1001 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 1 Root 5 diff --git a/xmlsecurity/test_docs/CAs/Root_5/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Root_5/demoCA/index.txt.attr new file mode 100644 index 000000000..8f7e63a34 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_5/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Root_5/demoCA/newcerts/1001.pem b/xmlsecurity/test_docs/CAs/Root_5/demoCA/newcerts/1001.pem new file mode 100644 index 000000000..b350f6eb3 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_5/demoCA/newcerts/1001.pem @@ -0,0 +1,66 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4097 (0x1001) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 5 + Validity + Not Before: Nov 20 11:30:23 2009 GMT + Not After : Nov 14 11:30:23 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 5 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:97:fa:a2:49:d3:bf:c1:2e:7a:ed:83:83:3c:78: + 96:c8:b2:b9:67:af:c0:5e:0a:89:89:fb:94:59:32: + a8:2a:e4:20:2f:3b:3d:ce:53:4f:72:fc:6c:0b:93: + 38:c3:df:66:6e:d5:79:d0:a4:4e:41:84:43:3c:99: + 79:0c:e0:5f:19:1a:3d:f5:4b:11:28:0f:80:b0:a0: + 71:34:5b:90:71:c2:ef:1e:85:2e:5b:9f:3b:22:c3: + 18:f8:7c:1f:ef:1b:78:17:a0:44:60:46:7e:88:eb: + a7:60:a0:5c:2a:7c:37:99:fa:27:97:08:e8:89:ba: + bc:69:4b:79:93:8f:ad:b5:9b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 01:E9:B5:99:E4:6D:F9:8C:42:3D:09:10:0F:A7:75:C6:27:78:4A:AF + X509v3 Authority Key Identifier: + keyid:C1:D1:A0:D4:5B:0B:9D:7E:31:61:F9:39:10:9F:31:10:E0:D2:06:B5 + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 5 + serial:F0:3D:B6:A9:A9:9C:A3:4E + + X509v3 CRL Distribution Points: + URI:http://localhost:8901/demoCA/crl/Root_5.crl + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 6d:ca:34:05:99:ff:99:49:d3:6d:9d:ad:c6:99:da:9d:6c:94: + 62:77:ed:1c:39:23:d2:e8:b6:3e:df:63:dc:7c:10:3f:c2:ed: + f4:04:26:58:05:01:4c:ed:a9:83:43:3a:5d:fe:60:6d:5b:58: + dc:93:8c:94:69:b6:7f:02:48:30:9c:31:f4:7d:de:e0:de:04: + d2:dc:79:b7:60:c2:87:f7:c7:92:a2:f5:86:a7:0c:70:3b:a3: + a7:35:11:cf:a4:28:21:aa:8b:24:50:2e:96:41:be:66:01:bd: + b9:ec:04:0c:92:d9:8a:e7:a0:96:24:9b:f1:a2:9f:59:59:4a: + 32:a4 +-----BEGIN CERTIFICATE----- +MIIDRjCCAq+gAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA1MB4XDTA5MTEyMDExMzAy +M1oXDTM0MTExNDExMzAyM1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA1MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQCX+qJJ07/BLnrtg4M8eJbIsrlnr8BeComJ+5RZMqgq5CAvOz3OU09y +/GwLkzjD32Zu1XnQpE5BhEM8mXkM4F8ZGj31SxEoD4CwoHE0W5Bxwu8ehS5bnzsi +wxj4fB/vG3gXoERgRn6I66dgoFwqfDeZ+ieXCOiJurxpS3mTj621mwIDAQABo4IB +BjCCAQIwHQYDVR0OBBYEFAHptZnkbfmMQj0JEA+ndcYneEqvMIGRBgNVHSMEgYkw +gYaAFMHRoNRbC51+MWH5ORCfMRDg0ga1oWOkYTBfMQswCQYDVQQGEwJERTEQMA4G +A1UECBMHSGFtYnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsT +C0RldmVsb3BtZW50MQ8wDQYDVQQDEwZSb290IDWCCQDwPbapqZyjTjA8BgNVHR8E +NTAzMDGgL6AthitodHRwOi8vbG9jYWxob3N0Ojg5MDEvZGVtb0NBL2NybC9Sb290 +XzUuY3JsMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAbco0BZn/ +mUnTbZ2txpnanWyUYnftHDkj0ui2Pt9j3HwQP8Lt9AQmWAUBTO2pg0M6Xf5gbVtY +3JOMlGm2fwJIMJwx9H3e4N4E0tx5t2DCh/fHkqL1hqcMcDujpzURz6QoIaqLJFAu +lkG+ZgG9uewEDJLZiuegliSb8aKfWVlKMqQ= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_5/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Root_5/demoCA/private/cakey.pem new file mode 100644 index 000000000..222320a9a --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_5/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,5F2D7F26BBEBD8FB + +qFyJ/G/DFwA+Kx3cVldc6bOMRbbduL7x5DBjCqS20YfoQoyvDcyel8FYz4/8CQ9d +kmb4nrM0Dj8/FgDiite2E8+qJV4U8OIBsXelFd8FWC8hB4z0DtwVxIAiM6mTMMcu +bWta3Lu5xrNvU/vosB967COztoYB5XLLQ/DrRPoV+tvJx0Le3zXLzceIj4PicuIk +/Mh5NVqN5a5blaV1/1JvcfOQLCI0rNebP3iAYhwCkKyu6WkpSNuHIw5gaMC6KXpq +ORPf3m+3/YKHLS9/tg+9CPQrRpyzLV/TOUduq6HFfzh9ZRXd04Dpn0P61JVCypYo +9u62lnNCAtreyvCUttzANLgujbgT9HNsjzKTAD2g+zjwQPgIS4epNm5LBPsQv15A +Vuw7CnNlLa8PxUxuDUjoW2YaGUR3PHNUz+TA1U0UFxlNK/lgeekIvmSvPjVyROOB +SxOH88yAZWe6pWioS3uzeg1kf1F5sj9u+KHPyikUe3nUBrS1cZSRtQczhlWWocgm +GtfwQSSVSwRtd7CWe/nQHuSJyrIJCbWFaDhnVXRhr+tyDpLtoeApCvefvel0p/AY +LTaRcno3zUxZS3G8Cv71hBPR8y5di5dAxBSfLgMYxwBD3UFO6CPkmiJteIhHska9 +FJqR98hfvF+0hwFnaFUTszDMGK1xV20MeTMhLAwSlttbuwtWMTourFKtS6t1SomB +JOTkpiVfojTSAJX40ExQgNtvY+7ayNUBLX9NIuIcOjFbQa1LNmGy9cOPQD49x067 +fALGA+V1KO7sFeUrunkpHncYoux5OThq3iDJ2tPfBmyhTQhOSzN38w== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Root_5/demoCA/serial b/xmlsecurity/test_docs/CAs/Root_5/demoCA/serial new file mode 100644 index 000000000..7d802a3e7 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_5/demoCA/serial @@ -0,0 +1 @@ +1002 diff --git a/xmlsecurity/test_docs/CAs/Root_5/openssl.cfg b/xmlsecurity/test_docs/CAs/Root_5/openssl.cfg new file mode 100644 index 000000000..0ea6df297 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_5/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Root_5.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Root_6/README.txt b/xmlsecurity/test_docs/CAs/Root_6/README.txt new file mode 100644 index 000000000..e49615a51 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_6/README.txt @@ -0,0 +1,5 @@ +To provide the CRL via HTTP run + +java -jar ../../tools/httpserv/dist/httpserv.jar -a 8901 + + diff --git a/xmlsecurity/test_docs/CAs/Root_6/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Root_6/demoCA/cacert.pem new file mode 100644 index 000000000..5a7fc185b --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_6/demoCA/cacert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDBDCCAm2gAwIBAgIJANhqTyT5yZQnMA0GCSqGSIb3DQEBBQUAMF8xCzAJBgNV +BAYTAkRFMRAwDgYDVQQIEwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9y +ZzEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgNjAeFw0wOTEx +MjAxMjI2MDFaFw0zNDExMTQxMjI2MDFaMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgNjCBnzANBgkqhkiG9w0BAQEFAAOBjQAw +gYkCgYEAslt6KM0bikDy8n0lNMeaNQiZk9Pcfsf6Vaasn9A8FABFn1chxV5zOMag +jo6CyZG1CNLhA841RtgiWVMc8BA+pDKzOQAzfgSk4VjXaY8nYgKEmGDKuNvls+kE +OKMkJibh/scNMDUOx8Bnc6S9LyYJAhZFrxm/lgmoIo7QMcdseIsCAwEAAaOBxzCB +xDAdBgNVHQ4EFgQUrCVem7W6TY69d7Kd2eKErnoxj/IwgZEGA1UdIwSBiTCBhoAU +rCVem7W6TY69d7Kd2eKErnoxj/KhY6RhMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgNoIJANhqTyT5yZQnMA8GA1UdEwEB/wQF +MAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAU6Sjyeo650mhSGK8JJBhDroVJgAryVF4 +wXEKWxK0yuO0TVZJxUWeHOESpegBW1eP5m9Pz0IHnxj6MsGBYq7SZU84awt4HJto +6O1ARZYfT9r+qTts33I/VVQVTJbvETF1vGsuAZfTTDhAJDqS2oueiPDSinzQxNMy +16L4Rajm8LE= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_6/demoCA/crl/DO_NOT_INSTALL_THIS_CRL b/xmlsecurity/test_docs/CAs/Root_6/demoCA/crl/DO_NOT_INSTALL_THIS_CRL new file mode 100644 index 000000000..e69de29bb 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 000000000..df6dcb21e 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 000000000..dd1172404 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_6/demoCA/crlnumber @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Root_6/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Root_6/demoCA/index.txt new file mode 100644 index 000000000..7f0df0d95 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_6/demoCA/index.txt @@ -0,0 +1 @@ +V 341114122807Z 1001 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 1 Root 6 diff --git a/xmlsecurity/test_docs/CAs/Root_6/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Root_6/demoCA/index.txt.attr new file mode 100644 index 000000000..8f7e63a34 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_6/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Root_6/demoCA/newcerts/1001.pem b/xmlsecurity/test_docs/CAs/Root_6/demoCA/newcerts/1001.pem new file mode 100644 index 000000000..0490b88cd --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_6/demoCA/newcerts/1001.pem @@ -0,0 +1,66 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4097 (0x1001) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 6 + Validity + Not Before: Nov 20 12:28:07 2009 GMT + Not After : Nov 14 12:28:07 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 6 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:c4:d9:ab:27:06:66:41:0e:36:ff:d4:b1:d0:8c: + f7:b4:25:55:cd:fd:fa:a4:5a:e6:4f:d0:05:dc:a3: + e5:bd:8d:53:77:d1:ea:95:5a:52:81:c8:b6:36:a0: + 5f:3a:e1:85:1e:8a:48:91:7d:29:78:ff:ea:c5:e3: + ad:c4:27:d5:b7:8f:59:20:26:d4:45:87:6a:56:db: + ac:f5:f8:0a:88:82:9e:c2:00:06:fc:98:8a:fe:35: + c3:02:a1:67:08:06:42:e3:88:48:e0:8f:33:ff:f8: + a4:87:1a:3a:d9:54:0e:1c:09:3e:a0:f0:70:cd:b5: + b0:b2:7e:07:73:ad:20:64:69 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 89:8C:D7:71:EB:67:78:4E:D6:01:35:B2:AC:A1:B4:88:43:CE:70:A7 + X509v3 Authority Key Identifier: + keyid:AC:25:5E:9B:B5:BA:4D:8E:BD:77:B2:9D:D9:E2:84:AE:7A:31:8F:F2 + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 6 + serial:D8:6A:4F:24:F9:C9:94:27 + + X509v3 CRL Distribution Points: + URI:http://localhost:8901/demoCA/crl/Root_6.crl + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 55:5b:3b:6b:8a:d0:1b:d8:19:d9:96:85:4d:b4:a0:98:b1:bd: + 9f:0b:62:21:92:8b:4e:d3:d0:1b:91:3d:e3:f5:bd:ce:16:57: + fc:b7:84:15:51:fd:98:ab:32:59:28:0b:44:57:49:ec:ac:11: + 67:26:7a:a3:c5:b8:9d:2a:de:b6:7c:76:0a:e9:18:9f:98:87: + e8:80:c8:72:99:56:74:ab:73:1b:f4:e7:b9:b1:3a:f3:7b:0d: + 2f:5d:82:6c:d1:99:9f:23:be:23:fb:4c:0e:15:5e:f5:9f:90: + 88:d7:51:3a:6a:7a:f0:54:a5:c4:89:a5:0d:0a:4e:94:59:64: + 59:54 +-----BEGIN CERTIFICATE----- +MIIDRjCCAq+gAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA2MB4XDTA5MTEyMDEyMjgw +N1oXDTM0MTExNDEyMjgwN1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA2MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDE2asnBmZBDjb/1LHQjPe0JVXN/fqkWuZP0AXco+W9jVN30eqVWlKB +yLY2oF864YUeikiRfSl4/+rF463EJ9W3j1kgJtRFh2pW26z1+AqIgp7CAAb8mIr+ +NcMCoWcIBkLjiEjgjzP/+KSHGjrZVA4cCT6g8HDNtbCyfgdzrSBkaQIDAQABo4IB +BjCCAQIwHQYDVR0OBBYEFImM13HrZ3hO1gE1sqyhtIhDznCnMIGRBgNVHSMEgYkw +gYaAFKwlXpu1uk2OvXeyndnihK56MY/yoWOkYTBfMQswCQYDVQQGEwJERTEQMA4G +A1UECBMHSGFtYnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsT +C0RldmVsb3BtZW50MQ8wDQYDVQQDEwZSb290IDaCCQDYak8k+cmUJzA8BgNVHR8E +NTAzMDGgL6AthitodHRwOi8vbG9jYWxob3N0Ojg5MDEvZGVtb0NBL2NybC9Sb290 +XzYuY3JsMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAVVs7a4rQ +G9gZ2ZaFTbSgmLG9nwtiIZKLTtPQG5E94/W9zhZX/LeEFVH9mKsyWSgLRFdJ7KwR +ZyZ6o8W4nSretnx2CukYn5iH6IDIcplWdKtzG/TnubE683sNL12CbNGZnyO+I/tM +DhVe9Z+QiNdROmp68FSlxImlDQpOlFlkWVQ= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_6/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Root_6/demoCA/private/cakey.pem new file mode 100644 index 000000000..166be0166 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_6/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,BADC417CBCEF5888 + +5vIfuyyd2rgqSPUElPa2YM8on+FeoYuAIB+mfVHy0nSGisUKjmQQACaeTVD+aO6S +UFBz3W/RJXCj/8x5+ZYa8Rj44DeSwlDrxSy5VBrWegOzujfGPqrzwCL/ASKGPPFN +RwK0i0niJsj6+oQOGgP6AIb08reX1tkT0GItwQMjIQAFETcDP8m1sA1kFpLhvBCF +dHyw0lfnh+NZ9nnpAdpVXwt8teccLUyEHARNscebg8vqjc2gRxi3KpT3pURg0dUc +eaGH8DIB5CuAYW2Mo1LLRQ0uvkFgSl56WcolYiRTy2KUMW7Gz7oBA5Qyb9lz25yV +9djt4Hrs9cI1p1TGmvSklGPKJUaTf0Yrf0XRkS6xknFVX4zzkbD4vYFelITSxeMT +pPVbjLSWiIo+mqBuW6i+LUNMt45b1RWM96pomrPRrGne4saJOkhVXTvv/pR4KB+S +J2iwlEDNOwzkxeqSB7lJuzIce/iUqERAzlXe8e0VVgy0P0UfOIViLWS98cuqR86H +P1rMYtWilAkLKBUYo+lS7f/3YD8E3V10XdBmYJFvmpHPXM2SP5HQZXtoNCXJNcvB +aAlb3c7InxfqLLn+kH6WgPzXXcXO7cxlZ3cXBbJf3IhRT3aBEnAH+s+DDCi0RCII +UiLOnrgfOEZuNyRhGin9R7WFRtnGYJjHTP54FMOY0f0Rj7ElT+xymeAZE8wyXKfi +MWDgswTYYkcC7uPJAJ8HnLtFixr9aEriug7yemGyr686oX8gLPdwrYwPYJBt7Q+b +0nf22SoMqMNWSCWcr89sc1AIb0ebX+FxtsN6j45ztEjZGjXYkk2iXQ== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Root_6/demoCA/serial b/xmlsecurity/test_docs/CAs/Root_6/demoCA/serial new file mode 100644 index 000000000..7d802a3e7 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_6/demoCA/serial @@ -0,0 +1 @@ +1002 diff --git a/xmlsecurity/test_docs/CAs/Root_6/openssl.cfg b/xmlsecurity/test_docs/CAs/Root_6/openssl.cfg new file mode 100644 index 000000000..f49c11090 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_6/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Root_6.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Root_7/README.txt b/xmlsecurity/test_docs/CAs/Root_7/README.txt new file mode 100644 index 000000000..056f1b133 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_7/README.txt @@ -0,0 +1,10 @@ +Revoked certificates: + +- Sub CA 2 Root 7 + + +To provide the CRL via HTTP run + +java -jar ../../tools/httpserv/dist/httpserv.jar -a 8901 + + diff --git a/xmlsecurity/test_docs/CAs/Root_7/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Root_7/demoCA/cacert.pem new file mode 100644 index 000000000..01761f55b --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_7/demoCA/cacert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDBDCCAm2gAwIBAgIJANXmY18YCYKJMA0GCSqGSIb3DQEBBQUAMF8xCzAJBgNV +BAYTAkRFMRAwDgYDVQQIEwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9y +ZzEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgNzAeFw0wOTEx +MjAxMzA0NDhaFw0zNDExMTQxMzA0NDhaMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgNzCBnzANBgkqhkiG9w0BAQEFAAOBjQAw +gYkCgYEAvG//bRySIKOz1hmmH6qx02wtf2ZO2skK/wxPnTAd+LLuH2upOfGkaFCi +hd1zsIshs9/TjtLNa4nplkYSvZlYBsbpIuNQZrEedbvLYV/zNdsnLfht+aX3yMuk +q1dh2BI0LdwXiyMyPwATJwQ96AXq/a+cZi1ZRBToCztZArJK/xMCAwEAAaOBxzCB +xDAdBgNVHQ4EFgQUgMb4C198SeSG/ciSxoBw2cBve94wgZEGA1UdIwSBiTCBhoAU +gMb4C198SeSG/ciSxoBw2cBve96hY6RhMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgN4IJANXmY18YCYKJMA8GA1UdEwEB/wQF +MAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAg15QATKSYmz+XGtnBLDnWu2Gk59nglH4 +gG3p1xiVVgOyQVGsvNr+3ETPTTcf6x+ap1+AHE9SJJ0/WQSuUHtOv6y/prp4MWbw +/QBL2WHS7adTFWxOJ/VWpb8GhTtJdG9PKYeSmVAtC1qzdI1zsjPYvHO3UJnokDkB +fY7kpaTJprg= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_7/demoCA/crl/DO_NOT_INSTALL_THIS_CRL b/xmlsecurity/test_docs/CAs/Root_7/demoCA/crl/DO_NOT_INSTALL_THIS_CRL new file mode 100644 index 000000000..e69de29bb 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 000000000..0eefbda68 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 000000000..dd1172404 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_7/demoCA/crlnumber @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Root_7/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Root_7/demoCA/index.txt new file mode 100644 index 000000000..24c353872 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_7/demoCA/index.txt @@ -0,0 +1,2 @@ +V 341114130753Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 1 Root 7 +R 341114133506Z 091120133621Z,keyCompromise 1001 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 2 Root 7 diff --git a/xmlsecurity/test_docs/CAs/Root_7/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Root_7/demoCA/index.txt.attr new file mode 100644 index 000000000..8f7e63a34 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_7/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Root_7/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Root_7/demoCA/newcerts/1000.pem new file mode 100644 index 000000000..2dda8f2b2 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_7/demoCA/newcerts/1000.pem @@ -0,0 +1,66 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 7 + Validity + Not Before: Nov 20 13:07:53 2009 GMT + Not After : Nov 14 13:07:53 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 7 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:b0:ae:6d:0a:21:ae:8a:92:b1:16:25:d3:08:cb: + ac:b7:4c:53:6d:4b:b3:12:82:40:54:c9:44:28:fc: + 4e:10:e6:65:40:de:70:5d:8b:ab:1f:5c:77:03:43: + 3d:3a:3d:9e:f7:37:66:9a:33:68:a0:cf:ad:8f:f4: + fb:9c:a3:87:57:5d:ec:d6:55:5a:18:b5:e1:2b:d2: + c4:10:fe:f0:01:a5:da:29:ee:c4:af:15:c9:8c:dc: + 7c:45:84:bd:e5:5b:09:1f:16:1d:11:e7:61:e6:22: + e7:1f:c8:86:bf:a1:da:cb:fe:6b:7e:c0:6e:aa:7f: + 97:84:e8:8f:81:69:f1:26:87 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 54:64:15:7E:93:8A:19:C8:F9:B7:EF:60:A0:DF:5C:C8:15:56:C0:EE + X509v3 Authority Key Identifier: + keyid:80:C6:F8:0B:5F:7C:49:E4:86:FD:C8:92:C6:80:70:D9:C0:6F:7B:DE + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 7 + serial:D5:E6:63:5F:18:09:82:89 + + X509v3 CRL Distribution Points: + URI:http://localhost:8901/demoCA/crl/Root_7.crl + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 1a:bc:5a:4b:9a:d5:e8:c0:35:c2:61:0a:58:7d:33:e2:87:01: + 61:83:80:42:8d:1a:7e:b1:9a:58:d5:01:fd:e7:ae:5c:c8:65: + fb:9e:1d:bf:49:ba:ed:40:f4:05:7c:3b:2d:db:0e:53:d0:05: + a0:bd:15:87:c4:37:22:0b:a0:04:a3:ad:cb:57:b2:00:97:ee: + 8f:89:91:8e:7d:0b:e2:27:96:6e:0f:ab:73:33:59:fa:9f:37: + f2:77:79:99:af:72:ad:f9:49:05:ed:55:08:31:eb:97:0f:99: + 6e:9c:a3:df:f0:52:1a:14:4e:78:25:0c:8b:02:cb:56:e9:4d: + f5:9f +-----BEGIN CERTIFICATE----- +MIIDRjCCAq+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA3MB4XDTA5MTEyMDEzMDc1 +M1oXDTM0MTExNDEzMDc1M1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA3MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQCwrm0KIa6KkrEWJdMIy6y3TFNtS7MSgkBUyUQo/E4Q5mVA3nBdi6sf +XHcDQz06PZ73N2aaM2igz62P9Puco4dXXezWVVoYteEr0sQQ/vABpdop7sSvFcmM +3HxFhL3lWwkfFh0R52HmIucfyIa/odrL/mt+wG6qf5eE6I+BafEmhwIDAQABo4IB +BjCCAQIwHQYDVR0OBBYEFFRkFX6TihnI+bfvYKDfXMgVVsDuMIGRBgNVHSMEgYkw +gYaAFIDG+AtffEnkhv3IksaAcNnAb3veoWOkYTBfMQswCQYDVQQGEwJERTEQMA4G +A1UECBMHSGFtYnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsT +C0RldmVsb3BtZW50MQ8wDQYDVQQDEwZSb290IDeCCQDV5mNfGAmCiTA8BgNVHR8E +NTAzMDGgL6AthitodHRwOi8vbG9jYWxob3N0Ojg5MDEvZGVtb0NBL2NybC9Sb290 +XzcuY3JsMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAGrxaS5rV +6MA1wmEKWH0z4ocBYYOAQo0afrGaWNUB/eeuXMhl+54dv0m67UD0BXw7LdsOU9AF +oL0Vh8Q3IgugBKOty1eyAJfuj4mRjn0L4ieWbg+rczNZ+p838nd5ma9yrflJBe1V +CDHrlw+Zbpyj3/BSGhROeCUMiwLLVulN9Z8= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_7/demoCA/newcerts/1001.pem b/xmlsecurity/test_docs/CAs/Root_7/demoCA/newcerts/1001.pem new file mode 100644 index 000000000..0d2a0f02a --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_7/demoCA/newcerts/1001.pem @@ -0,0 +1,66 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4097 (0x1001) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 7 + Validity + Not Before: Nov 20 13:35:06 2009 GMT + Not After : Nov 14 13:35:06 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 2 Root 7 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:f9:3f:5e:76:52:9a:ce:5d:98:b0:00:d8:e0:65: + e7:78:11:4c:7b:c7:e2:d3:44:bf:8e:60:42:69:3e: + 75:67:65:24:ab:f7:07:d8:9d:be:0f:23:b5:c1:26: + 00:6b:c3:22:84:72:a9:96:dc:5f:63:fc:f5:e0:e3: + cc:da:0c:74:e9:31:51:91:89:27:8f:e5:17:41:6e: + 3d:5e:2a:13:cd:08:f7:f3:61:34:a1:f7:79:c6:bd: + 5d:2c:34:01:ea:5a:8c:48:97:36:d6:57:e0:80:03: + 2e:7a:03:83:4c:bd:b4:af:a2:fd:d7:4b:1a:f7:ab: + 9f:5a:22:2b:d1:25:73:dd:6f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 3B:50:26:45:6C:E2:FE:28:B1:71:0A:A8:95:2D:78:63:8E:2C:48:92 + X509v3 Authority Key Identifier: + keyid:80:C6:F8:0B:5F:7C:49:E4:86:FD:C8:92:C6:80:70:D9:C0:6F:7B:DE + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 7 + serial:D5:E6:63:5F:18:09:82:89 + + X509v3 CRL Distribution Points: + URI:http://localhost:8901/demoCA/crl/Root_7.crl + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 5f:b4:70:11:4f:d9:df:6a:6a:5a:4a:97:fe:8b:5d:9e:46:84: + e2:27:67:41:7c:a9:2e:9d:77:cc:e4:8c:d6:16:3c:39:7d:51: + 29:60:80:32:4f:a1:d0:b4:7f:2a:e5:60:f4:b8:d3:3b:94:f8: + a5:fb:15:99:cf:a9:c5:a7:59:c1:11:89:67:11:9c:ff:a9:ac: + dd:ca:a9:92:a8:60:26:c3:ab:74:41:86:b9:4d:1e:4a:c5:de: + 63:e6:da:2a:36:39:7b:6c:66:f3:20:57:d1:f1:36:4b:69:c5: + 04:a3:1f:cf:de:0c:10:d0:3f:07:e2:8e:0f:cd:41:26:c9:2e: + e9:1b +-----BEGIN CERTIFICATE----- +MIIDRjCCAq+gAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA3MB4XDTA5MTEyMDEzMzUw +NloXDTM0MTExNDEzMzUwNlowaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDIgUm9vdCA3MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQD5P152UprOXZiwANjgZed4EUx7x+LTRL+OYEJpPnVnZSSr9wfYnb4P +I7XBJgBrwyKEcqmW3F9j/PXg48zaDHTpMVGRiSeP5RdBbj1eKhPNCPfzYTSh93nG +vV0sNAHqWoxIlzbWV+CAAy56A4NMvbSvov3XSxr3q59aIivRJXPdbwIDAQABo4IB +BjCCAQIwHQYDVR0OBBYEFDtQJkVs4v4osXEKqJUteGOOLEiSMIGRBgNVHSMEgYkw +gYaAFIDG+AtffEnkhv3IksaAcNnAb3veoWOkYTBfMQswCQYDVQQGEwJERTEQMA4G +A1UECBMHSGFtYnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsT +C0RldmVsb3BtZW50MQ8wDQYDVQQDEwZSb290IDeCCQDV5mNfGAmCiTA8BgNVHR8E +NTAzMDGgL6AthitodHRwOi8vbG9jYWxob3N0Ojg5MDEvZGVtb0NBL2NybC9Sb290 +XzcuY3JsMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAX7RwEU/Z +32pqWkqX/otdnkaE4idnQXypLp13zOSM1hY8OX1RKWCAMk+h0LR/KuVg9LjTO5T4 +pfsVmc+pxadZwRGJZxGc/6ms3cqpkqhgJsOrdEGGuU0eSsXeY+baKjY5e2xm8yBX +0fE2S2nFBKMfz94MENA/B+KOD81BJsku6Rs= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_7/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Root_7/demoCA/private/cakey.pem new file mode 100644 index 000000000..147ca4e9b --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_7/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,B17A06040862AC63 + +9VJMswLGoelYtmpO17/f34Lb7j1I2vaK+RUg7fH09M6rQKurA2SmpsO7kJo7lMUb +lwXEC8+JC5b3OoUcPeHLkZ5e9bB+flMJQq+bkzWs4NWYI17gRs2Tc74xm04XRTsO +OYU+H7uOyRMAuS86hkQF13H3hCHcZkg8RZcvqfDXhsY8S7iyp0gErQv8IDmbIije +R7go3NdZXCmkuINKhhABFYnPxnEpaHxhIMNKykbSn+jby02LX57X/u4JDGfkzjCH +wyJMi9PiO7VbXvi8IPYnFz0IaCMVr5cltTh47/KiqACeAADQ6ETekrX9r7lngkRz +sqFuyqEtdi02ujElsGIaDCImQ5KbD2u2IQ3FX2b6Jwmd/uDmqQQwtEfarEoUxich +chCEUBGAiqRxLcrnRzjT+Reqgx7qGNurjP78kmKeD91hDm3tEHeWtecy4iA3C8z0 +aMZFOZLx1r7kf5/YaRMREcLPmreEWgFmkIMN004GdIvOwlsUjmAM7UMle+cef17v +h1hxbFsznzYLBk0zOYjmsTpI3dQHtxSUVsyUWXXVJ0Y4YhJSjMHlMOOCanGYOpGS +vipUNzLx4aIWfMmQdJePQM4uxO2FNwTc1IGyRpoOhj6vxroICuGK3WkxqZsN3VwR +hwNol0cNMNHbVacKvhh5PQJcmWiqmLEXaQD8VWgCNQVa0otS59vj+SeyW4ZvULBM +Od/9FhFfEBHQDxNSL+c6B/dXFIO1oY159ErdElAn+NPRtQcHAsnu8HknKLhry1NP +b4d+KZcTZAq9q97ltRQf9/hXBpA3ophMtbBFnnnh5WJuMMdDMNgGsg== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Root_7/demoCA/serial b/xmlsecurity/test_docs/CAs/Root_7/demoCA/serial new file mode 100644 index 000000000..7d802a3e7 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_7/demoCA/serial @@ -0,0 +1 @@ +1002 diff --git a/xmlsecurity/test_docs/CAs/Root_7/openssl.cfg b/xmlsecurity/test_docs/CAs/Root_7/openssl.cfg new file mode 100644 index 000000000..f2615bef4 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_7/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Root_7.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Root_8/README.txt b/xmlsecurity/test_docs/CAs/Root_8/README.txt new file mode 100644 index 000000000..d749d8ebc --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_8/README.txt @@ -0,0 +1,9 @@ +Revoked certificates: + +- Sub CA 2 Root 8 + + +Start the OCSP responder: +openssl ocsp -index demoCA/index.txt -port 8888 -rsigner demoCA/cacert.pem -rkey demoCA/private/cakey.pem -CA demoCA/cacert.pem -text + + diff --git a/xmlsecurity/test_docs/CAs/Root_8/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Root_8/demoCA/cacert.pem new file mode 100644 index 000000000..ef431ec95 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_8/demoCA/cacert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDBDCCAm2gAwIBAgIJALJH3moqTIMZMA0GCSqGSIb3DQEBBQUAMF8xCzAJBgNV +BAYTAkRFMRAwDgYDVQQIEwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9y +ZzEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgODAeFw0wOTEx +MjAxNTI4NTZaFw0zNDExMTQxNTI4NTZaMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgODCBnzANBgkqhkiG9w0BAQEFAAOBjQAw +gYkCgYEAmR4R07C/I8zEPsAEQdc/nzH74hLjEwImtiWKL8nVc70fwquIRzWLaavm +DaQE3g/ha00d2hepB2dUiR1nV2GhMYdV64eq1utEPU+tTIYpx163axOGLYLWwKc3 +cBaR2mCqZmAkS+WABHkCX9hsBn+Ju/XNxLDVcpBohVrx882+3kMCAwEAAaOBxzCB +xDAdBgNVHQ4EFgQU1mZ2yQX/qVCIlmDd+8cwGHJnQRkwgZEGA1UdIwSBiTCBhoAU +1mZ2yQX/qVCIlmDd+8cwGHJnQRmhY6RhMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgOIIJALJH3moqTIMZMA8GA1UdEwEB/wQF +MAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAfZylT15q6Dnpvf9jWoCovzvUoBqAwL1Z +UDEikhCpajYsrfXI3MRvKYkTvt18lgg2Y09gJ2vhfLBCaDp+ELUq0Vc5hIbblGGO +EA4vBuH5Yfho3AK3gKAtk7Rc9l/qP2rBPb1JVw79pRaz95IkYGeOp35pVDQfBN+i +jji5JSyOeYQ= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_8/demoCA/crl/DO_NOT_INSTALL_THIS_CRL b/xmlsecurity/test_docs/CAs/Root_8/demoCA/crl/DO_NOT_INSTALL_THIS_CRL new file mode 100644 index 000000000..e69de29bb 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 000000000..8f91a1949 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 000000000..dd1172404 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_8/demoCA/crlnumber @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Root_8/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Root_8/demoCA/index.txt new file mode 100644 index 000000000..831cbf1a3 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_8/demoCA/index.txt @@ -0,0 +1,2 @@ +V 341114153321Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 1 Root 8 +R 341114155533Z 091120155655Z,superseded 1001 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 2 Root 8 diff --git a/xmlsecurity/test_docs/CAs/Root_8/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Root_8/demoCA/index.txt.attr new file mode 100644 index 000000000..8f7e63a34 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_8/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Root_8/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Root_8/demoCA/newcerts/1000.pem new file mode 100644 index 000000000..b2d1deb75 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_8/demoCA/newcerts/1000.pem @@ -0,0 +1,66 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 8 + Validity + Not Before: Nov 20 15:33:21 2009 GMT + Not After : Nov 14 15:33:21 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 8 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:96:79:01:9f:4f:68:c1:09:0d:44:3a:82:e4:eb: + ad:70:7a:cf:b9:71:e5:fb:e0:c8:0c:21:79:3e:cb: + 78:91:7f:4a:a0:de:3e:37:0f:a1:6b:73:10:12:9b: + 08:c4:96:dc:cb:a8:5b:87:9b:75:24:e4:00:5e:4a: + 6f:4c:13:79:1f:57:13:8c:3e:1b:38:31:e1:77:74: + 52:f9:94:47:36:57:33:bd:de:08:11:a3:01:e1:53: + 1c:bd:7b:39:9c:5e:96:5c:a9:61:6c:cc:2b:90:8d: + 5a:3c:9e:f4:4b:6e:e5:97:64:86:f3:8e:e8:72:20: + 5d:0d:50:bf:e9:cf:be:d4:13 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + EF:BD:C8:8E:78:79:F9:76:4B:11:59:B6:C3:32:10:07:C0:BC:E3:8A + X509v3 Authority Key Identifier: + keyid:D6:66:76:C9:05:FF:A9:50:88:96:60:DD:FB:C7:30:18:72:67:41:19 + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 8 + serial:B2:47:DE:6A:2A:4C:83:19 + + Authority Information Access: + OCSP - URI:http://localhost:8888 + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 4c:95:44:3b:57:08:ec:01:ec:f9:3e:7c:89:1c:30:b1:4e:26: + 32:b6:57:fa:25:bc:ed:eb:d4:a2:1c:67:ee:b9:8b:d0:4c:57: + 8a:0e:db:a0:9d:92:e7:de:c6:73:01:e7:de:61:1b:b5:0e:d0: + c5:c1:a7:a6:ab:e0:c6:0b:51:dd:e5:a2:32:1f:c6:52:ea:d3: + 03:68:3a:f5:92:bd:8b:b8:03:bb:50:70:63:cc:ec:ed:3c:11: + 76:ca:ac:72:47:ad:99:6b:8e:07:9e:38:f2:63:e1:ba:d4:df: + a9:73:54:1d:74:89:94:01:2e:68:dd:97:e7:53:f9:cf:b6:7d: + fc:87 +-----BEGIN CERTIFICATE----- +MIIDOTCCAqKgAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA4MB4XDTA5MTEyMDE1MzMy +MVoXDTM0MTExNDE1MzMyMVowaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA4MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQCWeQGfT2jBCQ1EOoLk661wes+5ceX74MgMIXk+y3iRf0qg3j43D6Fr +cxASmwjEltzLqFuHm3Uk5ABeSm9ME3kfVxOMPhs4MeF3dFL5lEc2VzO93ggRowHh +Uxy9ezmcXpZcqWFszCuQjVo8nvRLbuWXZIbzjuhyIF0NUL/pz77UEwIDAQABo4H6 +MIH3MB0GA1UdDgQWBBTvvciOeHn5dksRWbbDMhAHwLzjijCBkQYDVR0jBIGJMIGG +gBTWZnbJBf+pUIiWYN37xzAYcmdBGaFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA4ggkAskfeaipMgxkwMQYIKwYBBQUH +AQEEJTAjMCEGCCsGAQUFBzABhhVodHRwOi8vbG9jYWxob3N0Ojg4ODgwDwYDVR0T +AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBMlUQ7VwjsAez5PnyJHDCxTiYy +tlf6Jbzt69SiHGfuuYvQTFeKDtugnZLn3sZzAefeYRu1DtDFwaemq+DGC1Hd5aIy +H8ZS6tMDaDr1kr2LuAO7UHBjzOztPBF2yqxyR62Za44HnjjyY+G61N+pc1QddImU +AS5o3ZfnU/nPtn38hw== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_8/demoCA/newcerts/1001.pem b/xmlsecurity/test_docs/CAs/Root_8/demoCA/newcerts/1001.pem new file mode 100644 index 000000000..26368962e --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_8/demoCA/newcerts/1001.pem @@ -0,0 +1,66 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4097 (0x1001) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 8 + Validity + Not Before: Nov 20 15:55:33 2009 GMT + Not After : Nov 14 15:55:33 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 2 Root 8 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:e9:91:38:d8:c1:36:e5:c1:d0:32:e8:ae:02:11: + 97:e5:c5:07:8f:5b:46:3a:3c:d9:49:5e:9a:4b:51: + 4c:b7:7d:e9:d1:4f:a7:15:8c:c6:10:f6:fa:5f:a9: + 0b:1b:bc:de:56:f5:ad:a3:a0:40:f1:75:10:58:74: + 37:f9:b7:9f:76:ca:46:96:4c:1a:81:f4:a2:ce:88: + 8b:9e:00:6d:42:b3:d6:68:d1:67:d6:9f:b8:9c:3f: + 43:c7:36:bf:41:88:1b:e8:74:26:a0:51:5c:e2:ee: + 6d:9d:73:bb:0d:36:e1:5c:68:9f:21:3b:b2:aa:ed: + 39:1d:ae:fc:b4:ca:38:c2:fb + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 1B:AB:6B:0F:42:91:DC:1E:D4:7A:95:87:30:2D:CC:11:4F:35:B7:73 + X509v3 Authority Key Identifier: + keyid:D6:66:76:C9:05:FF:A9:50:88:96:60:DD:FB:C7:30:18:72:67:41:19 + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 8 + serial:B2:47:DE:6A:2A:4C:83:19 + + Authority Information Access: + OCSP - URI:http://localhost:8888 + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 89:f8:8d:a8:e5:0b:2a:fb:f3:6a:80:2c:26:a1:a7:36:7e:a0: + c5:61:65:9d:7e:d6:47:60:b4:f6:72:e9:6e:2c:d9:f8:7f:c8: + 7a:5d:75:98:ad:88:de:e7:1b:44:a3:96:37:84:c0:b3:20:98: + 3b:b5:f6:ee:70:9c:04:7a:6c:88:05:75:7f:12:cf:b9:76:e8: + c0:17:0c:5e:eb:10:38:1e:54:41:58:56:f6:3c:ec:07:a5:c0: + 74:24:34:af:b3:c7:b2:58:85:47:0f:6c:e4:a0:9f:c8:7b:5c: + 95:77:17:e5:ad:eb:c3:86:44:f7:81:ef:cb:58:12:1a:6a:c7: + 19:95 +-----BEGIN CERTIFICATE----- +MIIDOTCCAqKgAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA4MB4XDTA5MTEyMDE1NTUz +M1oXDTM0MTExNDE1NTUzM1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDIgUm9vdCA4MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDpkTjYwTblwdAy6K4CEZflxQePW0Y6PNlJXppLUUy3fenRT6cVjMYQ +9vpfqQsbvN5W9a2joEDxdRBYdDf5t592ykaWTBqB9KLOiIueAG1Cs9Zo0WfWn7ic +P0PHNr9BiBvodCagUVzi7m2dc7sNNuFcaJ8hO7Kq7Tkdrvy0yjjC+wIDAQABo4H6 +MIH3MB0GA1UdDgQWBBQbq2sPQpHcHtR6lYcwLcwRTzW3czCBkQYDVR0jBIGJMIGG +gBTWZnbJBf+pUIiWYN37xzAYcmdBGaFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA4ggkAskfeaipMgxkwMQYIKwYBBQUH +AQEEJTAjMCEGCCsGAQUFBzABhhVodHRwOi8vbG9jYWxob3N0Ojg4ODgwDwYDVR0T +AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQCJ+I2o5Qsq+/NqgCwmoac2fqDF +YWWdftZHYLT2culuLNn4f8h6XXWYrYje5xtEo5Y3hMCzIJg7tfbucJwEemyIBXV/ +Es+5dujAFwxe6xA4HlRBWFb2POwHpcB0JDSvs8eyWIVHD2zkoJ/Ie1yVdxflrevD +hkT3ge/LWBIaascZlQ== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_8/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Root_8/demoCA/private/cakey.pem new file mode 100644 index 000000000..dd11db443 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_8/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,1DE6DE80057C280E + +1pXaFFR4KgVEWQzq73tQrfEkLZn7J0G0fxp1ZZYKOVdL3g/S4su2cXn5zfkSypjG +sTPnj9YuHzZiW1sB5M+U84b0aCSuh4+HK1Y+K6Us99psx/VaDq36uEBJZQviJ4zb +uF7ZT6NRGWMs3pIkFEHqi9TQ6mmeRgHMgkiI/mpM/26Y00dLpXdxBIGOCpKIPXwp +02mx/o9CHqI7ASuXV6ZAhawEmvFKKRNCKsKOaSs0CylGOT5nAaqWRp/IVMrm46wr +o7cErGgCZCPzQ5Ndx4553oSeWTjnm4iTS5UKg0nwPgS6sVhsr3zrTxIhS9zzcW2G +ycREX312K7q0zxtCxdNZxGeSfowRRy54JRoLf+O5yoNTRXYFjLxXGHgCTQRWgpIh +ggOmgUyIeNQXts4Qf6ddUtEcfGzMowCAJWTakXpOBoWj42mF85lDlcAAn8V1L90Q +MDF31HzrDAe3po4g+dNA6qdZrpSpnDDVp0oPsr3ooz1dLlwa8LWpPpq5PRgDWeQF +hcYrywI5tfUJyXv0xkEv+BIGKjGofWHGNtZWazBunhAVgWG/GQbzWxdSBS5w2waE +2Zo65PBqfLgRdnO6HYl15Pc5wm3gEQJo5VYgl7HmRpEt7lQrcnReqLWnsuHmqZ/H +vaEmGnSfXauVTvBVRXnrpznM/ROC9n2FR50lNIO1nAtMM7a0S0PIKgB+uNwAtsAR +Y4dY4YCS/io8wCL+DNBPtdvuY85/y5lnURpj9ojWO916WZsK/EFPJIQFuVwhal2C +Q9NVu8PXPDiBAHTVGZz8HoG32eYYUtqzeIY4Xo5ybUlnsNGlncWSqw== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Root_8/demoCA/serial b/xmlsecurity/test_docs/CAs/Root_8/demoCA/serial new file mode 100644 index 000000000..7d802a3e7 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_8/demoCA/serial @@ -0,0 +1 @@ +1002 diff --git a/xmlsecurity/test_docs/CAs/Root_8/openssl.cfg b/xmlsecurity/test_docs/CAs/Root_8/openssl.cfg new file mode 100644 index 000000000..077e13b2b --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_8/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Root_7.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Root_9/DO_NOT_INSTALL_THIS_ROOT_CERT.txt b/xmlsecurity/test_docs/CAs/Root_9/DO_NOT_INSTALL_THIS_ROOT_CERT.txt new file mode 100644 index 000000000..ee3d2b339 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_9/DO_NOT_INSTALL_THIS_ROOT_CERT.txt @@ -0,0 +1 @@ +!!!DO NOT INSTALL THIS ROOT CERTIFICATE!!! diff --git a/xmlsecurity/test_docs/CAs/Root_9/demoCA/DO_NO_INSTALL_THIS_ROOT_CERTIFICATE b/xmlsecurity/test_docs/CAs/Root_9/demoCA/DO_NO_INSTALL_THIS_ROOT_CERTIFICATE new file mode 100644 index 000000000..e69de29bb 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 000000000..66e316546 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 000000000..ca53f28f7 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_9/demoCA/cacert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDBDCCAm2gAwIBAgIJAKTbFg1LjNSmMA0GCSqGSIb3DQEBBQUAMF8xCzAJBgNV +BAYTAkRFMRAwDgYDVQQIEwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9y +ZzEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgOTAeFw0wOTEx +MjMxMzUyNDNaFw0zNDExMTcxMzUyNDNaMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgOTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw +gYkCgYEAsOgehurKuYszsH2LFeGyHA9WYmCOMZmQfBFOgS/kO1Hkv6tNrDbshzyc +I/qOlpkosXUbQaaJPYoQmv3eTpfYxM9Dju5GkzOL03Q9J8AGe8RW1urMCfD5fC9g +XmhxAnIbrmDhS4K0lV8ngWwTQjmec9CV8SVBLQerrNtmcY/VvcMCAwEAAaOBxzCB +xDAdBgNVHQ4EFgQUzTNeq3MjUYC4A60SAQvFXo5VymQwgZEGA1UdIwSBiTCBhoAU +zTNeq3MjUYC4A60SAQvFXo5VymShY6RhMF8xCzAJBgNVBAYTAkRFMRAwDgYDVQQI +EwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2 +ZWxvcG1lbnQxDzANBgNVBAMTBlJvb3QgOYIJAKTbFg1LjNSmMA8GA1UdEwEB/wQF +MAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAqQkfiXNJm8l5v6qQzv6HwcDIgSQBuwkp +bN5FgHdLXaae/UOelXpmLSfrAbizw0Om1xLH/tnSeNY9MCGMGA4ScGU1hdNLUTIU +LK9upl/q+cHQayZL/Hz4Z8sqRNrP+E2m0GY0RMF1getJunfYZZV9VcsfbO3SqgAQ +exqICFDFi8M= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_9/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Root_9/demoCA/crlnumber new file mode 100644 index 000000000..dd1172404 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_9/demoCA/crlnumber @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Root_9/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Root_9/demoCA/index.txt new file mode 100644 index 000000000..c741bbfda --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_9/demoCA/index.txt @@ -0,0 +1 @@ +V 341117135919Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Sub CA 1 Root 9 diff --git a/xmlsecurity/test_docs/CAs/Root_9/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Root_9/demoCA/index.txt.attr new file mode 100644 index 000000000..8f7e63a34 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_9/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Root_9/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Root_9/demoCA/newcerts/1000.pem new file mode 100644 index 000000000..0b38d4db4 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_9/demoCA/newcerts/1000.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 9 + Validity + Not Before: Nov 23 13:59:19 2009 GMT + Not After : Nov 17 13:59:19 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 9 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:a9:6d:7f:6a:08:fb:e2:3a:5e:83:3f:ff:58:ba: + 92:a1:79:9d:ce:d2:0c:16:15:f2:7e:b3:e4:45:9c: + 02:32:65:9b:02:90:78:05:95:e4:04:1d:4a:05:bb: + ea:f6:ac:ab:15:74:c2:bc:ee:2a:c1:80:55:3e:93: + 1f:5c:94:eb:cf:cf:8f:15:eb:b8:22:fe:69:61:51: + a9:08:b8:80:bd:48:99:da:85:10:1c:75:97:fd:d3: + c3:c4:0b:dd:eb:01:12:5d:ee:62:62:c3:0c:18:ea: + ed:76:ff:9b:1c:1f:c7:81:f9:9a:cd:e5:25:89:b2: + 13:57:56:f3:27:53:72:76:69 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 7B:D3:57:BF:6A:CB:6C:10:81:91:DA:95:DC:88:4F:A5:D0:DB:D1:46 + X509v3 Authority Key Identifier: + keyid:CD:33:5E:AB:73:23:51:80:B8:03:AD:12:01:0B:C5:5E:8E:55:CA:64 + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 9 + serial:A4:DB:16:0D:4B:8C:D4:A6 + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 17:67:b0:21:da:0d:a1:fe:09:62:d0:cf:1d:c0:c8:bd:d4:22: + dd:75:ec:04:e2:23:ae:ea:8c:15:fa:73:2e:83:f4:16:eb:c1: + e1:87:36:bd:58:d0:64:e0:6e:2c:bc:27:cb:dc:4b:58:01:80: + 48:27:53:bb:75:85:a7:19:b8:e2:c0:1f:9f:a2:18:27:82:3f: + 25:bf:17:d1:34:32:de:c4:81:9d:8a:39:6f:6b:1f:b6:12:61: + 74:78:96:6d:6e:52:23:4a:67:30:78:03:91:b7:89:bf:3c:4a: + 36:e3:95:21:38:35:af:05:55:81:05:25:91:78:ca:2f:5d:79: + d2:05 +-----BEGIN CERTIFICATE----- +MIIDBjCCAm+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA5MB4XDTA5MTEyMzEzNTkx +OVoXDTM0MTExNzEzNTkxOVowaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA5MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQCpbX9qCPviOl6DP/9YupKheZ3O0gwWFfJ+s+RFnAIyZZsCkHgFleQE +HUoFu+r2rKsVdMK87irBgFU+kx9clOvPz48V67gi/mlhUakIuIC9SJnahRAcdZf9 +08PEC93rARJd7mJiwwwY6u12/5scH8eB+ZrN5SWJshNXVvMnU3J2aQIDAQABo4HH +MIHEMB0GA1UdDgQWBBR701e/astsEIGR2pXciE+l0NvRRjCBkQYDVR0jBIGJMIGG +gBTNM16rcyNRgLgDrRIBC8VejlXKZKFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA5ggkApNsWDUuM1KYwDwYDVR0TAQH/ +BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQAXZ7Ah2g2h/gli0M8dwMi91CLddewE +4iOu6owV+nMug/QW68Hhhza9WNBk4G4svCfL3EtYAYBIJ1O7dYWnGbjiwB+fohgn +gj8lvxfRNDLexIGdijlvax+2EmF0eJZtblIjSmcweAORt4m/PEo245UhODWvBVWB +BSWReMovXXnSBQ== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Root_9/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Root_9/demoCA/private/cakey.pem new file mode 100644 index 000000000..65149ff65 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_9/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,EEC173CF380C4BEC + +3ZAmsMS1aFKb3EfOncYO+hg0ucK80Y7pHg7GaH2/XZ+b6HmVQrHKuDrIcQNGEY5Z +QTCBeCGhmh7hnemBSrco4HURl/2LlA5CoYyd6CCc79VeUQZRJdLjL2thD4x/QwQs +Vh9uG+nunEAXK2kI2sFAxCScoCXSZmAgQqAANQ3SHyJ14e8BlOVgucfD0afYEDNE +udc86lO8+Lz7HfTvysnKO06pgp30ZFJlnBzSBXkXsTShPWEPg8f+2JRc+A5PbxVM +gz/S/ZrPMg8QyIfwwCGjRKzyRBeXVfquXqrwNqtGI+HXo4QaYYT8zuYUn9XuJsac +ZFn2BoXhI6TCBzyM+yuoXp+Xx5plY2A8QXaiLdKO2usV5xcXaBY3XTczrnOfJh7f +F3B2mbfhr/s4UJaFmnG4eULklFGADRY5tN2bIutsWmuuw17/ZwUSZxsjl+TybqVi +uvfmEqrSgoZ9Qz1vvRngVAAwJPAvQqsBQwkq3WapNeoLqmQeSHq/6z4G5RKPbkMs +t21L4SBUGQMhkZWAnJEtECDGsQpDjjwbDuJzrbVTSBiNvDWWeXJuGdyhzI6b17v7 +CZosIrzE82Oo0C+afWJVek2cB8rIMbgqEL+3Sj7x9c/kGeLx957d+geTSStqjD3z +P574kcEDP9ppEHalg1ygJ6t3SjkTNMWrbuYH+GlY8all7rniMDYUDMECIj3Xrv+Q +x3Yzv07FAooDYBE4pdWtTjpBlmwxa68XaMSDG28jQwTHck30GU/gwrM74CKWsg8y +4eZAaeQKHeUYFGsxWeYfmwr7aD4pG+VYGOmRmdia5PA= +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Root_9/demoCA/serial b/xmlsecurity/test_docs/CAs/Root_9/demoCA/serial new file mode 100644 index 000000000..dd1172404 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_9/demoCA/serial @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Root_9/openssl.cfg b/xmlsecurity/test_docs/CAs/Root_9/openssl.cfg new file mode 100644 index 000000000..f48e3d5a3 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Root_9/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Root_7.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/cacert.pem new file mode 100644 index 000000000..be26aa5d8 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/cacert.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 1 + Validity + Not Before: Nov 18 15:07:13 2009 GMT + Not After : Nov 12 15:07:13 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 1 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:d9:3a:8d:64:95:87:76:76:e8:61:c3:e9:65:f4: + a6:b7:0c:77:0e:4b:10:e8:14:a3:e1:84:69:7c:8e: + 97:d2:7d:01:ad:b2:dc:5c:cd:c6:91:a1:f3:93:7c: + 54:36:64:e3:ca:22:ca:00:cb:c6:91:ab:6b:26:88: + 69:60:9a:61:d7:59:17:db:93:7d:09:36:da:28:cb: + ec:2d:a4:26:bb:1a:42:20:b8:08:b2:0f:b9:77:a6: + 80:71:cf:13:f5:37:a2:90:4d:ab:e8:97:49:d2:80: + 94:8f:b1:9d:5a:b4:9f:de:ff:fa:b6:d6:e0:45:5f: + cc:d4:10:1e:32:46:7b:ba:55 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 37:71:74:81:44:DD:1E:B1:60:96:41:B7:4B:38:C4:B7:79:1B:CF:8A + X509v3 Authority Key Identifier: + keyid:0F:FA:C6:EB:DF:CE:B8:BB:B3:A9:3E:42:A6:BA:EC:D2:93:CA:47:A4 + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 1 + serial:95:B0:05:2B:ED:C2:39:2D + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 18:f6:02:5e:75:04:5f:eb:3b:07:41:85:c0:9e:08:29:58:3d: + b5:6f:c2:aa:24:0d:93:1d:17:fc:be:d6:43:ac:43:d7:4d:a0: + 2c:40:fd:3d:d5:7e:91:46:25:49:62:ba:e9:7f:67:c2:fc:8a: + c3:a0:37:bf:ec:f9:54:bf:61:10:35:dd:5b:bb:da:7c:70:54: + 32:13:b9:ae:7d:ea:a5:7d:aa:55:3e:ef:0a:ef:12:fd:c3:f6: + e5:25:98:97:34:02:64:fd:88:79:b3:e2:f4:fc:ff:e7:d3:98: + f1:d9:d5:18:d9:b4:62:ae:99:88:61:2e:ff:02:6a:13:35:fe: + 37:c7 +-----BEGIN CERTIFICATE----- +MIIDBjCCAm+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCAxMB4XDTA5MTExODE1MDcx +M1oXDTM0MTExMjE1MDcxM1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCAxMIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDZOo1klYd2duhhw+ll9Ka3DHcOSxDoFKPhhGl8jpfSfQGtstxczcaR +ofOTfFQ2ZOPKIsoAy8aRq2smiGlgmmHXWRfbk30JNtooy+wtpCa7GkIguAiyD7l3 +poBxzxP1N6KQTavol0nSgJSPsZ1atJ/e//q21uBFX8zUEB4yRnu6VQIDAQABo4HH +MIHEMB0GA1UdDgQWBBQ3cXSBRN0esWCWQbdLOMS3eRvPijCBkQYDVR0jBIGJMIGG +gBQP+sbr3864u7OpPkKmuuzSk8pHpKFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCAxggkAlbAFK+3COS0wDwYDVR0TAQH/ +BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQAY9gJedQRf6zsHQYXAnggpWD21b8Kq +JA2THRf8vtZDrEPXTaAsQP091X6RRiVJYrrpf2fC/IrDoDe/7PlUv2EQNd1bu9p8 +cFQyE7mufeqlfapVPu8K7xL9w/blJZiXNAJk/Yh5s+L0/P/n05jx2dUY2bRirpmI +YS7/AmoTNf43xw== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/crl/DO_NOT_CREATE_A_CRL b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/crl/DO_NOT_CREATE_A_CRL new file mode 100644 index 000000000..e69de29bb diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/crlnumber new file mode 100644 index 000000000..83b33d238 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/crlnumber @@ -0,0 +1 @@ +1000 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/index.txt new file mode 100644 index 000000000..e2027ce9f --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/index.txt @@ -0,0 +1 @@ +V 341112152323Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 1 Root 1 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/index.txt.attr new file mode 100644 index 000000000..8f7e63a34 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/newcerts/1000.pem new file mode 100644 index 000000000..e7d22dfd0 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/newcerts/1000.pem @@ -0,0 +1,58 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 1 + Validity + Not Before: Nov 18 15:23:23 2009 GMT + Not After : Nov 12 15:23:23 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 1 Root 1 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:c8:41:66:84:c7:d5:c5:72:8f:a6:98:1b:59:e2: + 33:ca:0d:d2:24:b3:c1:47:db:11:e2:bf:23:da:32: + 68:41:cc:ff:28:fe:9a:39:49:e7:08:f0:22:75:15: + 61:99:9e:99:e5:14:65:71:60:00:0f:58:42:70:78: + 5a:1e:d8:fa:97:92:82:0e:e3:0c:ac:20:dc:b8:e3: + 5e:87:8b:89:e3:a1:c3:87:49:1d:92:a5:fd:7c:77: + 79:ce:1f:fa:9c:5a:17:d9:11:0c:f2:7f:1a:fa:d8: + 32:41:f8:69:80:ae:8a:66:bd:36:c2:21:65:57:08: + be:cf:f0:ec:83:15:98:6d:65 + Exponent: 65537 (0x10001) + X509v3 extensions: + Netscape Comment: + OpenSSL Generated Certificate + X509v3 Subject Key Identifier: + FF:BB:B0:7F:E3:0E:E3:8C:CF:EC:88:49:A9:0E:62:B5:D3:60:12:46 + X509v3 Authority Key Identifier: + keyid:37:71:74:81:44:DD:1E:B1:60:96:41:B7:4B:38:C4:B7:79:1B:CF:8A + + Signature Algorithm: sha1WithRSAEncryption + 33:dd:e8:57:3e:69:1b:a0:4c:83:51:99:dd:73:b0:0c:cb:c7: + c0:ff:12:8b:b6:3b:59:12:b9:f1:20:87:75:f0:71:6e:bc:94: + 47:72:62:ae:93:90:05:e2:ff:63:31:5a:d2:80:a5:4a:7f:57: + e9:f7:4e:3e:be:bd:4c:9e:74:07:19:b0:4d:88:97:af:23:a7: + 5a:23:af:d1:a9:98:9b:55:7e:fa:6b:18:77:03:c4:aa:49:bc: + b6:3d:66:3e:8d:0a:80:5f:ac:b9:58:fb:11:ef:60:db:ad:a8: + 79:41:83:1a:6a:61:87:99:64:2d:e4:6a:bb:c0:30:00:dd:69: + e5:92 +-----BEGIN CERTIFICATE----- +MIICvjCCAiegAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCAxMB4XDTA5 +MTExODE1MjMyM1oXDTM0MTExMjE1MjMyM1owbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAxIFN1YiBDQSAxIFJvb3QgMTCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAyEFmhMfVxXKPppgbWeIzyg3SJLPBR9sR +4r8j2jJoQcz/KP6aOUnnCPAidRVhmZ6Z5RRlcWAAD1hCcHhaHtj6l5KCDuMMrCDc +uONeh4uJ46HDh0kdkqX9fHd5zh/6nFoX2REM8n8a+tgyQfhpgK6KZr02wiFlVwi+ +z/DsgxWYbWUCAwEAAaNwMG4wLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJh +dGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBT/u7B/4w7jjM/siEmpDmK102ASRjAf +BgNVHSMEGDAWgBQ3cXSBRN0esWCWQbdLOMS3eRvPijANBgkqhkiG9w0BAQUFAAOB +gQAz3ehXPmkboEyDUZndc7AMy8fA/xKLtjtZErnxIId18HFuvJRHcmKuk5AF4v9j +MVrSgKVKf1fp904+vr1MnnQHGbBNiJevI6daI6/RqZibVX76axh3A8SqSby2PWY+ +jQqAX6y5WPsR72Dbrah5QYMaamGHmWQt5Gq7wDAA3Wnlkg== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/private/cakey.pem new file mode 100644 index 000000000..602026a47 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,4E900CB191575111 + +vHLTGKUgxa3C35alVr0gWT30x8WW5Pmz4oFv23fMMWIXjrp/QLlRRmd2AO9H8rLb +3MWnA7cby5UTcrcsqwBA30TqhduNDi4iQFcOM60/S7yUFKjF5nj9bGi8XuUzMgTx +OrJuxMGkayLiELskZxEpi6SJvTEsSdreT6OvyhzXQfAFDodoJSW65oF08cuYxXzi +FFYFqvyWXa29WUyinBav5k3Mjax3Av3dYfMf/1u2n4vjGyjkfMg7mHrno19daWqa +FJsxHHFezq//G5+JvePWFQUo1b0fVh13fx9x1dCbCRGQ9duSXaI7BNfl2Jd2rlVk +xUMqnvd8VBNkW1AHxZL4csurQyO8ZQzg46w/kWaIMroeXbUnZYNJV7/TCs6nLGJF +iNwtsFAjunWgWttFbMx3X7L7T6f6cWXocOOTNeIDpH+W6Pw9vltrjzNPAyBBok17 +sboWXDtlihMrSq5lWzUSPE8gOueh7Bcf7fSnLTeXuOXgKooJVXelookSQzsilWmS +Fo5PTM+jOOaXVlbf8zfKFreLawohNkzagIxrCEP+HU+tF52ybJDP4mwPi1sQNcA0 +0luHyCL5EmaH5hVIqYeGUQoNPois5TqgYH1SEujyIuoNdEBi5r5qIRR/zz+BEpKU +Z1B+HmmSWb0hjfenFSSaSSmGyS6VW1wZsU2B+wcPr7r0uFqoWllkxYNmSdky6qmw +4Or0D6ayFUaJOQG6aTEfEVS31B4TUfFGfOLbeuUdwNa4/pNwMeFFSx+Xj7J3oYrn +udjIL0Hz8hhjLVXaPVcu/qkZ7pXhOVlRQJ7byx730G3+elUFalJ/eQ== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/serial new file mode 100644 index 000000000..dd1172404 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/demoCA/serial @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/openssl.cfg new file mode 100644 index 000000000..0dd15bd9e --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_1/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/DO_NOT_INSTALL_THIS_CERTIFICATE b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/DO_NOT_INSTALL_THIS_CERTIFICATE new file mode 100644 index 000000000..e69de29bb diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/README.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/README.txt new file mode 100644 index 000000000..a18ed9ce0 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/README.txt @@ -0,0 +1,19 @@ +Do NOT install !!! + + + +To provide the CRL via HTTP run + + + +java -jar ../../tools/httpserv/dist/httpserv.jar -a 8902 + + +To provide the intermediate certificate run + +java -jar ../../tools/httpserv/dist/httpserv.jar -a 8910 + + + + + diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/DO_NOT_INSTALL_THIS_CERTIFICATE b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/DO_NOT_INSTALL_THIS_CERTIFICATE new file mode 100644 index 000000000..e69de29bb 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 000000000..2bb9a4289 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 000000000..1f27b97b3 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/cacert.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 10 + Validity + Not Before: Nov 23 15:14:48 2009 GMT + Not After : Nov 17 15:14:48 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 10 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:e4:d5:66:14:88:9f:79:41:50:b0:d1:a0:1b:98: + bf:b0:21:34:30:36:70:58:6f:8b:58:f1:b9:58:3a: + ce:29:6b:65:b6:11:f7:0d:c8:a6:c3:be:db:0f:2a: + 4e:c7:42:df:c9:0e:13:c0:00:0f:af:b5:71:c4:bc: + dd:82:fc:4a:27:c0:ee:af:ba:e1:7b:67:de:6b:bb: + ac:4c:fe:88:01:1a:73:4e:f5:32:15:3a:d0:cb:6b: + 97:84:1b:6c:d0:d6:91:a8:a4:5a:87:2a:69:61:36: + 1d:42:cc:16:d0:03:9c:c6:90:5c:61:20:8b:b1:be: + b6:54:24:5b:6f:1f:a9:5a:6f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 11:63:A1:BE:8B:E3:56:07:E6:A3:9F:23:39:72:7D:E3:22:B6:53:39 + X509v3 Authority Key Identifier: + keyid:C8:A7:A3:80:20:74:6C:6F:EC:11:7A:F6:BE:26:10:37:31:87:B0:7A + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 10 + serial:BF:C8:0F:BB:D9:A0:3A:6B + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 6b:0f:75:6d:56:b0:4e:45:19:65:ad:50:ef:4e:87:6c:95:5d: + 05:39:5a:43:5c:b4:51:25:9a:ec:f4:93:d1:f0:f6:91:dd:a3: + 77:95:0c:74:3c:a9:7c:c2:f6:62:ce:bf:58:5f:66:1f:d0:55: + ca:d8:2d:c4:1e:29:3a:ad:55:2c:9d:2c:8f:8e:9e:ce:ac:17: + 7e:1b:d1:16:d9:12:76:5c:2d:3f:9d:70:66:aa:39:34:f0:ec: + 31:4b:4b:5a:14:0c:c5:5b:3c:c8:47:02:90:cb:77:d7:4f:88: + 10:a7:80:3d:ca:19:5c:b5:04:c9:f0:e1:1b:5a:5f:fb:61:b2: + 14:b5 +-----BEGIN CERTIFICATE----- +MIIDCTCCAnKgAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwYDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEQMA4GA1UEAxMHUm9vdCAxMDAeFw0wOTExMjMxNTE0 +NDhaFw0zNDExMTcxNTE0NDhaMGkxCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdIYW1i +dXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxMLRGV2ZWxvcG1l +bnQxGTAXBgNVBAMTEFN1YiBDQSAxIFJvb3QgMTAwgZ8wDQYJKoZIhvcNAQEBBQAD +gY0AMIGJAoGBAOTVZhSIn3lBULDRoBuYv7AhNDA2cFhvi1jxuVg6zilrZbYR9w3I +psO+2w8qTsdC38kOE8AAD6+1ccS83YL8SifA7q+64Xtn3mu7rEz+iAEac071MhU6 +0Mtrl4QbbNDWkaikWocqaWE2HULMFtADnMaQXGEgi7G+tlQkW28fqVpvAgMBAAGj +gcgwgcUwHQYDVR0OBBYEFBFjob6L41YH5qOfIzlyfeMitlM5MIGSBgNVHSMEgYow +gYeAFMino4AgdGxv7BF69r4mEDcxh7B6oWSkYjBgMQswCQYDVQQGEwJERTEQMA4G +A1UECBMHSGFtYnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsT +C0RldmVsb3BtZW50MRAwDgYDVQQDEwdSb290IDEwggkAv8gPu9mgOmswDwYDVR0T +AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBrD3VtVrBORRllrVDvTodslV0F +OVpDXLRRJZrs9JPR8PaR3aN3lQx0PKl8wvZizr9YX2Yf0FXK2C3EHik6rVUsnSyP +jp7OrBd+G9EW2RJ2XC0/nXBmqjk08OwxS0taFAzFWzzIRwKQy3fXT4gQp4A9yhlc +tQTJ8OEbWl/7YbIUtQ== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/crl/DO_NOT_INSTALL_THIS_CRL b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/crl/DO_NOT_INSTALL_THIS_CRL new file mode 100644 index 000000000..e69de29bb 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 000000000..67ed32da5 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 000000000..dd1172404 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/crlnumber @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/index.txt new file mode 100644 index 000000000..810ec7ef2 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/index.txt @@ -0,0 +1 @@ +V 341117153149Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 1 Root 10 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/index.txt.attr new file mode 100644 index 000000000..8f7e63a34 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/newcerts/1000.pem new file mode 100644 index 000000000..7449048bb --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/newcerts/1000.pem @@ -0,0 +1,67 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 10 + Validity + Not Before: Nov 23 15:31:49 2009 GMT + Not After : Nov 17 15:31:49 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 1 Root 10 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:ce:41:53:5f:ba:d9:26:e4:45:14:74:a9:f2:9e: + fa:91:50:ea:fe:e7:76:76:6e:62:26:4c:a2:bd:c9: + 98:ce:1d:b3:74:ea:95:04:ec:d8:24:ac:29:de:2d: + 7f:2f:7f:10:94:24:d2:0c:0b:ff:d0:38:f1:a9:8f: + ee:25:97:bf:bd:b0:1f:24:d7:9d:7a:20:79:c0:73: + 97:12:cb:5a:cf:6d:4f:df:4a:a8:9c:1b:be:49:63: + 1f:b1:03:6d:c6:5f:69:5c:0d:7e:81:23:48:2a:76: + 80:53:53:d2:03:f6:56:6d:dc:e3:cc:be:cb:0f:c3: + 1b:b7:6e:79:33:e0:da:f6:5d + Exponent: 65537 (0x10001) + X509v3 extensions: + Authority Information Access: + CA Issuers - URI:http://localhost:8910/demoCA/Sub_CA_1_Root_10.crt + + X509v3 CRL Distribution Points: + URI:http://localhost:8902/demoCA/crl/Sub_CA_1_Root_10.crl + + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 90:DC:ED:B0:CB:62:A1:BE:8F:23:65:01:79:14:85:22:48:70:7B:A1 + X509v3 Authority Key Identifier: + keyid:11:63:A1:BE:8B:E3:56:07:E6:A3:9F:23:39:72:7D:E3:22:B6:53:39 + + Signature Algorithm: sha1WithRSAEncryption + 54:e3:d2:eb:dc:aa:db:8b:88:34:c6:b9:5b:f6:d8:ca:81:24: + d0:ba:4c:c2:a7:8e:82:22:d3:68:64:c9:61:9b:0a:00:3e:d1: + 4e:cb:83:1d:b9:c7:07:6a:5e:7b:b4:ca:92:0c:93:d7:9e:99: + e1:58:47:17:b0:a7:6d:68:5f:e5:59:f9:2a:d1:96:df:b6:9f: + bc:47:40:f2:71:ed:71:2b:8a:6e:6f:aa:29:9f:4d:98:ee:f1: + aa:63:b4:44:39:58:8a:f8:c2:af:8d:c1:49:92:b4:99:02:2f: + 27:c7:5b:f5:30:7c:ed:67:ff:cd:12:dc:a7:c4:8e:98:4f:2c: + e0:05 +-----BEGIN CERTIFICATE----- +MIIDODCCAqGgAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwaTELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEZMBcGA1UEAxMQU3ViIENBIDEgUm9vdCAxMDAeFw0w +OTExMjMxNTMxNDlaFw0zNDExMTcxNTMxNDlaMHAxCzAJBgNVBAYTAkRFMRAwDgYD +VQQIEwdIYW1idXJnMRcwFQYDVQQKEw5PcGVuT2ZmaWNlLm9yZzEUMBIGA1UECxML +RGV2ZWxvcG1lbnQxIDAeBgNVBAMTF1VzZXIgMSBTdWIgQ0EgMSBSb290IDEwMIGf +MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOQVNfutkm5EUUdKnynvqRUOr+53Z2 +bmImTKK9yZjOHbN06pUE7NgkrCneLX8vfxCUJNIMC//QOPGpj+4ll7+9sB8k1516 +IHnAc5cSy1rPbU/fSqicG75JYx+xA23GX2lcDX6BI0gqdoBTU9ID9lZt3OPMvssP +wxu3bnkz4Nr2XQIDAQABo4HnMIHkME0GCCsGAQUFBwEBBEEwPzA9BggrBgEFBQcw +AoYxaHR0cDovL2xvY2FsaG9zdDo4OTEwL2RlbW9DQS9TdWJfQ0FfMV9Sb290XzEw +LmNydDBGBgNVHR8EPzA9MDugOaA3hjVodHRwOi8vbG9jYWxob3N0Ojg5MDIvZGVt +b0NBL2NybC9TdWJfQ0FfMV9Sb290XzEwLmNybDALBgNVHQ8EBAMCBeAwHQYDVR0O +BBYEFJDc7bDLYqG+jyNlAXkUhSJIcHuhMB8GA1UdIwQYMBaAFBFjob6L41YH5qOf +IzlyfeMitlM5MA0GCSqGSIb3DQEBBQUAA4GBAFTj0uvcqtuLiDTGuVv22MqBJNC6 +TMKnjoIi02hkyWGbCgA+0U7Lgx25xwdqXnu0ypIMk9eemeFYRxewp21oX+VZ+SrR +lt+2n7xHQPJx7XErim5vqimfTZju8apjtEQ5WIr4wq+NwUmStJkCLyfHW/UwfO1n +/80S3KfEjphPLOAF +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/private/cakey.pem new file mode 100644 index 000000000..260e3aa94 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,170F9697C268C4B5 + +eIaE0ShuxMcOUBJBlI7PXIuKg69hDunjUz55iy0I+4sGc9tFK+vtjvDZWxx+dpZI +WKGto0fDeobBf3f2xgKQFcwAtUPtiTMXk8C0BYfAbXsTYBgOgvKwJGOIo5FsjukZ +VJCNlUM1mwX5P3OrLdyT0j8OoL6lINztYDhSC8XL12YJk1j05yN4Gl8N108JQMLA +sywA2Q6WIhPloZQXtHkiN2mlQ7WWwbSBbaUbdXNQKk6sXelFLPMOk+JOTCLp9kHU +svTBAg7RyWKBuUmtEmkipNLtYhdkRVJ/dgL3/TAsZET6cjDd/eZg+1Kl0pn93KGv +avSQKppkKNjUcWkZiuM1imS8+0qeMiw56JQGzMdEeSjadcTdsyYb0lssXmndK/z0 +90bA6GegvCnsq6Wj0Nz97GbK+ZMzA76e+HPQLli0j3poAlVwdzBCFRyLO4ET5Qzl +OhTewxKZxe2yx75chECWJS+CLOajHkVyUe3x6QzyVuU+YZqjXWkJP7rTcQJZFcml ++3PHYWy5RnZ2sKOegksr3+QtL+UmDVa1xEeIhk3m0IMiYZ9HNWlrg1gedY02y9yY +MGsCOkCF10KnCNIp4j5s1kGMicdMquDt0jTXwu+8jt6Skh8FWcr9aLf0bNc63oHg +NaI7Y3+Ssl3GLUGFOGwC0lpooZ10SoJJDK9xxEjt48vUfX+Npn3bRv+UlwfLBYLo +GENyNV3OVAsKYQ8fGIh/gTeIqwMUdo7Efcs6bdeqiOrYQhBl04Gty0I4cO6/lFGd +by/4SesYDXoVtaKto1B5VOQn+QxovF7eY1pK6wDBU8+EaJbGSNK9Rw== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/serial new file mode 100644 index 000000000..dd1172404 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/demoCA/serial @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/openssl.cfg new file mode 100644 index 000000000..431650974 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_10/openssl.cfg @@ -0,0 +1,293 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8889 +authorityInfoAccess = caIssuers;URI:http://localhost:8910/demoCA/Sub_CA_1_Root_10.crt +crlDistributionPoints=URI:http://localhost:8902/demoCA/crl/Sub_CA_1_Root_10.crl +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +#nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/cacert.pem new file mode 100644 index 000000000..36a8eb3c0 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/cacert.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 2 + Validity + Not Before: Nov 18 15:55:38 2009 GMT + Not After : Nov 12 15:55:38 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 2 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:f0:7a:16:4c:ab:06:b2:af:27:9c:7d:3f:86:da: + de:7a:c3:01:67:77:56:49:09:ed:ed:31:72:83:e8: + 75:9c:4c:ce:f9:97:b6:63:3c:e2:ca:83:80:92:03: + 9c:96:e2:de:72:79:c1:cf:3e:3f:b9:0d:b4:87:c7: + 75:e6:56:8d:aa:f8:77:47:11:4e:fe:07:b0:1d:64: + 06:73:4b:6f:d4:ac:da:0f:05:87:b1:f1:98:a9:f5: + 8a:a1:a8:ed:17:9c:26:b8:da:92:63:d2:53:87:e6: + fc:ed:44:de:94:56:90:3e:a2:a1:67:08:cb:38:d4: + cf:17:3b:7e:ff:7a:97:c0:7b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 8C:F3:2C:30:A2:E8:62:50:70:BC:FC:71:A0:41:FA:E0:58:B4:4D:B8 + X509v3 Authority Key Identifier: + keyid:5F:BC:4C:DA:EB:0A:0C:B5:23:43:5E:24:32:27:79:41:F5:82:A3:02 + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 2 + serial:A2:AF:15:89:EC:73:54:86 + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 52:83:16:ab:0e:43:2d:b3:e4:0f:6c:c1:63:d4:86:ac:e7:1e: + ee:7b:ee:9b:0c:ff:4f:e0:59:d5:e4:27:af:68:bf:a7:f5:2a: + a3:c9:e3:2b:8d:b7:31:26:f6:04:80:4e:f2:a5:bf:da:63:5e: + 8c:d6:c6:b2:46:a0:46:10:2f:84:9f:02:76:f3:c8:33:05:62: + 0c:5f:2d:cc:06:23:53:9f:d9:f8:46:e4:2e:5c:da:05:fc:bf: + db:45:b4:ac:8d:8b:b5:4b:60:7b:7b:26:34:7f:b1:4b:41:96: + 41:26:70:7a:9d:78:a2:9b:e0:de:62:a2:04:86:9f:ed:7c:a6: + 20:eb +-----BEGIN CERTIFICATE----- +MIIDBjCCAm+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCAyMB4XDTA5MTExODE1NTUz +OFoXDTM0MTExMjE1NTUzOFowaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCAyMIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDwehZMqwayryecfT+G2t56wwFnd1ZJCe3tMXKD6HWcTM75l7ZjPOLK +g4CSA5yW4t5yecHPPj+5DbSHx3XmVo2q+HdHEU7+B7AdZAZzS2/UrNoPBYex8Zip +9YqhqO0XnCa42pJj0lOH5vztRN6UVpA+oqFnCMs41M8XO37/epfAewIDAQABo4HH +MIHEMB0GA1UdDgQWBBSM8ywwouhiUHC8/HGgQfrgWLRNuDCBkQYDVR0jBIGJMIGG +gBRfvEza6woMtSNDXiQyJ3lB9YKjAqFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCAyggkAoq8ViexzVIYwDwYDVR0TAQH/ +BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBSgxarDkMts+QPbMFj1Ias5x7ue+6b +DP9P4FnV5CevaL+n9SqjyeMrjbcxJvYEgE7ypb/aY16M1sayRqBGEC+EnwJ288gz +BWIMXy3MBiNTn9n4RuQuXNoF/L/bRbSsjYu1S2B7eyY0f7FLQZZBJnB6nXiim+De +YqIEhp/tfKYg6w== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/crlnumber new file mode 100644 index 000000000..dd1172404 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/crlnumber @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/index.txt new file mode 100644 index 000000000..ae1f2d1e4 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/index.txt @@ -0,0 +1 @@ +V 341112160955Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 1 Root 2 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/index.txt.attr new file mode 100644 index 000000000..8f7e63a34 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/newcerts/1000.pem new file mode 100644 index 000000000..a8c0b74ca --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/newcerts/1000.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 2 + Validity + Not Before: Nov 18 16:09:55 2009 GMT + Not After : Nov 12 16:09:55 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 1 Root 2 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:c7:00:aa:e0:5a:42:af:9c:b5:43:8c:f4:7d:7a: + 0f:ee:a9:19:22:d8:47:14:af:b4:e4:dd:5d:41:92: + a1:2b:32:39:5c:71:88:10:e3:77:87:b6:d5:38:85: + de:4b:91:c6:17:97:8e:3d:96:b3:af:8c:9d:74:8c: + 88:7f:2a:72:9a:ca:1a:1b:56:6c:63:2e:a4:a0:fc: + 3a:7b:0d:c2:16:15:d0:80:15:29:de:cd:0b:74:bc: + 5e:31:84:71:a4:fd:be:9b:06:6a:0c:47:1d:f9:e4: + c1:98:ae:46:e6:e2:51:55:d5:bb:ab:05:28:69:b5: + f8:35:32:d6:f0:64:d8:44:81 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + Netscape Comment: + OpenSSL Generated Certificate + X509v3 Subject Key Identifier: + 71:60:2B:22:B5:DF:FC:38:7E:79:F3:EF:7C:96:5F:C1:D2:42:9C:61 + X509v3 Authority Key Identifier: + keyid:8C:F3:2C:30:A2:E8:62:50:70:BC:FC:71:A0:41:FA:E0:58:B4:4D:B8 + + Signature Algorithm: sha1WithRSAEncryption + e5:b8:1a:43:82:75:20:48:e0:52:d0:46:25:6f:f7:5b:a9:3f: + 9e:cd:db:45:da:15:53:95:e7:c8:74:7b:e0:e4:2c:8c:f6:4d: + 1c:73:6e:2c:11:eb:c1:dc:4c:1d:50:e3:e8:10:2f:03:20:06: + ff:d7:4f:c9:a2:2e:ef:85:27:92:31:47:64:c8:75:f2:fc:a4: + 9d:c9:53:55:c5:da:69:b0:96:99:fd:ac:c4:16:40:ea:0c:1b: + 32:c3:fd:65:1d:03:ad:be:60:88:7c:70:53:35:91:ce:13:e2: + 3d:23:6b:e8:23:c0:3c:9a:57:5f:ad:4b:03:94:92:16:62:f9: + d4:01 +-----BEGIN CERTIFICATE----- +MIICyzCCAjSgAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCAyMB4XDTA5 +MTExODE2MDk1NVoXDTM0MTExMjE2MDk1NVowbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAxIFN1YiBDQSAxIFJvb3QgMjCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAxwCq4FpCr5y1Q4z0fXoP7qkZIthHFK+0 +5N1dQZKhKzI5XHGIEON3h7bVOIXeS5HGF5eOPZazr4yddIyIfypymsoaG1ZsYy6k +oPw6ew3CFhXQgBUp3s0LdLxeMYRxpP2+mwZqDEcd+eTBmK5G5uJRVdW7qwUoabX4 +NTLW8GTYRIECAwEAAaN9MHswCwYDVR0PBAQDAgXgMCwGCWCGSAGG+EIBDQQfFh1P +cGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUcWArIrXf/Dh+ +efPvfJZfwdJCnGEwHwYDVR0jBBgwFoAUjPMsMKLoYlBwvPxxoEH64Fi0TbgwDQYJ +KoZIhvcNAQEFBQADgYEA5bgaQ4J1IEjgUtBGJW/3W6k/ns3bRdoVU5XnyHR74OQs +jPZNHHNuLBHrwdxMHVDj6BAvAyAG/9dPyaIu74UnkjFHZMh18vyknclTVcXaabCW +mf2sxBZA6gwbMsP9ZR0Drb5giHxwUzWRzhPiPSNr6CPAPJpXX61LA5SSFmL51AE= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/private/cakey.pem new file mode 100644 index 000000000..ba6119464 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,A5EF3D451C410026 + +RByk5Bn7uG1eixW1qTghnNri2bQHvnrNUYcpSL/mJIx6NjuYEY6vE/vQ9A9qcjuZ +8NInLR1w+EmSlDS499za8dfllaJ4/djswWN+4gtkoP/kKF390AcNgIpf/gIiJX6d +tkrw3Esst2gUwdtdhWItQNh0qZoeWpY9KlraDdEYVZt46JmsgwEIufzHyHTHf53C +E9ZP7/vYBQeHPOvMGsvhwZWAZZOO5GnD4fktbVAnybQdnlPgJDrRTGabbTdawQNc +8GJoG6hgJPcwlYm7NbRrtB18L3bG4bxx95fjqeOtvGDSUxSY+FNV7B2xQpivnBu6 +ppLdwTRYHQGOCJSCZoCtW+GYM7wXR2L4kGXMPwB4hHUAQXt+Tva9TP0t96313lMW +bFTRgTcT71eBidEkUIn1OrOL/Al2lXvSaDhm0P2F0yElzj3JN/gqrIUChaXWcLrS +CZuOGA2zGpoBASQ5jF+CyC+5mEkmDgvbmAXiJNjNmK/ColklpTNRSGk65Vr8AufA +d/yoSQCGprhMgqhviue40MGSsOD58TLwR4Tsm5ptze0QYRNC2SkKCrgtS0IEXh/Z +/9cMAgwOypW1T7LMOV+rG9DOyKx9Ye+oxPLCHdS7wN4h6blusiESbbUW0f5wqAzF +FCe6VEd+AjahnQLjw7O8vP4zl8q99cjOYD5SB+wqYrr0beEely7xdpKrDMgXqiBe +tOE9XvgU9KR59GZd0l6FPRkpZCUA+3Wuu4Zvrbam5kEbxVy+VTamWd5cRrxbJBM4 +Ipn414lfeq/5Foz13roErJE6gbWxXeCFDzg0z5fjWc2T41PX58x4Tw== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/req.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/req.pem new file mode 100644 index 000000000..cc93d02e5 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/req.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIBqDCCARECAQAwaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1cmcxFzAV +BgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVudDEYMBYG +A1UEAxMPU3ViIENBIDEgUm9vdCAyMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB +gQDwehZMqwayryecfT+G2t56wwFnd1ZJCe3tMXKD6HWcTM75l7ZjPOLKg4CSA5yW +4t5yecHPPj+5DbSHx3XmVo2q+HdHEU7+B7AdZAZzS2/UrNoPBYex8Zip9YqhqO0X +nCa42pJj0lOH5vztRN6UVpA+oqFnCMs41M8XO37/epfAewIDAQABoAAwDQYJKoZI +hvcNAQEFBQADgYEADbuni6Yq0l5FJGFDUaabv4T75XxyMWy+k6wSojSt1thtwcJI +Bx5x1ngG5VyxeNmqyjLvd2KeYsVaV8M9J9ty40QGL8F83OArJPGADtBSM+gwmjdu +C+ksYL+5Yl8vSY3M7tKqJB2AFk2QlfP5okMQWRJ5QFTTwA8EFpHFsy4gsks= +-----END CERTIFICATE REQUEST----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/serial new file mode 100644 index 000000000..dd1172404 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/demoCA/serial @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/openssl.cfg new file mode 100644 index 000000000..51e520525 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_2/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/cacert.pem new file mode 100644 index 000000000..c14880b58 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/cacert.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 3 + Validity + Not Before: Nov 20 07:40:39 2009 GMT + Not After : Nov 14 07:40:39 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 3 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:9e:87:1f:af:f0:a0:1c:f4:9e:f8:c3:e7:ee:d3: + cb:a8:e2:54:98:ba:dd:7e:dc:6e:14:e1:7e:7f:5b: + 1e:ef:53:3d:89:76:ea:e2:b3:6c:08:0d:e8:c8:4d: + 24:40:ff:92:f3:5b:51:f7:90:ac:69:37:29:90:f5: + e8:95:6f:67:d1:10:cd:7b:dd:65:38:d6:25:ec:63: + 39:ba:2e:ea:13:58:8e:7a:82:8e:10:d1:7b:77:7a: + 08:d5:82:66:62:a4:83:39:ad:f5:83:d5:2f:5c:bc: + 23:6e:c8:78:8b:38:9f:eb:a3:67:ba:43:fa:e4:07: + 3f:90:72:db:0c:f9:49:0e:0d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 1B:2D:E0:A2:26:7F:0D:BA:38:7E:EC:06:81:81:0F:12:74:4C:5A:4D + X509v3 Authority Key Identifier: + keyid:69:FF:30:EC:1F:34:9A:67:3A:6B:20:D2:DF:7F:F5:05:04:ED:F9:1C + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 3 + serial:95:6F:F0:E3:2B:BE:76:F9 + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 6f:ac:53:9d:16:6e:95:ed:97:60:ed:c8:a8:96:ab:24:c5:1e: + d5:d7:26:98:fb:b5:aa:ef:da:a4:91:6a:82:55:ec:21:a2:08: + 24:c7:0c:a7:58:0c:06:69:3d:04:7d:08:f1:0b:77:41:ad:1c: + 13:c2:bd:17:c9:9e:ff:df:64:69:8b:58:f1:bc:40:bd:cf:e4: + 57:29:bc:5e:93:84:61:56:4c:e6:c1:3a:2c:6e:71:ea:5d:67: + c0:54:be:4f:2f:27:a8:59:8d:29:94:ba:c6:6c:ff:ed:25:3d: + 0b:fa:93:c9:45:f4:d5:a3:3d:be:8a:f1:9d:c4:92:d5:5c:d2: + 77:7c +-----BEGIN CERTIFICATE----- +MIIDBjCCAm+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCAzMB4XDTA5MTEyMDA3NDAz +OVoXDTM0MTExNDA3NDAzOVowaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCAzMIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQCehx+v8KAc9J74w+fu08uo4lSYut1+3G4U4X5/Wx7vUz2Jduris2wI +DejITSRA/5LzW1H3kKxpNymQ9eiVb2fREM173WU41iXsYzm6LuoTWI56go4Q0Xt3 +egjVgmZipIM5rfWD1S9cvCNuyHiLOJ/ro2e6Q/rkBz+QctsM+UkODQIDAQABo4HH +MIHEMB0GA1UdDgQWBBQbLeCiJn8Nujh+7AaBgQ8SdExaTTCBkQYDVR0jBIGJMIGG +gBRp/zDsHzSaZzprINLff/UFBO35HKFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCAzggkAlW/w4yu+dvkwDwYDVR0TAQH/ +BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBvrFOdFm6V7Zdg7ciolqskxR7V1yaY ++7Wq79qkkWqCVewhoggkxwynWAwGaT0EfQjxC3dBrRwTwr0XyZ7/32Rpi1jxvEC9 +z+RXKbxek4RhVkzmwTosbnHqXWfAVL5PLyeoWY0plLrGbP/tJT0L+pPJRfTVoz2+ +ivGdxJLVXNJ3fA== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/crl/DO_NOT_CREATE_A_CRL b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/crl/DO_NOT_CREATE_A_CRL new file mode 100644 index 000000000..e69de29bb diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/crlnumber new file mode 100644 index 000000000..83b33d238 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/crlnumber @@ -0,0 +1 @@ +1000 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/index.txt new file mode 100644 index 000000000..bd3b5eaea --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/index.txt @@ -0,0 +1 @@ +V 341114075225Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 1 Root 3 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/index.txt.attr new file mode 100644 index 000000000..8f7e63a34 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/newcerts/1000.pem new file mode 100644 index 000000000..46d60bda0 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/newcerts/1000.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 3 + Validity + Not Before: Nov 20 07:52:25 2009 GMT + Not After : Nov 14 07:52:25 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 1 Root 3 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:bc:82:f1:75:77:02:f8:fb:3a:c2:8d:3c:1b:cb: + b2:63:2e:89:07:92:6b:b4:e1:ab:ce:30:a1:a4:82: + 38:30:64:2a:ba:01:c6:ac:ee:03:cc:65:bf:83:3e: + 39:b8:ce:ac:45:99:97:f9:94:e2:7d:5d:f3:c5:f7: + d4:a5:d6:57:cf:24:c1:d7:56:eb:00:9c:5d:80:bc: + 23:0c:91:d6:8e:2a:62:f6:af:4d:c9:19:5b:dd:16: + be:21:54:51:71:be:f2:c6:64:c5:bb:8e:37:49:c9: + 4d:68:82:3a:42:8a:e3:de:ab:fa:c7:ff:a5:b4:c7: + 53:8f:17:a4:66:9d:c3:8e:b1 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + Netscape Comment: + OpenSSL Generated Certificate + X509v3 Subject Key Identifier: + 0B:DD:2E:E9:5C:8A:5F:67:C9:75:4C:B3:04:DB:95:2F:D8:74:76:EF + X509v3 Authority Key Identifier: + keyid:1B:2D:E0:A2:26:7F:0D:BA:38:7E:EC:06:81:81:0F:12:74:4C:5A:4D + + Signature Algorithm: sha1WithRSAEncryption + 18:2f:af:1a:27:c7:f8:81:cd:d5:31:a0:f2:06:05:94:d6:12: + 11:88:24:ae:4f:f6:86:18:bf:d0:1b:c9:19:7a:47:30:0e:fb: + 30:b2:50:31:8d:30:6b:8b:54:17:67:bc:b8:c1:d5:1c:6c:95: + c5:e4:c4:ad:12:39:2f:38:ee:53:6a:cf:be:1c:4f:ac:98:0c: + ea:eb:0b:48:3d:5e:7a:2b:ed:02:8b:34:89:0a:d8:32:b4:6f: + f4:b2:06:96:aa:6b:ae:19:38:ec:9f:47:43:3b:7b:bd:71:38: + 99:4f:b4:1e:87:95:73:63:76:d4:ff:21:57:2c:c3:f4:3c:fd: + cb:c3 +-----BEGIN CERTIFICATE----- +MIICyzCCAjSgAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCAzMB4XDTA5 +MTEyMDA3NTIyNVoXDTM0MTExNDA3NTIyNVowbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAxIFN1YiBDQSAxIFJvb3QgMzCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvILxdXcC+Ps6wo08G8uyYy6JB5JrtOGr +zjChpII4MGQqugHGrO4DzGW/gz45uM6sRZmX+ZTifV3zxffUpdZXzyTB11brAJxd +gLwjDJHWjipi9q9NyRlb3Ra+IVRRcb7yxmTFu443SclNaII6Qorj3qv6x/+ltMdT +jxekZp3DjrECAwEAAaN9MHswCwYDVR0PBAQDAgXgMCwGCWCGSAGG+EIBDQQfFh1P +cGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUC90u6VyKX2fJ +dUyzBNuVL9h0du8wHwYDVR0jBBgwFoAUGy3goiZ/Dbo4fuwGgYEPEnRMWk0wDQYJ +KoZIhvcNAQEFBQADgYEAGC+vGifH+IHN1TGg8gYFlNYSEYgkrk/2hhi/0BvJGXpH +MA77MLJQMY0wa4tUF2e8uMHVHGyVxeTErRI5LzjuU2rPvhxPrJgM6usLSD1eeivt +Aos0iQrYMrRv9LIGlqprrhk47J9HQzt7vXE4mU+0HoeVc2N21P8hVyzD9Dz9y8M= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/private/cakey.pem new file mode 100644 index 000000000..8d893cdf9 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,EF032FCF0827A7AA + +vTlvOy1d4MK41zEZfeUWDO7kjLqZ53jK6JdXhKT2P9MnstGf1S0QxwbEKP+KWj+4 +lwS7fSXs6/s2Q5OrG9QSV4bm5Sob0OpDfoc1GS24uSGvYXzhuyM9sjiITXvyGKCH ++0VQPV/GSXWShsk5CCzUXIBSBHDVxlEzmBvzWiHfcLEAwF1JJlh6ex9Xju9JL9sN +Gp4VMw9PML11V4iqNXKeyBZ87Bv/yew+bDACLCe7e1liBxdOj2ntc7mtpCrkf/pn +hLnJ1qKodcwgmmMLufa7//E1RCBMn1gml0YXMe+Grrn7tFdVWT/puKiSrKGgIbbB +RNf7JnG5E8Oy2V8NRk4SV5Au784fw5NMykQDCMJFp9aldwP7LlIUBPtPm/jpaY0V +e6tKT20e4Ru2mDzyfef8nhFRogMxvPrxVSxN8aI1u/soPMp55ypWrqg99QlsiZgG +MhpHaFODSWvHaFcwFY+gEDUmEH76S3wuOSgeFolvIPEETjw6Vc46Zi32N1ycQ1wz +NCbIGy2ftEzKIEOeXHAsuQiP+Cic1QYJEOxhvOq9VteYfilT7D9FQ2+QOqrl4+2X +hj2RaTJawpSFoWfEh7QM1ir0TPj3wRSTg6g3e0f+vAvI9AfVEP3ctPm6tpXirUgh +QOA1LZKZzHUYqr0q2TBvItyGsg3w7dxyeB6brCtzOzg+GpvNhaRZ1/+SVPxzYVgf +buLQIfvvLE6TmABxOloop1m61u6c6+Bg5kKHXSnUKehGv+iIxVLZgxrNkCFyyzX0 +Dpu9hkGYzVzE8QCujC09MZCKH/85iYGuEZtP81Mjyjs= +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/req.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/req.pem new file mode 100644 index 000000000..dd08bf671 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/req.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIBqDCCARECAQAwaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1cmcxFzAV +BgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVudDEYMBYG +A1UEAxMPU3ViIENBIDEgUm9vdCAzMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB +gQCehx+v8KAc9J74w+fu08uo4lSYut1+3G4U4X5/Wx7vUz2Jduris2wIDejITSRA +/5LzW1H3kKxpNymQ9eiVb2fREM173WU41iXsYzm6LuoTWI56go4Q0Xt3egjVgmZi +pIM5rfWD1S9cvCNuyHiLOJ/ro2e6Q/rkBz+QctsM+UkODQIDAQABoAAwDQYJKoZI +hvcNAQEFBQADgYEAiwW4WbC3V3wEBfPlIFiUagJHOettp5NyCzLULyQZE1FXs/zV +RxIi3Oxdaj643QZ8h6upKf9F60T8+oG15RBdp1ZjmBXnv7ZRx33LynExbxX0XKjo +Pg/8dGLFBomZqE8MpWbQtY5lRkQOkgt5XZLj5SMJQsgpVaAOPQcOg5Sqfag= +-----END CERTIFICATE REQUEST----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/serial new file mode 100644 index 000000000..dd1172404 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/demoCA/serial @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/openssl.cfg new file mode 100644 index 000000000..51e520525 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_3/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/README.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/README.txt new file mode 100644 index 000000000..3ac354b8f --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/README.txt @@ -0,0 +1,4 @@ +Revoked certificates: +--------------------- +- User 2 Sub CA 1 Root 4 + diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/cacert.pem new file mode 100644 index 000000000..391037118 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/cacert.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 4 + Validity + Not Before: Nov 20 08:37:27 2009 GMT + Not After : Nov 14 08:37:27 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 4 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:da:b0:21:94:89:b0:00:89:cb:69:59:9b:0d:fe: + 1f:b9:a0:a8:44:92:55:5f:0b:d5:e5:08:63:bd:47: + 6b:11:4d:b1:a8:12:6f:c1:cf:cb:9e:ae:e2:c1:03: + 68:46:59:0b:96:7c:21:45:9b:14:81:d8:f1:83:70: + 6b:3d:b4:56:65:49:87:1d:ab:e2:08:6a:49:66:0e: + 59:b4:da:7a:3f:72:23:b8:1f:fb:78:f5:f0:2d:c4: + fe:d9:94:6e:2e:c3:6e:95:ba:38:60:d1:0b:fa:16: + c7:02:71:ef:3e:71:72:63:26:56:35:1e:8b:ec:47: + 87:25:6e:bc:90:d0:8b:37:2d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 96:9A:2D:06:F6:76:4F:83:68:7B:9C:69:C4:18:BB:4A:EB:46:38:E4 + X509v3 Authority Key Identifier: + keyid:BA:8D:A1:97:DC:C4:39:1F:90:B5:51:6B:10:19:F2:46:0D:A9:65:8E + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 4 + serial:A2:93:46:74:3B:A6:E3:AD + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 45:77:ba:6b:b6:a7:2a:0f:6b:38:90:9f:0a:18:11:c7:54:7b: + c9:3b:9a:93:90:96:f0:04:0a:56:87:30:e0:f5:d8:84:40:39: + 90:85:ca:e7:38:1b:d8:df:2f:bd:73:91:13:cb:a6:c9:b0:7a: + f7:59:77:6b:9a:d5:86:78:06:dc:40:14:ce:ea:43:a8:ae:ed: + a2:03:64:51:3a:47:7a:9f:df:2d:65:49:56:a5:39:cf:28:2a: + ac:ab:fd:e1:93:fd:3e:56:e8:eb:7a:11:a8:f7:f9:1a:a1:83: + 1f:92:f7:da:4e:c6:d9:67:dd:67:ff:be:6f:e5:24:e1:6e:cc: + 94:3c +-----BEGIN CERTIFICATE----- +MIIDBjCCAm+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA0MB4XDTA5MTEyMDA4Mzcy +N1oXDTM0MTExNDA4MzcyN1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA0MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDasCGUibAAictpWZsN/h+5oKhEklVfC9XlCGO9R2sRTbGoEm/Bz8ue +ruLBA2hGWQuWfCFFmxSB2PGDcGs9tFZlSYcdq+IIaklmDlm02no/ciO4H/t49fAt +xP7ZlG4uw26Vujhg0Qv6FscCce8+cXJjJlY1HovsR4clbryQ0Is3LQIDAQABo4HH +MIHEMB0GA1UdDgQWBBSWmi0G9nZPg2h7nGnEGLtK60Y45DCBkQYDVR0jBIGJMIGG +gBS6jaGX3MQ5H5C1UWsQGfJGDalljqFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA0ggkAopNGdDum460wDwYDVR0TAQH/ +BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBFd7prtqcqD2s4kJ8KGBHHVHvJO5qT +kJbwBApWhzDg9diEQDmQhcrnOBvY3y+9c5ETy6bJsHr3WXdrmtWGeAbcQBTO6kOo +ru2iA2RROkd6n98tZUlWpTnPKCqsq/3hk/0+VujrehGo9/kaoYMfkvfaTsbZZ91n +/75v5SThbsyUPA== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/crlnumber new file mode 100644 index 000000000..dd1172404 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/crlnumber @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/index.txt new file mode 100644 index 000000000..88e41b76a --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/index.txt @@ -0,0 +1,2 @@ +V 341114084401Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 1 Root 4 +R 341114085720Z 091120085929Z,keyCompromise 1001 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 2 Sub CA 1 Root 4 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/index.txt.attr new file mode 100644 index 000000000..8f7e63a34 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/newcerts/1000.pem new file mode 100644 index 000000000..73563ed96 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/newcerts/1000.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 4 + Validity + Not Before: Nov 20 08:44:01 2009 GMT + Not After : Nov 14 08:44:01 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 1 Root 4 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:c3:55:aa:1b:4f:f6:b4:78:be:ac:61:2a:92:94: + 73:1b:39:4c:0e:57:7e:da:78:03:7e:65:11:57:97: + e6:f4:0d:72:1f:f6:2b:a4:33:f9:5c:bd:2b:25:6c: + 58:29:73:b9:46:d5:db:e9:03:1d:a2:f8:8e:6e:c2: + b5:95:ec:ba:95:c3:ac:2e:c0:b6:40:ba:23:1d:74: + 75:91:cc:d6:3a:4c:15:4d:15:03:a4:e6:80:4a:93: + fe:6c:91:ab:77:60:3b:43:65:21:cd:04:3d:01:71: + 99:47:28:12:c8:9d:f9:d7:25:7a:30:82:76:c0:27: + 5e:c3:70:42:54:2a:0a:02:97 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + Netscape Comment: + OpenSSL Generated Certificate + X509v3 Subject Key Identifier: + D5:2F:1A:60:8E:F9:2E:8F:51:EB:F7:AB:24:47:80:CE:B6:8D:F1:63 + X509v3 Authority Key Identifier: + keyid:96:9A:2D:06:F6:76:4F:83:68:7B:9C:69:C4:18:BB:4A:EB:46:38:E4 + + Signature Algorithm: sha1WithRSAEncryption + 7a:83:0c:a0:2d:14:52:97:a1:0e:dd:b3:2e:a1:1f:0d:51:e7: + 98:2e:89:9a:36:a3:1b:af:28:95:13:ab:3e:31:2e:f6:fa:5f: + f7:85:8c:01:7a:1b:25:63:7e:d6:f9:8e:ad:84:9e:42:3e:1d: + f4:ad:dc:b1:20:91:83:8b:48:ad:34:2a:b9:cc:ae:06:e6:bc: + e1:05:e6:35:71:ca:43:98:3a:e5:93:52:e1:3c:3a:1b:83:53: + d3:a6:ba:6a:43:38:00:92:ba:fb:8f:a8:17:46:f9:32:ac:42: + 47:87:7f:2e:ae:76:49:88:55:1e:65:70:6c:d6:35:ab:64:48: + a9:66 +-----BEGIN CERTIFICATE----- +MIICyzCCAjSgAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA0MB4XDTA5 +MTEyMDA4NDQwMVoXDTM0MTExNDA4NDQwMVowbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAxIFN1YiBDQSAxIFJvb3QgNDCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAw1WqG0/2tHi+rGEqkpRzGzlMDld+2ngD +fmURV5fm9A1yH/YrpDP5XL0rJWxYKXO5RtXb6QMdoviObsK1ley6lcOsLsC2QLoj +HXR1kczWOkwVTRUDpOaASpP+bJGrd2A7Q2UhzQQ9AXGZRygSyJ351yV6MIJ2wCde +w3BCVCoKApcCAwEAAaN9MHswCwYDVR0PBAQDAgXgMCwGCWCGSAGG+EIBDQQfFh1P +cGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQU1S8aYI75Lo9R +6/erJEeAzraN8WMwHwYDVR0jBBgwFoAUlpotBvZ2T4Noe5xpxBi7SutGOOQwDQYJ +KoZIhvcNAQEFBQADgYEAeoMMoC0UUpehDt2zLqEfDVHnmC6JmjajG68olROrPjEu +9vpf94WMAXobJWN+1vmOrYSeQj4d9K3csSCRg4tIrTQqucyuBua84QXmNXHKQ5g6 +5ZNS4Tw6G4NT06a6akM4AJK6+4+oF0b5MqxCR4d/Lq52SYhVHmVwbNY1q2RIqWY= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/newcerts/1001.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/newcerts/1001.pem new file mode 100644 index 000000000..7068aa0af --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/newcerts/1001.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4097 (0x1001) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 4 + Validity + Not Before: Nov 20 08:57:20 2009 GMT + Not After : Nov 14 08:57:20 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 2 Sub CA 1 Root 4 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:ab:2a:df:93:6c:f0:b1:34:54:15:5b:06:4e:15: + bb:94:53:89:96:96:47:db:43:49:e7:66:d5:6b:53: + eb:04:54:d0:96:48:08:8f:8e:cc:70:e1:62:88:6a: + f3:ff:bc:65:55:b9:55:a6:29:22:c1:f6:16:9a:01: + 25:86:a9:72:c8:7c:0f:29:87:b9:14:51:34:d2:fc: + 01:3e:20:46:dc:54:3f:f3:03:d8:07:e0:6b:0c:78: + 70:d0:d0:93:83:e2:cf:53:fc:3b:d5:b0:c9:7d:40: + 8b:ee:5d:d3:30:e9:24:01:1e:b0:ac:de:1a:18:97: + a1:0d:58:79:5e:67:cd:99:bf + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + Netscape Comment: + OpenSSL Generated Certificate + X509v3 Subject Key Identifier: + 47:DB:A7:93:38:C2:0F:34:7F:B7:DE:35:C9:23:75:CC:30:93:A4:42 + X509v3 Authority Key Identifier: + keyid:96:9A:2D:06:F6:76:4F:83:68:7B:9C:69:C4:18:BB:4A:EB:46:38:E4 + + Signature Algorithm: sha1WithRSAEncryption + 97:70:47:74:ce:e1:f6:51:bf:cc:cf:0f:cf:cc:23:75:df:4b: + 3d:36:f0:70:0f:47:5d:c7:96:ad:b0:78:95:89:3a:2a:7a:ba: + 79:45:fe:2f:37:4c:69:76:ab:0a:10:ea:0d:5e:fe:28:04:44: + 9c:f3:8d:43:f5:15:fa:79:be:d3:86:f3:c1:b5:8b:5a:74:a9: + c5:b7:fe:e8:63:6e:1f:13:3a:c9:49:3b:45:0c:a6:64:b9:07: + 9b:1a:30:09:1d:5e:f0:2b:a9:55:aa:41:fa:85:0d:ef:dd:c3: + f5:58:52:bf:7f:6d:f4:18:06:f4:5a:71:af:e4:57:b0:0a:6e: + f6:76 +-----BEGIN CERTIFICATE----- +MIICyzCCAjSgAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA0MB4XDTA5 +MTEyMDA4NTcyMFoXDTM0MTExNDA4NTcyMFowbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAyIFN1YiBDQSAxIFJvb3QgNDCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAqyrfk2zwsTRUFVsGThW7lFOJlpZH20NJ +52bVa1PrBFTQlkgIj47McOFiiGrz/7xlVblVpikiwfYWmgElhqlyyHwPKYe5FFE0 +0vwBPiBG3FQ/8wPYB+BrDHhw0NCTg+LPU/w71bDJfUCL7l3TMOkkAR6wrN4aGJeh +DVh5XmfNmb8CAwEAAaN9MHswCwYDVR0PBAQDAgXgMCwGCWCGSAGG+EIBDQQfFh1P +cGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUR9unkzjCDzR/ +t941ySN1zDCTpEIwHwYDVR0jBBgwFoAUlpotBvZ2T4Noe5xpxBi7SutGOOQwDQYJ +KoZIhvcNAQEFBQADgYEAl3BHdM7h9lG/zM8Pz8wjdd9LPTbwcA9HXceWrbB4lYk6 +Knq6eUX+LzdMaXarChDqDV7+KAREnPONQ/UV+nm+04bzwbWLWnSpxbf+6GNuHxM6 +yUk7RQymZLkHmxowCR1e8CupVapB+oUN793D9VhSv39t9BgG9Fpxr+RXsApu9nY= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/private/cakey.pem new file mode 100644 index 000000000..4c3de720f --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,48187111D008BD14 + +9y5tseMMq8fPCuUelw75mRr1ALSrxNWatiMrmFM44I27wxIlaVgePNk3ovpuUpjB +RTArkp0zqA8tHCE/ZzE0cKtkxabTfrghxeKb2lAIrIUFwAFnMPEoB69M23qKblQD +/CbYquy6mpjzLBYwM0Ub8fj4d6fMCJ29Mqlbzj9XJ2oif8zW90lxE4CZNGEWKWaO +pF0ytqUM0aVIBVXZOGmeUpJlAgwdshYHD0JwoULWzFOa+9aks+wjYwQcDxbPq3YC +TBSzHiKd68YSDvK5VevIAIrSKEEqrXgsnL0k23/xkK5ZN8w9gmROrwpqg78Aa/cp +13luMYMRAm+hBfCFzKXvc8hV49UCPWOJcB4/p8to8Bx95UcJ17npG71yrNJgwTA6 +Wgj4pxtddt4QItVqv6usIvkMwD4pQqZ4y+5UMEvw2paG428+SN6YElH6/6yB/9Cc +B7BxhhaazM+AEulpvvfQgjpIqn5+QyaZ7GVcNh/Bi66tenNv9NBVqP1PmuZUMF77 +QddQGzCpxaSb/x/3InhMP2PgGN37B9ezm8ee+AQpmk1VzJ5zpiuoGbQ3oLnDVMKS +aNe7VIyhovq7tnJIuIft8jOEMFfPot9vgIwnHVQ4PF+KK0bzWjSK+6HyO+1Jkw/5 +TpHfQSxEVf8brC8g9l7+FjGSbHF80EzOUx1lMDe/BUzuVvRhiewqrlkCrPf90uuy +hEf1UKqrDK2i2iLBzZ0+OXba3wj20jFRaYLN5YykE6fKo/H6UjEn203nMI2Qi+2m +5j5dgDAOXnNWQN45MxIMu6xxPSaEcb8YUgfMqwytfVmo/xSioyoV+w== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/serial new file mode 100644 index 000000000..7d802a3e7 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/demoCA/serial @@ -0,0 +1 @@ +1002 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/openssl.cfg new file mode 100644 index 000000000..51e520525 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_4/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/README.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/README.txt new file mode 100644 index 000000000..b266749a9 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/README.txt @@ -0,0 +1,5 @@ +To provide the CRL via HTTP run + +java -jar ../../tools/httpserv/dist/httpserv.jar -a 8902 + + diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/cacert.pem new file mode 100644 index 000000000..b350f6eb3 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/cacert.pem @@ -0,0 +1,66 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4097 (0x1001) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 5 + Validity + Not Before: Nov 20 11:30:23 2009 GMT + Not After : Nov 14 11:30:23 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 5 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:97:fa:a2:49:d3:bf:c1:2e:7a:ed:83:83:3c:78: + 96:c8:b2:b9:67:af:c0:5e:0a:89:89:fb:94:59:32: + a8:2a:e4:20:2f:3b:3d:ce:53:4f:72:fc:6c:0b:93: + 38:c3:df:66:6e:d5:79:d0:a4:4e:41:84:43:3c:99: + 79:0c:e0:5f:19:1a:3d:f5:4b:11:28:0f:80:b0:a0: + 71:34:5b:90:71:c2:ef:1e:85:2e:5b:9f:3b:22:c3: + 18:f8:7c:1f:ef:1b:78:17:a0:44:60:46:7e:88:eb: + a7:60:a0:5c:2a:7c:37:99:fa:27:97:08:e8:89:ba: + bc:69:4b:79:93:8f:ad:b5:9b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 01:E9:B5:99:E4:6D:F9:8C:42:3D:09:10:0F:A7:75:C6:27:78:4A:AF + X509v3 Authority Key Identifier: + keyid:C1:D1:A0:D4:5B:0B:9D:7E:31:61:F9:39:10:9F:31:10:E0:D2:06:B5 + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 5 + serial:F0:3D:B6:A9:A9:9C:A3:4E + + X509v3 CRL Distribution Points: + URI:http://localhost:8901/demoCA/crl/Root_5.crl + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 6d:ca:34:05:99:ff:99:49:d3:6d:9d:ad:c6:99:da:9d:6c:94: + 62:77:ed:1c:39:23:d2:e8:b6:3e:df:63:dc:7c:10:3f:c2:ed: + f4:04:26:58:05:01:4c:ed:a9:83:43:3a:5d:fe:60:6d:5b:58: + dc:93:8c:94:69:b6:7f:02:48:30:9c:31:f4:7d:de:e0:de:04: + d2:dc:79:b7:60:c2:87:f7:c7:92:a2:f5:86:a7:0c:70:3b:a3: + a7:35:11:cf:a4:28:21:aa:8b:24:50:2e:96:41:be:66:01:bd: + b9:ec:04:0c:92:d9:8a:e7:a0:96:24:9b:f1:a2:9f:59:59:4a: + 32:a4 +-----BEGIN CERTIFICATE----- +MIIDRjCCAq+gAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA1MB4XDTA5MTEyMDExMzAy +M1oXDTM0MTExNDExMzAyM1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA1MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQCX+qJJ07/BLnrtg4M8eJbIsrlnr8BeComJ+5RZMqgq5CAvOz3OU09y +/GwLkzjD32Zu1XnQpE5BhEM8mXkM4F8ZGj31SxEoD4CwoHE0W5Bxwu8ehS5bnzsi +wxj4fB/vG3gXoERgRn6I66dgoFwqfDeZ+ieXCOiJurxpS3mTj621mwIDAQABo4IB +BjCCAQIwHQYDVR0OBBYEFAHptZnkbfmMQj0JEA+ndcYneEqvMIGRBgNVHSMEgYkw +gYaAFMHRoNRbC51+MWH5ORCfMRDg0ga1oWOkYTBfMQswCQYDVQQGEwJERTEQMA4G +A1UECBMHSGFtYnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsT +C0RldmVsb3BtZW50MQ8wDQYDVQQDEwZSb290IDWCCQDwPbapqZyjTjA8BgNVHR8E +NTAzMDGgL6AthitodHRwOi8vbG9jYWxob3N0Ojg5MDEvZGVtb0NBL2NybC9Sb290 +XzUuY3JsMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAbco0BZn/ +mUnTbZ2txpnanWyUYnftHDkj0ui2Pt9j3HwQP8Lt9AQmWAUBTO2pg0M6Xf5gbVtY +3JOMlGm2fwJIMJwx9H3e4N4E0tx5t2DCh/fHkqL1hqcMcDujpzURz6QoIaqLJFAu +lkG+ZgG9uewEDJLZiuegliSb8aKfWVlKMqQ= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/crl/DO_NOT_INSTALL_THIS_CRL b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/crl/DO_NOT_INSTALL_THIS_CRL new file mode 100644 index 000000000..e69de29bb 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 000000000..3aec2bba1 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 000000000..dd1172404 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/crlnumber @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/index.txt new file mode 100644 index 000000000..2f83d6f9b --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/index.txt @@ -0,0 +1 @@ +V 341114113322Z 1002 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 1 Root 5 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/index.txt.attr new file mode 100644 index 000000000..8f7e63a34 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/newcerts/1002.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/newcerts/1002.pem new file mode 100644 index 000000000..59d5f7a2b --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/newcerts/1002.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4098 (0x1002) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 5 + Validity + Not Before: Nov 20 11:33:22 2009 GMT + Not After : Nov 14 11:33:22 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 1 Root 5 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:d3:fd:a7:4f:ea:02:e2:b4:32:80:3f:64:bb:37: + 9d:9e:fa:86:b2:25:b3:1d:f6:5d:05:8e:2b:0c:bd: + 60:1e:e6:52:39:4c:84:9e:93:6c:d2:b4:2d:34:1a: + e7:42:b6:bf:34:bd:ca:44:31:fb:06:5e:20:0a:a1: + 22:ca:9b:4f:01:57:bd:b1:30:57:a9:0f:fc:06:ae: + 18:6c:2d:9e:70:7a:21:2a:fd:0c:f8:03:00:32:60: + 5d:37:c5:11:56:74:30:e4:03:3c:88:71:d5:79:d3: + 76:02:e1:85:87:63:4b:5b:cd:c9:1f:ca:85:7a:8c: + 3a:fd:a9:83:94:b9:6d:f6:95 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 CRL Distribution Points: + URI:http://localhost:8902/demoCA/crl/Sub_CA_1_Root_5.crl + + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + E0:53:2E:E4:6B:0B:99:C0:AD:C1:02:40:46:6C:35:EE:49:73:5D:0B + X509v3 Authority Key Identifier: + keyid:01:E9:B5:99:E4:6D:F9:8C:42:3D:09:10:0F:A7:75:C6:27:78:4A:AF + + Signature Algorithm: sha1WithRSAEncryption + 5f:6a:81:3b:56:e8:6d:33:0e:1e:6a:73:b1:e8:69:b7:3f:83: + 81:6c:73:7c:9d:f7:12:c9:bf:99:16:cf:56:38:e4:58:db:28: + a5:9c:e3:8e:ed:27:d2:da:53:41:80:2a:d4:c3:92:5d:b5:b4: + 5a:d6:17:f7:74:9d:83:13:06:7f:20:8e:50:5f:60:5b:3a:9a: + 9f:c2:58:5f:fa:07:90:df:a0:02:cf:c4:d7:7d:2e:b7:72:df: + 8f:93:ce:5a:b3:17:ba:73:93:20:64:b9:b2:ad:6e:89:63:c5: + 08:e1:a0:6a:b2:9d:1e:33:31:83:98:d1:05:7d:ec:48:72:1f: + dd:60 +-----BEGIN CERTIFICATE----- +MIIC5jCCAk+gAwIBAgICEAIwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA1MB4XDTA5 +MTEyMDExMzMyMloXDTM0MTExNDExMzMyMlowbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAxIFN1YiBDQSAxIFJvb3QgNTCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0/2nT+oC4rQygD9kuzednvqGsiWzHfZd +BY4rDL1gHuZSOUyEnpNs0rQtNBrnQra/NL3KRDH7Bl4gCqEiyptPAVe9sTBXqQ/8 +Bq4YbC2ecHohKv0M+AMAMmBdN8URVnQw5AM8iHHVedN2AuGFh2NLW83JH8qFeow6 +/amDlLlt9pUCAwEAAaOBlzCBlDBFBgNVHR8EPjA8MDqgOKA2hjRodHRwOi8vbG9j +YWxob3N0Ojg5MDIvZGVtb0NBL2NybC9TdWJfQ0FfMV9Sb290XzUuY3JsMAsGA1Ud +DwQEAwIF4DAdBgNVHQ4EFgQU4FMu5GsLmcCtwQJARmw17klzXQswHwYDVR0jBBgw +FoAUAem1meRt+YxCPQkQD6d1xid4Sq8wDQYJKoZIhvcNAQEFBQADgYEAX2qBO1bo +bTMOHmpzsehptz+DgWxzfJ33Esm/mRbPVjjkWNsopZzjju0n0tpTQYAq1MOSXbW0 +WtYX93SdgxMGfyCOUF9gWzqan8JYX/oHkN+gAs/E130ut3Lfj5POWrMXunOTIGS5 +sq1uiWPFCOGgarKdHjMxg5jRBX3sSHIf3WA= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/private/cakey.pem new file mode 100644 index 000000000..fb9af1caa --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,30B50FFE9747C5F2 + +pXO59gJmBcDztjZDwRRcJV+m/BBdF/NlI0WD7WBr4vR663B6hZw0hqAkCn3o0VbO +DzLsoQUMUv/70aXc2SgvS8LleG+mWCkPE+huzFjPAn6Z6+p0MhHrYRJ7iulPAVV0 ++wCs8+1UbvKyozLy+BfvEwGHEho8sr3w81y2noE2pjaQOE1JGKY91VnFz1yPhYHC +r26sO1DqoqtWS8XSe2FdREG/guKpoHtoUazQhCkgeBk18OImKlrxp1pT/haObv5i +5qILjSvMBjmrTCJDi1vgShEiAZTE318ipK5wCLKiA6UvZ3GMxb2xjy+na3CUTrzf +AAefrW4NaoyIWI8dRtPxFic678ZgqcRMdMW7BgdffLXX5IueCqHeTNS7xcr2T2gd +hzKxinZnY8MQosFeyzP3fYWxv5PY54HNmCnsN2SXJSOq+CPSsIvbDR5p1bhrcEf9 +1O815NhJTx2nPAkIC+7bemAkz2f3g09SuhtQTaCnZMwcAmnMAT0ewWJSxDCVOg5s +B/OPe8RJ1tiO7DnaZH6RQDPUCKaUgS9xSzCu1q0IWWbzUWioPIX13fFlvl9gAxbY ++FI6dD2DwHBTyiPLLyT7FBfwjnHul2zSn/jXnby7n1sILQIP0AQK0cJDS1ZdC2CB +oe4gwzSVCxp7v3Zfp1ZoyYOtei0gT6+bDvjBYsl90jyvyucWfKjlZiEauQV8gSOQ +G2iY5QZ0clAFg7MQKmHuTaAALk0IrauSW20eR/HF0/2R6xCt91zcyhwbOiZFNyQ3 +gtvwLu9ZzAHfWcnIEWxpYF68O+vj+g6Jpl/q6j8KaTta3smEBzgpow== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/serial new file mode 100644 index 000000000..baccd0398 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/demoCA/serial @@ -0,0 +1 @@ +1003 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/openssl.cfg new file mode 100644 index 000000000..963ab884f --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_5/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ +crlDistributionPoints=URI:http://localhost:8902/demoCA/crl/Sub_CA_1_Root_5.crl +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +#nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/cacert.pem new file mode 100644 index 000000000..0490b88cd --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/cacert.pem @@ -0,0 +1,66 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4097 (0x1001) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 6 + Validity + Not Before: Nov 20 12:28:07 2009 GMT + Not After : Nov 14 12:28:07 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 6 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:c4:d9:ab:27:06:66:41:0e:36:ff:d4:b1:d0:8c: + f7:b4:25:55:cd:fd:fa:a4:5a:e6:4f:d0:05:dc:a3: + e5:bd:8d:53:77:d1:ea:95:5a:52:81:c8:b6:36:a0: + 5f:3a:e1:85:1e:8a:48:91:7d:29:78:ff:ea:c5:e3: + ad:c4:27:d5:b7:8f:59:20:26:d4:45:87:6a:56:db: + ac:f5:f8:0a:88:82:9e:c2:00:06:fc:98:8a:fe:35: + c3:02:a1:67:08:06:42:e3:88:48:e0:8f:33:ff:f8: + a4:87:1a:3a:d9:54:0e:1c:09:3e:a0:f0:70:cd:b5: + b0:b2:7e:07:73:ad:20:64:69 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 89:8C:D7:71:EB:67:78:4E:D6:01:35:B2:AC:A1:B4:88:43:CE:70:A7 + X509v3 Authority Key Identifier: + keyid:AC:25:5E:9B:B5:BA:4D:8E:BD:77:B2:9D:D9:E2:84:AE:7A:31:8F:F2 + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 6 + serial:D8:6A:4F:24:F9:C9:94:27 + + X509v3 CRL Distribution Points: + URI:http://localhost:8901/demoCA/crl/Root_6.crl + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 55:5b:3b:6b:8a:d0:1b:d8:19:d9:96:85:4d:b4:a0:98:b1:bd: + 9f:0b:62:21:92:8b:4e:d3:d0:1b:91:3d:e3:f5:bd:ce:16:57: + fc:b7:84:15:51:fd:98:ab:32:59:28:0b:44:57:49:ec:ac:11: + 67:26:7a:a3:c5:b8:9d:2a:de:b6:7c:76:0a:e9:18:9f:98:87: + e8:80:c8:72:99:56:74:ab:73:1b:f4:e7:b9:b1:3a:f3:7b:0d: + 2f:5d:82:6c:d1:99:9f:23:be:23:fb:4c:0e:15:5e:f5:9f:90: + 88:d7:51:3a:6a:7a:f0:54:a5:c4:89:a5:0d:0a:4e:94:59:64: + 59:54 +-----BEGIN CERTIFICATE----- +MIIDRjCCAq+gAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA2MB4XDTA5MTEyMDEyMjgw +N1oXDTM0MTExNDEyMjgwN1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA2MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDE2asnBmZBDjb/1LHQjPe0JVXN/fqkWuZP0AXco+W9jVN30eqVWlKB +yLY2oF864YUeikiRfSl4/+rF463EJ9W3j1kgJtRFh2pW26z1+AqIgp7CAAb8mIr+ +NcMCoWcIBkLjiEjgjzP/+KSHGjrZVA4cCT6g8HDNtbCyfgdzrSBkaQIDAQABo4IB +BjCCAQIwHQYDVR0OBBYEFImM13HrZ3hO1gE1sqyhtIhDznCnMIGRBgNVHSMEgYkw +gYaAFKwlXpu1uk2OvXeyndnihK56MY/yoWOkYTBfMQswCQYDVQQGEwJERTEQMA4G +A1UECBMHSGFtYnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsT +C0RldmVsb3BtZW50MQ8wDQYDVQQDEwZSb290IDaCCQDYak8k+cmUJzA8BgNVHR8E +NTAzMDGgL6AthitodHRwOi8vbG9jYWxob3N0Ojg5MDEvZGVtb0NBL2NybC9Sb290 +XzYuY3JsMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAVVs7a4rQ +G9gZ2ZaFTbSgmLG9nwtiIZKLTtPQG5E94/W9zhZX/LeEFVH9mKsyWSgLRFdJ7KwR +ZyZ6o8W4nSretnx2CukYn5iH6IDIcplWdKtzG/TnubE683sNL12CbNGZnyO+I/tM +DhVe9Z+QiNdROmp68FSlxImlDQpOlFlkWVQ= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/crl/DO_NOT_CREATE_A_CRL b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/crl/DO_NOT_CREATE_A_CRL new file mode 100644 index 000000000..e69de29bb diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/crlnumber new file mode 100644 index 000000000..83b33d238 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/crlnumber @@ -0,0 +1 @@ +1000 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/index.txt new file mode 100644 index 000000000..6e4d7577d --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/index.txt @@ -0,0 +1 @@ +V 341114123743Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 1 Root 6 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/index.txt.attr new file mode 100644 index 000000000..8f7e63a34 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/newcerts/1000.pem new file mode 100644 index 000000000..538cb4e0b --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/newcerts/1000.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 6 + Validity + Not Before: Nov 20 12:37:43 2009 GMT + Not After : Nov 14 12:37:43 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 1 Root 6 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:bb:ac:68:10:41:28:94:fd:fe:39:5e:63:cf:eb: + 9f:2b:20:82:f3:86:d2:e1:38:05:7e:95:cc:46:e5: + 42:8b:5c:0d:2c:ad:ad:44:c0:4c:2f:7c:75:e8:bd: + aa:cd:f2:05:16:18:a5:a3:fa:e7:a0:ba:57:31:e2: + b0:4d:85:9d:60:e4:41:92:49:3f:e1:79:47:52:e8: + 9e:71:be:88:10:6c:30:89:9f:55:84:9d:83:d0:c9: + 11:66:95:33:8b:44:38:86:45:05:b3:3a:54:c4:cf: + 4e:72:4c:00:07:d7:59:3a:8d:2f:cd:5e:0c:a0:95: + be:00:85:7a:a4:42:c2:f3:b7 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 CRL Distribution Points: + URI:http://localhost:8902/demoCA/crl/Sub_CA_1_Root_6.crl + + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 57:51:A4:44:AE:92:01:3C:9F:7E:82:67:C0:E5:B9:D7:A6:8F:A5:79 + X509v3 Authority Key Identifier: + keyid:89:8C:D7:71:EB:67:78:4E:D6:01:35:B2:AC:A1:B4:88:43:CE:70:A7 + + Signature Algorithm: sha1WithRSAEncryption + 7b:de:f2:2b:d7:94:ce:12:e2:f9:a7:b2:91:08:c6:51:3f:bc: + e2:87:ed:79:6d:3b:f5:38:6e:02:d4:63:e6:b8:a7:e5:df:f4: + 6e:b0:8a:bd:bb:b1:0b:e0:c2:cf:fa:af:0a:6a:a5:1f:28:ff: + de:21:bd:8a:f7:ec:48:35:bb:ab:97:c2:7a:31:6d:d1:73:8e: + ae:74:9b:94:86:73:06:06:da:6a:2c:82:04:b1:49:19:62:a9: + 05:e5:e7:2c:68:a1:3b:f4:bf:80:85:5b:1b:dc:21:7b:3d:c1: + ee:97:6c:72:35:2d:80:19:90:b4:ab:19:34:bb:88:5e:ea:70: + 27:df +-----BEGIN CERTIFICATE----- +MIIC5jCCAk+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA2MB4XDTA5 +MTEyMDEyMzc0M1oXDTM0MTExNDEyMzc0M1owbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAxIFN1YiBDQSAxIFJvb3QgNjCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAu6xoEEEolP3+OV5jz+ufKyCC84bS4TgF +fpXMRuVCi1wNLK2tRMBML3x16L2qzfIFFhilo/rnoLpXMeKwTYWdYORBkkk/4XlH +Uuiecb6IEGwwiZ9VhJ2D0MkRZpUzi0Q4hkUFszpUxM9OckwAB9dZOo0vzV4MoJW+ +AIV6pELC87cCAwEAAaOBlzCBlDBFBgNVHR8EPjA8MDqgOKA2hjRodHRwOi8vbG9j +YWxob3N0Ojg5MDIvZGVtb0NBL2NybC9TdWJfQ0FfMV9Sb290XzYuY3JsMAsGA1Ud +DwQEAwIF4DAdBgNVHQ4EFgQUV1GkRK6SATyffoJnwOW516aPpXkwHwYDVR0jBBgw +FoAUiYzXcetneE7WATWyrKG0iEPOcKcwDQYJKoZIhvcNAQEFBQADgYEAe97yK9eU +zhLi+aeykQjGUT+84ofteW079ThuAtRj5rin5d/0brCKvbuxC+DCz/qvCmqlHyj/ +3iG9ivfsSDW7q5fCejFt0XOOrnSblIZzBgbaaiyCBLFJGWKpBeXnLGihO/S/gIVb +G9whez3B7pdscjUtgBmQtKsZNLuIXupwJ98= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/private/cakey.pem new file mode 100644 index 000000000..9912ee088 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,8F1C89446B1EC221 + +joSSrVc7E1RavSuMdWDDAozXOV4Z0XIusMv5NjIWHLyKdW/SmFv6yfPy7PeuK1Qj +p/DuEO/ULU6SLmAhESXrdC8UzyL/B3hfPK3UzUzJzIRrDitF21SXLjMKU+KVxMrb +GkmstfsIQM157TZHOHJbk4F9zs9Xkl8ipKYDBpJrtVJo8gf4SeLfcEVXW9J0tlLU +Qi13SWWn4kGK+Latypx684S247Y0JfKSJ5BVHUGunmd+b/3mRpH1WARU03JmNqG9 +tyCJxyvCkkQh5Jnm4UEI72ywxSscemtFAzd5fa5LOrsVWOImSixfP1VdJvU0jCTv +gyXK03e/L+B+DhbUm2a6xkt+u83hQ2QjoGdmnfKwhX4vdYZBYINlBnHtHn2B8x2o +IXgLQmBFO/heY/K9wJ1BwwqPW31wHG3MhjRY7ooac1JAZsxS0/pU8cR/GNMpKjvE +fer3tGGUvPL3H1v3pT2XAA4Gm9pOtvnOHuLjbzg2mgNZScYMpcqa/vaQ5gXqCnhw +dtFrGVxEEQ5jTL23EAh4WfhPvsnewujr7Rkc6+a8xKpDJOHejgAPJYpXrYHg4poA +L0aQlIFSX1jriGu4KYAQiZO7bouhVWqcf9B3BNewr0kTaD7qq0gDvygCKLyrUyb7 +hqk0TwVfvmk7nYNFLBsTEcsB/el6jqH40oOfFo+ErlQzmdzRrKy9gBEaecDj8DxV +Fa8XPapE81O8WjS09a/WJNPW+3NdrI5wYMg72srOW8ll+AMtiUTWrAY2hIRxzZGt +VntCKwG/3j0v60jg+0wCP+l/IV4pPbV4He3ysxwM6lH1Y86XfaUBiA== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/serial new file mode 100644 index 000000000..dd1172404 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/demoCA/serial @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/openssl.cfg new file mode 100644 index 000000000..188ed62e2 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_6/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ +crlDistributionPoints=URI:http://localhost:8902/demoCA/crl/Sub_CA_1_Root_6.crl +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +#nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/README.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/README.txt new file mode 100644 index 000000000..d70e0550a --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/README.txt @@ -0,0 +1,3 @@ +To provide the CRL run: + +java -jar ../../tools/httpserv/dist/httpserv.jar -a 8902 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/cacert.pem new file mode 100644 index 000000000..2dda8f2b2 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/cacert.pem @@ -0,0 +1,66 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 7 + Validity + Not Before: Nov 20 13:07:53 2009 GMT + Not After : Nov 14 13:07:53 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 7 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:b0:ae:6d:0a:21:ae:8a:92:b1:16:25:d3:08:cb: + ac:b7:4c:53:6d:4b:b3:12:82:40:54:c9:44:28:fc: + 4e:10:e6:65:40:de:70:5d:8b:ab:1f:5c:77:03:43: + 3d:3a:3d:9e:f7:37:66:9a:33:68:a0:cf:ad:8f:f4: + fb:9c:a3:87:57:5d:ec:d6:55:5a:18:b5:e1:2b:d2: + c4:10:fe:f0:01:a5:da:29:ee:c4:af:15:c9:8c:dc: + 7c:45:84:bd:e5:5b:09:1f:16:1d:11:e7:61:e6:22: + e7:1f:c8:86:bf:a1:da:cb:fe:6b:7e:c0:6e:aa:7f: + 97:84:e8:8f:81:69:f1:26:87 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 54:64:15:7E:93:8A:19:C8:F9:B7:EF:60:A0:DF:5C:C8:15:56:C0:EE + X509v3 Authority Key Identifier: + keyid:80:C6:F8:0B:5F:7C:49:E4:86:FD:C8:92:C6:80:70:D9:C0:6F:7B:DE + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 7 + serial:D5:E6:63:5F:18:09:82:89 + + X509v3 CRL Distribution Points: + URI:http://localhost:8901/demoCA/crl/Root_7.crl + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 1a:bc:5a:4b:9a:d5:e8:c0:35:c2:61:0a:58:7d:33:e2:87:01: + 61:83:80:42:8d:1a:7e:b1:9a:58:d5:01:fd:e7:ae:5c:c8:65: + fb:9e:1d:bf:49:ba:ed:40:f4:05:7c:3b:2d:db:0e:53:d0:05: + a0:bd:15:87:c4:37:22:0b:a0:04:a3:ad:cb:57:b2:00:97:ee: + 8f:89:91:8e:7d:0b:e2:27:96:6e:0f:ab:73:33:59:fa:9f:37: + f2:77:79:99:af:72:ad:f9:49:05:ed:55:08:31:eb:97:0f:99: + 6e:9c:a3:df:f0:52:1a:14:4e:78:25:0c:8b:02:cb:56:e9:4d: + f5:9f +-----BEGIN CERTIFICATE----- +MIIDRjCCAq+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA3MB4XDTA5MTEyMDEzMDc1 +M1oXDTM0MTExNDEzMDc1M1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA3MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQCwrm0KIa6KkrEWJdMIy6y3TFNtS7MSgkBUyUQo/E4Q5mVA3nBdi6sf +XHcDQz06PZ73N2aaM2igz62P9Puco4dXXezWVVoYteEr0sQQ/vABpdop7sSvFcmM +3HxFhL3lWwkfFh0R52HmIucfyIa/odrL/mt+wG6qf5eE6I+BafEmhwIDAQABo4IB +BjCCAQIwHQYDVR0OBBYEFFRkFX6TihnI+bfvYKDfXMgVVsDuMIGRBgNVHSMEgYkw +gYaAFIDG+AtffEnkhv3IksaAcNnAb3veoWOkYTBfMQswCQYDVQQGEwJERTEQMA4G +A1UECBMHSGFtYnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsT +C0RldmVsb3BtZW50MQ8wDQYDVQQDEwZSb290IDeCCQDV5mNfGAmCiTA8BgNVHR8E +NTAzMDGgL6AthitodHRwOi8vbG9jYWxob3N0Ojg5MDEvZGVtb0NBL2NybC9Sb290 +XzcuY3JsMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAGrxaS5rV +6MA1wmEKWH0z4ocBYYOAQo0afrGaWNUB/eeuXMhl+54dv0m67UD0BXw7LdsOU9AF +oL0Vh8Q3IgugBKOty1eyAJfuj4mRjn0L4ieWbg+rczNZ+p838nd5ma9yrflJBe1V +CDHrlw+Zbpyj3/BSGhROeCUMiwLLVulN9Z8= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/crl/DO_NOT_INSTALL_THIS_CRL b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/crl/DO_NOT_INSTALL_THIS_CRL new file mode 100644 index 000000000..e69de29bb 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 000000000..f3f7e5cba 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 000000000..dd1172404 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/crlnumber @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/index.txt new file mode 100644 index 000000000..8bcb130f6 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/index.txt @@ -0,0 +1,2 @@ +V 341114131904Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 1 Root 7 +R 341114132648Z 091120132827Z,CACompromise 1001 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 2 Sub CA 1 Root 7 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/index.txt.attr new file mode 100644 index 000000000..8f7e63a34 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/newcerts/1000.pem new file mode 100644 index 000000000..234638d8c --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/newcerts/1000.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 7 + Validity + Not Before: Nov 20 13:19:04 2009 GMT + Not After : Nov 14 13:19:04 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 1 Root 7 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:ce:23:98:19:ac:0d:7c:f0:60:a2:94:72:c3:ab: + a5:a1:6b:d3:af:8c:cb:b9:c9:ee:0b:3e:a4:2e:0e: + 08:a5:a9:4c:09:2f:1a:a0:fe:87:89:41:4a:aa:b6: + ac:b4:bc:d3:0e:f9:c3:12:1f:b1:90:b3:6d:72:a6: + 38:5b:9d:05:7e:97:ff:f4:e1:31:2b:b4:08:de:b1: + 43:fe:1d:7e:32:54:ce:db:d5:14:21:f3:ad:9f:26: + f3:c6:0b:77:51:e4:11:88:ad:86:e1:30:d1:af:87: + 29:c0:7b:92:db:68:06:74:ca:27:ac:0b:61:3a:ac: + ba:03:35:e7:8e:08:28:58:7d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 CRL Distribution Points: + URI:http://localhost:8902/demoCA/crl/Sub_CA_1_Root_7.crl + + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + DE:66:84:E4:9B:BF:70:00:BD:60:3D:34:45:96:FE:FD:D5:88:9B:CD + X509v3 Authority Key Identifier: + keyid:54:64:15:7E:93:8A:19:C8:F9:B7:EF:60:A0:DF:5C:C8:15:56:C0:EE + + Signature Algorithm: sha1WithRSAEncryption + 6e:da:66:d2:3b:00:d6:0b:5a:9f:21:28:de:e1:10:fe:fd:26: + db:a6:75:86:74:47:e4:b0:b7:c4:c1:dc:43:82:51:71:00:8f: + bf:71:9a:23:db:2d:79:27:a2:80:2e:12:a4:5f:13:0c:73:53: + 1e:5c:33:6a:e9:31:be:e2:ae:4f:55:b0:e8:0a:0f:54:f0:3a: + 7e:14:41:d7:34:18:58:90:26:63:7d:2c:1a:ab:93:7f:4a:3d: + 5e:cf:f1:9d:c3:76:ee:a4:76:1c:d8:f9:d0:ac:53:3c:1a:4d: + c7:fa:b6:23:54:4b:04:a1:e2:76:a5:e3:0d:b8:db:8e:d3:39: + c2:65 +-----BEGIN CERTIFICATE----- +MIIC5jCCAk+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA3MB4XDTA5 +MTEyMDEzMTkwNFoXDTM0MTExNDEzMTkwNFowbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAxIFN1YiBDQSAxIFJvb3QgNzCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAziOYGawNfPBgopRyw6uloWvTr4zLucnu +Cz6kLg4IpalMCS8aoP6HiUFKqrastLzTDvnDEh+xkLNtcqY4W50Ffpf/9OExK7QI +3rFD/h1+MlTO29UUIfOtnybzxgt3UeQRiK2G4TDRr4cpwHuS22gGdMonrAthOqy6 +AzXnjggoWH0CAwEAAaOBlzCBlDBFBgNVHR8EPjA8MDqgOKA2hjRodHRwOi8vbG9j +YWxob3N0Ojg5MDIvZGVtb0NBL2NybC9TdWJfQ0FfMV9Sb290XzcuY3JsMAsGA1Ud +DwQEAwIF4DAdBgNVHQ4EFgQU3maE5Ju/cAC9YD00RZb+/dWIm80wHwYDVR0jBBgw +FoAUVGQVfpOKGcj5t+9goN9cyBVWwO4wDQYJKoZIhvcNAQEFBQADgYEAbtpm0jsA +1gtanyEo3uEQ/v0m26Z1hnRH5LC3xMHcQ4JRcQCPv3GaI9steSeigC4SpF8TDHNT +HlwzaukxvuKuT1Ww6AoPVPA6fhRB1zQYWJAmY30sGquTf0o9Xs/xncN27qR2HNj5 +0KxTPBpNx/q2I1RLBKHidqXjDbjbjtM5wmU= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/newcerts/1001.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/newcerts/1001.pem new file mode 100644 index 000000000..ddc504d77 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/newcerts/1001.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4097 (0x1001) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 7 + Validity + Not Before: Nov 20 13:26:48 2009 GMT + Not After : Nov 14 13:26:48 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 2 Sub CA 1 Root 7 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:b3:58:b2:22:45:b9:37:83:e5:a4:6f:5d:4e:59: + 60:60:4e:46:26:27:9a:70:4d:34:89:cf:cb:4f:4f: + 0b:22:6e:e4:21:e6:ab:c9:0a:4a:c4:cd:6f:3c:db: + e8:a3:52:55:2d:26:1d:13:9a:8b:cf:38:25:4e:4f: + 4a:e3:39:01:fa:5b:10:a5:3e:e1:93:65:19:ca:8b: + 5c:9f:e8:19:ed:0a:ef:47:e9:11:73:28:ce:b0:95: + 10:3a:ce:b5:46:89:79:a3:90:ea:d5:ca:ac:c9:af: + ee:55:0d:6c:32:5f:d2:f1:76:1c:b9:e7:d2:ac:07: + 61:83:82:c5:95:5a:62:ff:67 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 CRL Distribution Points: + URI:http://localhost:8902/demoCA/crl/Sub_CA_1_Root_7.crl + + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 12:7A:7A:69:C5:FE:E0:23:FD:8E:51:25:55:94:9F:C8:44:D8:F2:29 + X509v3 Authority Key Identifier: + keyid:54:64:15:7E:93:8A:19:C8:F9:B7:EF:60:A0:DF:5C:C8:15:56:C0:EE + + Signature Algorithm: sha1WithRSAEncryption + 4a:57:08:6a:66:af:b4:05:4f:b3:4c:39:23:2b:5d:c9:88:7b: + 6f:b5:28:a3:5a:72:e6:0b:e2:9e:64:65:ce:8f:b5:31:0f:5f: + c7:b7:56:96:4f:d3:34:65:1a:ea:84:60:2b:fe:27:1f:75:fd: + 0f:53:e5:eb:25:d3:f6:2c:21:72:59:40:32:ba:ec:72:cc:64: + d6:1d:db:cf:ca:ec:91:0a:81:ef:f5:e4:56:31:a3:c2:9a:1d: + e9:5c:48:b0:7c:7b:e2:51:35:33:ad:a8:5c:79:ac:ee:bf:42: + fa:0b:a0:02:72:cc:5e:07:c0:d4:d3:96:26:16:3e:8c:32:8d: + b4:09 +-----BEGIN CERTIFICATE----- +MIIC5jCCAk+gAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA3MB4XDTA5 +MTEyMDEzMjY0OFoXDTM0MTExNDEzMjY0OFowbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAyIFN1YiBDQSAxIFJvb3QgNzCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAs1iyIkW5N4PlpG9dTllgYE5GJieacE00 +ic/LT08LIm7kIearyQpKxM1vPNvoo1JVLSYdE5qLzzglTk9K4zkB+lsQpT7hk2UZ +yotcn+gZ7QrvR+kRcyjOsJUQOs61Rol5o5Dq1cqsya/uVQ1sMl/S8XYcuefSrAdh +g4LFlVpi/2cCAwEAAaOBlzCBlDBFBgNVHR8EPjA8MDqgOKA2hjRodHRwOi8vbG9j +YWxob3N0Ojg5MDIvZGVtb0NBL2NybC9TdWJfQ0FfMV9Sb290XzcuY3JsMAsGA1Ud +DwQEAwIF4DAdBgNVHQ4EFgQUEnp6acX+4CP9jlElVZSfyETY8ikwHwYDVR0jBBgw +FoAUVGQVfpOKGcj5t+9goN9cyBVWwO4wDQYJKoZIhvcNAQEFBQADgYEASlcIamav +tAVPs0w5IytdyYh7b7Uoo1py5gvinmRlzo+1MQ9fx7dWlk/TNGUa6oRgK/4nH3X9 +D1Pl6yXT9iwhcllAMrrscsxk1h3bz8rskQqB7/XkVjGjwpod6VxIsHx74lE1M62o +XHms7r9C+gugAnLMXgfA1NOWJhY+jDKNtAk= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/private/cakey.pem new file mode 100644 index 000000000..c107913a2 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,D710D797627524D4 + +SC46mzOOSpNMZ9t2F3syLy0MmYOk3zBJnY/qcm/ggD4ETOse6zGpqhXVSeZdn3OG +Uwj+b9tCjVC/7GMWanH4DmshCv89IRljMyy5DShsOVmgAr0hqLZNlkKqQRRRHC4d +y9ozYq1J9Zcj16jTmCbpPJW8Ul7kblelNbD0nVgJABc6m6Di/syCFEC0KVGmoJZv +5QjxyNiulh0UNmmP+X6iEGPWw4s5JJdcAg5DFXjPiCvvGazvjCGTT38Hcnya4GkB +9aHo7KbjFU4P98zQKUAV0fSVU7+tzJrLxH0aefenbkIKI45xegOTJmcv8NEZ3YgQ +64r+OlmqOONmvcWrtUdhADvsl8oJ8Lz+1UYcyPpbYLUvMhj8Potf6C6rCz1GuQPS +EmGPltUAOcaylpnP/neyuErAMHGQI9Mn2dhLc/NGK6gxqZi1SawGbrit7Uv5il/n +O3zc7D+d1Jmdkcqm/BZKsMW5hwM3KF4gzb6zMe/8ZCmtqT4iH4eDqjFQfaWeBXNK +kTM8vMUNCU8yQjMYoWL8iL4NNJxRheD0l2FABcGTbWI159eXy8laenk5eBfYKIwl +YGnoylDD2F4W0mdMl2MJIYNYTRP7pAQhLnMbVNSgGDgk5Z0kUF2Kl2rNz+3w1c36 +L3VC/CGFp5/spnQHhYMH2oUAkliS0iev7bNJyhvycVQkMlwYu8KZKMtqyn9bnpU4 +Kd6XlXPwF3BHGrVVdcb6RQo65GrwT6j+hWRwUKgEvcxC7BjtsY1ZV3xRfsRQpA/b +1sTQ/W0ev09+OJAHWEedIg2sTTp5WSiF2whCz6yviFxEAeYIUEGVHw== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/serial new file mode 100644 index 000000000..7d802a3e7 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/demoCA/serial @@ -0,0 +1 @@ +1002 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/openssl.cfg new file mode 100644 index 000000000..7cbc4664f --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_7/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ +crlDistributionPoints=URI:http://localhost:8902/demoCA/crl/Sub_CA_1_Root_7.crl +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +#nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/README.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/README.txt new file mode 100644 index 000000000..4d510fe39 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/README.txt @@ -0,0 +1,13 @@ +Revoked certificates: + +- User 2 Sub CA 1 Root 8 + + +Start the OCSP responder: +openssl ocsp -index demoCA/index.txt -port 8889 -rsigner demoCA/cacert.pem -rkey demoCA/private/cakey.pem -CA demoCA/cacert.pem -text + + + + + + diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/cacert.pem new file mode 100644 index 000000000..b2d1deb75 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/cacert.pem @@ -0,0 +1,66 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 8 + Validity + Not Before: Nov 20 15:33:21 2009 GMT + Not After : Nov 14 15:33:21 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 8 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:96:79:01:9f:4f:68:c1:09:0d:44:3a:82:e4:eb: + ad:70:7a:cf:b9:71:e5:fb:e0:c8:0c:21:79:3e:cb: + 78:91:7f:4a:a0:de:3e:37:0f:a1:6b:73:10:12:9b: + 08:c4:96:dc:cb:a8:5b:87:9b:75:24:e4:00:5e:4a: + 6f:4c:13:79:1f:57:13:8c:3e:1b:38:31:e1:77:74: + 52:f9:94:47:36:57:33:bd:de:08:11:a3:01:e1:53: + 1c:bd:7b:39:9c:5e:96:5c:a9:61:6c:cc:2b:90:8d: + 5a:3c:9e:f4:4b:6e:e5:97:64:86:f3:8e:e8:72:20: + 5d:0d:50:bf:e9:cf:be:d4:13 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + EF:BD:C8:8E:78:79:F9:76:4B:11:59:B6:C3:32:10:07:C0:BC:E3:8A + X509v3 Authority Key Identifier: + keyid:D6:66:76:C9:05:FF:A9:50:88:96:60:DD:FB:C7:30:18:72:67:41:19 + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 8 + serial:B2:47:DE:6A:2A:4C:83:19 + + Authority Information Access: + OCSP - URI:http://localhost:8888 + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 4c:95:44:3b:57:08:ec:01:ec:f9:3e:7c:89:1c:30:b1:4e:26: + 32:b6:57:fa:25:bc:ed:eb:d4:a2:1c:67:ee:b9:8b:d0:4c:57: + 8a:0e:db:a0:9d:92:e7:de:c6:73:01:e7:de:61:1b:b5:0e:d0: + c5:c1:a7:a6:ab:e0:c6:0b:51:dd:e5:a2:32:1f:c6:52:ea:d3: + 03:68:3a:f5:92:bd:8b:b8:03:bb:50:70:63:cc:ec:ed:3c:11: + 76:ca:ac:72:47:ad:99:6b:8e:07:9e:38:f2:63:e1:ba:d4:df: + a9:73:54:1d:74:89:94:01:2e:68:dd:97:e7:53:f9:cf:b6:7d: + fc:87 +-----BEGIN CERTIFICATE----- +MIIDOTCCAqKgAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA4MB4XDTA5MTEyMDE1MzMy +MVoXDTM0MTExNDE1MzMyMVowaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA4MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQCWeQGfT2jBCQ1EOoLk661wes+5ceX74MgMIXk+y3iRf0qg3j43D6Fr +cxASmwjEltzLqFuHm3Uk5ABeSm9ME3kfVxOMPhs4MeF3dFL5lEc2VzO93ggRowHh +Uxy9ezmcXpZcqWFszCuQjVo8nvRLbuWXZIbzjuhyIF0NUL/pz77UEwIDAQABo4H6 +MIH3MB0GA1UdDgQWBBTvvciOeHn5dksRWbbDMhAHwLzjijCBkQYDVR0jBIGJMIGG +gBTWZnbJBf+pUIiWYN37xzAYcmdBGaFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA4ggkAskfeaipMgxkwMQYIKwYBBQUH +AQEEJTAjMCEGCCsGAQUFBzABhhVodHRwOi8vbG9jYWxob3N0Ojg4ODgwDwYDVR0T +AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBMlUQ7VwjsAez5PnyJHDCxTiYy +tlf6Jbzt69SiHGfuuYvQTFeKDtugnZLn3sZzAefeYRu1DtDFwaemq+DGC1Hd5aIy +H8ZS6tMDaDr1kr2LuAO7UHBjzOztPBF2yqxyR62Za44HnjjyY+G61N+pc1QddImU +AS5o3ZfnU/nPtn38hw== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/crl/DO_NOT_INSTALL_THIS_CRL b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/crl/DO_NOT_INSTALL_THIS_CRL new file mode 100644 index 000000000..e69de29bb 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 000000000..7a9ee345e 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 000000000..dd1172404 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/crlnumber @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/index.txt new file mode 100644 index 000000000..ff1b3fe19 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/index.txt @@ -0,0 +1,2 @@ +V 341114154212Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 1 Root 8 +R 341114154716Z 091120155036Z,superseded 1001 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 2 Sub CA 1 Root 8 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/index.txt.attr new file mode 100644 index 000000000..8f7e63a34 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/newcerts/1000.pem new file mode 100644 index 000000000..71456d01b --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/newcerts/1000.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 8 + Validity + Not Before: Nov 20 15:42:12 2009 GMT + Not After : Nov 14 15:42:12 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 1 Root 8 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:b6:aa:34:ec:31:e5:9a:aa:fe:90:31:1f:e5:83: + 90:cb:9a:9e:15:cd:bb:35:1b:fc:3c:8b:d9:3d:29: + de:f4:07:3f:4c:06:9b:4f:db:21:a2:4b:87:8b:fd: + b4:61:31:de:34:6c:14:10:f9:a7:7a:e0:0a:e9:bf: + b3:83:a3:35:44:f4:ad:c3:d0:60:e8:71:8e:6d:c0: + 70:9a:16:85:65:7a:82:68:7c:67:ee:57:31:6b:e8: + fd:f2:3f:5f:c7:ec:4e:db:e7:8a:98:d6:15:45:13: + 14:03:bc:4e:8a:03:48:c2:e4:aa:c5:32:cf:80:82: + 45:16:8b:63:37:4b:d5:7a:97 + Exponent: 65537 (0x10001) + X509v3 extensions: + Authority Information Access: + OCSP - URI:http://localhost:8889 + + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 4E:0B:28:05:B5:07:8F:77:1E:A6:37:CB:CC:F0:CB:09:A4:8C:4A:1E + X509v3 Authority Key Identifier: + keyid:EF:BD:C8:8E:78:79:F9:76:4B:11:59:B6:C3:32:10:07:C0:BC:E3:8A + + Signature Algorithm: sha1WithRSAEncryption + 3e:f7:c5:94:58:2f:18:c9:11:29:29:28:33:bb:e7:6c:70:7c: + f8:c7:60:4a:e5:37:f2:bb:78:d9:52:1e:c2:a3:dd:b1:7f:da: + e1:8a:8b:9c:7e:d6:ee:ec:ef:94:37:b5:b8:97:26:92:01:56: + 78:15:44:4b:95:4d:d9:59:12:b0:89:86:e4:b5:7d:b4:73:0f: + f1:0d:a8:04:69:e4:3f:2a:6a:65:b9:0e:9a:06:f7:16:29:94: + 4d:ac:64:ab:e9:0f:06:3c:74:fe:4c:e1:71:98:bd:9f:bb:c1: + 2d:47:70:6a:3c:b3:76:0b:fc:c8:05:d6:4e:bf:33:9f:dd:58: + 74:9c +-----BEGIN CERTIFICATE----- +MIIC0jCCAjugAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA4MB4XDTA5 +MTEyMDE1NDIxMloXDTM0MTExNDE1NDIxMlowbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAxIFN1YiBDQSAxIFJvb3QgODCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAtqo07DHlmqr+kDEf5YOQy5qeFc27NRv8 +PIvZPSne9Ac/TAabT9shokuHi/20YTHeNGwUEPmneuAK6b+zg6M1RPStw9Bg6HGO +bcBwmhaFZXqCaHxn7lcxa+j98j9fx+xO2+eKmNYVRRMUA7xOigNIwuSqxTLPgIJF +FotjN0vVepcCAwEAAaOBgzCBgDAxBggrBgEFBQcBAQQlMCMwIQYIKwYBBQUHMAGG +FWh0dHA6Ly9sb2NhbGhvc3Q6ODg4OTALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFE4L +KAW1B493HqY3y8zwywmkjEoeMB8GA1UdIwQYMBaAFO+9yI54efl2SxFZtsMyEAfA +vOOKMA0GCSqGSIb3DQEBBQUAA4GBAD73xZRYLxjJESkpKDO752xwfPjHYErlN/K7 +eNlSHsKj3bF/2uGKi5x+1u7s75Q3tbiXJpIBVngVREuVTdlZErCJhuS1fbRzD/EN +qARp5D8qamW5DpoG9xYplE2sZKvpDwY8dP5M4XGYvZ+7wS1HcGo8s3YL/MgF1k6/ +M5/dWHSc +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/newcerts/1001.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/newcerts/1001.pem new file mode 100644 index 000000000..51102e24a --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/newcerts/1001.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4097 (0x1001) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 8 + Validity + Not Before: Nov 20 15:47:16 2009 GMT + Not After : Nov 14 15:47:16 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 2 Sub CA 1 Root 8 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:a1:55:67:7e:e5:7a:62:eb:2b:36:45:fa:1d:4d: + c7:0e:6d:db:f6:54:65:4d:55:39:14:ea:c1:ad:75: + 1b:2f:2f:3c:6e:67:e0:6d:c6:76:66:0c:11:a2:89: + fe:70:3b:24:3e:0d:2a:13:9f:86:b4:8a:a3:27:50: + 52:77:1f:b8:7b:85:4e:36:94:68:4f:23:2c:f6:a1: + 0f:01:bc:6d:d4:e9:a4:54:12:15:37:bd:6c:ba:ad: + ed:78:ed:00:cc:be:a9:20:99:f5:a5:db:96:ba:cb: + 89:6b:ff:30:36:5c:84:77:a8:0d:28:d3:f8:20:99: + 01:4d:0f:8e:b3:8e:de:8d:09 + Exponent: 65537 (0x10001) + X509v3 extensions: + Authority Information Access: + OCSP - URI:http://localhost:8889 + + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + FC:DC:A7:1C:CE:D2:A9:DA:9A:76:9D:AE:8F:C8:1E:56:BA:D2:D5:D5 + X509v3 Authority Key Identifier: + keyid:EF:BD:C8:8E:78:79:F9:76:4B:11:59:B6:C3:32:10:07:C0:BC:E3:8A + + Signature Algorithm: sha1WithRSAEncryption + 87:30:ed:08:e6:03:fa:cf:65:5a:ed:9e:83:db:64:5f:bb:6b: + 5c:f3:db:8d:b7:d0:95:35:8c:f6:c1:1c:2c:d9:0c:0a:41:27: + f9:1f:e4:aa:25:95:59:3c:45:85:ac:0f:02:42:92:67:e2:09: + 45:d3:c1:7b:6e:db:42:84:7b:0d:57:47:f5:07:38:dd:cf:38: + ac:29:b9:14:79:2e:04:a5:a0:d6:71:be:fa:6d:9e:b5:cd:89: + 99:d1:47:58:56:81:8c:d4:b0:96:c6:dc:a7:1b:b0:ef:6b:0c: + 25:5f:92:b8:01:b7:74:f0:e3:49:eb:30:29:9f:f3:b5:bd:ae: + 45:99 +-----BEGIN CERTIFICATE----- +MIIC0jCCAjugAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA4MB4XDTA5 +MTEyMDE1NDcxNloXDTM0MTExNDE1NDcxNlowbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAyIFN1YiBDQSAxIFJvb3QgODCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAoVVnfuV6YusrNkX6HU3HDm3b9lRlTVU5 +FOrBrXUbLy88bmfgbcZ2ZgwRoon+cDskPg0qE5+GtIqjJ1BSdx+4e4VONpRoTyMs +9qEPAbxt1OmkVBIVN71suq3teO0AzL6pIJn1pduWusuJa/8wNlyEd6gNKNP4IJkB +TQ+Os47ejQkCAwEAAaOBgzCBgDAxBggrBgEFBQcBAQQlMCMwIQYIKwYBBQUHMAGG +FWh0dHA6Ly9sb2NhbGhvc3Q6ODg4OTALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFPzc +pxzO0qnamnadro/IHla60tXVMB8GA1UdIwQYMBaAFO+9yI54efl2SxFZtsMyEAfA +vOOKMA0GCSqGSIb3DQEBBQUAA4GBAIcw7QjmA/rPZVrtnoPbZF+7a1zz24230JU1 +jPbBHCzZDApBJ/kf5KollVk8RYWsDwJCkmfiCUXTwXtu20KEew1XR/UHON3POKwp +uRR5LgSloNZxvvptnrXNiZnRR1hWgYzUsJbG3KcbsO9rDCVfkrgBt3Tw40nrMCmf +87W9rkWZ +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/private/cakey.pem new file mode 100644 index 000000000..6c934e3ec --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,D40C0B2149B20A3E + +u5VzDci4c2i/pIElAbIAVT81F72A2V3fpvZv8yUpQRai5ZPzciSc4oYgavdu3tLV +p8bS+60akNpr3/ti7sB4tQBcql/3FMdKLFCgflJgCH9ivr2UrUSIJOyu9UNoG2ym +UcJrvCSAqtksL11VLMb3SJO7TRYxJ/xOl69Auf0R+aRwdof9nSBO4jDPTqvR/X8L +j/plBnw7ENO0ravRnEEEAEiSgx/z0LkhzAsPTkrrkNN5eZ+kR2Sk/Uo5aTx3FTpB +RU+iZQxmbNTrxCErfYvSnMJ4w6soT+Bzezwfn2tVGLwbur/3gtuNMEHJpL0Y2st9 +aRBHHF6+DlJ30rqNWCVV5ZY+2wMUEPBtcRftLdmh3caw/9aN/NqVUGuvqmhWyTt7 +TJmnKLJhE9NSztQM2PuV7ka9jWp5D6KLv0g+cbedpEOw6VjYL5e1EKt0AOu4Pp2r +HerL1ouRmpzIQLpskFTwkccjVDQm/H2fnB/nVrjdWxi/U4QJ0EPHL8iCyyox5np+ +3HilWBkpyBSvMOhyGfPkUucsMZA6O7/XhDcciBSsCJ4SSMa5gQmfYfixQHKRwixS +O5sJADUnJkbo4hyvrptAolM/JJU+HN8IYnq541mJ72dXbyodheedRPIOpTCiLQam +1Y04wfuIFMN4w98O0oMpCbqcDsOHysxN1XYg2kMzlxYbwooFC5cud5+cEW6d9FWQ +kpZ8Wkigno3ytjpUXWb9TmsRcMNiQdgxlpkvN/eYhk4xsUpwzhA/M/HTkLkn8WtC +52EwCv9KcxF31AA0lOeI+oNfcyMruwNXwEkFn3eD36axZQ8QjPHfhw== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/serial new file mode 100644 index 000000000..7d802a3e7 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/demoCA/serial @@ -0,0 +1 @@ +1002 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/openssl.cfg new file mode 100644 index 000000000..571237e7d --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_8/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +authorityInfoAccess = OCSP;URI:http://localhost:8889 +#crlDistributionPoints=URI:http://localhost:8902/demoCA/crl/Sub_CA_2_Root_7.crl +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +#nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/cacert.pem new file mode 100644 index 000000000..0b38d4db4 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/cacert.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 9 + Validity + Not Before: Nov 23 13:59:19 2009 GMT + Not After : Nov 17 13:59:19 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 9 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:a9:6d:7f:6a:08:fb:e2:3a:5e:83:3f:ff:58:ba: + 92:a1:79:9d:ce:d2:0c:16:15:f2:7e:b3:e4:45:9c: + 02:32:65:9b:02:90:78:05:95:e4:04:1d:4a:05:bb: + ea:f6:ac:ab:15:74:c2:bc:ee:2a:c1:80:55:3e:93: + 1f:5c:94:eb:cf:cf:8f:15:eb:b8:22:fe:69:61:51: + a9:08:b8:80:bd:48:99:da:85:10:1c:75:97:fd:d3: + c3:c4:0b:dd:eb:01:12:5d:ee:62:62:c3:0c:18:ea: + ed:76:ff:9b:1c:1f:c7:81:f9:9a:cd:e5:25:89:b2: + 13:57:56:f3:27:53:72:76:69 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 7B:D3:57:BF:6A:CB:6C:10:81:91:DA:95:DC:88:4F:A5:D0:DB:D1:46 + X509v3 Authority Key Identifier: + keyid:CD:33:5E:AB:73:23:51:80:B8:03:AD:12:01:0B:C5:5E:8E:55:CA:64 + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 9 + serial:A4:DB:16:0D:4B:8C:D4:A6 + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 17:67:b0:21:da:0d:a1:fe:09:62:d0:cf:1d:c0:c8:bd:d4:22: + dd:75:ec:04:e2:23:ae:ea:8c:15:fa:73:2e:83:f4:16:eb:c1: + e1:87:36:bd:58:d0:64:e0:6e:2c:bc:27:cb:dc:4b:58:01:80: + 48:27:53:bb:75:85:a7:19:b8:e2:c0:1f:9f:a2:18:27:82:3f: + 25:bf:17:d1:34:32:de:c4:81:9d:8a:39:6f:6b:1f:b6:12:61: + 74:78:96:6d:6e:52:23:4a:67:30:78:03:91:b7:89:bf:3c:4a: + 36:e3:95:21:38:35:af:05:55:81:05:25:91:78:ca:2f:5d:79: + d2:05 +-----BEGIN CERTIFICATE----- +MIIDBjCCAm+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA5MB4XDTA5MTEyMzEzNTkx +OVoXDTM0MTExNzEzNTkxOVowaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA5MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQCpbX9qCPviOl6DP/9YupKheZ3O0gwWFfJ+s+RFnAIyZZsCkHgFleQE +HUoFu+r2rKsVdMK87irBgFU+kx9clOvPz48V67gi/mlhUakIuIC9SJnahRAcdZf9 +08PEC93rARJd7mJiwwwY6u12/5scH8eB+ZrN5SWJshNXVvMnU3J2aQIDAQABo4HH +MIHEMB0GA1UdDgQWBBR701e/astsEIGR2pXciE+l0NvRRjCBkQYDVR0jBIGJMIGG +gBTNM16rcyNRgLgDrRIBC8VejlXKZKFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA5ggkApNsWDUuM1KYwDwYDVR0TAQH/ +BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQAXZ7Ah2g2h/gli0M8dwMi91CLddewE +4iOu6owV+nMug/QW68Hhhza9WNBk4G4svCfL3EtYAYBIJ1O7dYWnGbjiwB+fohgn +gj8lvxfRNDLexIGdijlvax+2EmF0eJZtblIjSmcweAORt4m/PEo245UhODWvBVWB +BSWReMovXXnSBQ== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/crlnumber new file mode 100644 index 000000000..dd1172404 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/crlnumber @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/index.txt new file mode 100644 index 000000000..8c466eaff --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/index.txt @@ -0,0 +1 @@ +V 341117140202Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 1 Root 9 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/index.txt.attr new file mode 100644 index 000000000..8f7e63a34 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/newcerts/1000.pem new file mode 100644 index 000000000..e3ca26a8a --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/newcerts/1000.pem @@ -0,0 +1,58 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 1 Root 9 + Validity + Not Before: Nov 23 14:02:02 2009 GMT + Not After : Nov 17 14:02:02 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 1 Root 9 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:f2:d3:15:3c:73:42:ce:22:e4:40:3a:6b:02:f6: + 59:bd:66:0d:87:91:f4:c0:be:a9:ce:33:21:09:d9: + 4e:4b:03:51:87:c3:e9:75:91:e9:80:5e:fc:a1:f7: + 43:9b:c6:32:af:6d:77:4b:b6:dc:b1:08:a3:1f:a0: + 6d:ec:81:12:23:48:36:2d:7a:5a:d0:88:88:49:7c: + ce:ae:98:45:d8:ff:9f:15:72:ab:b4:85:f6:a5:23: + af:43:e4:64:45:da:20:e1:e0:3e:f2:87:ea:67:ea: + 0e:08:8a:c8:1c:ef:85:a5:e6:f3:54:68:02:fd:de: + bc:4d:a2:eb:7d:0d:7d:80:59 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 1B:56:DD:11:CE:38:A0:97:FF:BE:39:9C:AF:F4:60:82:3A:CA:5D:51 + X509v3 Authority Key Identifier: + keyid:7B:D3:57:BF:6A:CB:6C:10:81:91:DA:95:DC:88:4F:A5:D0:DB:D1:46 + + Signature Algorithm: sha1WithRSAEncryption + 54:5e:40:1d:83:35:67:23:01:28:35:e3:02:7f:9e:9f:ce:83: + fb:45:dd:5c:96:62:f5:28:45:c8:90:2a:7e:84:88:e9:e9:b7: + 21:17:e0:3b:ea:de:6d:a1:d5:37:90:ae:15:86:30:7f:82:81: + d1:bb:ca:d2:6c:7c:39:2e:e9:65:57:2b:74:47:04:49:99:74: + 63:c7:03:cc:7d:f4:b0:6e:92:75:bb:aa:28:dc:71:d3:95:73: + 15:f4:4f:38:43:9e:4f:9f:e3:97:5c:8d:dc:1e:ad:ad:1e:b7: + c2:b2:ca:87:ee:8e:a2:93:12:60:95:1a:fb:bf:42:c8:31:48: + 8a:43 +-----BEGIN CERTIFICATE----- +MIICnTCCAgagAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDEgUm9vdCA5MB4XDTA5 +MTEyMzE0MDIwMloXDTM0MTExNzE0MDIwMlowbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAxIFN1YiBDQSAxIFJvb3QgOTCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA8tMVPHNCziLkQDprAvZZvWYNh5H0wL6p +zjMhCdlOSwNRh8PpdZHpgF78ofdDm8Yyr213S7bcsQijH6Bt7IESI0g2LXpa0IiI +SXzOrphF2P+fFXKrtIX2pSOvQ+RkRdog4eA+8ofqZ+oOCIrIHO+FpebzVGgC/d68 +TaLrfQ19gFkCAwEAAaNPME0wCwYDVR0PBAQDAgXgMB0GA1UdDgQWBBQbVt0Rzjig +l/++OZyv9GCCOspdUTAfBgNVHSMEGDAWgBR701e/astsEIGR2pXciE+l0NvRRjAN +BgkqhkiG9w0BAQUFAAOBgQBUXkAdgzVnIwEoNeMCf56fzoP7Rd1clmL1KEXIkCp+ +hIjp6bchF+A76t5todU3kK4VhjB/goHRu8rSbHw5LullVyt0RwRJmXRjxwPMffSw +bpJ1u6oo3HHTlXMV9E84Q55Pn+OXXI3cHq2tHrfCssqH7o6ikxJglRr7v0LIMUiK +Qw== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/private/cakey.pem new file mode 100644 index 000000000..be54b542a --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,6D4A43A204C02659 + +ZPB/XY3gNrLz1f2DqTRkoZiL64CjVUEPw6ujRi/cAaMfAB+p32O/obtFbMyZWfpv +aLaoPmQH5hagNgsQqOW6OrSguxQ9i64Wv795TzRBrSYRHJ1as73AfDcS9aeI61AM +kiweFkVFAOPfgKOczYO152uXxtdRm4kpVr/CMsYuViE7966dzFvjDlY4vTDAD32+ +KJemzfjwsyErT/nYJaaabEkxxn+O3nwhgVqueoYWI8VeLYotFU41wO1NrOQvshs0 +tyrs5meiuSNPVuKagTltWfHv9PlMyVne7XYiRv1k7CIPmEansBge9/lY5KoPLHGQ +CHjuuwPykf6jnW7QG9IAGKRNPSdlMBpOT97EvKgNZ9I0FB4lSumhrxkjPHrRKz/J +usV+mEcGGYrfAb2OT0B/YSddOk1rCtKXpRVUMF8dzD7AyVxnU0Sdub6lwjNojAGh +Nb8exIFnVBM0/ka19xvlcdY0q9du7e0MuVvy8NhE0vkoqqDrUUnCP8iqg+uRBVts +0P7yk1lucsrNw8JQveLuiHm6zxN91iUAsBguwoOHG6szp3X9GLvvGhpQWPxTIOyo +obPMw6lY0y9MHY6eW9ekXVWGMZL2GDpIKLq9kqzLTqhY9kDw9OXYio4UYLl9vQG4 +Akr4ogzm8SKNQkPnGHprCdQV5J4V7fOa4HTNJb6NlTvMFuC99Sst+PYdE4RAn3sT +Jn+Lj2g0fDDSjvLNohmrT08DAYAAinbNt/+6gI975syPxuqxggrgfis4cliI7pf8 +ecmKIoSlbsJVCSfgd5a/d7e+9KwNuqBqopLu2vfgUN1YiFlEwAEQaQ== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/serial new file mode 100644 index 000000000..dd1172404 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/demoCA/serial @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/openssl.cfg new file mode 100644 index 000000000..4a5b97f53 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_1_Root_9/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8889 +#crlDistributionPoints=URI:http://localhost:8902/demoCA/crl/Sub_CA_2_Root_7.crl +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +#nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/README.txt b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/README.txt new file mode 100644 index 000000000..e020f03a5 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/README.txt @@ -0,0 +1,4 @@ +Revoked certificates: + +- User 2 Sub CA 2 Root 4 + diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/cacert.pem new file mode 100644 index 000000000..9d951ee26 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/cacert.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4097 (0x1001) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 4 + Validity + Not Before: Nov 20 09:22:27 2009 GMT + Not After : Nov 14 09:22:27 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 2 Root 4 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:e5:8d:27:4e:09:53:08:61:c6:23:25:9e:dd:9c: + 07:bf:81:38:5c:5c:10:8f:e4:12:2f:4e:2e:b1:a1: + cf:21:46:53:bf:e8:5e:de:17:3a:9d:f7:e8:ef:3e: + 9c:b4:29:37:4c:31:35:15:dc:98:e0:93:9c:ce:6a: + d6:e1:35:19:6b:d4:1d:3b:81:86:b1:e7:ff:1f:b8: + 34:a9:f9:de:4d:b8:62:ac:3b:d4:58:8e:5c:76:b5: + 07:7f:32:8a:3a:90:73:71:d5:da:f1:79:39:14:ed: + 1b:f1:8a:3e:be:48:bc:07:ec:f9:7c:03:14:fc:e7: + 55:a3:65:81:c7:6c:70:0b:ff + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 69:DE:B6:99:C4:95:F7:5A:FA:41:6B:4C:F6:C3:6D:89:AA:37:31:9D + X509v3 Authority Key Identifier: + keyid:BA:8D:A1:97:DC:C4:39:1F:90:B5:51:6B:10:19:F2:46:0D:A9:65:8E + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 4 + serial:A2:93:46:74:3B:A6:E3:AD + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + bc:cf:43:eb:72:b1:71:a7:94:8e:cd:5b:fc:d8:21:31:83:db: + a9:de:c7:5b:14:e5:7b:90:43:e6:05:df:db:6e:95:5f:24:ac: + 0c:a1:8a:ac:c6:cf:f2:03:cd:a0:30:ae:d3:a9:41:07:c9:b1: + be:4b:e0:fc:a2:76:09:07:75:6a:fa:e4:2f:a3:3a:cd:81:68: + ab:f6:06:c4:32:08:25:6e:e8:e7:36:9c:1a:f7:42:73:f8:b0: + d8:42:3e:85:c2:11:23:10:d6:6a:e4:8f:53:cb:8b:8b:1b:5a: + 4d:6d:9d:34:45:26:52:d2:ee:6d:8f:23:ff:00:92:f5:99:62: + 4c:41 +-----BEGIN CERTIFICATE----- +MIIDBjCCAm+gAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA0MB4XDTA5MTEyMDA5MjIy +N1oXDTM0MTExNDA5MjIyN1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDIgUm9vdCA0MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDljSdOCVMIYcYjJZ7dnAe/gThcXBCP5BIvTi6xoc8hRlO/6F7eFzqd +9+jvPpy0KTdMMTUV3Jjgk5zOatbhNRlr1B07gYax5/8fuDSp+d5NuGKsO9RYjlx2 +tQd/Moo6kHNx1drxeTkU7Rvxij6+SLwH7Pl8AxT851WjZYHHbHAL/wIDAQABo4HH +MIHEMB0GA1UdDgQWBBRp3raZxJX3WvpBa0z2w22JqjcxnTCBkQYDVR0jBIGJMIGG +gBS6jaGX3MQ5H5C1UWsQGfJGDalljqFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA0ggkAopNGdDum460wDwYDVR0TAQH/ +BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQC8z0PrcrFxp5SOzVv82CExg9up3sdb +FOV7kEPmBd/bbpVfJKwMoYqsxs/yA82gMK7TqUEHybG+S+D8onYJB3Vq+uQvozrN +gWir9gbEMgglbujnNpwa90Jz+LDYQj6FwhEjENZq5I9Ty4uLG1pNbZ00RSZS0u5t +jyP/AJL1mWJMQQ== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/crlnumber b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/crlnumber new file mode 100644 index 000000000..dd1172404 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/crlnumber @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/index.txt new file mode 100644 index 000000000..554a773b4 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/index.txt @@ -0,0 +1,2 @@ +V 341114093339Z 1001 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 2 Root 4 +R 341114095105Z 091120095246Z,keyCompromise 1002 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 2 Sub CA 2 Root 4 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/index.txt.attr new file mode 100644 index 000000000..8f7e63a34 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/newcerts/1001.pem b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/newcerts/1001.pem new file mode 100644 index 000000000..3fbf2133f --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/newcerts/1001.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4097 (0x1001) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 2 Root 4 + Validity + Not Before: Nov 20 09:33:39 2009 GMT + Not After : Nov 14 09:33:39 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 2 Root 4 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:c6:b2:8e:e4:f1:67:0b:07:3c:8c:b8:78:d9:79: + b1:2e:d5:10:c5:e8:76:9a:25:3f:dd:a3:0b:e0:3f: + 9f:50:87:e9:f1:15:74:86:ce:a0:01:07:b2:37:d0: + 74:dc:96:69:b4:f1:0e:cd:15:37:ca:ba:ed:ea:a3: + 99:ec:43:d4:ac:1c:8b:9b:18:d0:cd:80:78:49:80: + ca:e3:85:c6:2d:9a:15:02:73:d3:97:08:1d:4b:68: + 95:52:e6:92:57:c7:f6:76:0c:f1:a7:3d:90:10:0c: + 35:a8:9c:d3:e4:10:30:20:04:7f:ea:ad:ef:39:0c: + 65:05:43:f4:b6:51:3a:e7:95 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + Netscape Comment: + OpenSSL Generated Certificate + X509v3 Subject Key Identifier: + 79:C2:63:88:76:DF:C6:6F:BD:1D:AF:57:6E:87:08:AC:55:5D:AD:D1 + X509v3 Authority Key Identifier: + keyid:69:DE:B6:99:C4:95:F7:5A:FA:41:6B:4C:F6:C3:6D:89:AA:37:31:9D + + Signature Algorithm: sha1WithRSAEncryption + 07:68:5f:e9:01:bc:e4:d7:78:16:2b:19:7f:c2:9d:15:74:91: + ea:6d:fb:c9:ee:29:07:ff:62:e2:6a:85:5e:85:7d:5f:b4:bc: + 48:e1:89:24:3e:03:21:42:c1:10:3f:c6:41:7e:04:30:86:db: + c5:7e:7e:9f:04:49:a0:1e:fc:93:8e:b3:d1:cf:39:e3:41:89: + c3:06:51:3f:15:d5:02:49:2a:0b:15:d1:25:30:12:b6:2a:f9: + 03:06:f1:03:84:ae:4e:86:e1:dc:e6:a3:36:a4:27:24:2b:db: + 3a:3c:15:48:6f:c7:9f:ce:38:34:06:94:e3:d3:64:f7:4d:9e: + b6:c0 +-----BEGIN CERTIFICATE----- +MIICyzCCAjSgAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDIgUm9vdCA0MB4XDTA5 +MTEyMDA5MzMzOVoXDTM0MTExNDA5MzMzOVowbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAxIFN1YiBDQSAyIFJvb3QgNDCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAxrKO5PFnCwc8jLh42XmxLtUQxeh2miU/ +3aML4D+fUIfp8RV0hs6gAQeyN9B03JZptPEOzRU3yrrt6qOZ7EPUrByLmxjQzYB4 +SYDK44XGLZoVAnPTlwgdS2iVUuaSV8f2dgzxpz2QEAw1qJzT5BAwIAR/6q3vOQxl +BUP0tlE655UCAwEAAaN9MHswCwYDVR0PBAQDAgXgMCwGCWCGSAGG+EIBDQQfFh1P +cGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUecJjiHbfxm+9 +Ha9XbocIrFVdrdEwHwYDVR0jBBgwFoAUad62mcSV91r6QWtM9sNtiao3MZ0wDQYJ +KoZIhvcNAQEFBQADgYEAB2hf6QG85Nd4FisZf8KdFXSR6m37ye4pB/9i4mqFXoV9 +X7S8SOGJJD4DIULBED/GQX4EMIbbxX5+nwRJoB78k46z0c8540GJwwZRPxXVAkkq +CxXRJTAStir5AwbxA4SuTobh3OajNqQnJCvbOjwVSG/Hn844NAaU49Nk902etsA= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/newcerts/1002.pem b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/newcerts/1002.pem new file mode 100644 index 000000000..595fbbfaf --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/newcerts/1002.pem @@ -0,0 +1,60 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4098 (0x1002) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 2 Root 4 + Validity + Not Before: Nov 20 09:51:05 2009 GMT + Not After : Nov 14 09:51:05 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 2 Sub CA 2 Root 4 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:f5:2d:4a:b8:5d:39:da:58:5c:3c:a5:7d:4c:98: + b8:32:db:43:a0:13:cb:25:f8:5b:0b:6a:f2:e0:8d: + de:8f:c6:ea:c5:1c:03:bf:e0:b1:c9:14:a4:85:4b: + ed:95:87:f7:88:88:86:9e:65:3d:6e:e8:c5:be:17: + e6:9b:09:8e:44:c1:0a:20:00:ae:b4:3d:ba:68:9f: + 3e:ea:76:3c:96:64:ee:a7:91:65:31:03:f5:fd:01: + e5:60:a0:5e:62:a0:37:7b:db:cf:71:78:58:cc:dd: + 74:fc:b3:b1:2e:6b:f3:ec:ad:ac:75:ae:d8:d6:42: + 28:0a:20:68:8d:20:4a:30:61 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + Netscape Comment: + OpenSSL Generated Certificate + X509v3 Subject Key Identifier: + 32:E4:11:DF:CD:54:D6:80:67:68:85:36:A0:C5:14:88:D6:85:DB:C9 + X509v3 Authority Key Identifier: + keyid:69:DE:B6:99:C4:95:F7:5A:FA:41:6B:4C:F6:C3:6D:89:AA:37:31:9D + + Signature Algorithm: sha1WithRSAEncryption + e1:c2:5d:63:42:27:f4:df:a2:f0:f5:61:c3:e3:ac:f7:b6:29: + a9:dd:34:63:0c:cc:c9:7b:5c:1b:ac:77:8f:1a:e1:f4:3b:c8: + 96:8a:89:f6:c0:f0:c4:3b:bd:6e:b7:e7:84:5c:38:4f:d3:66: + 55:d6:d3:f8:70:1f:14:ce:9f:d3:04:68:be:6b:81:fc:6c:b6: + 2f:31:3d:de:2a:4e:6c:66:c0:c2:09:c8:ef:be:c4:88:39:28: + e8:62:da:44:63:f4:5c:f4:bb:cf:4b:54:c9:c0:ce:b4:27:7b: + 1e:9c:2f:90:9e:18:da:8a:27:af:e5:37:ea:3f:99:86:f8:5d: + d1:cb +-----BEGIN CERTIFICATE----- +MIICyzCCAjSgAwIBAgICEAIwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDIgUm9vdCA0MB4XDTA5 +MTEyMDA5NTEwNVoXDTM0MTExNDA5NTEwNVowbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAyIFN1YiBDQSAyIFJvb3QgNDCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA9S1KuF052lhcPKV9TJi4MttDoBPLJfhb +C2ry4I3ej8bqxRwDv+CxyRSkhUvtlYf3iIiGnmU9bujFvhfmmwmORMEKIACutD26 +aJ8+6nY8lmTup5FlMQP1/QHlYKBeYqA3e9vPcXhYzN10/LOxLmvz7K2sda7Y1kIo +CiBojSBKMGECAwEAAaN9MHswCwYDVR0PBAQDAgXgMCwGCWCGSAGG+EIBDQQfFh1P +cGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUMuQR381U1oBn +aIU2oMUUiNaF28kwHwYDVR0jBBgwFoAUad62mcSV91r6QWtM9sNtiao3MZ0wDQYJ +KoZIhvcNAQEFBQADgYEA4cJdY0In9N+i8PVhw+Os97Ypqd00YwzMyXtcG6x3jxrh +9DvIloqJ9sDwxDu9brfnhFw4T9NmVdbT+HAfFM6f0wRovmuB/Gy2LzE93ipObGbA +wgnI777EiDko6GLaRGP0XPS7z0tUycDOtCd7HpwvkJ4Y2oonr+U36j+Zhvhd0cs= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/private/cakey.pem new file mode 100644 index 000000000..a8f9640c8 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,1BD121CFCC6764E4 + +k3SMhf7UEWvpfhEyvd7Zc6kJFmiZ1JTg7KAawQhFhoRbGIVA1rSmRbuBdJm4XdQ5 +OxEAC5bVx5o3yxyhGmEkZr1dkGXkzQ1tc2a4Exf2p0O5zjlHUaxd2A4/mRYVAT0e +LAIQ+D+yqSd2wmLkLaz3EGGlfIPS8amTpnhSOvai40NjbLlRpw5DqDP/2KVWp7jH +T4JNzU33Xd6QuBsTSWyXuhIEeuzyrDbou0LceHIZSaa8Jqvp3yKX6OBTUdCNakwR +QtLLag63ie87qEhqeHg2VvZuVVEyhNCjPf2zRfxsCx742wI4TyY28JpxjYlFzJxX +Zd9toqIGFwritEOcr6wAqVX7NlE8/dDFFdEK9fPuv/jLoOYCCwDRvIMgDTE76c1k +foRMDMmqe0KcMdp+fbcfNDnV/U8gle2902AbEOXJLhdDEVUG/LCwrnIeUrfMOKiY +LwPysGwVndUb3uTFJ2e+PqV9i96G+ewpN9/hI9fThE12t8rhkpIsozEMl7WsBMgD +tdKrA5l7eibshCpk+zkIwGhkdMYXhj7hmioWWBJeMdJ93Ba8f91kt1IvI+J2Mn2K +1/5D0ZKEGPoTSAlEgMZ888sYWkT6WMk0UXH2Nq8BqdrrSTUypY2Uz0nDbWvhLrCf +zac6RZu9TtFsKAY6CQnXHFUJ+dvRmcSNQMhrIKS2VZ2UkL2oXASzXW2c9Hx6LO7T +WHuR7bXZiJhI63gUGI9pMRCs5NoRuXdg3KutzSTy8EWKJDXDKcvTemiomUZFB6i5 +zduXL73Wf/VjMcs7iOAijd7czGre0LBwyvgeNUAK2gj7SaGkR3bPZg== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/serial new file mode 100644 index 000000000..baccd0398 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/demoCA/serial @@ -0,0 +1 @@ +1003 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/openssl.cfg new file mode 100644 index 000000000..51e520525 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_4/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/README.txt b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/README.txt new file mode 100644 index 000000000..e04f69532 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/README.txt @@ -0,0 +1,12 @@ +Revoked certificates: + +- User 2 Sub 2 Root 7 + + +To provide the CRL via HTTP run + +java -jar ../../tools/httpserv/dist/httpserv.jar -a 8902 + + + + diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/cacert.pem new file mode 100644 index 000000000..0d2a0f02a --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/cacert.pem @@ -0,0 +1,66 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4097 (0x1001) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 7 + Validity + Not Before: Nov 20 13:35:06 2009 GMT + Not After : Nov 14 13:35:06 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 2 Root 7 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:f9:3f:5e:76:52:9a:ce:5d:98:b0:00:d8:e0:65: + e7:78:11:4c:7b:c7:e2:d3:44:bf:8e:60:42:69:3e: + 75:67:65:24:ab:f7:07:d8:9d:be:0f:23:b5:c1:26: + 00:6b:c3:22:84:72:a9:96:dc:5f:63:fc:f5:e0:e3: + cc:da:0c:74:e9:31:51:91:89:27:8f:e5:17:41:6e: + 3d:5e:2a:13:cd:08:f7:f3:61:34:a1:f7:79:c6:bd: + 5d:2c:34:01:ea:5a:8c:48:97:36:d6:57:e0:80:03: + 2e:7a:03:83:4c:bd:b4:af:a2:fd:d7:4b:1a:f7:ab: + 9f:5a:22:2b:d1:25:73:dd:6f + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 3B:50:26:45:6C:E2:FE:28:B1:71:0A:A8:95:2D:78:63:8E:2C:48:92 + X509v3 Authority Key Identifier: + keyid:80:C6:F8:0B:5F:7C:49:E4:86:FD:C8:92:C6:80:70:D9:C0:6F:7B:DE + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 7 + serial:D5:E6:63:5F:18:09:82:89 + + X509v3 CRL Distribution Points: + URI:http://localhost:8901/demoCA/crl/Root_7.crl + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 5f:b4:70:11:4f:d9:df:6a:6a:5a:4a:97:fe:8b:5d:9e:46:84: + e2:27:67:41:7c:a9:2e:9d:77:cc:e4:8c:d6:16:3c:39:7d:51: + 29:60:80:32:4f:a1:d0:b4:7f:2a:e5:60:f4:b8:d3:3b:94:f8: + a5:fb:15:99:cf:a9:c5:a7:59:c1:11:89:67:11:9c:ff:a9:ac: + dd:ca:a9:92:a8:60:26:c3:ab:74:41:86:b9:4d:1e:4a:c5:de: + 63:e6:da:2a:36:39:7b:6c:66:f3:20:57:d1:f1:36:4b:69:c5: + 04:a3:1f:cf:de:0c:10:d0:3f:07:e2:8e:0f:cd:41:26:c9:2e: + e9:1b +-----BEGIN CERTIFICATE----- +MIIDRjCCAq+gAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA3MB4XDTA5MTEyMDEzMzUw +NloXDTM0MTExNDEzMzUwNlowaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDIgUm9vdCA3MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQD5P152UprOXZiwANjgZed4EUx7x+LTRL+OYEJpPnVnZSSr9wfYnb4P +I7XBJgBrwyKEcqmW3F9j/PXg48zaDHTpMVGRiSeP5RdBbj1eKhPNCPfzYTSh93nG +vV0sNAHqWoxIlzbWV+CAAy56A4NMvbSvov3XSxr3q59aIivRJXPdbwIDAQABo4IB +BjCCAQIwHQYDVR0OBBYEFDtQJkVs4v4osXEKqJUteGOOLEiSMIGRBgNVHSMEgYkw +gYaAFIDG+AtffEnkhv3IksaAcNnAb3veoWOkYTBfMQswCQYDVQQGEwJERTEQMA4G +A1UECBMHSGFtYnVyZzEXMBUGA1UEChMOT3Blbk9mZmljZS5vcmcxFDASBgNVBAsT +C0RldmVsb3BtZW50MQ8wDQYDVQQDEwZSb290IDeCCQDV5mNfGAmCiTA8BgNVHR8E +NTAzMDGgL6AthitodHRwOi8vbG9jYWxob3N0Ojg5MDEvZGVtb0NBL2NybC9Sb290 +XzcuY3JsMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAX7RwEU/Z +32pqWkqX/otdnkaE4idnQXypLp13zOSM1hY8OX1RKWCAMk+h0LR/KuVg9LjTO5T4 +pfsVmc+pxadZwRGJZxGc/6ms3cqpkqhgJsOrdEGGuU0eSsXeY+baKjY5e2xm8yBX +0fE2S2nFBKMfz94MENA/B+KOD81BJsku6Rs= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/crl/DO_NOT_INSTALL_THIS_CRL b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/crl/DO_NOT_INSTALL_THIS_CRL new file mode 100644 index 000000000..e69de29bb 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 000000000..c4dd13d83 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 000000000..dd1172404 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/crlnumber @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/index.txt new file mode 100644 index 000000000..a5e282ddd --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/index.txt @@ -0,0 +1,2 @@ +V 341114134608Z 1000 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 2 Root 7 +R 341114135230Z 091120135413Z,CACompromise 1001 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 2 Sub CA 2 Root 7 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/index.txt.attr new file mode 100644 index 000000000..8f7e63a34 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/newcerts/1000.pem b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/newcerts/1000.pem new file mode 100644 index 000000000..ff1f1fa66 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/newcerts/1000.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 2 Root 7 + Validity + Not Before: Nov 20 13:46:08 2009 GMT + Not After : Nov 14 13:46:08 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 2 Root 7 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:a7:6b:af:a2:6e:61:33:2e:71:7b:e2:38:44:d9: + 4c:da:6e:86:bb:c6:f5:64:8e:2e:8b:e8:71:c8:46: + ad:c5:46:05:d2:06:a6:89:e2:ce:1f:1c:a7:4c:94: + a4:24:56:93:07:b1:c4:52:44:69:27:0b:34:eb:31: + 20:71:63:5c:0a:33:aa:0c:39:71:ac:08:49:c3:66: + ac:cb:e3:a8:66:ab:5c:a2:00:7a:bb:24:e6:93:91: + 1e:0e:7c:83:9e:f2:10:87:3f:0e:c0:f6:e5:bf:2c: + d3:cc:17:4c:d5:9a:96:35:4b:4e:ca:72:3a:9b:90: + c8:4c:24:04:2f:51:99:20:95 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 CRL Distribution Points: + URI:http://localhost:8902/demoCA/crl/Sub_CA_2_Root_7.crl + + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 27:98:7E:F6:AD:82:6D:F4:7A:32:AE:F1:54:D1:07:AE:08:0E:0E:2B + X509v3 Authority Key Identifier: + keyid:3B:50:26:45:6C:E2:FE:28:B1:71:0A:A8:95:2D:78:63:8E:2C:48:92 + + Signature Algorithm: sha1WithRSAEncryption + 06:7d:0a:e8:fa:8b:87:1d:75:61:2b:c7:d1:6d:56:5f:26:e3: + 29:b4:c3:27:05:35:0f:b7:c1:20:42:95:0b:9d:34:16:5d:9b: + c2:48:c8:67:e1:e7:43:eb:10:9e:45:3e:44:da:7c:4b:19:05: + 00:66:91:83:ea:82:86:48:e8:87:ea:a0:9f:c9:1d:f8:af:13: + fd:2e:4e:50:7e:a0:d2:b0:5e:a4:6f:dd:e6:c8:11:60:bc:41: + e5:b6:01:4c:7a:af:32:f6:cc:5b:57:e6:e4:87:21:ec:17:98: + 67:eb:4d:2f:07:db:8f:70:e2:f3:77:8f:c7:ff:60:d6:d9:f7: + 82:e3 +-----BEGIN CERTIFICATE----- +MIIC5jCCAk+gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDIgUm9vdCA3MB4XDTA5 +MTEyMDEzNDYwOFoXDTM0MTExNDEzNDYwOFowbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAxIFN1YiBDQSAyIFJvb3QgNzCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAp2uvom5hMy5xe+I4RNlM2m6Gu8b1ZI4u +i+hxyEatxUYF0gamieLOHxynTJSkJFaTB7HEUkRpJws06zEgcWNcCjOqDDlxrAhJ +w2asy+OoZqtcogB6uyTmk5EeDnyDnvIQhz8OwPblvyzTzBdM1ZqWNUtOynI6m5DI +TCQEL1GZIJUCAwEAAaOBlzCBlDBFBgNVHR8EPjA8MDqgOKA2hjRodHRwOi8vbG9j +YWxob3N0Ojg5MDIvZGVtb0NBL2NybC9TdWJfQ0FfMl9Sb290XzcuY3JsMAsGA1Ud +DwQEAwIF4DAdBgNVHQ4EFgQUJ5h+9q2CbfR6Mq7xVNEHrggODiswHwYDVR0jBBgw +FoAUO1AmRWzi/iixcQqolS14Y44sSJIwDQYJKoZIhvcNAQEFBQADgYEABn0K6PqL +hx11YSvH0W1WXybjKbTDJwU1D7fBIEKVC500Fl2bwkjIZ+HnQ+sQnkU+RNp8SxkF +AGaRg+qChkjoh+qgn8kd+K8T/S5OUH6g0rBepG/d5sgRYLxB5bYBTHqvMvbMW1fm +5Ich7BeYZ+tNLwfbj3Di83ePx/9g1tn3guM= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/newcerts/1001.pem b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/newcerts/1001.pem new file mode 100644 index 000000000..f16cdf4aa --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/newcerts/1001.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4097 (0x1001) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 2 Root 7 + Validity + Not Before: Nov 20 13:52:30 2009 GMT + Not After : Nov 14 13:52:30 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 2 Sub CA 2 Root 7 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:d3:1f:7e:28:b6:fd:f0:bb:01:21:88:04:c4:da: + 3d:6a:ce:09:8e:04:29:a5:0f:38:db:74:d0:ee:ad: + 5c:95:79:16:11:c0:b1:51:69:95:bb:a8:8f:8b:1c: + 7b:8c:82:27:16:21:82:82:d7:36:6f:b3:bb:36:a8: + ad:69:e2:e3:cd:6f:ef:81:ac:fa:e3:a9:ac:86:b7: + 31:1d:75:11:a3:2e:1d:89:0b:9c:5e:03:45:7a:b0: + a9:9d:ee:31:f1:15:c1:c5:f6:26:8e:d4:89:72:8f: + f4:86:94:d1:49:37:24:56:84:10:db:cc:f2:1d:3e: + 58:66:97:b2:17:6f:15:cb:81 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 CRL Distribution Points: + URI:http://localhost:8902/demoCA/crl/Sub_CA_2_Root_7.crl + + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + CD:A2:AE:51:D0:CF:A2:89:3A:53:23:74:1D:69:10:EE:2A:40:3A:22 + X509v3 Authority Key Identifier: + keyid:3B:50:26:45:6C:E2:FE:28:B1:71:0A:A8:95:2D:78:63:8E:2C:48:92 + + Signature Algorithm: sha1WithRSAEncryption + 40:8a:be:55:1f:d9:0f:96:fd:54:dd:9f:6b:1d:b1:34:ed:b7: + 11:6d:72:a9:65:9a:39:bd:79:3b:d3:4e:0c:22:60:39:e8:c0: + 2c:34:64:09:2c:0c:aa:f7:f9:9d:f1:d9:b9:04:d6:e2:c4:cb: + d5:05:33:75:5e:87:c0:2c:80:06:8b:6e:9c:ad:0c:7f:03:c0: + f5:91:e4:3a:64:b9:52:3b:5a:e0:e5:79:32:89:fb:4a:54:68: + 9a:e6:72:3e:61:93:a3:2a:67:aa:95:d0:3d:37:33:5c:da:6e: + a6:ac:3d:b6:b1:ac:68:f0:8c:8b:6b:96:a5:f7:ed:2d:6e:64: + c7:11 +-----BEGIN CERTIFICATE----- +MIIC5jCCAk+gAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDIgUm9vdCA3MB4XDTA5 +MTEyMDEzNTIzMFoXDTM0MTExNDEzNTIzMFowbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAyIFN1YiBDQSAyIFJvb3QgNzCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0x9+KLb98LsBIYgExNo9as4JjgQppQ84 +23TQ7q1clXkWEcCxUWmVu6iPixx7jIInFiGCgtc2b7O7NqitaeLjzW/vgaz646ms +hrcxHXURoy4diQucXgNFerCpne4x8RXBxfYmjtSJco/0hpTRSTckVoQQ28zyHT5Y +ZpeyF28Vy4ECAwEAAaOBlzCBlDBFBgNVHR8EPjA8MDqgOKA2hjRodHRwOi8vbG9j +YWxob3N0Ojg5MDIvZGVtb0NBL2NybC9TdWJfQ0FfMl9Sb290XzcuY3JsMAsGA1Ud +DwQEAwIF4DAdBgNVHQ4EFgQUzaKuUdDPook6UyN0HWkQ7ipAOiIwHwYDVR0jBBgw +FoAUO1AmRWzi/iixcQqolS14Y44sSJIwDQYJKoZIhvcNAQEFBQADgYEAQIq+VR/Z +D5b9VN2fax2xNO23EW1yqWWaOb15O9NODCJgOejALDRkCSwMqvf5nfHZuQTW4sTL +1QUzdV6HwCyABotunK0MfwPA9ZHkOmS5Ujta4OV5Mon7SlRomuZyPmGToypnqpXQ +PTczXNpupqw9trGsaPCMi2uWpfftLW5kxxE= +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/private/cakey.pem new file mode 100644 index 000000000..1f95ffa3c --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,70BBA561902B1296 + ++Pbay3A7tcxOMNFXIlyQ6Hpl4QxJJmzZzXT5UOfGZYYRYrFKv1489pqvzLNgp06z +nWvyILc3AUd4dWnzfkWvPN3fjJazGWXoZaYLfGgdccA0LdXh+TmqVHHxFjOZVFeO +lYlKqK6dUsybaciOhkYBKPs1ZFAaNtQLZc1/GVAA9jVYnfwNVmW14d5Q8gurZTp8 +qYwQmT9Sjm2j9USIFcD9MDH94gW77PI+XD1hu6PJTF8m7n8eSY9KcWfVmd/Qj9Ly +nzLRaS6SOKETWL4+fUaN6aDtddKGwFgagyDwlRRuizX18ZSue2qoK73AhLtZ8Gx/ +vgFLTsvcniZus9kzVrRm2dsWvzaVAmOwqN04IqD6bEr+kXq1obP/T+deGsRwR54K +wEy7NrkkMSGw4AOuxVNSO7NYgU2kXueAfvGU8SQiXuU1S7fdZpWci8T5Dm7FuP9B +iKsHqUH9GYgAVl+Y3dwa9n+mDaFkn4wxeVHDdL40XJT0LYCMz9PGKRy3JSTiHF// +j9BHDpIC+E8L9N01cJ74+p0bzLLOhZ7vyjx8umVJbNIAAlDbCrEi4ZFqwGvmdjHF +2dti2S0ALixAFQybub4s9Cp3QxfaWnYQOvV7A0SGhtHkjycaJwO0cSonQ8yEjJJJ +PQkIW9SK+xz/yDYMHqa/Yo5t53GkpCTKBo2STSdnXjnABNk3FAusf72POkIPcH99 +5uyje8bo+lS2VB/O/pm8tbf9mW9YEh/xd3VAglWiAMzYSfO1x0rSTpdqJMSDfOhK +ogim9NdrVwASi0JrE8nCovwO3auOPu+5sRvYstnt18IVNisZZoW/Qg== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/serial new file mode 100644 index 000000000..7d802a3e7 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/demoCA/serial @@ -0,0 +1 @@ +1002 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/openssl.cfg new file mode 100644 index 000000000..c6acf751f --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_7/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ +crlDistributionPoints=URI:http://localhost:8902/demoCA/crl/Sub_CA_2_Root_7.crl +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +#nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/README.txt b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/README.txt new file mode 100644 index 000000000..645ae6037 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/README.txt @@ -0,0 +1,13 @@ +Revoked certificates: + +- User 2 Sub CA 2 Root 8 + + +Start the OCSP responder: +openssl ocsp -index demoCA/index.txt -port 8889 -rsigner demoCA/cacert.pem -rkey demoCA/private/cakey.pem -CA demoCA/cacert.pem -text + + + + + + diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/cacert.pem b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/cacert.pem new file mode 100644 index 000000000..26368962e --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/cacert.pem @@ -0,0 +1,66 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4097 (0x1001) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 8 + Validity + Not Before: Nov 20 15:55:33 2009 GMT + Not After : Nov 14 15:55:33 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 2 Root 8 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:e9:91:38:d8:c1:36:e5:c1:d0:32:e8:ae:02:11: + 97:e5:c5:07:8f:5b:46:3a:3c:d9:49:5e:9a:4b:51: + 4c:b7:7d:e9:d1:4f:a7:15:8c:c6:10:f6:fa:5f:a9: + 0b:1b:bc:de:56:f5:ad:a3:a0:40:f1:75:10:58:74: + 37:f9:b7:9f:76:ca:46:96:4c:1a:81:f4:a2:ce:88: + 8b:9e:00:6d:42:b3:d6:68:d1:67:d6:9f:b8:9c:3f: + 43:c7:36:bf:41:88:1b:e8:74:26:a0:51:5c:e2:ee: + 6d:9d:73:bb:0d:36:e1:5c:68:9f:21:3b:b2:aa:ed: + 39:1d:ae:fc:b4:ca:38:c2:fb + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + 1B:AB:6B:0F:42:91:DC:1E:D4:7A:95:87:30:2D:CC:11:4F:35:B7:73 + X509v3 Authority Key Identifier: + keyid:D6:66:76:C9:05:FF:A9:50:88:96:60:DD:FB:C7:30:18:72:67:41:19 + DirName:/C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=Root 8 + serial:B2:47:DE:6A:2A:4C:83:19 + + Authority Information Access: + OCSP - URI:http://localhost:8888 + + X509v3 Basic Constraints: critical + CA:TRUE + Signature Algorithm: sha1WithRSAEncryption + 89:f8:8d:a8:e5:0b:2a:fb:f3:6a:80:2c:26:a1:a7:36:7e:a0: + c5:61:65:9d:7e:d6:47:60:b4:f6:72:e9:6e:2c:d9:f8:7f:c8: + 7a:5d:75:98:ad:88:de:e7:1b:44:a3:96:37:84:c0:b3:20:98: + 3b:b5:f6:ee:70:9c:04:7a:6c:88:05:75:7f:12:cf:b9:76:e8: + c0:17:0c:5e:eb:10:38:1e:54:41:58:56:f6:3c:ec:07:a5:c0: + 74:24:34:af:b3:c7:b2:58:85:47:0f:6c:e4:a0:9f:c8:7b:5c: + 95:77:17:e5:ad:eb:c3:86:44:f7:81:ef:cb:58:12:1a:6a:c7: + 19:95 +-----BEGIN CERTIFICATE----- +MIIDOTCCAqKgAwIBAgICEAEwDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA4MB4XDTA5MTEyMDE1NTUz +M1oXDTM0MTExNDE1NTUzM1owaDELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0hhbWJ1 +cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtEZXZlbG9wbWVu +dDEYMBYGA1UEAxMPU3ViIENBIDIgUm9vdCA4MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDpkTjYwTblwdAy6K4CEZflxQePW0Y6PNlJXppLUUy3fenRT6cVjMYQ +9vpfqQsbvN5W9a2joEDxdRBYdDf5t592ykaWTBqB9KLOiIueAG1Cs9Zo0WfWn7ic +P0PHNr9BiBvodCagUVzi7m2dc7sNNuFcaJ8hO7Kq7Tkdrvy0yjjC+wIDAQABo4H6 +MIH3MB0GA1UdDgQWBBQbq2sPQpHcHtR6lYcwLcwRTzW3czCBkQYDVR0jBIGJMIGG +gBTWZnbJBf+pUIiWYN37xzAYcmdBGaFjpGEwXzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEPMA0GA1UEAxMGUm9vdCA4ggkAskfeaipMgxkwMQYIKwYBBQUH +AQEEJTAjMCEGCCsGAQUFBzABhhVodHRwOi8vbG9jYWxob3N0Ojg4ODgwDwYDVR0T +AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQCJ+I2o5Qsq+/NqgCwmoac2fqDF +YWWdftZHYLT2culuLNn4f8h6XXWYrYje5xtEo5Y3hMCzIJg7tfbucJwEemyIBXV/ +Es+5dujAFwxe6xA4HlRBWFb2POwHpcB0JDSvs8eyWIVHD2zkoJ/Ie1yVdxflrevD +hkT3ge/LWBIaascZlQ== +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/crl/DO_NOT_INSTALL_THIS_CRL b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/crl/DO_NOT_INSTALL_THIS_CRL new file mode 100644 index 000000000..e69de29bb 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 000000000..f4e88754b 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 000000000..dd1172404 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/crlnumber @@ -0,0 +1 @@ +1001 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/index.txt b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/index.txt new file mode 100644 index 000000000..cdace00f7 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/index.txt @@ -0,0 +1,2 @@ +V 341114161332Z 1002 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 1 Sub CA 2 Root 8 +R 341114161602Z 091120161700Z,superseded 1003 unknown /C=DE/ST=Hamburg/O=OpenOffice.org/OU=Development/CN=User 2 Sub CA 2 Root 8 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/index.txt.attr b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/index.txt.attr new file mode 100644 index 000000000..8f7e63a34 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/newcerts/1002.pem b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/newcerts/1002.pem new file mode 100644 index 000000000..1107a4327 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/newcerts/1002.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4098 (0x1002) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 2 Root 8 + Validity + Not Before: Nov 20 16:13:32 2009 GMT + Not After : Nov 14 16:13:32 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 1 Sub CA 2 Root 8 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:d2:f6:25:c0:95:4b:07:1e:a0:57:67:52:36:b3: + 3e:5d:32:7f:61:25:e9:dd:31:a1:67:6e:02:9f:4f: + ca:ff:82:50:64:2e:ed:4e:8d:09:73:48:91:e1:90: + ca:df:06:ab:f4:c3:3d:8b:7d:d1:6b:5f:f8:f8:d6: + c0:f4:81:59:7c:0e:53:32:a9:cd:e4:34:3c:20:a9: + 08:b6:c2:b3:b7:91:d2:db:46:06:09:55:ff:f9:f4: + 4e:2a:28:36:46:0e:04:f1:78:7d:a3:ff:ac:08:1b: + 21:99:f5:b4:5b:f6:be:fd:1a:89:26:4b:eb:b9:58: + fc:c2:5f:44:42:a9:00:76:ff + Exponent: 65537 (0x10001) + X509v3 extensions: + Authority Information Access: + OCSP - URI:http://localhost:8889 + + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 9D:91:CD:7F:70:3B:00:C1:2A:FD:2F:5D:64:C4:8F:EB:0E:37:25:1B + X509v3 Authority Key Identifier: + keyid:1B:AB:6B:0F:42:91:DC:1E:D4:7A:95:87:30:2D:CC:11:4F:35:B7:73 + + Signature Algorithm: sha1WithRSAEncryption + 2c:68:5e:5b:2e:d7:48:ca:2a:01:b4:a0:99:0e:06:2d:e8:23: + b3:66:31:97:cd:9e:73:61:35:af:9d:d9:2f:7c:e6:87:7f:2a: + ae:3e:b0:99:c9:20:10:30:e3:a0:5b:28:8b:57:f2:12:3a:87: + c1:7a:5e:c8:21:b9:ae:49:c1:aa:4f:1c:9e:a8:ae:0f:ad:a2: + 3e:aa:61:94:64:41:f8:d7:19:8d:a1:be:c0:15:04:25:2c:35: + 29:af:00:1e:40:7c:e7:d7:41:89:a7:ab:2d:dd:78:dd:c7:ba: + d0:1b:7b:68:fa:7e:a4:0f:4c:ab:02:6e:d2:ff:b8:5b:05:f6: + 47:29 +-----BEGIN CERTIFICATE----- +MIIC0jCCAjugAwIBAgICEAIwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDIgUm9vdCA4MB4XDTA5 +MTEyMDE2MTMzMloXDTM0MTExNDE2MTMzMlowbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAxIFN1YiBDQSAyIFJvb3QgODCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0vYlwJVLBx6gV2dSNrM+XTJ/YSXp3TGh +Z24Cn0/K/4JQZC7tTo0Jc0iR4ZDK3war9MM9i33Ra1/4+NbA9IFZfA5TMqnN5DQ8 +IKkItsKzt5HS20YGCVX/+fROKig2Rg4E8Xh9o/+sCBshmfW0W/a+/RqJJkvruVj8 +wl9EQqkAdv8CAwEAAaOBgzCBgDAxBggrBgEFBQcBAQQlMCMwIQYIKwYBBQUHMAGG +FWh0dHA6Ly9sb2NhbGhvc3Q6ODg4OTALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFJ2R +zX9wOwDBKv0vXWTEj+sONyUbMB8GA1UdIwQYMBaAFBuraw9Ckdwe1HqVhzAtzBFP +NbdzMA0GCSqGSIb3DQEBBQUAA4GBACxoXlsu10jKKgG0oJkOBi3oI7NmMZfNnnNh +Na+d2S985od/Kq4+sJnJIBAw46BbKItX8hI6h8F6Xsghua5JwapPHJ6org+toj6q +YZRkQfjXGY2hvsAVBCUsNSmvAB5AfOfXQYmnqy3deN3HutAbe2j6fqQPTKsCbtL/ +uFsF9kcp +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/newcerts/1003.pem b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/newcerts/1003.pem new file mode 100644 index 000000000..53268ff52 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/newcerts/1003.pem @@ -0,0 +1,62 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4099 (0x1003) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Sub CA 2 Root 8 + Validity + Not Before: Nov 20 16:16:02 2009 GMT + Not After : Nov 14 16:16:02 2034 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 2 Sub CA 2 Root 8 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:b4:58:05:7c:f5:f2:48:af:35:03:82:62:af:d3: + ef:50:f0:0b:b1:a9:a1:9b:14:1c:54:a9:71:b4:f6: + e0:7d:8a:25:b3:21:e2:53:ab:a5:08:9e:ed:5a:ef: + 8b:4f:be:75:40:b0:10:05:eb:08:3b:94:c2:57:37: + 51:41:08:57:b9:1c:a5:2f:e9:cc:3c:a8:70:2b:eb: + 00:92:43:64:44:18:23:9f:85:5f:7f:a5:c9:30:b3: + 14:c0:2b:fc:94:a5:a6:ad:46:a8:37:12:20:ab:cf: + e0:02:74:5d:1f:2e:ec:1c:9f:27:1f:83:fc:c4:62: + d2:0b:6b:f4:65:21:1d:94:ff + Exponent: 65537 (0x10001) + X509v3 extensions: + Authority Information Access: + OCSP - URI:http://localhost:8889 + + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 1E:C7:A3:43:33:6B:EC:90:B5:66:81:64:D6:43:72:45:DB:D9:E4:57 + X509v3 Authority Key Identifier: + keyid:1B:AB:6B:0F:42:91:DC:1E:D4:7A:95:87:30:2D:CC:11:4F:35:B7:73 + + Signature Algorithm: sha1WithRSAEncryption + a8:66:0d:4b:6a:00:fc:31:e3:f5:8f:49:44:3d:60:26:76:2e: + 51:f8:41:35:3b:5b:7f:87:e3:00:d7:ae:85:bb:d9:81:a5:30: + db:6a:0a:a0:d2:e8:69:f5:47:d8:19:e5:2a:bd:c5:8e:99:f9: + 57:fc:b0:64:f5:43:bc:37:4a:8e:28:70:a4:6d:7d:da:2c:9e: + c1:55:8d:00:89:fe:f7:ef:c9:d9:8d:fe:01:3e:83:23:58:c3: + 3e:41:09:ab:5c:60:0e:9e:18:69:9e:99:7f:a2:cd:b7:95:5c: + ea:31:02:79:32:eb:1a:07:dc:75:98:80:8e:56:f2:0a:8f:0e: + cf:4f +-----BEGIN CERTIFICATE----- +MIIC0jCCAjugAwIBAgICEAMwDQYJKoZIhvcNAQEFBQAwaDELMAkGA1UEBhMCREUx +EDAOBgNVBAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYD +VQQLEwtEZXZlbG9wbWVudDEYMBYGA1UEAxMPU3ViIENBIDIgUm9vdCA4MB4XDTA5 +MTEyMDE2MTYwMloXDTM0MTExNDE2MTYwMlowbzELMAkGA1UEBhMCREUxEDAOBgNV +BAgTB0hhbWJ1cmcxFzAVBgNVBAoTDk9wZW5PZmZpY2Uub3JnMRQwEgYDVQQLEwtE +ZXZlbG9wbWVudDEfMB0GA1UEAxMWVXNlciAyIFN1YiBDQSAyIFJvb3QgODCBnzAN +BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAtFgFfPXySK81A4Jir9PvUPALsamhmxQc +VKlxtPbgfYolsyHiU6ulCJ7tWu+LT751QLAQBesIO5TCVzdRQQhXuRylL+nMPKhw +K+sAkkNkRBgjn4Vff6XJMLMUwCv8lKWmrUaoNxIgq8/gAnRdHy7sHJ8nH4P8xGLS +C2v0ZSEdlP8CAwEAAaOBgzCBgDAxBggrBgEFBQcBAQQlMCMwIQYIKwYBBQUHMAGG +FWh0dHA6Ly9sb2NhbGhvc3Q6ODg4OTALBgNVHQ8EBAMCBeAwHQYDVR0OBBYEFB7H +o0Mza+yQtWaBZNZDckXb2eRXMB8GA1UdIwQYMBaAFBuraw9Ckdwe1HqVhzAtzBFP +NbdzMA0GCSqGSIb3DQEBBQUAA4GBAKhmDUtqAPwx4/WPSUQ9YCZ2LlH4QTU7W3+H +4wDXroW72YGlMNtqCqDS6Gn1R9gZ5Sq9xY6Z+Vf8sGT1Q7w3So4ocKRtfdosnsFV +jQCJ/vfvydmN/gE+gyNYwz5BCatcYA6eGGmemX+izbeVXOoxAnky6xoH3HWYgI5W +8gqPDs9P +-----END CERTIFICATE----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/private/cakey.pem b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/private/cakey.pem new file mode 100644 index 000000000..e063b9726 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/private/cakey.pem @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,B84323C471CC815A + +UrT9eGAJB4+hzdjcS7YBCJi6jCL9n9/vZC0fC6mjZRK/dw4CxLka0KapKUVd+pj/ +I+XG6JOqa5tmsHcp9OWaWpzyu9W5DJqjodTum6pNlig68GVVSs21u7q0mF5mA6OR +PmRu+iOe2oZO6kVaRnpdGBnbsUsvlsbayiY3nHjXeDPxyc+XGnIMjT7mBOO360iR +h6IEOyapRho8klyuOXLy8hHZuUyspm66Nq+czorGdv3nlEdSI4t4LPTcqJGUMiHb +hLYsCK9Zwu7RQWne3OmGjAspU37TB3F1YrWjnHFIKE6YSvtdYMwXosMbybdUZFwQ +w4dGUhIxCxWLDF99Qfnygi8HJOC1FiFcJslVem0Xi3M654sshGLCiA4jMjdUAEmL +R+rzjUNZEHqvO/bGm7zsEoLWQFWEYqQZguwxDScam9Sii/fcnEBcSERbEi3yjvlX +7L3q4j/7/PlpYuRVB+f21ZuoI8R6M+omwF1ZzuSQNMSvUMyhAgQ+yB/pFJbArU68 +4l7ks0wNcSlLyGzjsexrzU9UB8Y8avFOMGuRiWGt4Kh54hNxgaCRGp9ugoyEq5H5 ++QNB1x8tBJSe1YC4T06olH2xZTYCd5e9qTyjQrbnqTK4SEBDrOL+XSASkleH3vVH +SO1paXDjh9fSSTxPo1T8DnAadIcouVlUNdvO4WrtqO4Kbf0rDHbqzZDtrNYG3Hwd +w86nEo6J1AKrTKyXysOLdhuAhNr+hGx4ITT5HfV/H5BE3ba0/fmLxvenqTxBXrJc +wkEeORwtu1XWW1hxYKRi3lRgfi4OH/ciMwxU530mKZzIJTOdvsKPgw== +-----END RSA PRIVATE KEY----- diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/serial b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/serial new file mode 100644 index 000000000..59c112266 --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/demoCA/serial @@ -0,0 +1 @@ +1004 diff --git a/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/openssl.cfg b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/openssl.cfg new file mode 100644 index 000000000..571237e7d --- /dev/null +++ b/xmlsecurity/test_docs/CAs/Sub_CA_2_Root_8/openssl.cfg @@ -0,0 +1,292 @@ +# +# OpenSSL example configuration file. +# This is mostly being used for generation of certificate requests. +# + +# This definition stops the following lines choking if HOME isn't +# defined. +HOME = . +RANDFILE = $ENV::HOME/.rnd + +# Extra OBJECT IDENTIFIER info: +#oid_file = $ENV::HOME/.oid +oid_section = new_oids + +# To use this configuration file with the "-extfile" option of the +# "openssl x509" utility, name here the section containing the +# X.509v3 extensions to use: +# extensions = +# (Alternatively, use a configuration file that has only +# X.509v3 extensions in its main [= default] section.) + +[ new_oids ] + +# We can add new OIDs in here for use by 'ca' and 'req'. +# Add a simple OID like this: +# testoid1=1.2.3.4 +# Or use config file substitution like this: +# testoid2=${testoid1}.5.6 + +#################################################################### +[ ca ] +default_ca = CA_default # The default ca section + +#################################################################### +[ CA_default ] + +dir = ./demoCA # Where everything is kept +certs = $dir/certs # Where the issued certs are kept +crl_dir = $dir/crl # Where the issued crl are kept +database = $dir/index.txt # database index file. +#unique_subject = no # Set to 'no' to allow creation of + # several certificates with same subject. +new_certs_dir = $dir/newcerts # default place for new certs. + +certificate = $dir/cacert.pem # The CA certificate +serial = $dir/serial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL +crl = $dir/crl.pem # The current CRL +private_key = $dir/private/cakey.pem # The private key +RANDFILE = $dir/private/.rand # private random number file + +x509_extensions = usr_cert # The extensions to add to the cert + +# Comment out the following two lines for the "traditional" +# (and highly broken) format. +name_opt = ca_default # Subject Name options +cert_opt = ca_default # Certificate field options + +# Extension copying option: use with caution. +# copy_extensions = copy + +# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs +# so this is commented out by default to leave a V1 CRL. +# crlnumber must also be commented out to leave a V1 CRL. +# crl_extensions = crl_ext + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = sha1 # which md to use. +preserve = no # keep passed DN ordering + +# A few difference way of specifying how similar the request should look +# For type CA, the listed attributes must be the same, and the optional +# and supplied fields are just that :-) +policy = policy_match + +# For the CA policy +[ policy_match ] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +# For the 'anything' policy +# At this point in time, you must list all acceptable 'object' +# types. +[ policy_anything ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +#################################################################### +[ req ] +default_bits = 1024 +default_keyfile = privkey.pem +distinguished_name = req_distinguished_name +attributes = req_attributes +x509_extensions = v3_ca # The extensions to add to the self signed cert + +# Passwords for private keys if not present they will be prompted for +# input_password = secret +# output_password = secret + +# This sets a mask for permitted string types. There are several options. +# default: PrintableString, T61String, BMPString. +# pkix : PrintableString, BMPString. +# utf8only: only UTF8Strings. +# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). +# MASK:XXXX a literal mask value. +# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings +# so use this option with caution! +string_mask = nombstr + +# req_extensions = v3_req # The extensions to add to a certificate request + +[ req_distinguished_name ] +countryName = Country Name (2 letter code) +countryName_default = DE +countryName_min = 2 +countryName_max = 2 + +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = Hamburg + +localityName = Locality Name (eg, city) + +0.organizationName = Organization Name (eg, company) +0.organizationName_default = OpenOffice.org + +# we can do this but it is not needed normally :-) +#1.organizationName = Second Organization Name (eg, company) +#1.organizationName_default = World Wide Web Pty Ltd + +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development + +commonName = Common Name (eg, YOUR name) +commonName_max = 64 + +emailAddress = Email Address +emailAddress_max = 64 + +# SET-ex3 = SET extension number 3 + +[ req_attributes ] +challengePassword = A challenge password +challengePassword_min = 4 +challengePassword_max = 20 + +unstructuredName = An optional company name + +[ usr_cert ] + +# These extensions are added when 'ca' signs a request. +authorityInfoAccess = OCSP;URI:http://localhost:8889 +#crlDistributionPoints=URI:http://localhost:8902/demoCA/crl/Sub_CA_2_Root_7.crl +# This is typical in keyUsage for a client certificate. +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +#nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + + + +[ v3_req ] + +# Extensions to add to a certificate request + +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +#authorityInfoAccess = OCSP;URI:http://localhost:8888/ + +[ v3_ca ] + + +# Extensions for a typical CA + + +# PKIX recommendation. + +subjectKeyIdentifier=hash + +authorityKeyIdentifier=keyid:always,issuer:always + +#authorityInfoAccess = OCSP;URI:http://localhost:8888 +#crlDistributionPoints=URI:http://localhost:8901/demoCA/crl/Test_CA_2009.2.crl +# This is what PKIX recommends but some broken software chokes on critical +# extensions. +#basicConstraints = critical,CA:true +# So we do this instead. +basicConstraints = critical, CA:true + +# Key usage: this is typical for a CA certificate. However since it will +# prevent it being used as a test self-signed certificate it is best +# left out by default. +# keyUsage = cRLSign, keyCertSign + +# Some might want this also +# nsCertType = sslCA, emailCA + +# Include email address in subject alt name: another PKIX recommendation +# subjectAltName=email:copy +# Copy issuer details +# issuerAltName=issuer:copy + +# DER hex encoding of an extension: beware experts only! +# obj=DER:02:03 +# Where 'obj' is a standard or added object +# You can even override a supported extension: +# basicConstraints= critical, DER:30:03:01:01:FF + +[ crl_ext ] + +# CRL extensions. +# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. + +# issuerAltName=issuer:copy +authorityKeyIdentifier=keyid:always,issuer:always + +[ proxy_cert_ext ] +# These extensions should be added when creating a proxy certificate + +# This goes against PKIX guidelines but some CAs do it and some software +# requires this to avoid interpreting an end user certificate as a CA. + +basicConstraints=CA:FALSE + +# Here are some examples of the usage of nsCertType. If it is omitted +# the certificate can be used for anything *except* object signing. + +# This is OK for an SSL server. +# nsCertType = server + +# For an object signing certificate this would be used. +# nsCertType = objsign + +# For normal client use this is typical +# nsCertType = client, email + +# and for everything including object signing: +# nsCertType = client, email, objsign + +# This is typical in keyUsage for a client certificate. +# keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +# This will be displayed in Netscape's comment listbox. +nsComment = "OpenSSL Generated Certificate" + +# PKIX recommendations harmless if included in all certificates. +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer:always + +# This stuff is for subjectAltName and issuerAltname. +# Import the email address. +# subjectAltName=email:copy +# An alternative to produce certificates that aren't +# deprecated according to PKIX. +# subjectAltName=email:move + +# Copy subject details +# issuerAltName=issuer:copy + +#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem +#nsBaseUrl +#nsRevocationUrl +#nsRenewalUrl +#nsCaPolicyUrl +#nsSslServerName + +# This really needs to be in place for it to be a proxy certificate. +proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo diff --git a/xmlsecurity/test_docs/certs/ca_certs/Root_1.crt b/xmlsecurity/test_docs/certs/ca_certs/Root_1.crt new file mode 100644 index 000000000..ff4f23a90 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 000000000..64f80334b 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 000000000..bbf0819dd 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 000000000..5f4bd15cd 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 000000000..306aa5649 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 000000000..a4c1dd84d 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 000000000..e9af2c330 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 000000000..03f2ff0b3 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 000000000..96eb50459 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 000000000..c714844ad 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 000000000..d83ce86de 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 000000000..c4857c541 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 000000000..d39b18b57 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 000000000..b881f8a12 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 000000000..61391a8c2 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 000000000..223d047ca 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 000000000..af6a36003 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 000000000..05297a327 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 000000000..209059fac 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 000000000..a981a091c 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 000000000..d73827e10 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 000000000..69da1318b 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 000000000..e7fee3ade 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 000000000..95e18ae6a 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 000000000..5978b2613 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 000000000..10b370c14 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 000000000..90bf8eba4 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 000000000..c9f542029 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 000000000..7fc03f255 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 000000000..567b8b5d1 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 000000000..a2ce79b3a 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 000000000..16abebe51 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 000000000..08f5040ce 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 000000000..18bd2475c 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 000000000..c7c83cf19 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 000000000..3ff2118d2 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 000000000..0fcd6393a 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 000000000..9f2874060 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 000000000..49442c6df 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 000000000..27109c5bb 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 000000000..5cce769b4 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 000000000..09f2a54f4 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 000000000..c3810ab50 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 000000000..1531d1e8d 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 000000000..3dab25877 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 000000000..278b11b77 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 000000000..fa6e84547 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 000000000..863f6f613 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 000000000..cae3959d1 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 000000000..e5786dc6c 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 000000000..a63a9f8c9 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 000000000..59a77df71 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 000000000..3b12b29c1 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 000000000..c11e716d7 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 000000000..026274f63 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 000000000..4a026790e 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 000000000..46b008eeb 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 000000000..7c1c2cb29 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 000000000..cc6185cc9 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 000000000..fa646e402 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 000000000..673db6cc9 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 000000000..e284dca9b 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 000000000..5b2cda461 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 000000000..532010b18 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 000000000..282aa47af 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 000000000..26a51418f 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 000000000..8a00d3008 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 000000000..935da38c2 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 000000000..79ea4fbcf 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 000000000..011c4ae2a 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 000000000..b14254428 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 000000000..8c8689e10 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 000000000..ed39bea1e 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 000000000..7f9e13698 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 000000000..dc28470c8 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 000000000..df9d81d8d 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 000000000..018da383d 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 000000000..0092d16c7 --- /dev/null +++ b/xmlsecurity/test_docs/certs/end_certs/User_35_Root_11.crt @@ -0,0 +1,64 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4130 (0x1022) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=Root 11 + Validity + Not Before: Nov 8 10:51:39 2010 GMT + Not After : Nov 8 10:51:39 2011 GMT + Subject: C=DE, ST=Hamburg, O=OpenOffice.org, OU=Development, CN=User 35 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (1024 bit) + Modulus (1024 bit): + 00:9b:36:00:64:f3:ce:93:97:62:19:fa:78:d9:6f: + 92:6a:b9:d2:9a:4e:06:2c:02:52:cd:93:50:84:28: + 19:42:a2:4a:34:e2:cd:e6:b0:39:7a:c8:4d:84:bc: + 71:51:ed:5d:6c:7e:f9:cc:01:5a:4b:73:50:a9:3b: + 5d:ad:cc:89:f7:dc:e0:dd:0a:ff:48:01:a9:34:19: + c0:6a:ee:4b:20:f4:cf:3c:94:c1:ae:88:0f:c9:42: + 1a:a6:47:31:fe:37:04:00:bb:ec:07:5f:cb:ee:70: + c4:c7:7c:6f:ee:03:19:76:de:0b:df:d0:48:91:67: + 55:9b:90:91:f4:ce:56:04:d5 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Subject Key Identifier: + 91:47:AC:29:95:5D:EF:72:14:8F:82:45:07:E2:94:49:75:C6:7D:73 + X509v3 Authority Key Identifier: + keyid:E8:6A:BB:C2:90:EA:6C:70:22:3E:F6:F6:48:1B:03:E6:BE:B7:A6:55 + + X509v3 Subject Alternative Name: + DNS:alt.openoffice.org, IP Address:192.168.7.1, IP Address:13:0:0:0:0:0:0:17, email:my@other.address, Registered ID:1.2.3.4, othername:, 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 000000000..879f4578c 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 000000000..75a9c7c84 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 000000000..cf07f4aa2 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 000000000..993a09f95 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 000000000..a1cebacb3 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 000000000..12410ebc8 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 000000000..f7372d09f 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 000000000..7df592643 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 000000000..048ca8e8f 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 000000000..4498cdb76 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 000000000..d85e0b7d4 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 000000000..ff666ff1e 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 000000000..55e0d6233 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 000000000..baa32f26b 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 000000000..7b20ff98c 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 000000000..6e980df49 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 000000000..4d343d6e7 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 000000000..aa5f27d2d 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 000000000..80e5bf47c 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 000000000..1e9a14cb8 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 000000000..d7096919b 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 000000000..adc61fff4 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 000000000..9213427a1 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 000000000..005191d16 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 000000000..e4599b113 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 000000000..32b4926ad 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 000000000..2c0ea4acb 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 000000000..b69a19e4e 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 000000000..7897733c4 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 000000000..99eb94452 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 000000000..1aefff504 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 000000000..6b6d5fd4e 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 000000000..bebfdc88a 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 000000000..cbd6730a8 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 000000000..ab2b651c1 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 000000000..518388c5b 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 000000000..775b1359d 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 000000000..f76a61869 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 000000000..ef1273c72 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 000000000..4208dc431 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 000000000..4826f2d04 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 000000000..bc211718a 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 000000000..876151de3 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 000000000..268eeb938 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 000000000..2fc86b9af 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 000000000..80dd6a8b0 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 000000000..821bb8ea5 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 000000000..3671d176d 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 000000000..a4c63b7f2 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 000000000..99b0be699 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 000000000..5dbaf524c 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 000000000..17e22f7a5 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 000000000..5982532a9 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 000000000..4c00b21d4 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 000000000..bc476b257 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 000000000..0b9bd319b 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 000000000..99de803de 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 000000000..a663a92d9 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 000000000..c3d4e7532 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 000000000..9db9c0ad4 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 000000000..ccb03b327 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 000000000..8c34889df 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 000000000..6a1b48c6a 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 000000000..248fccedd 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 000000000..2e0dbd6f7 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 000000000..3519e4a81 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 000000000..06e412fa3 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 000000000..851fc87e7 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 000000000..a97598d55 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 000000000..f82a02a45 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 000000000..5cbf289de 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 000000000..20c28d925 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 000000000..d3f59e601 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 000000000..8c6416b80 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 000000000..fce479cc6 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 000000000..53d1e01e7 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 000000000..1f69a3248 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 000000000..53a29310e 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 000000000..4d34bc0f5 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 000000000..ca17f6aab 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 000000000..798f25a35 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 000000000..591f9aa4d 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 000000000..cb0763b0a 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 000000000..f0555b1a2 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 000000000..b2e24fc61 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 000000000..640a80dce 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 000000000..35847216b 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 000000000..575f3a12d 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 000000000..75a417cab 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 000000000..f7d71762f 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 000000000..9984aa1bb 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 000000000..5ad7b68ab 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 000000000..d126a8dff 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 000000000..dd475c354 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 000000000..f8ab95c04 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 000000000..4d7c5cd80 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 000000000..0979ae5a9 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 000000000..f7c9bbf5e 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 000000000..d26eb58f0 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 000000000..5d6c053c2 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 000000000..cb6401c16 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 000000000..09b63b40a 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 000000000..e810d785d 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 000000000..6c2bbd045 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 000000000..b8b036cc8 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 000000000..6ba0ec52a 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 000000000..de1c635c1 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 000000000..f6575ec88 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 000000000..41f676f63 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 000000000..45bbb5b0d 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 000000000..b253a78b6 --- /dev/null +++ b/xmlsecurity/test_docs/tools/README.txt @@ -0,0 +1,24 @@ +httpserv +============ +Simple http server for testing of Certificate Revocation Lists (CRL). + +Netbeans 6.7.1 project. httpserv.jar requires java 6. + +Run with + +java -jar httpserv/dist/httpserv.jar --accept portnumber + +portnumber: an arbitrary port number to which the server should listen. + +httpserv looks for the requested file relative to the current directory. For +example, you are in +$(SRC_ROOT)/xmlsecurity/$(INPATH)/httpserv/dist/javadoc, +a directory which contains the index.html. From there you run httpserv.jar: + +java -jar /httpserv.jar --accept 8000 + +now enter in the Browser: + +localhost:8000/index.html + + diff --git a/xmlsecurity/test_docs/tools/httpserv/build.xml b/xmlsecurity/test_docs/tools/httpserv/build.xml new file mode 100644 index 000000000..3492d3aa6 --- /dev/null +++ b/xmlsecurity/test_docs/tools/httpserv/build.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + 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 000000000..328e8e5bc --- /dev/null +++ b/xmlsecurity/test_docs/tools/httpserv/manifest.mf @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +X-COMMENT: Main-Class will be added automatically by build + diff --git a/xmlsecurity/test_docs/tools/httpserv/nbproject/build-impl.xml b/xmlsecurity/test_docs/tools/httpserv/nbproject/build-impl.xml new file mode 100644 index 000000000..9064a3305 --- /dev/null +++ b/xmlsecurity/test_docs/tools/httpserv/nbproject/build-impl.xml @@ -0,0 +1,700 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 000000000..d8139c888 --- /dev/null +++ b/xmlsecurity/test_docs/tools/httpserv/nbproject/genfiles.properties @@ -0,0 +1,9 @@ +# x-no-translate +build.xml.data.CRC32=8071b819 +build.xml.script.CRC32=deb21e95 +build.xml.stylesheet.CRC32=958a1d3e@1.26.2.45 +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. +nbproject/build-impl.xml.data.CRC32=8071b819 +nbproject/build-impl.xml.script.CRC32=21d1be7e +nbproject/build-impl.xml.stylesheet.CRC32=5c621a33@1.26.2.45 diff --git a/xmlsecurity/test_docs/tools/httpserv/nbproject/project.properties b/xmlsecurity/test_docs/tools/httpserv/nbproject/project.properties new file mode 100644 index 000000000..a0ec60ac7 --- /dev/null +++ b/xmlsecurity/test_docs/tools/httpserv/nbproject/project.properties @@ -0,0 +1,65 @@ +# x-no-translate +application.title=httpserv +application.vendor=jochen +build.classes.dir=${build.dir}/classes +build.classes.excludes=**/*.java,**/*.form +# This directory is removed when the project is cleaned: +build.dir=build +build.generated.dir=${build.dir}/generated +build.generated.sources.dir=${build.dir}/generated-sources +# Only compile against the classpath explicitly listed here: +build.sysclasspath=ignore +build.test.classes.dir=${build.dir}/test/classes +build.test.results.dir=${build.dir}/test/results +# Uncomment to specify the preferred debugger connection transport: +#debug.transport=dt_socket +debug.classpath=\ + ${run.classpath} +debug.test.classpath=\ + ${run.test.classpath} +# This directory is removed when the project is cleaned: +dist.dir=../../../${env.INPATH}/misc/httpserv +dist.jar=${dist.dir}/httpserv.jar +dist.javadoc.dir=${dist.dir}/javadoc +excludes= +includes=** +jar.compress=false +javac.classpath= +# Space-separated list of extra javac options +javac.compilerargs= +javac.deprecation=false +javac.source=1.5 +javac.target=1.5 +javac.test.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir}:\ + ${libs.junit.classpath}:\ + ${libs.junit_4.classpath} +javadoc.additionalparam= +javadoc.author=false +javadoc.encoding=${source.encoding} +javadoc.noindex=false +javadoc.nonavbar=false +javadoc.notree=false +javadoc.private=false +javadoc.splitindex=true +javadoc.use=true +javadoc.version=false +javadoc.windowtitle= +main.class=httpserv.Main +manifest.file=manifest.mf +meta.inf.dir=${src.dir}/META-INF +platform.active=default_platform +run.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir} +# Space-separated list of JVM arguments used when running the project +# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value +# or test-sys-prop.name=value to set system properties for unit tests): +run.jvmargs= +run.test.classpath=\ + ${javac.test.classpath}:\ + ${build.test.classes.dir} +source.encoding=UTF-8 +src.dir=src +test.src.dir=test diff --git a/xmlsecurity/test_docs/tools/httpserv/nbproject/project.xml b/xmlsecurity/test_docs/tools/httpserv/nbproject/project.xml new file mode 100644 index 000000000..6fc771ca7 --- /dev/null +++ b/xmlsecurity/test_docs/tools/httpserv/nbproject/project.xml @@ -0,0 +1,15 @@ + + + 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 000000000..1f9fd91d2 --- /dev/null +++ b/xmlsecurity/test_docs/tools/httpserv/src/httpserv/Main.java @@ -0,0 +1,190 @@ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +package httpserv; + +import com.sun.net.httpserver.Headers; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.net.InetSocketAddress; + +public class Main { + + /** + * @param args the command line arguments + */ + public static void main(String[] args) { + try { + + Option[] opts = new Option[2]; + opts[0] = new Option("--help", "-h", false); + opts[1] = new Option("--accept", "-a", true); + if (!parseOptions(args, opts)) { + return; + } + HttpServer server = HttpServer.create( + new InetSocketAddress((Integer) opts[1].value), 0); + server.createContext("/", new MyHandler()); + server.setExecutor(null); + server.start(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + static boolean parseOptions(String[] args, Option[] inout_options) { + if (args.length == 0) { + printUsage(); + return false; + } + + boolean bWrongArgs = true; + Option currentOpt = null; + + for (String s : args) { + // get the value for an option + if (currentOpt != null && currentOpt.bHasValue) { + //now we expect the value for the option + //check the type + try { + if (currentOpt.sLong.equals("--accept")) { + currentOpt.value = Integer.decode(s); + } + } catch (Exception e ) { + printUsage(); + return false; + } + currentOpt = null; + continue; + } else { + currentOpt = null; + } + + + // get the option + for (Option o : inout_options) { + if (s.equals(o.sLong) || s.equals(o.sShort)) { + bWrongArgs = false; + //special handling for --help + if (o.sLong.equals("--help")) { + printUsage(); + return false; + } + else + { + currentOpt = o; + break; + } + } + } + } + + if (bWrongArgs) { + printUsage(); + return false; + } + return true; + } + + static void printUsage() { + String usage = + "Usage: \n" + + "java -jar httpserv [options] \n" + + "\n" + + "Options are: \n" + + "-h --help \t this help \n" + + "-a --accept port \t the port number to which this server listens \n"; + System.out.println(usage); + } +} + +class MyHandler implements HttpHandler { + + public void handle(HttpExchange xchange) throws IOException { + try { + //First get the path to the file + String sRequestPath = xchange.getRequestURI().getPath(); + System.out.println("requested: " + sRequestPath); + File fileRequest = new File(new File(".").getCanonicalPath(), sRequestPath); + if (!fileRequest.exists()) { + throw new IOException("The file " + fileRequest + " does not exist!"); + } + else if (fileRequest.isDirectory()) { + throw new IOException(fileRequest + " is a directory!"); + } + + + //Read the file into a byte array + byte[] data = new byte[(int) fileRequest.length()]; + FileInputStream fr = new FileInputStream(fileRequest); + fr.read(data); + fr.close(); + + //set the Content-type header + Headers h = xchange.getResponseHeaders(); + String canonicalPath = fileRequest.getCanonicalPath(); + int lastIndex = canonicalPath.lastIndexOf("."); + String fileExtension = canonicalPath.substring(lastIndex + 1); + + if (fileExtension.equalsIgnoreCase("crl")) + { + h.set("Content-Type","application/pkix-crl"); + } + else if (fileExtension.equalsIgnoreCase("crt") + || fileExtension.equalsIgnoreCase("cer") + || fileExtension.equalsIgnoreCase("der")) + { + h.set("Content-Type", "application/x-x509-ca-cert"); + } + + //write out the requested file + xchange.sendResponseHeaders(200, data.length); + OutputStream os = xchange.getResponseBody(); + os.write(data); + os.close(); + System.out.println("delivered: " + fileRequest.toString()); + + } catch (Exception e) { + xchange.sendResponseHeaders(404, e.getMessage().length()); + OutputStream os = xchange.getResponseBody(); + os.write(e.getMessage().getBytes()); + os.close(); + System.out.println("Error: " + e.getMessage()); + } + } +} + +class Option { + + Option(String _sLong, String _sShort, boolean _bHasValue) { + sLong = _sLong; + sShort = _sShort; + bHasValue = _bHasValue; + } + String sLong; + String sShort; + boolean bHasValue; + Object value; +} + + diff --git a/xmlsecurity/uiconfig/ui/certdetails.ui b/xmlsecurity/uiconfig/ui/certdetails.ui new file mode 100644 index 000000000..03c2a1459 --- /dev/null +++ b/xmlsecurity/uiconfig/ui/certdetails.ui @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + + + 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 + + + + + + + + + False + True + 0 + + + + + True + True + True + True + never + in + + + True + True + True + True + + + + + False + True + 1 + + + + diff --git a/xmlsecurity/uiconfig/ui/certgeneral.ui b/xmlsecurity/uiconfig/ui/certgeneral.ui new file mode 100644 index 000000000..a019bbdf3 --- /dev/null +++ b/xmlsecurity/uiconfig/ui/certgeneral.ui @@ -0,0 +1,248 @@ + + + + + + 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 + + + + + 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 000000000..38b0f095e --- /dev/null +++ b/xmlsecurity/uiconfig/ui/certpage.ui @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + 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.52999997138977051 + + + 0 + 2 + + + + + True + True + True + True + in + + + True + True + True + True + True + liststore3 + False + 0 + True + + + + + + True + 6 + + + + 0 + + + + + + + + + 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 + + + + + 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 + + + + diff --git a/xmlsecurity/uiconfig/ui/digitalsignaturesdialog.ui b/xmlsecurity/uiconfig/ui/digitalsignaturesdialog.ui new file mode 100644 index 000000000..fc86ae079 --- /dev/null +++ b/xmlsecurity/uiconfig/ui/digitalsignaturesdialog.ui @@ -0,0 +1,497 @@ + + + + + + + + + + + + + + + + + + + + + + + + False + 6 + Digital Signatures + True + dialog + + + + + + False + vertical + 12 + + + False + end + + + gtk-help + True + True + True + True + + + False + True + 0 + True + + + + + gtk-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 + + + + + + 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 + + + + + + + + + 0 + 4 + + + + + True + False + 12 + True + spread + + + View Certificate... + True + True + True + + + False + True + 0 + + + + + Sign Document... + True + True + True + True + + + False + True + 1 + + + + + Remove + True + True + True + + + False + 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 + + + + + Use AdES-compliant signature when there is a choice + True + True + True + start + True + 0.5 + True + + + 0 + 6 + + + + + True + True + 1 + + + + + + help + close + + + diff --git a/xmlsecurity/uiconfig/ui/macrosecuritydialog.ui b/xmlsecurity/uiconfig/ui/macrosecuritydialog.ui new file mode 100644 index 000000000..ffbb57cf5 --- /dev/null +++ b/xmlsecurity/uiconfig/ui/macrosecuritydialog.ui @@ -0,0 +1,206 @@ + + + + + + False + 6 + Macro Security + True + 0 + 0 + dialog + + + + + + False + vertical + 12 + + + False + end + + + gtk-revert-to-saved + True + True + True + True + + + False + True + 0 + + + + + gtk-ok + True + True + True + True + True + True + + + False + True + 1 + + + + + gtk-cancel + True + True + True + True + + + False + True + 2 + + + + + gtk-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 000000000..53cecc7d2 --- /dev/null +++ b/xmlsecurity/uiconfig/ui/securitylevelpage.ui @@ -0,0 +1,143 @@ + + + + + + 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 + 0 + True + high + + + 1 + 3 + + + + + _Medium. +Confirmation required before executing macros from untrusted sources. + True + True + False + True + True + 0 + True + high + + + 1 + 2 + + + + + H_igh. +Only signed macros from trusted sources are allowed to run. +Unsigned macros are disabled. + True + True + False + True + True + 0 + True + True + + + 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 + 0 + True + high + + + 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 000000000..b9d5ef518 --- /dev/null +++ b/xmlsecurity/uiconfig/ui/securitytrustpage.ui @@ -0,0 +1,379 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + True + False + True + True + 6 + vertical + 12 + + + True + False + True + True + 0 + none + + + True + False + True + True + 6 + 12 + + + True + False + 6 + True + True + 6 + 6 + + + True + False + True + 12 + end + + + _View... + True + True + True + True + + + False + True + 0 + + + + + gtk-remove + True + True + True + True + + + False + True + 1 + + + + + 1 + 1 + + + + + True + True + True + True + in + + + True + True + True + True + True + liststore3 + 0 + False + True + + + + + + True + 6 + Issued to + + + + 0 + + + + + + + True + 6 + Issued by + + + + 1 + + + + + + + True + 6 + Expiration date + + + + 2 + + + + + + + + + 1 + 0 + + + + + False + True + res/lock.png + center + center + + + 0 + 0 + + + + + + + + + + + + True + False + Trusted Certificates + + + + + + + + False + True + 0 + + + + + True + False + True + True + 0 + none + + + True + False + True + True + 6 + 12 + + + True + False + 6 + True + True + 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 + + + False + True + 0 + + + + + gtk-remove + True + True + True + True + + + False + True + 1 + + + + + 1 + 2 + + + + + True + True + True + True + in + + + True + True + True + True + True + liststore2 + False + 0 + False + + + + + + True + 6 + + + + 0 + + + + + + + + + 1 + 1 + + + + + False + True + res/lock.png + center + center + + + 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 000000000..e7be9472a --- /dev/null +++ b/xmlsecurity/uiconfig/ui/selectcertificatedialog.ui @@ -0,0 +1,282 @@ + + + + + + + + + + + + + + + + + + + + + + False + 6 + Select Certificate + False + True + dialog + + + + + + False + vertical + 12 + + + False + end + + + gtk-ok + True + True + True + True + True + True + + + False + True + 0 + + + + + gtk-cancel + True + True + True + True + + + False + True + 1 + + + + + gtk-help + True + True + True + True + + + False + True + 2 + True + + + + + False + True + end + 0 + + + + + True + False + True + True + 12 + 12 + + + False + 1 + Select the certificate you want to use for signing: + 0 + + + 0 + 0 + + + + + False + 1 + 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 + + + + + + True + 6 + Issued to + + + + 0 + + + + + + + True + 6 + Issued by + + + + 1 + + + + + + + True + 6 + Type + + + + 2 + + + + + + + True + 6 + Expiration date + + + + 3 + + + + + + + True + 6 + Certificate usage + + + + 4 + + + + + + + + + 0 + 2 + + + + + View Certificate... + True + True + True + end + + + 0 + 3 + + + + + True + False + 12 + + + True + False + Description: + + + False + True + 0 + + + + + True + True + True + + + True + True + 1 + + + + + 0 + 4 + + + + + True + True + 1 + + + + + + ok + cancel + help + + + diff --git a/xmlsecurity/uiconfig/ui/viewcertdialog.ui b/xmlsecurity/uiconfig/ui/viewcertdialog.ui new file mode 100644 index 000000000..a545c4249 --- /dev/null +++ b/xmlsecurity/uiconfig/ui/viewcertdialog.ui @@ -0,0 +1,224 @@ + + + + + + False + 6 + View Certificate + False + True + 0 + 0 + dialog + + + + + + False + vertical + 12 + + + False + end + + + gtk-ok + True + True + True + True + True + True + + + False + True + 0 + + + + + gtk-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 000000000..adb647f20 --- /dev/null +++ b/xmlsecurity/util/xmlsecurity.component @@ -0,0 +1,30 @@ + + + + + + + + + + + diff --git a/xmlsecurity/util/xsec_xmlsec.component b/xmlsecurity/util/xsec_xmlsec.component new file mode 100644 index 000000000..d219dc6f9 --- /dev/null +++ b/xmlsecurity/util/xsec_xmlsec.component @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xmlsecurity/workben/pdfverify.cxx b/xmlsecurity/workben/pdfverify.cxx new file mode 100644 index 000000000..c44803594 --- /dev/null +++ b/xmlsecurity/workben/pdfverify.cxx @@ -0,0 +1,222 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.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 + +using namespace com::sun::star; + +namespace +{ +/// Does PDF to PNG conversion using pdfium. +void generatePreview(const OString& rPdfPath, const OString& rPngPath) +{ + GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter(); + Graphic aGraphic; + OUString aInURL; + osl::FileBase::getFileURLFromSystemPath(OUString::fromUtf8(rPdfPath), aInURL); + SvFileStream aInStream(aInURL, StreamMode::READ); + WmfExternal* pExtHeader = nullptr; + if (rFilter.ImportGraphic(aGraphic, OUString(), aInStream, GRFILTER_FORMAT_DONTKNOW, nullptr, + GraphicFilterImportFlags::NONE, pExtHeader) + != ERRCODE_NONE) + return; + + BitmapEx aBitmapEx = aGraphic.GetBitmapEx(); + vcl::PNGWriter aWriter(aBitmapEx); + OUString aOutURL; + osl::FileBase::getFileURLFromSystemPath(OUString::fromUtf8(rPngPath), aOutURL); + SvFileStream aOutStream(aOutURL, StreamMode::WRITE); + aWriter.Write(aOutStream); +} + +int pdfVerify(int nArgc, char** pArgv) +{ + if (nArgc < 2) + { + SAL_WARN("xmlsecurity.pdfio", "not enough parameters"); + return 1; + } + + // Initialize nss / mscrypto. + uno::Reference xComponentContext; + try + { + xComponentContext = cppu::defaultBootstrap_InitialComponentContext(); + } + catch (const uno::RuntimeException&) + { + TOOLS_WARN_EXCEPTION("xmlsecurity.pdfio", + "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 && OString(pArgv[3]) == "-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.pdfio", + "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 && OString(pArgv[3]) == "-r") + bRemoveSignature = true; + + SvFileStream aStream(aInURL, StreamMode::READ); + vcl::filter::PDFDocument aDocument; + if (!aDocument.Read(aStream)) + { + SAL_WARN("xmlsecurity.pdfio", "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.pdfio", "failed to remove signature #" << nPosition); + return 1; + } + + SvFileStream aOutStream(aOutURL, StreamMode::WRITE | StreamMode::TRUNC); + if (!aDocument.Write(aOutStream)) + { + SAL_WARN("xmlsecurity.pdfio", "failed to write the document"); + return 1; + } + + return 0; + } + + if (aOutURL.isEmpty()) + { + std::cerr << "verifying signatures" << std::endl; + std::vector aSignatures = aDocument.GetSignatureWidgets(); + if (aSignatures.empty()) + std::cerr << "found no signatures" << std::endl; + else + { + std::cerr << "found " << aSignatures.size() << " signatures" << std::endl; + int nMDPPerm = aDocument.GetMDPPerm(); + for (size_t i = 0; i < aSignatures.size(); ++i) + { + SignatureInformation aInfo(i); + if (!xmlsecurity::pdfio::ValidateSignature(aStream, aSignatures[i], aInfo, + aDocument, nMDPPerm)) + { + SAL_WARN("xmlsecurity.pdfio", "failed to determine digest match"); + return 1; + } + + bool bSuccess + = aInfo.nStatus == xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED; + std::cerr << "signature #" << i << ": digest match? " << bSuccess << std::endl; + std::cerr << "signature #" << i << ": partial? " << aInfo.bPartialDocumentSignature + << std::endl; + } + } + + 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.pdfio", "no signing certificates found"); + return 1; + } + if (!aDocument.Sign(aCertificates[0], "pdfverify", /*bAdES=*/true)) + { + SAL_WARN("xmlsecurity.pdfio", "failed to sign"); + return 1; + } + + SvFileStream aOutStream(aOutURL, StreamMode::WRITE | StreamMode::TRUNC); + if (!aDocument.Write(aOutStream)) + { + SAL_WARN("xmlsecurity.pdfio", "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