From b4cbcc2c27c450719fad325ba7d7126d8688d7f2 Mon Sep 17 00:00:00 2001 From: Thomas <> Date: Thu, 1 Jul 2021 07:38:29 +0200 Subject: add tracelog into SAML2 verification engine --- .../impl/verification/SamlVerificationEngine.java | 17 +++ .../pvp2/test/SamlVerificationEngineEidasTest.java | 114 +++++++++++++++ .../src/test/resources/config/config_eidas.props | 19 +++ .../src/test/resources/data/junit_eidas.jks | Bin 0 -> 99870 bytes .../src/test/resources/data/metadata_eidas.xml | 153 +++++++++++++++++++++ .../src/test/resources/data/response_eidas.xml | 68 +++++++++ 6 files changed, 371 insertions(+) create mode 100644 eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/SamlVerificationEngineEidasTest.java create mode 100644 eaaf_modules/eaaf_module_pvp2_core/src/test/resources/config/config_eidas.props create mode 100644 eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/junit_eidas.jks create mode 100644 eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/metadata_eidas.xml create mode 100644 eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/response_eidas.xml diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/SamlVerificationEngine.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/SamlVerificationEngine.java index 8bc770eb..a209a131 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/SamlVerificationEngine.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/SamlVerificationEngine.java @@ -30,6 +30,8 @@ import javax.xml.validation.Validator; import org.apache.commons.lang3.StringUtils; import org.joda.time.DateTime; import org.opensaml.core.criterion.EntityIdCriterion; +import org.opensaml.core.xml.io.MarshallingException; +import org.opensaml.core.xml.util.XMLObjectSupport; import org.opensaml.saml.common.xml.SAMLConstants; import org.opensaml.saml.common.xml.SAMLSchemaBuilder; import org.opensaml.saml.common.xml.SAMLSchemaBuilder.SAML1Version; @@ -77,6 +79,7 @@ import lombok.extern.slf4j.Slf4j; import net.shibboleth.utilities.java.support.net.BasicURLComparator; import net.shibboleth.utilities.java.support.net.URIException; import net.shibboleth.utilities.java.support.resolver.CriteriaSet; +import net.shibboleth.utilities.java.support.xml.SerializeSupport; @Slf4j public class SamlVerificationEngine { @@ -247,6 +250,7 @@ public class SamlVerificationEngine { // validate each assertion final List validatedassertions = new ArrayList<>(); for (final Assertion saml2assertion : saml2assertions) { + traceLogFullAssertion(saml2assertion); if (internalAssertionValidation(saml2assertion, spEntityID, validateDateTime)) { log.debug("Add valid Assertion:" + saml2assertion.getID()); validatedassertions.add(saml2assertion); @@ -275,6 +279,19 @@ public class SamlVerificationEngine { } } + private void traceLogFullAssertion(Assertion saml2assertion) { + if (log.isTraceEnabled()) { + try { + log.trace("Decrypted SAML2 Response:", SerializeSupport.nodeToString( + XMLObjectSupport.getMarshaller(saml2assertion).marshall(saml2assertion))); + + } catch (MarshallingException e) { + log.info("Can NOT trace decrypted SAML2 Assertion", e); + + } + } + } + private boolean internalAssertionValidation(Assertion saml2assertion, String spEntityId, boolean validateDateTime) { boolean isAssertionValid = true; diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/SamlVerificationEngineEidasTest.java b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/SamlVerificationEngineEidasTest.java new file mode 100644 index 00000000..4785879e --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/SamlVerificationEngineEidasTest.java @@ -0,0 +1,114 @@ +package at.gv.egiz.eaaf.modules.pvp2.test; + +import org.apache.xml.security.algorithms.JCEMapper; +import org.joda.time.DateTime; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport; +import org.opensaml.core.xml.io.UnmarshallingException; +import org.opensaml.core.xml.util.XMLObjectSupport; +import org.opensaml.saml.saml2.core.Issuer; +import org.opensaml.saml.saml2.core.Response; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.annotation.DirtiesContext.ClassMode; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.core.impl.data.Pair; +import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2MetadataException; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlAssertionValidationExeption; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlSigningException; +import at.gv.egiz.eaaf.modules.pvp2.impl.metadata.PvpMetadataResolverFactory; +import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafOpenSaml3xInitializer; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils; +import at.gv.egiz.eaaf.modules.pvp2.impl.verification.SamlVerificationEngine; +import at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyCredentialProvider; +import at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyMetadataProvider; +import net.shibboleth.utilities.java.support.xml.XMLParserException; + +@Ignore +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration({ "/spring/test_eaaf_pvp.beans.xml", + "/spring/test_eaaf_core_spring_config.beans.xml", + "/spring/eaaf_utils.beans.xml" }) +@TestPropertySource(locations = { "/config/config_eidas.props" }) +@DirtiesContext(classMode = ClassMode.BEFORE_CLASS) +public class SamlVerificationEngineEidasTest { + + @Autowired + private PvpMetadataResolverFactory metadataResolverFactory; + + @Autowired + private SamlVerificationEngine verifyEngine; + @Autowired + private DummyCredentialProvider credentialProvider; + + @Autowired DummyMetadataProvider metadataProvider; + @Autowired IConfiguration authConfig; + + /** + * JUnit class initializer. + * + * @throws Exception In case of an OpenSAML3 initialization error + */ + @BeforeClass + public static void classInitializer() throws Exception { + EaafOpenSaml3xInitializer.eaafInitialize(); + + } + + /** + * Reset OpenSAML3.x JCEMapper to default. + * + */ + @AfterClass + public static void classCloser() { + JCEMapper.setProviderId(null); + + } + + @Test + public void verifyAssertionSucessNotEncrypted() throws SamlSigningException, Pvp2MetadataException, + CredentialsNotAvailableException, XMLParserException, UnmarshallingException, SamlAssertionValidationExeption { + final String responsePath = "/data/response_eidas.xml"; + final String metadataPath = "classpath:/data/metadata_eidas.xml"; + final String spEntityId = "https://vidp.gv.at/EidasNode/ColleagueResponse"; + + final Pair inputMsg = + initializeResponse(spEntityId, metadataPath, responsePath, + credentialProvider.getMetaDataSigningCredential()); + + verifyEngine.validateAssertion(inputMsg.getFirst(), credentialProvider.getMessageSigningCredential(), + spEntityId, "jUnit Test", false); + + + } + + protected Pair initializeResponse(String spEntityId, String metadataPath, + String authnReqPath, EaafX509Credential credential) + throws SamlSigningException, XMLParserException, UnmarshallingException, Pvp2MetadataException { + final IPvp2MetadataProvider mdResolver = metadataResolverFactory.createMetadataProvider( + metadataPath, null, "jUnit metadata resolver", null); + + final Response response = (Response) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + AbstractSamlVerificationEngine.class.getResourceAsStream(authnReqPath)); + response.setIssueInstant(DateTime.now()); + final Issuer issuer = Saml2Utils.createSamlObject(Issuer.class); + issuer.setValue(spEntityId); + response.setIssuer(issuer); + + return Pair.newInstance( + Saml2Utils.signSamlObject(response, credential, true), + mdResolver); + } +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/config/config_eidas.props b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/config/config_eidas.props new file mode 100644 index 00000000..f99f3de0 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/config/config_eidas.props @@ -0,0 +1,19 @@ +security.hsmfacade.host=eid.a-sit.at +security.hsmfacade.port=9050 +security.hsmfacade.trustedsslcert=src/test/resources/data/hsm_facade_trust_root.crt +security.hsmfacade.username=authhandler-junit +security.hsmfacade.password=supersecret123 +security.hsmfacade.hsmname=software + +keystore.path=classpath:/data/junit_eidas.jks +keystore.pass=password +key.metadata.alias=metadata +key.metadata.pass=password +key.sig.alias=signing +key.sig.pass=password +key.enc.alias=signing +key.enc.pass=password + +client.http.connection.timeout.socket=2 +client.http.connection.timeout.connection=2 +client.http.connection.timeout.request=2 \ No newline at end of file diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/junit_eidas.jks b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/junit_eidas.jks new file mode 100644 index 00000000..20a52d16 Binary files /dev/null and b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/junit_eidas.jks differ diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/metadata_eidas.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/metadata_eidas.xml new file mode 100644 index 00000000..0b9e0fb0 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/metadata_eidas.xml @@ -0,0 +1,153 @@ + + + + + + + + + + + + + mpRL1HhdQbVZvTErUOyLnEg8A9KwdXaRLIZRTIgC/vIbw5wktNzXzF140hYQGudHI8RovcQapGkA +6wjTAkrGvg== + + + +hYs/+wD1DLsPB4WxJStWgT/TWn4hTxfoamZbZe4XcavGWIgLNZoiitdeoYcDoSRbeeBAa5OoZuFf +ev7NmU8E8YjutpdR7i/tGpVAbGD3il5h08VrBMBWm9x1MN+P4fCsuVptrLFrVJcEVfrBVHEJZcOL +yKmc+l2eJh45t+7huH3gBukmbJciriJnsHOJc+xlu6cRBMrDHUIR65PlMdSdeG2Ff9orBA61iaZT +FYDOC19SA89/Mm7P9lylLYg0d+A4zZKGJw6dwPhjkc/NXm1GDZabj6hWLBAfQ7jRJKUVWMd1+QNd +Gnp/FcRdOipxNeiEIIVzEfOx2VwT8OgnNE6RkPVmWDOBdBtQ9udH3drHxAk/09rewEacD47tT37B +Ni9WAGNb2fxiS/wncUS6hKAFpUl86cbT2rXotH0UjEUd/q+fEwlkYzr2wWNVmyae9d40CHj0ps1y +vsAnIG2KudLUENazAwEZHjw9nheL3DyAeu3TWfpsTyyuA5YhWG/YyEeF + + + + MIIEDjCCAnYCCQD6nxCDuFkkmDANBgkqhkiG9w0BAQsFADBJMQswCQYDVQQGEwJBVDENMAsGA1UE +CgwERUdJWjEYMBYGA1UECwwPZUlEQVMgVGVzdC1Ob2RlMREwDwYDVQQDDAhNZXRhZGF0YTAeFw0y +MDA0MTQxNTA2NDFaFw0yMzAxMDgxNTA2NDFaMEkxCzAJBgNVBAYTAkFUMQ0wCwYDVQQKDARFR0la +MRgwFgYDVQQLDA9lSURBUyBUZXN0LU5vZGUxETAPBgNVBAMMCE1ldGFkYXRhMIIBojANBgkqhkiG +9w0BAQEFAAOCAY8AMIIBigKCAYEAnUM3hvAfyL0w4U35Qq1iVvnGYcy8XsxWlNydaqFM5kb5AoSx +AjXMkQ0nUgCJSvDc7A8a8KVkS5Z32gFcF1ucZB7uYB2pkSm8WnHJcwtJrjO8y+D5D+ReVKsNZ5Kp +yvH8CAS4Q+QO14ZFXj5Ear6D06NYuAMKqasXPrPig1Tdbww0vKykhEScr3cld7TTjeZfBODiBuMO +w4FS4IYPcOSGYk8rWw9h02BKfEq05gsR/cT+J/yqYKt5ZTrIvBPKec2EaVyDgiJMzi8g+j2YbBGA +voKABPZoGM19PIeo3QswNjdsrTVlhDZg9uOfLDeX3DKaGhnFApm44BVngz+k40j+vuwzHePIKH3r +5hN+CqHW8yHCRZoih327CYT7s/r8JF6dt+Si+X2Cn/EoVZp+V4jh5L7fmvLaDGbYgOKneTfhjIwe +6KeVOPMHdRmrbgJtNVPSeXGmyDmZCUlDoRdCU+Je9BL46UHGXv0vi8oU/n7ObiyS5uMCjEjYX+dL +UC7AFMpBAgMBAAEwDQYJKoZIhvcNAQELBQADggGBABkgstVxLeeKAaW+vgvt1ak9LUNxkEgXHF+z +hMgH0797I2YztfzCnW51gadnUMjU/fM3OyhuirxErhijxwHMnzzDN4GcfDzSk6W4PXyTAhXKe1b1 +LOP97m7Fpke5lf6EMKiIFcH+cKmXXxNMRImjjoa4h8unkreVh6sMAvtX7L6higi8I2yIsGGp6Dn4 +bHwRngvRVDzDx22OTpTT0EvX/EFsQPzLtxrMCFuJE4IM65drNYJI8WhuGBaXfMhnHhUY6mr5U8Lj +/zjcEQMFwu6qFVGfqF2p1AaNgK3kBslTBezPHoOdi1dt/FP12lozapAIKIBDhp1aqEdZkGYaOaI4 +QHfiBJag/Doao/NHMTTaqMe26/7dlBh5cmd67+DQlnp87jDBIBpg1EJr/JVU9r1rtg2OJhhUmyv3 +HZONASwc8UjkkREqWBIXKZX6GnJBXthVg7Lhna35Nh++agEjMg/IuZNcUzK6ZjDCZdlDD0fenUty +xFug0kx+UUxgnO/qSooe+g== + + + + + + + 1.2 + 1.1 + + + CEF:eIDAS-ref:2.5.0 + + + public + + + + + + + + + + + + + AT + + + + + MIIEDDCCAnQCCQCbVfZgUmuq4jANBgkqhkiG9w0BAQsFADBIMQswCQYDVQQGEwJBVDENMAsGA1UE +CgwERUdJWjEYMBYGA1UECwwPZUlEQVMgVGVzdC1Ob2RlMRAwDgYDVQQDDAdzaWduaW5nMB4XDTIw +MDQxNDE1MDcyMFoXDTIzMDEwODE1MDcyMFowSDELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVHSVox +GDAWBgNVBAsMD2VJREFTIFRlc3QtTm9kZTEQMA4GA1UEAwwHc2lnbmluZzCCAaIwDQYJKoZIhvcN +AQEBBQADggGPADCCAYoCggGBAJu0ab3tEsQ/9xQ4rwvO7PjnK+NOVUvPkReQMFOFg8uduSocBwZ2 +Kdr/WBRrC9kI8cCkWxJHcJi9o6QBKM8Jtc/cJbPmR7CZvm2rtVGiVNew83C3BAFWeUkXpdnXt1lP +lEklsMwq7eOD+OqWPmi6O0sL/QFMDBMo6J51YIXLtFz0ymiu4V4C75/2c5A/ztI7svDdzxIQEJLo +ATnikFV7WD9SZbgFXPi20v/9IicvtQVjLrfKWbctSXe9RV2CBFsuWevJUdxbf7DWETH+e9eukg+9 +6ZFkBIXDqr5xrXXYVD07Hx2DVqjq+aZM2ALnivNPAp7nLqN4GYP+VmqpDJ9A6S/C9K/6ROnVmK1x +YMtqmxv9WKTi0FkMsBEiH5TRuig3gl+MLKQeA44XjdXgNvPmd1WiSL3IgaQPTLXgLeVsflHAWpy/ +IrGjlzuYcpFhg40x0IMvvOv4Z8RGiXyuhFxa3P+T+0mRYBos/RA70UHjIzgoLhoAShBS/WKs3KqZ +2xi4HwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBgQAImDWnTLdq/4VEeaEJKoVzXk7yk++Rxj2gERRI +vh/eHDskFPDZ5Q2Cby3IC4iLaJFpbXyjKskAvVgoasAbRACA5Zf1H6v31V1YLtTmIViPOY1u3130 +kkY86z9QlLx8u6o86GWL2rGb09ZMxqSMjEEGXYntPJ4rWtdUT32Ef1sUKqh0Dm+qPb/M3OnlV2aO +Ti/yJR7sCuIJ8rrTBO5lqOrdK+zzyhWuJx5/JLfTRp7wjGHR+KPS+3CsnPa6fkG9YUkjz0/E7f1G +emt6cq4ozbGw5j5H50YxVJ5KS76KckKNETGUF2/9XXXV0rrBY7HcnqRCqWuc+sZPqv6pQph21gEZ ++1s2FY735uGRrxDR+1tsWuJd5o5agfl8w544erWQ+aLlkouISzfWZdN8opTLNtt/u0qfUjkcXQFg +CyaVwyMJp9Iq/fqOZzVY3he9i6OVGt6owox+n2rymNQ/Zon6qtDCdvgfw30TIpL8AuZzjMyUL1oG +aAb6colSGusGLBkme5k= + + + + + + + MIIEDDCCAnQCCQCbVfZgUmuq4jANBgkqhkiG9w0BAQsFADBIMQswCQYDVQQGEwJBVDENMAsGA1UE +CgwERUdJWjEYMBYGA1UECwwPZUlEQVMgVGVzdC1Ob2RlMRAwDgYDVQQDDAdzaWduaW5nMB4XDTIw +MDQxNDE1MDcyMFoXDTIzMDEwODE1MDcyMFowSDELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVHSVox +GDAWBgNVBAsMD2VJREFTIFRlc3QtTm9kZTEQMA4GA1UEAwwHc2lnbmluZzCCAaIwDQYJKoZIhvcN +AQEBBQADggGPADCCAYoCggGBAJu0ab3tEsQ/9xQ4rwvO7PjnK+NOVUvPkReQMFOFg8uduSocBwZ2 +Kdr/WBRrC9kI8cCkWxJHcJi9o6QBKM8Jtc/cJbPmR7CZvm2rtVGiVNew83C3BAFWeUkXpdnXt1lP +lEklsMwq7eOD+OqWPmi6O0sL/QFMDBMo6J51YIXLtFz0ymiu4V4C75/2c5A/ztI7svDdzxIQEJLo +ATnikFV7WD9SZbgFXPi20v/9IicvtQVjLrfKWbctSXe9RV2CBFsuWevJUdxbf7DWETH+e9eukg+9 +6ZFkBIXDqr5xrXXYVD07Hx2DVqjq+aZM2ALnivNPAp7nLqN4GYP+VmqpDJ9A6S/C9K/6ROnVmK1x +YMtqmxv9WKTi0FkMsBEiH5TRuig3gl+MLKQeA44XjdXgNvPmd1WiSL3IgaQPTLXgLeVsflHAWpy/ +IrGjlzuYcpFhg40x0IMvvOv4Z8RGiXyuhFxa3P+T+0mRYBos/RA70UHjIzgoLhoAShBS/WKs3KqZ +2xi4HwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBgQAImDWnTLdq/4VEeaEJKoVzXk7yk++Rxj2gERRI +vh/eHDskFPDZ5Q2Cby3IC4iLaJFpbXyjKskAvVgoasAbRACA5Zf1H6v31V1YLtTmIViPOY1u3130 +kkY86z9QlLx8u6o86GWL2rGb09ZMxqSMjEEGXYntPJ4rWtdUT32Ef1sUKqh0Dm+qPb/M3OnlV2aO +Ti/yJR7sCuIJ8rrTBO5lqOrdK+zzyhWuJx5/JLfTRp7wjGHR+KPS+3CsnPa6fkG9YUkjz0/E7f1G +emt6cq4ozbGw5j5H50YxVJ5KS76KckKNETGUF2/9XXXV0rrBY7HcnqRCqWuc+sZPqv6pQph21gEZ ++1s2FY735uGRrxDR+1tsWuJd5o5agfl8w544erWQ+aLlkouISzfWZdN8opTLNtt/u0qfUjkcXQFg +CyaVwyMJp9Iq/fqOZzVY3he9i6OVGt6owox+n2rymNQ/Zon6qtDCdvgfw30TIpL8AuZzjMyUL1oG +aAb6colSGusGLBkme5k= + + + + + + + urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified + urn:oasis:names:tc:SAML:2.0:nameid-format:persistent + urn:oasis:names:tc:SAML:2.0:nameid-format:transient + + + + + EGIZ + EGIZ eIDAS Connector + https://www.egiz.gv.at + + + EGIZ + Thomas + Lenz + thomas.lenz@egiz.gv.at + +43 316 873 - 5525 + + + EGIZ + Thomas + Lenz + thomas.lenz@egiz.gv.at + +43 316 873 - 5525 + + diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/response_eidas.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/response_eidas.xml new file mode 100644 index 00000000..fba8c69a --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/response_eidas.xml @@ -0,0 +1,68 @@ + + + https://vidp.gv.at/eidas-middleware/Metadata + + + + + + + + + + + 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 + + + + + + + + + + + + + + + + + MIIEDDCCAnQCCQCbVfZgUmuq4jANBgkqhkiG9w0BAQsFADBIMQswCQYDVQQGEwJBVDENMAsGA1UE +CgwERUdJWjEYMBYGA1UECwwPZUlEQVMgVGVzdC1Ob2RlMRAwDgYDVQQDDAdzaWduaW5nMB4XDTIw +MDQxNDE1MDcyMFoXDTIzMDEwODE1MDcyMFowSDELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVHSVox +GDAWBgNVBAsMD2VJREFTIFRlc3QtTm9kZTEQMA4GA1UEAwwHc2lnbmluZzCCAaIwDQYJKoZIhvcN +AQEBBQADggGPADCCAYoCggGBAJu0ab3tEsQ/9xQ4rwvO7PjnK+NOVUvPkReQMFOFg8uduSocBwZ2 +Kdr/WBRrC9kI8cCkWxJHcJi9o6QBKM8Jtc/cJbPmR7CZvm2rtVGiVNew83C3BAFWeUkXpdnXt1lP +lEklsMwq7eOD+OqWPmi6O0sL/QFMDBMo6J51YIXLtFz0ymiu4V4C75/2c5A/ztI7svDdzxIQEJLo +ATnikFV7WD9SZbgFXPi20v/9IicvtQVjLrfKWbctSXe9RV2CBFsuWevJUdxbf7DWETH+e9eukg+9 +6ZFkBIXDqr5xrXXYVD07Hx2DVqjq+aZM2ALnivNPAp7nLqN4GYP+VmqpDJ9A6S/C9K/6ROnVmK1x +YMtqmxv9WKTi0FkMsBEiH5TRuig3gl+MLKQeA44XjdXgNvPmd1WiSL3IgaQPTLXgLeVsflHAWpy/ +IrGjlzuYcpFhg40x0IMvvOv4Z8RGiXyuhFxa3P+T+0mRYBos/RA70UHjIzgoLhoAShBS/WKs3KqZ +2xi4HwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBgQAImDWnTLdq/4VEeaEJKoVzXk7yk++Rxj2gERRI +vh/eHDskFPDZ5Q2Cby3IC4iLaJFpbXyjKskAvVgoasAbRACA5Zf1H6v31V1YLtTmIViPOY1u3130 +kkY86z9QlLx8u6o86GWL2rGb09ZMxqSMjEEGXYntPJ4rWtdUT32Ef1sUKqh0Dm+qPb/M3OnlV2aO +Ti/yJR7sCuIJ8rrTBO5lqOrdK+zzyhWuJx5/JLfTRp7wjGHR+KPS+3CsnPa6fkG9YUkjz0/E7f1G +emt6cq4ozbGw5j5H50YxVJ5KS76KckKNETGUF2/9XXXV0rrBY7HcnqRCqWuc+sZPqv6pQph21gEZ ++1s2FY735uGRrxDR+1tsWuJd5o5agfl8w544erWQ+aLlkouISzfWZdN8opTLNtt/u0qfUjkcXQFg +CyaVwyMJp9Iq/fqOZzVY3he9i6OVGt6owox+n2rymNQ/Zon6qtDCdvgfw30TIpL8AuZzjMyUL1oG +aAb6colSGusGLBkme5k= + + + + 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 + + + + -- cgit v1.2.3