From 3adf46736778d7b28c7d944b308bcb1620e7f19e Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Tue, 14 Feb 2017 15:38:36 +0100 Subject: change log level of one log message to trace --- .../moa/id/auth/modules/eidas/config/MOAExtendedSWSigner.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'id/server/modules') diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAExtendedSWSigner.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAExtendedSWSigner.java index e08d302f6..c872bcfb6 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAExtendedSWSigner.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAExtendedSWSigner.java @@ -226,7 +226,7 @@ public class MOAExtendedSWSigner implements ProtocolSignerI, MetadataSignerI { checkCertificateIssuer(credential.getEntityCertificate()); Signature signature; try { - Logger.debug("Creating an OpenSAML signature object"); + Logger.trace("Creating an OpenSAML signature object"); signature = (Signature) Configuration.getBuilderFactory().getBuilder(Signature.DEFAULT_ELEMENT_NAME) .buildObject(Signature.DEFAULT_ELEMENT_NAME); -- cgit v1.2.3 From 3a55eb69e5fa94d0bcc43a1732850a14e524f6cc Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Tue, 21 Feb 2017 15:31:18 +0100 Subject: add support of additional eIDAS attributes by using a simple configuration file --- .../moa/id/auth/modules/eidas/Constants.java | 51 +++++++++++++--------- .../eidas/engine/MOAEidasProtocolProcesser.java | 13 ++++-- .../eidas/utils/MOAeIDASMetadataGenerator.java | 7 ++- .../auth/modules/eidas/utils/SAMLEngineUtils.java | 33 +++++++++++++- 4 files changed, 77 insertions(+), 27 deletions(-) (limited to 'id/server/modules') diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/Constants.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/Constants.java index 369d77863..eb5adcce1 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/Constants.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/Constants.java @@ -22,14 +22,15 @@ */ package at.gv.egovernment.moa.id.auth.modules.eidas; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + import org.apache.xml.security.signature.XMLSignature; import org.opensaml.xml.encryption.EncryptionConstants; import org.opensaml.xml.signature.SignatureConstants; //import eu.eidas.auth.engine.core.validator.eidas.EIDASAttributes; -import eu.eidas.auth.commons.attribute.AttributeRegistries; -import eu.eidas.auth.commons.attribute.AttributeRegistry; - /** * @author tlenz * @@ -61,12 +62,16 @@ public class Constants { public static final String CONIG_PROPS_EIDAS_SAMLENGINE_SIGN_CONFIGFILE = CONIG_PROPS_EIDAS_SAMLENGINE_PREFIX + "." + CONIG_PROPS_EIDAS_SAMLENGINE_SIGN + ".config.file"; public static final String CONIG_PROPS_EIDAS_SAMLENGINE_ENC_CONFIGFILE = CONIG_PROPS_EIDAS_SAMLENGINE_PREFIX + "." - + CONIG_PROPS_EIDAS_SAMLENGINE_ENCRYPT + ".config.file"; + + CONIG_PROPS_EIDAS_SAMLENGINE_ENCRYPT + ".config.file"; + public static final String CONIG_PROPS_EIDAS_SAMLENGINE_ATTIONAL_ATTRIBUTE_DEFINITIONS = + CONIG_PROPS_EIDAS_SAMLENGINE_PREFIX + ".attributes.addition.config"; public static final String CONIG_PROPS_EIDAS_METADATA_VALIDATION_TRUSTSTORE = CONIG_PROPS_EIDAS_PREFIX + ".metadata.validation.truststore"; + public static final String CONIG_PROPS_EIDAS_NODE_COUNTRYCODE = CONIG_PROPS_EIDAS_NODE + ".countrycode"; public static final String CONIG_PROPS_EIDAS_NODE_COUNTRY = CONIG_PROPS_EIDAS_NODE + ".country"; - public static final String CONIG_PROPS_EIDAS_NODE_LoA = CONIG_PROPS_EIDAS_NODE + ".LoA"; + public static final String CONIG_PROPS_EIDAS_NODE_LoA = CONIG_PROPS_EIDAS_NODE + ".LoA"; + //timeouts and clock skews @@ -115,21 +120,27 @@ public class Constants { // } // } // ); - - public static final AttributeRegistry NAT_ATTR = - AttributeRegistries.of( eu.eidas.auth.engine.core.eidas.spec.NaturalPersonSpec.Definitions.PERSON_IDENTIFIER, - eu.eidas.auth.engine.core.eidas.spec.NaturalPersonSpec.Definitions.CURRENT_FAMILY_NAME, - eu.eidas.auth.engine.core.eidas.spec.NaturalPersonSpec.Definitions.CURRENT_GIVEN_NAME, - eu.eidas.auth.engine.core.eidas.spec.NaturalPersonSpec.Definitions.DATE_OF_BIRTH - ); - - public static final AttributeRegistry LEGAL_ATTR = - AttributeRegistries.of( eu.eidas.auth.engine.core.eidas.spec.LegalPersonSpec.Definitions.LEGAL_PERSON_IDENTIFIER, - eu.eidas.auth.engine.core.eidas.spec.LegalPersonSpec.Definitions.LEGAL_NAME - ); - - public static final AttributeRegistry MOA_IDP_ATTR_REGISTRY = - AttributeRegistries.copyOf(NAT_ATTR, LEGAL_ATTR); + + //eIDAS attributes that can be provided by MOA-ID + public static final List MOA_IDP_SUPPORTED_eIDAS_ATTRIBUTES; + static { + List supportAttrList = new ArrayList(); + //natural person attributes that can be provided by MOA-ID + supportAttrList.add(eu.eidas.auth.engine.core.eidas.spec.NaturalPersonSpec.Definitions.PERSON_IDENTIFIER.getNameUri().toString()); + supportAttrList.add(eu.eidas.auth.engine.core.eidas.spec.NaturalPersonSpec.Definitions.CURRENT_FAMILY_NAME.getNameUri().toString()); + supportAttrList.add(eu.eidas.auth.engine.core.eidas.spec.NaturalPersonSpec.Definitions.CURRENT_GIVEN_NAME.getNameUri().toString()); + supportAttrList.add(eu.eidas.auth.engine.core.eidas.spec.NaturalPersonSpec.Definitions.DATE_OF_BIRTH.getNameUri().toString()); + + //legal person attributes that can be provided by MOA-ID + supportAttrList.add(eu.eidas.auth.engine.core.eidas.spec.LegalPersonSpec.Definitions.LEGAL_PERSON_IDENTIFIER.getNameUri().toString()); + supportAttrList.add(eu.eidas.auth.engine.core.eidas.spec.LegalPersonSpec.Definitions.LEGAL_NAME.getNameUri().toString()); + + //additionl person attributes that can be provided by MOA-ID + //supportAttrList.add("http://ehn/attributes/ehealth/patientidentifier"); + + MOA_IDP_SUPPORTED_eIDAS_ATTRIBUTES = Collections.unmodifiableList(supportAttrList); + + } public static final String METADATA_ALLOWED_ALG_DIGIST = diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAEidasProtocolProcesser.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAEidasProtocolProcesser.java index c24c5efca..8abf29703 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAEidasProtocolProcesser.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAEidasProtocolProcesser.java @@ -22,7 +22,9 @@ */ package at.gv.egovernment.moa.id.auth.modules.eidas.engine; +import eu.eidas.auth.commons.attribute.AttributeRegistry; import eu.eidas.auth.engine.core.eidas.EidasProtocolProcessor; +import eu.eidas.auth.engine.core.eidas.spec.EidasSpec; import eu.eidas.auth.engine.metadata.MetadataFetcherI; import eu.eidas.auth.engine.metadata.MetadataSignerI; @@ -38,11 +40,14 @@ public class MOAEidasProtocolProcesser extends EidasProtocolProcessor { private final MetadataSignerI metadataSigner; /** - * @param metadataFetcher - * @param metadataSigner + * Build a MOA specific eIDAS-engine protocol processor + * + * @param metadataFetcher eIDAS-engine Metadata fetcher implementation + * @param metadataSigner eIDAS-engine Signer implementation + * @param addAttrDefinitions additinal eIDAS attributes */ - public MOAEidasProtocolProcesser(MetadataFetcherI metadataFetcher, MetadataSignerI metadataSigner) { - super(metadataFetcher, metadataSigner); + public MOAEidasProtocolProcesser(MetadataFetcherI metadataFetcher, MetadataSignerI metadataSigner, AttributeRegistry addAttrDefinitions) { + super(EidasSpec.REGISTRY, addAttrDefinitions, metadataFetcher, metadataSigner); this.metadataFetcher = metadataFetcher; this.metadataSigner = metadataSigner; diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAeIDASMetadataGenerator.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAeIDASMetadataGenerator.java index 8faaf1874..1bebdebbf 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAeIDASMetadataGenerator.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAeIDASMetadataGenerator.java @@ -305,7 +305,12 @@ public class MOAeIDASMetadataGenerator extends MetadataGenerator { public ImmutableSortedSet> getAllSupportedAttributes() { ImmutableSortedSet.Builder> builder = new ImmutableSortedSet.Builder<>(Ordering.>natural()); - builder.addAll(Constants.MOA_IDP_ATTR_REGISTRY.getAttributes()); + + for (String attr : Constants.MOA_IDP_SUPPORTED_eIDAS_ATTRIBUTES) { + AttributeDefinition supAttr = params.getIdpEngine().getProtocolProcessor().getAttributeDefinitionNullable(attr); + builder.add(supAttr); + } + return builder.build(); } diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/SAMLEngineUtils.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/SAMLEngineUtils.java index 70135c06f..edbecc4a0 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/SAMLEngineUtils.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/SAMLEngineUtils.java @@ -23,6 +23,8 @@ package at.gv.egovernment.moa.id.auth.modules.eidas.utils; import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; import java.util.HashMap; import java.util.Map; @@ -36,8 +38,13 @@ import at.gv.egovernment.moa.id.auth.modules.eidas.engine.MOAEidasProtocolProces import at.gv.egovernment.moa.id.auth.modules.eidas.engine.MOAeIDASChainingMetadataProvider; import at.gv.egovernment.moa.id.auth.modules.eidas.engine.MOAeIDASMetadataProviderDecorator; import at.gv.egovernment.moa.id.auth.modules.eidas.exceptions.EIDASEngineException; +import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.FileUtils; +import at.gv.egovernment.moa.util.MiscUtil; import eu.eidas.auth.commons.attribute.AttributeDefinition; +import eu.eidas.auth.commons.attribute.AttributeRegistries; +import eu.eidas.auth.commons.attribute.AttributeRegistry; import eu.eidas.auth.engine.ProtocolEngineI; import eu.eidas.auth.engine.SamlEngineSystemClock; import eu.eidas.auth.engine.metadata.MetadataFetcherI; @@ -62,6 +69,7 @@ public class SAMLEngineUtils { if (eIDASEngine == null) { try { + //get eIDAS SAMLengine configuration from MOA-ID configuration CertificateConfigurationManager configManager = new MOAIDCertificateManagerConfigurationImpl(); @@ -70,12 +78,25 @@ public class SAMLEngineUtils { //set metadata signer metadataSigner = new MOAExtendedSWSigner(configManager); - + + //load additional eIDAS attribute definitions + String additionalAttributeConfigFile = + AuthConfigurationProviderFactory.getInstance().getBasicMOAIDConfiguration( + Constants.CONIG_PROPS_EIDAS_SAMLENGINE_ATTIONAL_ATTRIBUTE_DEFINITIONS); + AttributeRegistry addAttrDefinitions = AttributeRegistries.empty(); + if (MiscUtil.isNotEmpty(additionalAttributeConfigFile)) { + URL addAttrConfigUrl = new URL(FileUtils.makeAbsoluteURL( + additionalAttributeConfigFile, + AuthConfigurationProviderFactory.getInstance().getRootConfigFileDir())); + addAttrDefinitions = AttributeRegistries.fromFile(addAttrConfigUrl.getPath()); + + } + //build eIDAS SAML eninge ProtocolEngineI engine = MOAProtocolEngineFactory.createProtocolEngine( Constants.eIDAS_SAML_ENGINE_NAME, configManager, - new MOAEidasProtocolProcesser(metadataFetcher, metadataSigner), + new MOAEidasProtocolProcesser(metadataFetcher, metadataSigner, addAttrDefinitions), new SamlEngineSystemClock()); //build a map with all actually supported attributes @@ -93,6 +114,14 @@ public class SAMLEngineUtils { Logger.error("eIDAS SAMLengine initialization FAILED!", e); throw new EIDASEngineException("eIDAS.00", new Object[]{e.getMessage()}, e); + } catch (at.gv.egovernment.moa.id.commons.api.exceptions.ConfigurationException e) { + Logger.error("eIDAS SAMLengine initialization FAILED!", e); + throw new EIDASEngineException("eIDAS.00", new Object[]{e.getMessage()}, e); + + } catch (MalformedURLException e) { + Logger.error("eIDAS SAMLengine initialization FAILED!", e); + throw new EIDASEngineException("eIDAS.00", new Object[]{e.getMessage()}, e); + } } -- cgit v1.2.3 From f6acad73155af58b75709077d8dee67dab0be47e Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Wed, 22 Feb 2017 09:24:36 +0100 Subject: Refector eIDAS attribute generation do a dynamic way similar to the PVP attribute builder concept The eIDAS attribute list in eIDAS metadata that contains currently supported attributes is also generated dynamical --- .../builder/attributes/IAttributeGenerator.java | 7 + .../moa/id/auth/modules/eidas/Constants.java | 45 ------ .../eidas/utils/MOAeIDASMetadataGenerator.java | 5 +- .../modules/eidas/utils/eIDASAttributeBuilder.java | 167 +++++++++++++++++++++ .../moa/id/protocols/eidas/EIDASData.java | 4 +- .../moa/id/protocols/eidas/EIDASProtocol.java | 8 + .../eidas/attributes/builder/IeIDASAttribute.java | 33 ++++ .../attributes/builder/eIDASAttrDateOfBirth.java | 37 +++++ .../attributes/builder/eIDASAttrFamilyName.java | 61 ++++++++ .../attributes/builder/eIDASAttrGivenName.java | 61 ++++++++ .../attributes/builder/eIDASAttrLegalName.java | 37 +++++ .../builder/eIDASAttrLegalPersonIdentifier.java | 37 +++++ .../eIDASAttrNaturalPersonalIdentifier.java | 116 ++++++++++++++ .../eidas/eIDASAuthenticationRequest.java | 149 ++---------------- ....protocols.builder.attributes.IAttributeBuilder | 6 + ...tocols.eidas.attributes.builder.IeIDASAttribute | 6 + 16 files changed, 596 insertions(+), 183 deletions(-) create mode 100644 id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/eIDASAttributeBuilder.java create mode 100644 id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/IeIDASAttribute.java create mode 100644 id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/eIDASAttrDateOfBirth.java create mode 100644 id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/eIDASAttrFamilyName.java create mode 100644 id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/eIDASAttrGivenName.java create mode 100644 id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/eIDASAttrLegalName.java create mode 100644 id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/eIDASAttrLegalPersonIdentifier.java create mode 100644 id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/eIDASAttrNaturalPersonalIdentifier.java create mode 100644 id/server/modules/moa-id-module-eIDAS/src/main/resources/META-INF/services/at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeBuilder create mode 100644 id/server/modules/moa-id-module-eIDAS/src/main/resources/META-INF/services/at.gv.egovernment.moa.id.protocols.eidas.attributes.builder.IeIDASAttribute (limited to 'id/server/modules') diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/builder/attributes/IAttributeGenerator.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/builder/attributes/IAttributeGenerator.java index 0d51818f8..ecd67db64 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/builder/attributes/IAttributeGenerator.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/builder/attributes/IAttributeGenerator.java @@ -23,6 +23,13 @@ package at.gv.egovernment.moa.id.protocols.builder.attributes; public interface IAttributeGenerator { + /** + * + * @param friendlyName FriendlyName + * @param name Name + * @param value value + * @return + */ public abstract ATT buildStringAttribute(final String friendlyName, final String name, final String value); public abstract ATT buildIntegerAttribute(final String friendlyName, final String name, final int value); diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/Constants.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/Constants.java index eb5adcce1..36323f3a5 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/Constants.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/Constants.java @@ -22,14 +22,9 @@ */ package at.gv.egovernment.moa.id.auth.modules.eidas; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - import org.apache.xml.security.signature.XMLSignature; import org.opensaml.xml.encryption.EncryptionConstants; import org.opensaml.xml.signature.SignatureConstants; -//import eu.eidas.auth.engine.core.validator.eidas.EIDASAttributes; /** * @author tlenz @@ -93,8 +88,6 @@ public class Constants { //http endpoint descriptions public static final String eIDAS_HTTP_ENDPOINT_SP_POST = "/eidas/sp/post"; public static final String eIDAS_HTTP_ENDPOINT_SP_REDIRECT = "/eidas/sp/redirect"; - //public static final String eIDAS_HTTP_ENDPOINT_IDP_POST = "/eidas/idp/post"; - //public static final String eIDAS_HTTP_ENDPOINT_IDP_REDIRECT = "/eidas/idp/redirect"; public static final String eIDAS_HTTP_ENDPOINT_IDP_COLLEAGUEREQUEST = "/eidas/ColleagueRequest"; public static final String eIDAS_HTTP_ENDPOINT_METADATA = "/eidas/metadata"; @@ -104,44 +97,6 @@ public class Constants { public static final int eIDAS_REVERSIONSLOG_IDP_AUTHREQUEST = 3401; public static final int eIDAS_REVERSIONSLOG_IDP_AUTHRESPONSE = 3402; - //metadata constants -// public final static Map METADATA_POSSIBLE_ATTRIBUTES = Collections.unmodifiableMap( -// new HashMap(){ -// private static final long serialVersionUID = 1L; -// { -// put(EIDASAttributes.ATTRIBUTE_GIVENNAME, EidasAttributesTypes.NATURAL_PERSON_MANDATORY); -// put(EIDASAttributes.ATTRIBUTE_FIRSTNAME, EidasAttributesTypes.NATURAL_PERSON_MANDATORY); -// put(EIDASAttributes.ATTRIBUTE_DATEOFBIRTH, EidasAttributesTypes.NATURAL_PERSON_MANDATORY); -// put(EIDASAttributes.ATTRIBUTE_PERSONIDENTIFIER, EidasAttributesTypes.NATURAL_PERSON_MANDATORY); -// -// //TODO: add additional attributes for eIDAS with mandates -// //put(EIDASAttributes.ATTRIBUTE_LEGALIDENTIFIER, EidasAttributesTypes.LEGAL_PERSON_MANDATORY); -// //put(EIDASAttributes.ATTRIBUTE_LEGALNAME, EidasAttributesTypes.LEGAL_PERSON_MANDATORY); -// } -// } -// ); - - //eIDAS attributes that can be provided by MOA-ID - public static final List MOA_IDP_SUPPORTED_eIDAS_ATTRIBUTES; - static { - List supportAttrList = new ArrayList(); - //natural person attributes that can be provided by MOA-ID - supportAttrList.add(eu.eidas.auth.engine.core.eidas.spec.NaturalPersonSpec.Definitions.PERSON_IDENTIFIER.getNameUri().toString()); - supportAttrList.add(eu.eidas.auth.engine.core.eidas.spec.NaturalPersonSpec.Definitions.CURRENT_FAMILY_NAME.getNameUri().toString()); - supportAttrList.add(eu.eidas.auth.engine.core.eidas.spec.NaturalPersonSpec.Definitions.CURRENT_GIVEN_NAME.getNameUri().toString()); - supportAttrList.add(eu.eidas.auth.engine.core.eidas.spec.NaturalPersonSpec.Definitions.DATE_OF_BIRTH.getNameUri().toString()); - - //legal person attributes that can be provided by MOA-ID - supportAttrList.add(eu.eidas.auth.engine.core.eidas.spec.LegalPersonSpec.Definitions.LEGAL_PERSON_IDENTIFIER.getNameUri().toString()); - supportAttrList.add(eu.eidas.auth.engine.core.eidas.spec.LegalPersonSpec.Definitions.LEGAL_NAME.getNameUri().toString()); - - //additionl person attributes that can be provided by MOA-ID - //supportAttrList.add("http://ehn/attributes/ehealth/patientidentifier"); - - MOA_IDP_SUPPORTED_eIDAS_ATTRIBUTES = Collections.unmodifiableList(supportAttrList); - - } - public static final String METADATA_ALLOWED_ALG_DIGIST = SignatureConstants.ALGO_ID_DIGEST_SHA256 + ";" + diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAeIDASMetadataGenerator.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAeIDASMetadataGenerator.java index 1bebdebbf..9d397074b 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAeIDASMetadataGenerator.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAeIDASMetadataGenerator.java @@ -77,7 +77,6 @@ import org.slf4j.LoggerFactory; import com.google.common.collect.ImmutableSortedSet; import com.google.common.collect.Ordering; -import at.gv.egovernment.moa.id.auth.modules.eidas.Constants; import at.gv.egovernment.moa.id.protocols.pvp2x.utils.SAML2Utils; import eu.eidas.auth.commons.EIDASUtil; import eu.eidas.auth.commons.EidasStringUtil; @@ -305,8 +304,8 @@ public class MOAeIDASMetadataGenerator extends MetadataGenerator { public ImmutableSortedSet> getAllSupportedAttributes() { ImmutableSortedSet.Builder> builder = new ImmutableSortedSet.Builder<>(Ordering.>natural()); - - for (String attr : Constants.MOA_IDP_SUPPORTED_eIDAS_ATTRIBUTES) { + + for (String attr : eIDASAttributeBuilder.getAllProvideableeIDASAttributes()) { AttributeDefinition supAttr = params.getIdpEngine().getProtocolProcessor().getAttributeDefinitionNullable(attr); builder.add(supAttr); } diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/eIDASAttributeBuilder.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/eIDASAttributeBuilder.java new file mode 100644 index 000000000..1f34a912d --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/eIDASAttributeBuilder.java @@ -0,0 +1,167 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ +package at.gv.egovernment.moa.id.auth.modules.eidas.utils; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.ServiceLoader; + +import com.google.common.collect.ImmutableSet; + +import at.gv.egovernment.moa.id.commons.api.IOAAuthParameters; +import at.gv.egovernment.moa.id.data.IAuthData; +import at.gv.egovernment.moa.id.data.Pair; +import at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeBuilder; +import at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeGenerator; +import at.gv.egovernment.moa.id.protocols.eidas.attributes.builder.IeIDASAttribute; +import at.gv.egovernment.moa.id.protocols.pvp2x.builder.PVPAttributeBuilder; +import at.gv.egovernment.moa.id.protocols.pvp2x.builder.attributes.exceptions.AttributeException; +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.MiscUtil; +import eu.eidas.auth.commons.attribute.AttributeDefinition; +import eu.eidas.auth.commons.attribute.AttributeDefinition.Builder; +import eu.eidas.auth.commons.attribute.AttributeValue; +import eu.eidas.auth.commons.attribute.AttributeValueMarshaller; +import eu.eidas.auth.commons.attribute.AttributeValueMarshallingException; + +/** + * @author tlenz + * + */ +public class eIDASAttributeBuilder extends PVPAttributeBuilder { + private static IAttributeGenerator generator = new SimpleEidasAttributeGenerator(); + + private static List listOfSupportedeIDASAttributes; + private static ServiceLoader eIDASAttributLoader = + ServiceLoader.load(IeIDASAttribute.class); + + static { + List supportAttrList = new ArrayList(); + + Logger.info("Select eIDAS attributes that are corrently providable:"); + if (eIDASAttributLoader != null ) { + Iterator moduleLoaderInterator = eIDASAttributLoader.iterator(); + while (moduleLoaderInterator.hasNext()) { + try { + IeIDASAttribute modul = moduleLoaderInterator.next(); + Logger.info("Loading eIDAS attribut-builder Modul Information: " + modul.getName()); + supportAttrList.add(modul.getName()); + + } catch(Throwable e) { + Logger.error("Check configuration! " + "Some attribute-builder modul" + + " is not a valid IAttributeBuilder", e); + } + } + } + + listOfSupportedeIDASAttributes = Collections.unmodifiableList(supportAttrList); + Logger.info("Selection of providable eIDAS attributes done"); + + } + + public static List getAllProvideableeIDASAttributes() { + return listOfSupportedeIDASAttributes; + } + + /** + * + * @param attr + * @param onlineApplicationConfiguration + * @param authData + * @return + */ + public static Pair,ImmutableSet>> buildAttribute(AttributeDefinition attr, IOAAuthParameters onlineApplicationConfiguration, + IAuthData authData) { + + String attrName = attr.getNameUri().toString(); + Logger.trace("Build eIDAS attribute: "+ attrName); + + + IAttributeBuilder attrBuilder = getAttributeBuilder(attrName); + if (attrBuilder != null) { + try { + String attrValue = attrBuilder.build(onlineApplicationConfiguration, authData, generator); + if (MiscUtil.isNotEmpty(attrValue)) { + //set uniqueIdentifier attribute, because eIDAS SAMLEngine use this flag to select the + // Subject->NameID value from this attribute + Builder eIDASAttrBuilder = AttributeDefinition.builder(attr); + eIDASAttrBuilder.uniqueIdentifier(evaluateUniqueID(attrName, authData.isUseMandate())); + AttributeDefinition returnAttr = eIDASAttrBuilder.build(); + + //unmarshal attribute value into eIDAS attribute + AttributeValueMarshaller attributeValueMarshaller = returnAttr.getAttributeValueMarshaller(); + ImmutableSet.Builder> builder = ImmutableSet.builder(); + + AttributeValue attributeValue = null; + try { + attributeValue = attributeValueMarshaller.unmarshal(attrValue, false); + builder.add(attributeValue); + + } catch (AttributeValueMarshallingException e) { + throw new IllegalStateException(e); + + } + + return Pair.newInstance(returnAttr, builder.build()); + + } + + } catch (AttributeException e) { + Logger.debug("Attribute can not generate requested attribute:" + attr.getNameUri().toString() + " Reason:" + e.getMessage()); + + } + + } else + Logger.warn("NO attribute builder FOUND for eIDAS attr: " + attrName); + + return null; + } + + /** + * This method use the information from authenticated session and + * evaluate the uniqueID flag according to eIDAS specification + * + * @param attrName eIDAS attribute name that is evaluated + * @param useMandate flag that indicates if the current authenticated session includes a mandate + * @return true if eIDAS attribute holds the unique ID, otherwise false + */ + private static boolean evaluateUniqueID(String attrName, boolean useMandate) { + //if no mandate is used the natural person identifier is the unique ID + if (!useMandate && + attrName.equals(eu.eidas.auth.engine.core.eidas.spec.NaturalPersonSpec.Definitions.PERSON_IDENTIFIER.getNameUri().toString())) + return true; + + //if mandates are used the the legal person identifier or the natural person identifier of the mandator is the unique ID + else if (useMandate && + attrName.equals(eu.eidas.auth.engine.core.eidas.spec.LegalPersonSpec.Definitions.LEGAL_PERSON_IDENTIFIER.getNameUri().toString())) + return true; + + //TODO: implement flag selector for mandates and natural persons + + + return false; + } + +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EIDASData.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EIDASData.java index 7647b4cab..694efab80 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EIDASData.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EIDASData.java @@ -15,6 +15,8 @@ import eu.eidas.auth.commons.protocol.IAuthenticationRequest; @Scope(value = BeanDefinition.SCOPE_PROTOTYPE) public class EIDASData extends RequestImpl { + public static final String REQ_PARAM_eIDAS_AUTHN_TRANSIENT_ID = "transiendIDRequested"; + /** The Constant serialVersionUID. */ private static final long serialVersionUID = 8765755670214923910L; @@ -28,7 +30,7 @@ public class EIDASData extends RequestImpl { private String remoteIPAddress; private String remoteRelayState; - + @Override public Collection getRequestedAttributes(MetadataProvider metadataProvider) { // TODO Auto-generated method stub diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EIDASProtocol.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EIDASProtocol.java index 388d65963..5d13e26e2 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EIDASProtocol.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EIDASProtocol.java @@ -67,6 +67,7 @@ import eu.eidas.auth.commons.protocol.eidas.IEidasAuthenticationRequest; import eu.eidas.auth.commons.protocol.eidas.impl.EidasAuthenticationRequest; import eu.eidas.auth.commons.protocol.impl.AuthenticationResponse; import eu.eidas.auth.commons.protocol.impl.AuthenticationResponse.Builder; +import eu.eidas.auth.commons.protocol.impl.SamlNameIdFormat; import eu.eidas.auth.engine.ProtocolEngineI; import eu.eidas.auth.engine.metadata.MetadataUtil; import eu.eidas.engine.exceptions.EIDASSAMLEngineException; @@ -307,6 +308,13 @@ public class EIDASProtocol extends AbstractAuthProtocolModulController { pendingReq.setGenericDataToSession(RequestImpl.eIDAS_GENERIC_REQ_DATA_LEVELOFASSURENCE, eIDASSamlReq.getEidasLevelOfAssurance().stringValue()); + //set flag if transiend identifier is requested + if (MiscUtil.isNotEmpty(eIDASSamlReq.getNameIdFormat()) + && eIDASSamlReq.getNameIdFormat().equals(SamlNameIdFormat.TRANSIENT.getNameIdFormat())) + pendingReq.setGenericDataToSession(EIDASData.REQ_PARAM_eIDAS_AUTHN_TRANSIENT_ID, true); + else + pendingReq.setGenericDataToSession(EIDASData.REQ_PARAM_eIDAS_AUTHN_TRANSIENT_ID, false); + // - memorize requested attributes pendingReq.setEidasRequestedAttributes(eIDASSamlReq.getRequestedAttributes()); diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/IeIDASAttribute.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/IeIDASAttribute.java new file mode 100644 index 000000000..15060fb52 --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/IeIDASAttribute.java @@ -0,0 +1,33 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ +package at.gv.egovernment.moa.id.protocols.eidas.attributes.builder; + +import at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeBuilder; + +/** + * @author tlenz + * + */ +public interface IeIDASAttribute extends IAttributeBuilder{ + +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/eIDASAttrDateOfBirth.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/eIDASAttrDateOfBirth.java new file mode 100644 index 000000000..64e5ae770 --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/eIDASAttrDateOfBirth.java @@ -0,0 +1,37 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ +package at.gv.egovernment.moa.id.protocols.eidas.attributes.builder; + +import at.gv.egovernment.moa.id.protocols.builder.attributes.BirthdateAttributeBuilder; + +/** + * @author tlenz + * + */ +public class eIDASAttrDateOfBirth extends BirthdateAttributeBuilder implements IeIDASAttribute { + + @Override + public String getName() { + return eu.eidas.auth.engine.core.eidas.spec.NaturalPersonSpec.Definitions.DATE_OF_BIRTH.getNameUri().toString(); + } +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/eIDASAttrFamilyName.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/eIDASAttrFamilyName.java new file mode 100644 index 000000000..4195eeeef --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/eIDASAttrFamilyName.java @@ -0,0 +1,61 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ +package at.gv.egovernment.moa.id.protocols.eidas.attributes.builder; + +import at.gv.egovernment.moa.id.commons.api.IOAAuthParameters; +import at.gv.egovernment.moa.id.data.IAuthData; +import at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeGenerator; +import at.gv.egovernment.moa.id.protocols.pvp2x.builder.attributes.exceptions.AttributeException; + +/** + * @author tlenz + * + */ +public class eIDASAttrFamilyName implements IeIDASAttribute{ + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeBuilder#getName() + */ + @Override + public String getName() { + return eu.eidas.auth.engine.core.eidas.spec.NaturalPersonSpec.Definitions.CURRENT_FAMILY_NAME.getNameUri().toString(); + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeBuilder#build(at.gv.egovernment.moa.id.commons.api.IOAAuthParameters, at.gv.egovernment.moa.id.data.IAuthData, at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeGenerator) + */ + @Override + public ATT build(IOAAuthParameters oaParam, IAuthData authData, IAttributeGenerator g) + throws AttributeException { + return g.buildStringAttribute(null, getName(), authData.getFamilyName()); + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeBuilder#buildEmpty(at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeGenerator) + */ + @Override + public ATT buildEmpty(IAttributeGenerator g) { + return null; + } + +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/eIDASAttrGivenName.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/eIDASAttrGivenName.java new file mode 100644 index 000000000..2a654ac44 --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/eIDASAttrGivenName.java @@ -0,0 +1,61 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ +package at.gv.egovernment.moa.id.protocols.eidas.attributes.builder; + +import at.gv.egovernment.moa.id.commons.api.IOAAuthParameters; +import at.gv.egovernment.moa.id.data.IAuthData; +import at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeGenerator; +import at.gv.egovernment.moa.id.protocols.pvp2x.builder.attributes.exceptions.AttributeException; + +/** + * @author tlenz + * + */ +public class eIDASAttrGivenName implements IeIDASAttribute{ + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeBuilder#getName() + */ + @Override + public String getName() { + return eu.eidas.auth.engine.core.eidas.spec.NaturalPersonSpec.Definitions.CURRENT_GIVEN_NAME.getNameUri().toString(); + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeBuilder#build(at.gv.egovernment.moa.id.commons.api.IOAAuthParameters, at.gv.egovernment.moa.id.data.IAuthData, at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeGenerator) + */ + @Override + public ATT build(IOAAuthParameters oaParam, IAuthData authData, IAttributeGenerator g) + throws AttributeException { + return g.buildStringAttribute(null, getName(), authData.getGivenName()); + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeBuilder#buildEmpty(at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeGenerator) + */ + @Override + public ATT buildEmpty(IAttributeGenerator g) { + return null; + } + +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/eIDASAttrLegalName.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/eIDASAttrLegalName.java new file mode 100644 index 000000000..51a2bd69b --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/eIDASAttrLegalName.java @@ -0,0 +1,37 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ +package at.gv.egovernment.moa.id.protocols.eidas.attributes.builder; + +import at.gv.egovernment.moa.id.protocols.builder.attributes.MandateLegalPersonFullNameAttributeBuilder; + +/** + * @author tlenz + * + */ +public class eIDASAttrLegalName extends MandateLegalPersonFullNameAttributeBuilder implements IeIDASAttribute { + + @Override + public String getName() { + return eu.eidas.auth.engine.core.eidas.spec.LegalPersonSpec.Definitions.LEGAL_NAME.getNameUri().toString(); + } +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/eIDASAttrLegalPersonIdentifier.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/eIDASAttrLegalPersonIdentifier.java new file mode 100644 index 000000000..c008048cb --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/eIDASAttrLegalPersonIdentifier.java @@ -0,0 +1,37 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ +package at.gv.egovernment.moa.id.protocols.eidas.attributes.builder; + +import at.gv.egovernment.moa.id.protocols.builder.attributes.MandateLegalPersonSourcePinAttributeBuilder; + +/** + * @author tlenz + * + */ +public class eIDASAttrLegalPersonIdentifier extends MandateLegalPersonSourcePinAttributeBuilder implements IeIDASAttribute { + + @Override + public String getName() { + return eu.eidas.auth.engine.core.eidas.spec.LegalPersonSpec.Definitions.LEGAL_PERSON_IDENTIFIER.getNameUri().toString(); + } +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/eIDASAttrNaturalPersonalIdentifier.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/eIDASAttrNaturalPersonalIdentifier.java new file mode 100644 index 000000000..cb659c2b1 --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/attributes/builder/eIDASAttrNaturalPersonalIdentifier.java @@ -0,0 +1,116 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ +package at.gv.egovernment.moa.id.protocols.eidas.attributes.builder; + +import java.security.MessageDigest; + +import at.gv.egovernment.moa.id.auth.modules.eidas.utils.eIDASAttributeProcessingUtils; +import at.gv.egovernment.moa.id.commons.api.IOAAuthParameters; +import at.gv.egovernment.moa.id.data.IAuthData; +import at.gv.egovernment.moa.id.data.Trible; +import at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeGenerator; +import at.gv.egovernment.moa.id.protocols.eidas.EIDASData; +import at.gv.egovernment.moa.id.protocols.pvp2x.builder.attributes.exceptions.AttributeException; +import at.gv.egovernment.moa.id.util.Random; +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.Base64Utils; +import at.gv.egovernment.moa.util.MiscUtil; + +/** + * @author tlenz + * + */ +public class eIDASAttrNaturalPersonalIdentifier implements IeIDASAttribute{ + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeBuilder#getName() + */ + @Override + public String getName() { + return eu.eidas.auth.engine.core.eidas.spec.NaturalPersonSpec.Definitions.PERSON_IDENTIFIER.getNameUri().toString(); + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeBuilder#build(at.gv.egovernment.moa.id.commons.api.IOAAuthParameters, at.gv.egovernment.moa.id.data.IAuthData, at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeGenerator) + */ + @Override + public ATT build(IOAAuthParameters oaParam, IAuthData authData, IAttributeGenerator g) + throws AttributeException { + String personalID = authData.getBPK(); + + //generate eIDAS conform 'PersonalIdentifier' attribute + if (!eIDASAttributeProcessingUtils.validateEidasPersonalIdentifier(personalID)) { + Logger.debug("preCalculated PersonalIdentifier does not include eIDAS conform prefixes ... add prefix now"); + if (MiscUtil.isEmpty(authData.getBPKType()) + || !authData.getBPKType().startsWith(at.gv.egovernment.moa.util.Constants.URN_PREFIX_EIDAS)) { + Logger.error("BPKType is empty or does not start with eIDAS bPKType prefix! bPKType:" + authData.getBPKType()); + throw new AttributeException("Suspect bPKType for eIDAS identifier generation"); + + } + + String prefix = authData.getBPKType().substring(at.gv.egovernment.moa.util.Constants.URN_PREFIX_EIDAS.length() + 1); + personalID = prefix.replaceAll("\\+", "/") + "/" + personalID; + + } + + //generate a transient unique identifier if it is requested + Boolean isTransiendIDRequested = + authData.getGenericData(EIDASData.REQ_PARAM_eIDAS_AUTHN_TRANSIENT_ID, Boolean.class); + if (isTransiendIDRequested != null && isTransiendIDRequested) + personalID = generateTransientNameID(personalID); + + return g.buildStringAttribute(null, getName(), personalID); + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeBuilder#buildEmpty(at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeGenerator) + */ + @Override + public ATT buildEmpty(IAttributeGenerator g) { + return null; + } + + private String generateTransientNameID(String nameID) { + //extract source-country and destination country from persistent identifier + Trible split = eIDASAttributeProcessingUtils.parseEidasPersonalIdentifier(nameID); + if (split == null) { + Logger.error("eIDAS 'PersonalIdentifier' has a wrong format. There had to be a ERROR in implementation!!!!"); + throw new IllegalStateException("eIDAS 'PersonalIdentifier' has a wrong format. There had to be a ERROR in implementation!!!!"); + + } + + //build correct formated transient identifier + String random = Random.nextLongRandom(); + try { + MessageDigest md = MessageDigest.getInstance("SHA-1"); + byte[] hash = md.digest((split.getThird() + random).getBytes("ISO-8859-1")); + return split.getFirst() + "/" + split.getSecond() + "/" + Base64Utils.encode(hash); + + } catch (Exception e) { + Logger.error("Can not generate transient personal identifier!", e); + return null; + + } + + } +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/eIDASAuthenticationRequest.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/eIDASAuthenticationRequest.java index 2fe52bb4f..d0cda38c7 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/eIDASAuthenticationRequest.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/eIDASAuthenticationRequest.java @@ -23,8 +23,6 @@ package at.gv.egovernment.moa.id.protocols.eidas; import java.io.StringWriter; -import java.security.MessageDigest; -import java.text.SimpleDateFormat; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -43,33 +41,23 @@ import at.gv.egovernment.moa.id.auth.frontend.velocity.VelocityProvider; import at.gv.egovernment.moa.id.auth.modules.eidas.Constants; import at.gv.egovernment.moa.id.auth.modules.eidas.engine.MOAeIDASChainingMetadataProvider; import at.gv.egovernment.moa.id.auth.modules.eidas.utils.SimpleEidasAttributeGenerator; -import at.gv.egovernment.moa.id.auth.modules.eidas.utils.eIDASAttributeProcessingUtils; +import at.gv.egovernment.moa.id.auth.modules.eidas.utils.eIDASAttributeBuilder; import at.gv.egovernment.moa.id.commons.MOAIDConstants; import at.gv.egovernment.moa.id.commons.api.IRequest; import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException; import at.gv.egovernment.moa.id.data.IAuthData; +import at.gv.egovernment.moa.id.data.Pair; import at.gv.egovernment.moa.id.data.SLOInformationImpl; import at.gv.egovernment.moa.id.data.SLOInformationInterface; -import at.gv.egovernment.moa.id.data.Trible; import at.gv.egovernment.moa.id.moduls.IAction; import at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeGenerator; -import at.gv.egovernment.moa.id.protocols.builder.attributes.MandateLegalPersonFullNameAttributeBuilder; -import at.gv.egovernment.moa.id.protocols.builder.attributes.MandateLegalPersonSourcePinAttributeBuilder; -import at.gv.egovernment.moa.id.protocols.pvp2x.builder.attributes.exceptions.AttributeException; -import at.gv.egovernment.moa.id.util.Random; import at.gv.egovernment.moa.logging.Logger; -import at.gv.egovernment.moa.util.Base64Utils; -import at.gv.egovernment.moa.util.MiscUtil; import eu.eidas.auth.commons.EidasStringUtil; import eu.eidas.auth.commons.attribute.AttributeDefinition; -import eu.eidas.auth.commons.attribute.AttributeDefinition.Builder; import eu.eidas.auth.commons.attribute.AttributeValue; -import eu.eidas.auth.commons.attribute.AttributeValueMarshaller; -import eu.eidas.auth.commons.attribute.AttributeValueMarshallingException; import eu.eidas.auth.commons.attribute.ImmutableAttributeMap; import eu.eidas.auth.commons.protocol.IResponseMessage; import eu.eidas.auth.commons.protocol.impl.AuthenticationResponse; -import eu.eidas.auth.commons.protocol.impl.SamlNameIdFormat; import eu.eidas.auth.engine.ProtocolEngineI; import eu.eidas.auth.engine.xml.opensaml.SAMLEngineUtils; @@ -97,104 +85,31 @@ public class eIDASAuthenticationRequest implements IAction { else throw new MOAIDException("got wrong IRequest type. is: {}, should be: {}", new String[] {req.getClass().toString(), EIDASData.class.toString()}); - + String subjectNameID = null; - + //gather attributes ImmutableAttributeMap reqAttributeList = (ImmutableAttributeMap) eidasRequest.getEidasRequestedAttributes(); ImmutableAttributeMap.Builder attrMapBuilder = ImmutableAttributeMap.builder(); - - //TODO: if we support more then this minimum required attributes -> redesign to a smoother attribute builder selector + + //generate eIDAS attributes for(AttributeDefinition attr : reqAttributeList.getDefinitions()) { - String newValue = ""; - boolean isUniqueID = false; - try { - switch(attr.getFriendlyName()) { - case Constants.eIDAS_ATTR_DATEOFBIRTH: - newValue = new SimpleDateFormat("YYYY-MM-dd").format(authData.getDateOfBirth()); - break; - case Constants.eIDAS_ATTR_CURRENTFAMILYNAME: - newValue = authData.getFamilyName(); - break; - case Constants.eIDAS_ATTR_CURRENTGIVENNAME: - newValue = authData.getGivenName(); - break; - case Constants.eIDAS_ATTR_PERSONALIDENTIFIER: - newValue = authData.getBPK(); - isUniqueID = true; + Pair, ImmutableSet>> eIDASAttr = eIDASAttributeBuilder.buildAttribute( + attr, req.getOnlineApplicationConfiguration(), authData); - //generate eIDAS conform 'PersonalIdentifier' attribute - if (!eIDASAttributeProcessingUtils.validateEidasPersonalIdentifier(newValue)) { - Logger.debug("preCalculated PersonalIdentifier does not include eIDAS conform prefixes ... add prefix now"); - if (MiscUtil.isEmpty(authData.getBPKType()) - || !authData.getBPKType().startsWith(at.gv.egovernment.moa.util.Constants.URN_PREFIX_EIDAS)) { - Logger.error("BPKType is empty or does not start with eIDAS bPKType prefix! bPKType:" + authData.getBPKType()); - throw new MOAIDException("builder.08", new Object[]{"Suspect bPKType for eIDAS identifier generation"}); - - } - - String prefix = authData.getBPKType().substring(at.gv.egovernment.moa.util.Constants.URN_PREFIX_EIDAS.length() + 1); - newValue = prefix.replaceAll("\\+", "/") + "/" + newValue; - - } - - //generate a transient unique identifier if it is requested - String reqNameIDFormat = eidasRequest.getEidasRequest().getNameIdFormat(); - if (MiscUtil.isNotEmpty(reqNameIDFormat) - && reqNameIDFormat.equals(SamlNameIdFormat.TRANSIENT.getNameIdFormat())) - newValue = generateTransientNameID(newValue); - - - subjectNameID = newValue; - break; - case Constants.eIDAS_ATTR_LEGALPERSONIDENTIFIER: - newValue = new MandateLegalPersonSourcePinAttributeBuilder().build( - req.getOnlineApplicationConfiguration(), authData, generator); - break; - case Constants.eIDAS_ATTR_LEGALNAME: - newValue = new MandateLegalPersonFullNameAttributeBuilder().build( - req.getOnlineApplicationConfiguration(), authData, generator); - break; - - } - - } catch (AttributeException e) { - Logger.debug("Attribute can not generate requested attribute:" + attr.getFriendlyName() + " Reason:" + e.getMessage()); - - } - - if(MiscUtil.isEmpty(newValue)) { + if(eIDASAttr == null) { if (attr.isRequired()) { Logger.info("eIDAS Attr:" + attr.getNameUri() + " is marked as 'Required' but not available."); throw new MOAIDException("eIDAS.15", new Object[]{attr.getFriendlyName()}); } else Logger.info("eIDAS Attr:" + attr.getNameUri() + " is not available."); - } else { - //set uniqueIdentifier attribute, because eIDAS SAMLEngine use this flag to select the - // Subject->NameID value from this attribute - Builder attrBuilder = AttributeDefinition.builder(attr); - attrBuilder.uniqueIdentifier(isUniqueID); - AttributeDefinition returnAttr = attrBuilder.build(); - - //unmarshal attribute value into eIDAS attribute - AttributeValueMarshaller attributeValueMarshaller = returnAttr.getAttributeValueMarshaller(); - ImmutableSet.Builder> builder = ImmutableSet.builder(); - - AttributeValue attributeValue = null; - try { - attributeValue = attributeValueMarshaller.unmarshal(newValue, false); - builder.add(attributeValue); - - } catch (AttributeValueMarshallingException e) { - throw new IllegalStateException(e); - - } - - //add attribute to Map - attrMapBuilder.put((AttributeDefinition)returnAttr, (ImmutableSet) builder.build()); + //add attribute to Map + attrMapBuilder.put( + (AttributeDefinition)eIDASAttr.getFirst(), + (ImmutableSet)eIDASAttr.getSecond()); } } @@ -231,19 +146,7 @@ public class eIDASAuthenticationRequest implements IAction { eIDASRespMsg = engine.generateResponseMessage(eidasRequest.getEidasRequest(), response, true, eidasRequest.getRemoteAddress()); - -// if(null == eidasRequest.getEidasRequest().getAssertionConsumerServiceURL()) { -// String assertionConsumerUrl = MetadataUtil.getAssertionUrlFromMetadata( -// new MOAeIDASMetadataProviderDecorator(eIDASMetadataProvider), -// engine, -// eidasRequest.getEidasRequest()); -// eidasRequest.getEidasRequest().setAssertionConsumerServiceURL(assertionConsumerUrl); -// -// } - -// response = engine.generateEIDASAuthnResponse(eidasRequest.getEidasRequest(), response, eidasRequest.getRemoteAddress(), true); - - + token = EidasStringUtil.encodeToBase64(eIDASRespMsg.getMessageBytes()); } catch(Exception e) { @@ -319,28 +222,6 @@ public class eIDASAuthenticationRequest implements IAction { } - private String generateTransientNameID(String nameID) { - //extract source-country and destination country from persistent identifier - Trible split = eIDASAttributeProcessingUtils.parseEidasPersonalIdentifier(nameID); - if (split == null) { - Logger.error("eIDAS 'PersonalIdentifier' has a wrong format. There had to be a ERROR in implementation!!!!"); - throw new IllegalStateException("eIDAS 'PersonalIdentifier' has a wrong format. There had to be a ERROR in implementation!!!!"); - - } - - //build correct formated transient identifier - String random = Random.nextLongRandom(); - try { - MessageDigest md = MessageDigest.getInstance("SHA-1"); - byte[] hash = md.digest((split.getThird() + random).getBytes("ISO-8859-1")); - return split.getFirst() + "/" + split.getSecond() + "/" + Base64Utils.encode(hash); - - } catch (Exception e) { - Logger.error("Can not generate transient personal identifier!", e); - return null; - - } - - } + } diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/resources/META-INF/services/at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeBuilder b/id/server/modules/moa-id-module-eIDAS/src/main/resources/META-INF/services/at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeBuilder new file mode 100644 index 000000000..62e7c20ab --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/resources/META-INF/services/at.gv.egovernment.moa.id.protocols.builder.attributes.IAttributeBuilder @@ -0,0 +1,6 @@ +at.gv.egovernment.moa.id.protocols.eidas.attributes.builder.eIDASAttrDateOfBirth +at.gv.egovernment.moa.id.protocols.eidas.attributes.builder.eIDASAttrFamilyName +at.gv.egovernment.moa.id.protocols.eidas.attributes.builder.eIDASAttrGivenName +at.gv.egovernment.moa.id.protocols.eidas.attributes.builder.eIDASAttrNaturalPersonalIdentifier +at.gv.egovernment.moa.id.protocols.eidas.attributes.builder.eIDASAttrLegalPersonIdentifier +at.gv.egovernment.moa.id.protocols.eidas.attributes.builder.eIDASAttrLegalName diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/resources/META-INF/services/at.gv.egovernment.moa.id.protocols.eidas.attributes.builder.IeIDASAttribute b/id/server/modules/moa-id-module-eIDAS/src/main/resources/META-INF/services/at.gv.egovernment.moa.id.protocols.eidas.attributes.builder.IeIDASAttribute new file mode 100644 index 000000000..62e7c20ab --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/resources/META-INF/services/at.gv.egovernment.moa.id.protocols.eidas.attributes.builder.IeIDASAttribute @@ -0,0 +1,6 @@ +at.gv.egovernment.moa.id.protocols.eidas.attributes.builder.eIDASAttrDateOfBirth +at.gv.egovernment.moa.id.protocols.eidas.attributes.builder.eIDASAttrFamilyName +at.gv.egovernment.moa.id.protocols.eidas.attributes.builder.eIDASAttrGivenName +at.gv.egovernment.moa.id.protocols.eidas.attributes.builder.eIDASAttrNaturalPersonalIdentifier +at.gv.egovernment.moa.id.protocols.eidas.attributes.builder.eIDASAttrLegalPersonIdentifier +at.gv.egovernment.moa.id.protocols.eidas.attributes.builder.eIDASAttrLegalName -- cgit v1.2.3 From 44184c19d53146dcd84e2ddd704ff78aa539d511 Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Thu, 23 Feb 2017 08:13:11 +0100 Subject: update eIDAS SP metadata, because SP needs persistent identifiers only --- .../modules/eidas/utils/MOAeIDASMetadataGenerator.java | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'id/server/modules') diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAeIDASMetadataGenerator.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAeIDASMetadataGenerator.java index 9d397074b..7b159c73d 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAeIDASMetadataGenerator.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAeIDASMetadataGenerator.java @@ -208,7 +208,12 @@ public class MOAeIDASMetadataGenerator extends MetadataGenerator { if (!StringUtils.isEmpty(params.getAssertionConsumerUrl())) { addAssertionConsumerService(); } - fillNameIDFormat(spSSODescriptor); + + //FIX: Austrian eIDAS node SP only needs persistent identifiers + NameIDFormat persistentFormat = + (NameIDFormat) BuilderFactoryUtil.buildXmlObject(NameIDFormat.DEFAULT_ELEMENT_NAME); + persistentFormat.setFormat(SamlNameIdFormat.PERSISTENT.getNameIdFormat()); + spSSODescriptor.getNameIDFormats().add(persistentFormat); /**FIXME: * Double signing of SPSSODescribtor is not required @@ -221,8 +226,8 @@ public class MOAeIDASMetadataGenerator extends MetadataGenerator { entityDescriptor.getRoleDescriptors().add(spSSODescriptor); } - - private void fillNameIDFormat(SSODescriptor ssoDescriptor) throws EIDASSAMLEngineException { + + private void fillIDPNameIDFormat(SSODescriptor ssoDescriptor) throws EIDASSAMLEngineException { NameIDFormat persistentFormat = (NameIDFormat) BuilderFactoryUtil.buildXmlObject(NameIDFormat.DEFAULT_ELEMENT_NAME); persistentFormat.setFormat(SamlNameIdFormat.PERSISTENT.getNameIdFormat()); @@ -269,7 +274,9 @@ public class MOAeIDASMetadataGenerator extends MetadataGenerator { .add(getKeyDescriptor(keyInfoGeneratorFactory, params.getEncryptionCredential(), UsageType.ENCRYPTION)); } idpSSODescriptor.addSupportedProtocol(params.getIdpSamlProtocol()); - fillNameIDFormat(idpSSODescriptor); + + //Austrian eIDAS node IDP can provided persistent, transient, and unspecified identifiers + fillIDPNameIDFormat(idpSSODescriptor); if (params.getIdpEngine() != null) { @@ -298,7 +305,7 @@ public class MOAeIDASMetadataGenerator extends MetadataGenerator { } - /*TODO: Only a work-around to add eIDAS attributes, which could be provided from MOA-ID, to IDP metadata + /* FIX: Work-around to add eIDAS attributes, which could be provided from MOA-ID, to IDP metadata * If we restrict the eIDAS Engine attribute definitions then also additional incoming attributes can not processed any more. */ public ImmutableSortedSet> getAllSupportedAttributes() { -- cgit v1.2.3 From 322d191c02df1c1d4bdabe141e9cdc61acc9f015 Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Thu, 23 Feb 2017 08:13:35 +0100 Subject: add some javadoc information --- .../auth/modules/eidas/utils/eIDASAttributeBuilder.java | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'id/server/modules') diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/eIDASAttributeBuilder.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/eIDASAttributeBuilder.java index 1f34a912d..22b94178e 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/eIDASAttributeBuilder.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/eIDASAttributeBuilder.java @@ -81,16 +81,23 @@ public class eIDASAttributeBuilder extends PVPAttributeBuilder { } + /** + * Get all eIDAS attribute names that can be generated by the Austrian eIDAS node. + * This list is dynamically generated from loaded eIDAS attribute builders that are found in Java Classpath + * + * @return {@link List} of {@link String} of eIDAS attribute names + */ public static List getAllProvideableeIDASAttributes() { return listOfSupportedeIDASAttributes; } /** - * - * @param attr - * @param onlineApplicationConfiguration - * @param authData - * @return + * This method build an eIDAS response attribute, by using a loaded eIDAS attribute builder. + * + * @param attr eIDAS attribute that should be generated + * @param onlineApplicationConfiguration SP configuration + * @param authData Authentication data that contains user information for attribute generation + * @return eIDAS attribute response {@link Pair} or null if the attribute generation FAILES */ public static Pair,ImmutableSet>> buildAttribute(AttributeDefinition attr, IOAAuthParameters onlineApplicationConfiguration, IAuthData authData) { -- cgit v1.2.3 From 507fd437fcdd24ec9ce36680915e58643e3a6a8d Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Tue, 28 Mar 2017 10:34:55 +0200 Subject: update MOA eIDAS-Engine to reload eIDAS metadata if request or response validation are not success at first check. This update makes a key role-over easier for signing and encryption. --- .../eidas/engine/MOAEidasProtocolProcesser.java | 8 +- .../modules/eidas/engine/MOAProtocolEngine.java | 105 +++++++++++++++++++-- .../engine/MOAeIDASChainingMetadataProvider.java | 3 +- .../engine/MOAeIDASMetadataProviderDecorator.java | 18 ++++ .../eidas/utils/MOAProtocolEngineFactory.java | 50 ++++++---- .../auth/modules/eidas/utils/SAMLEngineUtils.java | 2 +- 6 files changed, 160 insertions(+), 26 deletions(-) (limited to 'id/server/modules') diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAEidasProtocolProcesser.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAEidasProtocolProcesser.java index 8abf29703..28d74075e 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAEidasProtocolProcesser.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAEidasProtocolProcesser.java @@ -58,5 +58,11 @@ public class MOAEidasProtocolProcesser extends EidasProtocolProcessor { public String getResponseValidatorId() { return OWN_EIDAS_RESPONSE_VALIDATOR_SUITE_ID; } - + + + public MetadataFetcherI getMetadataFetcher() { + return this.metadataFetcher; + } + + } diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAProtocolEngine.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAProtocolEngine.java index d8fcd1694..f347022b8 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAProtocolEngine.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAProtocolEngine.java @@ -1,16 +1,17 @@ package at.gv.egovernment.moa.id.auth.modules.eidas.engine; -import java.security.cert.X509Certificate; - -import org.apache.commons.lang3.StringUtils; +import org.opensaml.saml2.core.AuthnRequest; import org.opensaml.saml2.core.Response; +import org.w3c.dom.Document; import at.gv.egovernment.moa.logging.Logger; -import eu.eidas.auth.commons.EidasErrorKey; -import eu.eidas.auth.commons.protocol.IAuthenticationRequest; +import at.gv.egovernment.moa.util.MiscUtil; +import eu.eidas.auth.engine.Correlated; import eu.eidas.auth.engine.ProtocolEngine; import eu.eidas.auth.engine.configuration.ProtocolConfigurationAccessor; -import eu.eidas.auth.engine.xml.opensaml.SAMLEngineUtils; +import eu.eidas.auth.engine.core.ProtocolProcessorI; +import eu.eidas.auth.engine.metadata.MetadataFetcherI; +import eu.eidas.auth.engine.xml.opensaml.XmlSchemaUtil; import eu.eidas.engine.exceptions.EIDASSAMLEngineException; public class MOAProtocolEngine extends ProtocolEngine { @@ -20,6 +21,98 @@ public class MOAProtocolEngine extends ProtocolEngine { } + /** + * Add SAML2 metadata refresh functionality if first validation failed + * + */ + @Override + public Correlated unmarshallResponse(byte[] responseBytes) throws EIDASSAMLEngineException { + try { + return super.unmarshallResponse(responseBytes); + + } catch (EIDASSAMLEngineException e) { + if (responseBytes != null ) { + Logger.info("eIDAS Response validation FAILED. Starting metadata reloading process ..."); + Document document = XmlSchemaUtil.validateSamlSchema(responseBytes); + Response response = (Response) unmarshall(document); + String entityID = response.getIssuer().getValue(); + + if (MiscUtil.isEmpty(entityID)) { + Logger.debug("eIDAS Response contains no EntityID."); + throw e; + + } + + if (startInternalMetadataRefesh(entityID)) { + Logger.debug("Metadata refresh success. Revalidate eIDAS Response ..."); + return super.unmarshallResponse(responseBytes); + + } + Logger.info("eIDAS metadata refresh not possible or not successful."); + + } + throw e; + + } + } + + /** + * Add SAML2 metadata refresh functionality if first validation failed + * + */ + @Override + public AuthnRequest unmarshallRequest(byte[] requestBytes) throws EIDASSAMLEngineException { + try { + return super.unmarshallRequest(requestBytes); + + + } catch (EIDASSAMLEngineException e) { + if (null != requestBytes) { + Logger.info("eIDAS Request validation FAILED. Starting metadata reloading process ..."); + Document document = XmlSchemaUtil.validateSamlSchema(requestBytes); + AuthnRequest request = (AuthnRequest) unmarshall(document); + String entityID = request.getIssuer().getValue(); + + if (MiscUtil.isEmpty(entityID)) { + Logger.debug("eIDAS Authn. Request contains no EntityID."); + throw e; + + } + + if (startInternalMetadataRefesh(entityID)) { + Logger.debug("Metadata refresh success. Revalidate eIDAS Authn. Request ..."); + return super.unmarshallRequest(requestBytes); + + } + + Logger.info("eIDAS metadata refresh not possible or not successful."); + } + + throw e; + + } + } + + /** + * Refresh SAML2 metadata if the internal metadata provider supports this functionality + * + * @param entityID + * @return true if refresh was success, otherwise false + */ + private boolean startInternalMetadataRefesh(String entityID) { + //check if eIDAS SAML-Engine implementation supports metadata refresh + ProtocolProcessorI protocolProcessor = this.getProtocolProcessor(); + if (protocolProcessor instanceof MOAEidasProtocolProcesser) { + MetadataFetcherI metadataFetcher = + ((MOAEidasProtocolProcesser)protocolProcessor).getMetadataFetcher(); + if (metadataFetcher instanceof MOAeIDASMetadataProviderDecorator) + return ((MOAeIDASMetadataProviderDecorator)metadataFetcher).refreshMetadata(entityID); + + } + + return false; + } + // @Override // protected X509Certificate getEncryptionCertificate(String requestIssuer, // String destinationCountryCode) throws EIDASSAMLEngineException { diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAeIDASChainingMetadataProvider.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAeIDASChainingMetadataProvider.java index ffa74b92b..75d57e615 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAeIDASChainingMetadataProvider.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAeIDASChainingMetadataProvider.java @@ -35,6 +35,7 @@ import at.gv.egovernment.moa.id.commons.utils.MOAHttpProtocolSocketFactory; import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.filter.SchemaValidationException; import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.filter.SignatureValidationException; +import at.gv.egovernment.moa.id.protocols.pvp2x.metadata.IMOARefreshableMetadataProvider; import at.gv.egovernment.moa.id.protocols.pvp2x.verification.metadata.MOASPMetadataSignatureFilter; import at.gv.egovernment.moa.id.saml2.MetadataFilterChain; import at.gv.egovernment.moa.logging.Logger; @@ -43,7 +44,7 @@ import eu.eidas.auth.engine.AbstractProtocolEngine; @Service("eIDASMetadataProvider") public class MOAeIDASChainingMetadataProvider implements ObservableMetadataProvider, - IGarbageCollectorProcessing, IDestroyableObject { + IGarbageCollectorProcessing, IDestroyableObject, IMOARefreshableMetadataProvider { // private static MOAeIDASChainingMetadataProvider instance = null; private static Object mutex = new Object(); diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAeIDASMetadataProviderDecorator.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAeIDASMetadataProviderDecorator.java index c5e56502b..9adc221e5 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAeIDASMetadataProviderDecorator.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAeIDASMetadataProviderDecorator.java @@ -31,6 +31,7 @@ import org.opensaml.saml2.metadata.SPSSODescriptor; import org.opensaml.saml2.metadata.provider.MetadataProvider; import org.opensaml.saml2.metadata.provider.MetadataProviderException; +import at.gv.egovernment.moa.id.protocols.pvp2x.metadata.IMOARefreshableMetadataProvider; import eu.eidas.auth.engine.ProtocolEngineI; import eu.eidas.auth.engine.metadata.MetadataFetcherI; import eu.eidas.auth.engine.metadata.MetadataSignerI; @@ -54,6 +55,23 @@ public class MOAeIDASMetadataProviderDecorator implements MetadataFetcherI { } + /** + * Refresh the SAML2 metadata of a specific Entity + *
+ * Info: A refresh is only possible if the internal metadata provider implements + * the 'RefeshableMetadataProvider' interface + * + * @param entityId EntityID that should be refreshed + * @return true if refresh was successful, otherwise false + */ + public boolean refreshMetadata(String entityId) { + if (this.metadataprovider instanceof IMOARefreshableMetadataProvider ) + return ((IMOARefreshableMetadataProvider)this.metadataprovider).refreshMetadataProvider(entityId); + else + return false; + + } + /* (non-Javadoc) * @see eu.eidas.auth.engine.metadata.MetadataFetcherI#getEntityDescriptor(java.lang.String, eu.eidas.auth.engine.metadata.MetadataSignerI) */ diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAProtocolEngineFactory.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAProtocolEngineFactory.java index 47cdb4ade..dbe11c12e 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAProtocolEngineFactory.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAProtocolEngineFactory.java @@ -23,10 +23,16 @@ package at.gv.egovernment.moa.id.auth.modules.eidas.utils; import at.gv.egovernment.moa.id.auth.modules.eidas.config.MOAIDCertificateManagerConfigurationImpl; +import at.gv.egovernment.moa.id.auth.modules.eidas.engine.MOAProtocolEngine; import at.gv.egovernment.moa.logging.Logger; import eu.eidas.auth.engine.ProtocolEngineFactory; +import eu.eidas.auth.engine.ProtocolEngineI; +import eu.eidas.auth.engine.SamlEngineClock; +import eu.eidas.auth.engine.configuration.FixedProtocolConfigurationAccessor; +import eu.eidas.auth.engine.configuration.ProtocolEngineConfiguration; import eu.eidas.auth.engine.configuration.SamlEngineConfigurationException; import eu.eidas.auth.engine.configuration.dom.ProtocolEngineConfigurationFactory; +import eu.eidas.auth.engine.core.ProtocolProcessorI; import eu.eidas.samlengineconfig.CertificateConfigurationManager; /** @@ -95,22 +101,32 @@ public class MOAProtocolEngineFactory extends ProtocolEngineFactory { } -// public static ProtocolEngineI createProtocolEngine(String instanceName, -// ProtocolEngineConfigurationFactory protocolEngineConfigurationFactory, -// ProtocolProcessorI protocolProcessor, SamlEngineClock samlEngineClock) -// throws SamlEngineConfigurationException { -// -// ProtocolEngineConfiguration preConfiguration = protocolEngineConfigurationFactory -// .getConfiguration(instanceName); -// -// protocolProcessor.configure(); -// -// ProtocolEngineConfiguration configuration = ProtocolEngineConfiguration.builder(preConfiguration) -// .protocolProcessor(protocolProcessor).clock(samlEngineClock).build(); -// -// ProtocolEngineI samlEngine = new MOAProtocolEngine(new FixedProtocolConfigurationAccessor(configuration)); -// -// return samlEngine; -// } + public static ProtocolEngineI ownCreateProtocolEngine(String instanceName, + CertificateConfigurationManager configManager, ProtocolProcessorI protocolProcessor, + SamlEngineClock samlEngineClock) throws SamlEngineConfigurationException { + ProtocolEngineConfigurationFactory protocolEngineConfigurationFactory = new ProtocolEngineConfigurationFactory( + configManager); + + return createProtocolEngine(instanceName, protocolEngineConfigurationFactory, protocolProcessor, + samlEngineClock); + } + + public static ProtocolEngineI createProtocolEngine(String instanceName, + ProtocolEngineConfigurationFactory protocolEngineConfigurationFactory, + ProtocolProcessorI protocolProcessor, SamlEngineClock samlEngineClock) + throws SamlEngineConfigurationException { + + ProtocolEngineConfiguration preConfiguration = protocolEngineConfigurationFactory + .getConfiguration(instanceName); + + protocolProcessor.configure(); + + ProtocolEngineConfiguration configuration = ProtocolEngineConfiguration.builder(preConfiguration) + .protocolProcessor(protocolProcessor).clock(samlEngineClock).build(); + + ProtocolEngineI samlEngine = new MOAProtocolEngine(new FixedProtocolConfigurationAccessor(configuration)); + + return samlEngine; + } } diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/SAMLEngineUtils.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/SAMLEngineUtils.java index edbecc4a0..773e08ea9 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/SAMLEngineUtils.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/SAMLEngineUtils.java @@ -93,7 +93,7 @@ public class SAMLEngineUtils { } //build eIDAS SAML eninge - ProtocolEngineI engine = MOAProtocolEngineFactory.createProtocolEngine( + ProtocolEngineI engine = MOAProtocolEngineFactory.ownCreateProtocolEngine( Constants.eIDAS_SAML_ENGINE_NAME, configManager, new MOAEidasProtocolProcesser(metadataFetcher, metadataSigner, addAttrDefinitions), -- cgit v1.2.3 From 8af293b80fb4a7930dfee4af5557036b3b47283b Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Wed, 3 May 2017 09:27:34 +0200 Subject: Log full MOA-SP signature-verification request into MOA-ID log if LogLevel is trace --- .../java/at/gv/egovernment/moa/id/auth/AuthenticationServer.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'id/server/modules') diff --git a/id/server/modules/moa-id-modul-citizencard_authentication/src/main/java/at/gv/egovernment/moa/id/auth/AuthenticationServer.java b/id/server/modules/moa-id-modul-citizencard_authentication/src/main/java/at/gv/egovernment/moa/id/auth/AuthenticationServer.java index 66161e508..9294f3658 100644 --- a/id/server/modules/moa-id-modul-citizencard_authentication/src/main/java/at/gv/egovernment/moa/id/auth/AuthenticationServer.java +++ b/id/server/modules/moa-id-modul-citizencard_authentication/src/main/java/at/gv/egovernment/moa/id/auth/AuthenticationServer.java @@ -972,8 +972,9 @@ public class AuthenticationServer extends BaseAuthenticationServer { try { String xmlVerifyXMLSignatureResponse = DOMUtils .serializeNode(domVsresp, true); - Logger.trace(new LogMsg(xmlCreateXMLSignatureReadResponse)); - Logger.trace(new LogMsg(xmlVerifyXMLSignatureResponse)); + Logger.trace("Signature from BKU: " + new LogMsg(xmlCreateXMLSignatureReadResponse)); + Logger.trace("Signature verification request: " + new LogMsg(DOMUtils.serializeNode(domVsreq, true))); + Logger.trace("Signature verification result: " + new LogMsg(xmlVerifyXMLSignatureResponse)); } catch (Throwable t) { t.printStackTrace(); Logger.info(new LogMsg(t.getStackTrace())); -- cgit v1.2.3 From a76ea96898c29947d321036f8eae4e5b5c01caaa Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Tue, 6 Jun 2017 15:15:44 +0200 Subject: fix bug with empty OpenIDConnect scope parameter --- .../oauth20/protocol/OAuth20AuthAction.java | 34 ++++++++++++---------- 1 file changed, 18 insertions(+), 16 deletions(-) (limited to 'id/server/modules') diff --git a/id/server/modules/moa-id-module-openID/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/protocol/OAuth20AuthAction.java b/id/server/modules/moa-id-module-openID/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/protocol/OAuth20AuthAction.java index b9bed7a22..f0cf45293 100644 --- a/id/server/modules/moa-id-module-openID/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/protocol/OAuth20AuthAction.java +++ b/id/server/modules/moa-id-module-openID/src/main/java/at/gv/egovernment/moa/id/protocols/oauth20/protocol/OAuth20AuthAction.java @@ -163,22 +163,24 @@ class OAuth20AuthAction implements IAction { OAuth20AttributeBuilder.addScopeOpenId(token.getPayloadAsJsonObject(), oaParam, authData, oAuthRequest); resultScopes.append("openId"); - for (String s : scope.split(" ")) { - if (s.equalsIgnoreCase("profile")) { - OAuth20AttributeBuilder.addScopeProfile(token.getPayloadAsJsonObject(), oaParam, authData); - resultScopes.append(" profile"); - } else if (s.equalsIgnoreCase("eID")) { - OAuth20AttributeBuilder.addScopeEID(token.getPayloadAsJsonObject(), oaParam, authData); - resultScopes.append(" eID"); - } else if (s.equalsIgnoreCase("eID_gov")) { - OAuth20AttributeBuilder.addScopeEIDGov(token.getPayloadAsJsonObject(), oaParam, authData); - resultScopes.append(" eID_gov"); - } else if (s.equalsIgnoreCase("mandate")) { - OAuth20AttributeBuilder.addScopeMandate(token.getPayloadAsJsonObject(), oaParam, authData); - resultScopes.append(" mandate"); - } else if (s.equalsIgnoreCase("stork")) { - OAuth20AttributeBuilder.addScopeSTORK(token.getPayloadAsJsonObject(), oaParam, authData); - resultScopes.append(" stork"); + if (scope != null) { + for (String s : scope.split(" ")) { + if (s.equalsIgnoreCase("profile")) { + OAuth20AttributeBuilder.addScopeProfile(token.getPayloadAsJsonObject(), oaParam, authData); + resultScopes.append(" profile"); + } else if (s.equalsIgnoreCase("eID")) { + OAuth20AttributeBuilder.addScopeEID(token.getPayloadAsJsonObject(), oaParam, authData); + resultScopes.append(" eID"); + } else if (s.equalsIgnoreCase("eID_gov")) { + OAuth20AttributeBuilder.addScopeEIDGov(token.getPayloadAsJsonObject(), oaParam, authData); + resultScopes.append(" eID_gov"); + } else if (s.equalsIgnoreCase("mandate")) { + OAuth20AttributeBuilder.addScopeMandate(token.getPayloadAsJsonObject(), oaParam, authData); + resultScopes.append(" mandate"); + } else if (s.equalsIgnoreCase("stork")) { + OAuth20AttributeBuilder.addScopeSTORK(token.getPayloadAsJsonObject(), oaParam, authData); + resultScopes.append(" stork"); + } } } -- cgit v1.2.3 From 55876723bc59b0b3ea1a68f1a5df9a83d75a9385 Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Wed, 7 Jun 2017 16:34:33 +0200 Subject: first untested implementation that based on the snapshot version 1.3.0 of eIDAS SAML-engine --- id/server/modules/moa-id-module-eIDAS/pom.xml | 10 +- .../modules/eidas/config/MOAExtendedSWSigner.java | 9 +- .../id/auth/modules/eidas/config/MOASWSigner.java | 8 +- .../modules/eidas/config/ModifiedEncryptionSW.java | 6 +- .../eidas/tasks/GenerateAuthnRequestTask.java | 4 +- .../eidas/utils/MOAeIDASMetadataGenerator.java | 1367 ++++++++++---------- .../modules/eidas/utils/NewMoaEidasMetadata.java | 602 +++++++++ .../auth/modules/eidas/utils/SAMLEngineUtils.java | 2 +- .../moa/id/protocols/eidas/EIDASProtocol.java | 2 +- .../id/protocols/eidas/EidasMetaDataRequest.java | 82 +- .../src/test/java/at/gv/egiz/tests/Tests.java | 280 +++- .../eidas-commons-1.3.0-SNAPSHOT.jar | Bin 0 -> 253127 bytes .../eidas-configmodule-1.3.0-SNAPSHOT.jar | Bin 0 -> 64871 bytes .../eidas-encryption-1.3.0-SNAPSHOT.jar | Bin 0 -> 21023 bytes .../eidas-light-commons-1.3.0-SNAPSHOT.jar | Bin 0 -> 102277 bytes .../eidas-saml-engine-1.3.0-SNAPSHOT.jar | Bin 0 -> 587188 bytes ...fic-communication-definition-1.3.0-SNAPSHOT.jar | Bin 0 -> 5531 bytes .../eidas-specific-1.3.0-SNAPSHOT.jar | Bin 0 -> 32866 bytes 18 files changed, 1623 insertions(+), 749 deletions(-) create mode 100644 id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/NewMoaEidasMetadata.java create mode 100644 repository/eu/eidas/eidas-commons/1.3.0-SNAPSHOT/eidas-commons-1.3.0-SNAPSHOT.jar create mode 100644 repository/eu/eidas/eidas-configmodule/1.3.0-SNAPSHOT/eidas-configmodule-1.3.0-SNAPSHOT.jar create mode 100644 repository/eu/eidas/eidas-encryption/1.3.0-SNAPSHOT/eidas-encryption-1.3.0-SNAPSHOT.jar create mode 100644 repository/eu/eidas/eidas-light-commons/1.3.0-SNAPSHOT/eidas-light-commons-1.3.0-SNAPSHOT.jar create mode 100644 repository/eu/eidas/eidas-saml-engine/1.3.0-SNAPSHOT/eidas-saml-engine-1.3.0-SNAPSHOT.jar create mode 100644 repository/eu/eidas/eidas-specific-communication-definition/1.3.0-SNAPSHOT/eidas-specific-communication-definition-1.3.0-SNAPSHOT.jar create mode 100644 repository/eu/eidas/eidas-specific/1.3.0-SNAPSHOT/eidas-specific-1.3.0-SNAPSHOT.jar (limited to 'id/server/modules') diff --git a/id/server/modules/moa-id-module-eIDAS/pom.xml b/id/server/modules/moa-id-module-eIDAS/pom.xml index 55d02e82a..58f6584ae 100644 --- a/id/server/modules/moa-id-module-eIDAS/pom.xml +++ b/id/server/modules/moa-id-module-eIDAS/pom.xml @@ -12,11 +12,11 @@ ${basedir}/../../../../repository - 1.2.0 - 1.2.0 - 1.2.0 - 1.2.0 - 1.2.0 + 1.3.0-SNAPSHOT + 1.3.0-SNAPSHOT + 1.3.0-SNAPSHOT + 1.3.0-SNAPSHOT + 1.3.0-SNAPSHOT diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAExtendedSWSigner.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAExtendedSWSigner.java index c872bcfb6..6a48e5030 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAExtendedSWSigner.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOAExtendedSWSigner.java @@ -98,8 +98,11 @@ public class MOAExtendedSWSigner implements ProtocolSignerI, MetadataSignerI { private final ImmutableList trustedCredentials; private final String signatureAlgorithm; - public MOAExtendedSWSigner(Map properties) throws SamlEngineConfigurationException { - this(new KeyStoreSignatureConfigurator().getSignatureConfiguration(properties)); + + //TODO: check if it is required any more + + public MOAExtendedSWSigner(Map properties, String defaultConfigPath) throws SamlEngineConfigurationException { + this(new KeyStoreSignatureConfigurator().getSignatureConfiguration(properties, null)); } @@ -109,7 +112,7 @@ public class MOAExtendedSWSigner implements ProtocolSignerI, MetadataSignerI { */ public MOAExtendedSWSigner(CertificateConfigurationManager configManager) throws SamlEngineConfigurationException { this(new KeyStoreSignatureConfigurator().getSignatureConfiguration( - ConfigurationAdapter.adapt(configManager).getInstances().get(Constants.eIDAS_SAML_ENGINE_NAME).getConfigurationEntries().get(ConfigurationKey.SIGNATURE_CONFIGURATION.getKey()).getParameters())); + ConfigurationAdapter.adapt(configManager).getInstances().get(Constants.eIDAS_SAML_ENGINE_NAME).getConfigurationEntries().get(ConfigurationKey.SIGNATURE_CONFIGURATION.getKey()).getParameters(), null)); } diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOASWSigner.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOASWSigner.java index 5cf5e83ec..3cc9787df 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOASWSigner.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/MOASWSigner.java @@ -79,8 +79,8 @@ public class MOASWSigner extends KeyStoreProtocolSigner { //Set other algorithms which are not supported by openSAML in default StringUtils.lowerCase(XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA256_MGF1, Locale.ENGLISH)); - public MOASWSigner(Map properties) throws SamlEngineConfigurationException { - super(properties); + public MOASWSigner(Map properties, String defaultConfigPath) throws SamlEngineConfigurationException { + super(properties, null); props = properties; } @@ -90,7 +90,7 @@ public class MOASWSigner extends KeyStoreProtocolSigner { * @throws SamlEngineConfigurationException */ public MOASWSigner(CertificateConfigurationManager configManager) throws SamlEngineConfigurationException { - super(props = ConfigurationAdapter.adapt(configManager).getInstances().get(Constants.eIDAS_SAML_ENGINE_NAME).getConfigurationEntries().get(ConfigurationKey.SIGNATURE_CONFIGURATION.getKey()).getParameters()); + super(props = ConfigurationAdapter.adapt(configManager).getInstances().get(Constants.eIDAS_SAML_ENGINE_NAME).getConfigurationEntries().get(ConfigurationKey.SIGNATURE_CONFIGURATION.getKey()).getParameters(), null); } @@ -100,7 +100,7 @@ public class MOASWSigner extends KeyStoreProtocolSigner { if (sigAlgWhiteList == null) { sigAlgWhiteList = MOAWhiteListConfigurator.getAllowedAlgorithms(DEFAULT_ALGORITHM_WHITE_LIST, ALLOWED_ALGORITHMS_FOR_VERIFYING, - (new KeyStoreSignatureConfigurator().getSignatureConfiguration(props)).getSignatureAlgorithmWhiteList()); + (new KeyStoreSignatureConfigurator().getSignatureConfiguration(props, null)).getSignatureAlgorithmWhiteList()); } diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/ModifiedEncryptionSW.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/ModifiedEncryptionSW.java index de4f3fc9c..d5cbb2cfd 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/ModifiedEncryptionSW.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/config/ModifiedEncryptionSW.java @@ -33,15 +33,15 @@ public class ModifiedEncryptionSW extends KeyStoreSamlEngineEncryption { private static ReloadableProperties initActivationConf(Map properties) { String activationConfigurationFile = EncryptionKey.ENCRYPTION_ACTIVATION.getAsString(properties); Logger.debug("File containing encryption configuration: \"" + activationConfigurationFile + "\""); - return new ReloadableProperties(activationConfigurationFile); + return new ReloadableProperties(activationConfigurationFile, null); } /** * @param properties * @throws SamlEngineConfigurationException */ - public ModifiedEncryptionSW(Map properties) throws SamlEngineConfigurationException { - super(properties); + public ModifiedEncryptionSW(Map properties, String defaultConfigPath) throws SamlEngineConfigurationException { + super(properties, null); this.properties = ImmutableMap.copyOf(properties); encryptionActivationProperties = initActivationConf(properties); } diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/GenerateAuthnRequestTask.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/GenerateAuthnRequestTask.java index 7155040c6..6f1d75bfe 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/GenerateAuthnRequestTask.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/GenerateAuthnRequestTask.java @@ -228,9 +228,9 @@ public class GenerateAuthnRequestTask extends AbstractAuthServletTask { //set correct SPType for this online application if (oaConfig.getBusinessService()) - authnRequestBuilder.spType(SpType.PRIVATE); + authnRequestBuilder.spType(SpType.PRIVATE.getValue()); else - authnRequestBuilder.spType(SpType.PUBLIC); + authnRequestBuilder.spType(SpType.PUBLIC.getValue()); //set service provider (eIDAS node) countryCode diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAeIDASMetadataGenerator.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAeIDASMetadataGenerator.java index 7b159c73d..9683db503 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAeIDASMetadataGenerator.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/MOAeIDASMetadataGenerator.java @@ -1,686 +1,681 @@ -/* - * Copyright 2014 Federal Chancellery Austria - * MOA-ID has been developed in a cooperation between BRZ, the Federal - * Chancellery Austria - ICT staff unit, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * http://www.osor.eu/eupl/ - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. - */ -package at.gv.egovernment.moa.id.auth.modules.eidas.utils; - -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import org.apache.commons.lang.StringUtils; -import org.joda.time.DateTime; -import org.joda.time.DurationFieldType; -import org.opensaml.Configuration; -import org.opensaml.common.xml.SAMLConstants; -import org.opensaml.saml2.common.Extensions; -import org.opensaml.saml2.common.impl.ExtensionsBuilder; -import org.opensaml.saml2.core.Attribute; -import org.opensaml.saml2.core.AttributeValue; -import org.opensaml.saml2.metadata.AssertionConsumerService; -import org.opensaml.saml2.metadata.Company; -import org.opensaml.saml2.metadata.ContactPerson; -import org.opensaml.saml2.metadata.ContactPersonTypeEnumeration; -import org.opensaml.saml2.metadata.EmailAddress; -import org.opensaml.saml2.metadata.EncryptionMethod; -import org.opensaml.saml2.metadata.EntitiesDescriptor; -import org.opensaml.saml2.metadata.EntityDescriptor; -import org.opensaml.saml2.metadata.GivenName; -import org.opensaml.saml2.metadata.IDPSSODescriptor; -import org.opensaml.saml2.metadata.KeyDescriptor; -import org.opensaml.saml2.metadata.LocalizedString; -import org.opensaml.saml2.metadata.NameIDFormat; -import org.opensaml.saml2.metadata.Organization; -import org.opensaml.saml2.metadata.OrganizationDisplayName; -import org.opensaml.saml2.metadata.OrganizationName; -import org.opensaml.saml2.metadata.OrganizationURL; -import org.opensaml.saml2.metadata.SPSSODescriptor; -import org.opensaml.saml2.metadata.SSODescriptor; -import org.opensaml.saml2.metadata.SingleSignOnService; -import org.opensaml.saml2.metadata.SurName; -import org.opensaml.saml2.metadata.TelephoneNumber; -import org.opensaml.samlext.saml2mdattr.EntityAttributes; -import org.opensaml.xml.XMLObject; -import org.opensaml.xml.XMLObjectBuilderFactory; -import org.opensaml.xml.schema.XSString; -import org.opensaml.xml.schema.impl.XSStringBuilder; -import org.opensaml.xml.security.SecurityException; -import org.opensaml.xml.security.credential.Credential; -import org.opensaml.xml.security.credential.UsageType; -import org.opensaml.xml.security.keyinfo.KeyInfoGenerator; -import org.opensaml.xml.security.x509.X509KeyInfoGeneratorFactory; -import org.opensaml.xml.signature.KeyInfo; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.collect.ImmutableSortedSet; -import com.google.common.collect.Ordering; - -import at.gv.egovernment.moa.id.protocols.pvp2x.utils.SAML2Utils; -import eu.eidas.auth.commons.EIDASUtil; -import eu.eidas.auth.commons.EidasStringUtil; -import eu.eidas.auth.commons.attribute.AttributeDefinition; -import eu.eidas.auth.commons.protocol.impl.SamlNameIdFormat; -import eu.eidas.auth.commons.xml.opensaml.OpenSamlHelper; -import eu.eidas.auth.engine.ProtocolEngineI; -import eu.eidas.auth.engine.core.SAMLExtensionFormat; -import eu.eidas.auth.engine.core.eidas.DigestMethod; -import eu.eidas.auth.engine.core.eidas.EidasConstants; -import eu.eidas.auth.engine.core.eidas.SPType; -import eu.eidas.auth.engine.core.eidas.SigningMethod; -import eu.eidas.auth.engine.metadata.Contact; -import eu.eidas.auth.engine.metadata.EntityDescriptorContainer; -import eu.eidas.auth.engine.metadata.MetadataConfigParams; -import eu.eidas.auth.engine.metadata.MetadataGenerator; -import eu.eidas.auth.engine.metadata.MetadataSignerI; -import eu.eidas.auth.engine.xml.opensaml.BuilderFactoryUtil; -import eu.eidas.auth.engine.xml.opensaml.CertificateUtil; -import eu.eidas.encryption.exception.UnmarshallException; -import eu.eidas.engine.exceptions.EIDASSAMLEngineException; -import eu.eidas.engine.exceptions.SAMLEngineException; - -/** - * @author tlenz - * - */ -public class MOAeIDASMetadataGenerator extends MetadataGenerator { - private static final Logger LOGGER = LoggerFactory.getLogger(MetadataGenerator.class.getName()); - - MetadataConfigParams params; - - XMLObjectBuilderFactory builderFactory = Configuration.getBuilderFactory(); - - SPSSODescriptor spSSODescriptor = null; - - IDPSSODescriptor idpSSODescriptor = null; - - private String ssoLocation; - - /** - * @return a String representation of the entityDescriptr built based on the attributes previously set - */ - public String generateMetadata() throws EIDASSAMLEngineException { - EntityDescriptor entityDescriptor; - try { - entityDescriptor = (EntityDescriptor) builderFactory.getBuilder(EntityDescriptor.DEFAULT_ELEMENT_NAME) - .buildObject(EntityDescriptor.DEFAULT_ELEMENT_NAME); - - entityDescriptor.setEntityID(params.getEntityID()); - entityDescriptor.setOrganization(buildOrganization()); - - /**FIXME: - * HOTFIX: do not add empty contactPerson elements - */ - ContactPerson contactSupport = buildContact(ContactPersonTypeEnumeration.SUPPORT); - if (contactSupport != null) - entityDescriptor.getContactPersons().add(contactSupport); - ContactPerson contactTech = buildContact(ContactPersonTypeEnumeration.TECHNICAL); - if (contactTech != null) - entityDescriptor.getContactPersons().add(contactTech); - - entityDescriptor.setValidUntil(getExpireDate()); - - X509KeyInfoGeneratorFactory keyInfoGeneratorFactory = new X509KeyInfoGeneratorFactory(); - keyInfoGeneratorFactory.setEmitEntityCertificate(true); - Extensions e = generateExtensions(); - if (!e.getUnknownXMLObjects().isEmpty()) { - entityDescriptor.setExtensions(e); - } - if (spSSODescriptor != null) { - generateSPSSODescriptor(entityDescriptor, keyInfoGeneratorFactory); - } - if (idpSSODescriptor != null) { - generateIDPSSODescriptor(entityDescriptor, keyInfoGeneratorFactory); - } - if (params.getSpEngine() != null) { - ProtocolEngineI spEngine = params.getSpEngine(); - ((MetadataSignerI) spEngine.getSigner()).signMetadata(entityDescriptor); - } else if (params.getIdpEngine() != null) { - ProtocolEngineI idpEngine = params.getIdpEngine(); - ((MetadataSignerI) idpEngine.getSigner()).signMetadata(entityDescriptor); - } - return EidasStringUtil.toString(OpenSamlHelper.marshall(entityDescriptor, false)); - } catch (Exception ex) { - LOGGER.info("ERROR : SAMLException ", ex.getMessage()); - LOGGER.debug("ERROR : SAMLException ", ex); - throw new IllegalStateException(ex); - } - } - - private void generateSPSSODescriptor(final EntityDescriptor entityDescriptor, - final X509KeyInfoGeneratorFactory keyInfoGeneratorFactory) - throws org.opensaml.xml.security.SecurityException, IllegalAccessException, NoSuchFieldException, - SAMLEngineException, EIDASSAMLEngineException { - //the node has SP role - spSSODescriptor.setWantAssertionsSigned(params.isWantAssertionsSigned()); - spSSODescriptor.setAuthnRequestsSigned(true); - - - /**FIXME: - * "SP" + params.getEntityID()) is not a valid XML ID attribute value - */ - //spSSODescriptor.setID(idpSSODescriptor == null ? params.getEntityID() : ("SP" + params.getEntityID())); - spSSODescriptor.setID(SAML2Utils.getSecureIdentifier()); - - - if (params.getSPSignature() != null) { - spSSODescriptor.setSignature(params.getSPSignature()); - } - if (params.getSpSigningCredential() != null) { - spSSODescriptor.getKeyDescriptors() - .add(getKeyDescriptor(keyInfoGeneratorFactory, params.getSpSigningCredential(), UsageType.SIGNING)); - - } else if (params.getSigningCredential() != null) { - spSSODescriptor.getKeyDescriptors() - .add(getKeyDescriptor(keyInfoGeneratorFactory, params.getSigningCredential(), UsageType.SIGNING)); - } - - if (params.getSpEncryptionCredential() != null) { - spSSODescriptor.getKeyDescriptors() - .add(getKeyDescriptor(keyInfoGeneratorFactory, params.getSpEncryptionCredential(), - UsageType.ENCRYPTION)); - } else if (params.getEncryptionCredential() != null) { - spSSODescriptor.getKeyDescriptors() - .add(getKeyDescriptor(keyInfoGeneratorFactory, params.getEncryptionCredential(), UsageType.ENCRYPTION)); - } - spSSODescriptor.addSupportedProtocol(params.getSpSamlProtocol()); - if (!StringUtils.isEmpty(params.getAssertionConsumerUrl())) { - addAssertionConsumerService(); - } - - //FIX: Austrian eIDAS node SP only needs persistent identifiers - NameIDFormat persistentFormat = - (NameIDFormat) BuilderFactoryUtil.buildXmlObject(NameIDFormat.DEFAULT_ELEMENT_NAME); - persistentFormat.setFormat(SamlNameIdFormat.PERSISTENT.getNameIdFormat()); - spSSODescriptor.getNameIDFormats().add(persistentFormat); - - /**FIXME: - * Double signing of SPSSODescribtor is not required - */ -// if (params.getSpEngine() != null) { -// ProtocolEngineI spEngine = params.getSpEngine(); -// ((MetadataSignerI) spEngine.getSigner()).signMetadata(spSSODescriptor); -// } - - entityDescriptor.getRoleDescriptors().add(spSSODescriptor); - - } - - private void fillIDPNameIDFormat(SSODescriptor ssoDescriptor) throws EIDASSAMLEngineException { - NameIDFormat persistentFormat = - (NameIDFormat) BuilderFactoryUtil.buildXmlObject(NameIDFormat.DEFAULT_ELEMENT_NAME); - persistentFormat.setFormat(SamlNameIdFormat.PERSISTENT.getNameIdFormat()); - ssoDescriptor.getNameIDFormats().add(persistentFormat); - NameIDFormat transientFormat = - (NameIDFormat) BuilderFactoryUtil.buildXmlObject(NameIDFormat.DEFAULT_ELEMENT_NAME); - transientFormat.setFormat(SamlNameIdFormat.TRANSIENT.getNameIdFormat()); - ssoDescriptor.getNameIDFormats().add(transientFormat); - NameIDFormat unspecifiedFormat = - (NameIDFormat) BuilderFactoryUtil.buildXmlObject(NameIDFormat.DEFAULT_ELEMENT_NAME); - unspecifiedFormat.setFormat(SamlNameIdFormat.UNSPECIFIED.getNameIdFormat()); - ssoDescriptor.getNameIDFormats().add(unspecifiedFormat); - } - - private void generateIDPSSODescriptor(final EntityDescriptor entityDescriptor, - final X509KeyInfoGeneratorFactory keyInfoGeneratorFactory) - throws org.opensaml.xml.security.SecurityException, IllegalAccessException, NoSuchFieldException, - SAMLEngineException, EIDASSAMLEngineException { - //the node has IDP role - idpSSODescriptor.setWantAuthnRequestsSigned(true); - - /**FIXME: - * "IDP" + params.getEntityID()) is not a valid XML ID attribute value - */ - //idpSSODescriptor.setID(spSSODescriptor == null ? params.getEntityID() : ("IDP" + params.getEntityID())); - idpSSODescriptor.setID(SAML2Utils.getSecureIdentifier()); - - if (params.getIDPSignature() != null) { - idpSSODescriptor.setSignature(params.getIDPSignature()); - } - if (params.getIdpSigningCredential() != null) { - idpSSODescriptor.getKeyDescriptors() - .add(getKeyDescriptor(keyInfoGeneratorFactory, params.getIdpSigningCredential(), UsageType.SIGNING)); - } else if (params.getSigningCredential() != null) { - idpSSODescriptor.getKeyDescriptors() - .add(getKeyDescriptor(keyInfoGeneratorFactory, params.getSigningCredential(), UsageType.SIGNING)); - } - if (params.getIdpEncryptionCredential() != null) { - idpSSODescriptor.getKeyDescriptors() - .add(getKeyDescriptor(keyInfoGeneratorFactory, params.getIdpEncryptionCredential(), - UsageType.ENCRYPTION)); - } else if (params.getEncryptionCredential() != null) { - idpSSODescriptor.getKeyDescriptors() - .add(getKeyDescriptor(keyInfoGeneratorFactory, params.getEncryptionCredential(), UsageType.ENCRYPTION)); - } - idpSSODescriptor.addSupportedProtocol(params.getIdpSamlProtocol()); - - //Austrian eIDAS node IDP can provided persistent, transient, and unspecified identifiers - fillIDPNameIDFormat(idpSSODescriptor); - - - if (params.getIdpEngine() != null) { - if (params.getIdpEngine().getProtocolProcessor() != null - && params.getIdpEngine().getProtocolProcessor().getFormat() == SAMLExtensionFormat.EIDAS10) { - - /*TODO: Only a work-around to add eIDAS attributes, which could be provided from MOA-ID, to IDP metadata - * If we restrict the eIDAS Engine attribute definitions then also additional incoming attributes can not processed any more. - * - * INFO: Maybe, this code can be removed in a future version of the eIDAS engine - */ - generateSupportedAttributes(idpSSODescriptor, getAllSupportedAttributes()); - } - - - /**FIXME: - * Double signing of IDPSSODescribtor is not required - */ -// ProtocolEngineI idpEngine = params.getIdpEngine(); -// ((MetadataSignerI) idpEngine.getSigner()).signMetadata(idpSSODescriptor); - } - - idpSSODescriptor.getSingleSignOnServices().addAll(buildSingleSignOnServicesBindingLocations()); - - entityDescriptor.getRoleDescriptors().add(idpSSODescriptor); - - } - - /* FIX: Work-around to add eIDAS attributes, which could be provided from MOA-ID, to IDP metadata - * If we restrict the eIDAS Engine attribute definitions then also additional incoming attributes can not processed any more. - */ - public ImmutableSortedSet> getAllSupportedAttributes() { - ImmutableSortedSet.Builder> builder = - new ImmutableSortedSet.Builder<>(Ordering.>natural()); - - for (String attr : eIDASAttributeBuilder.getAllProvideableeIDASAttributes()) { - AttributeDefinition supAttr = params.getIdpEngine().getProtocolProcessor().getAttributeDefinitionNullable(attr); - builder.add(supAttr); - } - - return builder.build(); - } - - private ArrayList buildSingleSignOnServicesBindingLocations() - throws NoSuchFieldException, IllegalAccessException { - ArrayList singleSignOnServices = new ArrayList(); - - HashMap bindingLocations = params.getProtocolBindingLocation(); - for (String binding : bindingLocations.keySet()) { - SingleSignOnService ssos = BuilderFactoryUtil.buildXmlObject(SingleSignOnService.class); - ssos.setBinding(binding); - ssos.setLocation(bindingLocations.get(binding)); - singleSignOnServices.add(ssos); - } - - return singleSignOnServices; - } - - /** - * @param metadata - * @return an EntityDescriptor parsed from the given String or null - */ - // TODO (commented by donydgr) Move to a eu.eidas.auth.engine.metadata.MetadataUtil ? Throw an exception if the metadata is invalid instead of returning null ? - public static EntityDescriptorContainer deserializeEntityDescriptor(String metadata) { - EntityDescriptorContainer result = new EntityDescriptorContainer(); - try { - byte[] metaDataBytes = EidasStringUtil.getBytes(metadata); - XMLObject obj = OpenSamlHelper.unmarshall(metaDataBytes); - if (obj instanceof EntityDescriptor) { - result.addEntityDescriptor((EntityDescriptor) obj, metaDataBytes); - } else if (obj instanceof EntitiesDescriptor) { - EntitiesDescriptor ed = (EntitiesDescriptor) obj; - result.setEntitiesDescriptor(ed); - result.getEntityDescriptors().addAll(((EntitiesDescriptor) obj).getEntityDescriptors()); - result.setSerializedEntitesDescriptor(metaDataBytes); - } - } catch (UnmarshallException ue) { - LOGGER.info("ERROR : unmarshalling error", ue.getMessage()); - LOGGER.debug("ERROR : unmarshalling error", ue); - } - return result; - } - - private KeyDescriptor getKeyDescriptor(X509KeyInfoGeneratorFactory keyInfoGeneratorFactory, - Credential credential, - UsageType usage) - throws NoSuchFieldException, IllegalAccessException, SecurityException, EIDASSAMLEngineException { - KeyDescriptor keyDescriptor = null; - if (credential != null) { - keyDescriptor = BuilderFactoryUtil.buildXmlObject(KeyDescriptor.class); - KeyInfoGenerator keyInfoGenerator = keyInfoGeneratorFactory.newInstance(); - - KeyInfo keyInfo = keyInfoGenerator.generate(credential); - keyDescriptor.setUse(usage); - keyDescriptor.setKeyInfo(keyInfo); - if (usage == UsageType.ENCRYPTION && params.getEncryptionAlgorithms() != null) { - Set encryptionAlgos = EIDASUtil.parseSemicolonSeparatedList(params.getEncryptionAlgorithms()); - for (String encryptionAlgo : encryptionAlgos) { - EncryptionMethod em = - (EncryptionMethod) BuilderFactoryUtil.buildXmlObject(EncryptionMethod.DEFAULT_ELEMENT_NAME); - em.setAlgorithm(encryptionAlgo); - keyDescriptor.getEncryptionMethods().add(em); - } - } - - } - return keyDescriptor; - } - - private Organization buildOrganization() { - Organization organization = null; - try { - organization = BuilderFactoryUtil.buildXmlObject(Organization.class); - - /**FIXME: - * set correct OrganizationName value if it is not fixed in next eIDAS node version - */ - OrganizationName orgName = BuilderFactoryUtil.buildXmlObject(OrganizationName.class); - orgName.setName(new LocalizedString(params.getNodeUrl(), "en")); - organization.getOrganizationNames().add(orgName); - - OrganizationDisplayName odn = BuilderFactoryUtil.buildXmlObject(OrganizationDisplayName.class); - odn.setName(new LocalizedString(params.getCountryName(), "en")); - organization.getDisplayNames().add(odn); - OrganizationURL url = BuilderFactoryUtil.buildXmlObject(OrganizationURL.class); - url.setURL(new LocalizedString(params.getNodeUrl(), "en")); - organization.getURLs().add(url); - } catch (IllegalAccessException iae) { - LOGGER.info("ERROR : error generating the Organization: {}", iae.getMessage()); - LOGGER.debug("ERROR : error generating the Organization: {}", iae); - } catch (NoSuchFieldException nfe) { - LOGGER.info("ERROR : error generating the Organization: {}", nfe.getMessage()); - LOGGER.debug("ERROR : error generating the Organization: {}", nfe); - } - return organization; - } - - private ContactPerson buildContact(ContactPersonTypeEnumeration contactType) { - ContactPerson contact = null; - try { - Contact currentContact = null; - if (contactType == ContactPersonTypeEnumeration.SUPPORT) { - currentContact = params.getSupportContact(); - } else if (contactType == ContactPersonTypeEnumeration.TECHNICAL) { - currentContact = params.getTechnicalContact(); - } else { - LOGGER.error("ERROR: unsupported contact type"); - } - contact = BuilderFactoryUtil.buildXmlObject(ContactPerson.class); - if (currentContact == null) { - LOGGER.error("ERROR: cannot retrieve contact from the configuration"); - return null; - } - - EmailAddress emailAddressObj = BuilderFactoryUtil.buildXmlObject(EmailAddress.class); - Company company = BuilderFactoryUtil.buildXmlObject(Company.class); - GivenName givenName = BuilderFactoryUtil.buildXmlObject(GivenName.class); - SurName surName = BuilderFactoryUtil.buildXmlObject(SurName.class); - TelephoneNumber phoneNumber = BuilderFactoryUtil.buildXmlObject(TelephoneNumber.class); - contact.setType(contactType); - emailAddressObj.setAddress(currentContact.getEmail()); - company.setName(currentContact.getCompany()); - givenName.setName(currentContact.getGivenName()); - surName.setName(currentContact.getSurName()); - phoneNumber.setNumber(currentContact.getPhone()); - - populateContact(contact, currentContact, emailAddressObj, company, givenName, surName, phoneNumber); - - } catch (IllegalAccessException iae) { - LOGGER.info("ERROR : error generating the Organization: {}", iae.getMessage()); - LOGGER.debug("ERROR : error generating the Organization: {}", iae); - } catch (NoSuchFieldException nfe) { - LOGGER.info("ERROR : error generating the Organization: {}", nfe.getMessage()); - LOGGER.debug("ERROR : error generating the Organization: {}", nfe); - } - return contact; - } - - private void populateContact(ContactPerson contact, - Contact currentContact, - EmailAddress emailAddressObj, - Company company, - GivenName givenName, - SurName surName, - TelephoneNumber phoneNumber) { - if (!StringUtils.isEmpty(currentContact.getEmail())) { - contact.getEmailAddresses().add(emailAddressObj); - } - if (!StringUtils.isEmpty(currentContact.getCompany())) { - contact.setCompany(company); - } - if (!StringUtils.isEmpty(currentContact.getGivenName())) { - contact.setGivenName(givenName); - } - if (!StringUtils.isEmpty(currentContact.getSurName())) { - contact.setSurName(surName); - } - if (!StringUtils.isEmpty(currentContact.getPhone())) { - contact.getTelephoneNumbers().add(phoneNumber); - } - - } - - /** - * @param engine a EIDASSamlEngine from which signing and encryption information is extracted - */ - - public void initialize(ProtocolEngineI engine) throws EIDASSAMLEngineException { - - X509Certificate decryptionCertificate = engine.getDecryptionCertificate(); - if (null != decryptionCertificate) { - params.setSpEncryptionCredential(CertificateUtil.toCredential(decryptionCertificate)); - } - params.setSigningCredential(CertificateUtil.toCredential(engine.getSigningCertificate())); - params.setIdpEngine(engine); - params.setSpEngine(engine); - } - - /** - * @param spEngine a EIDASSamlEngine for the - */ - - public void initialize(ProtocolEngineI spEngine, ProtocolEngineI idpEngine) throws EIDASSAMLEngineException { - if (idpEngine != null) { - idpEngine.getProtocolProcessor().configure(); - params.setIdpSigningCredential(CertificateUtil.toCredential(idpEngine.getSigningCertificate())); - - final X509Certificate idpEngineDecryptionCertificate = idpEngine.getDecryptionCertificate(); - if (idpEngineDecryptionCertificate != null) { - params.setIdpEncryptionCredential(CertificateUtil.toCredential(idpEngineDecryptionCertificate)); - } - - } - if (spEngine != null) { - spEngine.getProtocolProcessor().configure(); - params.setSpSigningCredential(CertificateUtil.toCredential(spEngine.getSigningCertificate())); - - final X509Certificate spEngineDecryptionCertificate = spEngine.getDecryptionCertificate(); - if (spEngineDecryptionCertificate != null) { - params.setSpEncryptionCredential(CertificateUtil.toCredential(spEngineDecryptionCertificate)); - } - } - - params.setIdpEngine(idpEngine); - params.setSpEngine(spEngine); - } - - public void addSPRole() throws EIDASSAMLEngineException { - try { - if (spSSODescriptor == null) { - spSSODescriptor = BuilderFactoryUtil.buildXmlObject(SPSSODescriptor.class); - } - } catch (IllegalAccessException iae) { - throw new EIDASSAMLEngineException(iae); - } catch (NoSuchFieldException nsfe) { - throw new EIDASSAMLEngineException(nsfe); - } - } - - public void addIDPRole() throws EIDASSAMLEngineException { - try { - if (idpSSODescriptor == null) { - idpSSODescriptor = BuilderFactoryUtil.buildXmlObject(IDPSSODescriptor.class); - } - } catch (IllegalAccessException iae) { - throw new EIDASSAMLEngineException(iae); - } catch (NoSuchFieldException nsfe) { - throw new EIDASSAMLEngineException(nsfe); - } - } - - private void generateDigest(Extensions eidasExtensions) throws EIDASSAMLEngineException { - if (!StringUtils.isEmpty(params.getDigestMethods())) { - Set signatureMethods = EIDASUtil.parseSemicolonSeparatedList(params.getDigestMethods()); - Set digestMethods = new HashSet(); - for (String signatureMethod : signatureMethods) { - - //BUGFIX: eIDAS implementation does not allow MGF1 signature schemes - digestMethods.add(signatureMethod); - //digestMethods.add(CertificateUtil.validateDigestAlgorithm(signatureMethod)); - } - for (String digestMethod : digestMethods) { - final DigestMethod dm = (DigestMethod) BuilderFactoryUtil.buildXmlObject(DigestMethod.DEF_ELEMENT_NAME); - if (dm != null) { - dm.setAlgorithm(digestMethod); - eidasExtensions.getUnknownXMLObjects().add(dm); - } else { - LOGGER.info("BUSINESS EXCEPTION error adding DigestMethod extension"); - } - } - } - - } - - private Extensions generateExtensions() throws EIDASSAMLEngineException { - /**FIXME: BuilderFactoryUtil.generateExtension() generates extensions from SAML2 request namespace - * but SAML2 metadata namespace is required - **/ - //Extensions eidasExtensions = BuilderFactoryUtil.generateExtension(); - - ExtensionsBuilder extensionsBuilder = new ExtensionsBuilder(); - Extensions eidasExtensions = extensionsBuilder.buildObject("urn:oasis:names:tc:SAML:2.0:metadata", "Extensions", "md"); - - if (params.getAssuranceLevel() != null) { - generateLoA(eidasExtensions); - } - if (!StringUtils.isEmpty(params.getSpType())) { - final SPType spTypeObj = (SPType) BuilderFactoryUtil.buildXmlObject(SPType.DEF_ELEMENT_NAME); - if (spTypeObj != null) { - spTypeObj.setSPType(params.getSpType()); - eidasExtensions.getUnknownXMLObjects().add(spTypeObj); - } else { - LOGGER.info("BUSINESS EXCEPTION error adding SPType extension"); - } - } - generateDigest(eidasExtensions); - - if (!StringUtils.isEmpty(params.getSigningMethods())) { - Set signMethods = EIDASUtil.parseSemicolonSeparatedList(params.getSigningMethods()); - for (String signMethod : signMethods) { - final SigningMethod sm = - (SigningMethod) BuilderFactoryUtil.buildXmlObject(SigningMethod.DEF_ELEMENT_NAME); - if (sm != null) { - sm.setAlgorithm(signMethod); - eidasExtensions.getUnknownXMLObjects().add(sm); - } else { - LOGGER.info("BUSINESS EXCEPTION error adding SigningMethod extension"); - } - } - } - return eidasExtensions; - } - - private void generateLoA(Extensions eidasExtensions) throws EIDASSAMLEngineException { - EntityAttributes loa = - (EntityAttributes) BuilderFactoryUtil.buildXmlObject(EntityAttributes.DEFAULT_ELEMENT_NAME); - Attribute loaAttrib = (Attribute) BuilderFactoryUtil.buildXmlObject(Attribute.DEFAULT_ELEMENT_NAME); - loaAttrib.setName(EidasConstants.LEVEL_OF_ASSURANCE_NAME); - loaAttrib.setNameFormat(Attribute.URI_REFERENCE); - XSStringBuilder stringBuilder = - (XSStringBuilder) Configuration.getBuilderFactory().getBuilder(XSString.TYPE_NAME); - XSString stringValue = stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, XSString.TYPE_NAME); - stringValue.setValue(params.getAssuranceLevel()); - loaAttrib.getAttributeValues().add(stringValue); - loa.getAttributes().add(loaAttrib); - eidasExtensions.getUnknownXMLObjects().add(loa); - - } - - private static final Set DEFAULT_BINDING = new HashSet() {{ - this.add(SAMLConstants.SAML2_POST_BINDING_URI); - }}; - - private void addAssertionConsumerService() throws EIDASSAMLEngineException { - int index = 0; - Set bindings = params.getProtocolBinding().isEmpty() ? DEFAULT_BINDING : params.getProtocolBinding(); - for (String binding : bindings) { - AssertionConsumerService asc = (AssertionConsumerService) BuilderFactoryUtil.buildXmlObject( - AssertionConsumerService.DEFAULT_ELEMENT_NAME); - asc.setLocation(params.getAssertionConsumerUrl()); - asc.setBinding(checkBinding(binding)); - asc.setIndex(index); - if (index == 0) { - asc.setIsDefault(true); - } - index++; - spSSODescriptor.getAssertionConsumerServices().add(asc); - } - } - - private String checkBinding(String binding) { - if (binding != null && (binding.equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI) || binding.equals( - SAMLConstants.SAML2_POST_BINDING_URI))) { - return binding; - } - return SAMLConstants.SAML2_POST_BINDING_URI; - } - - private DateTime getExpireDate() { - DateTime expiryDate = DateTime.now(); - expiryDate = - expiryDate.withFieldAdded(DurationFieldType.seconds(), (int) (getConfigParams().getValidityDuration())); - return expiryDate; - } - - private void generateSupportedAttributes(IDPSSODescriptor idpssoDescriptor, - ImmutableSortedSet> attributeDefinitions) - throws EIDASSAMLEngineException { - List attributes = idpssoDescriptor.getAttributes(); - for (AttributeDefinition attributeDefinition : attributeDefinitions) { - Attribute a = (Attribute) BuilderFactoryUtil.buildXmlObject(Attribute.DEFAULT_ELEMENT_NAME); - a.setName(attributeDefinition.getNameUri().toASCIIString()); - a.setFriendlyName(attributeDefinition.getFriendlyName()); - a.setNameFormat(Attribute.URI_REFERENCE); - attributes.add(a); - } - } - - public MetadataConfigParams getConfigParams() { - return params; - } - - public void setConfigParams(MetadataConfigParams params) { - this.params = params; - } - -} +///* +// * Copyright 2014 Federal Chancellery Austria +// * MOA-ID has been developed in a cooperation between BRZ, the Federal +// * Chancellery Austria - ICT staff unit, and Graz University of Technology. +// * +// * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by +// * the European Commission - subsequent versions of the EUPL (the "Licence"); +// * You may not use this work except in compliance with the Licence. +// * You may obtain a copy of the Licence at: +// * http://www.osor.eu/eupl/ +// * +// * Unless required by applicable law or agreed to in writing, software +// * distributed under the Licence is distributed on an "AS IS" basis, +// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// * See the Licence for the specific language governing permissions and +// * limitations under the Licence. +// * +// * This product combines work with different licenses. See the "NOTICE" text +// * file for details on the various modules and licenses. +// * The "NOTICE" text file is part of the distribution. Any derivative works +// * that you distribute must include a readable copy of the "NOTICE" text file. +// */ +//package at.gv.egovernment.moa.id.auth.modules.eidas.utils; +// +//import java.security.cert.X509Certificate; +//import java.util.ArrayList; +//import java.util.HashMap; +//import java.util.HashSet; +//import java.util.List; +//import java.util.Set; +// +//import org.apache.commons.lang.StringUtils; +//import org.joda.time.DateTime; +//import org.joda.time.DurationFieldType; +//import org.opensaml.Configuration; +//import org.opensaml.common.xml.SAMLConstants; +//import org.opensaml.saml2.common.Extensions; +//import org.opensaml.saml2.common.impl.ExtensionsBuilder; +//import org.opensaml.saml2.core.Attribute; +//import org.opensaml.saml2.core.AttributeValue; +//import org.opensaml.saml2.metadata.AssertionConsumerService; +//import org.opensaml.saml2.metadata.Company; +//import org.opensaml.saml2.metadata.ContactPerson; +//import org.opensaml.saml2.metadata.ContactPersonTypeEnumeration; +//import org.opensaml.saml2.metadata.EmailAddress; +//import org.opensaml.saml2.metadata.EncryptionMethod; +//import org.opensaml.saml2.metadata.EntitiesDescriptor; +//import org.opensaml.saml2.metadata.EntityDescriptor; +//import org.opensaml.saml2.metadata.GivenName; +//import org.opensaml.saml2.metadata.IDPSSODescriptor; +//import org.opensaml.saml2.metadata.KeyDescriptor; +//import org.opensaml.saml2.metadata.LocalizedString; +//import org.opensaml.saml2.metadata.NameIDFormat; +//import org.opensaml.saml2.metadata.Organization; +//import org.opensaml.saml2.metadata.OrganizationDisplayName; +//import org.opensaml.saml2.metadata.OrganizationName; +//import org.opensaml.saml2.metadata.OrganizationURL; +//import org.opensaml.saml2.metadata.SPSSODescriptor; +//import org.opensaml.saml2.metadata.SSODescriptor; +//import org.opensaml.saml2.metadata.SingleSignOnService; +//import org.opensaml.saml2.metadata.SurName; +//import org.opensaml.saml2.metadata.TelephoneNumber; +//import org.opensaml.samlext.saml2mdattr.EntityAttributes; +//import org.opensaml.xml.XMLObject; +//import org.opensaml.xml.XMLObjectBuilderFactory; +//import org.opensaml.xml.schema.XSString; +//import org.opensaml.xml.schema.impl.XSStringBuilder; +//import org.opensaml.xml.security.SecurityException; +//import org.opensaml.xml.security.credential.Credential; +//import org.opensaml.xml.security.credential.UsageType; +//import org.opensaml.xml.security.keyinfo.KeyInfoGenerator; +//import org.opensaml.xml.security.x509.X509KeyInfoGeneratorFactory; +//import org.opensaml.xml.signature.KeyInfo; +//import org.slf4j.Logger; +//import org.slf4j.LoggerFactory; +// +//import com.google.common.collect.ImmutableSortedSet; +//import com.google.common.collect.Ordering; +// +//import at.gv.egovernment.moa.id.commons.db.dao.config.deprecated.Contact; +//import at.gv.egovernment.moa.id.protocols.pvp2x.utils.SAML2Utils; +//import eu.eidas.auth.commons.EIDASUtil; +//import eu.eidas.auth.commons.EidasStringUtil; +//import eu.eidas.auth.commons.attribute.AttributeDefinition; +//import eu.eidas.auth.commons.protocol.impl.SamlNameIdFormat; +//import eu.eidas.auth.commons.xml.opensaml.OpenSamlHelper; +//import eu.eidas.auth.engine.ProtocolEngineI; +//import eu.eidas.auth.engine.core.SAMLExtensionFormat; +//import eu.eidas.auth.engine.core.eidas.DigestMethod; +//import eu.eidas.auth.engine.core.eidas.EidasConstants; +//import eu.eidas.auth.engine.core.eidas.SPType; +//import eu.eidas.auth.engine.core.eidas.SigningMethod; +//import eu.eidas.auth.engine.metadata.EntityDescriptorContainer; +//import eu.eidas.auth.engine.metadata.MetadataConfigParams; +//import eu.eidas.auth.engine.metadata.MetadataGenerator; +//import eu.eidas.auth.engine.metadata.MetadataSignerI; +//import eu.eidas.auth.engine.xml.opensaml.BuilderFactoryUtil; +//import eu.eidas.auth.engine.xml.opensaml.CertificateUtil; +//import eu.eidas.encryption.exception.UnmarshallException; +//import eu.eidas.engine.exceptions.EIDASSAMLEngineException; +//import eu.eidas.engine.exceptions.SAMLEngineException; +// +///** +// * @author tlenz +// * +// */ +//public class MOAeIDASMetadataGenerator extends MetadataGenerator { +// private static final Logger LOGGER = LoggerFactory.getLogger(MetadataGenerator.class.getName()); +// +// MetadataConfigParams params; +// +// XMLObjectBuilderFactory builderFactory = Configuration.getBuilderFactory(); +// +// SPSSODescriptor spSSODescriptor = null; +// +// IDPSSODescriptor idpSSODescriptor = null; +// +// private String ssoLocation; +// +// /** +// * @return a String representation of the entityDescriptr built based on the attributes previously set +// */ +// public String generateMetadata() throws EIDASSAMLEngineException { +// EntityDescriptor entityDescriptor; +// try { +// entityDescriptor = (EntityDescriptor) builderFactory.getBuilder(EntityDescriptor.DEFAULT_ELEMENT_NAME) +// .buildObject(EntityDescriptor.DEFAULT_ELEMENT_NAME); +// +// entityDescriptor.setEntityID(params.getEntityID()); +// entityDescriptor.setOrganization(buildOrganization()); +// +// /**FIXME: +// * HOTFIX: do not add empty contactPerson elements +// */ +// ContactPerson contactSupport = buildContact(ContactPersonTypeEnumeration.SUPPORT); +// if (contactSupport != null) +// entityDescriptor.getContactPersons().add(contactSupport); +// ContactPerson contactTech = buildContact(ContactPersonTypeEnumeration.TECHNICAL); +// if (contactTech != null) +// entityDescriptor.getContactPersons().add(contactTech); +// +// entityDescriptor.setValidUntil(getExpireDate()); +// +// X509KeyInfoGeneratorFactory keyInfoGeneratorFactory = new X509KeyInfoGeneratorFactory(); +// keyInfoGeneratorFactory.setEmitEntityCertificate(true); +// Extensions e = generateExtensions(); +// if (!e.getUnknownXMLObjects().isEmpty()) { +// entityDescriptor.setExtensions(e); +// } +// if (spSSODescriptor != null) { +// generateSPSSODescriptor(entityDescriptor, keyInfoGeneratorFactory); +// } +// if (idpSSODescriptor != null) { +// generateIDPSSODescriptor(entityDescriptor, keyInfoGeneratorFactory); +// } +// if (params.getSpEngine() != null) { +// ProtocolEngineI spEngine = params.getSpEngine(); +// ((MetadataSignerI) spEngine.getSigner()).signMetadata(entityDescriptor); +// } else if (params.getIdpEngine() != null) { +// ProtocolEngineI idpEngine = params.getIdpEngine(); +// ((MetadataSignerI) idpEngine.getSigner()).signMetadata(entityDescriptor); +// } +// return EidasStringUtil.toString(OpenSamlHelper.marshall(entityDescriptor, false)); +// } catch (Exception ex) { +// LOGGER.info("ERROR : SAMLException ", ex.getMessage()); +// LOGGER.debug("ERROR : SAMLException ", ex); +// throw new IllegalStateException(ex); +// } +// } +// +// private void generateSPSSODescriptor(final EntityDescriptor entityDescriptor, +// final X509KeyInfoGeneratorFactory keyInfoGeneratorFactory) +// throws org.opensaml.xml.security.SecurityException, IllegalAccessException, NoSuchFieldException, +// SAMLEngineException, EIDASSAMLEngineException { +// //the node has SP role +// spSSODescriptor.setWantAssertionsSigned(params.isWantAssertionsSigned()); +// spSSODescriptor.setAuthnRequestsSigned(true); +// +// +// /**FIXME: +// * "SP" + params.getEntityID()) is not a valid XML ID attribute value +// */ +// //spSSODescriptor.setID(idpSSODescriptor == null ? params.getEntityID() : ("SP" + params.getEntityID())); +// spSSODescriptor.setID(SAML2Utils.getSecureIdentifier()); +// +// +// if (params.getSPSignature() != null) { +// spSSODescriptor.setSignature(params.getSPSignature()); +// } +// if (params.getSpSigningCredential() != null) { +// spSSODescriptor.getKeyDescriptors() +// .add(getKeyDescriptor(keyInfoGeneratorFactory, params.getSpSigningCredential(), UsageType.SIGNING)); +// +// } else if (params.getSigningCredential() != null) { +// spSSODescriptor.getKeyDescriptors() +// .add(getKeyDescriptor(keyInfoGeneratorFactory, params.getSigningCredential(), UsageType.SIGNING)); +// } +// +// if (params.getSpEncryptionCredential() != null) { +// spSSODescriptor.getKeyDescriptors() +// .add(getKeyDescriptor(keyInfoGeneratorFactory, params.getSpEncryptionCredential(), +// UsageType.ENCRYPTION)); +// } else if (params.getEncryptionCredential() != null) { +// spSSODescriptor.getKeyDescriptors() +// .add(getKeyDescriptor(keyInfoGeneratorFactory, params.getEncryptionCredential(), UsageType.ENCRYPTION)); +// } +// spSSODescriptor.addSupportedProtocol(params.getSpSamlProtocol()); +// if (!StringUtils.isEmpty(params.getAssertionConsumerUrl())) { +// addAssertionConsumerService(); +// } +// +// //FIX: Austrian eIDAS node SP only needs persistent identifiers +// NameIDFormat persistentFormat = +// (NameIDFormat) BuilderFactoryUtil.buildXmlObject(NameIDFormat.DEFAULT_ELEMENT_NAME); +// persistentFormat.setFormat(SamlNameIdFormat.PERSISTENT.getNameIdFormat()); +// spSSODescriptor.getNameIDFormats().add(persistentFormat); +// +// /**FIXME: +// * Double signing of SPSSODescribtor is not required +// */ +//// if (params.getSpEngine() != null) { +//// ProtocolEngineI spEngine = params.getSpEngine(); +//// ((MetadataSignerI) spEngine.getSigner()).signMetadata(spSSODescriptor); +//// } +// +// entityDescriptor.getRoleDescriptors().add(spSSODescriptor); +// +// } +// +// private void fillIDPNameIDFormat(SSODescriptor ssoDescriptor) throws EIDASSAMLEngineException { +// NameIDFormat persistentFormat = +// (NameIDFormat) BuilderFactoryUtil.buildXmlObject(NameIDFormat.DEFAULT_ELEMENT_NAME); +// persistentFormat.setFormat(SamlNameIdFormat.PERSISTENT.getNameIdFormat()); +// ssoDescriptor.getNameIDFormats().add(persistentFormat); +// NameIDFormat transientFormat = +// (NameIDFormat) BuilderFactoryUtil.buildXmlObject(NameIDFormat.DEFAULT_ELEMENT_NAME); +// transientFormat.setFormat(SamlNameIdFormat.TRANSIENT.getNameIdFormat()); +// ssoDescriptor.getNameIDFormats().add(transientFormat); +// NameIDFormat unspecifiedFormat = +// (NameIDFormat) BuilderFactoryUtil.buildXmlObject(NameIDFormat.DEFAULT_ELEMENT_NAME); +// unspecifiedFormat.setFormat(SamlNameIdFormat.UNSPECIFIED.getNameIdFormat()); +// ssoDescriptor.getNameIDFormats().add(unspecifiedFormat); +// } +// +// private void generateIDPSSODescriptor(final EntityDescriptor entityDescriptor, +// final X509KeyInfoGeneratorFactory keyInfoGeneratorFactory) +// throws org.opensaml.xml.security.SecurityException, IllegalAccessException, NoSuchFieldException, +// SAMLEngineException, EIDASSAMLEngineException { +// //the node has IDP role +// idpSSODescriptor.setWantAuthnRequestsSigned(true); +// +// /**FIXME: +// * "IDP" + params.getEntityID()) is not a valid XML ID attribute value +// */ +// //idpSSODescriptor.setID(spSSODescriptor == null ? params.getEntityID() : ("IDP" + params.getEntityID())); +// idpSSODescriptor.setID(SAML2Utils.getSecureIdentifier()); +// +// if (params.getIDPSignature() != null) { +// idpSSODescriptor.setSignature(params.getIDPSignature()); +// } +// if (params.getIdpSigningCredential() != null) { +// idpSSODescriptor.getKeyDescriptors() +// .add(getKeyDescriptor(keyInfoGeneratorFactory, params.getIdpSigningCredential(), UsageType.SIGNING)); +// } else if (params.getSigningCredential() != null) { +// idpSSODescriptor.getKeyDescriptors() +// .add(getKeyDescriptor(keyInfoGeneratorFactory, params.getSigningCredential(), UsageType.SIGNING)); +// } +// if (params.getIdpEncryptionCredential() != null) { +// idpSSODescriptor.getKeyDescriptors() +// .add(getKeyDescriptor(keyInfoGeneratorFactory, params.getIdpEncryptionCredential(), +// UsageType.ENCRYPTION)); +// } else if (params.getEncryptionCredential() != null) { +// idpSSODescriptor.getKeyDescriptors() +// .add(getKeyDescriptor(keyInfoGeneratorFactory, params.getEncryptionCredential(), UsageType.ENCRYPTION)); +// } +// idpSSODescriptor.addSupportedProtocol(params.getIdpSamlProtocol()); +// +// //Austrian eIDAS node IDP can provided persistent, transient, and unspecified identifiers +// fillIDPNameIDFormat(idpSSODescriptor); +// +// +// if (params.getIdpEngine() != null) { +// if (params.getIdpEngine().getProtocolProcessor() != null +// && params.getIdpEngine().getProtocolProcessor().getFormat() == SAMLExtensionFormat.EIDAS10) { +// +// generateSupportedAttributes(idpSSODescriptor, getAllSupportedAttributes()); +// } +// +// +// /**FIXME: +// * Double signing of IDPSSODescribtor is not required +// */ +//// ProtocolEngineI idpEngine = params.getIdpEngine(); +//// ((MetadataSignerI) idpEngine.getSigner()).signMetadata(idpSSODescriptor); +// } +// +// idpSSODescriptor.getSingleSignOnServices().addAll(buildSingleSignOnServicesBindingLocations()); +// +// entityDescriptor.getRoleDescriptors().add(idpSSODescriptor); +// +// } +// +// /* FIX: Work-around to add eIDAS attributes, which could be provided from MOA-ID, to IDP metadata +// * If we restrict the eIDAS Engine attribute definitions then also additional incoming attributes can not processed any more. +// */ +// public ImmutableSortedSet> getAllSupportedAttributes() { +// ImmutableSortedSet.Builder> builder = +// new ImmutableSortedSet.Builder<>(Ordering.>natural()); +// +// for (String attr : eIDASAttributeBuilder.getAllProvideableeIDASAttributes()) { +// AttributeDefinition supAttr = params.getIdpEngine().getProtocolProcessor().getAttributeDefinitionNullable(attr); +// builder.add(supAttr); +// } +// +// return builder.build(); +// } +// +// private ArrayList buildSingleSignOnServicesBindingLocations() +// throws NoSuchFieldException, IllegalAccessException { +// ArrayList singleSignOnServices = new ArrayList(); +// +// HashMap bindingLocations = params.getProtocolBindingLocation(); +// for (String binding : bindingLocations.keySet()) { +// SingleSignOnService ssos = BuilderFactoryUtil.buildXmlObject(SingleSignOnService.class); +// ssos.setBinding(binding); +// ssos.setLocation(bindingLocations.get(binding)); +// singleSignOnServices.add(ssos); +// } +// +// return singleSignOnServices; +// } +// +// /** +// * @param metadata +// * @return an EntityDescriptor parsed from the given String or null +// */ +// // TODO (commented by donydgr) Move to a eu.eidas.auth.engine.metadata.MetadataUtil ? Throw an exception if the metadata is invalid instead of returning null ? +// public static EntityDescriptorContainer deserializeEntityDescriptor(String metadata) { +// EntityDescriptorContainer result = new EntityDescriptorContainer(); +// try { +// byte[] metaDataBytes = EidasStringUtil.getBytes(metadata); +// XMLObject obj = OpenSamlHelper.unmarshall(metaDataBytes); +// if (obj instanceof EntityDescriptor) { +// result.addEntityDescriptor((EntityDescriptor) obj, metaDataBytes); +// } else if (obj instanceof EntitiesDescriptor) { +// EntitiesDescriptor ed = (EntitiesDescriptor) obj; +// result.setEntitiesDescriptor(ed); +// result.getEntityDescriptors().addAll(((EntitiesDescriptor) obj).getEntityDescriptors()); +// result.setSerializedEntitesDescriptor(metaDataBytes); +// } +// } catch (UnmarshallException ue) { +// LOGGER.info("ERROR : unmarshalling error", ue.getMessage()); +// LOGGER.debug("ERROR : unmarshalling error", ue); +// } +// return result; +// } +// +// private KeyDescriptor getKeyDescriptor(X509KeyInfoGeneratorFactory keyInfoGeneratorFactory, +// Credential credential, +// UsageType usage) +// throws NoSuchFieldException, IllegalAccessException, SecurityException, EIDASSAMLEngineException { +// KeyDescriptor keyDescriptor = null; +// if (credential != null) { +// keyDescriptor = BuilderFactoryUtil.buildXmlObject(KeyDescriptor.class); +// KeyInfoGenerator keyInfoGenerator = keyInfoGeneratorFactory.newInstance(); +// +// KeyInfo keyInfo = keyInfoGenerator.generate(credential); +// keyDescriptor.setUse(usage); +// keyDescriptor.setKeyInfo(keyInfo); +// if (usage == UsageType.ENCRYPTION && params.getEncryptionAlgorithms() != null) { +// Set encryptionAlgos = EIDASUtil.parseSemicolonSeparatedList(params.getEncryptionAlgorithms()); +// for (String encryptionAlgo : encryptionAlgos) { +// EncryptionMethod em = +// (EncryptionMethod) BuilderFactoryUtil.buildXmlObject(EncryptionMethod.DEFAULT_ELEMENT_NAME); +// em.setAlgorithm(encryptionAlgo); +// keyDescriptor.getEncryptionMethods().add(em); +// } +// } +// +// } +// return keyDescriptor; +// } +// +// private Organization buildOrganization() { +// Organization organization = null; +// try { +// organization = BuilderFactoryUtil.buildXmlObject(Organization.class); +// +// /**FIXME: +// * set correct OrganizationName value if it is not fixed in next eIDAS node version +// */ +// OrganizationName orgName = BuilderFactoryUtil.buildXmlObject(OrganizationName.class); +// orgName.setName(new LocalizedString(params.getNodeUrl(), "en")); +// organization.getOrganizationNames().add(orgName); +// +// OrganizationDisplayName odn = BuilderFactoryUtil.buildXmlObject(OrganizationDisplayName.class); +// odn.setName(new LocalizedString(params.getCountryName(), "en")); +// organization.getDisplayNames().add(odn); +// OrganizationURL url = BuilderFactoryUtil.buildXmlObject(OrganizationURL.class); +// url.setURL(new LocalizedString(params.getNodeUrl(), "en")); +// organization.getURLs().add(url); +// } catch (IllegalAccessException iae) { +// LOGGER.info("ERROR : error generating the Organization: {}", iae.getMessage()); +// LOGGER.debug("ERROR : error generating the Organization: {}", iae); +// } catch (NoSuchFieldException nfe) { +// LOGGER.info("ERROR : error generating the Organization: {}", nfe.getMessage()); +// LOGGER.debug("ERROR : error generating the Organization: {}", nfe); +// } +// return organization; +// } +// +// private ContactPerson buildContact(ContactPersonTypeEnumeration contactType) { +// ContactPerson contact = null; +// try { +// Contact currentContact = null; +// if (contactType == ContactPersonTypeEnumeration.SUPPORT) { +// currentContact = params.getSupportContact(); +// } else if (contactType == ContactPersonTypeEnumeration.TECHNICAL) { +// currentContact = params.getTechnicalContact(); +// } else { +// LOGGER.error("ERROR: unsupported contact type"); +// } +// contact = BuilderFactoryUtil.buildXmlObject(ContactPerson.class); +// if (currentContact == null) { +// LOGGER.error("ERROR: cannot retrieve contact from the configuration"); +// return null; +// } +// +// EmailAddress emailAddressObj = BuilderFactoryUtil.buildXmlObject(EmailAddress.class); +// Company company = BuilderFactoryUtil.buildXmlObject(Company.class); +// GivenName givenName = BuilderFactoryUtil.buildXmlObject(GivenName.class); +// SurName surName = BuilderFactoryUtil.buildXmlObject(SurName.class); +// TelephoneNumber phoneNumber = BuilderFactoryUtil.buildXmlObject(TelephoneNumber.class); +// contact.setType(contactType); +// emailAddressObj.setAddress(currentContact.getEmail()); +// company.setName(currentContact.getCompany()); +// givenName.setName(currentContact.getGivenName()); +// surName.setName(currentContact.getSurName()); +// phoneNumber.setNumber(currentContact.getPhone()); +// +// populateContact(contact, currentContact, emailAddressObj, company, givenName, surName, phoneNumber); +// +// } catch (IllegalAccessException iae) { +// LOGGER.info("ERROR : error generating the Organization: {}", iae.getMessage()); +// LOGGER.debug("ERROR : error generating the Organization: {}", iae); +// } catch (NoSuchFieldException nfe) { +// LOGGER.info("ERROR : error generating the Organization: {}", nfe.getMessage()); +// LOGGER.debug("ERROR : error generating the Organization: {}", nfe); +// } +// return contact; +// } +// +// private void populateContact(ContactPerson contact, +// Contact currentContact, +// EmailAddress emailAddressObj, +// Company company, +// GivenName givenName, +// SurName surName, +// TelephoneNumber phoneNumber) { +// if (!StringUtils.isEmpty(currentContact.getEmail())) { +// contact.getEmailAddresses().add(emailAddressObj); +// } +// if (!StringUtils.isEmpty(currentContact.getCompany())) { +// contact.setCompany(company); +// } +// if (!StringUtils.isEmpty(currentContact.getGivenName())) { +// contact.setGivenName(givenName); +// } +// if (!StringUtils.isEmpty(currentContact.getSurName())) { +// contact.setSurName(surName); +// } +// if (!StringUtils.isEmpty(currentContact.getPhone())) { +// contact.getTelephoneNumbers().add(phoneNumber); +// } +// +// } +// +// /** +// * @param engine a EIDASSamlEngine from which signing and encryption information is extracted +// */ +// +// public void initialize(ProtocolEngineI engine) throws EIDASSAMLEngineException { +// +// X509Certificate decryptionCertificate = engine.getDecryptionCertificate(); +// if (null != decryptionCertificate) { +// params.setSpEncryptionCredential(CertificateUtil.toCredential(decryptionCertificate)); +// } +// params.setSigningCredential(CertificateUtil.toCredential(engine.getSigningCertificate())); +// params.setIdpEngine(engine); +// params.setSpEngine(engine); +// } +// +// /** +// * @param spEngine a EIDASSamlEngine for the +// */ +// +// public void initialize(ProtocolEngineI spEngine, ProtocolEngineI idpEngine) throws EIDASSAMLEngineException { +// if (idpEngine != null) { +// idpEngine.getProtocolProcessor().configure(); +// params.setIdpSigningCredential(CertificateUtil.toCredential(idpEngine.getSigningCertificate())); +// +// final X509Certificate idpEngineDecryptionCertificate = idpEngine.getDecryptionCertificate(); +// if (idpEngineDecryptionCertificate != null) { +// params.setIdpEncryptionCredential(CertificateUtil.toCredential(idpEngineDecryptionCertificate)); +// } +// +// } +// if (spEngine != null) { +// spEngine.getProtocolProcessor().configure(); +// params.setSpSigningCredential(CertificateUtil.toCredential(spEngine.getSigningCertificate())); +// +// final X509Certificate spEngineDecryptionCertificate = spEngine.getDecryptionCertificate(); +// if (spEngineDecryptionCertificate != null) { +// params.setSpEncryptionCredential(CertificateUtil.toCredential(spEngineDecryptionCertificate)); +// } +// } +// +// params.setIdpEngine(idpEngine); +// params.setSpEngine(spEngine); +// } +// +// public void addSPRole() throws EIDASSAMLEngineException { +// try { +// if (spSSODescriptor == null) { +// spSSODescriptor = BuilderFactoryUtil.buildXmlObject(SPSSODescriptor.class); +// } +// } catch (IllegalAccessException iae) { +// throw new EIDASSAMLEngineException(iae); +// } catch (NoSuchFieldException nsfe) { +// throw new EIDASSAMLEngineException(nsfe); +// } +// } +// +// public void addIDPRole() throws EIDASSAMLEngineException { +// try { +// if (idpSSODescriptor == null) { +// idpSSODescriptor = BuilderFactoryUtil.buildXmlObject(IDPSSODescriptor.class); +// } +// } catch (IllegalAccessException iae) { +// throw new EIDASSAMLEngineException(iae); +// } catch (NoSuchFieldException nsfe) { +// throw new EIDASSAMLEngineException(nsfe); +// } +// } +// +// private void generateDigest(Extensions eidasExtensions) throws EIDASSAMLEngineException { +// if (!StringUtils.isEmpty(params.getDigestMethods())) { +// Set signatureMethods = EIDASUtil.parseSemicolonSeparatedList(params.getDigestMethods()); +// Set digestMethods = new HashSet(); +// for (String signatureMethod : signatureMethods) { +// +// //BUGFIX: eIDAS implementation does not allow MGF1 signature schemes +// digestMethods.add(signatureMethod); +// //digestMethods.add(CertificateUtil.validateDigestAlgorithm(signatureMethod)); +// } +// for (String digestMethod : digestMethods) { +// final DigestMethod dm = (DigestMethod) BuilderFactoryUtil.buildXmlObject(DigestMethod.DEF_ELEMENT_NAME); +// if (dm != null) { +// dm.setAlgorithm(digestMethod); +// eidasExtensions.getUnknownXMLObjects().add(dm); +// } else { +// LOGGER.info("BUSINESS EXCEPTION error adding DigestMethod extension"); +// } +// } +// } +// +// } +// +// private Extensions generateExtensions() throws EIDASSAMLEngineException { +// /**FIXME: BuilderFactoryUtil.generateExtension() generates extensions from SAML2 request namespace +// * but SAML2 metadata namespace is required +// **/ +// //Extensions eidasExtensions = BuilderFactoryUtil.generateExtension(); +// +// ExtensionsBuilder extensionsBuilder = new ExtensionsBuilder(); +// Extensions eidasExtensions = extensionsBuilder.buildObject("urn:oasis:names:tc:SAML:2.0:metadata", "Extensions", "md"); +// +// if (params.getAssuranceLevel() != null) { +// generateLoA(eidasExtensions); +// } +// if (!StringUtils.isEmpty(params.getSpType())) { +// final SPType spTypeObj = (SPType) BuilderFactoryUtil.buildXmlObject(SPType.DEF_ELEMENT_NAME); +// if (spTypeObj != null) { +// spTypeObj.setSPType(params.getSpType()); +// eidasExtensions.getUnknownXMLObjects().add(spTypeObj); +// } else { +// LOGGER.info("BUSINESS EXCEPTION error adding SPType extension"); +// } +// } +// generateDigest(eidasExtensions); +// +// if (!StringUtils.isEmpty(params.getSigningMethods())) { +// Set signMethods = EIDASUtil.parseSemicolonSeparatedList(params.getSigningMethods()); +// for (String signMethod : signMethods) { +// final SigningMethod sm = +// (SigningMethod) BuilderFactoryUtil.buildXmlObject(SigningMethod.DEF_ELEMENT_NAME); +// if (sm != null) { +// sm.setAlgorithm(signMethod); +// eidasExtensions.getUnknownXMLObjects().add(sm); +// } else { +// LOGGER.info("BUSINESS EXCEPTION error adding SigningMethod extension"); +// } +// } +// } +// return eidasExtensions; +// } +// +// private void generateLoA(Extensions eidasExtensions) throws EIDASSAMLEngineException { +// EntityAttributes loa = +// (EntityAttributes) BuilderFactoryUtil.buildXmlObject(EntityAttributes.DEFAULT_ELEMENT_NAME); +// Attribute loaAttrib = (Attribute) BuilderFactoryUtil.buildXmlObject(Attribute.DEFAULT_ELEMENT_NAME); +// loaAttrib.setName(EidasConstants.LEVEL_OF_ASSURANCE_NAME); +// loaAttrib.setNameFormat(Attribute.URI_REFERENCE); +// XSStringBuilder stringBuilder = +// (XSStringBuilder) Configuration.getBuilderFactory().getBuilder(XSString.TYPE_NAME); +// XSString stringValue = stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, XSString.TYPE_NAME); +// stringValue.setValue(params.getAssuranceLevel()); +// loaAttrib.getAttributeValues().add(stringValue); +// loa.getAttributes().add(loaAttrib); +// eidasExtensions.getUnknownXMLObjects().add(loa); +// +// } +// +// private static final Set DEFAULT_BINDING = new HashSet() {{ +// this.add(SAMLConstants.SAML2_POST_BINDING_URI); +// }}; +// +// private void addAssertionConsumerService() throws EIDASSAMLEngineException { +// int index = 0; +// Set bindings = params.getProtocolBinding().isEmpty() ? DEFAULT_BINDING : params.getProtocolBinding(); +// for (String binding : bindings) { +// AssertionConsumerService asc = (AssertionConsumerService) BuilderFactoryUtil.buildXmlObject( +// AssertionConsumerService.DEFAULT_ELEMENT_NAME); +// asc.setLocation(params.getAssertionConsumerUrl()); +// asc.setBinding(checkBinding(binding)); +// asc.setIndex(index); +// if (index == 0) { +// asc.setIsDefault(true); +// } +// index++; +// spSSODescriptor.getAssertionConsumerServices().add(asc); +// } +// } +// +// private String checkBinding(String binding) { +// if (binding != null && (binding.equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI) || binding.equals( +// SAMLConstants.SAML2_POST_BINDING_URI))) { +// return binding; +// } +// return SAMLConstants.SAML2_POST_BINDING_URI; +// } +// +// private DateTime getExpireDate() { +// DateTime expiryDate = DateTime.now(); +// expiryDate = +// expiryDate.withFieldAdded(DurationFieldType.seconds(), (int) (getConfigParams().getValidityDuration())); +// return expiryDate; +// } +// +// private void generateSupportedAttributes(IDPSSODescriptor idpssoDescriptor, +// ImmutableSortedSet> attributeDefinitions) +// throws EIDASSAMLEngineException { +// List attributes = idpssoDescriptor.getAttributes(); +// for (AttributeDefinition attributeDefinition : attributeDefinitions) { +// Attribute a = (Attribute) BuilderFactoryUtil.buildXmlObject(Attribute.DEFAULT_ELEMENT_NAME); +// a.setName(attributeDefinition.getNameUri().toASCIIString()); +// a.setFriendlyName(attributeDefinition.getFriendlyName()); +// a.setNameFormat(Attribute.URI_REFERENCE); +// attributes.add(a); +// } +// } +// +// public MetadataConfigParams getConfigParams() { +// return params; +// } +// +// public void setConfigParams(MetadataConfigParams params) { +// this.params = params; +// } +// +//} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/NewMoaEidasMetadata.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/NewMoaEidasMetadata.java new file mode 100644 index 000000000..d0c003b31 --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/NewMoaEidasMetadata.java @@ -0,0 +1,602 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ +package at.gv.egovernment.moa.id.auth.modules.eidas.utils; + +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.lang.StringUtils; +import org.joda.time.DateTime; +import org.joda.time.DurationFieldType; +import org.opensaml.Configuration; +import org.opensaml.saml2.common.Extensions; +import org.opensaml.saml2.core.Attribute; +import org.opensaml.saml2.core.AttributeValue; +import org.opensaml.saml2.metadata.AssertionConsumerService; +import org.opensaml.saml2.metadata.Company; +import org.opensaml.saml2.metadata.ContactPerson; +import org.opensaml.saml2.metadata.ContactPersonTypeEnumeration; +import org.opensaml.saml2.metadata.EmailAddress; +import org.opensaml.saml2.metadata.EncryptionMethod; +import org.opensaml.saml2.metadata.EntityDescriptor; +import org.opensaml.saml2.metadata.GivenName; +import org.opensaml.saml2.metadata.IDPSSODescriptor; +import org.opensaml.saml2.metadata.KeyDescriptor; +import org.opensaml.saml2.metadata.LocalizedString; +import org.opensaml.saml2.metadata.NameIDFormat; +import org.opensaml.saml2.metadata.Organization; +import org.opensaml.saml2.metadata.OrganizationDisplayName; +import org.opensaml.saml2.metadata.OrganizationName; +import org.opensaml.saml2.metadata.OrganizationURL; +import org.opensaml.saml2.metadata.SPSSODescriptor; +import org.opensaml.saml2.metadata.SSODescriptor; +import org.opensaml.saml2.metadata.SingleSignOnService; +import org.opensaml.saml2.metadata.SurName; +import org.opensaml.saml2.metadata.TelephoneNumber; +import org.opensaml.samlext.saml2mdattr.EntityAttributes; +import org.opensaml.xml.XMLObjectBuilderFactory; +import org.opensaml.xml.schema.XSString; +import org.opensaml.xml.schema.impl.XSStringBuilder; +import org.opensaml.xml.security.SecurityException; +import org.opensaml.xml.security.credential.Credential; +import org.opensaml.xml.security.credential.UsageType; +import org.opensaml.xml.security.keyinfo.KeyInfoGenerator; +import org.opensaml.xml.security.x509.X509KeyInfoGeneratorFactory; +import org.opensaml.xml.signature.KeyInfo; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Ordering; + +import eu.eidas.auth.commons.EIDASUtil; +import eu.eidas.auth.commons.EidasStringUtil; +import eu.eidas.auth.commons.attribute.AttributeDefinition; +import eu.eidas.auth.commons.protocol.impl.SamlNameIdFormat; +import eu.eidas.auth.commons.xml.opensaml.OpenSamlHelper; +import eu.eidas.auth.engine.ProtocolEngineI; +import eu.eidas.auth.engine.core.SAMLExtensionFormat; +import eu.eidas.auth.engine.core.eidas.DigestMethod; +import eu.eidas.auth.engine.core.eidas.SPType; +import eu.eidas.auth.engine.core.eidas.SigningMethod; +import eu.eidas.auth.engine.metadata.ContactData; +import eu.eidas.auth.engine.metadata.EidasMetadata; +import eu.eidas.auth.engine.metadata.MetadataConfigParams; +import eu.eidas.auth.engine.metadata.MetadataSignerI; +import eu.eidas.auth.engine.xml.opensaml.BuilderFactoryUtil; +import eu.eidas.auth.engine.xml.opensaml.CertificateUtil; +import eu.eidas.engine.exceptions.EIDASSAMLEngineException; +import eu.eidas.engine.exceptions.SAMLEngineException; +import eu.eidas.util.Preconditions; + +/** + * @author tlenz + * + * MOA specific implementation of {@link EidasMetadata} + * This version fix some bugs
+ *
    + *
  • Does not add an encryption certificated to IDPSSODescriptor
  • + *
  • Only set provideable eIDAS attributes to IDPSSODescriptor
  • + *
  • SPSSODescriptor only requests 'persistent' subject nameIDs
  • + *
+ * + */ +public class NewMoaEidasMetadata { + private static final Logger LOGGER = LoggerFactory.getLogger(EidasMetadata.class.getName()); + private final String metadata; + private final String entityId; + private static final Set DEFAULT_BINDING = new HashSet() { + }; + + private NewMoaEidasMetadata( Generator generator) throws EIDASSAMLEngineException { + this.entityId = generator.entityId; + this.metadata = generator.metadata; + } + + public String getMetadata() { + return this.metadata; + } + + + public static Generator generator() { + return new Generator(); + } + + + public static Generator generator( Generator copy) { + return new Generator(copy); + } + + public static final class Generator { + private XMLObjectBuilderFactory builderFactory = Configuration.getBuilderFactory(); + private MetadataConfigParams params; + private SPSSODescriptor spSSODescriptor = null; + private IDPSSODescriptor idpSSODescriptor = null; + private String ssoLocation; + private String metadata; + private String entityId; + + public Generator() { + } + + public Generator( Generator copy) { + Preconditions.checkNotNull(copy, "copy"); + this.params = copy.params; + this.spSSODescriptor = copy.spSSODescriptor; + this.idpSSODescriptor = copy.idpSSODescriptor; + this.ssoLocation = copy.ssoLocation; + this.entityId = copy.entityId; + } + + + public NewMoaEidasMetadata build() throws EIDASSAMLEngineException { + initialize(); + this.entityId = this.params.getEntityID(); + this.metadata = generateMetadata(); + return new NewMoaEidasMetadata(this); + } + + public Generator configParams(MetadataConfigParams params) { + this.params = params; + return this; + } + + private void generateDigest(Extensions eidasExtensions) throws EIDASSAMLEngineException { + if (!(StringUtils.isEmpty(this.params.getDigestMethods()))) { + Set signatureMethods = EIDASUtil.parseSemicolonSeparatedList(this.params.getDigestMethods()); + Set digestMethods = new HashSet(); + for (String signatureMethod : signatureMethods) { + digestMethods.add(CertificateUtil.validateDigestAlgorithm(signatureMethod)); + } + for (String digestMethod : digestMethods) { + DigestMethod dm = (DigestMethod) BuilderFactoryUtil.buildXmlObject(DigestMethod.DEF_ELEMENT_NAME); + if (dm != null) { + dm.setAlgorithm(digestMethod); + eidasExtensions.getUnknownXMLObjects().add(dm); + } else { + NewMoaEidasMetadata.LOGGER.info("BUSINESS EXCEPTION error adding DigestMethod extension"); + } + } + } + } + + private Extensions generateExtensions() throws EIDASSAMLEngineException { + Extensions eidasExtensions = BuilderFactoryUtil.generateMetadataExtension(); + if (this.params.getAssuranceLevel() != null) { + generateLoA(eidasExtensions); + } + if (!(StringUtils.isEmpty(this.params.getSpType()))) { + SPType spTypeObj = (SPType) BuilderFactoryUtil.buildXmlObject(SPType.DEF_ELEMENT_NAME); + if (spTypeObj != null) { + spTypeObj.setSPType(this.params.getSpType()); + eidasExtensions.getUnknownXMLObjects().add(spTypeObj); + } else { + NewMoaEidasMetadata.LOGGER.info("BUSINESS EXCEPTION error adding SPType extension"); + } + } + generateDigest(eidasExtensions); + + if (!(StringUtils.isEmpty(this.params.getSigningMethods()))) { + Set signMethods = EIDASUtil.parseSemicolonSeparatedList(this.params.getDigestMethods()); + for (String signMethod : signMethods) { + SigningMethod sm = (SigningMethod) BuilderFactoryUtil + .buildXmlObject(SigningMethod.DEF_ELEMENT_NAME); + + if (sm != null) { + sm.setAlgorithm(signMethod); + eidasExtensions.getUnknownXMLObjects().add(sm); + } else { + NewMoaEidasMetadata.LOGGER.info("BUSINESS EXCEPTION error adding SigningMethod extension"); + } + } + } + return eidasExtensions; + } + + private void generateLoA(Extensions eidasExtensions) throws EIDASSAMLEngineException { + EntityAttributes loa = (EntityAttributes) BuilderFactoryUtil + .buildXmlObject(EntityAttributes.DEFAULT_ELEMENT_NAME); + + Attribute loaAttrib = (Attribute) BuilderFactoryUtil.buildXmlObject(Attribute.DEFAULT_ELEMENT_NAME); + loaAttrib.setName("urn:oasis:names:tc:SAML:attribute:assurance-certification"); + loaAttrib.setNameFormat("urn:oasis:names:tc:SAML:2.0:attrname-format:uri"); + XSStringBuilder stringBuilder = (XSStringBuilder) Configuration.getBuilderFactory() + .getBuilder(XSString.TYPE_NAME); + + XSString stringValue = (XSString) stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, + XSString.TYPE_NAME); + stringValue.setValue(this.params.getAssuranceLevel()); + loaAttrib.getAttributeValues().add(stringValue); + loa.getAttributes().add(loaAttrib); + eidasExtensions.getUnknownXMLObjects().add(loa); + } + + private void addAssertionConsumerService() throws EIDASSAMLEngineException { + int index = 0; + Set bindings = (this.params.getProtocolBinding().isEmpty()) ? NewMoaEidasMetadata.DEFAULT_BINDING + : this.params.getProtocolBinding(); + for (String binding : bindings) { + AssertionConsumerService asc = (AssertionConsumerService) BuilderFactoryUtil + .buildXmlObject(AssertionConsumerService.DEFAULT_ELEMENT_NAME); + + asc.setLocation(this.params.getAssertionConsumerUrl()); + asc.setBinding(checkBinding(binding)); + asc.setIndex(Integer.valueOf(index)); + if (index == 0) { + asc.setIsDefault(Boolean.valueOf(true)); + } + ++index; + this.spSSODescriptor.getAssertionConsumerServices().add(asc); + } + } + + private String checkBinding(String binding) { + if ((binding != null) && (((binding.equals("urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect")) + || (binding.equals("urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"))))) { + return binding; + } + return "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"; + } + + private DateTime getExpireDate() { + DateTime expiryDate = DateTime.now(); + expiryDate = expiryDate.withFieldAdded(DurationFieldType.seconds(), + (int) this.params.getValidityDuration()); + + return expiryDate; + } + + private void generateSupportedAttributes(IDPSSODescriptor idpssoDescriptor, + ImmutableSortedSet> attributeDefinitions) throws EIDASSAMLEngineException { + List attributes = idpssoDescriptor.getAttributes(); + for (AttributeDefinition attributeDefinition : attributeDefinitions) { + Attribute a = (Attribute) BuilderFactoryUtil.buildXmlObject(Attribute.DEFAULT_ELEMENT_NAME); + a.setName(attributeDefinition.getNameUri().toASCIIString()); + a.setFriendlyName(attributeDefinition.getFriendlyName()); + a.setNameFormat("urn:oasis:names:tc:SAML:2.0:attrname-format:uri"); + attributes.add(a); + } + } + + private void generateSPSSODescriptor(EntityDescriptor entityDescriptor, + X509KeyInfoGeneratorFactory keyInfoGeneratorFactory) throws SecurityException, IllegalAccessException, + NoSuchFieldException, SAMLEngineException, EIDASSAMLEngineException { + this.spSSODescriptor.setWantAssertionsSigned(Boolean.valueOf(this.params.isWantAssertionsSigned())); + this.spSSODescriptor.setAuthnRequestsSigned(Boolean.valueOf(true)); + if (this.params.getSpSignature() != null) { + this.spSSODescriptor.setSignature(this.params.getSpSignature()); + } + if (this.params.getSpSigningCredential() != null) { + this.spSSODescriptor.getKeyDescriptors().add(getKeyDescriptor(keyInfoGeneratorFactory, + this.params.getSpSigningCredential(), UsageType.SIGNING)); + } + + if (this.params.getSpEncryptionCredential() != null) { + this.spSSODescriptor.getKeyDescriptors().add(getKeyDescriptor(keyInfoGeneratorFactory, + this.params.getSpEncryptionCredential(), UsageType.ENCRYPTION)); + } + + this.spSSODescriptor.addSupportedProtocol(this.params.getSpSamlProtocol()); + if (!(StringUtils.isEmpty(this.params.getAssertionConsumerUrl()))) { + addAssertionConsumerService(); + } + + + //fillNameIDFormat(this.spSSODescriptor); + //FIX: Austrian eIDAS node SP only needs persistent identifiers + NameIDFormat persistentFormat = + (NameIDFormat) BuilderFactoryUtil.buildXmlObject(NameIDFormat.DEFAULT_ELEMENT_NAME); + persistentFormat.setFormat(SamlNameIdFormat.PERSISTENT.getNameIdFormat()); + spSSODescriptor.getNameIDFormats().add(persistentFormat); + + entityDescriptor.getRoleDescriptors().add(this.spSSODescriptor); + } + + private void fillNameIDFormatIDP(SSODescriptor ssoDescriptor) throws EIDASSAMLEngineException { + NameIDFormat persistentFormat = (NameIDFormat) BuilderFactoryUtil + .buildXmlObject(NameIDFormat.DEFAULT_ELEMENT_NAME); + + persistentFormat.setFormat(SamlNameIdFormat.PERSISTENT.getNameIdFormat()); + ssoDescriptor.getNameIDFormats().add(persistentFormat); + NameIDFormat transientFormat = (NameIDFormat) BuilderFactoryUtil + .buildXmlObject(NameIDFormat.DEFAULT_ELEMENT_NAME); + + transientFormat.setFormat(SamlNameIdFormat.TRANSIENT.getNameIdFormat()); + ssoDescriptor.getNameIDFormats().add(transientFormat); + NameIDFormat unspecifiedFormat = (NameIDFormat) BuilderFactoryUtil + .buildXmlObject(NameIDFormat.DEFAULT_ELEMENT_NAME); + + unspecifiedFormat.setFormat(SamlNameIdFormat.UNSPECIFIED.getNameIdFormat()); + ssoDescriptor.getNameIDFormats().add(unspecifiedFormat); + } + + private void generateIDPSSODescriptor(EntityDescriptor entityDescriptor, + X509KeyInfoGeneratorFactory keyInfoGeneratorFactory) throws SecurityException, IllegalAccessException, + NoSuchFieldException, SAMLEngineException, EIDASSAMLEngineException { + this.idpSSODescriptor.setWantAuthnRequestsSigned(Boolean.valueOf(true)); + if (this.params.getIdpSignature() != null) { + this.idpSSODescriptor.setSignature(this.params.getIdpSignature()); + } + if (this.params.getIdpSigningCredential() != null) { + this.idpSSODescriptor.getKeyDescriptors().add(getKeyDescriptor(keyInfoGeneratorFactory, + this.params.getIdpSigningCredential(), UsageType.SIGNING)); + } + + //INFO: IDP requires no encryption certificate +// if (this.params.getIdpEncryptionCredential() != null) { +// this.idpSSODescriptor.getKeyDescriptors().add(getKeyDescriptor(keyInfoGeneratorFactory, +// this.params.getIdpEncryptionCredential(), UsageType.ENCRYPTION)); +// } + + this.idpSSODescriptor.addSupportedProtocol(this.params.getIdpSamlProtocol()); + fillNameIDFormatIDP(this.idpSSODescriptor); + this.idpSSODescriptor.getSingleSignOnServices().addAll(buildSingleSignOnServicesBindingLocations()); + if ((this.params.getIdpEngine() != null) && (this.params.getIdpEngine().getProtocolProcessor() != null) + && (this.params.getIdpEngine().getProtocolProcessor().getFormat() == SAMLExtensionFormat.EIDAS10)) { + + /*TODO: Only a work-around to add eIDAS attributes, which could be provided from MOA-ID, to IDP metadata + * If we restrict the eIDAS Engine attribute definitions then also additional incoming attributes can not processed any more. + * + * INFO: Maybe, this code can be removed in a future version of the eIDAS engine + */ + generateSupportedAttributes(this.idpSSODescriptor, getAllSupportedAttributes()); + } + entityDescriptor.getRoleDescriptors().add(this.idpSSODescriptor); + } + + /* FIX: Work-around to add eIDAS attributes, which could be provided from MOA-ID, to IDP metadata + * If we restrict the eIDAS Engine attribute definitions then also additional incoming attributes can not processed any more. + */ + public ImmutableSortedSet> getAllSupportedAttributes() { + ImmutableSortedSet.Builder> builder = + new ImmutableSortedSet.Builder<>(Ordering.>natural()); + + for (String attr : eIDASAttributeBuilder.getAllProvideableeIDASAttributes()) { + AttributeDefinition supAttr = params.getIdpEngine().getProtocolProcessor().getAttributeDefinitionNullable(attr); + builder.add(supAttr); + } + + return builder.build(); + } + + private ArrayList buildSingleSignOnServicesBindingLocations() + throws NoSuchFieldException, IllegalAccessException { + ArrayList singleSignOnServices = new ArrayList(); + + HashMap bindingLocations = this.params.getProtocolBindingLocation(); + Iterator bindLocs = bindingLocations.entrySet().iterator(); + while (bindLocs.hasNext()) { + Map.Entry bindingLoc = (Map.Entry) bindLocs.next(); + SingleSignOnService ssos = (SingleSignOnService) BuilderFactoryUtil + .buildXmlObject(SingleSignOnService.class); + ssos.setBinding((String) bindingLoc.getKey()); + ssos.setLocation((String) bindingLoc.getValue()); + singleSignOnServices.add(ssos); + } + return singleSignOnServices; + } + + private KeyDescriptor getKeyDescriptor(X509KeyInfoGeneratorFactory keyInfoGeneratorFactory, + Credential credential, UsageType usage) + throws NoSuchFieldException, IllegalAccessException, SecurityException, EIDASSAMLEngineException { + KeyDescriptor keyDescriptor = null; + if (credential != null) { + keyDescriptor = (KeyDescriptor) BuilderFactoryUtil.buildXmlObject(KeyDescriptor.class); + KeyInfoGenerator keyInfoGenerator = keyInfoGeneratorFactory.newInstance(); + + KeyInfo keyInfo = keyInfoGenerator.generate(credential); + keyDescriptor.setUse(usage); + keyDescriptor.setKeyInfo(keyInfo); + if ((usage == UsageType.ENCRYPTION) && (this.params.getEncryptionAlgorithms() != null)) { + Set encryptionAlgos = EIDASUtil.parseSemicolonSeparatedList(this.params.getEncryptionAlgorithms()); + for (String encryptionAlgo : encryptionAlgos) { + EncryptionMethod em = (EncryptionMethod) BuilderFactoryUtil + .buildXmlObject(EncryptionMethod.DEFAULT_ELEMENT_NAME); + + em.setAlgorithm(encryptionAlgo); + keyDescriptor.getEncryptionMethods().add(em); + } + } + } + + return keyDescriptor; + } + + private Organization buildOrganization() { + Organization organization = null; + if (this.params.getOrganization() != null) { + try { + organization = (Organization) BuilderFactoryUtil.buildXmlObject(Organization.class); + OrganizationDisplayName odn = (OrganizationDisplayName) BuilderFactoryUtil + .buildXmlObject(OrganizationDisplayName.class); + odn.setName(new LocalizedString(this.params.getOrganization().getDisplayName(), "en")); + organization.getDisplayNames().add(odn); + OrganizationName on = (OrganizationName) BuilderFactoryUtil.buildXmlObject(OrganizationName.class); + on.setName(new LocalizedString(this.params.getOrganization().getName(), "en")); + organization.getOrganizationNames().add(on); + OrganizationURL url = (OrganizationURL) BuilderFactoryUtil.buildXmlObject(OrganizationURL.class); + url.setURL(new LocalizedString(this.params.getOrganization().getUrl(), "en")); + organization.getURLs().add(url); + } catch (IllegalAccessException iae) { + NewMoaEidasMetadata.LOGGER.info("ERROR : error generating the OrganizationData: {}", iae.getMessage()); + NewMoaEidasMetadata.LOGGER.debug("ERROR : error generating the OrganizationData: {}", iae); + } catch (NoSuchFieldException nfe) { + NewMoaEidasMetadata.LOGGER.info("ERROR : error generating the OrganizationData: {}", nfe.getMessage()); + NewMoaEidasMetadata.LOGGER.debug("ERROR : error generating the OrganizationData: {}", nfe); + } + } + return organization; + } + + private ContactPerson buildContact(ContactPersonTypeEnumeration contactType) { + ContactPerson contact = null; + try { + ContactData currentContact = null; + if (contactType == ContactPersonTypeEnumeration.SUPPORT) + currentContact = this.params.getSupportContact(); + else if (contactType == ContactPersonTypeEnumeration.TECHNICAL) + currentContact = this.params.getTechnicalContact(); + else { + NewMoaEidasMetadata.LOGGER.error("ERROR: unsupported contact type"); + } + contact = (ContactPerson) BuilderFactoryUtil.buildXmlObject(ContactPerson.class); + if (currentContact == null) { + NewMoaEidasMetadata.LOGGER.error("ERROR: cannot retrieve contact from the configuration"); + return contact; + } + + EmailAddress emailAddressObj = (EmailAddress) BuilderFactoryUtil.buildXmlObject(EmailAddress.class); + Company company = (Company) BuilderFactoryUtil.buildXmlObject(Company.class); + GivenName givenName = (GivenName) BuilderFactoryUtil.buildXmlObject(GivenName.class); + SurName surName = (SurName) BuilderFactoryUtil.buildXmlObject(SurName.class); + TelephoneNumber phoneNumber = (TelephoneNumber) BuilderFactoryUtil + .buildXmlObject(TelephoneNumber.class); + contact.setType(contactType); + emailAddressObj.setAddress(currentContact.getEmail()); + company.setName(currentContact.getCompany()); + givenName.setName(currentContact.getGivenName()); + surName.setName(currentContact.getSurName()); + phoneNumber.setNumber(currentContact.getPhone()); + + populateContact(contact, currentContact, emailAddressObj, company, givenName, surName, phoneNumber); + } catch (IllegalAccessException iae) { + NewMoaEidasMetadata.LOGGER.info("ERROR : error generating the OrganizationData: {}", iae.getMessage()); + NewMoaEidasMetadata.LOGGER.debug("ERROR : error generating the OrganizationData: {}", iae); + } catch (NoSuchFieldException nfe) { + NewMoaEidasMetadata.LOGGER.info("ERROR : error generating the OrganizationData: {}", nfe.getMessage()); + NewMoaEidasMetadata.LOGGER.debug("ERROR : error generating the OrganizationData: {}", nfe); + } + return contact; + } + + private void populateContact(ContactPerson contact, ContactData currentContact, EmailAddress emailAddressObj, + Company company, GivenName givenName, SurName surName, TelephoneNumber phoneNumber) { + if (!(StringUtils.isEmpty(currentContact.getEmail()))) { + contact.getEmailAddresses().add(emailAddressObj); + } + if (!(StringUtils.isEmpty(currentContact.getCompany()))) { + contact.setCompany(company); + } + if (!(StringUtils.isEmpty(currentContact.getGivenName()))) { + contact.setGivenName(givenName); + } + if (!(StringUtils.isEmpty(currentContact.getSurName()))) { + contact.setSurName(surName); + } + if (!(StringUtils.isEmpty(currentContact.getPhone()))) + contact.getTelephoneNumbers().add(phoneNumber); + } + + private String generateMetadata() throws EIDASSAMLEngineException { + try { + EntityDescriptor entityDescriptor = (EntityDescriptor) this.builderFactory + .getBuilder(EntityDescriptor.DEFAULT_ELEMENT_NAME) + .buildObject(EntityDescriptor.DEFAULT_ELEMENT_NAME); + + entityDescriptor.setEntityID(this.params.getEntityID()); + entityDescriptor.setOrganization(buildOrganization()); + entityDescriptor.getContactPersons().add(buildContact(ContactPersonTypeEnumeration.SUPPORT)); + entityDescriptor.getContactPersons().add(buildContact(ContactPersonTypeEnumeration.TECHNICAL)); + entityDescriptor.setValidUntil(getExpireDate()); + + X509KeyInfoGeneratorFactory keyInfoGeneratorFactory = new X509KeyInfoGeneratorFactory(); + keyInfoGeneratorFactory.setEmitEntityCertificate(true); + Extensions e = generateExtensions(); + if (!(e.getUnknownXMLObjects().isEmpty())) { + entityDescriptor.setExtensions(e); + } + if (this.spSSODescriptor != null) { + generateSPSSODescriptor(entityDescriptor, keyInfoGeneratorFactory); + } + if (this.idpSSODescriptor != null) { + generateIDPSSODescriptor(entityDescriptor, keyInfoGeneratorFactory); + } + if (this.params.getSpEngine() != null) { + ProtocolEngineI spEngine = this.params.getSpEngine(); + ((MetadataSignerI) spEngine.getSigner()).signMetadata(entityDescriptor); + } else if (this.params.getIdpEngine() != null) { + ProtocolEngineI idpEngine = this.params.getIdpEngine(); + ((MetadataSignerI) idpEngine.getSigner()).signMetadata(entityDescriptor); + } + return EidasStringUtil.toString(OpenSamlHelper.marshall(entityDescriptor, false)); + } catch (Exception ex) { + NewMoaEidasMetadata.LOGGER.info("ERROR : SAMLException ", ex.getMessage()); + NewMoaEidasMetadata.LOGGER.debug("ERROR : SAMLException ", ex); + throw new IllegalStateException(ex); + } + } + + private void initialize() throws EIDASSAMLEngineException { + ProtocolEngineI idpEngine = this.params.getIdpEngine(); + ProtocolEngineI spEngine = this.params.getSpEngine(); + MetadataConfigParams.Builder initParamBuilder = MetadataConfigParams.builder(this.params); + if (idpEngine != null) { + idpEngine.getProtocolProcessor().configure(); + initParamBuilder.idpSigningCredential(CertificateUtil.toCredential(idpEngine.getSigningCertificate())); + + X509Certificate idpEngineDecryptionCertificate = idpEngine.getDecryptionCertificate(); + if (idpEngineDecryptionCertificate != null) { + initParamBuilder + .idpEncryptionCredential(CertificateUtil.toCredential(idpEngineDecryptionCertificate)); + } + if (this.idpSSODescriptor == null) { + try { + this.idpSSODescriptor = ((IDPSSODescriptor) BuilderFactoryUtil + .buildXmlObject(IDPSSODescriptor.class)); + } catch (NoSuchFieldException e) { + throw new EIDASSAMLEngineException(e); + } catch (IllegalAccessException e) { + throw new EIDASSAMLEngineException(e); + } + } + } + if (spEngine != null) { + spEngine.getProtocolProcessor().configure(); + initParamBuilder.spSigningCredential(CertificateUtil.toCredential(spEngine.getSigningCertificate())); + + X509Certificate spEngineDecryptionCertificate = spEngine.getDecryptionCertificate(); + if (spEngineDecryptionCertificate != null) { + initParamBuilder + .spEncryptionCredential(CertificateUtil.toCredential(spEngineDecryptionCertificate)); + } + if (this.spSSODescriptor == null) { + try { + this.spSSODescriptor = ((SPSSODescriptor) BuilderFactoryUtil + .buildXmlObject(SPSSODescriptor.class)); + } catch (NoSuchFieldException e) { + throw new EIDASSAMLEngineException(e); + } catch (IllegalAccessException e) { + throw new EIDASSAMLEngineException(e); + } + } + } + this.params = initParamBuilder.build(); + } + } +} diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/SAMLEngineUtils.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/SAMLEngineUtils.java index 773e08ea9..d469ca28c 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/SAMLEngineUtils.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/SAMLEngineUtils.java @@ -88,7 +88,7 @@ public class SAMLEngineUtils { URL addAttrConfigUrl = new URL(FileUtils.makeAbsoluteURL( additionalAttributeConfigFile, AuthConfigurationProviderFactory.getInstance().getRootConfigFileDir())); - addAttrDefinitions = AttributeRegistries.fromFile(addAttrConfigUrl.getPath()); + addAttrDefinitions = AttributeRegistries.fromFile(addAttrConfigUrl.getPath(), null); } diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EIDASProtocol.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EIDASProtocol.java index 5d13e26e2..940b91b44 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EIDASProtocol.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EIDASProtocol.java @@ -330,7 +330,7 @@ public class EIDASProtocol extends AbstractAuthProtocolModulController { // - memorize service-provider type from eIDAS request String spType = null; if (eIDASSamlReq.getSpType() != null) - spType = eIDASSamlReq.getSpType().getValue(); + spType = eIDASSamlReq.getSpType(); if (MiscUtil.isEmpty(spType)) spType = MetadataUtil.getSPTypeFromMetadata(eIDASNodeEntityDesc); diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EidasMetaDataRequest.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EidasMetaDataRequest.java index df96bef12..bfe410fc2 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EidasMetaDataRequest.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EidasMetaDataRequest.java @@ -31,7 +31,7 @@ import org.springframework.stereotype.Service; import at.gv.egovernment.moa.id.auth.modules.eidas.Constants; import at.gv.egovernment.moa.id.auth.modules.eidas.engine.MOAeIDASChainingMetadataProvider; import at.gv.egovernment.moa.id.auth.modules.eidas.exceptions.EIDASEngineException; -import at.gv.egovernment.moa.id.auth.modules.eidas.utils.MOAeIDASMetadataGenerator; +import at.gv.egovernment.moa.id.auth.modules.eidas.utils.NewMoaEidasMetadata; import at.gv.egovernment.moa.id.auth.modules.eidas.utils.SAMLEngineUtils; import at.gv.egovernment.moa.id.commons.MOAIDAuthConstants; import at.gv.egovernment.moa.id.commons.api.AuthConfiguration; @@ -44,8 +44,10 @@ import at.gv.egovernment.moa.id.moduls.IAction; import at.gv.egovernment.moa.id.protocols.pvp2x.config.PVPConfiguration; import at.gv.egovernment.moa.logging.Logger; import eu.eidas.auth.engine.ProtocolEngineI; -import eu.eidas.auth.engine.metadata.Contact; +import eu.eidas.auth.engine.metadata.ContactData; import eu.eidas.auth.engine.metadata.MetadataConfigParams; +import eu.eidas.auth.engine.metadata.MetadataConfigParams.Builder; +import eu.eidas.auth.engine.metadata.OrganizationData; import eu.eidas.engine.exceptions.EIDASSAMLEngineException; @@ -119,22 +121,20 @@ public class EidasMetaDataRequest implements IAction { ProtocolEngineI engine = SAMLEngineUtils.createSAMLEngine(eIDASMetadataProvider); - MOAeIDASMetadataGenerator generator = new MOAeIDASMetadataGenerator(); - MetadataConfigParams mcp=new MetadataConfigParams(); - generator.setConfigParams(mcp); - generator.initialize(engine); - - mcp.setEntityID(metadata_url); - mcp.setAssertionConsumerUrl(sp_return_url); - mcp.getProtocolBindingLocation().put( + //configura metadata builder + Builder metadataConfigBuilder = MetadataConfigParams.builder(); + metadataConfigBuilder.entityID(metadata_url); + metadataConfigBuilder.assertionConsumerUrl(sp_return_url); + + metadataConfigBuilder.addProtocolBindingLocation( SAMLConstants.SAML2_POST_BINDING_URI, pendingReq.getAuthURL() + Constants.eIDAS_HTTP_ENDPOINT_IDP_COLLEAGUEREQUEST); //TODO: make it configurable - mcp.setAuthnRequestsSigned(true); - mcp.setWantAssertionsSigned(true); - mcp.setAssuranceLevel( + metadataConfigBuilder.authnRequestsSigned(true); + metadataConfigBuilder.wantAssertionsSigned(true); + metadataConfigBuilder.assuranceLevel( authConfig.getBasicMOAIDConfiguration( Constants.CONIG_PROPS_EIDAS_NODE_LoA, MOAIDAuthConstants.eIDAS_LOA_HIGH)); @@ -142,47 +142,71 @@ public class EidasMetaDataRequest implements IAction { //must be set in request, because it could be different for every online-application //mcp.setSpType(SPType.DEFAULT_VALUE); - mcp.setDigestMethods(Constants.METADATA_ALLOWED_ALG_DIGIST); - mcp.setSigningMethods(Constants.METADATA_ALLOWED_ALG_SIGN); - mcp.setEncryptionAlgorithms(Constants.METADATA_ALLOWED_ALG_ENCRYPT); + metadataConfigBuilder.digestMethods(Constants.METADATA_ALLOWED_ALG_DIGIST); + metadataConfigBuilder.signingMethods(Constants.METADATA_ALLOWED_ALG_SIGN); + metadataConfigBuilder.encryptionAlgorithms(Constants.METADATA_ALLOWED_ALG_ENCRYPT); //add organisation information from PVP metadata information Organization pvpOrganisation = null; try { pvpOrganisation = PVPConfiguration.getInstance().getIDPOrganisation(); - Contact technicalContact = new Contact(); + eu.eidas.auth.engine.metadata.ContactData.Builder technicalContact = ContactData.builder(); List contacts = PVPConfiguration.getInstance().getIDPContacts(); if (contacts != null && contacts.size() >= 1) { ContactPerson contact = contacts.get(0); - technicalContact.setGivenName(contact.getGivenName().getName()); - technicalContact.setSurName(contact.getSurName().getName()); + technicalContact.givenName(contact.getGivenName().getName()); + technicalContact.surName(contact.getSurName().getName()); if (!contact.getEmailAddresses().isEmpty()) - technicalContact.setEmail(contact.getEmailAddresses().get(0).getAddress()); + technicalContact.email(contact.getEmailAddresses().get(0).getAddress()); if (!contact.getTelephoneNumbers().isEmpty()) - technicalContact.setPhone(contact.getTelephoneNumbers().get(0).getNumber()); + technicalContact.phone(contact.getTelephoneNumbers().get(0).getNumber()); - mcp.setTechnicalContact(technicalContact ); + } if (pvpOrganisation != null) { - mcp.setNodeUrl(pvpOrganisation.getURLs().get(0).getURL().getLocalString()); - mcp.setCountryName(authConfig.getBasicMOAIDConfiguration(Constants.CONIG_PROPS_EIDAS_NODE_COUNTRY, "Austria")); - technicalContact.setCompany(pvpOrganisation.getDisplayNames().get(0).getName().getLocalString()); + eu.eidas.auth.engine.metadata.OrganizationData.Builder organizationConfig = OrganizationData.builder(); + organizationConfig.url(pvpOrganisation.getURLs().get(0).getURL().getLocalString()); + organizationConfig.name(authConfig.getBasicMOAIDConfiguration(Constants.CONIG_PROPS_EIDAS_NODE_COUNTRY, "Austria")); + //TODO: add display name and maybe update name + + + metadataConfigBuilder.organization(organizationConfig.build()); + + technicalContact.company(pvpOrganisation.getDisplayNames().get(0).getName().getLocalString()); } + + metadataConfigBuilder.technicalContact(technicalContact.build()); + + //TODO: add correct support contact + metadataConfigBuilder.supportContact(ContactData.builder(technicalContact.build()).build()); + } catch (ConfigurationException | NullPointerException e) { Logger.warn("Can not load Organisation or Contact from Configuration", e); } - - generator.addSPRole(); - generator.addIDPRole(); + + metadataConfigBuilder.idpEngine(engine); + metadataConfigBuilder.spEngine(engine); + + //TODO: +// MOAeIDASMetadataGenerator generator = new MOAeIDASMetadataGenerator(); +// generator.initialize(engine); +// generator.addSPRole(); +// generator.addIDPRole(); +// metadata = generator.generateMetadata(); + + //use own implementation that solves some problems in original implementation + NewMoaEidasMetadata.Generator generator = NewMoaEidasMetadata.generator(); + generator.configParams(metadataConfigBuilder.build()); + NewMoaEidasMetadata eidasMetadata = generator.build(); + metadata = eidasMetadata.getMetadata(); - metadata = generator.generateMetadata(); return metadata; } } diff --git a/id/server/modules/moa-id-module-ssoTransfer/src/test/java/at/gv/egiz/tests/Tests.java b/id/server/modules/moa-id-module-ssoTransfer/src/test/java/at/gv/egiz/tests/Tests.java index 0eb71ec92..fe859c7bc 100644 --- a/id/server/modules/moa-id-module-ssoTransfer/src/test/java/at/gv/egiz/tests/Tests.java +++ b/id/server/modules/moa-id-module-ssoTransfer/src/test/java/at/gv/egiz/tests/Tests.java @@ -22,20 +22,267 @@ */ package at.gv.egiz.tests; -import com.google.gson.JsonObject; +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.SecureRandom; +import java.security.Security; +import java.util.Arrays; +import java.util.Base64; +import java.util.List; -import at.gv.egovernment.moa.id.auth.modules.ssotransfer.SSOTransferConstants; +import org.bouncycastle.jce.ECNamedCurveTable; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec; +import org.bouncycastle.math.ec.ECPoint; +import org.bouncycastle.util.BigIntegers; + +import at.gv.egovernment.moa.id.data.Pair; +import at.gv.egovernment.moa.util.Base64Utils; +import iaik.security.random.SeedGenerator; /** * @author tlenz * */ public class Tests { + + //private static SecureRandom random = new SecureRandom(); + private static SecureRandom random; + private static SeedGenerator seedgenerator; + + static { + random = iaik.security.random.SHA256FIPS186Random.getDefault(); + seedgenerator = iaik.security.random.AutoSeedGenerator.getDefault(); + + if (seedgenerator.seedAvailable()) + random.setSeed(seedgenerator.getSeed()); + } + + + /** + * from https://trac.tools.ietf.org/id/draft-goldbe-vrf-00.htm + * Section: 5.4.1.1. ECVRF_hash_to_curve1 + * + * @param pubKey + * @param target + * @throws NoSuchProviderException + * @throws NoSuchAlgorithmException + */ + private static ECPoint ECVRFHashToCurce(ECPoint pubKey, String target) throws NoSuchAlgorithmException, NoSuchProviderException { + + MessageDigest md = MessageDigest.getInstance("SHA-256", BouncyCastleProvider.PROVIDER_NAME); + + + BigInteger ctr = BigInteger.ZERO; + + boolean runLoop = true; + byte[] comprPubKey = pubKey.getEncoded(true); + + while(runLoop) { + + + //byte[] ctrArray = BigEndianConversions.I2OSP(ctr, 4); + byte[] ctrArray = BigIntegers.asUnsignedByteArray(4, ctr); + + //calculate hash from target, pubKey, and ctr + byte[] hash = md.digest(ByteBuffer.wrap(new byte[target.getBytes().length + comprPubKey.length + ctrArray.length]) + .put(target.getBytes()).put(comprPubKey).put(ctrArray).array()); + + //first hash and check (EC Point x coordinate) + byte[] hashECPointCompr = ByteBuffer.wrap(new byte[1 + hash.length]) + .put((byte)0x02).put(hash).array(); + ECPoint hashECPoint = pubKey.getCurve().decodePoint(hashECPointCompr); + + if (hashECPoint.isValid()) { + //find valid EC point --> stop hash loop + return hashECPoint; + + } + + //second hash and check (EC Point y coordinate) + byte[] hashECPointCompr2 = ByteBuffer.wrap(new byte[1 + hash.length]) + .put((byte)0x03).put(hash).array(); + ECPoint hashECPoint2 = pubKey.getCurve().decodePoint(hashECPointCompr2); + if (hashECPoint2.isValid()) { + //find valid EC point --> stop hash loop + return hashECPoint; + + } + + ctr = ctr.add(BigInteger.ONE); + + } + return null; + + } + + + private static BigInteger ECVRFHashPoints(List points) throws NoSuchAlgorithmException, NoSuchProviderException { + + MessageDigest md = MessageDigest.getInstance("SHA-256", BouncyCastleProvider.PROVIDER_NAME); + + //create a array of encoded EC points + byte[] encPoints = null; + for (int i=0; i generatebPKAndProof(ECNamedCurveParameterSpec ecParamSpec, + BigInteger sourcePin, ECPoint pubKey, String target) throws NoSuchAlgorithmException, NoSuchProviderException { + + //generate bPK + ECPoint bPKECPointHash = ECVRFHashToCurce(pubKey, target); + ECPoint bPKECPoint = bPKECPointHash.multiply(sourcePin); + String bpK = Base64.getEncoder().encodeToString(bPKECPoint.getEncoded(true)); + + //generate proof + BigInteger k = new BigInteger(pubKey.getCurve().getFieldSize(), random); + //c = ECVRF_hash_points(g, h, g^x, h^x, g^k, h^k) + BigInteger c = ECVRFHashPoints(Arrays.asList(ecParamSpec.getG(), + bPKECPointHash, + pubKey, + bPKECPoint, + ecParamSpec.getG().multiply(k), + bPKECPointHash.multiply(k))); + + //s = k - c*sourcePin mod q //error in original document + BigInteger s = (k.subtract(c.multiply(sourcePin))).mod(ecParamSpec.getN()); + + //create arrays with 32 * 8bit array (8*32 = 256bit ==> prime order used of EC curve) + byte[] cArray = BigIntegers.asUnsignedByteArray(pubKey.getCurve().getFieldSize()/8, c); + byte[] sArray = BigIntegers.asUnsignedByteArray(pubKey.getCurve().getFieldSize()/8, s); + + byte[] proof = ByteBuffer.wrap(new byte[cArray.length + sArray.length]).put(cArray).put(sArray).array(); + + return Pair.newInstance(bpK, proof); + + } + + /** + * @param ecParamSpec + * @param pubkeyPoint + * @param first + * @param second + * @param target + * @return + * @throws NoSuchProviderException + * @throws NoSuchAlgorithmException + */ + private static boolean validatebPK(ECNamedCurveParameterSpec ecParamSpec, ECPoint pubKey, String bPK, + byte[] proof, String target) throws NoSuchAlgorithmException, NoSuchProviderException { + + System.out.println("Validate bPK:" + bPK); + + //decode bPK EC point + ECPoint bPKECPoint = pubKey.getCurve().decodePoint(Base64.getDecoder().decode(bPK)); + if (!bPKECPoint.isValid()) { + System.out.println("No valid bPK because its not point on EC curve"); + return false; + + } + + //decode c and s values from proof + byte[] cArray = Arrays.copyOfRange(proof, 0, (pubKey.getCurve().getFieldSize()/8)); + BigInteger c = BigIntegers.fromUnsignedByteArray(cArray); + + byte[] sArray = Arrays.copyOfRange(proof, pubKey.getCurve().getFieldSize()/8, proof.length); + BigInteger s = BigIntegers.fromUnsignedByteArray(sArray); + + ECPoint u = pubKey.multiply(c).add(ecParamSpec.getG().multiply(s)); + ECPoint h = ECVRFHashToCurce(pubKey, target); + ECPoint v = bPKECPoint.multiply(c).add(h.multiply(s)); + + BigInteger cSlash = ECVRFHashPoints(Arrays.asList( + ecParamSpec.getG(), + h, + pubKey, + bPKECPoint, + u, + v)); + + if (c.equals(cSlash)) { + System.out.println("Check successfull!!!!! \n"); + return true; + + } + + System.out.println("FAILED!!! \n" + + "c =" + c.toString(16) + "\n" + + "c'=" + cSlash.toString(16) + "\n"); + return false; + } + /** * @param args */ public static void main(String[] args) { + + + /* + * Test verifyable random functions with RSA + * + */ + try { + Security.addProvider(new BouncyCastleProvider()); + + String baseIDEnc = "gL/IWO/MtC+EQVLp2ie8GA=="; + byte[] baseID = Base64.getDecoder().decode(baseIDEnc); + + //use sourcePin as private key + BigInteger baseIDKeyInt = new BigInteger(Base64Utils.decode(baseIDEnc, false)); + + //calculate EC PublicKey from sourcePin + ECNamedCurveParameterSpec ecParamSpec = ECNamedCurveTable.getParameterSpec("secp256r1"); + ECPoint pubkeyPoint = ecParamSpec.getG().multiply(baseIDKeyInt); + + //generate bPK and proof + Pair bPKAndProof = + generatebPKAndProof(ecParamSpec, baseIDKeyInt, pubkeyPoint, "urn:publicid:gv.at:wbpk+FN+468924i"); + + System.out.println("bPK=" + bPKAndProof.getFirst() + "\n" + + "proof=" + Base64.getEncoder().encodeToString(bPKAndProof.getSecond()) + "\n"); + + //verify bPK with proof and publicKey + validatebPK(ecParamSpec, pubkeyPoint, bPKAndProof.getFirst(), + bPKAndProof.getSecond(), "urn:publicid:gv.at:wbpk+FN+468924i"); + + + + //verify bPK with proof and publicKey + validatebPK(ecParamSpec, pubkeyPoint, bPKAndProof.getFirst(), + bPKAndProof.getSecond(), "urn:publicid:gv.at:wbpk+FN+468925i"); + + validatebPK(ecParamSpec, pubkeyPoint.multiply(BigInteger.TEN), bPKAndProof.getFirst(), + bPKAndProof.getSecond(), "urn:publicid:gv.at:wbpk+FN+468924i"); + + validatebPK(ecParamSpec, pubkeyPoint, bPKAndProof.getFirst(), + bPKAndProof.getSecond(), "urn:publicid:gv.at:wbpk+XFN+468924i"); + + System.out.println("Finished..."); + + + } catch (Exception e) { + System.out.println("ERROR: " + e.getMessage()); + e.printStackTrace(); + + } + + // String json = // "{\"data\":{\"session\":{\"validTo\":\"2015-10-09T10:55:34.738Z\",\"entityID\":\"https://demo.egiz.gv.at/demoportal_moaid-2.0\",\"userID\":\"Thomas Georg Lenz\",\"sessionBlob\":\"PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c2FtbDJwOlJl\\u000ac3BvbnNlIHhtbG5zOnNhbWwycD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4w\\u000aOnByb3RvY29sIiBJRD0iXzQ5ZjgzMDIyZjRkZjFjODMyMDNlZGU1NTQxZDY1ODU4\\u000aIiBJc3N1ZUluc3RhbnQ9IjIwMTUtMTAtMDlUMTA6MzU6NTEuMDI0WiIgVmVyc2lv\\u000abj0iMi4wIj48c2FtbDI6SXNzdWVyIHhtbG5zOnNhbWwyPSJ1cm46b2FzaXM6bmFt\\u000aZXM6dGM6U0FNTDoyLjA6YXNzZXJ0aW9uIiBGb3JtYXQ9InVybjpvYXNpczpuYW1l\\u000aczp0YzpTQU1MOjIuMDpuYW1laWQtZm9ybWF0OmVudGl0eSI+aHR0cHM6Ly9kZW1v\\u000aLmVnaXouZ3YuYXQvZGVtb3BvcnRhbF9tb2FpZC0yLjA8L3NhbWwyOklzc3Vlcj48\\u000aZHM6U2lnbmF0dXJlIHhtbG5zOmRzPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5\\u000aL3htbGRzaWcjIj48ZHM6U2lnbmVkSW5mbz48ZHM6Q2Fub25pY2FsaXphdGlvbk1l\\u000adGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMTAveG1sLWV4\\u000aYy1jMTRuIyIvPjxkczpTaWduYXR1cmVNZXRob2QgQWxnb3JpdGhtPSJodHRwOi8v\\u000ad3d3LnczLm9yZy8yMDAxLzA0L3htbGRzaWctbW9yZSNyc2Etc2hhMjU2Ii8+PGRz\\u000aOlJlZmVyZW5jZSBVUkk9IiNfNDlmODMwMjJmNGRmMWM4MzIwM2VkZTU1NDFkNjU4\\u000aNTgiPjxkczpUcmFuc2Zvcm1zPjxkczpUcmFuc2Zvcm0gQWxnb3JpdGhtPSJodHRw\\u000aOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjZW52ZWxvcGVkLXNpZ25hdHVy\\u000aZSIvPjxkczpUcmFuc2Zvcm0gQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8y\\u000aMDAxLzEwL3htbC1leGMtYzE0biMiLz48L2RzOlRyYW5zZm9ybXM+PGRzOkRpZ2Vz\\u000adE1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMDQveG1s\\u000aZW5jI3NoYTI1NiIvPjxkczpEaWdlc3RWYWx1ZT44eE9qNmlYVzhIQzk5UGhETEZ0\\u000aOVp0M205VWliaVdrdHMzaWVQTS9CZlFZPTwvZHM6RGlnZXN0VmFsdWU+PC9kczpS\\u000aZWZlcmVuY2U+PC9kczpTaWduZWRJbmZvPjxkczpTaWduYXR1cmVWYWx1ZT5mNjM2\\u000aYjVBeGx6THdUL0I1SmdLdnhNN0haK1lEZGVldUdaRUlxc05KdHdiN05TVFhlbVFC\\u000aTExObDlJTk1aUW1Ybkx3ektCc0pra0tGTXl3MkpsNXVYcWlHWVBzMExTWTNiWTdj\\u000aTTZoeHpDaGdVVHRMWXlPcE9qemxxbE5CN2FKTVpZWU10Q2phcWNqSmxVM0wxTjBv\\u000aYUJ5QlRjaTRHdjd5TUJkdE9nRElHNVVpVEppVmVNOURZcUowZFVaZDNRcG1BK0Zm\\u000aUm10WFVzaVRzU0N0b3lWVHlXYTJWemJweTZxcDMwWkZSTU03LzU0Q0NWZHIvaDZW\\u000aTnZCQ1YydkFEMWdZaUg5VG41aTRSRmRWMFBKNTkrNS9HYXVUMm1HSVRUVmNreVk2\\u000aRlJQSjI2MUV0bmdScE8xK1FYRDZwQVZBM2V6Rm9ZbkkyQ2dYdHQ2K2EyTkV3cnBO\\u000aaHc9PTwvZHM6U2lnbmF0dXJlVmFsdWU+PGRzOktleUluZm8+PGRzOlg1MDlEYXRh\\u000aPjxkczpYNTA5Q2VydGlmaWNhdGU+TUlJREZUQ0NBZjBDQkZVQm5MNHdEUVlKS29a\\u000aSWh2Y05BUUVMQlFBd1R6RUxNQWtHQTFVRUJoTUNRVlF4RFRBTEJnTlZCQWNNQkVk\\u000aeQpZWG94RFRBTEJnTlZCQW9NQkVWSFNWb3hJakFnQmdOVkJBTU1HVTFQUVMxSlJD\\u000aQkpSRkFnS0ZSbGMzUXRWbVZ5YzJsdmJpa3dIaGNOCk1UVXdNekV5TVRRd016UXlX\\u000aaGNOTVRjeE1qQTFNVFF3TXpReVdqQlBNUXN3Q1FZRFZRUUdFd0pCVkRFTk1Bc0dB\\u000aMVVFQnd3RVIzSmgKZWpFTk1Bc0dBMVVFQ2d3RVJVZEpXakVpTUNBR0ExVUVBd3da\\u000aVFU5QkxVbEVJRWxFVUNBb1ZHVnpkQzFXWlhKemFXOXVLVENDQVNJdwpEUVlKS29a\\u000aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBSUp2MHFlOVVkdkZZU0w1STAy\\u000aR29rd0VWZnNJR2M3STdFaFZOT3hZCjltdFVlbm1ocU5yTHNMQkZnMUlpUGJrMElT\\u000aV2hPUndQeVZwL1AzK0d5R1AzMzlxWjY4VUNHVjM2MUUwUW03Y2pQZS9PMytyM0hB\\u000aTTIKWkJOOG9BWm9IbXBock5TNmZLZlk1OGt5Z3RyVWErWnlNellXVFRpUzMyU0NN\\u000aOEg1NWJsdUVGYmVaa3NuYlAwWTk0SWprZkpkZ3Z6bApNeHpybFN5b1YyeW1XQmp2\\u000aUzV3ZWxESGdiQ0t5anNqSWhUUmpKdS9vbEdKeWVuMDEvRXBJVnRTeURYTy8ySVMy\\u000adjJPOVVpRndBb3lCCllBalBubDNIeEsyQTU3N25SNjNNeGxnUDAvcytyODR1QnFP\\u000aQWxiNHFuYnBVN2x1NUd4bENQa1ptcFJvb0NRWVVSaW9DK3dqUzZsTUMKQXdFQUFU\\u000aQU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFCcU83a2txL2dSYWhBdnBzUWc1TExa\\u000aUk9HRnI5cElQcnlOOXhtSkdnUG83agpLTmw3cnM3Z05TMGxtdWx1WVdXbkpjd0FQ\\u000aYndGZWI5NTRWTUI5eDlwOVFFdzVSblhhbVVZOXFhMExnY1MvdC9XWDZ2SmtaUE5o\\u000aV3BoCjhiWHdoME12bHNiZnJ2RFRKcjhjakgzcWZ4SVRwN3BhM3hiMXFFN3N1UmZm\\u000aVlVkRFhhd2lYWG5XSi9XSnIrdHdWVkhIRXFuWnoxbEEKclNETHhNOHNDakc4RGVK\\u000adzh2blF5NW1QR3JHVlRCYmE0dXBjOFVUWTFuUFY5VTJHQkpWWXVBa29WUmpiVGxO\\u000adnJMNUpxTnF5cEtjRwpiZWpqV3hncnpaa2VRZVUyaEZjanVubWd3R1ordWcyZnE0\\u000aa0trUWZ0d2NxZUpUenl6Qm9vMitPbzRUbWZic2gvb254UFdBPT08L2RzOlg1MDlD\\u000aZXJ0aWZpY2F0ZT48L2RzOlg1MDlEYXRhPjwvZHM6S2V5SW5mbz48L2RzOlNpZ25h\\u000adHVyZT48c2FtbDJwOlN0YXR1cz48c2FtbDJwOlN0YXR1c0NvZGUgVmFsdWU9InVy\\u000abjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpzdGF0dXM6U3VjY2VzcyIvPjwvc2Ft\\u000abDJwOlN0YXR1cz48c2FtbDI6RW5jcnlwdGVkQXNzZXJ0aW9uIHhtbG5zOnNhbWwy\\u000aPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXNzZXJ0aW9uIj48eGVuYzpF\\u000abmNyeXB0ZWREYXRhIHhtbG5zOnhlbmM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEv\\u000aMDQveG1sZW5jIyIgSWQ9Il8zZmQzNTg5MmU5YThlYWNiOGUwOGYyODBhODNmY2I3\\u000aNCIgVHlwZT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8wNC94bWxlbmMjRWxlbWVu\\u000adCI+PHhlbmM6RW5jcnlwdGlvbk1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cu\\u000adzMub3JnLzIwMDEvMDQveG1sZW5jI2FlczEyOC1jYmMiIHhtbG5zOnhlbmM9Imh0\\u000adHA6Ly93d3cudzMub3JnLzIwMDEvMDQveG1sZW5jIyIvPjxkczpLZXlJbmZvIHht\\u000abG5zOmRzPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjIj48ZHM6\\u000aUmV0cmlldmFsTWV0aG9kIFR5cGU9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMDQv\\u000aeG1sZW5jI0VuY3J5cHRlZEtleSIgVVJJPSIjX2E3NDBjZjA5MTViZDE1MmRiNzRk\\u000aMDNjZDQ1NzUyMTM3Ii8+PC9kczpLZXlJbmZvPjx4ZW5jOkNpcGhlckRhdGEgeG1s\\u000abnM6eGVuYz0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8wNC94bWxlbmMjIj48eGVu\\u000aYzpDaXBoZXJWYWx1ZT43R0hKY0NYYXlzME1pY2ZvYXc3cnFNeTZ1bUQyd0FEQmtH\\u000aOThKclJ2UUdMczJneTBOSWFvSlM2SWM1Z254RXBNcUZHZ2ZLNHBBWGxRUVh3K1h6\\u000aY0RNaURhY2tqS1c5ckptNTh0b3dxNmFEbWVIU2doTTRDVzhVb1RaQlFlazVvY1dU\\u000aNmRIT3hPVzFFOFUrTXprTEg1NjVXUWxLYkdHamVSSGNzb3V3MXFuNk1XS01EU0V4\\u000aRzQrZERzSVliMk1uaEc3OEh6TDNZK0VMVG40TWd1cXF4bmpTVC9rRkpTK2dSMm93\\u000aL2tHVHN2ZnlLWmdMZUVYTzRpVHlNM2RzRk1Ma05rM0tHSHVHRmhGeUxycUR3Sko2\\u000aTmY5OVZRTmlDZDlrUnpxOE1qWklpNWQ0SjlhSmgvRk93NFI0TXAveCsvaC9hYVhk\\u000acDVyQ09CcUVaZ3FZUXlqT2FIMlAxRHR0VkU5SU5xS2w1OXh5ZTJaR0tDd1p5TTgr\\u000adWdSRnVDbTJ2RFlRSUx1T1RTaVNpbkJsNnBpLzFYRktNL1lVbTRJMXA0N21LNDlE\\u000aeW9Ia0lBaUk0NjQ2ejNJZ0tMZTBnaFlQYUlvTHhNcDE1ZE83RHRDQzhsZnYwb3Qx\\u000aYVdvTy9TcGpXaVJiOEhCaXdleGxTdHV4dVorUGVqZDlzUS9neTNFOFp1MWJXRmsv\\u000aTDVrNTZqUTAxZStIcEdORW5FSml1c1RHWldMRTZBY1lvd1NCeEZidC9RUHhGTlhh\\u000aRFBmcmlGRGZMK1RuMngyc2Rwb1RlMVpZM1JnZXo5b1Y2QUtJQWZZWC8zMllsT0NK\\u000aTlV5Myt4OU5teHljOFdKNTBjQ2RTd3ZuNTRBc1Z2U0xYRi9sbHIwQmh2cWRWQ0dP\\u000aTy82WGQvdEtpblFPWHdmeEJBMDVJZSs5MFZhU1J2NGFrRXJ4dHhrekVIeXB3R01j\\u000aVStieTYybDh5Q2Qya01vMnpQK0hmZ3NkTU9Ba2hrbDUvRXB2NVdiZGMzeElKRUhK\\u000aOVptbitUdGNWR2FiOHNPeSsyblIwQWNwZDJxeVIvNkNUd3dodk5nbXF1TldiLy9P\\u000aaGNxdDMvR1dPZkt0NGhrRnQxeGE2allTSXVoNHVWMHJqcENvK21ISFk4ZFZaTGZ6\\u000aNE9oR3dpNGd4bDBlV3hYUWF3UGpMWlI5RzdpQ1NCT2ZPV0d5bkdydklKSFF2VUJD\\u000aUVUwLzh3eFNxRmkxcVdQVXN2ZWtxV012SFpYTGdMMGZNYUJEa1ZZTm5YT2FlalJU\\u000aVHNZeENZc1AxYlRCNDY5ZytjRkQ1bEd0VDErTi95S3dKOUJTTGhaenhzRVhVWkhG\\u000aQ1NJTk1vTTlnaVF4TzI2L0VLUENMdXp2bnkyN3orNWdxcURkVzhlVUFCUmEyeFpp\\u000aZ204YmFkSllGWE12dkdDUVBjcmhiN3c1c3dSL2I1TXNiZXV4L3F0RFQ4R3VWcUNG\\u000ac3JDL3E4MlZpOUd5b3VCWDdGRk50UWhWRDFFVWtCQWZTYWE2UDhKU2VPdE01TVYr\\u000aV21OcGJrQ0U2M2hZS2g4cHN5MUdMdlRZRVA3Slh3TmNIWXlmS3FtdXk5S1dOVmUv\\u000aT2JPZTM5azhCWE5tWE9DejRJay93ajZqaU1DWEsrblhwdTBZQ1Z2ODJXM1BMeGlR\\u000ab1liRURMMjNHV05sNFFHQzQ1dE45WUpwK29CSGZjRStmUHk4S1FrOFBDK0s4SFFr\\u000aK21HV3NkTVUxUitTaTExY0VYdzBKTTRTczJzTWpZb05tQXd6a2RvRHliVkdnK3B3\\u000aSnUrUmFmaEJrSmpIU0FMeVQ3Y1R3dncrOW56S1BIdUhvWW5wSTRLQSt6U2xrYkUr\\u000aQ0dSbzd1MUxXVFl0cGZTYnFtd1NjYVlxU01WaTZ5QVdkRnoyS001LzlkVHB6alBY\\u000aNGhOZW82ZE96eVRHUkFMVnVUZi9Ma0RqaElqWGJ0Z2J6ZnU0aWdrWXg3Q2d1RnZ0\\u000abVlkTEhNSE4yRnFOTkN1UWk2bTJLUGYyUG5HdmVrSFVwMEJYZ3NEOUhkZFJtNHBF\\u000aYnE1VEsvV05RTzBuS0g0M1owOU9NcWZZbHEybk5mTi84ZnMyTjc1c2h5NmtheElK\\u000aL0FZUlNkOUU5M1VjOWJmV2FIeUwraWNNTE1GelU5MytMZlhpREkyWDVScEVtSnFB\\u000aSUMwVlJ0NWtXdnlVNGVlWnhOdE8zWUtxUnN2YVo0dzhnZ0I3dkxheFFKUWtnMWhs\\u000acVAzQzhDQW5HWnkrdDR5alRVejA1LzlpQi9HRk1DdDNteEpPajUvaVdTOTZRRW54\\u000aVm8wdVYvYzhDRFd6OERHYzYvLzFBQzBWS0VmaGRsSmFGOHg1NzVHNTI2dHoxTVln\\u000aMHBaaitNRzlsRUxkNm12d011cVE3VEVZdEYyN0Y4Vk5iQ29ZWXUraDhJTCs1Y0Vr\\u000acnBjakUzMm9MbWx4ZjBjNnpZaDhwa3FsVTR2RHlQeGJJcm50WkFPcThMUzk5Vktr\\u000aUjdFL0w5OXNoZUxqd3I0bTJtQ21CZ2tGZVZhVG1Ca00vSFd4MUNEYjlIcVM0N25Z\\u000aSWJaQW94ampIK0QzR1EweXlES1R3aG1iSXNHMFQ4Ry96eStRR0pmNkg2MXg0M1ZJ\\u000abkNwRkxmQjNiQUNJay9OanhCeFdheGVwMXRMMTRBSlRMZlROTnA3K3dCT016THhm\\u000aSHBjSUlWT2dOeXJ6UVk2Q0x6eXlDM2hub212a0hadFJ2WmpBYmExMmJSZ3VoTUJX\\u000aOFZiaHNKMmZaekZ3TXp0amxzSEkwREc2OGs1R0JDemFDQVRPZlBBWnFPN2lEQ2JC\\u000aMW1KSEgzTmxvQ2xuL1pTY01rOUVqTERyTndIWHZ4ZEFTRFMwS1RrZVNxS21TZm54\\u000aUWlSQ3lLNjhrSEZNc0trUTRYS3JKZjZGMWRreVYrL3NFdzRsS1FFYW52VkVVSTJx\\u000aUExDSVZnVWVkQVFaeFAxeVp0dDA1V2ptSUdhZnhQMldWNE9PYm8vTGFaamo0YW9H\\u000aNjNxWkdGdGJyWUt4TVc1Ny9RL0ZkbjN5TUpmUlkxVGU0UCtpTTNHUjNRcU1QeVMr\\u000aZWZDMlRDNk9pYithOHZ2SVcxTFI4OGV0V2t4SHJzMEpVcVRpM1ZEY1lXNEcwUHVn\\u000aTFhsZEYwWVVod1RLaTlOUjZmWTNXMXBTQUlNRGYvbk5hcVBIUnNLVWU4Z3pwcll3\\u000aOUdWLytXWjkrNUxEQnYzWmNKVGlLcllOcG1TUHl2MDdvNWx2Mmo2MXJtaEdsQVJ6\\u000aODJzWlhDUzA5K0lyaUpmVUg4bko0NFRFUk8wb1pBd2RxZWhEVmQ2YzZIV044dlJI\\u000aeEVJZWhmeXJhUVZ5Q3FlQkU3d3VPcXZFSmI2R0Urc1czNlBMNGFwT2ZMcCtISU5V\\u000aMkRhbVBrWHJWdVV6Q1dWZWlXaGIzSVBPNk81WkNENVp5RHlQc0liV3RuMnc2bnpI\\u000aU3EyUDhOdmZZRHhTcmM2YlU1aThoQ0FOZFdudTliMWJia0tXTXhUazhjamQ2bk8w\\u000aN1FtZnJFZGJCQ1ptWmh6blJ2cmRYMDdHSXo0YXhtM0Z2UHBtazBvZ1FaUzBieDd1\\u000aSWhFTDhGR2ozQW9lSllpOFB0dFA3NmFKaTRPYndlUmhlWVE2L1p0NHlPcXhabUph\\u000aMEFnTjJieTlpT1kyZ2tLclg2RTY1UWMzM2Q0Wlh6aXdDc1BsNVlGQmY1bG9ndGFE\\u000acXFVU0p1TEQyUEMyZEZNeDAzaGkrcUpSNmxPZ3ozYjJrM3dUTjhGTjJBMnQycHo2\\u000aNjJSS3IyQVRuSklrZkdndHVTcFlicGdab05VL0pheS9qMERWMXRaMkFmODdsUU43\\u000ablphdmF0YjVvbWx1Vi8yU3ZVYk5rbW1HdUhrTmFjQnNuTjIza3FOTEFrMmZvQ0xZ\\u000aT1FZaG5uQm1ZTUdYdS9tOG9haXdmUzhxRlZyYllTc0tKSWpLU1ptaFZBU3hXa01t\\u000aT3lSVUcrYkhlQ3RuT3ljWmlhb25XZElvbFUzT2hJMi9JTkpDSUNzQjJNWGhtNkpa\\u000aOEFtcUlqSGQxR1JvVElRTDlFNlBUbGF1MVB5dDhmbnl0aERac2R5L1dmMGU2SGRy\\u000abXJleXBiaE5PYTh4NUF4ckhaRGxjemttaUJyOHEzU0dYU1JVWUt0YndGUk5DZjFX\\u000aYkVyci9uN3duVmlZOENiS0wxZGJzMzlDNmtaVGlUVE16b1NCaFVKcW0xeUpHZUM3\\u000aT2pLRC9VNUFUK2NmOXV3c2hVNDhKZHNUNDVOWjJnOFNkL21xODlyTFBRVTAxNG9h\\u000aNUhRbzV4bEkvaldPUE1MM0R3MmtFVkkyZ3R0eG5HamExVk9aZVlJSGM1amJWenBx\\u000aSDMxZ2ZNYkZLTTNqNHRyaFVKVmFyM29ZWndZWnR6c1IyNmg5NWxIVlNNQzJ2MGZH\\u000aZ29nRFBMYzROejFtelNUNzQ2OFFTeVJJTzZtOTVTOTV3UWxiWXFoRzhMLzJsZW13\\u000aS1JNMUNUSGVUeVFjQlRNb1lrdU9wNFRZaVlXZzAwMjlXelNyMkhCUlFXZm9zNzc0\\u000abWlBbjBEQWtxcysybzFOdUtjTmU3cVFmY1Vnd2lHNzZJK1FZcEZPbkJSeUh1d1px\\u000acHR1WmpKTWV5amtZWC9wRE5VRkxYMmNWRGgrT0FSRUFaT3NBSVlPbnU1OWZnRHVB\\u000aM2RrOVNHMGVIclNXVkR2dU5yTDJiWm1hUXJxQmZ4bXRaall2Q0lmdDFXcmQvUkFo\\u000aeUs4bEFMNWFJZ1pZajV4WjBtV2hXd2hHTFBKNXBnMXpCeHFmZ2hyNzhRSVBQNGEr\\u000aT3YwU21qTmdwbVNQQzc4d2RPNVh6N3NzeU1mUC9uWkhVZEVJbUNqUGVMM2lJalhn\\u000aVVY1SjRnckc1cWY3WHZJQzBpNGZBdktnZ01LYXFYWGRZclBCZzFWQm5vR3BNVWZm\\u000aUU9Wa29pcjNjL2hYNWxlN1BoQlp3OVlWaEN3UDg2VU1oeGFmclp6blQzbnVUV0lL\\u000aRUMxOWVXNDJSak0wU3V2dWlreFY0L1o1UUhxcUtvNmRPamJZL1NKR1FQU1VWczdx\\u000aU3owNks1bTF4Q3Mybk51QWR2V0lVS25leE1oRUxsRTVGbGJQVkZ0Nkc3d0dLNUxv\\u000aNkV0bVZPWnE3bXpxWS84RHdUMnpUbm1UbW1lZEdIZDlUUWRCM1gxU2orUHlFRDFr\\u000aT01kYUkvVlVOWCt4bFlmUkd4RHF1Rlp2YmdTVSsxaDJHSjQ5M3VsYk9KVmJjeXpP\\u000acFFmTks5UTNNNEp2V1hPRVUzT2NPVkMwbkZGUUVEbDFEZ2h2Wldoeit6dy9sZkg1\\u000ab3UvV0kvOUpmKzB6ajJNNDE2YytTbkpneCtaSVZUd0lTQlhDc1NicW5tbG54ZE9a\\u000aSnhrbElrWXlwMGVNZ0RkTzZscHdTbXlLc21KMFVaM3ZPUFRuQXBxdTROeUxLOXUw\\u000aNzFZRVB5WUhWWnRXOUdITm5LM3RvZm5TVVZpMSsrVEx5bDY4aWRqS0RCa2hFVWNy\\u000aeWU5QkFhak1VR3VSc00zQ0RNZGlrSEd6eDVwM2RoeGIwczJTcGhxREhFLzJMSlBj\\u000aU2kyQkFVWTA1WXNDUytiWDgzb3VESDRXSmozZDM0NFFTcnFwQnk0ek11UHJPdWdT\\u000aRWo1a1Z1MjhMT1RKcnZPL09jbmxoTUYvWndielBRVVI5TmhUV21GOFV4WEE0Vjd0\\u000aK2RQNDVnTFFvYnNnVHY4MXkrUDVuTnZ2alNtL2I3aVpzZXJhV0VaSHlwNGo0bis0\\u000aSWJJTmZrcXVYVG9pcTlyVHFvZFdyemN4TkJCdDBOMTFtRWpwM2ZvYjJiVFU5QkVn\\u000aalZlTHRFSGxqVFJJV1ovK1IvTHpTaXRJL241MlNvTUI4RlVZc2lXQzF3WVBOY2lR\\u000aeEJYdFRNZ2xLY3NiVkUyN0dxSEtueDVkMlVHSE9iQVVIOGpKdmVaZUNRYVExWEZu\\u000aZ1ROdXVNcVBzdERaSFNPQ1pWVXhJajkyQTFUNkVTaFo3cTY1VjhadFEwNmdYb3dB\\u000ab1ZDc2xjaUJEZHZwUEZCL2FlV3hjbHc3cFZBQ2xBQ0ltVmhMRG5YNEtGWUNIUE5n\\u000ac2FLYU9ua05SVVZSc0Vad1pad2x2bklRdXpBRW9KTmtremd3Z2dtdHgyL09EK0NY\\u000aaVlLdE5pT3hHWDlKZEUveVovUk9qbHlSNUo5Q09CL3JNMmdlY0FWZ2dmcXQ4RUc5\\u000aQUJNVHZhN3RpVHF0M2Q4V2NjREV5S1F0aTlySXhoNWZVWGkwbTFrNlJGblNEajZN\\u000aRXZBNjBULzRJY1hPUERtYTJ2WU9EZ0NBS21IMWtnNzY1dDI4MFNtcFNnMFlnQUpV\\u000adkphSXlsdGY4VWhPWE9DdE1RaXdEVlVjSCtDTHBiSXh4a25Pa2Q5K1hYNDU3bm1j\\u000adjc5S0FMbzRjbEp0RWpqS3h1aUIrK1ZwNGxzRVlENkI2RVkzMjJiNmk4ZExkQkJu\\u000aZ0JKdXUwMDFBSjlWUFlIWlJBeDNRNDh4UU11dUp3WWdZNmlEV3hzY3lheDdENkxu\\u000aS2czbnBaYmhmVzRlc1l2NjBqdkhTNDZwem1lSlVKVmNmVUFFeWQ4azFXK3huWHFi\\u000aN1dxRFRGNXhaTHgrZHRlQk90UmR5U1NIR2cvcUhQNEFvZ3VSc2JvVFU5OEJqOWIy\\u000aSysvSEU0ZTIveDk2bkg3VzRlU0tGRGsxaWxoNk9EckE5SE1uQ3h1QWFxZXB5VTFo\\u000aRGNsZjNEVXdGamdRR3Vnb29TNHpITElvbnpxVFVjcTRzcC9SZ0YzRk00TGxpL2NC\\u000aTDdSbTYxMHZBYUprcmZWRG1JZGZ0NHd0SVVTVysyRGtoQ2lyb21LL3RLckZUbC96\\u000aTk5HMGpBTmo3SjllRWhQaE9kdzFVMHRlN3ZlakVwMGRLb09NRkRTSTNaWWJieWNs\\u000aUHJ3bkw2ZW5ocmlrWHBzNXVMVDRqT2p2NFVJSVRQSjJLN2NjWUZmQzJqZlJKMDJt\\u000aRk1wRkc0MGplcEdHblJ3cTNRZzQ5NEVhVGN2dG13SVdjbEtlVmJ5MW04N3ppc3hV\\u000aT1JWQXlnUlljU3ZvVXdxdWMzakx3MGJYVzBmUkFYVTMyaFlWUWZJUTFwY01pSDRW\\u000aRStyL3AvRGpJWS9zYngzVm1Hc1dCTGhNOFIweElVWm5YSnJyejk3S09GQkE3NGdu\\u000abVluSXJQa3lmT2hQUGVFSDQyL2VpRHUybWRWL2U0UGEzS1VLZFhjeUo4cm85MjZC\\u000aSTF3aGk4Q2h4SVVtZzZNaDQrOHg4YjhjS3VpZWtFaWZ2cU52aG1KQ3hlaThTYSty\\u000aUVpQMEx2aHAvekEwRWIxY1d0ek1VTUlFdUhJcDREa1hhY1dNZ2NuV3U0L2d4Q3Vi\\u000aMXhHaE5xWDI5U2p4SUhHeFdJRkNvQU9lVkNkL2xiSlFPS3V4R3BnMmR2RjdDUUhM\\u000adGYxQVRQaEQxRVNsNnR5dTg0dndWcTk3U3lTcktweWJxenZydHdSTFhwb0kyUHA5\\u000aWEd6S3BtaXIrT1Fva1dwSUhZTElzU0hmditDWjJDaW5aaUpEWWdtL3ZyOUZWdFpv\\u000aU0JKN2puYlA2TkpKYTlidGd0QzBFZnRTcGxPSHpicm1nMVR4M3gvNytTRlRGc1Yz\\u000ac29yejcwTWxIZE43M1ZjK3B2a080LzM4ZVF6SEFqdkhlTVgybGFMT1Ntb2Z5Nmpw\\u000aOVBWV1RMWFJmSi9kOTRNbmhaK1lvQ04vSVl2cWsyTzlPcDlzWnY3SGNHdHBMYlFr\\u000aUkh3WG9od1VpSFRxVkhEQVVxbEszUkdHdDk3ZHZJY1owSUdlRFJROGtULytCUTZ4\\u000aVGpxN3pvQmpMaGwxT2M1cUxkYldUM2FLbVNoL09Tb1BPWlR1OG5QYXROdjFIektB\\u000aOUE1UGovaDlRTCtGeldrMXM1MzZYRzJHaXRwckdiMERQaUF6MzVaU3dCdVpGbFBs\\u000acmpZbVhONWdsOEpwSVh5c3R0SFdqNTVDSWlJbHYrSnhGOXBGaSs3M0pHNkNUVkNa\\u000acVEzM2p0SmVWLzVsTnFJcGhUUUQzcS9rbDlGNTNPMGRQa0UwM01lWDJkS3p2VkV3\\u000aYldDbnNQMm5rVEhDMDloVDdkSjhVU3NMaElCZnZ4dFJ3VG1nbnRoSE5seVZrR1pK\\u000aWmxVa21QMXFHZU9tdmU4RjgzYlpSMTBNK1dyZmV1ZEJYbVJZUHgzRW5FVHkvK3B4\\u000ad1d1cVczd21WV2JxM3BsRnJCNFd3eUZuc2NNUkNuSjNuQlJQK3ZCYXprb0hpVXk0\\u000aOEJPVkJvMm0zWFRUVmRVcWRmbksvUlpXc0RhaEZKYnpWQ3cvSTlJM0lySkFRa1N2\\u000aSG1qUkRsMW5aeDdCaHU2WTR2ODZKa2dmSk5UMzRocHlYQkRaUW1YNEh0NXZacnlj\\u000aVTE0cTJ4SWVoUGNVRmMyZmQxMmNkWERvazVrSi94ZWF4Zi9RbDMxRUFzQ0xDR0x6\\u000aWFI1b24zL1VaMGtGNEx2Y3IvTVJ0VjhJWWdjbDUxcHlMbjhnbnh0ZmErVmZpMStD\\u000aQ1kySXFJUkpTeGtmWGgvTlhWam5MeFZaem42d1pGWFZ4UXBBUE03TjR5V1pkT242\\u000aMFlXK3ZCTmRGVExKZkxnTVA2UDBZWFZNRlpUVFRtVE04eWRGd2tFZDF2OUUrcysx\\u000abDRzNU50Z01yaEZVTkwxOVo0VVdSNVE5YTQwSXhhK3hBbVdPTElDQjFuUmxkZHll\\u000aeDdmVmtYSDE2WUV3RnZDVlpTWGRZODdaK3JENmZCbEtKL2lvandRbnZPV1hPS1dj\\u000aTmdEemc2bFoyYnVtREJpM1FlSllkNnU1Vk1ybGIxYk81dGZMa0xvM25ZMXROL2ZO\\u000aWmF2NDY1MnM3K3dRaFh4eVZ5bzMzQmY5d0VxaGxwN2pmcnRmY011MS9zcEhwQ1ls\\u000aOWF0MFdVbTR4UytaN3gybkgxUWtJanh4U3RaUVNmQ21LbzdiN0pGUFloVGg4QktR\\u000aQ2U2VnYzemYrUlloMkVNR0d5RXFMdWIvdG1Od2FnRGdGYXk3L3NEaTNTNnUzSmpy\\u000aQlE2b2R2ZkNrU240cytaYUdqb1I2VkNtUHF3VlorTXZQRXBKQURRUm5HS1ludlhs\\u000aUVU4dUo2MWpZNXpUUE0rUExaYytCNmdpdzZlZmNIenp6ejJJUmRPWEJGNFE0RVFO\\u000aek55ZVFrYTNoUUk5TWtFbnc0SDlZV2ljTkV4NVpKazR2NmJzeVl6T0Y3dVdiMi84\\u000ab09NNnRhWHdOWWFTSWRyQ1JxVGl3MFZOR3hVOFgvNGNwU05lSmNsRGRxVXg4TEli\\u000aazdxaCtXYkkwSnNLdHE4d3c0VDlvN3Q5MExpSTl6RWdjUisrbGVvajhxV2Z1aDZp\\u000aL0tzRGtTNFBHMmw1VFBqUWhWMHJaY1FhdW1hRzU3dXc1eUl0RnM4QVVlbTF6VWxN\\u000adjcydDhSalNnTWdBOWdWdGNCcUNlWjIwZzk4ZThWc1FwQ1Y2SDlpSWRIalZTZkFK\\u000aMG5MbnJud1BucWJPZFdvL2xJYXR4dnFSb2hwWFhyR2loSjBPMEpNNkw4Y0JJQlFl\\u000adkZxSE9qVlRIVGFpSVhxL2dQcThVUzZtcTNIS0U0S2tUR09zMXdzV0ZFRmpKei9m\\u000aeUxmYk5sVklIQ0tRTjhjb1lKdFNlSEZUMTNZdm8reTNBa1VRb2hWTno4RXg1TUJ4\\u000aMkYyeGtoZ1BLdDl2aUlLWXdGRlpOQVU5ZzZDWVRjOVY3WmtHTFRBT1JqQ0IwNTVm\\u000aTnBkSGVvRWpydElMU1lTMjZhV3Q1TmtnVVJsV2dEalpTN0t1UWZuY1dXMjQrOVND\\u000ab0xCV1VzSXhVTWVsZTEwZDhwbGxsZ01YRUR6aWEyc0NEemxvOFdOa2h2M3hZZjFT\\u000aYXBjMk8wTnVmS1p2NEVWMXhzMy8wblIrMHc1b3ZHa1UyY0ZXMnpBVUcwaGU2azhZ\\u000aTjR6QVJRallUem4wajNVa3F3Vkl5dGZuUlRYUzZEODZkTVAxaG9ETWY3N0duMzI1\\u000aRUpKM1lGanpFbEFjaURlRkgvMS93Wm4ybm1ST3hDU0p5SUxXNnJiTUdyV1JDSjc0\\u000acFNyNkZUcXRsVFdNWkExL01ZeEk4a0JlWThHaEQwWGZ4bWdPaTI5NjcxSHI4SFVL\\u000admNLYk8zWUxHemhqaEtCWklEWkNwanlUY3p6VkN0MzVOcXpGUnMzM1Z6Y0VDU0I0\\u000aWmVZSCtxS1RDZEhPK0J6VE9HOVh1am5HazJVb3BkdldldkovdVh0SDlmTGhUQjJn\\u000abUQ4azZSa3FSTnUzUjZlN1NJTlhpejFuc3pqMmo3QTlDNXE1c1VkNThjVTdNRlg3\\u000aMGkzVHJ0NUh0MloyaFNQY1hPNTU3Sk1LRVdVcFZxS1l0WmhQTWN1a2hHb0hVekJJ\\u000aTUV1bDlSYXo5c3M2RndsZHo1QmFvWDZJcW5yd2pGaXRnTjVnWUZpaHJEbmlXUVhx\\u000aaXQyTWtETmFROTIvWUlHRlJGMm5iaUdPWDFUamxqQ0VDMU1DQUwvSWxqRU4vM0ZZ\\u000aOEJLWElpdkU0RTNNRGt0eXJzWC8zOGxUZjN0YXZOVk5aVnFESHMxUmxuRUM4WEZI\\u000aUVFNZXdXWjF1RlZVM3pGOVVlcXYzcTRxZUVQREZ5R2lFN2dEV2tNbW5xYnZURiti\\u000aVysyMVJzTHBpbUphS3dqclRMTWtoaCt4Z3hvK0paWml4c1NxNXgrK0NCdEtOQ3BC\\u000aNkUwTnc1SUlnUnVzL1kwMmxQMWZ5OFVsdjU4eHBNUjVETWRmeHZ1cjlPd05BTTY4\\u000aNi9zeUwrbHVwVDZhNnRhOC82YlNPVWphNGRtMXgxWHBhWkZ1Qy9EMGxkU3ZPdTZv\\u000aQmhVVUtuYXhCalpIeXl1UkNQVlpwY0tFZDFkemE4THdJcjY0Q09CeDl5OVJSZTlV\\u000abmN0L1dIanlQSnZsWWx5OTBLZ3JFOWYzMUdkeEFoK2hHVjZrbWhIUUhpRnB2ckRi\\u000ad05tRWdhNzZlTHRLdHpGNDh2cDdZYWdOaERjZlBCbzVJMW5pOGxZcFFDeW50WVB1\\u000aWnRIZWNyNWFDQS9RSWpGZGdUSkRXaGJkVW5rbzgwa1RGRTZ1czByVUNuLzNrcUhK\\u000aeC9Lc2R3S0VxQ2ZzNUVhWW5LbVhvQW5HZWZYYVdoNkU4Mm96Tk5qVzhBSUpJcENJ\\u000aTTZrbkFjWi9mVGVjL255azZmTisyeXltaWFXWkN1ai9lS0piMWZFK1MybWxpbjEw\\u000aM05oWmtNTkJHUDNqTUF2K0l6dGVuMFFDazdySmJ6cmlTeUFGYml2aFB4bjZqQnlx\\u000aaTJKRU4xd29KOU9MYWwvaURBSXNoRXUwQ0dwQ1JMRnUralI5WE9zdktjNTdGVVo0\\u000aSHo2Z0ZBYjEvNkszWnNWSXRGZElvL2tmbHJ3Ukttc0hTN2VuZ1phOVdYSVFHb3FR\\u000ablVaYXVjb1JRVWEwa0haN0UwK0szNVpZa1lZVFRwUHJuQWhQbTJBaXdmRUpzVmQy\\u000aM0tnWUx6QW9tQ0J4Wm41RkFFd3lMVUZSTFAzOGRZR0hlZnhyR1FiemNzOUtpS3I2\\u000aQUFVRTVSM09yMHdDTUpLV1Jmbk9QZjZQdmtIdlcrSFZhZStBeEV6ZXF4TzFwOVVU\\u000ab1hoVlcra3NoRzZ3QTIvL2NkR3Y0MHJrVEh1RFE1c0Y3Q0ZGckNodlJZb0MwMzJJ\\u000aS01qa1Rzc2FKS3dqSEZlSVMzc0tjbmdEL05WR3pTK2xOcGNwSDg2RkJGQTd5SzNq\\u000aVzBrZHRmblRaLzlSSkNXblV0YXFpM3BFaWFlak0rbEs2cXRuVzdVcHhVV2o2K21x\\u000aZzNtb1FCUjZ2Yk4vS0xrSkpsUjhsUWNnQzVLamJLOUd4YXpGZlErbGprcGhKRHBi\\u000adERUZThEZ3dBSmlraGlZT1YzYjU4aTA5MXo1V0JZSmFtQmxodS80MzF2TWIwNFJw\\u000aVVdOSlphSEdySWdCNXNwdFV2SVNxSDRBYm9xN0ZNMVZjZS9pOXpMcXlGVVhXZEhl\\u000aaDBmTWFKUVp1S3NPNDFmQUtsNHhLWE9icUF6eXo5ampGTnJjZDQ4MlNZVzhrVGlW\\u000aZklEUHN3eFc2aEVhd1psaUxRYUtIa1pSU1JYempUVE4wc1draXhmU0dPTDRYNXNy\\u000adXVuajQxNDJyRW80L0NYRzhwODRWTnBrVmRXYk1USEIwT3JmcDdvQWdiLzFRUlZt\\u000aUmpyaUhMZ0Jzb25sWUJvQmNKaVpjb1ljNFJoVmROSnVGdldUaUg5MWM5dXZkdUsz\\u000aeHhoMDNlUCtTRld3Wm44NDZjZ2lGL1pDZTY0d0tVemNPT0JvbkoyVm1JZlFWYUdq\\u000aTmUyY1ZDZVNhM0IwUi9PZXBBRk1ZQmozTTM4djdabFJRUXJMVnRzVXZXMEtjbnRJ\\u000aaHZWa2NYVkpZM3RRYkFKWm44aVUzWnhiN2VvUnF0MjFGem9raVVWbzV6d0FuNDV6\\u000aZVVWUUEwaFhaN0s2K2RmUnJCSGFaMkRob0RLc3FaYkFjVDhTTExxY3dJTlBsdHha\\u000aWkUrUUdMSGc2SXhHdWZmT1VEaEtmdUtoVUlOQ0dwSisycjJqSEZrZGJRaTl1R0Ux\\u000acWh5WmtrcGhEcDRnZ2Z4RjB6QkNQZWJDOHBXRDAxaEdSUFdDVkNzRjBMdGlQV1Mv\\u000aSnU2Q09MWXZKeWhlWURYeWNFLy8wOUkxYTdYRGFaLzBLSWlhNjY5YWNZQ3pGWnEv\\u000aYkxkZjZoWWg1UHp6RlZYNjI4eUJuRnRvbm9MMGlSdlo3eEkvbXQ1alBFc05CYXgx\\u000abGhhdXZJVXlNVEdvM0xGcHZrYStiN2dYZmFPZXgyajZwb0FDdVVZKzJtZmY5Und2\\u000aWitVQThheFB1N3NydUdCaEpJZ2JyeUx0QlNwL09ZZlIzZ0ZSdjA0a3l2bVdkL2w5\\u000aTGxRanVwQ2JvUm81RjFVb09Lb28vQ2l2dWp4WmVDd09QSmdEYndNVWZ1ZUZLazcr\\u000acjFCcktGdWNzbVlhc1dYYUNua0I2TUxOVDdoeHFqYk1hM3JXcVVFa1JyNXJzWWZq\\u000aSFo3SloxdGZacHVyK1Y4M2c5V01rSkFFclhaQnRibFJMM0UxamNicmdBRXQ5MzZP\\u000aR2U3MndPTUg4akNMU2FSSzVUSHlWZmdiUDluYlcxeWdsNHdIQ0tmQlh6RVZ3bWpa\\u000aSmdKWWxtbHp0SnBNcTZJNWJBc2Y2aWlKNFJyQUJmV1VKbkdGNEhuL1RoYTBVZi9p\\u000aMEQrSi9ZUE1RNWIrTmRvajNuSU15UFk3blJ5WWNNVEpaa1lFSWJ1dzd2MXhxUGJz\\u000aTmlSZkczMmJ3dll3QlBVNTduN2lLZXJFTmpnQll6RFVSZWtmVWVxYWZtUHBPWFU2\\u000aZDBBRDJTcjM4M1BnekhsdW0wWmhEUUlnaThycmkyNVU1eDEvdmEyK1YwZWlCdnhH\\u000aTE40b0dZQjZ4a2ZFa3NNTkV4ZlpYU1dCdzlzVnBMeEVxclVqV1NGdk4xbjV5c2Nk\\u000aTi9JY3EzTDhvWDZ6WmR6bFFqWFN4amZ0L0hMR3FrSTVZTTM2K0V0MStXUFFLcG5t\\u000acEpVVnFWemJ1ei9VK0dpcUhSVGVqRDY2a01lUUJnWHB1djFRY3FBU21Tcmtyd21E\\u000aRmVCbXA0amxHV1NCM0R6djBHb2tvK1VrRWxENmRhSGtjQkJCeTlPWEdCTXhKemt5\\u000admNhQkpOY1E5KzN0SjNnVUI2c2QzR3l6ZGNienhMcWFPcFh0bkkyRVZjYXlLekRL\\u000aZ0E5RGRUNHpva3hTTzhObVFOTVMrdFprQ0hJK2ErQW5iSFRvNlJQZ3JpRVg0TG0y\\u000aTGJsUy9UZjRKbjlHaVh0V2V0UWNpbU12UXJxd0UrbTRmTEpURGgxb0ViRFhXL3Vw\\u000aSDdFTktQV3F5bEhwTFZTV2ZJcjR0QVJMaEl4NlhLeXNwYTJvY1h1UWpzRXkvVmZ3\\u000aQUlyMi9NNVZOR3JDcEdmY2Y5U3U4NTBEWFMzVUg1Ri9KM1ZEWlYwL2tiOXNVT09s\\u000aa3dnZ3VGYXR0T3l2QmZFTnNOeklUd2V2VC9mOXgzMjlyL1MxYlhJbmRvM3NHRmNk\\u000aQnlKWUFROGM4OXFaaDJsSHkrWmRvWlRiTXZESFhKOTdJVERwb2dHOExrYU1EUWhv\\u000aaExjOUhHRFluVnkrRGsxWE56d1RlajJmWS9qZWRXcUxXVDcvNm1kSmlUL1NmZW55\\u000aQ0lzQ01TU0tTZ2pVenY0TmY3SUVyeUpvYXhET1UvRGRpOTBXWjlBZ29MUi9JK0F5\\u000acDZ4ZERMV1BUZGpsa0RYbHRaQlp5MXRmV3N0QWpqM0Y0Sm5xMHBHcDBqTVJNUXg3\\u000aQWtHMGpycVFpamh6NCsvd1lrNFhLUGtsZDlQQXQ3b1lQbHdWRERMSGtIVTBOeXBs\\u000aMTVNa1lvRks5TWhNVWdJZWpoTU1UZER0eHV5Q05PVWkzUHVrdmFFVmN6SWI2RXpM\\u000ad0JyYUpzNjN0VmhPQ3lMdXBuZ2VOajNLNHltSWxhVlpHVUdxWDlrRERzbG5oZmpi\\u000aeU1Gd3lVUERtUFM3VlpJdDFVRjJZTWE1ODBjNXFpZnF2YWxFZktlQmFXdUMvOStX\\u000aREgyM3VvYjRiazMxT1JxUjRvbTNrdzZRSzhkaDZETHllNTRoSFVhdnIwNkZ6SWF5\\u000aNkZNcDZhMUljbnpGT0tremtDeWk2OW8vdFZyWHg0alVnYnNtcDlQaFUweVpKRHFH\\u000aYWFINjJyeEcwZEpkNUh3ZkZkUnpXbnBSV0JEajlFbkFkaE5VYnpLNVRJaWZaZE5h\\u000aNnJ2aXBsUk1ZK2N6ZW9CSTU0VHd5d2FPZ0dCcjJIaUVqRUhCY3pvWXdkSXNrY3Rt\\u000aRjZtZTA1N3U1RS9uMFVkTmMzbENJZXNqZml5SVdDTUxkeFNnQktXalBjSnRDSjRR\\u000aTmFFK2p2bUpCbk13cFI3enhOMU85b2tCWHFZWnozWUFUY1ZtdTgvY3V0NWs1Rk12\\u000aZTkxUlF3MysyL0FTVnRmdU91L1JOMTBYWm40ZldiWEZjcDI3NG02OUs2RkRYOVcz\\u000aNXVSWEhZeHp6OHl1L1k2TitVNzBoOStXL0psRi8zTFh4S3FveVlwZUtXdlVWRG1r\\u000aT1ArMUhhNmxNbm1BQm1Cdy9KYVg2WWN3bk1ibkZuekFVWTJvRE9lT2o0dkt6cWly\\u000aMkZMQXVUSWo1Q0VWZStHa3ZHRU4wTFNkNlZzTzIrNXBVRHc3b0FmU0IrUXd6bzFx\\u000aN2Urbm8vWWtuancwOVdEeEtpVWxoWHRqN2s5K1p1VjVWYWhmczR2bExLaVBPbmhI\\u000aQTFlRHdXRFlVdDdRSDRQUWUrZjhaV2dtcTFaTnhVUzE2Q2d0ZU9MYjFJZXVucERN\\u000aeFZUSFZaVy9sQmlzakFCaEJpY2x6a3cvWTkrcTlEdU1hbGQvU3plVHZVaXpvaUVi\\u000aM1RTVGluVUozUUt6a2lJWityOFJrdnB0WDlnZks4VWdva1BFa0tleGd3bFdmTjRr\\u000aRzMrdDlsaGw4Mm1oZzQ3bTk3Z252Qnc0L1JtOGlaNXJXRzhqOWlEbHJaMkJWVzRz\\u000aMGNmdmZsaUFTVjMzRElNenJveWFFaXBFdlZMTW96a0loTm9OdkZpRXp3NWpUdWgv\\u000aWXB3c0NtaVJ0NDVnUURyUzF2WE9lRzNSdmdPdC9rMXdhUWZIQ0ZjNkFlWVRKdXd4\\u000aWENMOU1laDFhd05qd3BFZThBbU9oK1dkYk92ZklvVXRVcXRXb1pkR0NXdWZoY0d6\\u000aNldESUxpYmUrZ1Rsem1sTitEQml3ZXRNMGt0N2V4eGg5ank5MTA0a2pkdTMydkIz\\u000aa054WWtOaUVsWUNSMnBBSHNhWC9mczE4YjJzdTRUUlRUSG1MWFVrbXdwcmhSUXpG\\u000aMkpVOWlWV3NmbEVqN2d6SlBMNGRyckxsKzkrUUdGUG44VHZFY2U2TTdLRGZUWkNP\\u000aV3o4Y0FjcW9ibVJjNGZDVFRNN0ZKRXVGUklIcXdvaERRYXZlOFJSUG5BZk1XckZy\\u000aTUJOekpUTWllY3lpWWZIcGE2U2NseExoaU9aYm8wbWo4OGpLN2FXVXdqdng2THRJ\\u000aQ3RqbTk1LzZQcjV1L05lUDJORFZ5dXVBK1pCRjl0YXNhOVBLbVY5K25uMUg5bU11\\u000aR2pndlQvUHJmMS9RUGFMUEltUjhOTFlPamdhb3crRUEzWVBZMytIT0RDQzVlRnZF\\u000aOC9PNVg2QmRpTElzVU9uL21ReUZSS0JHNEpySThkSzRyZlJXTmgvYXg3a0h5amFB\\u000aVkNGV2pQdGp4TDJjaFZ5UjBUMDE5eWdGUGwrRVZUcDFML2UxWGo0RjhRTFZzZGYz\\u000aUXNaM2g0ZGpvREVUZ3V0OFZTOTFuSDRnMzJPYjJndnEzOWtQRjNERzRjUU1kRzha\\u000aeFZEaWtIbTJrU0RjMThaTE82RkFqeXpncmp4ZWVaeFhvVzc3QWZGM1YyaWt1Yi94\\u000aamQvOFhJZzFNZHkwVHNEbGorVEpBUVVwOVBOZkN4MmxUNlBuN0dZMVNBUGptSS9a\\u000aUkVJSEdncEx4cUcrSkdBVXlROTR6b1ZnM3ZYOTNkZStXV1JEWWpxaXRXYjlvbU9R\\u000aYXhmVDF5Mk5yeWtib1pXaWNTb3lMWnhZVFU2bktrbTdUb3lMU2F5ZFo2MWhzUlB6\\u000aZXNlcDA3S3NxTU1Zc2lRT0J4VHN5a1EwcHhVenRqczRJeVkxWWtmcUdvaXZPQW9E\\u000aVStxN1dOTEpuRDZnd2x3bklSSUR3aVpuREJrckNZc0JFK3c4QUNoaTBiN3RqR3Qy\\u000aaG4zVmRjd0FabmQzOWo2RlF2Z0JtWGZERzlJRi9SUTBTNWN1OFh4OTNFaGhoOE9B\\u000aK1hTNlkyci9rbTZwTm9NaVA3TERJSk02SmRrVlRGT1h6VWszdzVrS1liQVZwRy9r\\u000aandjRGJnZVlHUkNxVHBmMFBXeG1YTU4zWjZtS2J6MVFaNnd0TGx4L0FNYTA1Tkgx\\u000aYk1zbE14TE1WWlEwdHNsdVVqSWNVamRNdGlTb3BaYzBOOWZDY3pmN3VBMUl4Skc4\\u000adFIwdnltdkVQSGdKVXVSYXhxZ1crSHV5eDd4ZVAvNVJGS2VBZmdNcTBzaS85OHVS\\u000aSFlZZFVORUZSUmQ4WXluR2lqZFlxZ1lZZkNnZnM4bmcyWDlsdnUzaFNIMkdQM2Z0\\u000aVUdMS295L24ybE43ekdjMFdxQWxDYXh0WWdNMFVwMmpQWDd2N2ZySUlTc0sxYmdX\\u000aSnZXN0xEQThJMjVEVDZaVkdOY244WkZ6RWV3VGJSdlBFNk9oeDdSc1ZBL2JwbVBP\\u000aR3prQ3N1V3A5OVhSa2tQQTNaQmluejJ1RXIzQ0NTRU04eitIeTZrV2RRTExSTlpO\\u000aZnQyV3dBWFVwc25tL0YwNmpVZXU4Nk4yWnNMeEN4S28xYnNYYlorKzNCM0NTMFYz\\u000aYXVBYXN5aGwwa1NWczI4eTdYaTFSajFZV1VabHNmQVYvR282SXZyNE5YTklpK1hY\\u000aWVJtaXNRVGI0UzNHUXRvRmhvcXdOZ1p1L3A1dzBmc2lVTDBFK1BDMjRvVkIzNzlj\\u000aUG1pUXUzdTZ5eE0vUVVCVW4vNlQ1U215MEszaUFGdTJEVU5ZRkg5NllEdFNZK0RV\\u000aVDJJVTByK1F2K24rYUJ2SC9xRmVLWXhNZTZMVlF4KzRNTk8xZzh5M0ZvYTNzckZV\\u000aT0R5azM3YlVrQUZWUXNPUWNEV2d4S2l0TU1kbWdpc0JwQXNNeTRXQTAvTnVqVGZy\\u000aUmZWVFRWVjFxWFJZL2dMVVNGbmMxMjNkbW11WEF4UjM1cFVzWERwbk0vallRcHRM\\u000aSmtNcHpPWnZmTEhNVmpVQU05WUtSOUhxSFBxaWVoN1ZZT0t4ZnlTL21ZbnpVWE1T\\u000ad3l1VHdRL0VLaEFkaVo1bHdhYnBhcEYwb1RCWWN3ZkVnejRRZDZjZVgvOWh0S0xx\\u000ab3o3RGpMVVlqRThPK1JxanpVeGJTbThvMnpHWG5yL1B3Mm5COEw4bE1yQlpTaUN4\\u000aUkJuK3lkeHZ0UnRGSm4yMWZMVmlqYzVOVFpDUVZ1bThGUlpTa2FLc2JkQmVERFNJ\\u000aaVJ3NGErY09mc3FPZjNQa2ZScTNraDJ6TUd6Ylk5b1MzWnFxSTJHdGowUmJaMFZ5\\u000ac1VTVWJnVU5uQ0lSR1RtOHE0T3J0Skp6Rk1oYm5Yc0R1MUxJbFY4b3ZTaW9VanZr\\u000aU2I3bnhQUTQxMGljZEt2NkczNmx0VFhVVkhnM0RzMFFrK2Vha3ErUk85clhBYkxD\\u000aYzBxTDhkOUFELys5NFZ0eEZ3a1M4NzltUmhGZDlZQ1FPVU9HYWRXbzJUYnoxM0hs\\u000aRDNUUUVvQ3JkQ0lwdGdhVTZ3WURjZzRtbi9IcW1aK1RuMzFJTERDejlvb2pPM2dl\\u000aYVE2aUR2eTlhVEl2TUdrKy9GR1B1emRHYmhRWmorSFFvbWNDaVMvYWxES3h0c0Nx\\u000aU3RkaWRQTmZwa3ZVSHA5UmNERHorVmlMMUlKRGcwVkg4N1N6VmNjd3Bva0NIaW9B\\u000aZGsyLy9SQ1lwbHFQWGdHbFZSV05jK0w1M3BhVFpPT3IrQXpFNUI5dVNFRDI4c0lw\\u000aVnZIb0lBbGhpZFNDT3M5UzJjdGhqYTk5WlQzREFMbFRYcFd3NDdpZmhkZ09aVkZU\\u000aNFJEYUlpMm9TMVp0SStkNXJSQ21PN1lEa3liNjhkc201UGlLZUVGdHJNYm1mcUNV\\u000adDhSWUNEd0dnNHF1UEI3Z3V3bExhNnhHczNJQTV3VVNJN0FUWC9CME9Jc1NsSFRO\\u000aZU1TYjlVbTdQTGhieUc3T1JKaXNLUjMwWEtkVFVRUjJGMzZWdzErZDVHMTBUWisz\\u000aaE9XSEc2bWlHU2hPZkFJY1hBN205VkFNWXhJM2lSUFBqLzE2STRGeExTdVFDYmFa\\u000aUmptb1hDRGRidHRYNXFqS0NXRDBBTEl3RmZ1VEFMNlVQV0NDYzRKOHpnMnJpc2pm\\u000aZ09tU015RUJ6UHVBRkc1Uk1lZi9DNGJzdHVGd1JDaUc1WkZlNmhyMUE0RkxLODAw\\u000aemw2ZDVjYkQzN3Q3amxXNmIwVHZpaVFrUS81K2dqak5QaXdPTGxPRU8vWHhXN1gv\\u000ac00zWm1EZlovZUhLMDM3VXd0QkRpNTBGaURXSHJON2svNXladnZFL2lUcUh4OHBW\\u000aSjZ4UXF2QWdLRlpFamE1Y0hEcE5MdWFTb0RIMjBzelNNL0NmU3g1SyttZ2c4L2ht\\u000aRHlBbXVPT3RJVnk4N2RQY1phUWcyZ1d0K05vbnN5eXgwR2k0eGNuNWZEZzVPQ0xT\\u000aeC81dm95REJNQnltZFp3aS9QSEtBZlRMWlBlaGlvemRDb21vS01nQ21JQ2tJS0hl\\u000aM2M0TkFTN1B2S1hSWDI3V2gwbk1aNFo5TUQxVzlVeUIvMFVoVjJQUHdLVnpvY09w\\u000aT3NEZk1WWXI0TXdxZjlXTEtFME9BQ0E2T1ppZFJYRnBKN0lUNW8wMFNzNStXZTNh\\u000aa3dER0hRRVhPN1JQc0U5SzloVmJDUDBuUk1YUDU3bFZ4WXBPRG5pRS9lK21MekFT\\u000aVm5rVlYvWUM2N0ovM1E5ZXpQdlE5VzJYcDFRTzlRUjRkVGpnTTEyRVBmUEpyTDV3\\u000aaUxaeW0zeitVNlNpUFFXQTNMSDVOdzVCQlRGMGlGRGxOaEExTVorUlIzRXU5eEQ4\\u000aWkVaV0VMMkIySGR1L1JGcDRkaFI2VE9FZDNTTDhIaDJYcm9pRE1YVnBnWU5FS1lG\\u000abENQMnlDTUNsQkFEcnNuQWVRR1Q0bVh0Rm5aMmVCSGtHNEhTUVRtQkM1NVgzRjMv\\u000aYTAxRmtNcTBtelYwSWVzUGM2UTRVc1lMWHZIQkl4L1lrT2hhTnVMMmprWnRGejdL\\u000aTDFQblRESEt5bWJJcFc1RFZuVDlFU3pHbUlDSG0xZ0lleVRMN0x5MldSTCtBTFdw\\u000aOW1aaHhJS2FxdmdmK29jNWFGaGlQellEaDFjS3ZxVDdHakxBTHk1amJrbDI4QzhO\\u000aSlFXZU9QR0hFVjRsUXJmNy9oejEzK0VrTGRaUHJuM2tJOGVzVStURXVST3pkSXN4\\u000aWUgrU1hpOGhxeGt1ZVByN0Z2aEF6bXk1WWFXYTZJT3JHNkM1RTZNTndCcmhVYXNF\\u000aMlQ5bE5OcG05a0Ywc0o5aTFud2o3WW93S3BnTVR2cWJFWUszTE05SGUzMnhRN3ZI\\u000aN2dncHloVmhBYk85cCtBZHQzT0lsanVrTC9NUGxRM3dnWDNyS1lBM205RWlyaDJ4\\u000adHhQVWR6cTI2NzNabjMwaU9vcWRBQzhVaGZFN1R2RUdMS2dZb0FlSGlqMS8wekRC\\u000aUEJNUVkyaWNwblpyK2dNV2huRlBtN1dXUmNkQ00yOFhsZTVBa3ZoSGtmM25tOU9P\\u000aV0RESStERkRPOHJhQ0N5SzI0QVhMNWxMZWwySTRlTW8zNU5kT1dRaWtidU0vWlNW\\u000aM3Y1WUdSMjB1OHlSajdrZ2Uva2FvSXk5ck8xaFA1MDFxV0xOd2owUFpIZTZ3TDhI\\u000aT1d5WHhnMmZweFRlbjRpUVFRcDJqRmEzR3hJbDk5U042emJvcEVZL3FGa0hjR2t3\\u000aeFk5S3EyOE01Rzc0ek1xK1JaTFYxVFVRV1h0Sk9lOHZWUDFkMDZPRHFSMlZrOUla\\u000aaTRwSGd5Zk9XNlBWT01WcVRGRkpJWU53cW04alJCakV2OUZ3dUluajA3ekpXRUp2\\u000aMC9sdXdaRFQ4R3pEY0RoaHdyWVFFR3BaVkl1ZVlXbkRoZnRxVkloS25zTW5KREFG\\u000aQ04zSEhFTG1VbjdJRVpIdU9Sa3A0alpSc0x6dTliK1RmSDhGYmU1d0pJVHBiSDhB\\u000adzhweUx6VTdqMk5xd28vYU5oZ0FUUmcxL3BERWpOWlArcEJ1T3hIRy9ldVM4YTBz\\u000aeEVETXFTclUxSG5jaWxFSkpMRU9yZ0tURkx2ZDB0eE8wamRGUGFLOGttRWtmWVVn\\u000aSDdJbTNudVQxSjVScDEvRXR1d0E1Mmg3YTVHWEhaTmduR2hzbE9kN1ZRLzBCQ1dL\\u000aNG9OaHBTY0FybUZibEhVMDRLY1V4dlAzV2MwNGZJOEV5ZHdZczFDbm1iLzQ1TXU3\\u000abnRCM1RkUDJOdXVoZlZHQUJyOEF5eS9UTDBSYytZdTcyQUxFZ0w2MkNtekNyOG9R\\u000aaExEVkQ2RnRDM29PQ3lMNXJhbVNKTzVXZ2d4bTA1WlE1UFN0TWx2RmVrNnhnd216\\u000aeUNBSTRzUkc1SUV3NTQvM2N0TjZxUzRYTEFVVWNlRUg0eUQ3N1VyZEdmdWw0dU91\\u000aOGNJZEk3alFkcGZQMW5XSjZRZUgvRDFCUEZOREtwQkhCY3hRbjd3aTBGckZOSTZw\\u000aTFpEeTFZYjhYNHQxaVkvVzE1b0NQUGw1a0hoOGpyeXpUb2tRN3NSbWcvaHh0UEpv\\u000aaHNqM3dSeW9OS2ZWSHMzbzg4dExWTlpQYUNPKzhUWGxlRm5ycGU0N01QZE9ldU5n\\u000ac0luaWk4a0s4bDJ0UUVpMlVpTmtER1pGdGliR2pxdXE5cm9nUWpSMXZMNDF2czBy\\u000aaGdXL1I5OHp4RDgzUzV3c29qQndEWXpPTzBtNDB2WVFFUEVoV0NXV043SlRaWEN4\\u000aMXR2U0hDMmZUSDREa3RjaHkya29CZ28zUDdYTXZPUnYyU0w3ZGkrajlKdkVqVWxx\\u000aVkRFTWRQRDc2b1RYYXh5T3lLUzVVbE4xTDJYbWk3QlRYMmlxL2xueGwyd2VONEx6\\u000aWFBsTmdEaHN0KzRSS1VtYVB4a1QrdlJpdTZ6b3dEV0ZlNGQwUHE2azhRZU1HT1My\\u000aUFFETnhuWHNXUXZoc0UvWGJ1SEl2Y1ptUVlKTjh2bHdGSjBzdnFkV05URWlDNGdJ\\u000aWlJxWHJ1MnUybG03b2RCSVZrdjUwcVVnRENLVG9xS2tkdkYwOVhnKzZsOUNiZjJy\\u000aQWE3d1RjMlU0ZEVtR3VxZ1pyR3VYRnhVZmlKYVR5TFE5KzFLcDNnZFRJQTVFVVRZ\\u000aOUs4cWhnS2lHdjNlQmdIamU1VXhITUMvMGFwWGhiNkFySEM3RW5yOHhEbmN5YU5v\\u000aOXJmSTBjT3RCT1g1QVZsS0xZcVdnWEp1bDZTNmZSWWpvdVVjaVF2UHpBRU1iUERV\\u000aaU95ZVVTQzd6SHpHcTZ4LzlBQXFySEZrbkIxS1lYdFJYWk5zQlNJRCtTV2NNMEZG\\u000aK1B5amxJbVQ0K2pYOFJBVjVGdTNpL09hcjBJNk1NVldSZzhNQ1RsRzVWWDd3cmt4\\u000aQ2pGUW5scGs4U2NrbzlRZkNjb1FsTlhyK1Fuay9rcFROOHJHQktvQ0xZVkpNWS83\\u000aa2RYZlluOXBOWTJXejlYSlJXcXh1dFRoMXU0K0ZZUzcrY2h5b3g0Q3ZHTTZjR1BP\\u000adDFZY1BJMjl3cnlYOTFiMks1MWdOQkNzSThPQlJXTkdkdXhMUzA3aDh3eDFSOHVS\\u000aY2dETm9kWnJQQ0pnQ3ovYjd5R0EyMDFManUySEFqeUR4N0pnOUJzTmJ3dTZnZW1z\\u000ackNnOHpJQjdZOFdsQWZueUhuOWRma1dhNFRZMGx6VEZoUStOZUtEM1RaUklrV21J\\u000aQkpUcitwaW1FWmJUSFIxSk5PeUh4L0M0cFlTem94MXhGYmMxbndMck5rd1lyRElN\\u000aM3YxaDQ4eldub3Zad2hIUmk5d1kxdngzQ3RiVXVOMVYwZnVGU0U4K1pvYmNaYzd4\\u000aZDVNdUJ4RW1rYUFneWJSQ2JSRlZvUFgxdjdGMklkZGd3TFRYM1ozSGNZdG85eWJM\\u000acWowZ0FNbUpadTJGM3pYUkkxUFczc25STFpubTd6TnBCYVUrL1luQzRjSUlYL0Er\\u000aMy9zZ0tYeDR1U2tqTGlwN2lTU2xoTTRmZFQwcFBSaUVoTkRyTG16UzErWmM1UXpN\\u000aaVVFVGM5L3Q4bFJDa0E1UXhYZkdmZmJvTFNGT2VMNTV5NWEzYXhNMUtZK0VzOFBx\\u000aRnk0cGhYY0dLVHZ6dDcrdXRlOEVUdWJKUUR2cStFUnhTeWkwWm9kK2RyTC9zSmty\\u000aa2tMRnU0ZGEzOTlkS3VobGRMekM3MlZxS3VDTUN6eGtOU2NOT3ZRSlRYVHlEblkz\\u000aa3pXRnFKK2l6SXRvTm9ydVRNUEJTNkpOMEJWQmlBOFF2bjhWd1dyOXEySDBzWlJ2\\u000aNWxsUkZZZnM1bEZ5TkI5bkpONnVPZ2JMU0pNSm02ZGc2NHlITDdFOXE4OE5rZDVx\\u000aMXVhY21pd0VUN0VzVGpSUXdLMm5oN05lMC96VGVpSzdiVG1RMW1KUGpwZEEycXp6\\u000aZ3lIRGoxRVlNenhoZFZIb3lHQW4wWlhDak96T21SR0F3U05pY3VhR1I3aERpRzNU\\u000aZllxSkxLWUorUHBnYTh4NlRha0xwcnZyK2F4c01wSWNPWkFpQy9jQUV0REFQV1lN\\u000aQmZaeEI3cFdSR2NqVThPbDhzUnlwTXZ4ZDByWlpoZDR6K2NSQ0p4aEM2RDl4blMv\\u000aVHd5MWVxOFd5TmNLdDYyRkVaU0dMWXFCaWVUSUp6ODRLMnpTWFdYVzBDZnhrcDVu\\u000aZXlnbTc2eFlyWmJLUndPcmxuRVFwaEVUbVl1SzB6RjdtOERKOVBtNlBNeVl3SVVP\\u000aL2t5aVYwU0R3WW5CM05HMFdSNEtFN01jOUZOMWFtM3l2N2IvOFBPRWlNVDBpK2o5\\u000aWm5lajRMT2ZVcnVVTDBqc1UyRkxSLy9RVXpaZUpxL2NaenBKc1VEY2ZvcW1qNERI\\u000abTk1YW5IQXNPdnZJZXBqdDJsQ0dLZVExRm1yb1h1NzQyc1BQMndySmtyMDd1SThM\\u000abnN0R2xucFNPNzZ2ZnRDa2kvYjc4THJOc0VIRm42ZDgzM1JXbzUrWVhaUXllWWUw\\u000aUEovWUpad0c4bFkyRS9YZWFrTjAxSjJpT2tNK0lmVkhnYWsvUG5PRVhhOFFqOXdu\\u000aejBNKzY5eVFGVksyVDJxRW5PUmtEZmtacFJtM2x0WXdqcFhCbDJrdDVKUE5qVStH\\u000ad1A5SjJHdExWR2IyNmJleCs1QmlVNWtxbUQzaGdHUlRsVmp1WXFkS3pYL3Z5bVJP\\u000acm9MZWhHMEZtMjFpYXFvZitQd1I3ZmlOUHh4WitLa1Axb2JGb2xDalo3S2o0OWdj\\u000aR1JNSnE5U3lya3BWcVkwS21YMGw1SnpERE9QUWdiRDhlRlQ1ckhjbFc2SHVCZFdB\\u000aOHAyckhQNG5BaXhiazIrSGRsMG5Rd3QwalNwUHNsSmJrYkpYQWtaZnZJNVVwU0RY\\u000aZGpRQmlXOFNJRWY1QXhPaUFveEdGQksxKzZzS2xJMzMzNCtKYmlSOVZDQlE1akQx\\u000acjM0MnlPcDlzc2VjZEFGVmRNQXZOQk1jQlQ3Nmx1ZmVlRkNCUFRQOC9sZFF4dmxy\\u000ac1Z0SEZoRHBHa2FYSk9hck5TVlV6d25uU0djTTZUMEM3ZTJLV3l3VUpLb1pYdmwv\\u000ac3czdG5KaFhTaDE5SUJxS3BLYjBTV1piTTZFaHlPTmZHc0hqSkhuR28rVHlBQlRu\\u000abWtNY25tTkxPSjcxYzNnMjJKdk8zS0diMGRQZTNYMTEyS09LNmpEdFZPVjRIS1Ax\\u000aK3UzRkRCT2pqYWU2SC8vYjN4RVNXWTB0VmlNSEN2YUVVYkhKL0dyQXpNWElwNTNB\\u000aYVRoSXEzVlVOckJlTDVraFFjbDl3ejcxM3JLRHkzSG0wRWxnQUpYSEt2cHpYS3BC\\u000aUm1pUDFJVHdRQ1F6L3lTREF5ZldpK2pxT0hNdUxaR1oxcW9qT3V1UnhIdWFTeU95\\u000aQWFwU3F3TUtFQTlIeGlZeFB3UUEvcHFySENJS0JDRWtSUnRrNDloQlY2VXdsOVdv\\u000aMnlJQm11cC93UE9rRVVRRW9NckxKL1FMSlZyUzd0N3BaRkNXdmdwV3RoZXcwMjBj\\u000aNTQ4QmkreEl5UjdFeVFmaXB4NmFtM3JzUUNLdDdMTXIwTXkvNVBkL2d4bWVNRjlG\\u000aUmNCdUtEQ3FlWEwzeWZWZmhwMjZQQzZTenFBdmJsbzh2ZG9EWXZKenFkWGVlMXFw\\u000aYzJmeHF6bFBkMXpicEJzeTh5NjRMM2V6M1NqWDBubnMwU2NvaVVuQkozci9hUG1E\\u000aR2tzUU1UaFBlbzVOcWpVTmc2d3FUQXlDMThqc1ByNkd0VXFMQ3lSOU9UZW5RaDdM\\u000aNXVSK0FMTVRscC81N1pMMjJkc2liUUJEdmVhNEtISGhzWjZzbDBGKy9YdmR5a1gr\\u000aZWU1eExVMnFES1RlRVkwNmt3elNQSTVxWkYrTXRtVVJTUWtoYVRuRGJYRy9kd1Ir\\u000aaHdRb1RQcXpBeURLRi9ITmRZVDdzM0lxYS9zQkEyTjJZVXFJbElId3Y1TUFGclE5\\u000abXYwbFhrc0FHbzF6TUpKdVRNUFY4alFmdDh0NFB4aUY1Uml6b0s4cWI4TjBLK3RQ\\u000aTGRJdWJtcnlJRitYSXhkV0t6NDhvMWR5MWYyalFIV0V5eVJNZTNvM2NTSCtDRU5S\\u000aanM2aDdPUjhyekd3ZFJxVmlEeHRtR3FMc3lhYVZYWUoreVZ4Zm5kNmg1RGNTNlI2\\u000aclAzOS96WEtSS0dYU05zd0EyMjBjTy9ER3VsYVdtT0pLand1TkNFRHpFM01sWHc2\\u000aLzB1cllNUktsVUVVTmpDTVVxbEFPSUJ1Y3g5YnhEYmpzU0lHN0wrSDUzSFFXZnI4\\u000abVlaOXhjYnFidXc2Yk1PQi94Z28xK0RyZkQ3VzJ3YVdoOGpKUW03NFN1L1ltQldT\\u000aUjBOVEQyNXd5R21zTVJOYmZvS3VTbUZNM05pVXdOcU40eVNQa1FOaTZod1ErNmVC\\u000aT2lPcmY3aDJqdE1VUU1HVFk2dEYyZzhzUVRRZVRVa0NqRkordExVVXBlR3BRaTE2\\u000aKytHa0UwV1dJWlBzeGtuT2Q0U1lXdHZBUWxBWTV3RXlTejFYQVNLNU45cmx3TldX\\u000aWE4vSjVIaVZacE5tVDUycjkvSTlzRlhpeWN4d3NPL1prd3lMeWFnaUw1cE9hQ1g5\\u000aUzJuNmVDcmk0cjBpcUtSWTE0QlhaZEdrNGlnbHpQR2tPMU1zc3JEU2FsejZIdGJY\\u000aMWgyd1VSMHdTZGlETHpUc3o1QmR6USs1ZlVwOHMxNkFicWlxQU82Y2Y3WlpPRWFs\\u000aOFBVZlI1bzZQZ2llZVFqN1lQUjdqcmVtT1RwUDZqaXZZLzFyQzBJYThLQ2pyNzF1\\u000adVBEa3VVVlZ0MXJiZzNZaCtWVE00aWU5VS95U3lXSFUwejZIbU1icHZCZ3AzUTV5\\u000aaXN2azdtVFFDdE1uNkR5VTlKSWlDRHBhZWVGUGpaVWJiSXRqbytiWFV2SW5ZbUxu\\u000aankwaUVJYW80YmhOcERGSjAzcnltQ3NMeTRSb1ZZczQ4NWxMd3hEcEFLbG4vMWFY\\u000abUFiK0p2VFFlTE1xNmMrRUtqR1FITXJycmU2T3VaamxiKzRDVVlBYkdLclA3b2Mz\\u000aL0tVL0JrTGVpdm9lQjFXaUgvSHBncDZSNVh3VTNvUXBXTUtlc244UkhMU0NsYWUz\\u000aaW5ic2FsNUpGK25KUDFSaXZldnNya0IyMWU0OXcxU2NIbmJVdDgrZEJJc1ZqOGhD\\u000aT1p2SjdqTVR1YUJteDV6UnJGUk9OSHJuTjdOMlFPQklpUmxDVFRmSUJTci8zdkwr\\u000admxObm9GLzlMcTU5c1gxY0JrVk9qQmI5cEFJRm85TnFRMHFLdGw1YXZiSkxXdG02\\u000aa21lei9xcG9HT0FRWnF3VE4xeHpwTWtSRTBpVExPQk50TkcyazM1RUJwUUI4WmQr\\u000aekFJM3d2ZGFPV3FsRk1oSHVQTHVTejliaHhEa1RicTVwSzhMWGxNVldURFVUM29L\\u000aM0g5d1M4bTE4aW9IRnpPUUtSMnVXc0FrZ09yMEt5b0Iyb1pEN0cxejJOYWNLTmgr\\u000aOFlyZXdOanVnZTBSbDJaWmVSVkNLc015UTRqT0diSmV5K1hQWkVyWHRGNWtsMC8w\\u000aZDdMT3BVQjRUcWM2NVp3NmpBOTFRK0c0dURuN0xicXY5LzVoUFllblBHeHM2Snhl\\u000aQVNhTW41OVR4L2JYUlEyQVIrbnpyNDRMTG9xVEN2dzJCRzJ5ZlBzb3pwZlpITlIv\\u000aMWE3cGRRdjdvVzhwdWV2WjYrb1p5R3p1NDhPRmRTZjFjWnNVMUhXdnUxd2J0blgx\\u000aSGdFWU1hNm10MWR4WjlNMktzMWpMc252eDdyTjJBMHlUeXA3WndadTZCQlRTeHVS\\u000aSjJiYjY4THJFZDlSbU9FN0VKZkhpZjB1a0tKWnIwZndJM2o5bkNnWk1hMml2Yzk0\\u000ac0NSMXV5c2pWcGc3d2FoOGUyRkg5cFN4U2VZa3RqVzBnY3ZvVndLNmZiRThiWVp5\\u000aQU1DL1A0Z2JxSlRIWkZzeVA3dVVIaVhQdXoxTEhnNXdOSk5BdXYxSFEvVTlLQlBF\\u000ac1lKd1R3YmxEa0RqK0RCbE4yZEVtVHpaVkpWbGU4SGlINGhzT1NoNDQ1Q2xHREFn\\u000aL2hZTE1kYTBqSDJaS2NneVZSMnhNMVlYd3NMZTR3QnNBNUdLRkJTWERFQjZmMkIv\\u000adDJIU3VZczFmNldpbEFEaDBqaU1JcllTTnM0Z2tOTFJYU3IxbkxpaGxMV1FWNzZk\\u000aU09YOW55MTJONFFwZ2wxTzVSSzUwWjB4SktNNE0xN09xZldHcVVFNnlSYWx5V29D\\u000aakFjZzhSdE5TZzViSjhDUnRQaFJFcnNZeE51VzRVZHJSaEk5dThxU3dERTl5QmNQ\\u000aUWoyUzhodm9FYlRMbXV0SW9zRXdvdFFOeXVvU1NuN2lVQXJwSWpuVzhLc1U2VTAy\\u000aeCtzd2NYSDl4VU92ZE9ZczhCWE1tSC84bXFxV0UzMkpVcGJGNUlaWEw3TUIzMEc1\\u000aTTg2NFZmWG5HK1FUbmkzbFlSWEhyd0Z4R1FPUTY0M2hzVkZDSVVvYVhiczRkM2RE\\u000aajZPUVZhVGxtM0k4R0ttYVNNSSszR0pYNWZFVHNOYkdGcCs0ZStNZEZkak1Yb1hR\\u000abjZjSFVGN3NYd2FIVVRtekphNDZaZDBLSjVVeEdicU1oMUo5cWJLamUvWWJzNjNZ\\u000aTjAzanNWNGljZy9qNngzb1VvRWdnd2lDSW1td3pIbDZVd20zNGNmZ3g2WEFJM3BW\\u000aaTIxMHhBTll3K2M4WDNPbGxnbHlEWjlaOHE1bTZOMnV6UUZMTFRDYzVIUVU2eWkx\\u000aU2g5d2pjOUdkakJSSDErdFZ2cVVDbnUrZXZNanBZL1A4R1hDZXRIdEhGa2xER3dF\\u000aMnNQRUI1WkZVZFkvcm9WeDdRczVSWVpkMVdOVEovRkMxRk1YTkVtTkNqRFNUUk9X\\u000aVUZlaHF2d3RjUmVQVHdkdEdjVWdONmVqSXBOdTlzSWNoUFI3UkVOYWtRRWR2UERF\\u000adWl0dWpQc1g5a2ptV3A3TnB6MU1XQzV3MGlEOXdLVkhHc01jWGF1SlBwVFVCdzUz\\u000aS2M5RTNGc3F3Q0J1cGNscDRZMWpzRk94WkYrbTBweFlnSUxPS2JSTjBjZHFGT2ll\\u000aRzhKcVJidXBpaGovOEpwaVg2RlI4dWxXSXZzZ3RSU21pSVZodlo5L3V5cjVXbkxJ\\u000aNklDV1hWVHRWYVY0clF0QUFSV1VlY0JYY0FXRHcwOEhzL0sydGpNQ0t3WXIxYzg4\\u000aSU4veXdaVnBuT0lveHdxNU9wczg3cnBqS2hvaHlCMk9ORUlNZlBEM0hYZG9OQWRY\\u000aTlF0SysreG4xN05XNHF0WHFxQitFeFRDNWRGQVpvT0I3QnpiVFdKbjV4NGMvUTNw\\u000aeEMxY3Q4L291ZERnQ1drTGZpT0NYWEwxbzlqRjN4SEsvL3hhMEducFh3Nm1IRndw\\u000aNW5XZk5UMFFDSmRJcWRrM05WbklIcTJwRmhSTDFwSUptdHBTOUNuSlFiNWZLVkcr\\u000aNXFTM2pXMkNzdTZTTWFiSkpNQm5vT2l0cWpTRzJxL0pIMENKaElCZk5IeXVxK1NF\\u000aN3FhaEJmZ2dtNlRQUkMzWXFjc2V1R2Zqa1N2RnBXN3hNU3c2QlNvZWljdktVTUNp\\u000aQW1GQVB1MXBNam5MMUp3VkpFUkxHcVZrVFdZanZqanduY0pWZWhJQTFNeHNHWWsv\\u000ab0ZpbnF5TDVsSVUySmNYMi9kcXlKclB1dzR6eWxIU0ZXT0FPSWtsSEN6eVFSN0lr\\u000aeFphbGJDYmpjWGRFVFZFV1YxSnJsZzVaMHhNbG5jYnZjQnUyNWtUMC9oYmh0alNK\\u000aUnJMU0dqOGx0Vm9ONCtCWmt4Y1ZTVUtLVGhSTGtKeENBdlQwV0RkQjM4aDh3eWtD\\u000aODVib0ZmU092UWsvdXFWalczK3ZzY283V2NzRmE2OEVKdWN1Y1Y1QzhiOEJ2dFV4\\u000aRWRiUXZuMlNkcjNUTEFqazlsQ2ZtcUM2Mm05VEpHOXVxdi9Fc1BxNmxtWFNLdHpv\\u000aWmo2Z1Z5ZGd2T2FXajZLMnF2R20xSGZiOTlpWkdhWEV3Y1U1bUZGNVBZYlMrdVVl\\u000aTlRPODgwdTl1dVJlYzJlR2dBMVR4SlZTVHY3N3ZuRTI4cnBzQUZycWl0ZklwTXll\\u000aUW10RzAvQU05bTNMelJmT3dLNTRBeEdDRk5CV2txYmpRUll0bUlaa0hWdDVkQS9Z\\u000aaXF3KytQQjkxaWJIQ0l3WnAwdWYvL1AzdHRzVDRHUy9KNjBoZ2pWNEJwek5FVVJJ\\u000aODNkSEo2SGZHM2dlaXlNeGYwd0ZuNjVpd1loc2s0bng2WjlleDVEN0J6Y0U5K24z\\u000aWFVBVkJmcXV1V3d2Qitxb0RBK1RpMVRDQ1gzTElteVM2RkhJZU50Y0lOQTc0UldO\\u000ac3ZtY01mZTlYUi9IQ1RERzMydXk3QzhiR29RQ3JFcllreTRXTVlhSGZScXN2cjRa\\u000aWGV6TGpENTJkbHkrV3UxQVd0YmtxbzU4am9pNzgrYjhhaEREVG5ib2ZFOXdoeGxW\\u000abTdGYXB0Z2NET3E1TER1WDlNTHdZRmM2WGludDZIUGtHMUhoeE1rMGdIRk1xTzJs\\u000acm1lQ09nb2t2MndwYk1MZ0txRUxZR252amNzR3R3WDZQMzlWNnlFRmcrOCtFZzFP\\u000aR2tRUmkvbzRScTRjSm1QZ0x6ajZKVC9FK1VZV2NjQitLaXc4S29NOEJBVGVsNEsz\\u000aVFlhcHlBeUVyYW13d1NGWldKOGJDdUx6WWNRODVEWkxCRy9UaWtDUHA2RmZzQy9V\\u000aNDBCWGdzZ2IvOERKS3U4SnNQRWZ5WEhFR1I2cEZSVHoyVmE0YXRiL1hCc3NMcmpm\\u000aTUsrTVJ3dXZnTTZmQjBjbUh5eXRkbjVrdVBCUitSa0FnLzgwMVRhR3RJUml5UnlQ\\u000aYmU2aXZSa21tY29idTVGc3F4eFlCa3V0VUxoZm1JaE5Ma3EvQUhvWGZZTzdpZnRW\\u000aMkljTmE2QkZQU0NaajZ1SlY2MDBKN2swRjRnZ292UmVWZmlTMFFoSk5TeEZ2YUQ4\\u000aZVRuUHlVc21SWjY3blMvenp4QVFyN0FrTXN1S2xLVlBReVlVOTAwcFZsaGRlNEVH\\u000aalRTREcxTjYvV0crdWN0SFo3Mm1DM3VYQTdoUUVLZEdxbUs5WER6Qmp2MU1UWDQ1\\u000aakhFR3JWbU5GaytKVHJFSkVsdEdRTmJqRE96UklORklxMVgzalRtN1pZTWQ4MVNv\\u000aOS91Tk14Y2hDcXExUzkybHMrUkl0elJJSVRjZVVDMkp5NVdtQjUzUHNqdDNWYW4x\\u000aSThBaTN1OUxUa2djaGk4N2QyNXVRbEhFd0RGMWZydjgrb3NubUZBQy9GbXQ0YXA3\\u000abjRKenFzVUhDV0RucVU4RjNEVVBTRXBsSEY2UFFNc04wd0JnaEdDNmdpTDFVU2ti\\u000aci81UUlhNlZWV1B1MHE5OFdyVlNCT2dnMUxHVVZvUFVXOHdlaWdRelpXYW1PU1hs\\u000aY0FkL2lrQmVaSW9iVlY5VDlDZytWbUN4Ynk2eGhBL2kvRzZDSmVjc0c4UnpTM1dN\\u000aY1did3RyeFZicy82bVhoWGtRZWhCckhTSDZyUTdvckdMakljQk52WXRyR3FJeFF4\\u000aNDRKQjJIdUdyTUR2QW9rSEJCYXMvWlBsOGdOTVZ0L2ZqQm1ZbFdRSi84WFdBT0Rm\\u000aa0JHMG5HLzRBUldUanpkM1lsb2xKQW10Qnp0YkNGWWkvNTlaWFZvV1hBbVg2b0g3\\u000aNUhvZmcrRHdmQW1nalYzR0VvKzhUR3VnQ1BqMFRJRERvUEUzV0IvR0wvUlAyRHRz\\u000aZVZ3c0pxak1UM0tWYjVTTHZkdjNLWFJXdVF4K2JNaVZCckZQSy9uKzhZNTJENjJi\\u000aT1NPZHVka01jQVVnaHpuRUpNWUJPZGtZNnplUjRLbnljVW5wc2xiTXhVRUtsMGht\\u000aL0JiM0FCUWdzMXVGZmg5QUVEUjJ0ZmJKNEd5RE5lZSswVEVYbDlTRHFRazB1eFAv\\u000aTEFMTUp2Z1ZPdHZqaVg1bjQ5a21icVdQbldWRGo2OUxPNGgxN05IWFNhQU9uNHk4\\u000acnVrSnh0akw4VTZLdTNST0tjMnlEZVpwNUc0V1dUNVVndjJQSUdyencyM2FqMWNj\\u000abE0ycmpqeFF2V1RQS0cvaDl5bm9GWjMzWm5LNkdGSnRYUTJFQ21VTGZ4OVZ3UDZj\\u000adWpzdVNwRVQwUlo5NXk4Tzc1dmNBRnhXNnpubnZSNkkvRlBxbHE3MzM5UnBJRUFH\\u000aTFRuaUQvZkJLSi9hS1RyMXlaM0IveldiVmlsYkdYWlp3UW9uZnptYy9qS1orVTl6\\u000aWXlTMTZ2Yy9TV0k0aytiQmpNM2hoS1pKaWJFeGpGalpIQStVU2lQS2Z1VDV3T0tx\\u000aU2lsbWJLcWJNbWtNLzNKelZCTlJtSnZwNkxHdnRJdDVJMkYyRS9DTXlPMjRHQ3RQ\\u000aajdlYjlYNlA4cUd3SG81VHlmWm9Vb2VPaXNMVFFmZXpISHhXUHFGeVdKY2VmSE9B\\u000aM0VjVTgwWHhPdlhyUWlKR2laUlRWWVB6dnAzU1ovYnJRRk51bHM2Rm5FYW1hRER2\\u000aNDJqSTRyVi9TYVFPZ3dRTHdYMEd0MCtvdGRRbjd4S1diZVNHNWhNbzFXMkdFRC9r\\u000aelpJRGM5ay8vZXdkMXg0UGhGekRFcjMzSDVtQ09mYTcvTi9KR2wvYXpFUnl3Qm1j\\u000aTDZ1enBFQWd0YXRrSjViQytnVy9objM3WDRRZml6cnZzQURXVU5uMTljK3ZzZG9M\\u000aelNwUmVzNDB2azQxUk9SakZ6eFEraUZnRTluVXZLSEx2ZnpwSHVkeGZKRzlRZGQ3\\u000aTk9mU2NRaisvTzBHbnhOZDgySnBXZ1p0SnZHRzBGWkZ6Z29aaXhBcWorLzIrRHJJ\\u000aUjRYeUdQa29aVDJLVGYxU0RNbTR1dEhuRkYyRldtV0hxWVYxSjdwMkwxZ01kYW8z\\u000aeVA5TDFFME8xMWNBSVVNaGIvMWhvSEFIbldBYlF2OEJQUnNVTE9SdUI2dENWTGNj\\u000aenlEY3UrR01nYWU3bUdPWERaTmczM0gyTnNmV1RJMWpCd0JSYUhYaGoxUHhJc0tQ\\u000aOVdnWENNQkxlWHdHV0s0WUpDdmNUTjZoUlIzZWZ6aHd2UzZjM0k5clVDc05HaTBk\\u000aWEdIc0QyRWV5RjdtYm96cm9Zb0tSWDhXL0Ntejh4TnI2eitNS1RwSWZmb3QrZ0NP\\u000aaTN4QkJxQ2pLdmg5eTdLMVQ2MkdEVElqUjdOaXEwUkwxTEU0cVFSbDFmNkNWMGJI\\u000aMzQvMzMraERCWnJmREVmekRSNlpSTGhycmI0c01DU0ZiaUYyaXlqY1QycVJTZkVH\\u000aZENwanlHcVZQZWpWT3VvK0JZUkhoZURqVHZwNHUwV0NBS0cyNHViM0VQWnYwS3Ey\\u000aNHZGOEhQclJIcFBSVkNqdUZHa0dNK3NqWWlkeHh4VnBDa2hsZmxZZnJFUjJSMGtM\\u000aTW9Hamkway9wYnlRdEd1dnk3RDFQZ0V6UEhCUUVHSzZhaTc2U2pWNU9HUUdzMzFz\\u000aYzJKMFlRME14Ky9wNEZtb3hvek02bkxrVkNObUxWMStPSXZHaFV3cEFUd25XZTZP\\u000aUFBHeUVyVFpvalZlZXVqa3Q2ejFzNUtVdEo2YVRpMWZxRlRiY2tmUGpaaGt0K2Ru\\u000aTUdmNHVxdXhza0VDYmJTOEVEUm1DUlM4Z0poM05GQ3VGR0pzWW94OVBvWk5BaHhK\\u000abEYzaDhFNk1UWkxNUFRrWHhHS3B0VndqR3IxTmx0VGRycVNKRVFtSUZTWDQ4cUwx\\u000aeWtudXY3WEV0TWxxUGxVUVBrd1l2THhpeHNqTHJEV1R5UG5MY3RRR3EvVDJ0cFp1\\u000aYjc4cXM3Y0NoSFNMVWV5OEt3ejVxS0ZpS3ZBTjBBOEhvalhzOElZa0F0NDFJdVZm\\u000aYW9oTHVEcER2Nk5wTmtLaUV5ckZyclVuZjY4cFNybHNiTHpSTmgyek9DTitDaXZ0\\u000aOTB5S0JXbjlUeXkrdHhIcy9EL25qMzl3Y3ExWXc2VDhlR0txVDR1OExOUGJ3L05o\\u000aMm1ramxQaE5SR0R1SUZON3MyKzlmYjhlYmJQRG5LL2ozdUtieWRjNEM1QWhDbUFk\\u000aYWpzVXA0Q3dpNTVGTjJreXRZZkZ6TTlyZk95T0VlZ084bzdDOFB6WDVjcENIbHdo\\u000aZmtMWHFwMDBPUktXZ0RQQlZnaVkyT2JFaU1CeUFOZFVOK2k0dVJqUjZJUnBMMXlU\\u000aY1F4Z3JlWmVkK1hWK3BwWEtWb1dVMEowR3o1cE94MDRYY244UUh2Zno3MjdtN1NL\\u000aWDdKaVVwY1dJc1g5UmZjdFlJb1FxSkY1endSN0s0WDJYV252NVBtTk9YLzVGU2Qy\\u000abXcyN240WlFqRjZYdFRUbzZZeTF5d2dzOUpELzdnSmIwTkczMjhQcU5Hd3FFUzBo\\u000aUnBYR2RydHY5S21hbzFjWFNGN2drVHZ5RFRScXRYcHYzeER5bXROSW1pUlNOOXlk\\u000abHV4aFUydG50dXVUVlN1WEUrTkJ1QXovQXdPSU05cnNOL1F6QzZXT2hGWkNjd1lF\\u000aK3pGa0FLVUJLUzBvSG4xbmR5dVQ5d1ZqbnVDL3ZhbWNTVmwwWnhJODlpcTc1Tzd1\\u000aS0V1dGt3Wlhnei9YekdVS01NZmo4Qi9oYW40WlE3MFRidHZDNkszYUpLWXB5RlQ5\\u000aby9OazZkMzQ5MFV4Z3AyclZVQnprV3JucmtZUy8rRkV2VUd1cW51V3BrZzZra2Y2\\u000aWmFtbTVidVk2Rmx3WTJIODVxQkV5a0haWGc4RU5tWVBtc09QOFM1TU10bEZYbXgz\\u000adnJUVUlRY2RtUHV4V1RYNlArSEtvOWZyandLMkxFTmhYUXN0aldZbW5VWW93TUZH\\u000aY3l1NlR2TTdWZDUrb2VOU0tGaldQNGgxbUFMNVYyTHZWU0JSYTYxb29mQ3VPODZI\\u000aWmNQbzRPNEZoVlFXeFkrYzBLT0tFbzVlSjZiemlneTVvclM5WmY3OTlQTXdRbVJy\\u000aZmVjWDF6R3ZYMEZTeE9KdzZEM0FVZ1VhR3dSb3M3d1FlREd3QWdmUGJ3bTJLcFda\\u000aK3pGK204cTJXOHlUbitGR3J5czJ2bXJKczRTZ1YybU4yN28wRFRQV1p0a3h6Y3gx\\u000aU1JoUjM3Z3d1NUdreGVpL3A5NVdTeHNVdEozUUd4Rk91dnQ3T284V09rRjNlN3FK\\u000aSnQ5U2tYSVVpMVNGYzVRblZ6Mno1MmYzVStabzlwdlBVVnN2UlkwelFuSU1xVTFE\\u000aN2FwTEdhWGltMm84MWszQ1gwVmRJQXlaYmlGUHVEcGtZOWdvcE1FcjgrclFIQWRB\\u000aMlRZalpwQlhCV3NyNDg2Z202Um5tc1luVXlRRnFTSkNFcWhCUnhXekhBQk5GdVZS\\u000abEF6ZE5DV1Z2L1RLVXV4WmV2bTVCTWNyL3V4ZmgyTDNpUmh4Zm96cU5HMnh1RXFS\\u000adTFSR1pTRWFkVmUwaUdUVlhWcnQ1WHU5QXMxdXY0QlJGcm1GY0FpbWkxQ1ZqbUJq\\u000ad1pPNTVmeUdrL1haNGgrQklkaXJyK2Vxdm01ZmhZV1JKMmk1YmNUUE9WYTFpeXlm\\u000aZUlaNkppMC8wMk1BTVdlSzB4L0puWW90clJXblA1MGJFOC9XT3hTZ2VMRFNaLy90\\u000ad2pGaUpSTlpEQkdZcCszZGFrZ0R5VHo3Q1hWV1FRTFlGL0NLOGpXRXI4RE9ySUFp\\u000aVjNheFBaNG96YVlqWGVXNHNxQkpkTkdkZ1VzV203bmJnMDRNcCtIL2dDbmQva0py\\u000aOVNmSklaaXdtbnpJR1hXVHV6ZjlTV1ljYU5DK3dzTVBpQURPNjJsUDhoN29xWk5F\\u000ac1dpQmRTTEZ6ak9zdm5rM0Rvak1GeFFxTzlGaHF4ZWtFbmtiS0xoTFQ1d0hhZ1V6\\u000aNE43Vmk5ejNRMFI0VUoxV1pHVGF5dDVkVElYZVppWkpyc0dVc3BiVEFQTElndnM0\\u000aais4aXFwL2pGZWNpclpDRUpuOEo0V3R3UWYxYXROWC8yMlpQWWpZb2lqYXVWTm1l\\u000ac3lTUXRIbzNFYVZmVmljRzUrcHQxYm1ReE5rNlh2ZHUvbVlkVUpMSFZ6VHVpcDVO\\u000aYjdId2VYTFo5WjZwSnZMeEdJSndmR21HZjY5a3Ara2RZODhHN3JvQnN0bk9lMVZU\\u000aUjVuR0lyblhJRDlqcXdQZWF2RlAzV3BjWXRsdzJVQStZdUVVRkJkUkpDRiszdkx0\\u000aQ1pyUm4xNnlYU2tRN1FpSmdHeXV2V0p4QUdZRzYxZGJ4bG41d1ArejlWcUlyMUVr\\u000aY0pXcjZtME9takNJOCswL3lFNXdGbjdEbHlWRWxVRW5ZNzdyOGh6QXFJTUMwSTI5\\u000aNUpnc3BGY2lSaTI1eWRLMzE5c3dLc1dHVFEwZ0xFWlVnNDVxWjAyalBqRWRsM2ZJ\\u000aTm90VGl6TVBVWkdHeTlmK2JpOE9UYld6NlF1K2YxNFk5UkltbWx6N1BmUmltRzVJ\\u000aZ254ZUljRkpxcDBacW9WZ3NpeWtyTVdIaUdDVUMzejZ0d2FnT2lFZlU1bXJ0RGJn\\u000aVkU4NkFROVhWZ3hhZitpRzhYb1JVNmhIVkpNM2dhWk9EVmFYY0tiQkg5L1NaN3p4\\u000aZlI3UjBwVnJyc0U1UHE5cGJ0VUphRmRvK2hpQnpxdGRLdEJrUDdjYkFEVER2eHU4\\u000aYjhkSDdhYVMzUzlxS0dmaHUzMW0xK0hVSjZHYmhTRW9sYnlGcTJySVkyV1p1K3FX\\u000aUHVxU3NtV3NEeVRDSGJ0d2N6RVkvOCtUdEhUa1pFYmpkN0F0RGZ6dmlJRW1aazRh\\u000aRFpCdEdYMTc1NlFIb2hJT21KdGVPTWlqSEtqdk1VNHlYZVh3VkkwcFVwc09JZVhZ\\u000aNStSOWVGQVFFZUJTTG9FOU93ekpOYm1idFJvSHMyQVJWUFlaN0lZMUxOM1oxdnNI\\u000aYVY4czZVbnB6TXZNRjBMdGw1UmEycmxwa0NsOHR0a3p3bDF0T0NVYmRmc0d2UVhu\\u000aZktjVllNN3d3bXFQakFRdWJpK2dEcHZrcnVFZTFxekd1NlA4cFlsY28yN1o3WUFE\\u000aL2dzL0s2ZittSGI0VXlpeXI3cklaampSb2c5UWN4NDR3TXF3RWZvbWQwQXFlbWo0\\u000aQTZ3Q1ZVSjFUN1ZwVmYyc0FSWWVnLzAzbWMvTzZySTZtSTVTQ0tKZ0J2UWhvNEN2\\u000aWVYrNzNNbVg3Z1dNUHRkUExydE9vbk13M1V5aEtxODNuV05nSUFhbDZySlhaV1Bl\\u000aYXVVbjVVdm5jeElNZFMzWjFjRndsRHhVd0ltRytGWnJrTGpqWm1XaDRjdzVGOGNj\\u000aOXhSZk93WW5aaTJJMVRUeExLcTlDOUgrak1sOUxna2hoemtWZDFSZUFkcFpZYUdw\\u000aZnlSUzZsWlBWaDZiNlA3a0lsdlhremplcDhkZUprNm5ycWlQL2ZBdFNTQVNUcTdY\\u000aVVVQUEhnSW0rNTR4UWcrdlQ2MHVHY2ZPaHljN0owd29ia1lYMDJ1Q3p0c2lranRa\\u000aRW03WTEvOWRjekx2c2xodUZ0d1UzTWF5Q0QwakRmRkhKbVJCMmVLWmxRZHZmU1A0\\u000acmJ6SGdwMEpzQUJlNndTMlkzdDd2VTJDdklqM3djTlZRTkZCQnZYbmk5SWNxQVNm\\u000aREVWMGhYc3F4YWtQNFAvRTVDMCtkNVR6eDBIRlF6czk2ajNEcnlHNjl4eTByRzBV\\u000adGZLRDBmK3VMc3NQVERybWNhU1ppVXh0WmJqbGtpR0hDU2R5YVo2RlNSYWhMcXpH\\u000aWVJ3YW9wRENDVHhQNXh6WnZaMGIxWDlveWE5c2JRZWFEVEtJZmdmMnc3RVEyZEZn\\u000aLzdCN25lZUxJSVdWTXZvK1pzMUpsR0RuWWpvVUdRYU9ITWI4ZFlIWUJnbEZ6UjJp\\u000aZUN4SjFhU3haQkFQNGFtalErQWp2RDE0MXk3WWsrVnNMeG9jdHcrbzVCRndHOU5m\\u000aVHJzT3MyQ09IckRoZW43TzYwMFNuNWh6MVNhclJHbzBTQjZBOUxJdnc3OUwxZFJ1\\u000aeUc4aWVjaURhRmVVb0M3OERCTjFGRFJyNEpxYmlHTjdXZ0JLQUpyRmd0L1dZMjNV\\u000aSEJPTFpOSHBGZ2lwNnFmNEtTNENRWFFuL1o1MUx3MXhHQUFRSWc0RUxGbjlDcitz\\u000aME94czZkWXZmeVhMWVhiOXkwa3ZyTnZXZDVZUkFWWHZENkFpVTRtOUJZNmZEWFNa\\u000aWm9ma0w5em1BU3Q4anpVZnRPWU94OWVqNzRJeDRQdmRyYmdVV2MyV3hvOWc0U092\\u000aTy9jVlFjd1RPYmFxNkFuVjZIVkl4dGtpakRkeG96dDhYTEJCdVBncFlZWnRWcHJ4\\u000aTGlVb3g3ZGpDRml3cVVYZEo4Mzg1a1gvcXdVNXlYZWwyMnM2c1BHSU95RlI4REw1\\u000ac2ZacW1Qei95bDA1RGJMaTBoTjlBaU9jQStVQ1ExT1ByVllNZ3ZqUjl3ODIwemZh\\u000aTStmOTgvNC9FNW5mVWoxdXlwU3RpbC9tWTJqeWZxd2hnaUpjcFdhWWNZenFQYkY5\\u000aMDVsUkJpa0hNQTBzSGxyeVJpUVdBc1Baa0lxclN1SHg2aGpHSDNGeGpTSnYxZzhp\\u000aVHllL1V4MDBucGVYV1c2ZFg5cGJHYWlOcmZDeGZlOHQzWDcvc3dPTUJyR0VEdEhr\\u000aZWhoWWNybm16U01yZVY4dTV5dDVFL3dmUzJKejNTeGVoTmp5cHhEQUNFSDk4dTFJ\\u000aUUg2d0ZaanlHYVhSQWNqTnVqTTNPbk12NHFKSThzVTdHcE02VHZFcXdrSG0zUjF5\\u000aY3ZhSTRDd0l3d3FzUFlFdUQ4dkIrNks0WGIzQXJzTnd3Qm45ZjZqZzYzZlFvbERL\\u000aZG1zbEJiUGhkdXY3QzJYM21qVnJBUnl4bWdKZGhKckNmbG1hU05rTTIzTWxCZzRQ\\u000aSVR2ZTNhSGFxVnVFVy9jUHVPMTR3alBGdzNDa2RzSWtuancvWTNkOWJiQzl0UHVC\\u000abG0zcXRMQWhSWVJtT1dvWE9malFCUG93WldlMm1RQnJ1TFV1VzhhRG5WU0NTVUNw\\u000ab2lWWnVNYXhuVWpscTAzZ3V1OUcrOVRPZU8xMnJFQkY4cDhtWVA1STU3aWF2enVP\\u000aUjZQa3BWSU5ERVRrQWxqNjZOMDA3T1Zid0IzUk80bDJYTHV5emQxWDI2b1VFUTVl\\u000aamp4LzY1RUdZd0E5ajZpMFE0YTZkZzkxbDBMTndiaGhVbk4wM3dvM3BTRmoraU9F\\u000acUpMc2RUY3pkalllazFlMFlDYU1wVW9ITDlzVkFlcStld1A3VU9wdisxTlF1SnM3\\u000aTWQzUVJnNW9RSzN1NzhYdXNzaGpTZHFpd3RkQTcvVm5SQzN3Mk01bWJLd0VlVGNT\\u000abjl3Ri9GZXBGcTkwQ29wL0hGc1hxeXNVRU51NWtTY3E5dHpESmhnOGJpSmJkVXN4\\u000acU54NFRYWmExZnA2ZU52ZGFzdjVsOUo1bnBmWDZvbjA2MG9CelZvMk9JNXhRMTBH\\u000ac0J0MW5YNWIrQ2UySjk0ekVObXQrYnFLZ0VoNUlzWlZ0YTlhNnYzcWhtYmQvNGJK\\u000admdhTzVmNmd1Y1BRL3JxcjFVbGtDa2dQdnZyWm1zWWVyUDlzeWE2YWhBbDJHaGo0\\u000aekh6eTBDSytEdkxBU0s4MEhCN0tWZFc0dUpxRDYycGlLYkxKVUU5aUhoVTRRVVpu\\u000aeG14eGtNZmJnQS9pdVR0NG9vdy9LOWtIcDkrUWJVazlFUGc5Rno0TVE3bDNiTUxo\\u000aZzdVMjR1N1hTdlR4TUxuMis4ODB6TDNudUJhRUhkYTRic2VDYzBwaDdOS2s5YUFl\\u000aTWF0cWZycjNTSVpycklDZHVETkNhMmRVZXl1d0x1Lzd1Zi92Wm1oVEpaV3c2MjlG\\u000ad2thdjdhaGJRYU1NZ042NXBhL29BR2IwMXJrc1NYZ1hkRjdhc3JVR3YzSGM5ajhu\\u000aSXh1NThqWHh6TGM1d2l1WmIxRFB0OE9mSmdXYTBGeVJKajZBSEY1SEdicWFGTTlV\\u000aRU15SXU5Q3I4c3BGNHJURTVBNjRrb3hqZTNtWGZIVVNVanBUemtLMlllMkpLaFk2\\u000aY0dYc0t2aE4xbHlBblNQTEZ4Tm9sc2k2cHJDWTFaeUdQdVl2bm8ybDdQbFRGblAx\\u000aM1orMCtRMGxCdG02eHZCQm4rUGl5bWxtOWV2TUpoeHNOeGlaN2NZMzNPQnl3NGJ4\\u000aRlQvN2RmUngyUWxxT09BTHI2a1c2ZXI2WUVuQ21CNWdGWDVsSEZML3UzQTRPUFAz\\u000aZ3k2aUdjQ1pPVnJrOTdUQ0NZZDJ6UTVkZVFKSWlKeFFQQnlGbVlQTzg5eU40QlVI\\u000aOWtRVFNDZUdvbVYveWNIYVpkSGwyQ2JIVFd2aGdCcWFiTWJYSnhWRVdac1MrLzJN\\u000aaGttZE5aSThaV0VnYm5odFlXVHUybjhtOGZBREYwMll4UjFjTG9Fa25FN3p0TkpZ\\u000aZE1MZWUyOEMxRk5kbDNtUzVyRlYvclhXVUdtQXAzZ09Lb1NXUmJMRDNlSi9ybE9U\\u000aL1NwVGJFUDVJNGdsQ3AwOHYxOXBMK2krTDlpSkVhWmp3dHd2M1BXRElBekkrWWlr\\u000aZGJnR01uYitYeWwyUDk0R2c0cVk1RTRQN2ZTcFllaVZiVEJleUpRMG9JUzhuUDlI\\u000aUHpwV2NSRjNFOGkyVmhCSU1aYjdSNWtJSVdxa0lMbXJwNnBrejA2NUNKQlNDay9U\\u000aYkYzaVhadU1kcE9udFhMYk5Wc3VGdVJud2FYZkpwVE5LT3U2K2VTcC9rSDE1cFda\\u000adjVJMlFSN0FGaElXSHFCYXo4Z3k0QzdVcS9uVWVqN2ZHM0V2c2ozTVJ4YlNTUjhG\\u000aSnFGZDB4MSt4SzgxTnM4QmlqYUVPV2xBRDFvMU05WEFGTXFWM3pVNEVuQjIwaUl3\\u000aYW5DclBGemJidWNUcVU4RHMzb2k3Yy83emU5Z3ByRHFtK2hKcXRTYXEyNkIxeXZp\\u000acXl6VTd4UVZEczU5VCt0VGkvdDFwalZkclJIVWNWZVZSQ3h6NFl1N1k5TFVaWDA3\\u000aM2o4eXk1MktLZXk3dk95VzBkNWxKVHpkWEpmZkhlQlNhQ2ltMnVwZWZaeTZKeTla\\u000aZWkydDBOMENIUUtzRnkyQk90bTl0MnNUUXFQREJFR0dDdGVRTFB1Y1BOL1doZS93\\u000aZC9Ma0cyNXFOTit2MTJybUNWTE9CM1JiRFpOYnB2Yldxcks5azR0UFF4MkM3M0d4\\u000aeXNIMjNzNWhJOEtvWVVJSEgrQnUvMWF6SDVZTjVhanVXcTNKV1hZVHk1S1crOE4y\\u000aamdvNk9qTENIVzBzUzU5TXcrQU1MajFCaWl2WG5Uc0xTeHBTSVByb21Dei80c2Ri\\u000aM0N3a296akZSOUxLRUJTS0NNK3RxMXA4ZUtTZ3NqUzVuaCtwU2NNRkpxWjdhekRB\\u000aeEhXYVoyNTQ1bWpEdVJOV0Z2M1lsTEhXczZBM24xSExCdnVOUWs1ek05RnYzT2tm\\u000aTzBqOVlVUWFnWjdCMTlUVjVCNDhwQnAxNGdYNS9TR1VmOTZOaWQwWmdURVhQRU8x\\u000aM1JnRU45cWVsazRPQk1icXJQNlZ0d1FPT3BjNXVEWHgzcEdWQkhTejZrb2JRNDV5\\u000aU2l5SUI2L3BiUGlsbjlDdmhNSWVyNWp2YlZneEtCdkFyajB4RFRWWVpGcVVYZVhz\\u000abHRlSE5WN0czd0E2dG9DWU1ZZ3R5UHRtWjd6MDMxZGVEemtwQnBBV21HOW85OVEw\\u000aSC8yV0EwaXNQdVVhbU8zbjFFUG9BRFZQZHF6UFpUOThPeDRjS3kyQmdBWmJBZVgr\\u000aR3lRTzgyblhudE1hWmUwbVV3cnFPbE13clZZNGhlaXY0aFEwOG1VekdkVXRSY0lL\\u000aTGpITm1OcXZvdTdlY2ZHdVhTcnhvMXVJdkdIbzNuVlVZTWc2ZEFRRlpnWUh2ejdZ\\u000aREFKWTBEWGYzTHVFZTR6bVh1azhlNm4vVU5BbE1ZQUlvdEsxY2Z2TDV0bnQ0akVD\\u000aRFFjb3lZaDRjUlVFei9XUXdudEE4Wm5sQUxRMlJOUDY0NXhjU0JOMEVCYUkyb2tB\\u000aNXI5TEYzK1h2UjdxQTB4b3VoNEMrNWZRTnpHdTdwTjFUck9WblYvQXBsMlNaMmtD\\u000aTEJQN0hjWWt2b3ZBYWFick8zeGtrUmtsdFRCd01rR3RmRC9NTm13WW14NTN3U0RL\\u000aUjE3NG1uckRCRDdOb2d0S3NTNG03Yk5iZUZyTE1hdDYwYmZVWWsweFp0YWxuSDdP\\u000aU0xqcURHdmhYQlBDaVFLNzNNVXppdU1qWFZXMTVUWWJDempuMHV0Q3d4Szk4TVlv\\u000aY1lNV0o1UGQ3WG0zejRva2prNDVFTU9DZVRGRmdZclpVNzlWYmdERVFpbUd4a0Ni\\u000aOGR4ejRMZkh4N1NGUXVhSEpNSjh4SUxZTWFSL3doQ2F4ODUydlNRaElJWG0zZ05n\\u000aWHNyeTZ3M3EzLzQ1WDd4OHVPd0p1T29GUGd1NEtNVDBTUkUwSmZRaFhQUDdpTXVJ\\u000aYnRrd0ZXeWxGQno1SmhVMzhzZ2JGdjlaVnczQzcvbnFZVUVDMXZRWHRnbEs4bGJj\\u000aazlUMzU5YVFpclBkcHF3NjA5OFFGVktyNmliTlMySk0wTHFlM21neTBYQ1RTYXUx\\u000aVE4xeXN2SHBpdU1jSW5BZWFyL3d5b1lsek5BZU1kbUQxUTduaWNBK0pWTWM4elJn\\u000aZ1NKcnRoZDZ0emd4NTFFTUNoQUpFaGR6UkpjRG03Z2c5eE9TTzNPTGpRdW05K29k\\u000adjY0b3NZNVNtbDJHSkgzZ0pzRmdyc2d0TXpTMCt1dnYwdGlZY1BoY0VsL040Vlh6\\u000aV1FTNjByZERQMTlUMFFYREMxc1luSS9rZFREcG40WnNyNFZOUzRkM0cwaEQ2Rnh3\\u000aZzlVdXBzN3k0MjRzcmlOWDgzZS9CWFhZTzNBWlZCS3czUlBVWnl1RFRZY0V4cnFM\\u000ad1RPWnJNQUJrVTBuNnBpYVRqMWZhRDJpZUZxcEFycGxIZzdrTW5ZdVN2MVFDekl3\\u000aL21GR0VEWVFqSWFiWXNRelZMRzd4YjJxbkkvTWdTbUdGUFN1VkhKNDBMNzRPYTh5\\u000aSklyeUxvV29ZSDZYZGo2WkdqZXlpT25YcEJFOUgwT2RlMUJJMkJTTjVwWFFZc0hH\\u000abFUzQ1preHdHdUZ5WnVzamVDRW9kZURPQ2lveUJha2kwSzB0cE4wTWZYS0Zubjd0\\u000aVitWb2FXV0dQSEtBa2c0eGJIcjJnYWltWW43UlN5cVcvcUVkdzFVTEgrR1RMQVds\\u000aS0F0eG1LR0ZnNkhtNzFtY2kzNXBGTW1QakROeER0RktZWm40Y3RMZURIR2ZVSEI3\\u000aZlBEOHRjZ0c0VmxTSktwTWVYR2RRT21qMkJubFQrTFYvN2JLbFQ3aSsxTWk2QnVZ\\u000aUmNBbW1GZnU3ZGF2Z2IyVFRvMVM4aTNPdkNieTgyMW16OXNjZllyVjd1bWhYWTJU\\u000aU2ZIQllyeXFtTzlHOXBuSGpTejlsTko0aEdpdU1hR3hNSWhOYUE1Q0trNTd5OEE2\\u000aSW9hWjFWL01BRmJyNXB6RXNlckx4VzdLbld3cjB5WGE2U2hCSDVwSGFXR3hRRlBS\\u000aNEs2bEJKZXpjUlM1ZUcwdjV1SHBQWTYrR2J3dFBUNHBDcENIdHBKNk56dlNVNlFP\\u000aNGVHYUY4b1NEV3pPRXRJVEJCdlBuUWFxa010L2V3Vi9qZldMNVhJbll1aHV2RGtu\\u000aNnZhbTRzenBONWs2WFRYVjh1QXNWY3VaQ3dLRXBKZldSQ0V4dGZqZVIzZ2E4U28x\\u000aeWg4Qm1QSFNBd2FxOUVHc3pBcmdScm40QllKZ1B3VWZ2WkY2c0pIV0pKSm54YUdI\\u000adUNBK1dHejBrcFRpVlJLYVM0SkUvODBHOUxKZjcvTTlvWEVULzFTbWRUaWEzM3lY\\u000abFVSb0xGdVE2OWZuTzhDUzVNM0IxM01HTHN4Wll4aUdTUkpYYkxHVWQ2bnNsQzJ0\\u000aNlh5SUZNdVFtSFcvQVJSNXVNL0o0VStWSUdUZlFPTlowVnZoQStuNlUxNDRtR3Jk\\u000aU251dWROWEpXRk83N0JzZWp2dHMvRWJXNHFOcHE1NWNQQmY0MzFEQ0NoMVJNdTJ3\\u000aNnZUZUJRNitJcllOMGo3aTllcng1UFEvYXN1NkRvMnNRWFZhNTZHVXFNUmJKVUNs\\u000aaFBNM0F0SDFmZ3VucnAvODU3a290UEhkUURBM05hOURNT2lvTEpSM3puN0tiSWlU\\u000aNEo3THFtbUpET05WcW10LzdpeGwwTVlDTDh3azFHOXlnWUhxR0ZsWGoxUXpxTlVS\\u000acHhUU0pualYyTjZOejZmYy9MVW9NR1E5OE5yb1Q5YjhhclNBcVN1TmhCaGwvbEto\\u000aNDJ4QXp0UVdDNkZEY3Nmd2FrUUpGeGs4OEdWWk9hMHJ3UFNEM29LcUMxc05sc2VW\\u000adzVzMWRjK2dodzJKTGRmeUcwWk1yZ3NaQm5uV3RHanhEdFg1WmUxZ0VKbUo3cnN3\\u000aTGsvWW80S1VuWkZ2REF5d2t5VllMY2hwMVJ2ejJKeTNGcHVpWU5sRXRkMHZKRjlX\\u000aR2dkeUd2L1JpN1pEd2tybzYxS3lMallvMVhaelBmUTlscEVqMGRTKzBCZllZUjcv\\u000ac0crcW1qZEZFb2YybmJLRWVaU1N0K010UTdnR1ZGUy9ENmtvWmZNSlM3c0svSTBh\\u000aekVrdkxRR0hTWDN0QW13YXB6K284VDlEYUZxTDFDYjZSNXluUUNucjZ2Vk1QMG1F\\u000aRm5GbURxWVMzY2c4cldyeEdrQmFUcTFDTDZKblhzb0x4dHMxV2N3QmVmR3NyM2Yy\\u000adEZMcXN2TjFHOG9nYm1pN0JDSWthcFdEK3FzRUI2UmtNeStGRVQxaEhuMEZyNEk4\\u000ad2l2YnE0cVpsd0NncHZ4Ui9tYU9iRTZiTjBjK093a1dxcEpRTUl5aDZJcXZsTUtP\\u000aR1d5YmR2aWEzemJMNk5XY05IUnk5aWl0bERzdjJSNy9QMXNqR1I1ZmI1NGRkbXhO\\u000aMmlFVzZLdEFZRU5Bb2VwSUtrWkVDNUJ3QUNYajZrM1Y5dXBNYzcrZnlOSEFBbmZr\\u000aaTZ5amRVa1BZMzVsbmNhcTJRcDd6Q3BWdk1qbTlTK1dtWHV2ZlNwc3EwZlVxWlN3\\u000aNmluZnpncjhlNy9zZDhIc1hVL1BmSDY3S0ZzWElOQlpMVm41QXF5b01YTVVNY3dV\\u000aVCs3RjhnSGl3NUpRcnhELzhvcVhUL3dvLzIxcFJObXF2ZDQreG5hcGtDZnBpOUlv\\u000adFNjd054ZlpmelkrdDZyRmJyU3VWMXZQVHJaSWNrT2ZXNmt5MHp2UmRCL2hna2Ur\\u000aNVBvVGRnd0diSnp0Ylo5R1pYSGpGZFVLWFFKVWxscmJWRGhUTkNoakhxNGE2QzhH\\u000aWWRMV1hxNzZxWlEwWnhvRjJxdUtkM3NjazEvaUxIY3owMEVuRGExK3BXd2VTMVhU\\u000adUZaR1lFTXNGeUptWSt5QmdRK3Z4aHQ2bFArKzZzSW9pbUF4cUMweWU1SC9McHFM\\u000aaFBTQlVpZHppcnlTblZ2SjZmcjI3TVRQUTBoci9JYUFXRlZnUG1yNEdqd3gxdWh0\\u000ad1J4aVU3K0lwUUxNSVVZYU1nVldnaTZvbU5aM25mcHZyYUdwWWxvaE84Z3ZXK0lL\\u000aWFJNWEJBR0Y4TlQ5UG1ZazNXa3NPVU8rVS9XKzlOL1d2algzc2haZWpGd21GYVg1\\u000aWVhyREE1MS9icDRvQWlIMzd2TmZqTGxzd1piZ2o4NVFsbXBydlhuY1dnS1RZN1pP\\u000aSmMxcmhmQnA5ZUhuUm1nQkVyNHZXOGROdkxibVFSa1dhTmxrTFBSeGd5NHU3d1p3\\u000aN1dmZnYvOG5uWEhsbWoxNDVWQ0NxOHlJR2FiM2tqQ1dvQnFQbnh0Vko5VVFNME9D\\u000aSVFhay9mWjJvdDV6Vk92dGhJeE1pK0MzNVAwRjVkUi80RVBaS3g4a1AyVnZ6RkZy\\u000aN3hFUlBSZFJnbjRqWDlFREVZQTJoWVlwRWRLRUdGai9aZTlKRlJrNmxQZjlVY05Y\\u000aRkgxd0srMW5HZi83WnZzd3dSYnNzalZjRXlMODVQU2F5eVl1ZXQrMUZ5UFpKRk9J\\u000aRnVSRm9vMWhaYUp1cGlTdm5yL1VSSXlGWEhMQ1B2Sld5MnZQVzBibVphR1NRVEJZ\\u000aYlRMcVl0UzBvdTJxOHVBd01vZUYyT25FVDdaTENjMVhTV3lFWWErWFJ0MkduMHBl\\u000aUEkxUW91NGduby8yRGlrN3NxTERydnFRbVpTOFNISlFSQVJaSnh1UUJBWDUrNzgy\\u000aYU9uaWN1aUtTbmwyeHFkM2pYRTRuUS82S2phbmhlVXpzdVRrWHFQcG4xbWlPQi9H\\u000aTFNUQ3VaWHRXcjdlSFpFb3RhZ0pOQm9OSlBYdG5KSElQb1VTdHpGTG9HM01Vc3dY\\u000aeFlCMG0xc2FjaTdaRlJ5cU1sMGtvKytlN1VCSEZOMi9UNS9ybXdsbEhaZ3A3Mm8r\\u000aWjZzWERyVXdxMW8zSVVocnRYNkJPYzJKOWladTVaenVRNkxNNkRhY0Z4bEdtcXRh\\u000aeDB3SlQyZkxpblRRU1ZIeDZDeWRMU3dTcDREOHlPd00zUEc5Zks5VklSRm05S2VY\\u000aaEd3dWxyMXBHVTAwTDU4QUVBb2ZxRmt6eEZneE0vRlRBTVZ1NWxCd29QNDYycSt6\\u000aM3pHQXkyemFTcndJKzdiWnd2OHVTMnpKOEtPajU4MHpKb2JOdU9YdC8vVHlMOGFV\\u000aZ1BtVFB2aTV3eDJGMHRVUGlzL0tUemZoZkR1NTExQXJOS2szZXIva1BrUTVmL1BC\\u000aTVBBSEpPQ3crLzh6NEVDdE9tL3g0UkliR3VIbDExNzdhQkh2WDc1TzloYnBaSkhV\\u000ac1ZlWGJOa3VUQjU2YWVoVkl3T3hHQitDeTR5eGZDb1JJRENXdy9oa1FVNjlZUUhL\\u000aQ1dhUXYydE16eVRkOXFsMFlRc3VBR0h3TDJTWTVKeDJ3RjZ6elMwRUVCMGtCU281\\u000aNlhYZmVwRGZnclVleUlzV2Rwc2hrQUQ2T1NsVDVaQTFHMWtpZHMzRUZiSFlxbmJh\\u000aVzFTZUtoc05QamVBcWErWE4zNnFYQ0NVclIrNlJDK01xTVc5a29XWjFqSzZqMkNq\\u000abHNWVjhkVGI5OXY4alVuSEgrbCtrbituaWo1MllRRzk3eCsrQkVMZ0FZVWQ5Ykxi\\u000aMmI3OWYwSnJYc2s4V1psajZ4Q0l4VXI5ZnZ0c05aa3NEWTI2NXl1VGtoNzE3Smho\\u000aaXFaUHowVi9HcGdVaHJDSmdhbVR1WEo1SmdMdEtJZ1Y4WFVQWXd5QWFUdGpvcGJT\\u000aSmx0MDVJVGtka25LVEZidjNxd28xNWllS1ZBUHhvNVVoZEN6a0xUZ1hyWStjMldo\\u000aOGd1R0JPbFlSVGVRbUlHK1Qram0zRGpyMHVLSEx1U2lmQ3JlMXdyaHp6dUF6MTd4\\u000aaXVkbFczR1I2UGVmbDZOdUt5WG1VU25LL1F6MXJNZVVjT2p1UzBmTkdlWVQ5bHNz\\u000adGt0Mm5TVVdKZnBaQzhZRGlPWDd2TUZSUFZOSXo2Vk9lbHJDS0hHMXlTc3Vkc2JP\\u000aVTRiMEg2KzVPVWphYlJuOSt2YnQ4T1BNbE9BVDBEcDJ1TnMxNlBSYjJPMGp6NWlo\\u000aL3FwYjVZMENnK0VlYWFPMGdxdXN0WGdDUHJPbktYM3JLcU4wUG5lMXpmYkZqVklJ\\u000abWk4NjcvRGUyYmt0RThtdTQrWTJIeUg1K3JUVnBkMlRxWExaOUhEaUFMaWZ5NjJL\\u000aWFVjQ3NEanJEMGhyWTdYZzdTNnVjSW00ejNqSDV0amtOczZxMEFqMnhscG5zbi9D\\u000aejVmd2FPUS93ZEpPSjB5aTVtanRjOFBRdnJ6UFhNQ0tIZU9hUGJmVHZ1SmFwOC9Z\\u000aVmpTNkw2NjNxNVVkaFlGcTJlblp5ek1LYUwvU0RmYVhyZzZrREw4d1podXZuRlJx\\u000aYmthVmp5S0FQYlFFUGhvdmJCYW5DajVwUGh1MHJoeFh4T05rbkhmaDhneGxudWlx\\u000aKzdzTmxoeXBSUXk2N3NNSVluMmdnS3dRL0ZCVlZ4SXBRNG5oMUw0ZldOS29MY0tX\\u000aZFBCSktHUUQxNCtPUXRXcVEydDRKYS9KVlpxZVlQRFJxSUtPNStEeUdLemRPK2Q4\\u000adTJhNUZkaUo5UG9SUmJqekszbnhYa1A1TTgvYytCWkdMK1lURmtVOGREZW83L3I1\\u000aeDVVOWk2TEhpT1FhMDZMWlpGQWttSEdMbjhtNVRPbllWbGhzdUVlZUdWU1hscVVh\\u000aV1dhSFppc3FrWVl6am1Cako5T3JsUU55aEhRR3Q1cXFNM0FTandMQitoQ3dwaXZH\\u000aRXZ0aStHdy9IbDZiQlpFa3FoaDlCUlh0TU0zT2d4Rm9kd25nTmpHSUpDak1xZGhk\\u000aTkFjNWpBQWlsUlJ5dWRQdFFsQ2tObHpCV3gyZjhCMDBDVmZQNkwvd1J6WFRFOEhR\\u000aK2JiL0F6SkhCYnM0YjR4M2o1ZnpOS1doOFJZc0x2VklmVkdBUjJEcjlJTUp5NkpP\\u000aTzIzdlRmbWVPcFBudmpvdlhkbTI3WlcrdzdGSElrdU1peENqckh3NTgvQjkvWUx4\\u000aVGRoSzlFY1dOcXMvclA0TEYvMEJVSS8xdVdsa05pdTBJNjk5UHRkWTdzQThNVUdO\\u000aT3VhTTYveGNZN25DMGRjVXRCcjBXSmoyZmRtYmlTM0Nld0VrT2c2L2tQQkNHVHVi\\u000adVNSdUVLYUNWNXRFZktlZEtERStIaTFuK3g0U3h6U09KanhYZUJTb2hEWTdlNVVu\\u000aN2ZRcHdvVEdiTUVHUjZJc0pOaUNzR0dSbkR6ajd0aDFSOE94ckVLRWx1dXQ0Ym9u\\u000aOEo5ejlxWGRVSUtlQ09va0dQNStrWW5BbHBrNWVQNzltM1gwS2dSUW9kSGN1N1pP\\u000aeTRBdm9GTXpYd0pFVDdzYnNaQVB4Z21VeXZFbDVRdzNBQzhBaXRybmFBWm40Sml6\\u000aZTdKSEtFdXpHczlBa0IyVG9hWXcwRE5zbWdzSncwWElTSzFsSzBUWjVDUTlPQ1VN\\u000aeHFZYWNPRTEwa3VTVUtQTUpoTHo5UHhrRDhnbE0vZEV2OWFLc2VqczFXMkF1VytU\\u000adldzM0crZ0cwRkNHajljeEJBa3VRSDZNb0tOMG96VWExUTBxcU9JRjRiRFZJZFFI\\u000aTHE1ODRvbTluU1IvV0ZIRHY1dWxSeTZteWpIMU0xUFB6azJ6K1drQW84TFhRaXpM\\u000aWjZmblFpTEZ6OFVzZGQvTzVIM2xCcUFUZUpvRzRVdTRCMjVuRjhOK2JabEdoM2d6\\u000aK2xTZG16YVlUR0oxWFZPNTdNR0hla0dyZjJRZndoeU1zZFlsZFpQZXBNQnB5YU5R\\u000aOXpvR3ZNQ0ZnYlR4c0JFRmN4aWM5TmdZUWNDVk5xcTBnS1F6SmtxUHZtV2o3WnpP\\u000aMWZJS3Rnb1FmZ1k4a2JSSFRPMGJIRXlsNm5EcldRR2RXbkQ4d2ErNGNLSnU2bkpH\\u000aWng2QWVGdXI5QzJsZzBWdWZGNGlqVGVrcWlEb3U2Y2x3czkzRHdWa2VPNmxsQzJm\\u000acUpUcm1zQy9DTC9oYzZuckZ0RERsV3Buc0Jkc29ydEtxN2lVTGF1ekRIRnA5MVI3\\u000aaTdCanBuMTNWcXlZMjVUVXlSWUovYlN0NWVGR0FINnpQZHE5RkhqTWhyeGZpTURC\\u000aK3NTRUxqd2FJR2ZxWDBQSG82UmZ1Ky9tOWlpRWwzRWxrSWJpYVMycmdFWHkxZFgr\\u000admdBZkYzOWQzWEFTdmI5aElrNXg0OGltcHRtaDBPaHgwWENOMThtNnpvQndKajNw\\u000acmNnK2ZNWHE0UzZMdlJjQTdtV0MwRzcrdVdXdi9GblkxYUg0a3NPcHRmeWkydU16\\u000aS3kwQTJFbWNad3YyZktYdmljcnQ0Ry9yWU1ZZnlic2loQS8rcXhReTlERmlEek9n\\u000aZXZzZTZ2NnFTUE5TY1lYLzlYRUxKMzh2dmpMTTNjZHlQNEJOMVF3UENtRmFrVm1K\\u000aRTNKRzU0RXhycHRUdGdKTERaNW5FYTY4Mjc4dnRJL3JVR3k2OFFuNTJyMHVXc0ZX\\u000abk5obFRPR2RxYzZzdjdNTGdTYkQ3RUVmNWNiVHNKV3JQZ1ZHbUQ1Q2o5Y3ZmRjlR\\u000aakMvM1RiSXFWVE5QSkhhbXpnbUJsSFJZSGJQN1p0a3ZUZDBnTkF2SXllZGY1MkdY\\u000aUzhESkQwTStrSS8xNmF4dm0zSlB4RC9BVHE1Ri9xdmtIWFRUVStCSEtUTWk2dnk1\\u000aMkNEUmh0YkQ1dVNNa1YyQmROK0c5Y0xnL3hTeTc3TjBnTEc4WDZ6ODM1cllYbE0r\\u000aaGloeGx2UWtiSHR0eE9EN3VBYnpFcExEaC95NFFtZVRSK1FaQU9QeUc3azhGdENG\\u000aam5TM0lLWkFTVldFTVVFODlGTG1hdFhMNERvaHlXWnViSDJPVXlGUHp5ZnNvNWNF\\u000aNEpLVnBIb21NVWZWcjk5bUZnVk1ESUdyUEdFcFRmU2NqZ01wRmlDaEFxU1djUWFH\\u000aU2cwdlBrRkdlWXFIek15SENqMndxc3VDV3BIZWlyU25ncHNXa1RLMjFLRG42TDVx\\u000aaENpRk5wM3JWNUJFMkwwcEhqQnZEVmFrZXdqcnF0a1puZ3FKcHhZalhyV0dxUjVP\\u000aV3IraWhxZ0VJZ011WGhkdUxqR2wrWVZkU1d5ZTlER05OS29DN2FlUGhJMTJQRmg3\\u000aSlJoZjdIYWVlQUNPaGZaTndDWitXMndRb3hCZHpwYzltVCtDVlpxOUo2NkNyTlFI\\u000adTBtaStlaVRTdXNEVHR2b3RmQi9IQ20wMXVaZmgxbE1JQWdMNXozSTFHRVcvREpX\\u000aMk8wdWZBKzVPV2pnWFlzOG9aUlRCMnhYOWhmSW81eDREVXNiTFM1ZzgvbFBUVndF\\u000aamYxQlg2dU9vaTVvV2lJWVJqQmpmSWdVTEVURnhMTGtBUnJQTzJETzU1ekJnMi9Q\\u000adE9mdG00SzFjeWI3V0h2QkdrcmRYanlQUXlYYzRJVXU0SzR0aTlPSlE1eVRmWUN0\\u000aY2o1OWMya05BNHlOWmdwd3kxVnAvSytGdHVlZ0xsd2l4ZTRwakR5ekNJSnBnU0ZD\\u000acmtxREV1K0hqOFZWNXMweFFXc1d5ZWdOUUpldVBheWVSY0RGMzBoMWc2WmZGQjNa\\u000adE9RWWpFQnFyVWVZNkJndk5OWU42TWFrUndnRDBja2NDbEoyMUhZNGpvU2twcE9Z\\u000aZ3NUeTNrR1laNHFUelJNY0lsQ0REaXQ4ZENHZm9Cb3JKQ2t5NTUvNDFiV3FtbTdt\\u000aTElRVzJBTG9kdktQbVVXeFhibzN5WGNnSTRKdnFjZlAzRVVXTytjV3VIZEFSN2VF\\u000aOTc3MytSVUV2TXROdnMzWWxqeERrTmFNNzZ0VjhqanhRcFJZNEc0RWRSaUs0MTN3\\u000aWUkyWTE3UWE2ZEs4K2FhaHRad0JtVWpBSVkvREdZa2VOY2wzWjdxaWpJMTMvUnpn\\u000aNXlWcjl4VUsvSUFGUVlhNDlXQ1RRYTlzVWYzeEgzZUYvTW9HN0ZmMTdrOC8xMURx\\u000aTE5YQzUvSGhOeDJ2S09CTmx1RXJodURjYjNMZmJ5TGlRVllEMkhYeGRyTkc5M1E0\\u000aNGJPajRWb0xZV0hndTI5UG9sL0htRHhUSDFwdHBQVmM5K0U0R2RwN21yVmF1bHU1\\u000acXhDOWliRzlKV3ljUUdkMUJuMG9RMjluSGlMcGd4K25HOFlkZHdPVWRkRzRndkpq\\u000aS21iUTl5aTAwYXdUamhOUE9GZXEvejVuVFJHQ3liSDZsWW9MVGtueE9UQiszMkpy\\u000aQ2pBbDVMRG90amtDZWtBUllwbVVxOWhSY2I3c3l0ME1RY1BBZUg0VlBHNmhFMUpN\\u000aYkxpTXdUWVdKNWtTM3F1elp1SkZQSUl4SFp3UmtJUzFjTnBjL0FtSUpwZm04RCtL\\u000aYUEvVmdoRkJpdnZzZnlUNndoNVRybENBcE9DcHNOTlNWbWRLRHF5QVBFTENuaURj\\u000adTRwcmpZRU5JU2tKdExUTVdBSzVCWWdRZ1ZQOVcrekJyMjNuSGlZVnhLWWhjdm9M\\u000aYTh6dUdLYlJtY2xpL3o0cXpmWnk5RGlJNmoxdWFUT1FMQzEvMzIwT2xBRGtSOVUy\\u000aT3hYZFVuSTFaSzFyY0hRZnllS3BsbUFsRTJDM3MzYkFkR3V5bXRKTDQ2M1dqZm9P\\u000aUkhHWWpvZnZNQTI0cHhnY3hFRnU5YVRFamdFVVBNeHBzN2Y4TVMyaVJvL3dxU3pX\\u000aZ0lwN1EvZHVYY1FQb0dSS2JrR0FySnNJVGdVT3BSQ3hxTFlXbk5UUy8xbmxCeXk3\\u000aQVBjcGRaRmk1WjRqM1IvbGJ0T2Era1ZiYmo4ZC8wazMwTnlDVjJGRVZGV2tPbG9z\\u000aNTFQNUNOUiswNUh6QkhQM3V3N3VyODRZYkRGdHd2UjhNM29UMXNtbXljYUsxMkpE\\u000aZGNBOUQ2YWErY2k5Wmh0UWNhbUw0Z1pjZmVpZllHNEt6NWsyT3lpMlpUNkZKOUV4\\u000aMHQ1T1d5MjZUSjllQmlCcGRaV25XZDB3bzZOMU5ST0xLdFY5L052d3R1WlZSRkxS\\u000aRUg1WGNLMnRMcTFWczFaVkg4MXM4R29UOUQ4VkFEaGFwVDBCU0xsR3A4TkNZdUdK\\u000aeXI1YVVwODdPZEl4RCt3S244NTRteVlKaXlVZnIwWmtGNGhoOEtkTXcvemg3RVQv\\u000aYkxIWlVxUXozdUV3QkcvODRuR1E9PTwveGVuYzpDaXBoZXJWYWx1ZT48L3hlbmM6\\u000aQ2lwaGVyRGF0YT48L3hlbmM6RW5jcnlwdGVkRGF0YT48eGVuYzpFbmNyeXB0ZWRL\\u000aZXkgeG1sbnM6eGVuYz0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8wNC94bWxlbmMj\\u000aIiBJZD0iX2E3NDBjZjA5MTViZDE1MmRiNzRkMDNjZDQ1NzUyMTM3Ij48eGVuYzpF\\u000abmNyeXB0aW9uTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAw\\u000aMS8wNC94bWxlbmMjcnNhLW9hZXAtbWdmMXAiIHhtbG5zOnhlbmM9Imh0dHA6Ly93\\u000ad3cudzMub3JnLzIwMDEvMDQveG1sZW5jIyI+PGRzOkRpZ2VzdE1ldGhvZCB4bWxu\\u000aczpkcz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnIyIgQWxnb3Jp\\u000adGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjc2hhMSIvPjwv\\u000aeGVuYzpFbmNyeXB0aW9uTWV0aG9kPjxkczpLZXlJbmZvIHhtbG5zOmRzPSJodHRw\\u000aOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjIj48ZHM6WDUwOURhdGE+PGRz\\u000aOlg1MDlDZXJ0aWZpY2F0ZT5NSUlERlRDQ0FmMENCRlVCbkw0d0RRWUpLb1pJaHZj\\u000aTkFRRUxCUUF3VHpFTE1Ba0dBMVVFQmhNQ1FWUXhEVEFMQmdOVkJBY01CRWR5CllY\\u000ab3hEVEFMQmdOVkJBb01CRVZIU1ZveElqQWdCZ05WQkFNTUdVMVBRUzFKUkNCSlJG\\u000aQWdLRlJsYzNRdFZtVnljMmx2Ymlrd0hoY04KTVRVd016RXlNVFF3TXpReVdoY05N\\u000aVGN4TWpBMU1UUXdNelF5V2pCUE1Rc3dDUVlEVlFRR0V3SkJWREVOTUFzR0ExVUVC\\u000ad3dFUjNKaAplakVOTUFzR0ExVUVDZ3dFUlVkSldqRWlNQ0FHQTFVRUF3d1pUVTlC\\u000aTFVsRUlFbEVVQ0FvVkdWemRDMVdaWEp6YVc5dUtUQ0NBU0l3CkRRWUpLb1pJaHZj\\u000aTkFRRUJCUUFEZ2dFUEFEQ0NBUW9DZ2dFQkFJSnYwcWU5VWR2RllTTDVJMDJHb2t3\\u000aRVZmc0lHYzdJN0VoVk5PeFkKOW10VWVubWhxTnJMc0xCRmcxSWlQYmswSVNXaE9S\\u000ad1B5VnAvUDMrR3lHUDMzOXFaNjhVQ0dWMzYxRTBRbTdjalBlL08zK3IzSEFNMgpa\\u000aQk44b0Fab0htcGhyTlM2ZktmWTU4a3lndHJVYStaeU16WVdUVGlTMzJTQ004SDU1\\u000aYmx1RUZiZVprc25iUDBZOTRJamtmSmRndnpsCk14enJsU3lvVjJ5bVdCanZTNXdl\\u000abERIZ2JDS3lqc2pJaFRSakp1L29sR0p5ZW4wMS9FcElWdFN5RFhPLzJJUzJ2Mk85\\u000aVWlGd0FveUIKWUFqUG5sM0h4SzJBNTc3blI2M014bGdQMC9zK3I4NHVCcU9BbGI0\\u000acW5icFU3bHU1R3hsQ1BrWm1wUm9vQ1FZVVJpb0Mrd2pTNmxNQwpBd0VBQVRBTkJn\\u000aa3Foa2lHOXcwQkFRc0ZBQU9DQVFFQUJxTzdra3EvZ1JhaEF2cHNRZzVMTFpST0dG\\u000acjlwSVByeU45eG1KR2dQbzdqCktObDdyczdnTlMwbG11bHVZV1duSmN3QVBid0Zl\\u000aYjk1NFZNQjl4OXA5UUV3NVJuWGFtVVk5cWEwTGdjUy90L1dYNnZKa1pQTmhXcGgK\\u000aOGJYd2gwTXZsc2JmcnZEVEpyOGNqSDNxZnhJVHA3cGEzeGIxcUU3c3VSZmZWVWRE\\u000aWGF3aVhYbldKL1dKcit0d1ZWSEhFcW5aejFsQQpyU0RMeE04c0NqRzhEZUp3OHZu\\u000aUXk1bVBHckdWVEJiYTR1cGM4VVRZMW5QVjlVMkdCSlZZdUFrb1ZSamJUbE52ckw1\\u000aSnFOcXlwS2NHCmJlampXeGdyelprZVFlVTJoRmNqdW5tZ3dHWit1ZzJmcTRrS2tR\\u000aZnR3Y3FlSlR6eXpCb28yK09vNFRtZmJzaC9vbnhQV0E9PTwvZHM6WDUwOUNlcnRp\\u000aZmljYXRlPjwvZHM6WDUwOURhdGE+PC9kczpLZXlJbmZvPjx4ZW5jOkNpcGhlckRh\\u000adGEgeG1sbnM6eGVuYz0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8wNC94bWxlbmMj\\u000aIj48eGVuYzpDaXBoZXJWYWx1ZT5Sb1NHTGFDbDN3ZkRXdDlXMm9JSDNUQ3JPTVN4\\u000aL3Y1S0pQV2hndmhWNml2RmZXSWFJeDB5RnV2NVZTME5VZ2FUVGIwVjhUYnNGN1Vz\\u000aRllzQ0xldkVUa2lWbG5OeWE4dlVoL2lYTDYzT0JmdzR3T3pSNVZheVBuaWFwWFdM\\u000aa0RHTmQ5Y3E2QU8zR1JoTWJaZDdma2NhRWNJVTB2bGtZeUJJNmE0Yms4bHM3Mm0v\\u000aZkxKQS8vaWl5L2piODkzQkZ4dk9EMk5hT1pabXhzSlI4YlFmWWpBMHdXa1pBcW56\\u000aN0EzY3lhcHV3aXVTc01wc1hYSnFjVXp2TS9GS090dE1wTnhSUVprdk1RZlNnMCtM\\u000aUVM5M0IxN0ZUZFE2OHNRL3dZQmhubFBEZXFZK0NnY1VjeVYzOVdjTjAwcUtVYmNQ\\u000aM2kzSWRWUVRkcEJQUTdRS01HR2JmS1Y0RlE9PTwveGVuYzpDaXBoZXJWYWx1ZT48\\u000aL3hlbmM6Q2lwaGVyRGF0YT48eGVuYzpSZWZlcmVuY2VMaXN0Pjx4ZW5jOkRhdGFS\\u000aZWZlcmVuY2UgVVJJPSIjXzNmZDM1ODkyZTlhOGVhY2I4ZTA4ZjI4MGE4M2ZjYjc0\\u000aIi8+PC94ZW5jOlJlZmVyZW5jZUxpc3Q+PC94ZW5jOkVuY3J5cHRlZEtleT48L3Nh\\u000abWwyOkVuY3J5cHRlZEFzc2VydGlvbj48L3NhbWwycDpSZXNwb25zZT4=\",\"dateTimeCreated\":\"2015-10-09T10:36:02.075Z\",\"id\":1}}}"; // @@ -57,19 +304,19 @@ public class Tests { - JsonObject responseMsg = new JsonObject(); - responseMsg.addProperty( - SSOTransferConstants.SSOCONTAINER_KEY_STATUS, - "OK"); - - - JsonObject levelTwo = new JsonObject(); - levelTwo.addProperty("test", "12345"); - - responseMsg.add("levelTwo", levelTwo ); - - - System.out.println(responseMsg.toString()); +// JsonObject responseMsg = new JsonObject(); +// responseMsg.addProperty( +// SSOTransferConstants.SSOCONTAINER_KEY_STATUS, +// "OK"); +// +// +// JsonObject levelTwo = new JsonObject(); +// levelTwo.addProperty("test", "12345"); +// +// responseMsg.add("levelTwo", levelTwo ); +// +// +// System.out.println(responseMsg.toString()); // } catch (IOException e) { // // TODO Auto-generated catch block @@ -80,4 +327,7 @@ public class Tests { } + + + } diff --git a/repository/eu/eidas/eidas-commons/1.3.0-SNAPSHOT/eidas-commons-1.3.0-SNAPSHOT.jar b/repository/eu/eidas/eidas-commons/1.3.0-SNAPSHOT/eidas-commons-1.3.0-SNAPSHOT.jar new file mode 100644 index 000000000..fb0f3b301 Binary files /dev/null and b/repository/eu/eidas/eidas-commons/1.3.0-SNAPSHOT/eidas-commons-1.3.0-SNAPSHOT.jar differ diff --git a/repository/eu/eidas/eidas-configmodule/1.3.0-SNAPSHOT/eidas-configmodule-1.3.0-SNAPSHOT.jar b/repository/eu/eidas/eidas-configmodule/1.3.0-SNAPSHOT/eidas-configmodule-1.3.0-SNAPSHOT.jar new file mode 100644 index 000000000..0ff0547e5 Binary files /dev/null and b/repository/eu/eidas/eidas-configmodule/1.3.0-SNAPSHOT/eidas-configmodule-1.3.0-SNAPSHOT.jar differ diff --git a/repository/eu/eidas/eidas-encryption/1.3.0-SNAPSHOT/eidas-encryption-1.3.0-SNAPSHOT.jar b/repository/eu/eidas/eidas-encryption/1.3.0-SNAPSHOT/eidas-encryption-1.3.0-SNAPSHOT.jar new file mode 100644 index 000000000..d024a9b29 Binary files /dev/null and b/repository/eu/eidas/eidas-encryption/1.3.0-SNAPSHOT/eidas-encryption-1.3.0-SNAPSHOT.jar differ diff --git a/repository/eu/eidas/eidas-light-commons/1.3.0-SNAPSHOT/eidas-light-commons-1.3.0-SNAPSHOT.jar b/repository/eu/eidas/eidas-light-commons/1.3.0-SNAPSHOT/eidas-light-commons-1.3.0-SNAPSHOT.jar new file mode 100644 index 000000000..6c49296bc Binary files /dev/null and b/repository/eu/eidas/eidas-light-commons/1.3.0-SNAPSHOT/eidas-light-commons-1.3.0-SNAPSHOT.jar differ diff --git a/repository/eu/eidas/eidas-saml-engine/1.3.0-SNAPSHOT/eidas-saml-engine-1.3.0-SNAPSHOT.jar b/repository/eu/eidas/eidas-saml-engine/1.3.0-SNAPSHOT/eidas-saml-engine-1.3.0-SNAPSHOT.jar new file mode 100644 index 000000000..ccc5b5456 Binary files /dev/null and b/repository/eu/eidas/eidas-saml-engine/1.3.0-SNAPSHOT/eidas-saml-engine-1.3.0-SNAPSHOT.jar differ diff --git a/repository/eu/eidas/eidas-specific-communication-definition/1.3.0-SNAPSHOT/eidas-specific-communication-definition-1.3.0-SNAPSHOT.jar b/repository/eu/eidas/eidas-specific-communication-definition/1.3.0-SNAPSHOT/eidas-specific-communication-definition-1.3.0-SNAPSHOT.jar new file mode 100644 index 000000000..cf8ba0695 Binary files /dev/null and b/repository/eu/eidas/eidas-specific-communication-definition/1.3.0-SNAPSHOT/eidas-specific-communication-definition-1.3.0-SNAPSHOT.jar differ diff --git a/repository/eu/eidas/eidas-specific/1.3.0-SNAPSHOT/eidas-specific-1.3.0-SNAPSHOT.jar b/repository/eu/eidas/eidas-specific/1.3.0-SNAPSHOT/eidas-specific-1.3.0-SNAPSHOT.jar new file mode 100644 index 000000000..51d638033 Binary files /dev/null and b/repository/eu/eidas/eidas-specific/1.3.0-SNAPSHOT/eidas-specific-1.3.0-SNAPSHOT.jar differ -- cgit v1.2.3 From 250a89d7eaeb1c8a905fa7bb2032992946fec40f Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Wed, 12 Jul 2017 14:42:09 +0200 Subject: add new demo module for dummy authentication --- id/server/auth-edu/pom.xml | 7 ++ .../moa/id/commons/MOAIDAuthConstants.java | 3 +- .../moa-id-module-bkaMobilaAuthSAML2Test/pom.xml | 10 ++ .../bkamobileauthtests/BKAMobileAuthModule.java | 83 ++++++++++++++++ .../BKAMobileAuthSpringResourceProvider.java | 62 ++++++++++++ .../tasks/FirstBKAMobileAuthTask.java | 56 +++++++++++ .../tasks/SecondBKAMobileAuthTask.java | 104 +++++++++++++++++++++ .../src/main/resources/BKAMobileAuth.process.xml | 22 +++++ ...iz.components.spring.api.SpringResourceProvider | 1 + .../main/resources/moaid_bka_mobileauth.beans.xml | 25 +++++ id/server/modules/pom.xml | 1 + pom.xml | 10 +- 12 files changed, 381 insertions(+), 3 deletions(-) create mode 100644 id/server/modules/moa-id-module-bkaMobilaAuthSAML2Test/pom.xml create mode 100644 id/server/modules/moa-id-module-bkaMobilaAuthSAML2Test/src/main/java/at/gv/egovernment/moa/id/auth/modules/bkamobileauthtests/BKAMobileAuthModule.java create mode 100644 id/server/modules/moa-id-module-bkaMobilaAuthSAML2Test/src/main/java/at/gv/egovernment/moa/id/auth/modules/bkamobileauthtests/BKAMobileAuthSpringResourceProvider.java create mode 100644 id/server/modules/moa-id-module-bkaMobilaAuthSAML2Test/src/main/java/at/gv/egovernment/moa/id/auth/modules/bkamobileauthtests/tasks/FirstBKAMobileAuthTask.java create mode 100644 id/server/modules/moa-id-module-bkaMobilaAuthSAML2Test/src/main/java/at/gv/egovernment/moa/id/auth/modules/bkamobileauthtests/tasks/SecondBKAMobileAuthTask.java create mode 100644 id/server/modules/moa-id-module-bkaMobilaAuthSAML2Test/src/main/resources/BKAMobileAuth.process.xml create mode 100644 id/server/modules/moa-id-module-bkaMobilaAuthSAML2Test/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider create mode 100644 id/server/modules/moa-id-module-bkaMobilaAuthSAML2Test/src/main/resources/moaid_bka_mobileauth.beans.xml (limited to 'id/server/modules') diff --git a/id/server/auth-edu/pom.xml b/id/server/auth-edu/pom.xml index 4e01c6260..b8bdad311 100644 --- a/id/server/auth-edu/pom.xml +++ b/id/server/auth-edu/pom.xml @@ -202,6 +202,13 @@ moa-id-module-ssoTransfer ${moa-id-version} + + + MOA.id.server.modules + moa-id-module-bkaMobilaAuthSAML2Test + ${moa-id-version} + + + + + + + + + + + + + + + + + + diff --git a/id/server/modules/moa-id-module-bkaMobilaAuthSAML2Test/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider b/id/server/modules/moa-id-module-bkaMobilaAuthSAML2Test/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider new file mode 100644 index 000000000..42dbf09e7 --- /dev/null +++ b/id/server/modules/moa-id-module-bkaMobilaAuthSAML2Test/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider @@ -0,0 +1 @@ +at.gv.egovernment.moa.id.auth.modules.bkamobileauthtests.BKAMobileAuthSpringResourceProvider \ No newline at end of file diff --git a/id/server/modules/moa-id-module-bkaMobilaAuthSAML2Test/src/main/resources/moaid_bka_mobileauth.beans.xml b/id/server/modules/moa-id-module-bkaMobilaAuthSAML2Test/src/main/resources/moaid_bka_mobileauth.beans.xml new file mode 100644 index 000000000..ef13b0348 --- /dev/null +++ b/id/server/modules/moa-id-module-bkaMobilaAuthSAML2Test/src/main/resources/moaid_bka_mobileauth.beans.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/id/server/modules/pom.xml b/id/server/modules/pom.xml index 3ca3497a0..000851a5f 100644 --- a/id/server/modules/pom.xml +++ b/id/server/modules/pom.xml @@ -32,6 +32,7 @@ moa-id-module-elga_mandate_service moa-id-module-ssoTransfer + moa-id-module-bkaMobilaAuthSAML2Test diff --git a/pom.xml b/pom.xml index b834320cb..17ea3499e 100644 --- a/pom.xml +++ b/pom.xml @@ -91,13 +91,13 @@ local file:${basedir}/../../../repository - + jboss https://repository.jboss.org/nexus/content/repositories/central/ @@ -524,6 +524,12 @@ moa-id-module-elga_mandate_service ${moa-id-module-elga_mandate_client} + + + MOA.id.server.modules + moa-id-module-bkaMobilaAuthSAML2Test + ${moa-id-version} + MOA.id.server -- cgit v1.2.3 From 3e2575cfe85ac8f3076f0470a82191d9f1dae636 Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Thu, 13 Jul 2017 07:06:14 +0200 Subject: update DummyAuthentication module to support more than one SP --- .../bkamobileauthtests/BKAMobileAuthModule.java | 31 +++++++++++++++++++--- 1 file changed, 27 insertions(+), 4 deletions(-) (limited to 'id/server/modules') diff --git a/id/server/modules/moa-id-module-bkaMobilaAuthSAML2Test/src/main/java/at/gv/egovernment/moa/id/auth/modules/bkamobileauthtests/BKAMobileAuthModule.java b/id/server/modules/moa-id-module-bkaMobilaAuthSAML2Test/src/main/java/at/gv/egovernment/moa/id/auth/modules/bkamobileauthtests/BKAMobileAuthModule.java index 72087180a..44554e21d 100644 --- a/id/server/modules/moa-id-module-bkaMobilaAuthSAML2Test/src/main/java/at/gv/egovernment/moa/id/auth/modules/bkamobileauthtests/BKAMobileAuthModule.java +++ b/id/server/modules/moa-id-module-bkaMobilaAuthSAML2Test/src/main/java/at/gv/egovernment/moa/id/auth/modules/bkamobileauthtests/BKAMobileAuthModule.java @@ -22,12 +22,19 @@ */ package at.gv.egovernment.moa.id.auth.modules.bkamobileauthtests; +import java.util.ArrayList; +import java.util.List; + +import javax.annotation.PostConstruct; + import org.springframework.beans.factory.annotation.Autowired; import at.gv.egovernment.moa.id.auth.modules.AuthModule; import at.gv.egovernment.moa.id.commons.MOAIDAuthConstants; import at.gv.egovernment.moa.id.commons.api.AuthConfiguration; +import at.gv.egovernment.moa.id.commons.utils.KeyValueUtils; import at.gv.egovernment.moa.id.process.api.ExecutionContext; +import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.MiscUtil; /** @@ -40,6 +47,8 @@ public class BKAMobileAuthModule implements AuthModule { @Autowired protected AuthConfiguration authConfig; + private List uniqueIDsDummyAuthEnabled = new ArrayList(); + /* (non-Javadoc) * @see at.gv.egovernment.moa.id.auth.modules.AuthModule#getPriority() */ @@ -56,15 +65,29 @@ public class BKAMobileAuthModule implements AuthModule { this.priority = priority; } + + @PostConstruct + public void initialDummyAuthWhiteList() { + String sensitiveSpIdentifier = authConfig.getBasicMOAIDConfiguration("modules.bkamobileAuth.entityID"); + if (MiscUtil.isNotEmpty(sensitiveSpIdentifier)) { + uniqueIDsDummyAuthEnabled.addAll(KeyValueUtils.getListOfCSVValues(sensitiveSpIdentifier)); + + if (!uniqueIDsDummyAuthEnabled.isEmpty()) { + Logger.info("Dummy authentication is enabled for ...."); + for (String el : uniqueIDsDummyAuthEnabled) + Logger.info(" EntityID: " + el); + } + } + } + /* (non-Javadoc) * @see at.gv.egovernment.moa.id.auth.modules.AuthModule#selectProcess(at.gv.egovernment.moa.id.process.api.ExecutionContext) */ @Override - public String selectProcess(ExecutionContext context) { + public String selectProcess(ExecutionContext context) { String spEntityID = (String) context.get(MOAIDAuthConstants.PROCESSCONTEXT_UNIQUE_OA_IDENTFIER); - if (MiscUtil.isNotEmpty(spEntityID)) { - String sensitiveSpIdentifier = authConfig.getBasicMOAIDConfiguration("modules.bkamobileAuth.entityID"); - if (spEntityID.equalsIgnoreCase(sensitiveSpIdentifier)) + if (MiscUtil.isNotEmpty(spEntityID)) { + if (uniqueIDsDummyAuthEnabled.contains(spEntityID)) return "BKAMobileAuthentication"; } -- cgit v1.2.3 From 91d38d59b42ee77346b0d33315f403d8fa678576 Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Mon, 17 Jul 2017 10:25:02 +0200 Subject: update MOA SAML2 metadata provider to support metadata located on file system --- .../validation/oa/OAPVP2ConfigValidation.java | 105 +++++++-------- .../pvp2x/metadata/MOAMetadataProvider.java | 145 ++++++++++----------- .../pvp2x/metadata/SimpleMOAMetadataProvider.java | 116 ++++++++++++++++- .../moa/id/commons/api/AuthConfiguration.java | 3 +- .../utils/ELGAMandateServiceMetadataProvider.java | 14 +- 5 files changed, 244 insertions(+), 139 deletions(-) (limited to 'id/server/modules') diff --git a/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/validation/oa/OAPVP2ConfigValidation.java b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/validation/oa/OAPVP2ConfigValidation.java index 61a380188..79e7e9252 100644 --- a/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/validation/oa/OAPVP2ConfigValidation.java +++ b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/validation/oa/OAPVP2ConfigValidation.java @@ -111,81 +111,84 @@ public class OAPVP2ConfigValidation { log.info("MetaDataURL has no valid form."); errors.add(LanguageHelper.getErrorString("validation.pvp2.metadataurl.valid", request)); - } else { - + } else { if (certSerialized == null) { log.info("No certificate for metadata validation"); errors.add(LanguageHelper.getErrorString("validation.pvp2.certificate.notfound", request)); - } else { - - X509Certificate cert = new X509Certificate(certSerialized); - BasicX509Credential credential = new BasicX509Credential(); - credential.setEntityCertificate(cert); + } else { + if (form.getMetaDataURL().startsWith("http")) { + X509Certificate cert = new X509Certificate(certSerialized); + BasicX509Credential credential = new BasicX509Credential(); + credential.setEntityCertificate(cert); - timer = new Timer(); - httpClient = new MOAHttpClient(); + timer = new Timer(); + httpClient = new MOAHttpClient(); - if (form.getMetaDataURL().startsWith("https:")) - try { - MOAHttpProtocolSocketFactory protoSocketFactory = new MOAHttpProtocolSocketFactory( - "MOAMetaDataProvider", - ConfigurationProvider.getInstance().getCertStoreDirectory(), - ConfigurationProvider.getInstance().getTrustStoreDirectory(), - null, - "pkix", - true, - new String[]{"crl"}, - false); + if (form.getMetaDataURL().startsWith("https:")) + try { + MOAHttpProtocolSocketFactory protoSocketFactory = new MOAHttpProtocolSocketFactory( + "MOAMetaDataProvider", + ConfigurationProvider.getInstance().getCertStoreDirectory(), + ConfigurationProvider.getInstance().getTrustStoreDirectory(), + null, + "pkix", + true, + new String[]{"crl"}, + false); - httpClient.setCustomSSLTrustStore( - form.getMetaDataURL(), - protoSocketFactory); + httpClient.setCustomSSLTrustStore( + form.getMetaDataURL(), + protoSocketFactory); - } catch (MOAHttpProtocolSocketFactoryException e) { - log.warn("MOA SSL-TrustStore can not initialized. Use default Java TrustStore.", e); + } catch (MOAHttpProtocolSocketFactoryException e) { + log.warn("MOA SSL-TrustStore can not initialized. Use default Java TrustStore.", e); - } catch (ConfigurationException e) { - log.info("No MOA specific SSL-TrustStore configured. Use default Java TrustStore.", e); + } catch (ConfigurationException e) { + log.info("No MOA specific SSL-TrustStore configured. Use default Java TrustStore.", e); - } + } - List filterList = new ArrayList(); - filterList.add(new MetaDataVerificationFilter(credential)); + List filterList = new ArrayList(); + filterList.add(new MetaDataVerificationFilter(credential)); - try { - filterList.add(new SchemaValidationFilter( - ConfigurationProvider.getInstance().isPVPMetadataSchemaValidationActive())); + try { + filterList.add(new SchemaValidationFilter( + ConfigurationProvider.getInstance().isPVPMetadataSchemaValidationActive())); - } catch (ConfigurationException e) { - log.warn("Configuration access FAILED!", e); + } catch (ConfigurationException e) { + log.warn("Configuration access FAILED!", e); - } + } + + MetadataFilterChain filter = new MetadataFilterChain(); + filter.setFilters(filterList); - MetadataFilterChain filter = new MetadataFilterChain(); - filter.setFilters(filterList); + httpProvider = + new HTTPMetadataProvider(timer, httpClient, form.getMetaDataURL()); + httpProvider.setParserPool(new BasicParserPool()); + httpProvider.setRequireValidMetadata(true); + httpProvider.setMetadataFilter(filter); + httpProvider.setMinRefreshDelay(1000*60*15); //15 minutes + httpProvider.setMaxRefreshDelay(1000*60*60*24); //24 hours - httpProvider = - new HTTPMetadataProvider(timer, httpClient, form.getMetaDataURL()); - httpProvider.setParserPool(new BasicParserPool()); - httpProvider.setRequireValidMetadata(true); - httpProvider.setMetadataFilter(filter); - httpProvider.setMinRefreshDelay(1000*60*15); //15 minutes - httpProvider.setMaxRefreshDelay(1000*60*60*24); //24 hours + httpProvider.setRequireValidMetadata(true); - httpProvider.setRequireValidMetadata(true); + httpProvider.initialize(); - httpProvider.initialize(); + if (httpProvider.getMetadata() == null) { + log.info("Metadata could be received but validation FAILED."); + errors.add(LanguageHelper.getErrorString("validation.pvp2.metadata.validation", request)); + } - if (httpProvider.getMetadata() == null) { - log.info("Metadata could be received but validation FAILED."); - errors.add(LanguageHelper.getErrorString("validation.pvp2.metadata.validation", request)); + } else { + log.info("Metadata load validation skipped, because it's no http(s) metadata: " + form.getMetaDataURL()); + } - } } } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/metadata/MOAMetadataProvider.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/metadata/MOAMetadataProvider.java index b2597c3cb..5380d7f53 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/metadata/MOAMetadataProvider.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/metadata/MOAMetadataProvider.java @@ -38,6 +38,7 @@ import javax.xml.namespace.QName; import org.opensaml.saml2.metadata.EntitiesDescriptor; import org.opensaml.saml2.metadata.EntityDescriptor; import org.opensaml.saml2.metadata.RoleDescriptor; +import org.opensaml.saml2.metadata.provider.BaseMetadataProvider; import org.opensaml.saml2.metadata.provider.ChainingMetadataProvider; import org.opensaml.saml2.metadata.provider.HTTPMetadataProvider; import org.opensaml.saml2.metadata.provider.MetadataFilter; @@ -45,6 +46,7 @@ import org.opensaml.saml2.metadata.provider.MetadataProvider; import org.opensaml.saml2.metadata.provider.MetadataProviderException; import org.opensaml.saml2.metadata.provider.ObservableMetadataProvider; import org.opensaml.xml.XMLObject; +import org.opensaml.xml.parse.BasicParserPool; import org.springframework.stereotype.Service; import at.gv.egovernment.moa.id.auth.IDestroyableObject; @@ -52,7 +54,6 @@ import at.gv.egovernment.moa.id.auth.IGarbageCollectorProcessing; import at.gv.egovernment.moa.id.commons.api.IOAAuthParameters; import at.gv.egovernment.moa.id.commons.api.exceptions.ConfigurationException; import at.gv.egovernment.moa.id.commons.config.MOAIDConfigurationConstants; -import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; import at.gv.egovernment.moa.id.protocols.pvp2x.verification.metadata.InterfederatedIDPPublicServiceFilter; import at.gv.egovernment.moa.id.protocols.pvp2x.verification.metadata.PVPMetadataFilterChain; import at.gv.egovernment.moa.id.protocols.pvp2x.verification.metadata.SchemaValidationFilter; @@ -154,7 +155,7 @@ public class MOAMetadataProvider extends SimpleMOAMetadataProvider //reload metadata provider IOAAuthParameters oaParam = - AuthConfigurationProviderFactory.getInstance().getOnlineApplicationParameter(entityID); + authConfig.getOnlineApplicationParameter(entityID); if (oaParam != null) { String metadataURL = oaParam.getConfigurationValue(MOAIDConfigurationConstants.SERVICE_PROTOCOLS_PVP2X_URL); if (MiscUtil.isNotEmpty(metadataURL)) { @@ -178,10 +179,11 @@ public class MOAMetadataProvider extends SimpleMOAMetadataProvider timer = new Timer(true); ChainingMetadataProvider chainProvider = (ChainingMetadataProvider) internalProvider; - HTTPMetadataProvider newMetadataProvider = createNewHTTPMetaDataProvider(metadataURL, + MetadataProvider newMetadataProvider = createNewMoaMetadataProvider(metadataURL, buildMetadataFilterChain(oaParam, metadataURL, cert), oaFriendlyName, - timer); + timer, + new BasicParserPool()); chainProvider.addMetadataProvider(newMetadataProvider); @@ -203,9 +205,6 @@ public class MOAMetadataProvider extends SimpleMOAMetadataProvider Logger.debug("Can not refresh PVP2X metadata: NO onlineApplication with Id: " + entityID); - } catch (ConfigurationException e) { - Logger.warn("Access MOA-ID configuration FAILED.", e); - } catch (MetadataProviderException e) { Logger.warn("Refresh PVP2X metadata for onlineApplication: " + entityID + " FAILED.", e); @@ -268,7 +267,7 @@ public class MOAMetadataProvider extends SimpleMOAMetadataProvider //load all PVP2 OAs form ConfigurationDatabase and //compare actually loaded Providers with configured PVP2 OAs - Map allOAs = AuthConfigurationProviderFactory.getInstance().getConfigurationWithWildCard( + Map allOAs = authConfig.getConfigurationWithWildCard( MOAIDConfigurationConstants.PREFIX_MOAID_SERVICES + ".%." + MOAIDConfigurationConstants.SERVICE_UNIQUEIDENTIFIER); @@ -279,7 +278,7 @@ public class MOAMetadataProvider extends SimpleMOAMetadataProvider Entry oaKeyPair = oaInterator.next(); IOAAuthParameters oaParam = - AuthConfigurationProviderFactory.getInstance().getOnlineApplicationParameter(oaKeyPair.getValue()); + authConfig.getOnlineApplicationParameter(oaKeyPair.getValue()); if (oaParam != null) { String metadataurl = oaParam.getConfigurationValue(MOAIDConfigurationConstants.SERVICE_PROTOCOLS_PVP2X_URL); @@ -409,83 +408,79 @@ public class MOAMetadataProvider extends SimpleMOAMetadataProvider ChainingMetadataProvider chainProvider = new ChainingMetadataProvider(); Logger.info("Loading metadata"); Map providersinuse = new HashMap(); - try { - Map allOAs = AuthConfigurationProviderFactory.getInstance().getConfigurationWithWildCard( - MOAIDConfigurationConstants.PREFIX_MOAID_SERVICES - + ".%." - + MOAIDConfigurationConstants.SERVICE_UNIQUEIDENTIFIER); - - if (allOAs != null) { - Iterator> oaInterator = allOAs.entrySet().iterator(); - while (oaInterator.hasNext()) { - Entry oaKeyPair = oaInterator.next(); - - IOAAuthParameters oaParam = - AuthConfigurationProviderFactory.getInstance().getOnlineApplicationParameter(oaKeyPair.getValue()); - if (oaParam != null) { - String metadataurl = oaParam.getConfigurationValue(MOAIDConfigurationConstants.SERVICE_PROTOCOLS_PVP2X_URL); - String oaFriendlyName = oaParam.getFriendlyName(); - HTTPMetadataProvider httpProvider = null; + Map allOAs = authConfig.getConfigurationWithWildCard( + MOAIDConfigurationConstants.PREFIX_MOAID_SERVICES + + ".%." + + MOAIDConfigurationConstants.SERVICE_UNIQUEIDENTIFIER); + + if (allOAs != null) { + Iterator> oaInterator = allOAs.entrySet().iterator(); + while (oaInterator.hasNext()) { + Entry oaKeyPair = oaInterator.next(); - try { - String certBase64 = oaParam.getConfigurationValue(MOAIDConfigurationConstants.SERVICE_PROTOCOLS_PVP2X_CERTIFICATE); - if (MiscUtil.isNotEmpty(certBase64) && MiscUtil.isNotEmpty(metadataurl)) { - byte[] cert = Base64Utils.decode(certBase64, false); - - - if (timer == null) - timer = new Timer(true); - - Logger.info("Loading metadata for: " + oaFriendlyName); - if (!providersinuse.containsKey(metadataurl)) { - httpProvider = createNewHTTPMetaDataProvider( - metadataurl, - buildMetadataFilterChain(oaParam, metadataurl, cert), - oaFriendlyName, - timer); - - if (httpProvider != null) - providersinuse.put(metadataurl, httpProvider); + IOAAuthParameters oaParam = + authConfig.getOnlineApplicationParameter(oaKeyPair.getValue()); + if (oaParam != null) { + String metadataurl = oaParam.getConfigurationValue(MOAIDConfigurationConstants.SERVICE_PROTOCOLS_PVP2X_URL); + String oaFriendlyName = oaParam.getFriendlyName(); + MetadataProvider httpProvider = null; + + try { + String certBase64 = oaParam.getConfigurationValue(MOAIDConfigurationConstants.SERVICE_PROTOCOLS_PVP2X_CERTIFICATE); + if (MiscUtil.isNotEmpty(certBase64) && MiscUtil.isNotEmpty(metadataurl)) { + byte[] cert = Base64Utils.decode(certBase64, false); - } else { - Logger.info(metadataurl + " are already added."); - } + + if (timer == null) + timer = new Timer(true); + + Logger.info("Loading metadata for: " + oaFriendlyName); + if (!providersinuse.containsKey(metadataurl)) { + httpProvider = createNewMoaMetadataProvider( + metadataurl, + buildMetadataFilterChain(oaParam, metadataurl, cert), + oaFriendlyName, + timer, + new BasicParserPool()); + + if (httpProvider != null) + providersinuse.put(metadataurl, httpProvider); } else { - Logger.info(oaFriendlyName - + " is not a PVP2 Application skipping"); + Logger.info(metadataurl + " are already added."); } - } catch (Throwable e) { - Logger.error( - "Failed to add Metadata (unhandled reason: " - + e.getMessage(), e); - if (httpProvider != null) { - Logger.debug("Destroy failed Metadata provider"); - httpProvider.destroy(); - } - } - } - } + } else { + Logger.info(oaFriendlyName + + " is not a PVP2 Application skipping"); + } + } catch (Throwable e) { + Logger.error( + "Failed to add Metadata (unhandled reason: " + + e.getMessage(), e); - } else - Logger.info("No Online-Application configuration found. PVP 2.1 metadata provider initialization failed!"); - - try { - chainProvider.setProviders(new ArrayList(providersinuse.values())); - - } catch (MetadataProviderException e) { - Logger.error( - "Failed to add Metadata (unhandled reason: " - + e.getMessage(), e); + if (httpProvider != null && httpProvider instanceof BaseMetadataProvider) { + Logger.debug("Destroy failed Metadata provider"); + ((BaseMetadataProvider)httpProvider).destroy(); + + } + } + } } - internalProvider = chainProvider; - - } catch (ConfigurationException e) { - Logger.error("Access MOA-ID configuration FAILED.", e); + } else + Logger.info("No Online-Application configuration found. PVP 2.1 metadata provider initialization failed!"); + + try { + chainProvider.setProviders(new ArrayList(providersinuse.values())); + } catch (MetadataProviderException e) { + Logger.error( + "Failed to add Metadata (unhandled reason: " + + e.getMessage(), e); } + + internalProvider = chainProvider; } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/metadata/SimpleMOAMetadataProvider.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/metadata/SimpleMOAMetadataProvider.java index d5c7d9100..e060e18e1 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/metadata/SimpleMOAMetadataProvider.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/metadata/SimpleMOAMetadataProvider.java @@ -22,15 +22,19 @@ */ package at.gv.egovernment.moa.id.protocols.pvp2x.metadata; +import java.io.File; import java.util.Timer; import javax.net.ssl.SSLHandshakeException; import org.apache.commons.httpclient.MOAHttpClient; +import org.apache.commons.httpclient.params.HttpClientParams; +import org.opensaml.saml2.metadata.provider.FilesystemMetadataProvider; import org.opensaml.saml2.metadata.provider.HTTPMetadataProvider; import org.opensaml.saml2.metadata.provider.MetadataFilter; import org.opensaml.saml2.metadata.provider.MetadataProvider; -import org.opensaml.xml.parse.BasicParserPool; +import org.opensaml.xml.parse.ParserPool; +import org.springframework.beans.factory.annotation.Autowired; import at.gv.egovernment.moa.id.commons.api.AuthConfiguration; import at.gv.egovernment.moa.id.commons.ex.MOAHttpProtocolSocketFactoryException; @@ -40,6 +44,7 @@ import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants; import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.filter.SchemaValidationException; import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.filter.SignatureValidationException; import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.FileUtils; /** * @author tlenz @@ -47,6 +52,104 @@ import at.gv.egovernment.moa.logging.Logger; */ public abstract class SimpleMOAMetadataProvider implements MetadataProvider{ + private static final String URI_PREFIX_HTTP = "http:"; + private static final String URI_PREFIX_HTTPS = "https:"; + private static final String URI_PREFIX_FILE = "file:"; + + + @Autowired + protected AuthConfiguration authConfig; + + /** + * Create a single SAML2 MOA specific metadata provider + * + * @param metadataLocation where the metadata should be loaded, but never null. If the location starts with http(s):, than a http + * based metadata provider is used. If the location starts with file:, than a filesystem based metadata provider is used + * @param filter Filters, which should be used to validate the metadata + * @param IdForLogging Id, which is used for Logging + * @param timer {@link Timer} which is used to schedule metadata refresh operations + * + * @return SAML2 Metadata Provider, or null if the metadata provider can not initialized + */ + protected MetadataProvider createNewMoaMetadataProvider(String metadataLocation, MetadataFilter filter, + String IdForLogging, Timer timer, ParserPool pool) { + if (metadataLocation.startsWith(URI_PREFIX_HTTP) || metadataLocation.startsWith(URI_PREFIX_HTTPS)) + return createNewHTTPMetaDataProvider(metadataLocation, filter, IdForLogging, timer, pool); + + else { + String absoluteMetadataLocation = FileUtils.makeAbsoluteURL( + metadataLocation, + authConfig.getRootConfigFileDir()); + + if (absoluteMetadataLocation.startsWith(URI_PREFIX_FILE)) { + File metadataFile = new File(absoluteMetadataLocation); + if (metadataFile.exists()) + return createNewFileSystemMetaDataProvider(metadataFile, filter, IdForLogging, timer, pool); + + else { + Logger.warn("SAML2 metadata file: " + absoluteMetadataLocation + " not found or not exist"); + return null; + } + + } + } + + Logger.warn("SAML2 metadata has an unsupported metadata location prefix: " + metadataLocation); + return null; + + } + + + /** + * Create a single SAML2 filesystem based metadata provider + * + * @param metadataFile File, where the metadata should be loaded + * @param filter Filters, which should be used to validate the metadata + * @param IdForLogging Id, which is used for Logging + * @param timer {@link Timer} which is used to schedule metadata refresh operations + * @param pool + * + * @return SAML2 Metadata Provider + */ + private MetadataProvider createNewFileSystemMetaDataProvider(File metadataFile, MetadataFilter filter, String IdForLogging, Timer timer, ParserPool pool) { + FilesystemMetadataProvider fileSystemProvider = null; + try { + fileSystemProvider = new FilesystemMetadataProvider(timer, metadataFile); + fileSystemProvider.setParserPool(pool); + fileSystemProvider.setRequireValidMetadata(true); + fileSystemProvider.setMinRefreshDelay(1000*60*15); //15 minutes + fileSystemProvider.setMaxRefreshDelay(1000*60*60*24); //24 hours + //httpProvider.setRefreshDelayFactor(0.1F); + + fileSystemProvider.setMetadataFilter(filter); + fileSystemProvider.initialize(); + + fileSystemProvider.setRequireValidMetadata(true); + + return fileSystemProvider; + + } catch (Exception e) { + Logger.warn( + "Failed to load Metadata file for " + + IdForLogging + "[ " + + "File: " + metadataFile.getAbsolutePath() + + " Msg: " + e.getMessage() + " ]", e); + + + Logger.warn("Can not initialize SAML2 metadata provider from filesystem: " + metadataFile.getAbsolutePath() + + " Reason: " + e.getMessage(), e); + + if (fileSystemProvider != null) + fileSystemProvider.destroy(); + + } + + return null; + + } + + + /** * Create a single SAML2 HTTP metadata provider * @@ -54,16 +157,21 @@ public abstract class SimpleMOAMetadataProvider implements MetadataProvider{ * @param filter Filters, which should be used to validate the metadata * @param IdForLogging Id, which is used for Logging * @param timer {@link Timer} which is used to schedule metadata refresh operations + * @param pool * * @return SAML2 Metadata Provider */ - protected HTTPMetadataProvider createNewHTTPMetaDataProvider(String metadataURL, MetadataFilter filter, String IdForLogging, Timer timer) { + private MetadataProvider createNewHTTPMetaDataProvider(String metadataURL, MetadataFilter filter, String IdForLogging, Timer timer, ParserPool pool) { HTTPMetadataProvider httpProvider = null; //Timer timer= null; MOAHttpClient httpClient = null; try { httpClient = new MOAHttpClient(); + HttpClientParams httpClientParams = new HttpClientParams(); + httpClientParams.setSoTimeout(AuthConfiguration.CONFIG_PROPS_METADATA_SOCKED_TIMEOUT); + httpClient.setParams(httpClientParams); + if (metadataURL.startsWith("https:")) { try { //FIX: change hostname validation default flag to true when httpClient is updated to > 4.4 @@ -88,7 +196,7 @@ public abstract class SimpleMOAMetadataProvider implements MetadataProvider{ // timer = new Timer(true); httpProvider = new HTTPMetadataProvider(timer, httpClient, metadataURL); - httpProvider.setParserPool(new BasicParserPool()); + httpProvider.setParserPool(pool); httpProvider.setRequireValidMetadata(true); httpProvider.setMinRefreshDelay(1000*60*15); //15 minutes httpProvider.setMaxRefreshDelay(1000*60*60*24); //24 hours @@ -115,7 +223,7 @@ public abstract class SimpleMOAMetadataProvider implements MetadataProvider{ + metadataURL + " FAILED.", e); } - Logger.error( + Logger.warn( "Failed to load Metadata file for " + IdForLogging + "[ " + e.getMessage() + " ]", e); diff --git a/id/server/moa-id-commons/src/main/java/at/gv/egovernment/moa/id/commons/api/AuthConfiguration.java b/id/server/moa-id-commons/src/main/java/at/gv/egovernment/moa/id/commons/api/AuthConfiguration.java index fcf4c3ffa..4df11b35c 100644 --- a/id/server/moa-id-commons/src/main/java/at/gv/egovernment/moa/id/commons/api/AuthConfiguration.java +++ b/id/server/moa-id-commons/src/main/java/at/gv/egovernment/moa/id/commons/api/AuthConfiguration.java @@ -16,7 +16,8 @@ public interface AuthConfiguration extends ConfigurationProvider{ public static final String DEFAULT_X509_CHAININGMODE = "pkix"; - + public static final int CONFIG_PROPS_METADATA_SOCKED_TIMEOUT = 20 * 1000; //20 seconds metadata socked timeout + public Properties getGeneralPVP2ProperiesConfig(); diff --git a/id/server/modules/moa-id-module-elga_mandate_service/src/main/java/at/gv/egovernment/moa/id/auth/modules/elgamandates/utils/ELGAMandateServiceMetadataProvider.java b/id/server/modules/moa-id-module-elga_mandate_service/src/main/java/at/gv/egovernment/moa/id/auth/modules/elgamandates/utils/ELGAMandateServiceMetadataProvider.java index b35ffdf62..adc2a310b 100644 --- a/id/server/modules/moa-id-module-elga_mandate_service/src/main/java/at/gv/egovernment/moa/id/auth/modules/elgamandates/utils/ELGAMandateServiceMetadataProvider.java +++ b/id/server/modules/moa-id-module-elga_mandate_service/src/main/java/at/gv/egovernment/moa/id/auth/modules/elgamandates/utils/ELGAMandateServiceMetadataProvider.java @@ -36,12 +36,11 @@ import org.opensaml.saml2.metadata.provider.MetadataFilter; import org.opensaml.saml2.metadata.provider.MetadataProvider; import org.opensaml.saml2.metadata.provider.MetadataProviderException; import org.opensaml.xml.XMLObject; -import org.springframework.beans.factory.annotation.Autowired; +import org.opensaml.xml.parse.BasicParserPool; import org.springframework.stereotype.Service; import at.gv.egovernment.moa.id.auth.IDestroyableObject; import at.gv.egovernment.moa.id.auth.modules.elgamandates.ELGAMandatesAuthConstants; -import at.gv.egovernment.moa.id.commons.api.AuthConfiguration; import at.gv.egovernment.moa.id.protocols.pvp2x.metadata.SimpleMOAMetadataProvider; import at.gv.egovernment.moa.id.protocols.pvp2x.verification.metadata.MOASPMetadataSignatureFilter; import at.gv.egovernment.moa.id.protocols.pvp2x.verification.metadata.SchemaValidationFilter; @@ -57,8 +56,6 @@ import at.gv.egovernment.moa.util.MiscUtil; @Service("ELGAMandate_MetadataProvider") public class ELGAMandateServiceMetadataProvider extends SimpleMOAMetadataProvider implements IDestroyableObject { - - @Autowired AuthConfiguration authConfig; private ChainingMetadataProvider metadataProvider = new ChainingMetadataProvider(); private Timer timer = null; @@ -256,11 +253,12 @@ public class ELGAMandateServiceMetadataProvider extends SimpleMOAMetadataProvide filter.addFilter(new SchemaValidationFilter(true)); filter.addFilter(new MOASPMetadataSignatureFilter(trustProfileID)); - HTTPMetadataProvider idpMetadataProvider = createNewHTTPMetaDataProvider(metdataURL, + MetadataProvider idpMetadataProvider = createNewMoaMetadataProvider(metdataURL, filter, - ELGAMandatesAuthConstants.MODULE_NAME_FOR_LOGGING, - timer); - + ELGAMandatesAuthConstants.MODULE_NAME_FOR_LOGGING, + timer, + new BasicParserPool()); + if (idpMetadataProvider == null) { Logger.error("Create ELGA Mandate-Service Client FAILED."); throw new MetadataProviderException("Can not initialize ELGA Mandate-Service metadata provider."); -- cgit v1.2.3 From 782b159ec4050a459f8aadf85b68fb2b15fbf1b2 Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Mon, 17 Jul 2017 10:25:31 +0200 Subject: refactor MOA eIDAS metadata provider --- .../moa/id/auth/modules/eidas/Constants.java | 1 - .../engine/MOAeIDASChainingMetadataProvider.java | 122 ++++----------------- 2 files changed, 22 insertions(+), 101 deletions(-) (limited to 'id/server/modules') diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/Constants.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/Constants.java index 36323f3a5..01b202a88 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/Constants.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/Constants.java @@ -71,7 +71,6 @@ public class Constants { //timeouts and clock skews public static final int CONFIG_PROPS_SKEWTIME = 2 * 60 * 1000; //2 minutes skew time for response validation - public static final int CONFIG_PROPS_METADATA_SOCKED_TIMEOUT = 20 * 1000; //20 seconds metadata socked timeout public static final long CONFIG_PROPS_METADATA_GARBAGE_TIMEOUT = 7 * 24 * 60 * 60 * 1000; //remove unused eIDAS metadata after 7 days //eIDAS request parameters diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAeIDASChainingMetadataProvider.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAeIDASChainingMetadataProvider.java index 75d57e615..a0330903b 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAeIDASChainingMetadataProvider.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAeIDASChainingMetadataProvider.java @@ -9,11 +9,8 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Timer; -import javax.net.ssl.SSLHandshakeException; import javax.xml.namespace.QName; -import org.apache.commons.httpclient.MOAHttpClient; -import org.apache.commons.httpclient.params.HttpClientParams; import org.opensaml.saml2.metadata.EntitiesDescriptor; import org.opensaml.saml2.metadata.EntityDescriptor; import org.opensaml.saml2.metadata.RoleDescriptor; @@ -29,13 +26,8 @@ import org.springframework.stereotype.Service; import at.gv.egovernment.moa.id.auth.IDestroyableObject; import at.gv.egovernment.moa.id.auth.IGarbageCollectorProcessing; import at.gv.egovernment.moa.id.auth.modules.eidas.Constants; -import at.gv.egovernment.moa.id.commons.api.AuthConfiguration; -import at.gv.egovernment.moa.id.commons.ex.MOAHttpProtocolSocketFactoryException; -import at.gv.egovernment.moa.id.commons.utils.MOAHttpProtocolSocketFactory; -import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; -import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.filter.SchemaValidationException; -import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.filter.SignatureValidationException; import at.gv.egovernment.moa.id.protocols.pvp2x.metadata.IMOARefreshableMetadataProvider; +import at.gv.egovernment.moa.id.protocols.pvp2x.metadata.SimpleMOAMetadataProvider; import at.gv.egovernment.moa.id.protocols.pvp2x.verification.metadata.MOASPMetadataSignatureFilter; import at.gv.egovernment.moa.id.saml2.MetadataFilterChain; import at.gv.egovernment.moa.logging.Logger; @@ -43,11 +35,10 @@ import at.gv.egovernment.moa.util.MiscUtil; import eu.eidas.auth.engine.AbstractProtocolEngine; @Service("eIDASMetadataProvider") -public class MOAeIDASChainingMetadataProvider implements ObservableMetadataProvider, +public class MOAeIDASChainingMetadataProvider extends SimpleMOAMetadataProvider implements ObservableMetadataProvider, IGarbageCollectorProcessing, IDestroyableObject, IMOARefreshableMetadataProvider { -// private static MOAeIDASChainingMetadataProvider instance = null; - private static Object mutex = new Object(); + private Timer timer = null; private MetadataProvider internalProvider; private Map lastAccess = null; @@ -77,6 +68,10 @@ public class MOAeIDASChainingMetadataProvider implements ObservableMetadataProvi */ @Override public void fullyDestroy() { + + if (timer != null) + timer.cancel(); + Map loadedproviders = getAllActuallyLoadedProviders(); if (loadedproviders != null) { for (Entry el : loadedproviders.entrySet()) { @@ -188,94 +183,20 @@ public class MOAeIDASChainingMetadataProvider implements ObservableMetadataProvi } } - - - private HTTPMetadataProvider createNewHTTPMetaDataProvider(String metadataURL) { - HTTPMetadataProvider httpProvider = null; - Timer timer= null; - MOAHttpClient httpClient = null; - try { - AuthConfiguration authConfig = AuthConfigurationProviderFactory.getInstance(); - - httpClient = new MOAHttpClient(); - - HttpClientParams httpClientParams = new HttpClientParams(); - httpClientParams.setSoTimeout(Constants.CONFIG_PROPS_METADATA_SOCKED_TIMEOUT); - httpClient.setParams(httpClientParams); - - if (metadataURL.startsWith("https:")) { - try { - //FIX: change hostname validation default flag to true when httpClient is updated to > 4.4 - MOAHttpProtocolSocketFactory protoSocketFactory = new MOAHttpProtocolSocketFactory( - Constants.SSLSOCKETFACTORYNAME, - authConfig.getTrustedCACertificates(), - null, - AuthConfiguration.DEFAULT_X509_CHAININGMODE, - authConfig.isTrustmanagerrevoationchecking(), - authConfig.getRevocationMethodOrder(), - authConfig.getBasicMOAIDConfigurationBoolean( - AuthConfiguration.PROP_KEY_SSL_HOSTNAME_VALIDATION, false)); - - httpClient.setCustomSSLTrustStore(metadataURL, protoSocketFactory); - - } catch (MOAHttpProtocolSocketFactoryException e) { - Logger.warn("MOA SSL-TrustStore can not initialized. Use default Java TrustStore."); - - } - } - + + private MetadataProvider createNewHTTPMetaDataProvider(String metadataURL) { + if (timer == null) timer = new Timer(true); - httpProvider = new HTTPMetadataProvider(timer, httpClient, - metadataURL); - httpProvider.setParserPool(AbstractProtocolEngine.getSecuredParserPool()); - httpProvider.setRequireValidMetadata(true); - httpProvider.setMinRefreshDelay(1000*60*15); //15 minutes - httpProvider.setMaxRefreshDelay(1000*60*60*24); //24 hours - //httpProvider.setRefreshDelayFactor(0.1F); - - //add Metadata filters - MetadataFilterChain filter = new MetadataFilterChain(); - filter.addFilter(new MOASPMetadataSignatureFilter( - authConfig.getBasicMOAIDConfiguration(Constants.CONIG_PROPS_EIDAS_METADATA_VALIDATION_TRUSTSTORE))); - httpProvider.setMetadataFilter(filter); - - httpProvider.initialize(); - - return httpProvider; - - } catch (Throwable e) { - if (e.getCause() != null && e.getCause().getCause() instanceof SSLHandshakeException) { - Logger.warn("SSL-Server certificate for metadata " - + metadataURL + " not trusted.", e); - - } if (e.getCause() != null && e.getCause().getCause() instanceof SignatureValidationException) { - Logger.warn("Signature verification for metadata" - + metadataURL + " FAILED.", e); - - } if (e.getCause() != null && e.getCause().getCause() instanceof SchemaValidationException) { - Logger.warn("Schema validation for metadata " - + metadataURL + " FAILED.", e); - } - - Logger.error( - "Failed to add Metadata file for " - + metadataURL + "[ " - + e.getMessage() + " ]", e); - - if (httpProvider != null) { - Logger.debug("Destroy failed Metadata provider"); - httpProvider.destroy(); - } - - if (timer != null) { - Logger.debug("Destroy Timer."); - timer.cancel(); - } - - - } - return null; + //add Metadata filters + MetadataFilterChain filter = new MetadataFilterChain(); + filter.addFilter(new MOASPMetadataSignatureFilter( + authConfig.getBasicMOAIDConfiguration(Constants.CONIG_PROPS_EIDAS_METADATA_VALIDATION_TRUSTSTORE))); + + return createNewMoaMetadataProvider(metadataURL, filter, + "eIDAS metadata-provider", + timer, AbstractProtocolEngine.getSecuredParserPool()); + } private Map getAllActuallyLoadedProviders() { @@ -310,7 +231,7 @@ public class MOAeIDASChainingMetadataProvider implements ObservableMetadataProvi } else { //load new Metadata Provider ChainingMetadataProvider chainProvider = (ChainingMetadataProvider) internalProvider; - HTTPMetadataProvider newMetadataProvider = createNewHTTPMetaDataProvider(metadataURL); + MetadataProvider newMetadataProvider = createNewHTTPMetaDataProvider(metadataURL); if (newMetadataProvider != null) { chainProvider.addMetadataProvider(newMetadataProvider); @@ -320,7 +241,8 @@ public class MOAeIDASChainingMetadataProvider implements ObservableMetadataProvi + metadataURL + " is added."); return true; - } + } else + Logger.warn("Can not load eIDAS metadata from URL: " + metadataURL); } } else -- cgit v1.2.3 From f912da9959267d214bb10a2be8e412af731141ed Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Wed, 26 Jul 2017 10:24:55 +0200 Subject: refactor MOA metadataprovider to load metadata from file system --- .../moa/id/auth/IPostStartupInitializable.java | 41 ++++++++++++++++++++++ .../moa/id/auth/MOAIDAuthInitializer.java | 2 +- .../PropertyBasedAuthConfigurationProvider.java | 5 +++ .../pvp2x/metadata/SimpleMOAMetadataProvider.java | 9 +++-- .../resources/properties/id_messages_de.properties | 2 +- .../moa/id/commons/api/AuthConfiguration.java | 10 ++++++ .../moa/id/commons/utils/KeyValueUtils.java | 22 ++++++++++++ .../moa/id/auth/MOAIDAuthSpringInitializer.java | 16 ++++++++- .../moa/id/auth/modules/eidas/Constants.java | 2 ++ .../engine/MOAeIDASChainingMetadataProvider.java | 30 +++++++++++++++- 10 files changed, 130 insertions(+), 9 deletions(-) create mode 100644 id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/IPostStartupInitializable.java (limited to 'id/server/modules') diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/IPostStartupInitializable.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/IPostStartupInitializable.java new file mode 100644 index 000000000..d918be463 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/IPostStartupInitializable.java @@ -0,0 +1,41 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ +package at.gv.egovernment.moa.id.auth; + + +/** + * + * @author tlenz + * + * Interface initialize a Object when the MOA-ID-Auth start-up process is fully completed + * + */ +public interface IPostStartupInitializable { + + /** + * This method is called once when MOA-ID-Auth start-up process is fully completed + * + */ + public void executeAfterStartup(); + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthInitializer.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthInitializer.java index 65ea2fd90..3d45e2468 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthInitializer.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthInitializer.java @@ -127,7 +127,7 @@ public class MOAIDAuthInitializer { Random.seedRandom(); Logger.debug("Random-number generator is seeded."); - // Initialize configuration provider + // Initialize configuration provider for non-spring managed parts AuthConfiguration authConf = AuthConfigurationProviderFactory.reload(rootContext); //test, if MOA-ID is already configured diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/PropertyBasedAuthConfigurationProvider.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/PropertyBasedAuthConfigurationProvider.java index 7e0f48744..35d052acd 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/PropertyBasedAuthConfigurationProvider.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/PropertyBasedAuthConfigurationProvider.java @@ -235,6 +235,11 @@ public class PropertyBasedAuthConfigurationProvider extends ConfigurationProvide return properties.getProperty(key, defaultValue); } + + public Map getBasicMOAIDConfigurationWithPrefix(final String prefix) { + return KeyValueUtils.getSubSetWithPrefix(KeyValueUtils.concertPropertiesToMap(properties), prefix); + + } /* (non-Javadoc) diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/metadata/SimpleMOAMetadataProvider.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/metadata/SimpleMOAMetadataProvider.java index e060e18e1..6c2235654 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/metadata/SimpleMOAMetadataProvider.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/metadata/SimpleMOAMetadataProvider.java @@ -39,7 +39,6 @@ import org.springframework.beans.factory.annotation.Autowired; import at.gv.egovernment.moa.id.commons.api.AuthConfiguration; import at.gv.egovernment.moa.id.commons.ex.MOAHttpProtocolSocketFactoryException; import at.gv.egovernment.moa.id.commons.utils.MOAHttpProtocolSocketFactory; -import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants; import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.filter.SchemaValidationException; import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.filter.SignatureValidationException; @@ -177,12 +176,12 @@ public abstract class SimpleMOAMetadataProvider implements MetadataProvider{ //FIX: change hostname validation default flag to true when httpClient is updated to > 4.4 MOAHttpProtocolSocketFactory protoSocketFactory = new MOAHttpProtocolSocketFactory( PVPConstants.SSLSOCKETFACTORYNAME, - AuthConfigurationProviderFactory.getInstance().getTrustedCACertificates(), + authConfig.getTrustedCACertificates(), null, AuthConfiguration.DEFAULT_X509_CHAININGMODE, - AuthConfigurationProviderFactory.getInstance().isTrustmanagerrevoationchecking(), - AuthConfigurationProviderFactory.getInstance().getRevocationMethodOrder(), - AuthConfigurationProviderFactory.getInstance().getBasicMOAIDConfigurationBoolean( + authConfig.isTrustmanagerrevoationchecking(), + authConfig.getRevocationMethodOrder(), + authConfig.getBasicMOAIDConfigurationBoolean( AuthConfiguration.PROP_KEY_SSL_HOSTNAME_VALIDATION, false)); httpClient.setCustomSSLTrustStore(metadataURL, protoSocketFactory); diff --git a/id/server/idserverlib/src/main/resources/resources/properties/id_messages_de.properties b/id/server/idserverlib/src/main/resources/resources/properties/id_messages_de.properties index 1a2f0d1d3..50b2c5ece 100644 --- a/id/server/idserverlib/src/main/resources/resources/properties/id_messages_de.properties +++ b/id/server/idserverlib/src/main/resources/resources/properties/id_messages_de.properties @@ -53,7 +53,7 @@ auth.32=Federated authentication FAILED. No configuration for IDP {0} auth.33=Federated authentication FAILED. Configuration of IDP {0} does not allow inbound messages. auth.34=Federated authentication FAILED. Configuration of IDP {0} is marked as BusinessService-IDP, but Public-Service attributes are requested. -init.00=MOA ID Authentisierung wurde erfolgreich gestartet +init.00=MOA-ID-Auth wurde erfolgreich gestartet init.01=Fehler beim Aktivieren des IAIK-JCE/JSSE/JDK1.3 Workaround\: SSL ist m\u00F6glicherweise nicht verf\u00FCgbar init.02=Fehler beim Starten des Service MOA-ID-Auth init.04=Fehler beim Datenbankzugriff mit der SessionID {0} diff --git a/id/server/moa-id-commons/src/main/java/at/gv/egovernment/moa/id/commons/api/AuthConfiguration.java b/id/server/moa-id-commons/src/main/java/at/gv/egovernment/moa/id/commons/api/AuthConfiguration.java index 4df11b35c..07b07d980 100644 --- a/id/server/moa-id-commons/src/main/java/at/gv/egovernment/moa/id/commons/api/AuthConfiguration.java +++ b/id/server/moa-id-commons/src/main/java/at/gv/egovernment/moa/id/commons/api/AuthConfiguration.java @@ -47,6 +47,16 @@ public interface AuthConfiguration extends ConfigurationProvider{ */ public String getBasicMOAIDConfiguration(final String key, final String defaultValue); + /** + * Get a set of configuration values from basic file based MOA-ID configuration that starts with this prefix + *

+ * Important: The configuration values must be of type String! + * + * @param prefix Prefix of the configuration key + * @return Map without prefix, but never null + */ + public Map getBasicMOAIDConfigurationWithPrefix(final String prefix); + public int getTransactionTimeOut(); public int getSSOCreatedTimeOut(); public int getSSOUpdatedTimeOut(); diff --git a/id/server/moa-id-commons/src/main/java/at/gv/egovernment/moa/id/commons/utils/KeyValueUtils.java b/id/server/moa-id-commons/src/main/java/at/gv/egovernment/moa/id/commons/utils/KeyValueUtils.java index bc567e5d2..40ef5a23a 100644 --- a/id/server/moa-id-commons/src/main/java/at/gv/egovernment/moa/id/commons/utils/KeyValueUtils.java +++ b/id/server/moa-id-commons/src/main/java/at/gv/egovernment/moa/id/commons/utils/KeyValueUtils.java @@ -29,6 +29,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Properties; import java.util.Set; import org.apache.commons.lang3.StringUtils; @@ -44,6 +45,27 @@ public class KeyValueUtils { public static final String KEY_DELIMITER = "."; public static final String CSV_DELIMITER = ","; + /** + * Convert Java properties into a Map + *

+ * Important: The key/values from properties must be of type String! + * + * @param properties + * @return + */ + public static Map concertPropertiesToMap(Properties properties) { + return new HashMap((Map) properties); + + //INFO Java8 solution ;) + // return properties.entrySet().stream().collect( +// Collectors.toMap( +// e -> e.getKey().toString(), +// e -> e.getValue().toString() +// ) +// ); + + } + /** * Extract the first child of an input key after a the prefix * diff --git a/id/server/moa-id-spring-initializer/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthSpringInitializer.java b/id/server/moa-id-spring-initializer/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthSpringInitializer.java index 07ba6a89e..b6fd8de8e 100644 --- a/id/server/moa-id-spring-initializer/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthSpringInitializer.java +++ b/id/server/moa-id-spring-initializer/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthSpringInitializer.java @@ -1,5 +1,8 @@ package at.gv.egovernment.moa.id.auth; +import java.util.Map; +import java.util.Map.Entry; + import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRegistration; @@ -147,8 +150,19 @@ public class MOAIDAuthSpringInitializer implements WebApplicationInitializer { // servletContext.addFilter("vHost RequestFilter", new VHostUrlRewriteServletFilter(rootContext)) // .addMappingForUrlPatterns(null, false, "/*"); - Logger.info("Basic Context initalisation finished --> Start MOA-ID-Auth initialisation process ..."); + Logger.info("Basic Context initalisation finished --> Start MOA-ID-Auth initialization process ..."); MOAIDAuthInitializer.initialize(rootContext); + + + //initialize object that implements the IPostStartupInitializeable interface + Map objForInitialization = rootContext.getBeansOfType(IPostStartupInitializable.class); + for (Entry el : objForInitialization.entrySet()) { + Logger.debug("Starting post start-up initialization of '" + el.getKey() + "' ..." ); + el.getValue().executeAfterStartup(); + Logger.info("Post start-up initialization of '" + el.getKey() + "' finished." ); + + } + Logger.info(MOAIDMessageProvider.getInstance().getMessage( "init.00", null)); Logger.info("MOA-ID-Auth initialization finished."); diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/Constants.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/Constants.java index 01b202a88..adf6c4979 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/Constants.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/Constants.java @@ -67,6 +67,8 @@ public class Constants { public static final String CONIG_PROPS_EIDAS_NODE_COUNTRY = CONIG_PROPS_EIDAS_NODE + ".country"; public static final String CONIG_PROPS_EIDAS_NODE_LoA = CONIG_PROPS_EIDAS_NODE + ".LoA"; + public static final String CONIG_PROPS_EIDAS_METADATA_URLS_LIST_PREFIX = CONIG_PROPS_EIDAS_PREFIX + ".metadata.url"; + //timeouts and clock skews diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAeIDASChainingMetadataProvider.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAeIDASChainingMetadataProvider.java index a0330903b..76cc12e44 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAeIDASChainingMetadataProvider.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAeIDASChainingMetadataProvider.java @@ -25,18 +25,20 @@ import org.springframework.stereotype.Service; import at.gv.egovernment.moa.id.auth.IDestroyableObject; import at.gv.egovernment.moa.id.auth.IGarbageCollectorProcessing; +import at.gv.egovernment.moa.id.auth.IPostStartupInitializable; import at.gv.egovernment.moa.id.auth.modules.eidas.Constants; import at.gv.egovernment.moa.id.protocols.pvp2x.metadata.IMOARefreshableMetadataProvider; import at.gv.egovernment.moa.id.protocols.pvp2x.metadata.SimpleMOAMetadataProvider; import at.gv.egovernment.moa.id.protocols.pvp2x.verification.metadata.MOASPMetadataSignatureFilter; import at.gv.egovernment.moa.id.saml2.MetadataFilterChain; import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.FileUtils; import at.gv.egovernment.moa.util.MiscUtil; import eu.eidas.auth.engine.AbstractProtocolEngine; @Service("eIDASMetadataProvider") public class MOAeIDASChainingMetadataProvider extends SimpleMOAMetadataProvider implements ObservableMetadataProvider, - IGarbageCollectorProcessing, IDestroyableObject, IMOARefreshableMetadataProvider { + IGarbageCollectorProcessing, IDestroyableObject, IMOARefreshableMetadataProvider, IPostStartupInitializable{ private Timer timer = null; @@ -62,6 +64,31 @@ public class MOAeIDASChainingMetadataProvider extends SimpleMOAMetadataProvider lastAccess = new HashMap(); } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.auth.IPostStartupInitializable#executeAfterStartup() + */ + @Override + public void executeAfterStartup() { + initializeEidasMetadataFromFileSystem(); + + } + + protected void initializeEidasMetadataFromFileSystem() { + Map metadataToLoad = authConfig.getBasicMOAIDConfigurationWithPrefix(Constants.CONIG_PROPS_EIDAS_METADATA_URLS_LIST_PREFIX); + if (!metadataToLoad.isEmpty()) { + Logger.info("Load static configurated eIDAS metadata ... "); + for (String metaatalocation : metadataToLoad.values()) { + String absMetadataLocation = FileUtils.makeAbsoluteURL(metaatalocation, authConfig.getRootConfigFileDir()); + Logger.info(" Load eIDAS metadata from: " + absMetadataLocation); + refreshMetadataProvider(absMetadataLocation); + + } + + Logger.info("Load static configurated eIDAS metadata finished "); + } + } + /* (non-Javadoc) * @see at.gv.egovernment.moa.id.auth.IDestroyableObject#fullyDestroy() @@ -358,4 +385,5 @@ public class MOAeIDASChainingMetadataProvider extends SimpleMOAMetadataProvider if (observer != null) observer.onEvent(this); } + } -- cgit v1.2.3 From f84bcfbcc5563a3784b6218e41c27ec3432e58a6 Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Wed, 26 Jul 2017 10:25:32 +0200 Subject: switch to eIDAS SAML-engine 1.3.0-final --- id/server/modules/moa-id-module-eIDAS/pom.xml | 10 +++++----- .../id/auth/modules/eidas/tasks/ReceiveAuthnResponseTask.java | 1 + 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'id/server/modules') diff --git a/id/server/modules/moa-id-module-eIDAS/pom.xml b/id/server/modules/moa-id-module-eIDAS/pom.xml index 58f6584ae..5bdead8b2 100644 --- a/id/server/modules/moa-id-module-eIDAS/pom.xml +++ b/id/server/modules/moa-id-module-eIDAS/pom.xml @@ -12,11 +12,11 @@ ${basedir}/../../../../repository - 1.3.0-SNAPSHOT - 1.3.0-SNAPSHOT - 1.3.0-SNAPSHOT - 1.3.0-SNAPSHOT - 1.3.0-SNAPSHOT + 1.3.0 + 1.3.0 + 1.3.0 + 1.3.0 + 1.3.0 diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/ReceiveAuthnResponseTask.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/ReceiveAuthnResponseTask.java index 45ba3d64e..a31bbaf02 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/ReceiveAuthnResponseTask.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/ReceiveAuthnResponseTask.java @@ -58,6 +58,7 @@ public class ReceiveAuthnResponseTask extends AbstractAuthServletTask { IAuthenticationResponse samlResp = engine.unmarshallResponseAndValidate(decSamlToken, request.getRemoteHost(), Constants.CONFIG_PROPS_SKEWTIME, + Constants.CONFIG_PROPS_SKEWTIME, pendingReq.getAuthURL() + Constants.eIDAS_HTTP_ENDPOINT_METADATA); if (samlResp.isEncrypted()) { -- cgit v1.2.3 From ac7930ec5d3505dc9ef47fef045d6b5bae53eadb Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Wed, 26 Jul 2017 15:35:42 +0200 Subject: fix some bugs in combination with eIDAS saml-engine 1.3 --- .../java/at/gv/egovernment/moa/id/auth/modules/eidas/Constants.java | 3 ++- .../modules/eidas/engine/validation/MoaEidasConditionsValidator.java | 4 ++-- .../moa/id/auth/modules/eidas/tasks/ReceiveAuthnResponseTask.java | 4 ++-- .../gv/egovernment/moa/id/protocols/eidas/EidasMetaDataRequest.java | 1 + 4 files changed, 7 insertions(+), 5 deletions(-) (limited to 'id/server/modules') diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/Constants.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/Constants.java index adf6c4979..c0101b553 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/Constants.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/Constants.java @@ -72,7 +72,8 @@ public class Constants { //timeouts and clock skews - public static final int CONFIG_PROPS_SKEWTIME = 2 * 60 * 1000; //2 minutes skew time for response validation + public static final long CONFIG_PROPS_SKEWTIME_BEFORE = -2 * 60 * 1000; //5 minutes skew time for response validation + public static final long CONFIG_PROPS_SKEWTIME_AFTER = 2 * 60 * 1000; //5 minutes skew time for response validation public static final long CONFIG_PROPS_METADATA_GARBAGE_TIMEOUT = 7 * 24 * 60 * 60 * 1000; //remove unused eIDAS metadata after 7 days //eIDAS request parameters diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/validation/MoaEidasConditionsValidator.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/validation/MoaEidasConditionsValidator.java index d9453322f..9895ca79f 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/validation/MoaEidasConditionsValidator.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/validation/MoaEidasConditionsValidator.java @@ -56,7 +56,7 @@ public class MoaEidasConditionsValidator extends ConditionsSpecValidator { throw new ValidationException("NotBefore is required."); } - if (conditions.getNotBefore().minusMillis(Constants.CONFIG_PROPS_SKEWTIME).isAfterNow()) { + if (conditions.getNotBefore().plusMillis((int)Constants.CONFIG_PROPS_SKEWTIME_BEFORE).isAfterNow()) { throw new ValidationException("Current time is before NotBefore condition"); } @@ -64,7 +64,7 @@ public class MoaEidasConditionsValidator extends ConditionsSpecValidator { throw new ValidationException("NotOnOrAfter is required."); } - if (conditions.getNotOnOrAfter().isBeforeNow()) { + if (conditions.getNotOnOrAfter().plusMillis((int)Constants.CONFIG_PROPS_SKEWTIME_AFTER).isBeforeNow()) { throw new ValidationException("Current time is after NotOnOrAfter condition"); } diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/ReceiveAuthnResponseTask.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/ReceiveAuthnResponseTask.java index a31bbaf02..17e112c4c 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/ReceiveAuthnResponseTask.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/tasks/ReceiveAuthnResponseTask.java @@ -57,8 +57,8 @@ public class ReceiveAuthnResponseTask extends AbstractAuthServletTask { //validate SAML token IAuthenticationResponse samlResp = engine.unmarshallResponseAndValidate(decSamlToken, request.getRemoteHost(), - Constants.CONFIG_PROPS_SKEWTIME, - Constants.CONFIG_PROPS_SKEWTIME, + Constants.CONFIG_PROPS_SKEWTIME_BEFORE, + Constants.CONFIG_PROPS_SKEWTIME_AFTER, pendingReq.getAuthURL() + Constants.eIDAS_HTTP_ENDPOINT_METADATA); if (samlResp.isEncrypted()) { diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EidasMetaDataRequest.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EidasMetaDataRequest.java index bfe410fc2..cc9b09107 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EidasMetaDataRequest.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/protocols/eidas/EidasMetaDataRequest.java @@ -126,6 +126,7 @@ public class EidasMetaDataRequest implements IAction { metadataConfigBuilder.entityID(metadata_url); metadataConfigBuilder.assertionConsumerUrl(sp_return_url); + metadataConfigBuilder.addProtocolBinding(SAMLConstants.SAML2_POST_BINDING_URI); metadataConfigBuilder.addProtocolBindingLocation( SAMLConstants.SAML2_POST_BINDING_URI, pendingReq.getAuthURL() + Constants.eIDAS_HTTP_ENDPOINT_IDP_COLLEAGUEREQUEST); -- cgit v1.2.3 From 22665d0bb596d772cf6cb81ba458b75d8b455324 Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Thu, 27 Jul 2017 09:49:10 +0200 Subject: update logging behavior of eIDAS metadata provider implementation --- .../engine/MOAeIDASChainingMetadataProvider.java | 27 ++++++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) (limited to 'id/server/modules') diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAeIDASChainingMetadataProvider.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAeIDASChainingMetadataProvider.java index 76cc12e44..490dc9dcf 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAeIDASChainingMetadataProvider.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/engine/MOAeIDASChainingMetadataProvider.java @@ -15,6 +15,7 @@ import org.opensaml.saml2.metadata.EntitiesDescriptor; import org.opensaml.saml2.metadata.EntityDescriptor; import org.opensaml.saml2.metadata.RoleDescriptor; import org.opensaml.saml2.metadata.provider.ChainingMetadataProvider; +import org.opensaml.saml2.metadata.provider.FilesystemMetadataProvider; import org.opensaml.saml2.metadata.provider.HTTPMetadataProvider; import org.opensaml.saml2.metadata.provider.MetadataFilter; import org.opensaml.saml2.metadata.provider.MetadataProvider; @@ -163,8 +164,8 @@ public class MOAeIDASChainingMetadataProvider extends SimpleMOAMetadataProvider + " after timeout."); } else - Logger.warn("eIDAS metadata for EntityID: " + expired - + " is marked as unsed, but no loaded metadata provider is found."); + Logger.info("eIDAS metadata for EntityID: " + expired + + " is marked as expired, but no currently loaded HTTPMetadataProvider metadata provider is found."); } } @@ -229,15 +230,31 @@ public class MOAeIDASChainingMetadataProvider extends SimpleMOAMetadataProvider private Map getAllActuallyLoadedProviders() { Map loadedproviders = new HashMap(); ChainingMetadataProvider chainProvider = (ChainingMetadataProvider) internalProvider; - + //make a Map of all actually loaded HTTPMetadataProvider List providers = chainProvider.getProviders(); for (MetadataProvider provider : providers) { if (provider instanceof HTTPMetadataProvider) { HTTPMetadataProvider httpprovider = (HTTPMetadataProvider) provider; loadedproviders.put(httpprovider.getMetadataURI(), httpprovider); - - } + + } else if (provider instanceof FilesystemMetadataProvider) { + String entityID = "'!!NO-ENTITYID!!'"; + try { + if (provider.getMetadata() instanceof EntityDescriptor) + entityID = ((EntityDescriptor)provider.getMetadata()).getEntityID(); + + Logger.debug("Skip eIDAS metadata: " + entityID + " because it is loaded from local Filesystem"); + + } catch (MetadataProviderException e) { + Logger.info("Collect currently loaded eIDAS metadata provider has an internel process error: " + e.getMessage()); + + } + + } else + Logger.info("Skip " + provider.getClass().getName() + " from list of currently loaded " + + "eIDAS metadata provider"); + } return loadedproviders; -- cgit v1.2.3 From 41275a296c73a5ecb29d52829116f4b6e99ce006 Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Wed, 6 Sep 2017 12:39:48 +0200 Subject: add xsd schema for eIDAS specific SAML2 extensions --- .../java/at/gv/egovernment/moa/util/Constants.java | 9 ++++++- .../resources/schemas/eIDAS_saml_extensions.xsd | 31 ++++++++++++++++++++++ .../auth/modules/eidas/utils/SAMLEngineUtils.java | 4 +++ .../resources/schema/eIDAS_saml_extensions.xsd | 31 ++++++++++++++++++++++ 4 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 id/server/moa-id-commons/src/main/resources/resources/schemas/eIDAS_saml_extensions.xsd create mode 100644 id/server/modules/moa-id-module-eIDAS/src/main/resources/schema/eIDAS_saml_extensions.xsd (limited to 'id/server/modules') diff --git a/id/server/moa-id-commons/src/main/java/at/gv/egovernment/moa/util/Constants.java b/id/server/moa-id-commons/src/main/java/at/gv/egovernment/moa/util/Constants.java index 129478270..2a4e3b362 100644 --- a/id/server/moa-id-commons/src/main/java/at/gv/egovernment/moa/util/Constants.java +++ b/id/server/moa-id-commons/src/main/java/at/gv/egovernment/moa/util/Constants.java @@ -394,6 +394,12 @@ public interface Constants { public static final String SAML2_METADATA_SCHEMA_LOCATION = SCHEMA_ROOT + "saml-schema-metadata-2.0.xsd"; + + /* Prefix and Schema definition for eIDAS specific SAML2 extensions*/ + public static final String SAML2_eIDAS_EXTENSIONS_PREFIX = "eidas"; + public static final String SAML2_eIDAS_EXTENSIONS = "http://eidas.europa.eu/saml-extensions"; + public static final String SAML2_eIDAS_EXTENSIONS_SCHEMA_LOCATION = SCHEMA_ROOT + "eIDAS_saml_extensions.xsd"; + /** * Contains all namespaces and local schema locations for XML schema * definitions relevant for MOA. For use in validating XML parsers. @@ -427,7 +433,8 @@ public interface Constants { + (STORK_NS_URI + " " + STORK_SCHEMA_LOCATION + " ") + (STORKP_NS_URI + " " + STORKP_SCHEMA_LOCATION + " ") + (SAML2_METADATA_URI + " " + SAML2_METADATA_SCHEMA_LOCATION + " ") - + (XENC_NS_URI + " " + XENC_SCHEMA_LOCATION); + + (XENC_NS_URI + " " + XENC_SCHEMA_LOCATION) + + (SAML2_eIDAS_EXTENSIONS + " " + SAML2_eIDAS_EXTENSIONS_SCHEMA_LOCATION); /** URN prefix for bPK and wbPK. */ public static final String URN_PREFIX = "urn:publicid:gv.at"; diff --git a/id/server/moa-id-commons/src/main/resources/resources/schemas/eIDAS_saml_extensions.xsd b/id/server/moa-id-commons/src/main/resources/resources/schemas/eIDAS_saml_extensions.xsd new file mode 100644 index 000000000..76b82a267 --- /dev/null +++ b/id/server/moa-id-commons/src/main/resources/resources/schemas/eIDAS_saml_extensions.xsd @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/SAMLEngineUtils.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/SAMLEngineUtils.java index d469ca28c..02a5df098 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/SAMLEngineUtils.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/SAMLEngineUtils.java @@ -28,6 +28,7 @@ import java.net.URL; import java.util.HashMap; import java.util.Map; +import org.opensaml.common.xml.SAMLSchemaBuilder; import org.opensaml.xml.ConfigurationException; import org.opensaml.xml.XMLConfigurator; @@ -107,6 +108,9 @@ public class SAMLEngineUtils { //overwrite eIDAS response validator suite because Condition-Valitator has not time jitter initOpenSAMLConfig("own-saml-eidasnode-config.xml"); + //add eIDAS specific SAML2 extensions to eIDAS Schema validatior + SAMLSchemaBuilder.addExtensionSchema( + at.gv.egovernment.moa.util.Constants.SAML2_eIDAS_EXTENSIONS_SCHEMA_LOCATION); eIDASEngine = engine; diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/resources/schema/eIDAS_saml_extensions.xsd b/id/server/modules/moa-id-module-eIDAS/src/main/resources/schema/eIDAS_saml_extensions.xsd new file mode 100644 index 000000000..76b82a267 --- /dev/null +++ b/id/server/modules/moa-id-module-eIDAS/src/main/resources/schema/eIDAS_saml_extensions.xsd @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- cgit v1.2.3 From e36b3381215d1e29ba83658314e22085a3daff14 Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Wed, 6 Sep 2017 14:30:42 +0200 Subject: fix wrong entries in eIDAS metadata extensions --- .../moa/id/auth/modules/eidas/utils/NewMoaEidasMetadata.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'id/server/modules') diff --git a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/NewMoaEidasMetadata.java b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/NewMoaEidasMetadata.java index d0c003b31..bb52d2ffe 100644 --- a/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/NewMoaEidasMetadata.java +++ b/id/server/modules/moa-id-module-eIDAS/src/main/java/at/gv/egovernment/moa/id/auth/modules/eidas/utils/NewMoaEidasMetadata.java @@ -168,12 +168,12 @@ public class NewMoaEidasMetadata { } private void generateDigest(Extensions eidasExtensions) throws EIDASSAMLEngineException { - if (!(StringUtils.isEmpty(this.params.getDigestMethods()))) { - Set signatureMethods = EIDASUtil.parseSemicolonSeparatedList(this.params.getDigestMethods()); + if (!(StringUtils.isEmpty(this.params.getSigningMethods()))) { + Set signatureMethods = EIDASUtil.parseSemicolonSeparatedList(this.params.getSigningMethods()); Set digestMethods = new HashSet(); for (String signatureMethod : signatureMethods) { digestMethods.add(CertificateUtil.validateDigestAlgorithm(signatureMethod)); - } + } for (String digestMethod : digestMethods) { DigestMethod dm = (DigestMethod) BuilderFactoryUtil.buildXmlObject(DigestMethod.DEF_ELEMENT_NAME); if (dm != null) { @@ -203,7 +203,7 @@ public class NewMoaEidasMetadata { generateDigest(eidasExtensions); if (!(StringUtils.isEmpty(this.params.getSigningMethods()))) { - Set signMethods = EIDASUtil.parseSemicolonSeparatedList(this.params.getDigestMethods()); + Set signMethods = EIDASUtil.parseSemicolonSeparatedList(this.params.getSigningMethods()); for (String signMethod : signMethods) { SigningMethod sm = (SigningMethod) BuilderFactoryUtil .buildXmlObject(SigningMethod.DEF_ELEMENT_NAME); -- cgit v1.2.3 From 98e5c09745c58ef1b04132a9c92c60143332540e Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Wed, 6 Sep 2017 14:32:27 +0200 Subject: switch to eIDAS SAML-engine 1.4.0-RC1 --- id/server/modules/moa-id-module-eIDAS/pom.xml | 10 +++++----- .../1.4.0-SNAPSHOT/eidas-commons-1.4.0-SNAPSHOT.jar | Bin 0 -> 252060 bytes .../eidas-configmodule-1.4.0-SNAPSHOT.jar | Bin 0 -> 64872 bytes .../1.4.0-SNAPSHOT/eidas-encryption-1.4.0-SNAPSHOT.jar | Bin 0 -> 21023 bytes .../eidas-light-commons-1.4.0-SNAPSHOT.jar | Bin 0 -> 102277 bytes .../eidas-saml-engine-1.4.0-SNAPSHOT.jar | Bin 0 -> 589078 bytes ...pecific-communication-definition-1.4.0-SNAPSHOT.jar | Bin 0 -> 5531 bytes .../1.4.0-SNAPSHOT/eidas-specific-1.4.0-SNAPSHOT.jar | Bin 0 -> 32876 bytes 8 files changed, 5 insertions(+), 5 deletions(-) create mode 100644 repository/eu/eidas/eidas-commons/1.4.0-SNAPSHOT/eidas-commons-1.4.0-SNAPSHOT.jar create mode 100644 repository/eu/eidas/eidas-configmodule/1.4.0-SNAPSHOT/eidas-configmodule-1.4.0-SNAPSHOT.jar create mode 100644 repository/eu/eidas/eidas-encryption/1.4.0-SNAPSHOT/eidas-encryption-1.4.0-SNAPSHOT.jar create mode 100644 repository/eu/eidas/eidas-light-commons/1.4.0-SNAPSHOT/eidas-light-commons-1.4.0-SNAPSHOT.jar create mode 100644 repository/eu/eidas/eidas-saml-engine/1.4.0-SNAPSHOT/eidas-saml-engine-1.4.0-SNAPSHOT.jar create mode 100644 repository/eu/eidas/eidas-specific-communication-definition/1.4.0-SNAPSHOT/eidas-specific-communication-definition-1.4.0-SNAPSHOT.jar create mode 100644 repository/eu/eidas/eidas-specific/1.4.0-SNAPSHOT/eidas-specific-1.4.0-SNAPSHOT.jar (limited to 'id/server/modules') diff --git a/id/server/modules/moa-id-module-eIDAS/pom.xml b/id/server/modules/moa-id-module-eIDAS/pom.xml index 5bdead8b2..f3d8eeb36 100644 --- a/id/server/modules/moa-id-module-eIDAS/pom.xml +++ b/id/server/modules/moa-id-module-eIDAS/pom.xml @@ -12,11 +12,11 @@ ${basedir}/../../../../repository - 1.3.0 - 1.3.0 - 1.3.0 - 1.3.0 - 1.3.0 + 1.4.0-SNAPSHOT + 1.4.0-SNAPSHOT + 1.4.0-SNAPSHOT + 1.4.0-SNAPSHOT + 1.4.0-SNAPSHOT diff --git a/repository/eu/eidas/eidas-commons/1.4.0-SNAPSHOT/eidas-commons-1.4.0-SNAPSHOT.jar b/repository/eu/eidas/eidas-commons/1.4.0-SNAPSHOT/eidas-commons-1.4.0-SNAPSHOT.jar new file mode 100644 index 000000000..0da2486b6 Binary files /dev/null and b/repository/eu/eidas/eidas-commons/1.4.0-SNAPSHOT/eidas-commons-1.4.0-SNAPSHOT.jar differ diff --git a/repository/eu/eidas/eidas-configmodule/1.4.0-SNAPSHOT/eidas-configmodule-1.4.0-SNAPSHOT.jar b/repository/eu/eidas/eidas-configmodule/1.4.0-SNAPSHOT/eidas-configmodule-1.4.0-SNAPSHOT.jar new file mode 100644 index 000000000..a0e3f3daf Binary files /dev/null and b/repository/eu/eidas/eidas-configmodule/1.4.0-SNAPSHOT/eidas-configmodule-1.4.0-SNAPSHOT.jar differ diff --git a/repository/eu/eidas/eidas-encryption/1.4.0-SNAPSHOT/eidas-encryption-1.4.0-SNAPSHOT.jar b/repository/eu/eidas/eidas-encryption/1.4.0-SNAPSHOT/eidas-encryption-1.4.0-SNAPSHOT.jar new file mode 100644 index 000000000..a6ec48dda Binary files /dev/null and b/repository/eu/eidas/eidas-encryption/1.4.0-SNAPSHOT/eidas-encryption-1.4.0-SNAPSHOT.jar differ diff --git a/repository/eu/eidas/eidas-light-commons/1.4.0-SNAPSHOT/eidas-light-commons-1.4.0-SNAPSHOT.jar b/repository/eu/eidas/eidas-light-commons/1.4.0-SNAPSHOT/eidas-light-commons-1.4.0-SNAPSHOT.jar new file mode 100644 index 000000000..af63d8bd7 Binary files /dev/null and b/repository/eu/eidas/eidas-light-commons/1.4.0-SNAPSHOT/eidas-light-commons-1.4.0-SNAPSHOT.jar differ diff --git a/repository/eu/eidas/eidas-saml-engine/1.4.0-SNAPSHOT/eidas-saml-engine-1.4.0-SNAPSHOT.jar b/repository/eu/eidas/eidas-saml-engine/1.4.0-SNAPSHOT/eidas-saml-engine-1.4.0-SNAPSHOT.jar new file mode 100644 index 000000000..d72a32406 Binary files /dev/null and b/repository/eu/eidas/eidas-saml-engine/1.4.0-SNAPSHOT/eidas-saml-engine-1.4.0-SNAPSHOT.jar differ diff --git a/repository/eu/eidas/eidas-specific-communication-definition/1.4.0-SNAPSHOT/eidas-specific-communication-definition-1.4.0-SNAPSHOT.jar b/repository/eu/eidas/eidas-specific-communication-definition/1.4.0-SNAPSHOT/eidas-specific-communication-definition-1.4.0-SNAPSHOT.jar new file mode 100644 index 000000000..c2029c366 Binary files /dev/null and b/repository/eu/eidas/eidas-specific-communication-definition/1.4.0-SNAPSHOT/eidas-specific-communication-definition-1.4.0-SNAPSHOT.jar differ diff --git a/repository/eu/eidas/eidas-specific/1.4.0-SNAPSHOT/eidas-specific-1.4.0-SNAPSHOT.jar b/repository/eu/eidas/eidas-specific/1.4.0-SNAPSHOT/eidas-specific-1.4.0-SNAPSHOT.jar new file mode 100644 index 000000000..e14f033bd Binary files /dev/null and b/repository/eu/eidas/eidas-specific/1.4.0-SNAPSHOT/eidas-specific-1.4.0-SNAPSHOT.jar differ -- cgit v1.2.3