diff options
Diffstat (limited to 'eaaf_modules')
298 files changed, 23592 insertions, 13150 deletions
diff --git a/eaaf_modules/eaaf_module_auth_sl20/pom.xml b/eaaf_modules/eaaf_module_auth_sl20/pom.xml index d3c141d3..81611aff 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/pom.xml +++ b/eaaf_modules/eaaf_module_auth_sl20/pom.xml @@ -1,14 +1,17 @@ -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>at.gv.egiz.eaaf</groupId> <artifactId>eaaf_modules</artifactId> - <version>1.0.13.2</version> + <version>1.1.0</version> </parent> <artifactId>eaaf_module_auth_sl20</artifactId> <name>Generic SL2.0 authentication</name> - - <licenses> + + <licenses> <license> <name>European Union Public License, version 1.2 (EUPL-1.2)</name> <url>https://opensource.org/licenses/EUPL-1.2</url> @@ -24,37 +27,37 @@ <organizationUrl>https://www.egiz.gv.at</organizationUrl> </developer> </developers> - + <dependencies> - <dependency> - <groupId>at.gv.egiz.eaaf</groupId> - <artifactId>eaaf-core</artifactId> - <version>${egiz.eaaf.version}</version> - </dependency> - <dependency> - <groupId>org.bitbucket.b_c</groupId> - <artifactId>jose4j</artifactId> - </dependency> - <dependency> - <groupId>com.fasterxml.jackson.core</groupId> - <artifactId>jackson-databind</artifactId> - </dependency> - - <dependency> - <groupId>javax.servlet</groupId> - <artifactId>javax.servlet-api</artifactId> - <scope>provided</scope> - </dependency> + <dependency> + <groupId>at.gv.egiz.eaaf</groupId> + <artifactId>eaaf-core</artifactId> + <version>${egiz.eaaf.version}</version> + </dependency> + <dependency> + <groupId>org.bitbucket.b_c</groupId> + <artifactId>jose4j</artifactId> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-databind</artifactId> + </dependency> + + <dependency> + <groupId>javax.servlet</groupId> + <artifactId>javax.servlet-api</artifactId> + <scope>provided</scope> + </dependency> </dependencies> - + <build> - <resources> - <resource> - <directory>src/main/resources</directory> - </resource> - </resources> - - <plugins> + <resources> + <resource> + <directory>src/main/resources</directory> + </resource> + </resources> + + <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> @@ -70,13 +73,13 @@ <artifactId>maven-jar-plugin</artifactId> <version>3.1.1</version> <configuration> - <archive> - <manifest> - <addClasspath>true</addClasspath> - <addDefaultImplementationEntries>true</addDefaultImplementationEntries> - <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries> - </manifest> - </archive> + <archive> + <manifest> + <addClasspath>true</addClasspath> + <addDefaultImplementationEntries>true</addDefaultImplementationEntries> + <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries> + </manifest> + </archive> </configuration> </plugin> @@ -92,23 +95,23 @@ </filesets> </configuration> </plugin> - + <!-- enable co-existence of testng and junit --> - <plugin> - <artifactId>maven-surefire-plugin</artifactId> - <version>${surefire.version}</version> - <configuration> - <threadCount>1</threadCount> - </configuration> - <dependencies> - <dependency> - <groupId>org.apache.maven.surefire</groupId> - <artifactId>surefire-junit47</artifactId> - <version>${surefire.version}</version> - </dependency> - </dependencies> - </plugin> - </plugins> + <plugin> + <artifactId>maven-surefire-plugin</artifactId> + <version>${surefire.version}</version> + <configuration> + <threadCount>1</threadCount> + </configuration> + <dependencies> + <dependency> + <groupId>org.apache.maven.surefire</groupId> + <artifactId>surefire-junit47</artifactId> + <version>${surefire.version}</version> + </dependency> + </dependencies> + </plugin> + </plugins> </build> - + </project>
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/AbstractSL20AuthenticationModulImpl.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/AbstractSL20AuthenticationModulImpl.java index 7e306f25..e9932ae8 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/AbstractSL20AuthenticationModulImpl.java +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/AbstractSL20AuthenticationModulImpl.java @@ -12,119 +12,130 @@ import org.springframework.beans.factory.annotation.Autowired; import at.gv.egiz.eaaf.core.api.IRequest; import at.gv.egiz.eaaf.core.api.idp.IConfiguration; -import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration; +import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration; import at.gv.egiz.eaaf.core.api.idp.auth.modules.AuthModule; import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext; import at.gv.egiz.eaaf.core.impl.idp.auth.AbstractAuthenticationManager; import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20Constants; - /** + * AuthModule to select a Securtiy-Layer 2.0 based authentication process. + * * @author tlenz * */ -public abstract class AbstractSL20AuthenticationModulImpl implements AuthModule { - private static final Logger log = LoggerFactory.getLogger(AbstractSL20AuthenticationModulImpl.class); - - private int priority = 3; - public static final List<String> VDA_TYPE_IDS = Arrays.asList("1", "2", "3", "4"); - - @Autowired(required=true) protected IConfiguration authConfig; - @Autowired(required=true) private AbstractAuthenticationManager authManager; - - @Override - public int getPriority() { - return priority; - } - - /** - * Sets the priority of this module. Default value is {@code 0}. - * @param priority The priority. - */ - public void setPriority(int priority) { - this.priority = priority; - } - - @PostConstruct - protected void initalSL20Authentication() { - //parameter to whiteList - authManager.addHeaderNameToWhiteList(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE); - authManager.addHeaderNameToWhiteList(SL20Constants.HTTP_HEADER_SL20_VDA_TYPE); - - } - - - /* (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, IRequest pendingReq) { - final ISPConfiguration spConfig = pendingReq.getServiceProviderConfiguration(); - - if (spConfig == null) { - log.error("Suspect state. NO SP CONFIGURATION IN CONTEXT!"); - throw new RuntimeException("Suspect state. NO SP CONFIGURATION IN CONTEXT!"); - - } - - final String sl20ClientTypeHeader = (String) context.get(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE.toLowerCase()); - final String sl20VDATypeHeader = (String) context.get(SL20Constants.HTTP_HEADER_SL20_VDA_TYPE.toLowerCase()); - - if (authConfig.getBasicConfigurationBoolean(getGeneralConfigPropertyNameEnableModule(), getGeneralConfigPropertyNameEnableModuleDefault())) { - if (spConfig != null && - StringUtils.isNotEmpty(spConfig.getConfigurationValue(getSPConfigPropertyNameEnableModule())) && - Boolean.valueOf(spConfig.getConfigurationValue(getSPConfigPropertyNameEnableModule()))) { - log.debug("SL2.0 is enabled for " + spConfig.getUniqueIdentifier()); - log.trace(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE + ": " + sl20ClientTypeHeader); - log.trace(SL20Constants.HTTP_HEADER_SL20_VDA_TYPE + ": " + sl20VDATypeHeader); - return getProcessName(); - - } else { - log.trace("SL2.0 is NOT enabled for " + spConfig.getUniqueIdentifier()); - return null; - - } - - } else { - log.trace("SL2.0 is NOT enabled with property: {}", getGeneralConfigPropertyNameEnableModule()); - return null; - - } - - } - - /** - * Get the general configuration-key that holds the enabled key for this authentication module - * - * @return - */ - public abstract String getGeneralConfigPropertyNameEnableModule(); - - /** - * Get the default value of the general configuration-key that holds the enabled key for this authentication module - * - * @return - */ - public abstract boolean getGeneralConfigPropertyNameEnableModuleDefault(); - - /** - * Get the SP specific configuration-key that holds the enabled key for this authentication module - * - * @return configuration key for SP configuration - */ - public abstract String getSPConfigPropertyNameEnableModule(); - - /** - * Get the name of this specific SL2.0 process - * - * @return - */ - public abstract String getProcessName(); - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.modules.AuthModule#getProcessDefinitions() - */ - @Override - public abstract String[] getProcessDefinitions(); +public abstract class AbstractSL20AuthenticationModulImpl implements AuthModule { + private static final Logger log = LoggerFactory.getLogger(AbstractSL20AuthenticationModulImpl.class); + + private int priority = 3; + public static final List<String> VDA_TYPE_IDS = Arrays.asList("1", "2", "3", "4"); + + @Autowired(required = true) + protected IConfiguration authConfig; + @Autowired(required = true) + private AbstractAuthenticationManager authManager; + + @Override + public int getPriority() { + return priority; + } + + /** + * Sets the priority of this module. Default value is {@code 0}. + * + * @param priority The priority. + */ + public void setPriority(final int priority) { + this.priority = priority; + } + + @PostConstruct + protected void initalSL20Authentication() { + // parameter to whiteList + authManager.addHeaderNameToWhiteList(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE); + authManager.addHeaderNameToWhiteList(SL20Constants.HTTP_HEADER_SL20_VDA_TYPE); + + } + + /* + * (non-Javadoc) + * + * @see at.gv.egovernment.moa.id.auth.modules.AuthModule#selectProcess(at.gv. + * egovernment.moa.id.process .api.ExecutionContext) + */ + @Override + public String selectProcess(final ExecutionContext context, final IRequest pendingReq) { + final ISpConfiguration spConfig = pendingReq.getServiceProviderConfiguration(); + + if (spConfig == null) { + log.error("Suspect state. NO SP CONFIGURATION IN CONTEXT!"); + throw new RuntimeException("Suspect state. NO SP CONFIGURATION IN CONTEXT!"); + + } + + final String sl20ClientTypeHeader = (String) context.get(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE.toLowerCase()); + final String sl20VdaTypeHeader = (String) context.get(SL20Constants.HTTP_HEADER_SL20_VDA_TYPE.toLowerCase()); + + if (authConfig.getBasicConfigurationBoolean(getGeneralConfigPropertyNameEnableModule(), + getGeneralConfigPropertyNameEnableModuleDefault())) { + if (StringUtils.isNotEmpty(spConfig.getConfigurationValue(getSpConfigPropertyNameEnableModule())) + && Boolean.valueOf(spConfig.getConfigurationValue(getSpConfigPropertyNameEnableModule()))) { + log.debug("SL2.0 is enabled for " + spConfig.getUniqueIdentifier()); + log.trace(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE + ": " + sl20ClientTypeHeader); + log.trace(SL20Constants.HTTP_HEADER_SL20_VDA_TYPE + ": " + sl20VdaTypeHeader); + return getProcessName(); + + } else { + log.trace("SL2.0 is NOT enabled for " + spConfig.getUniqueIdentifier()); + return null; + + } + + } else { + log.trace("SL2.0 is NOT enabled with property: {}", getGeneralConfigPropertyNameEnableModule()); + return null; + + } + + } + + /** + * Get the general configuration-key that holds the enabled key for this + * authentication module. + * + * @return + */ + public abstract String getGeneralConfigPropertyNameEnableModule(); + + /** + * Get the default value of the general configuration-key that holds the enabled + * key for this authentication module. + * + * @return + */ + public abstract boolean getGeneralConfigPropertyNameEnableModuleDefault(); + + /** + * Get the SP specific configuration-key that holds the enabled key for this + * authentication module. + * + * @return configuration key for SP configuration + */ + public abstract String getSpConfigPropertyNameEnableModule(); + + /** + * Get the name of this specific SL2.0 process. + * + * @return + */ + public abstract String getProcessName(); + + /* + * (non-Javadoc) + * + * @see at.gv.egovernment.moa.id.auth.modules.AuthModule#getProcessDefinitions() + */ + @Override + public abstract String[] getProcessDefinitions(); } diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/Constants.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/Constants.java index a1490d2b..11fd41fb 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/Constants.java +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/Constants.java @@ -1,58 +1,87 @@ package at.gv.egiz.eaaf.modules.auth.sl20; public class Constants { - - public static final String CONFIG_PROP_PREFIX = "modules.sl20"; - public static final String CONFIG_PROP_VDA_ENDPOINT_QUALeID = CONFIG_PROP_PREFIX + ".vda.urls.qualeID."; - - public static final String CONFIG_PROP_VDA_AUTHBLOCK_TRANSFORMATION_ID = CONFIG_PROP_PREFIX + ".vda.authblock.transformation.id"; - public static final String CONFIG_PROP_SECURITY_KEYSTORE_PATH = CONFIG_PROP_PREFIX + ".security.keystore.path"; - public static final String CONFIG_PROP_SECURITY_KEYSTORE_PASSWORD = CONFIG_PROP_PREFIX + ".security.keystore.password"; - public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_SIGN_ALIAS = CONFIG_PROP_PREFIX + ".security.sign.alias"; - public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_SIGN_PASSWORD = CONFIG_PROP_PREFIX + ".security.sign.password"; - public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_ENCRYPTION_ALIAS = CONFIG_PROP_PREFIX + ".security.encryption.alias";; - public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_ENCRYPTION_PASSWORD = CONFIG_PROP_PREFIX + ".security.encryption.password"; - - public static final String CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT_ELEMENT = "default"; - public static final String CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT = CONFIG_PROP_VDA_ENDPOINT_QUALeID + CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT_ELEMENT; - public static final String CONFIG_PROP_VDA_ENDPOINT_QUALeID_LIST = CONFIG_PROP_VDA_ENDPOINT_QUALeID + "list"; - public static final String CONFIG_PROP_SP_LIST = CONFIG_PROP_PREFIX + ".sp.entityIds."; - - public static final String CONFIG_PROP_DISABLE_EID_VALIDATION = CONFIG_PROP_PREFIX + ".security.eID.validation.disable"; - public static final String CONFIG_PROP_ENABLE_EID_ENCRYPTION = CONFIG_PROP_PREFIX + ".security.eID.encryption.enabled"; - public static final String CONFIG_PROP_FORCE_EID_ENCRYPTION = CONFIG_PROP_PREFIX + ".security.eID.encryption.required"; - public static final String CONFIG_PROP_FORCE_EID_SIGNED_RESULT = CONFIG_PROP_PREFIX + ".security.eID.signed.result.required"; - - public static final String CONFIG_PROP_IPC_RETURN_URL = CONFIG_PROP_PREFIX + ".testing.ipc.return.url"; - public static final String CONFIG_PROP_HTTP_REDIRECT_CODE = CONFIG_PROP_PREFIX + ".testing.redirect.http.code"; - public static final String CONFIG_PROP_HTTP_REDIRECT_CODE_DEFAULT_VALUE = "303"; - - public static final String CONFIG_PROP_SP_ENABLE_SL20_AUTHENTICATION = "auth.sl20.enabled"; - public static final String CONFIG_PROP_SP_SL20_ENDPOINT_LIST = "auth.sl20.endpoints"; - - public static final String PENDING_REQ_STORAGE_PREFIX = "SL20_AUTH_"; - - /** - * Only dummy data for development!!!!!! - */ - public static final String DUMMY_SIGNING_CERT = - "MIIC9zCCAd8CBFretWcwDQYJKoZIhvcNAQEOBQAwQDELMAkGA1UEBhMCQVQxDTAL\n" + - "BgNVBAoMBEVHSVoxIjAgBgNVBAMMGW93biBkdW1teSBtZXRhZGF0YSBzaWduZXIw\n" + - "HhcNMTgwNDI0MDQ0MTExWhcNMjEwMTE3MDQ0MTExWjBAMQswCQYDVQQGEwJBVDEN\n" + - "MAsGA1UECgwERUdJWjEiMCAGA1UEAwwZb3duIGR1bW15IG1ldGFkYXRhIHNpZ25l\n" + - "cjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJvN3l1pjzlnmoW5trHH\n" + - "Rb1s60QtGNp2v1nfMg1R6h7SzygtmO869v5bqrVBBVGmujslr7W8cZ2DLmJoQx1N\n" + - "WwhccjXTHpNPw0B70qHGch2uRNkqkizSOlwth0Ll2DJtzxTolbajYdg+xppXScUq\n" + - "WNlNZndauPSnB2CESgNkaUou4x4YVSDInugAtLvdLx8rf2YcuidI6UIXxeSZr3VO\n" + - "Z12YtddzcJ+lwh7OX8B0UvLsdYjKjefjEudyuNBmVwLv4K2LsFhSqgE1CAzk3oCb\n" + - "V2A84klaWVPiXoBiOucyouvX781WVp1aCBp0QA8gpJH7/2wRsdPQ90tjMzM7dcgY\n" + - "LDkCAwEAATANBgkqhkiG9w0BAQ4FAAOCAQEAQuYRQcCNLDYU1ItliYz9f28+KDyU\n" + - "8WjF3NDZrlJbGSKQ4n7wkBfxdK3zprmpHadWDB+aZaPt/+voE2FduzPiLUDlpazN\n" + - "60JJ5/YHZ3q9MZvdoNg6rjkpioWatoj/smUkT6oUWL/gp8tH12fOd2oJygBqXMve\n" + - "3y3qVCghnjRaMYuXcScTZcjH9yebkTLygirtw34oGVb7t+HwbtcN65fUIBly6Rcl\n" + - "8NV3pwOKhXFKDAqXUpvhebL4+tWOqPdqfIfGaE6rELfTf3icGY3CQCzDz5Gp0Ptc\n" + - "TfQqm64xnhtAruXNJXWg2ptg+GuQgWnJUgQ8wLNMxw9XdeEwlQo5dL6xmg=="; - - public static final String DUMMY_SIGNING_CERT_FINGERPRINT = "IwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJvN3l1pjzlnmoW"; + + public static final String CONFIG_PROP_PREFIX = "modules.sl20"; + public static final String CONFIG_PROP_VDA_ENDPOINT_QUALeID = CONFIG_PROP_PREFIX + ".vda.urls.qualeID."; + + public static final String CONFIG_PROP_VDA_AUTHBLOCK_TRANSFORMATION_ID = CONFIG_PROP_PREFIX + + ".vda.authblock.transformation.id"; + + //KeyStore configuration + public static final String CONFIG_PROP_SECURITY_KEYSTORE_TYPE = + CONFIG_PROP_PREFIX + ".security.keystore.type"; + public static final String CONFIG_PROP_SECURITY_KEYSTORE_NAME = + CONFIG_PROP_PREFIX + ".security.keystore.name"; + public static final String CONFIG_PROP_SECURITY_KEYSTORE_PATH = + CONFIG_PROP_PREFIX + ".security.keystore.path"; + public static final String CONFIG_PROP_SECURITY_KEYSTORE_PASSWORD = + CONFIG_PROP_PREFIX + ".security.keystore.password"; + + public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_SIGN_ALIAS = + CONFIG_PROP_PREFIX + ".security.sign.alias"; + public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_SIGN_PASSWORD = + CONFIG_PROP_PREFIX + ".security.sign.password"; + public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_ENCRYPTION_ALIAS = + CONFIG_PROP_PREFIX + ".security.encryption.alias"; + public static final String CONFIG_PROP_SECURITY_KEYSTORE_KEY_ENCRYPTION_PASSWORD = + CONFIG_PROP_PREFIX + ".security.encryption.password"; + + //TrustStore configuration + public static final String CONFIG_PROP_SECURITY_TRUSTSTORE_TYPE = + CONFIG_PROP_PREFIX + ".security.truststore.type"; + public static final String CONFIG_PROP_SECURITY_TRUSTSTORE_NAME = + CONFIG_PROP_PREFIX + ".security.truststore.name"; + public static final String CONFIG_PROP_SECURITY_TRUSTSTORE_PATH = + CONFIG_PROP_PREFIX + ".security.truststore.path"; + public static final String CONFIG_PROP_SECURITY_TRUSTSTORE_PASSWORD = + CONFIG_PROP_PREFIX + ".security.truststore.password"; + + + public static final String CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT_ELEMENT = "default"; + public static final String CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT = CONFIG_PROP_VDA_ENDPOINT_QUALeID + + CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT_ELEMENT; + public static final String CONFIG_PROP_VDA_ENDPOINT_QUALeID_LIST = CONFIG_PROP_VDA_ENDPOINT_QUALeID + "list"; + public static final String CONFIG_PROP_SP_LIST = CONFIG_PROP_PREFIX + ".sp.entityIds."; + + public static final String CONFIG_PROP_DISABLE_EID_VALIDATION = CONFIG_PROP_PREFIX + + ".security.eID.validation.disable"; + public static final String CONFIG_PROP_ENABLE_EID_ENCRYPTION = CONFIG_PROP_PREFIX + + ".security.eID.encryption.enabled"; + public static final String CONFIG_PROP_FORCE_EID_ENCRYPTION = CONFIG_PROP_PREFIX + + ".security.eID.encryption.required"; + public static final String CONFIG_PROP_FORCE_EID_SIGNED_RESULT = CONFIG_PROP_PREFIX + + ".security.eID.signed.result.required"; + + public static final String CONFIG_PROP_IPC_RETURN_URL = CONFIG_PROP_PREFIX + ".testing.ipc.return.url"; + public static final String CONFIG_PROP_HTTP_REDIRECT_CODE = CONFIG_PROP_PREFIX + ".testing.redirect.http.code"; + public static final String CONFIG_PROP_HTTP_REDIRECT_CODE_DEFAULT_VALUE = "303"; + + public static final String CONFIG_PROP_SP_ENABLE_SL20_AUTHENTICATION = "auth.sl20.enabled"; + public static final String CONFIG_PROP_SP_SL20_ENDPOINT_LIST = "auth.sl20.endpoints"; + + public static final String PENDING_REQ_STORAGE_PREFIX = "SL20_AUTH_"; + + /** + * Only dummy data for development!!!!!!. + */ + public static final String DUMMY_SIGNING_CERT = "MIIC9zCCAd8CBFretWcwDQYJKoZIhvcNAQEOBQAwQDELMAkGA1UEBhMCQVQxDTAL\n" + + "BgNVBAoMBEVHSVoxIjAgBgNVBAMMGW93biBkdW1teSBtZXRhZGF0YSBzaWduZXIw\n" + + "HhcNMTgwNDI0MDQ0MTExWhcNMjEwMTE3MDQ0MTExWjBAMQswCQYDVQQGEwJBVDEN\n" + + "MAsGA1UECgwERUdJWjEiMCAGA1UEAwwZb3duIGR1bW15IG1ldGFkYXRhIHNpZ25l\n" + + "cjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJvN3l1pjzlnmoW5trHH\n" + + "Rb1s60QtGNp2v1nfMg1R6h7SzygtmO869v5bqrVBBVGmujslr7W8cZ2DLmJoQx1N\n" + + "WwhccjXTHpNPw0B70qHGch2uRNkqkizSOlwth0Ll2DJtzxTolbajYdg+xppXScUq\n" + + "WNlNZndauPSnB2CESgNkaUou4x4YVSDInugAtLvdLx8rf2YcuidI6UIXxeSZr3VO\n" + + "Z12YtddzcJ+lwh7OX8B0UvLsdYjKjefjEudyuNBmVwLv4K2LsFhSqgE1CAzk3oCb\n" + + "V2A84klaWVPiXoBiOucyouvX781WVp1aCBp0QA8gpJH7/2wRsdPQ90tjMzM7dcgY\n" + + "LDkCAwEAATANBgkqhkiG9w0BAQ4FAAOCAQEAQuYRQcCNLDYU1ItliYz9f28+KDyU\n" + + "8WjF3NDZrlJbGSKQ4n7wkBfxdK3zprmpHadWDB+aZaPt/+voE2FduzPiLUDlpazN\n" + + "60JJ5/YHZ3q9MZvdoNg6rjkpioWatoj/smUkT6oUWL/gp8tH12fOd2oJygBqXMve\n" + + "3y3qVCghnjRaMYuXcScTZcjH9yebkTLygirtw34oGVb7t+HwbtcN65fUIBly6Rcl\n" + + "8NV3pwOKhXFKDAqXUpvhebL4+tWOqPdqfIfGaE6rELfTf3icGY3CQCzDz5Gp0Ptc\n" + + "TfQqm64xnhtAruXNJXWg2ptg+GuQgWnJUgQ8wLNMxw9XdeEwlQo5dL6xmg=="; + + public static final String DUMMY_SIGNING_CERT_FINGERPRINT = "IwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJvN3l1pjzlnmoW"; } diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/EventCodes.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/EventCodes.java index e19ef5fc..af155206 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/EventCodes.java +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/EventCodes.java @@ -1,16 +1,16 @@ package at.gv.egiz.eaaf.modules.auth.sl20; /** - * Set of event codes uses in Auth-Handler implementation - * + * Set of event codes uses in Auth-Handler implementation. + * * @author tlenz * */ public class EventCodes { - public static final int AUTHPROCESS_SL20_SELECTED = 4111; - public static final int AUTHPROCESS_SL20_ENDPOINT_URL = 4112; - public static final int AUTHPROCESS_SL20_DATAURL_IP = 4113; - - public static final int AUTHPROCESS_SL20_CONSENT_VALID = 4113; + public static final int AUTHPROCESS_SL20_SELECTED = 4111; + public static final int AUTHPROCESS_SL20_ENDPOINT_URL = 4112; + public static final int AUTHPROCESS_SL20_DATAURL_IP = 4113; + + public static final int AUTHPROCESS_SL20_CONSENT_VALID = 4113; } diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/data/VerificationResult.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/data/VerificationResult.java index 0c625a9b..bb0c41d7 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/data/VerificationResult.java +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/data/VerificationResult.java @@ -7,33 +7,39 @@ import com.fasterxml.jackson.databind.JsonNode; public class VerificationResult { - private Boolean validSigned = null; - private List<X509Certificate> certs = null; - private JsonNode payload = null; - - public VerificationResult(JsonNode payload) { - this.payload = payload; - - } - - public VerificationResult(JsonNode string, List<X509Certificate> certs, boolean wasValidSigned) { - this.payload = string; - this.certs = certs; - this.validSigned = wasValidSigned; - - } - - public Boolean isValidSigned() { - return validSigned; - } - public List<X509Certificate> getCertChain() { - return certs; - } - public JsonNode getPayload() { - return payload; - } - - - - + private Boolean validSigned = null; + private List<X509Certificate> certs = null; + private JsonNode payload = null; + + public VerificationResult(final JsonNode payload) { + this.payload = payload; + + } + + /** + * JWS signature verification-result container. + * + * @param payload JWS payload + * @param certs JWS signercertificate + * @param wasValidSigned true if signature was valid + */ + public VerificationResult(final JsonNode payload, final List<X509Certificate> certs, final boolean wasValidSigned) { + this.payload = payload; + this.certs = certs; + this.validSigned = wasValidSigned; + + } + + public Boolean isValidSigned() { + return validSigned; + } + + public List<X509Certificate> getCertChain() { + return certs; + } + + public JsonNode getPayload() { + return payload; + } + } diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20EidDataValidationException.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20EidDataValidationException.java new file mode 100644 index 00000000..a14fbe9e --- /dev/null +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20EidDataValidationException.java @@ -0,0 +1,16 @@ +package at.gv.egiz.eaaf.modules.auth.sl20.exceptions; + +public class SL20EidDataValidationException extends SL20Exception { + private static final long serialVersionUID = 1L; + + public SL20EidDataValidationException(final Object[] parameters) { + super("sl20.07", parameters); + + } + + public SL20EidDataValidationException(final Object[] parameters, final Throwable e) { + super("sl20.07", parameters, e); + + } + +} diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20Exception.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20Exception.java index b23b5ca3..12921ad6 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20Exception.java +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20Exception.java @@ -1,19 +1,19 @@ package at.gv.egiz.eaaf.modules.auth.sl20.exceptions; -import at.gv.egiz.eaaf.core.exceptions.EAAFAuthenticationException; +import at.gv.egiz.eaaf.core.exceptions.EaafAuthenticationException; -public class SL20Exception extends EAAFAuthenticationException { +public class SL20Exception extends EaafAuthenticationException { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - public SL20Exception(String messageId, Object[] parameters) { - super(messageId, parameters); + public SL20Exception(final String messageId, final Object[] parameters) { + super(messageId, parameters); - } - - public SL20Exception(String messageId, Object[] parameters, Throwable wrapped) { - super(messageId, parameters, wrapped); + } - } + public SL20Exception(final String messageId, final Object[] parameters, final Throwable wrapped) { + super(messageId, parameters, wrapped); + + } } diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20SecurityException.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20SecurityException.java index eaf55ba3..62abdeb8 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20SecurityException.java +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20SecurityException.java @@ -2,19 +2,19 @@ package at.gv.egiz.eaaf.modules.auth.sl20.exceptions; public class SL20SecurityException extends SL20Exception { - private static final long serialVersionUID = 3281385988027147449L; + private static final long serialVersionUID = 3281385988027147449L; - public SL20SecurityException(Object[] parameters) { - super("sl20.05", parameters); - } - - public SL20SecurityException(String parameter) { - super("sl20.05", new Object[] {parameter}); - } - - public SL20SecurityException(Object[] parameters, Throwable wrapped) { - super("sl20.05", parameters, wrapped); + public SL20SecurityException(final Object[] parameters) { + super("sl20.05", parameters); + } - } + public SL20SecurityException(final String parameter) { + super("sl20.05", new Object[] { parameter }); + } + + public SL20SecurityException(final Object[] parameters, final Throwable wrapped) { + super("sl20.05", parameters, wrapped); + + } } diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20eIDDataValidationException.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20eIDDataValidationException.java deleted file mode 100644 index 24df735a..00000000 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SL20eIDDataValidationException.java +++ /dev/null @@ -1,16 +0,0 @@ -package at.gv.egiz.eaaf.modules.auth.sl20.exceptions; - -public class SL20eIDDataValidationException extends SL20Exception { - private static final long serialVersionUID = 1L; - - public SL20eIDDataValidationException(Object[] parameters) { - super("sl20.07", parameters); - - } - - public SL20eIDDataValidationException(Object[] parameters, Throwable e) { - super("sl20.07", parameters, e); - - } - -} diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SLCommandoBuildException.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SLCommandoBuildException.java deleted file mode 100644 index 1f521ebc..00000000 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SLCommandoBuildException.java +++ /dev/null @@ -1,17 +0,0 @@ -package at.gv.egiz.eaaf.modules.auth.sl20.exceptions; - -public class SLCommandoBuildException extends SL20Exception { - - private static final long serialVersionUID = 1L; - - - public SLCommandoBuildException(String msg) { - super("sl20.01", new Object[]{msg}); - - } - - public SLCommandoBuildException(String msg, Throwable e) { - super("sl20.01", new Object[]{msg}, e); - - } -} diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SLCommandoParserException.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SLCommandoParserException.java deleted file mode 100644 index 60993e69..00000000 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SLCommandoParserException.java +++ /dev/null @@ -1,17 +0,0 @@ -package at.gv.egiz.eaaf.modules.auth.sl20.exceptions; - -public class SLCommandoParserException extends SL20Exception { - - private static final long serialVersionUID = 1L; - - - public SLCommandoParserException(String msg) { - super("sl20.02", new Object[]{msg}); - - } - - public SLCommandoParserException(String msg, Throwable e) { - super("sl20.02", new Object[]{msg}, e); - - } -} diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SlCommandoBuildException.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SlCommandoBuildException.java new file mode 100644 index 00000000..361f57b7 --- /dev/null +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SlCommandoBuildException.java @@ -0,0 +1,16 @@ +package at.gv.egiz.eaaf.modules.auth.sl20.exceptions; + +public class SlCommandoBuildException extends SL20Exception { + + private static final long serialVersionUID = 1L; + + public SlCommandoBuildException(final String msg) { + super("sl20.01", new Object[] { msg }); + + } + + public SlCommandoBuildException(final String msg, final Throwable e) { + super("sl20.01", new Object[] { msg }, e); + + } +} diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SlCommandoParserException.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SlCommandoParserException.java new file mode 100644 index 00000000..4993796a --- /dev/null +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/exceptions/SlCommandoParserException.java @@ -0,0 +1,16 @@ +package at.gv.egiz.eaaf.modules.auth.sl20.exceptions; + +public class SlCommandoParserException extends SL20Exception { + + private static final long serialVersionUID = 1L; + + public SlCommandoParserException(final String msg) { + super("sl20.02", new Object[] { msg }); + + } + + public SlCommandoParserException(final String msg, final Throwable e) { + super("sl20.02", new Object[] { msg }, e); + + } +} diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractCreateQualEidRequestTask.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractCreateQualEidRequestTask.java new file mode 100644 index 00000000..d1887d5c --- /dev/null +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractCreateQualEidRequestTask.java @@ -0,0 +1,241 @@ +package at.gv.egiz.eaaf.modules.auth.sl20.tasks; + +import java.security.cert.CertificateEncodingException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang3.StringUtils; +import org.apache.http.HttpResponse; +import org.apache.http.NameValuePair; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.message.BasicNameValuePair; +import org.jose4j.base64url.Base64Url; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + +import at.gv.egiz.eaaf.core.api.idp.IConfigurationWithSP; +import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration; +import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext; +import at.gv.egiz.eaaf.core.exceptions.EaafAuthenticationException; +import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException; +import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask; +import at.gv.egiz.eaaf.core.impl.utils.IHttpClientFactory; +import at.gv.egiz.eaaf.core.impl.utils.KeyValueUtils; +import at.gv.egiz.eaaf.core.impl.utils.Random; +import at.gv.egiz.eaaf.core.impl.utils.TransactionIdUtils; +import at.gv.egiz.eaaf.modules.auth.sl20.Constants; +import at.gv.egiz.eaaf.modules.auth.sl20.EventCodes; +import at.gv.egiz.eaaf.modules.auth.sl20.data.VerificationResult; +import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20Exception; +import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SlCommandoParserException; +import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20Constants; +import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20HttpBindingUtils; +import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20JsonBuilderUtils; +import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20JsonExtractorUtils; + +public abstract class AbstractCreateQualEidRequestTask extends AbstractAuthServletTask { + private static final Logger log = LoggerFactory.getLogger(AbstractCreateQualEidRequestTask.class); + + @Autowired(required = true) + private IHttpClientFactory httpClientFactory; + @Autowired(required = true) + protected IConfigurationWithSP authConfigWithSp; + + @Override + public void execute(final ExecutionContext executionContext, final HttpServletRequest request, + final HttpServletResponse response) throws TaskExecutionException { + + log.debug("Starting SL2.0 authentication process .... "); + + revisionsLogger.logEvent(pendingReq, EventCodes.AUTHPROCESS_SL20_SELECTED, "sl20auth"); + + try { + // get service-provider configuration + final ISpConfiguration oaConfig = pendingReq.getServiceProviderConfiguration(); + + if (oaConfig == null) { + log.warn("No SP configuration in pendingReq!"); + throw new RuntimeException("Suspect state. NO SP CONFIGURATION IN PendingRequest!"); + + } + + // get basic configuration parameters + final String vdaQualEidDUrl = extractVdaUrlForSpecificOa(oaConfig, executionContext); + if (StringUtils.isEmpty(vdaQualEidDUrl)) { + log.error("NO VDA URL for qualified eID (" + Constants.CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT + ")"); + throw new SL20Exception("sl20.03", new Object[] { "NO VDA URL for qualified eID" }); + + } + + log.debug("Use {} as VDA end-point", vdaQualEidDUrl); + pendingReq.setRawDataToTransaction( + Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_CCSURL, vdaQualEidDUrl); + revisionsLogger.logEvent(pendingReq, EventCodes.AUTHPROCESS_SL20_ENDPOINT_URL, vdaQualEidDUrl); + + // create SL2.0 command for qualified eID + final String signedQualEidCommand = buildSignedQualifiedEidCommand(); + + // build request container + final String qualEidReqId = Random.nextProcessReferenceValue(); + final ObjectNode sl20Req = SL20JsonBuilderUtils.createGenericRequest(qualEidReqId, null, null, + signedQualEidCommand); + + // build http POST request + final HttpPost httpReq = new HttpPost(new URIBuilder(vdaQualEidDUrl).build()); + final List<NameValuePair> parameters = new ArrayList<>(); + parameters.add(new BasicNameValuePair(SL20Constants.PARAM_SL20_REQ_COMMAND_PARAM, + Base64Url.encode(sl20Req.toString().getBytes("UTF-8")))); + httpReq.setEntity(new UrlEncodedFormEntity(parameters)); + + // build http GET request + // URIBuilder sl20ReqUri = new URIBuilder(vdaQualeIDUrl); + // sl20ReqUri.addParameter(SL20Constants.PARAM_SL20_REQ_COMMAND_PARAM, + // Base64Url.encode(sl20Req.toString().getBytes())); + // HttpGet httpReq = new HttpGet(sl20ReqUri.build()); + + // set native client header + httpReq.addHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE, SL20Constants.HTTP_HEADER_VALUE_NATIVE); + + log.trace("Request VDA via SL20 with: " + Base64Url.encode(sl20Req.toString().getBytes("UTF-8"))); + + // request VDA + final HttpResponse httpResp = httpClientFactory.getHttpClient(false).execute(httpReq); + + // parse response + log.info("Receive response from VDA ... "); + final JsonNode sl20Resp = SL20JsonExtractorUtils.getSL20ContainerFromResponse(httpResp); + final VerificationResult respPayloadContainer = SL20JsonExtractorUtils.extractSL20PayLoad(sl20Resp, null, false); + + if (respPayloadContainer.isValidSigned() == null) { + log.debug("Receive unsigned payLoad from VDA"); + + } + + final JsonNode respPayload = respPayloadContainer.getPayload(); + if (respPayload.get(SL20Constants.SL20_COMMAND_CONTAINER_NAME).asText() + .equals(SL20Constants.SL20_COMMAND_IDENTIFIER_REDIRECT)) { + log.debug("Find 'redirect' command in VDA response ... "); + final JsonNode params = SL20JsonExtractorUtils.getJsonObjectValue(respPayload, + SL20Constants.SL20_COMMAND_CONTAINER_PARAMS, true); + final String redirectUrl = SL20JsonExtractorUtils.getStringValue(params, + SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_URL, true); + final JsonNode command = SL20JsonExtractorUtils.getJsonObjectValue(params, + SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_COMMAND, false); + final String signedCommand = SL20JsonExtractorUtils.getStringValue(params, + SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_SIGNEDCOMMAND, false); + + // create forward SL2.0 command + final ObjectNode sl20Forward = sl20Resp.deepCopy(); + SL20JsonBuilderUtils.addOnlyOnceOfTwo(sl20Forward, SL20Constants.SL20_PAYLOAD, SL20Constants.SL20_SIGNEDPAYLOAD, + command.deepCopy(), signedCommand); + + // store pending request + pendingReq.setRawDataToTransaction(Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_REQID, + qualEidReqId); + requestStoreage.storePendingRequest(pendingReq); + + // forward SL2.0 command + // TODO: maybe add SL2ClientType Header from execution context + SL20HttpBindingUtils.writeIntoResponse(request, response, sl20Forward, redirectUrl, + Integer.parseInt(authConfig.getBasicConfiguration(Constants.CONFIG_PROP_HTTP_REDIRECT_CODE, + Constants.CONFIG_PROP_HTTP_REDIRECT_CODE_DEFAULT_VALUE))); + + } else if (respPayload.get(SL20Constants.SL20_COMMAND_CONTAINER_NAME).asText() + .equals(SL20Constants.SL20_COMMAND_IDENTIFIER_ERROR)) { + JsonNode result = SL20JsonExtractorUtils.getJsonObjectValue(respPayload, + SL20Constants.SL20_COMMAND_CONTAINER_RESULT, false); + if (result == null) { + result = SL20JsonExtractorUtils.getJsonObjectValue(respPayload, SL20Constants.SL20_COMMAND_CONTAINER_PARAMS, + false); + } + + final String errorCode = SL20JsonExtractorUtils.getStringValue(result, + SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORCODE, true); + final String errorMsg = SL20JsonExtractorUtils.getStringValue(result, + SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORMESSAGE, true); + + log.info("Receive SL2.0 error. Code:" + errorCode + " Msg:" + errorMsg); + throw new SL20Exception("sl20.08", new Object[] { errorCode, errorMsg }); + + } else { + // TODO: update to add error handling + log.warn( + "Received an unrecognized command: " + respPayload.get(SL20Constants.SL20_COMMAND_CONTAINER_NAME).asText()); + throw new SlCommandoParserException("Received an unrecognized command: " + + respPayload.get(SL20Constants.SL20_COMMAND_CONTAINER_NAME).toString()); + } + + } catch (final EaafAuthenticationException e) { + throw new TaskExecutionException(pendingReq, "SL2.0 Authentication FAILED. Msg: " + e.getMessage(), e); + + } catch (final Exception e) { + log.warn("SL2.0 Authentication FAILED with a generic error.", e); + throw new TaskExecutionException(pendingReq, e.getMessage(), e); + + } finally { + TransactionIdUtils.removeTransactionId(); + TransactionIdUtils.removeSessionId(); + + } + + } + + /** + * Create a implementation specific qualified eID SL2.0 command + * + * @param oaConfig + * + * @return signed JWT token as serialized {@link String} + * @throws CertificateEncodingException In case of certificate parsing error + * @throws SL20Exception In case of a SL2.0 error + */ + protected abstract String buildSignedQualifiedEidCommand() throws CertificateEncodingException, SL20Exception; + + private String extractVdaUrlForSpecificOa(final ISpConfiguration oaConfig, final ExecutionContext executionContext) { + + // load SP specific config for development and testing purposes + final String spSpecificVdaEndpoints = oaConfig.getConfigurationValue(Constants.CONFIG_PROP_SP_SL20_ENDPOINT_LIST); + + // load general configuration + final Map<String, String> endPointMap = authConfigWithSp + .getBasicConfigurationWithPrefix(Constants.CONFIG_PROP_VDA_ENDPOINT_QUALeID_LIST); + endPointMap.put(Constants.CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT_ELEMENT, + authConfig.getBasicConfiguration(Constants.CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT)); + if (StringUtils.isNotEmpty(spSpecificVdaEndpoints)) { + endPointMap.putAll(KeyValueUtils.convertListToMap( + KeyValueUtils.getListOfCsvValues(KeyValueUtils.normalizeCsvValueString(spSpecificVdaEndpoints)))); + log.debug("Find OA specific SL2.0 endpoints. Updating endPoint list ... "); + + } + + log.trace("Find #" + endPointMap.size() + " SL2.0 endpoints ... "); + + // selection based on request Header + final String sl20VdaTypeHeader = (String) executionContext + .get(SL20Constants.HTTP_HEADER_SL20_VDA_TYPE.toLowerCase()); + if (StringUtils.isNotEmpty(sl20VdaTypeHeader)) { + final String vdaUrl = endPointMap.get(sl20VdaTypeHeader); + if (StringUtils.isNotEmpty(vdaUrl)) { + return vdaUrl.trim(); + } else { + log.info("Can NOT find VDA with Id: " + sl20VdaTypeHeader + ". Use default VDA"); + } + + } + + log.info("NO specific VDA endpoint requested or found. Use default VDA"); + return endPointMap.get(Constants.CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT_ELEMENT); + + } + +} diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractCreateQualeIDRequestTask.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractCreateQualeIDRequestTask.java deleted file mode 100644 index 85302d83..00000000 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractCreateQualeIDRequestTask.java +++ /dev/null @@ -1,227 +0,0 @@ -package at.gv.egiz.eaaf.modules.auth.sl20.tasks; - -import java.security.cert.CertificateEncodingException; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.lang3.StringUtils; -import org.apache.http.HttpResponse; -import org.apache.http.NameValuePair; -import org.apache.http.client.entity.UrlEncodedFormEntity; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.client.utils.URIBuilder; -import org.apache.http.message.BasicNameValuePair; -import org.jose4j.base64url.Base64Url; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ObjectNode; - -import at.gv.egiz.eaaf.core.api.idp.IConfigurationWithSP; -import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration; -import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext; -import at.gv.egiz.eaaf.core.exceptions.EAAFAuthenticationException; -import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException; -import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask; -import at.gv.egiz.eaaf.core.impl.utils.IHttpClientFactory; -import at.gv.egiz.eaaf.core.impl.utils.KeyValueUtils; -import at.gv.egiz.eaaf.core.impl.utils.Random; -import at.gv.egiz.eaaf.core.impl.utils.TransactionIDUtils; -import at.gv.egiz.eaaf.modules.auth.sl20.Constants; -import at.gv.egiz.eaaf.modules.auth.sl20.EventCodes; -import at.gv.egiz.eaaf.modules.auth.sl20.data.VerificationResult; -import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20Exception; -import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SLCommandoBuildException; -import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SLCommandoParserException; -import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20Constants; -import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20HttpBindingUtils; -import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20JSONBuilderUtils; -import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20JSONExtractorUtils; - -public abstract class AbstractCreateQualeIDRequestTask extends AbstractAuthServletTask { - private static final Logger log = LoggerFactory.getLogger(AbstractCreateQualeIDRequestTask.class); - - @Autowired(required=true) private IHttpClientFactory httpClientFactory; - @Autowired(required=true) protected IConfigurationWithSP authConfigWithSp; - - @Override - public void execute(ExecutionContext executionContext, HttpServletRequest request, HttpServletResponse response) - throws TaskExecutionException { - - log.debug("Starting SL2.0 authentication process .... "); - - revisionsLogger.logEvent(pendingReq, EventCodes.AUTHPROCESS_SL20_SELECTED, "sl20auth"); - - try { - //get service-provider configuration - final ISPConfiguration oaConfig = pendingReq.getServiceProviderConfiguration(); - - if (oaConfig == null) { - log.warn("No SP configuration in pendingReq!"); - throw new RuntimeException("Suspect state. NO SP CONFIGURATION IN PendingRequest!"); - - } - - //get basic configuration parameters - final String vdaQualeIDUrl = extractVDAURLForSpecificOA(oaConfig, executionContext); - if (StringUtils.isEmpty(vdaQualeIDUrl)) { - log.error("NO VDA URL for qualified eID (" + Constants.CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT + ")"); - throw new SL20Exception("sl20.03", new Object[]{"NO VDA URL for qualified eID"}); - - } - - log.debug("Use {} as VDA end-point", vdaQualeIDUrl) ; - pendingReq.setRawDataToTransaction( - Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_CCSURL, - vdaQualeIDUrl); - revisionsLogger.logEvent(pendingReq, EventCodes.AUTHPROCESS_SL20_ENDPOINT_URL, vdaQualeIDUrl); - - //create SL2.0 command for qualified eID - final String signedQualeIDCommand = buildSignedQualifiedEIDCommand(); - - //build request container - final String qualeIDReqId = Random.nextProcessReferenceValue(); - final ObjectNode sl20Req = SL20JSONBuilderUtils.createGenericRequest(qualeIDReqId, null, null, signedQualeIDCommand); - - //build http POST request - final HttpPost httpReq = new HttpPost(new URIBuilder(vdaQualeIDUrl).build()); - final List<NameValuePair> parameters = new ArrayList<NameValuePair>();; - parameters.add(new BasicNameValuePair(SL20Constants.PARAM_SL20_REQ_COMMAND_PARAM, Base64Url.encode(sl20Req.toString().getBytes()))); - httpReq.setEntity(new UrlEncodedFormEntity(parameters )); - - //build http GET request -// URIBuilder sl20ReqUri = new URIBuilder(vdaQualeIDUrl); -// sl20ReqUri.addParameter(SL20Constants.PARAM_SL20_REQ_COMMAND_PARAM, Base64Url.encode(sl20Req.toString().getBytes())); -// HttpGet httpReq = new HttpGet(sl20ReqUri.build()); - - //set native client header - httpReq.addHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE, SL20Constants.HTTP_HEADER_VALUE_NATIVE); - - log.trace("Request VDA via SL20 with: " + Base64Url.encode(sl20Req.toString().getBytes())); - - //request VDA - final HttpResponse httpResp = httpClientFactory.getHttpClient(false).execute(httpReq); - - //parse response - log.info("Receive response from VDA ... "); - final JsonNode sl20Resp = SL20JSONExtractorUtils.getSL20ContainerFromResponse(httpResp); - final VerificationResult respPayloadContainer = SL20JSONExtractorUtils.extractSL20PayLoad(sl20Resp, null, false); - - if (respPayloadContainer.isValidSigned() == null) { - log.debug("Receive unsigned payLoad from VDA"); - - } - - final JsonNode respPayload = respPayloadContainer.getPayload(); - if (respPayload.get(SL20Constants.SL20_COMMAND_CONTAINER_NAME).asText() - .equals(SL20Constants.SL20_COMMAND_IDENTIFIER_REDIRECT)) { - log.debug("Find 'redirect' command in VDA response ... "); - final JsonNode params = SL20JSONExtractorUtils.getJSONObjectValue(respPayload, SL20Constants.SL20_COMMAND_CONTAINER_PARAMS, true); - final String redirectURL = SL20JSONExtractorUtils.getStringValue(params, SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_URL, true); - final JsonNode command = SL20JSONExtractorUtils.getJSONObjectValue(params, SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_COMMAND, false); - final String signedCommand = SL20JSONExtractorUtils.getStringValue(params, SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_SIGNEDCOMMAND, false); - - //create forward SL2.0 command - final ObjectNode sl20Forward = sl20Resp.deepCopy(); - SL20JSONBuilderUtils.addOnlyOnceOfTwo(sl20Forward, - SL20Constants.SL20_PAYLOAD, SL20Constants.SL20_SIGNEDPAYLOAD, - command.deepCopy(), signedCommand); - - //store pending request - pendingReq.setRawDataToTransaction(Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_REQID, - qualeIDReqId); - requestStoreage.storePendingRequest(pendingReq); - - //forward SL2.0 command - //TODO: maybe add SL2ClientType Header from execution context - SL20HttpBindingUtils.writeIntoResponse(request, response, sl20Forward, redirectURL, - Integer.parseInt(authConfig.getBasicConfiguration(Constants.CONFIG_PROP_HTTP_REDIRECT_CODE, Constants.CONFIG_PROP_HTTP_REDIRECT_CODE_DEFAULT_VALUE))); - - } else if (respPayload.get(SL20Constants.SL20_COMMAND_CONTAINER_NAME).asText() - .equals(SL20Constants.SL20_COMMAND_IDENTIFIER_ERROR)) { - JsonNode result = SL20JSONExtractorUtils.getJSONObjectValue(respPayload, SL20Constants.SL20_COMMAND_CONTAINER_RESULT, false); - if (result == null) - result = SL20JSONExtractorUtils.getJSONObjectValue(respPayload, SL20Constants.SL20_COMMAND_CONTAINER_PARAMS, false); - - final String errorCode = SL20JSONExtractorUtils.getStringValue(result, SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORCODE, true); - final String errorMsg = SL20JSONExtractorUtils.getStringValue(result, SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORMESSAGE, true); - - log.info("Receive SL2.0 error. Code:" + errorCode + " Msg:" + errorMsg); - throw new SL20Exception("sl20.08", new Object[]{errorCode, errorMsg}); - - } else { - //TODO: update to add error handling - log.warn("Received an unrecognized command: " + respPayload.get(SL20Constants.SL20_COMMAND_CONTAINER_NAME).asText()); - throw new SLCommandoParserException("Received an unrecognized command: \" + respPayload.get(SL20Constants.SL20_COMMAND_CONTAINER_NAME).getAsString()"); - } - - - } catch (final EAAFAuthenticationException e) { - throw new TaskExecutionException(pendingReq, "SL2.0 Authentication FAILED. Msg: " + e.getMessage(), e); - - } catch (final Exception e) { - log.warn("SL2.0 Authentication FAILED with a generic error.", e); - throw new TaskExecutionException(pendingReq, e.getMessage(), e); - - } finally { - TransactionIDUtils.removeTransactionId(); - TransactionIDUtils.removeSessionId(); - - } - - } - - /** - * Create a implementation specific qualified eID SL2.0 command - * @param oaConfig - * - * @return signed JWT token as serialized {@link String} - * @throws CertificateEncodingException - * @throws SLCommandoBuildException - * @throws SL20Exception - */ - protected abstract String buildSignedQualifiedEIDCommand() throws CertificateEncodingException, SL20Exception; - - - private String extractVDAURLForSpecificOA(ISPConfiguration oaConfig, ExecutionContext executionContext) { - - //load SP specific config for development and testing purposes - final String spSpecificVDAEndpoints = oaConfig.getConfigurationValue(Constants.CONFIG_PROP_SP_SL20_ENDPOINT_LIST); - - //load general configuration - final Map<String, String> endPointMap = authConfigWithSp.getBasicConfigurationWithPrefix(Constants.CONFIG_PROP_VDA_ENDPOINT_QUALeID_LIST); - endPointMap.put(Constants.CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT_ELEMENT, authConfig.getBasicConfiguration(Constants.CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT)); - if (StringUtils.isNotEmpty(spSpecificVDAEndpoints)) { - endPointMap.putAll(KeyValueUtils.convertListToMap( - KeyValueUtils.getListOfCSVValues( - KeyValueUtils.normalizeCSVValueString(spSpecificVDAEndpoints)))); - log.debug("Find OA specific SL2.0 endpoints. Updating endPoint list ... "); - - } - - log.trace("Find #" + endPointMap.size() + " SL2.0 endpoints ... "); - - //selection based on request Header - final String sl20VDATypeHeader = (String) executionContext.get(SL20Constants.HTTP_HEADER_SL20_VDA_TYPE.toLowerCase()); - if (StringUtils.isNotEmpty(sl20VDATypeHeader)) { - final String vdaURL = endPointMap.get(sl20VDATypeHeader); - if (StringUtils.isNotEmpty(vdaURL)) - return vdaURL.trim(); - else - log.info("Can NOT find VDA with Id: " + sl20VDATypeHeader + ". Use default VDA"); - - } - - - log.info("NO specific VDA endpoint requested or found. Use default VDA"); - return endPointMap.get(Constants.CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT_ELEMENT); - - } - -} diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractReceiveQualEidTask.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractReceiveQualEidTask.java new file mode 100644 index 00000000..655cc2c6 --- /dev/null +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractReceiveQualEidTask.java @@ -0,0 +1,211 @@ +package at.gv.egiz.eaaf.modules.auth.sl20.tasks; + +import java.io.IOException; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext; +import at.gv.egiz.eaaf.core.exceptions.EaafAuthenticationException; +import at.gv.egiz.eaaf.core.exceptions.EaafStorageException; +import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException; +import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask; +import at.gv.egiz.eaaf.core.impl.utils.DataUrlBuilder; +import at.gv.egiz.eaaf.core.impl.utils.StreamUtils; +import at.gv.egiz.eaaf.core.impl.utils.TransactionIdUtils; +import at.gv.egiz.eaaf.modules.auth.sl20.Constants; +import at.gv.egiz.eaaf.modules.auth.sl20.EventCodes; +import at.gv.egiz.eaaf.modules.auth.sl20.data.VerificationResult; +import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20Exception; +import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20SecurityException; +import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SlCommandoParserException; +import at.gv.egiz.eaaf.modules.auth.sl20.utils.IJoseTools; +import at.gv.egiz.eaaf.modules.auth.sl20.utils.JsonMapper; +import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20Constants; +import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20JsonExtractorUtils; +import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20ResponseUtils; + +import org.apache.commons.lang3.StringUtils; +import org.jose4j.base64url.Base64Url; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; + +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonNode; + +public abstract class AbstractReceiveQualEidTask extends AbstractAuthServletTask { + private static final Logger log = LoggerFactory.getLogger(AbstractReceiveQualEidTask.class); + + @Autowired(required = true) + private IJoseTools joseTools; + + @Override + public void execute(final ExecutionContext executionContext, final HttpServletRequest request, + final HttpServletResponse response) throws TaskExecutionException { + String sl20Result = null; + + try { + log.debug("Receiving SL2.0 response process .... "); + JsonNode sl20ReqObj = null; + + // A-Trust does not SET http-header 'SL2ClientType' with value 'native' + // If A-trust sends an error, its maybe FrontChannel on DataURL + // boolean aTrustErrorWorkAround = false; + + try { + // get SL2.0 command or result from HTTP request + final Map<String, String> reqParams = getParameters(request); + sl20Result = reqParams.get(SL20Constants.PARAM_SL20_REQ_COMMAND_PARAM); + + if (StringUtils.isEmpty(sl20Result)) { + // Workaround for SIC Handy-Signature, because it sends result in InputStream + final String isReqInput = StreamUtils.readStream(request.getInputStream(), "UTF-8"); + if (StringUtils.isNotEmpty(isReqInput)) { + log.info("Use SIC Handy-Signature work-around!"); + sl20Result = isReqInput.substring("slcommand=".length()); + + } else { + log.info("NO SL2.0 commando or result FOUND."); + throw new SL20Exception("sl20.04", null); + } + + } + + log.trace("Received SL2.0 result: " + sl20Result); + revisionsLogger.logEvent(pendingReq, EventCodes.AUTHPROCESS_SL20_DATAURL_IP, request.getRemoteAddr()); + + // parse SL2.0 command/result into JSON + try { + sl20ReqObj = new JsonMapper().getMapper().readTree(Base64Url.decodeToUtf8String(sl20Result)); + + } catch (final JsonParseException e) { + log.warn("SL2.0 command or result is NOT valid JSON.", e); + log.debug("SL2.0 msg: " + sl20Result); + throw new SL20Exception("sl20.02", new Object[] { "SL2.0 command or result is NOT valid JSON." }, e); + + } + + // check on errorMessage + final VerificationResult payLoadContainerErrorCheck = SL20JsonExtractorUtils.extractSL20PayLoad(sl20ReqObj, + joseTools, false); + if (SL20JsonExtractorUtils + .getStringValue(payLoadContainerErrorCheck.getPayload(), SL20Constants.SL20_COMMAND_CONTAINER_NAME, true) + .equals(SL20Constants.SL20_COMMAND_IDENTIFIER_ERROR)) { + log.debug("Find " + SL20Constants.SL20_COMMAND_IDENTIFIER_ERROR + " result .... "); + final JsonNode errorResult = SL20JsonExtractorUtils.extractSL20Result(payLoadContainerErrorCheck.getPayload(), + joseTools, false); + final String errorCode = SL20JsonExtractorUtils.getStringValue(errorResult, + SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORCODE, true); + final String errorMsg = SL20JsonExtractorUtils.getStringValue(errorResult, + SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORMESSAGE, false); + + log.info("Receiving errorcode: {} with msg: {} from VDA! Stopping auth-process ... ", errorCode, errorMsg); + // aTrustErrorWorkAround = true; + throw new SL20Exception("sl20.08", new Object[] { errorCode, errorMsg }); + + } else { + // Receive no error - To request validation + + // validate reqId with inResponseTo + final String sl20ReqId = pendingReq + .getRawData(Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_REQID, String.class); + final String inRespTo = SL20JsonExtractorUtils.getStringValue(sl20ReqObj, SL20Constants.SL20_INRESPTO, true); + if (sl20ReqId == null || !sl20ReqId.equals(inRespTo)) { + log.info("SL20 'reqId': " + sl20ReqId + " does NOT match to 'inResponseTo':" + inRespTo); + throw new SL20SecurityException( + "SL20 'reqId': " + sl20ReqId + " does NOT match to 'inResponseTo':" + inRespTo); + } + + // validate signature + final VerificationResult payLoadContainer = SL20JsonExtractorUtils.extractSL20PayLoad(sl20ReqObj, joseTools, + authConfig.getBasicConfigurationBoolean(Constants.CONFIG_PROP_FORCE_EID_SIGNED_RESULT, true)); + + if (payLoadContainer.isValidSigned() == null || !payLoadContainer.isValidSigned()) { + if (authConfig.getBasicConfigurationBoolean(Constants.CONFIG_PROP_FORCE_EID_SIGNED_RESULT, true)) { + log.info("SL20 result from VDA was not valid signed"); + throw new SL20SecurityException(new Object[] { "Signature on SL20 result NOT valid." }); + + } else { + log.warn("SL20 result from VDA is NOT valid signed, but signatures-verification " + + "is DISABLED by configuration!"); + + } + } + + // extract payloaf + final JsonNode payLoad = payLoadContainer.getPayload(); + + // handle SL2.0 response payLoad + handleResponsePayLoad(payLoad); + + } + + } catch (final EaafAuthenticationException e) { + log.warn("SL2.0 processing error:", e); + if (sl20Result != null) { + log.debug("Received SL2.0 result: " + sl20Result); + } + pendingReq.setRawDataToTransaction( + Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_COMMAND_IDENTIFIER_ERROR, + new TaskExecutionException(pendingReq, "SL2.0 Authentication FAILED. Msg: " + e.getMessage(), e)); + + } catch (final Exception e) { + log.warn("ERROR:", e); + log.warn("SL2.0 Authentication FAILED with a generic error.", e); + if (sl20Result != null) { + log.debug("Received SL2.0 result: " + sl20Result); + } + pendingReq.setRawDataToTransaction( + Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_COMMAND_IDENTIFIER_ERROR, + new TaskExecutionException(pendingReq, e.getMessage(), e)); + + } finally { + // store pending request + requestStoreage.storePendingRequest(pendingReq); + + // write SL2.0 response + if (sl20ReqObj != null) { + final String resumeEndpoint = new DataUrlBuilder().buildDataUrl(pendingReq.getAuthUrl(), + getResumeEndPoint(), pendingReq.getPendingRequestId()); + SL20ResponseUtils.buildResponse(request, response, pendingReq, resumeEndpoint, + SL20JsonExtractorUtils.getStringValue(sl20ReqObj, SL20Constants.SL20_TRANSACTIONID, false), + authConfig); + + } else { + SL20ResponseUtils.buildErrorResponse(response, "2000", "General transport Binding error"); + } + + } + + } catch (final Exception e) { + // write internal server errror 500 according to SL2.0 specification, chapter + // https transport + // binding + log.warn("Can NOT build SL2.0 response. Reason: " + e.getMessage(), e); + if (sl20Result != null) { + log.debug("Received SL2.0 result: " + sl20Result); + } + try { + response.sendError(500, "Internal Server Error."); + + } catch (final IOException e1) { + log.error("Can NOT send error message. SOMETHING IS REALY WRONG!", e); + + } + + } finally { + TransactionIdUtils.removeTransactionId(); + TransactionIdUtils.removeSessionId(); + + } + } + + protected abstract void handleResponsePayLoad(JsonNode payLoad) + throws SlCommandoParserException, SL20Exception, EaafStorageException; + + protected abstract String getResumeEndPoint(); + + +} diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractReceiveQualeIDTask.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractReceiveQualeIDTask.java deleted file mode 100644 index b4039cf9..00000000 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/tasks/AbstractReceiveQualeIDTask.java +++ /dev/null @@ -1,321 +0,0 @@ -package at.gv.egiz.eaaf.modules.auth.sl20.tasks; - -import java.io.IOException; -import java.io.StringWriter; -import java.net.URISyntaxException; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.lang3.StringUtils; -import org.apache.http.client.utils.URIBuilder; -import org.apache.http.entity.ContentType; -import org.jose4j.base64url.Base64Url; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; - -import com.fasterxml.jackson.core.JsonParseException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ObjectNode; - -import at.gv.egiz.eaaf.core.api.data.EAAFConstants; -import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext; -import at.gv.egiz.eaaf.core.exceptions.EAAFAuthenticationException; -import at.gv.egiz.eaaf.core.exceptions.EAAFStorageException; -import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException; -import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask; -import at.gv.egiz.eaaf.core.impl.utils.DataURLBuilder; -import at.gv.egiz.eaaf.core.impl.utils.StreamUtils; -import at.gv.egiz.eaaf.core.impl.utils.TransactionIDUtils; -import at.gv.egiz.eaaf.modules.auth.sl20.Constants; -import at.gv.egiz.eaaf.modules.auth.sl20.EventCodes; -import at.gv.egiz.eaaf.modules.auth.sl20.data.VerificationResult; -import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20Exception; -import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20SecurityException; -import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SLCommandoParserException; -import at.gv.egiz.eaaf.modules.auth.sl20.utils.IJOSETools; -import at.gv.egiz.eaaf.modules.auth.sl20.utils.JsonMapper; -import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20Constants; -import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20JSONBuilderUtils; -import at.gv.egiz.eaaf.modules.auth.sl20.utils.SL20JSONExtractorUtils; - - -public abstract class AbstractReceiveQualeIDTask extends AbstractAuthServletTask { - private static final Logger log = LoggerFactory.getLogger(AbstractReceiveQualeIDTask.class); - - @Autowired(required=true) private IJOSETools joseTools; - - @Override - public void execute(ExecutionContext executionContext, HttpServletRequest request, HttpServletResponse response) - throws TaskExecutionException { - String sl20Result = null; - - try { - log.debug("Receiving SL2.0 response process .... "); - JsonNode sl20ReqObj = null; - - //A-Trust does not SET http-header 'SL2ClientType' with value 'native' - //If A-trust sends an error, its maybe FrontChannel on DataURL - //boolean aTrustErrorWorkAround = false; - - try { - //get SL2.0 command or result from HTTP request - final Map<String, String> reqParams = getParameters(request); - sl20Result = reqParams.get(SL20Constants.PARAM_SL20_REQ_COMMAND_PARAM); - - if (StringUtils.isEmpty(sl20Result)) { - //Workaround for SIC Handy-Signature, because it sends result in InputStream - final String isReqInput = StreamUtils.readStream(request.getInputStream(), "UTF-8"); - if (StringUtils.isNotEmpty(isReqInput)) { - log.info("Use SIC Handy-Signature work-around!"); - sl20Result = isReqInput.substring("slcommand=".length()); - - } else { - log.info("NO SL2.0 commando or result FOUND."); - throw new SL20Exception("sl20.04", null); - } - - } - - log.trace("Received SL2.0 result: " + sl20Result); - revisionsLogger.logEvent(pendingReq, EventCodes.AUTHPROCESS_SL20_DATAURL_IP, request.getRemoteAddr()); - - //parse SL2.0 command/result into JSON - try { - sl20ReqObj = new JsonMapper().getMapper().readTree(Base64Url.decodeToUtf8String(sl20Result)); - - } catch (final JsonParseException e) { - log.warn("SL2.0 command or result is NOT valid JSON.", e); - log.debug("SL2.0 msg: " + sl20Result); - throw new SL20Exception("sl20.02", new Object[]{"SL2.0 command or result is NOT valid JSON."}, e); - - } - - //check on errorMessage - final VerificationResult payLoadContainerErrorCheck = SL20JSONExtractorUtils.extractSL20PayLoad(sl20ReqObj, joseTools, false); - if (SL20JSONExtractorUtils.getStringValue( - payLoadContainerErrorCheck.getPayload(), SL20Constants.SL20_COMMAND_CONTAINER_NAME, true) - .equals(SL20Constants.SL20_COMMAND_IDENTIFIER_ERROR)) { - log.debug("Find " + SL20Constants.SL20_COMMAND_IDENTIFIER_ERROR + " result .... "); - final JsonNode errorResult = SL20JSONExtractorUtils.extractSL20Result(payLoadContainerErrorCheck.getPayload(), joseTools, false); - final String errorCode = SL20JSONExtractorUtils.getStringValue(errorResult, - SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORCODE, true); - final String errorMsg = SL20JSONExtractorUtils.getStringValue(errorResult, - SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORMESSAGE, false); - - log.info("Receiving errorcode: {} with msg: {} from VDA! Stopping auth-process ... ", errorCode, errorMsg); - //aTrustErrorWorkAround = true; - throw new SL20Exception("sl20.08", new Object[] {errorCode, errorMsg}); - - } else { - //Receive no error - To request validation - - //validate reqId with inResponseTo - final String sl20ReqId = pendingReq.getRawData(Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_REQID, String.class); - final String inRespTo = SL20JSONExtractorUtils.getStringValue(sl20ReqObj, SL20Constants.SL20_INRESPTO, true); - if (sl20ReqId == null || !sl20ReqId.equals(inRespTo)) { - log.info("SL20 'reqId': " + sl20ReqId + " does NOT match to 'inResponseTo':" + inRespTo); - throw new SL20SecurityException("SL20 'reqId': " + sl20ReqId + " does NOT match to 'inResponseTo':" + inRespTo); - } - - - //validate signature - final VerificationResult payLoadContainer = SL20JSONExtractorUtils.extractSL20PayLoad( - sl20ReqObj, joseTools, - authConfig.getBasicConfigurationBoolean(Constants.CONFIG_PROP_FORCE_EID_SIGNED_RESULT, true)); - - if ( (payLoadContainer.isValidSigned() == null || !payLoadContainer.isValidSigned())) { - if (authConfig.getBasicConfigurationBoolean(Constants.CONFIG_PROP_FORCE_EID_SIGNED_RESULT, true)) { - log.info("SL20 result from VDA was not valid signed"); - throw new SL20SecurityException(new Object[]{"Signature on SL20 result NOT valid."}); - - } else { - log.warn("SL20 result from VDA is NOT valid signed, but signatures-verification is DISABLED by configuration!"); - - } - } - - payLoadContainer.getCertChain(); - - - //extract payloaf - final JsonNode payLoad = payLoadContainer.getPayload(); - - - //handle SL2.0 response payLoad - handleResponsePayLoad(payLoad); - - } - - } catch (final EAAFAuthenticationException e) { - log.warn("SL2.0 processing error:", e); - if (sl20Result != null) - log.debug("Received SL2.0 result: " + sl20Result); - pendingReq.setRawDataToTransaction( - Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_COMMAND_IDENTIFIER_ERROR, - new TaskExecutionException(pendingReq, "SL2.0 Authentication FAILED. Msg: " + e.getMessage(), e)); - - } catch (final Exception e) { - log.warn("ERROR:", e); - log.warn("SL2.0 Authentication FAILED with a generic error.", e); - if (sl20Result != null) - log.debug("Received SL2.0 result: " + sl20Result); - pendingReq.setRawDataToTransaction( - Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_COMMAND_IDENTIFIER_ERROR, - new TaskExecutionException(pendingReq, e.getMessage(), e)); - - } finally { - //store pending request - requestStoreage.storePendingRequest(pendingReq); - - //write SL2.0 response - if (sl20ReqObj != null) - //buildResponse(request, response, sl20ReqObj, aTrustErrorWorkAround); - buildResponse(request, response, sl20ReqObj); - else - buildErrorResponse(request, response, "2000", "General transport Binding error"); - - } - - } catch (final Exception e) { - //write internal server errror 500 according to SL2.0 specification, chapter https transport binding - log.warn("Can NOT build SL2.0 response. Reason: " + e.getMessage(), e); - if (sl20Result != null) - log.debug("Received SL2.0 result: " + sl20Result); - try { - response.sendError(500, "Internal Server Error."); - - } catch (final IOException e1) { - log.error("Can NOT send error message. SOMETHING IS REALY WRONG!", e); - - } - - } finally { - TransactionIDUtils.removeTransactionId(); - TransactionIDUtils.removeSessionId(); - - } - } - - protected abstract void handleResponsePayLoad(JsonNode payLoad) throws SLCommandoParserException, SL20Exception, EAAFStorageException; - - protected abstract String getResumeEndPoint(); - - private void buildErrorResponse(HttpServletRequest request, HttpServletResponse response, String errorCode, String errorMsg) throws Exception { - final ObjectNode error = SL20JSONBuilderUtils.createErrorCommandResult(errorCode, errorMsg); - final ObjectNode errorCommand = SL20JSONBuilderUtils.createCommandResponse(SL20Constants.SL20_COMMAND_IDENTIFIER_ERROR, error, null); - - - final ObjectNode respContainer = SL20JSONBuilderUtils.createGenericResponse( - UUID.randomUUID().toString(), - null, - null, - errorCommand , - null); - - log.trace("SL20 response to VDA: " + respContainer); - final StringWriter writer = new StringWriter(); - writer.write(respContainer.toString()); - final byte[] content = writer.toString().getBytes("UTF-8"); - response.setStatus(HttpServletResponse.SC_OK); - response.setContentLength(content.length); - response.setContentType(ContentType.APPLICATION_JSON.toString()); - response.getOutputStream().write(content); - - } - - private void buildResponse(HttpServletRequest request, HttpServletResponse response, JsonNode sl20ReqObj) throws IOException, SL20Exception, URISyntaxException { - //create response - final Map<String, String> reqParameters = new HashMap<String, String>(); - reqParameters.put(EAAFConstants.PARAM_HTTP_TARGET_PENDINGREQUESTID, pendingReq.getPendingRequestId()); - final ObjectNode callReqParams = SL20JSONBuilderUtils.createCallCommandParameters( - new DataURLBuilder().buildDataURL(pendingReq.getAuthURL(), getResumeEndPoint(), null), - SL20Constants.SL20_COMMAND_PARAM_GENERAL_CALL_METHOD_GET, - false, - reqParameters); - final ObjectNode callCommand = SL20JSONBuilderUtils.createCommand(SL20Constants.SL20_COMMAND_IDENTIFIER_CALL, callReqParams); - - //build first redirect command for app - final ObjectNode redirectOneParams = SL20JSONBuilderUtils.createRedirectCommandParameters( - generateICPRedirectURLForDebugging(), - callCommand, null, true); - final ObjectNode redirectOneCommand = SL20JSONBuilderUtils.createCommand(SL20Constants.SL20_COMMAND_IDENTIFIER_REDIRECT, redirectOneParams); - - //build second redirect command for IDP - final ObjectNode redirectTwoParams = SL20JSONBuilderUtils.createRedirectCommandParameters( - new DataURLBuilder().buildDataURL(pendingReq.getAuthURL(), getResumeEndPoint(), pendingReq.getPendingRequestId()), - redirectOneCommand, null, false); - final ObjectNode redirectTwoCommand = SL20JSONBuilderUtils.createCommand(SL20Constants.SL20_COMMAND_IDENTIFIER_REDIRECT, redirectTwoParams); - - //build generic SL2.0 response container - final String transactionId = SL20JSONExtractorUtils.getStringValue(sl20ReqObj, SL20Constants.SL20_TRANSACTIONID, false); - final ObjectNode respContainer = SL20JSONBuilderUtils.createGenericRequest( - UUID.randomUUID().toString(), - transactionId, - redirectTwoCommand, - null); - - if (request.getHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE) != null && - request.getHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE).equals(SL20Constants.HTTP_HEADER_VALUE_NATIVE)) { - log.debug("Client request containts 'native client' header ... "); - log.trace("SL20 response to VDA: " + respContainer); - final StringWriter writer = new StringWriter(); - writer.write(respContainer.toString()); - final byte[] content = writer.toString().getBytes("UTF-8"); - response.setStatus(HttpServletResponse.SC_OK); - response.setContentLength(content.length); - response.setContentType(ContentType.APPLICATION_JSON.toString()); - response.getOutputStream().write(content); - - - } else { - log.info("SL2.0 DataURL communication needs http header: '" + SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE + "'"); - - log.debug("Client request containts is no native client ... "); - final URIBuilder clientRedirectURI = new URIBuilder( - new DataURLBuilder().buildDataURL( - pendingReq.getAuthURL(), getResumeEndPoint(), pendingReq.getPendingRequestId())); - response.setStatus(Integer.parseInt( - authConfig.getBasicConfiguration( - Constants.CONFIG_PROP_HTTP_REDIRECT_CODE, - Constants.CONFIG_PROP_HTTP_REDIRECT_CODE_DEFAULT_VALUE))); - response.setHeader("Location", clientRedirectURI.build().toString()); - - -// throw new SL20Exception("sl20.06", -// new Object[] {"SL2.0 DataURL communication needs http header: '" + SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE + "'"}); - - } - } - - /** - * Generates a IPC redirect URL that is configured on IDP side - * - * @return IPC ReturnURL, or null if no URL is configured - */ - private String generateICPRedirectURLForDebugging() { - final String PATTERN_PENDING_REQ_ID = "#PENDINGREQID#"; - - String ipcRedirectURLConfig = authConfig.getBasicConfiguration(Constants.CONFIG_PROP_IPC_RETURN_URL); - if (StringUtils.isNotEmpty(ipcRedirectURLConfig)) { - if (ipcRedirectURLConfig.contains(PATTERN_PENDING_REQ_ID)) { - log.trace("Find 'pendingReqId' pattern in IPC redirect URL. Update url ... "); - ipcRedirectURLConfig = ipcRedirectURLConfig.replaceAll( - "#PENDINGREQID#", - EAAFConstants.PARAM_HTTP_TARGET_PENDINGREQUESTID + "=" + pendingReq.getPendingRequestId()); - - } - - return ipcRedirectURLConfig; - } - - return null; - - } - - -} diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/IJOSETools.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/IJOSETools.java deleted file mode 100644 index b124ada7..00000000 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/IJOSETools.java +++ /dev/null @@ -1,87 +0,0 @@ -package at.gv.egiz.eaaf.modules.auth.sl20.utils; - -import java.io.IOException; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.cert.X509Certificate; -import java.util.List; - -import javax.annotation.Nonnull; - -import org.jose4j.jwa.AlgorithmConstraints; -import org.jose4j.lang.JoseException; - -import com.fasterxml.jackson.databind.JsonNode; - -import at.gv.egiz.eaaf.modules.auth.sl20.data.VerificationResult; -import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20Exception; -import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SLCommandoBuildException; -import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SLCommandoParserException; - -public interface IJOSETools { - - /** - * Create a JWS signature - * - * @param payLoad Payload to sign - * @throws SLCommandoBuildException - */ - public String createSignature(String payLoad) throws SLCommandoBuildException; - - /** - * Validates a signed SL2.0 message - * - * @param serializedContent - * @return - * @throws SLCommandoParserException - * @throws SL20Exception - */ - @Nonnull - public VerificationResult validateSignature(@Nonnull String serializedContent) throws SL20Exception; - - /** - * Validate a JWS signature - * - * @param serializedContent JWS in serialized form - * @param trustedCerts trusted X509 certificates - * @param constraints signature verification constraints - * @return Signature-verification result - * @throws JoseException - * @throws IOException - */ - @Nonnull - public VerificationResult validateSignature(@Nonnull String serializedContent, @Nonnull List<X509Certificate> trustedCerts, - @Nonnull AlgorithmConstraints constraints) throws JoseException, IOException; - - /** - * Validate a JWS signature - * - * @param serializedContent JWS in serialized form - * @param trustStore with trusted X509 certificates - * @param algconstraints signature verification constraints - * @return Signature-verification result - * @throws JoseException - * @throws IOException - * @throws KeyStoreException - */ - @Nonnull - public VerificationResult validateSignature(@Nonnull String serializedContent, @Nonnull KeyStore trustStore, - @Nonnull AlgorithmConstraints algconstraints) throws JoseException, IOException, KeyStoreException; - - /** - * Get the encryption certificate for SL2.0 End-to-End encryption - * - * @return - */ - public X509Certificate getEncryptionCertificate(); - - /** - * Decrypt a serialized JWE token - * - * @param compactSerialization Serialized JWE token - * @return decrypted payload - * @throws SL20Exception - */ - public JsonNode decryptPayload(String compactSerialization) throws SL20Exception; - -} diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/IJoseTools.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/IJoseTools.java new file mode 100644 index 00000000..f04555dc --- /dev/null +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/IJoseTools.java @@ -0,0 +1,98 @@ +package at.gv.egiz.eaaf.modules.auth.sl20.utils; + +import java.io.IOException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.cert.X509Certificate; +import java.util.List; + +import javax.annotation.Nonnull; + +import at.gv.egiz.eaaf.modules.auth.sl20.data.VerificationResult; +import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20Exception; +import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SlCommandoBuildException; + +import org.jose4j.jwa.AlgorithmConstraints; +import org.jose4j.lang.JoseException; + +import com.fasterxml.jackson.databind.JsonNode; + +public interface IJoseTools { + + /** + * Create a JWS signature. + * + *<p>This method adds the certificate chain into JOSE header.</p> + * + * @param payLoad Payload to sign + * @throws SlCommandoBuildException In case of a signature creation error + */ + String createSignature(String payLoad) throws SlCommandoBuildException; + + /** + * Create a JWS signature. + * + * @param payLoad Payload to sign + * @param addFullCertChain If <code>true</code> the full certificate chain will be added, + * otherwise only the X509CertSha256Fingerprint is added into JOSE header + * @return Signed PayLoad in serialized form + * @throws SlCommandoBuildException SlCommandoBuildException In case of a signature creation error + */ + String createSignature(String payLoad, boolean addFullCertChain) throws SlCommandoBuildException; + + /** + * Validates a signed SL2.0 message. + * + * @param serializedContent Serialized JWS signature + * @return Verification-result DAO + * @throws SL20Exception In case of a signature validation error + */ + @Nonnull + VerificationResult validateSignature(@Nonnull String serializedContent) throws SL20Exception; + + /** + * Validate a JWS signature. + * + * @param serializedContent JWS in serialized form + * @param trustedCerts trusted X509 certificates + * @param constraints signature verification constraints + * @return Signature-verification result + * @throws JoseException In case of a signature verification error + * @throws IOException In case of a general IO error + */ + @Nonnull + VerificationResult validateSignature(@Nonnull String serializedContent, @Nonnull List<X509Certificate> trustedCerts, + @Nonnull AlgorithmConstraints constraints) throws JoseException, IOException; + + /** + * Validate a JWS signature. + * + * @param serializedContent JWS in serialized form + * @param trustStore with trusted X509 certificates + * @param algconstraints signature verification constraints + * @return Signature-verification result + * @throws JoseException In case of a signature verification error + * @throws IOException In case of a general IO error + * @throws KeyStoreException In case of TrustStore error + */ + @Nonnull + VerificationResult validateSignature(@Nonnull String serializedContent, @Nonnull KeyStore trustStore, + @Nonnull AlgorithmConstraints algconstraints) throws JoseException, IOException, KeyStoreException; + + /** + * Get the encryption certificate for SL2.0 End-to-End encryption. + * + * @return + */ + X509Certificate getEncryptionCertificate(); + + /** + * Decrypt a serialized JWE token. + * + * @param compactSerialization Serialized JWE token + * @return decrypted payload + * @throws SL20Exception In case of a decryption error + */ + JsonNode decryptPayload(String compactSerialization) throws SL20Exception; + +} diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonMapper.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonMapper.java index b33649e1..2387a9f2 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonMapper.java +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonMapper.java @@ -18,114 +18,122 @@ import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.type.TypeFactory; import at.gv.egiz.eaaf.core.api.utils.IJsonMapper; -import at.gv.egiz.eaaf.core.exceptions.EAAFJsonMapperException; +import at.gv.egiz.eaaf.core.exceptions.EaafJsonMapperException; public class JsonMapper implements IJsonMapper { - private static final Logger log = LoggerFactory.getLogger(JsonMapper.class); - - private final ObjectMapper mapper = new ObjectMapper(); - - /** - * The default constructor where the default pretty printer is disabled. - */ - public JsonMapper() { - this(false); - - } - - /** - * The constructor. - * @param prettyPrint enables or disables the default pretty printer - */ - public JsonMapper(@NonNull boolean prettyPrint) { - log.trace("Initializing JSON object-mapper ... "); - mapper.configure(DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY, true); - mapper.configure(DeserializationFeature.FAIL_ON_TRAILING_TOKENS, true); - mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES , true); - mapper.setVisibility(PropertyAccessor.ALL, Visibility.NONE); - mapper.setVisibility(PropertyAccessor.GETTER, Visibility.PUBLIC_ONLY); - mapper.setVisibility(PropertyAccessor.IS_GETTER, Visibility.PUBLIC_ONLY); - if (prettyPrint) { - mapper.enable(SerializationFeature.INDENT_OUTPUT); - } - - log.debug("JSON object-mapper initialized"); - - } - - - /* (non-Javadoc) - * @at.gv.egiz.eaaf.core.api.utils.IJsonMapper#getMapper() - */ - public ObjectMapper getMapper() { - return mapper; - - } - - - /* (non-Javadoc) - * @see at.gv.egiz.eaaf.core.api.utils.IJsonMapper#serialize(java.lang.Object) - */ - @Override - public String serialize(Object value) throws EAAFJsonMapperException { - try { - return mapper.writeValueAsString(value); - - } catch (final JsonProcessingException e) { - log.warn("JSON mapping FAILED with error: {}", e.getMessage()); - throw new EAAFJsonMapperException(e.getMessage(), e); - - } - - } - - /* (non-Javadoc) - * @see at.gv.egiz.eaaf.core.api.utils.IJsonMapper#deserialize(java.lang.String, java.lang.Class) - */ - @Override - public <T> Object deserialize(String value, Class<T> clazz) throws EAAFJsonMapperException { - try { - if (clazz != null) { - if (clazz.isAssignableFrom(TypeReference.class)) - return mapper.readValue(value, clazz); - else { - final JavaType javaType = TypeFactory.defaultInstance().constructType(clazz); - return mapper.readValue(value, javaType); - - } - - } else - return mapper.readValue(value, Object.class); - - } catch (final IOException e) { - log.warn("JSON mapping FAILED with error: {}", e.getMessage()); - throw new EAAFJsonMapperException(e.getMessage(), e); - - } - - } - - @Override - public <T> Object deserialize(InputStream is, Class<T> clazz) throws EAAFJsonMapperException { - try { - if (clazz != null) { - if (clazz.isAssignableFrom(TypeReference.class)) - return mapper.readValue(is, clazz); - else { - final JavaType javaType = TypeFactory.defaultInstance().constructType(clazz); - return mapper.readValue(is, javaType); - - } - - } else - return mapper.readValue(is, Object.class); - - } catch (final IOException e) { - log.warn("JSON mapping FAILED with error: {}", e.getMessage()); - throw new EAAFJsonMapperException(e.getMessage(), e); - - } - - } - + private static final Logger log = LoggerFactory.getLogger(JsonMapper.class); + + private final ObjectMapper mapper = new ObjectMapper(); + + /** + * The default constructor where the default pretty printer is disabled. + */ + public JsonMapper() { + this(false); + + } + + /** + * The constructor. + * + * @param prettyPrint enables or disables the default pretty printer + */ + public JsonMapper(@NonNull final boolean prettyPrint) { + log.trace("Initializing JSON object-mapper ... "); + mapper.configure(DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY, true); + mapper.configure(DeserializationFeature.FAIL_ON_TRAILING_TOKENS, true); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true); + mapper.setVisibility(PropertyAccessor.ALL, Visibility.NONE); + mapper.setVisibility(PropertyAccessor.GETTER, Visibility.PUBLIC_ONLY); + mapper.setVisibility(PropertyAccessor.IS_GETTER, Visibility.PUBLIC_ONLY); + if (prettyPrint) { + mapper.enable(SerializationFeature.INDENT_OUTPUT); + } + + log.debug("JSON object-mapper initialized"); + + } + + /* + * (non-Javadoc) + * + * @at.gv.egiz.eaaf.core.api.utils.IJsonMapper#getMapper() + */ + public ObjectMapper getMapper() { + return mapper; + + } + + /* + * (non-Javadoc) + * + * @see at.gv.egiz.eaaf.core.api.utils.IJsonMapper#serialize(java.lang.Object) + */ + @Override + public String serialize(final Object value) throws EaafJsonMapperException { + try { + return mapper.writeValueAsString(value); + + } catch (final JsonProcessingException e) { + log.warn("JSON mapping FAILED with error: {}", e.getMessage()); + throw new EaafJsonMapperException(e.getMessage(), e); + + } + + } + + /* + * (non-Javadoc) + * + * @see at.gv.egiz.eaaf.core.api.utils.IJsonMapper#deserialize(java.lang.String, + * java.lang.Class) + */ + @Override + public <T> Object deserialize(final String value, final Class<T> clazz) throws EaafJsonMapperException { + try { + if (clazz != null) { + if (clazz.isAssignableFrom(TypeReference.class)) { + return mapper.readValue(value, clazz); + } else { + final JavaType javaType = TypeFactory.defaultInstance().constructType(clazz); + return mapper.readValue(value, javaType); + + } + + } else { + return mapper.readValue(value, Object.class); + } + + } catch (final IOException e) { + log.warn("JSON mapping FAILED with error: {}", e.getMessage()); + throw new EaafJsonMapperException(e.getMessage(), e); + + } + + } + + @Override + public <T> Object deserialize(final InputStream is, final Class<T> clazz) throws EaafJsonMapperException { + try { + if (clazz != null) { + if (clazz.isAssignableFrom(TypeReference.class)) { + return mapper.readValue(is, clazz); + } else { + final JavaType javaType = TypeFactory.defaultInstance().constructType(clazz); + return mapper.readValue(is, javaType); + + } + + } else { + return mapper.readValue(is, Object.class); + } + + } catch (final IOException e) { + log.warn("JSON mapping FAILED with error: {}", e.getMessage()); + throw new EaafJsonMapperException(e.getMessage(), e); + + } + + } + } diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonSecurityUtils.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonSecurityUtils.java index c07c6081..1b1f090f 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonSecurityUtils.java +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/JsonSecurityUtils.java @@ -1,23 +1,36 @@ package at.gv.egiz.eaaf.modules.auth.sl20.utils; import java.io.IOException; -import java.net.MalformedURLException; import java.security.Key; import java.security.KeyStore; import java.security.KeyStoreException; -import java.security.PrivateKey; -import java.security.cert.Certificate; +import java.security.Provider; import java.security.cert.CertificateEncodingException; import java.security.cert.X509Certificate; -import java.util.ArrayList; import java.util.Collections; -import java.util.Enumeration; import java.util.List; import javax.annotation.Nonnull; import javax.annotation.PostConstruct; +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.core.exception.EaafKeyAccessException; +import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException; +import at.gv.egiz.eaaf.core.impl.credential.EaafKeyStoreFactory; +import at.gv.egiz.eaaf.core.impl.credential.EaafKeyStoreUtils; +import at.gv.egiz.eaaf.core.impl.credential.KeyStoreConfiguration; +import at.gv.egiz.eaaf.core.impl.credential.KeyStoreConfiguration.KeyStoreType; +import at.gv.egiz.eaaf.core.impl.data.Pair; +import at.gv.egiz.eaaf.core.impl.utils.X509Utils; +import at.gv.egiz.eaaf.modules.auth.sl20.Constants; +import at.gv.egiz.eaaf.modules.auth.sl20.data.VerificationResult; +import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20Exception; +import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20SecurityException; +import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SlCommandoBuildException; +import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SlCommandoParserException; + import org.apache.commons.lang3.StringUtils; +import org.jose4j.jca.ProviderContext; import org.jose4j.jwa.AlgorithmConstraints; import org.jose4j.jwa.AlgorithmConstraints.ConstraintType; import org.jose4j.jwe.JsonWebEncryption; @@ -37,384 +50,403 @@ import org.springframework.util.Base64Utils; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.databind.JsonNode; -import at.gv.egiz.eaaf.core.api.idp.IConfiguration; -import at.gv.egiz.eaaf.core.exceptions.EAAFConfigurationException; -import at.gv.egiz.eaaf.core.impl.utils.FileUtils; -import at.gv.egiz.eaaf.core.impl.utils.KeyStoreUtils; -import at.gv.egiz.eaaf.core.impl.utils.X509Utils; -import at.gv.egiz.eaaf.modules.auth.sl20.Constants; -import at.gv.egiz.eaaf.modules.auth.sl20.data.VerificationResult; -import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20Exception; -import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20SecurityException; -import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SLCommandoBuildException; -import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SLCommandoParserException; - @Service -public class JsonSecurityUtils implements IJOSETools{ - private static final Logger log = LoggerFactory.getLogger(JsonSecurityUtils.class); - - @Autowired(required=true) IConfiguration authConfig; - private Key signPrivKey = null; - private X509Certificate[] signCertChain = null; - - private Key encPrivKey = null; - private X509Certificate[] encCertChain = null; - - private List<X509Certificate> trustedCerts = new ArrayList<X509Certificate>(); - - private static JsonMapper mapper = new JsonMapper(); - - @PostConstruct - protected void initalize() { - log.info("Initialize SL2.0 authentication security constrains ... "); - try { - if (getKeyStoreFilePath() != null) { - final KeyStore keyStore = KeyStoreUtils.loadKeyStore(getKeyStoreFilePath(), - getKeyStorePassword()); - - //load signing key - signPrivKey = keyStore.getKey(getSigningKeyAlias(), getSigningKeyPassword().toCharArray()); - final Certificate[] certChainSigning = keyStore.getCertificateChain(getSigningKeyAlias()); - signCertChain = new X509Certificate[certChainSigning.length]; - for (int i=0; i<certChainSigning.length; i++) { - if (certChainSigning[i] instanceof X509Certificate) { - signCertChain[i] = (X509Certificate)certChainSigning[i]; - } else - log.warn("NO X509 certificate for signing: " + certChainSigning[i].getType()); - - } - - //load encryption key - try { - encPrivKey = keyStore.getKey(getEncryptionKeyAlias(), getEncryptionKeyPassword().toCharArray()); - if (encPrivKey != null) { - final Certificate[] certChainEncryption = keyStore.getCertificateChain(getEncryptionKeyAlias()); - encCertChain = new X509Certificate[certChainEncryption.length]; - for (int i=0; i<certChainEncryption.length; i++) { - if (certChainEncryption[i] instanceof X509Certificate) { - encCertChain[i] = (X509Certificate)certChainEncryption[i]; - } else - log.warn("NO X509 certificate for encryption: " + certChainEncryption[i].getType()); - } - } else - log.info("No encryption key for SL2.0 found. End-to-End encryption is not used."); - - } catch (final Exception e) { - log.warn("No encryption key for SL2.0 found. End-to-End encryption is not used. Reason: " + e.getMessage(), e); - - } - - //load trusted certificates - trustedCerts = readCertsFromKeyStore(keyStore); - - //some short validation - if (signPrivKey == null || !(signPrivKey instanceof PrivateKey)) { - log.info("Can NOT open privateKey for SL2.0 signing. KeyStore=" + getKeyStoreFilePath()); - throw new SL20Exception("sl20.03", new Object[]{"Can NOT open private key for signing"}); - - } - - if (signCertChain == null || signCertChain.length == 0) { - log.info("NO certificate for SL2.0 signing. KeyStore=" + getKeyStoreFilePath()); - throw new SL20Exception("sl20.03", new Object[]{"NO certificate for SL2.0 signing"}); - - } - - log.info("SL2.0 authentication security constrains initialized."); - - } else - log.info("NO SL2.0 authentication security configuration. Initialization was skipped"); - - } catch ( final Exception e) { - log.error("SL2.0 security constrains initialization FAILED.", e); - - } - - } - - @Override - public String createSignature(String payLoad) throws SLCommandoBuildException { - try { - final JsonWebSignature jws = new JsonWebSignature(); - - //set payload - jws.setPayload(payLoad); - - //set basic header - jws.setContentTypeHeaderValue(SL20Constants.SL20_CONTENTTYPE_SIGNED_COMMAND); - - //set signing information - jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256); - jws.setKey(signPrivKey); - - //TODO: - jws.setCertificateChainHeaderValue(signCertChain); - jws.setX509CertSha256ThumbprintHeaderValue(signCertChain[0]); - - return jws.getCompactSerialization(); - - } catch (final JoseException e) { - log.warn("Can NOT sign SL2.0 command.", e); - throw new SLCommandoBuildException("Can NOT sign SL2.0 command.", e); - - } - - } - - @Override - public VerificationResult validateSignature(String serializedContent, KeyStore trustStore, - AlgorithmConstraints algconstraints) throws JoseException, IOException, KeyStoreException { - final List<X509Certificate> trustedCertificates = readCertsFromKeyStore(trustStore); - return validateSignature(serializedContent, trustedCertificates , algconstraints); - - } - - @Override - @NonNull - public VerificationResult validateSignature(@Nonnull String serializedContent, @Nonnull List<X509Certificate> trustedCerts, @Nonnull AlgorithmConstraints constraints) throws JoseException, IOException { - final JsonWebSignature jws = new JsonWebSignature(); - //set payload - jws.setCompactSerialization(serializedContent); - - //set security constrains - jws.setAlgorithmConstraints(constraints); - - //load signinc certs - Key selectedKey = null; - final List<X509Certificate> x5cCerts = jws.getCertificateChainHeaderValue(); - final String x5t256 = jws.getX509CertSha256ThumbprintHeaderValue(); - if (x5cCerts != null) { - log.debug("Found x509 certificate in JOSE header ... "); - log.trace("Sorting received X509 certificates ... "); - final List<X509Certificate> sortedX5cCerts = X509Utils.sortCertificates(x5cCerts); - - if (trustedCerts.contains(sortedX5cCerts.get(0))) { - selectedKey = sortedX5cCerts.get(0).getPublicKey(); - - } else { - log.info("Can NOT find JOSE certificate in truststore."); - try { - log.debug("Cert: " + Base64Utils.encodeToString(sortedX5cCerts.get(0).getEncoded())); - - } catch (final CertificateEncodingException e) { - e.printStackTrace(); - - } - - } - - } else if (StringUtils.isNotEmpty(x5t256)) { - log.debug("Found x5t256 fingerprint in JOSE header .... "); - final X509VerificationKeyResolver x509VerificationKeyResolver = new X509VerificationKeyResolver(trustedCerts); - selectedKey = x509VerificationKeyResolver.resolveKey(jws, Collections.<JsonWebStructure>emptyList()); - - } else { - throw new JoseException("JWS contains NO signature certificate or NO certificate fingerprint"); - - } - - if (selectedKey == null) { - throw new JoseException("Can NOT select verification key for JWS. Signature verification FAILED"); - - } - - //set verification key - jws.setKey(selectedKey); - - //load payLoad - return new VerificationResult(mapper.getMapper().readTree(jws.getPayload()), null, jws.verifySignature()) ; - - - } - - @Override - @Nonnull - public VerificationResult validateSignature(@Nonnull String serializedContent) throws SL20Exception { - try { - final AlgorithmConstraints algConstraints = new AlgorithmConstraints(ConstraintType.WHITELIST, - SL20Constants.SL20_ALGORITHM_WHITELIST_SIGNING.toArray(new String[SL20Constants.SL20_ALGORITHM_WHITELIST_SIGNING.size()])); - - final VerificationResult result = validateSignature(serializedContent, trustedCerts, algConstraints); - - if (!result.isValidSigned()) { - log.info("JWS signature invalide. Stopping authentication process ..."); - log.debug("Received JWS msg: " + serializedContent); - throw new SL20SecurityException("JWS signature invalide."); - - } - - log.debug("SL2.0 commando signature validation sucessfull"); - return result; - - } catch (JoseException | JsonParseException e) { - log.warn("SL2.0 commando signature validation FAILED", e); - throw new SL20SecurityException(new Object[]{e.getMessage()}, e); - - } catch (final IOException e) { - log.warn("Decrypted SL2.0 result can not be parsed.", e); - throw new SLCommandoParserException("Decrypted SL2.0 result can not be parsed", e); - - } - - } - - - @Override - public JsonNode decryptPayload(String compactSerialization) throws SL20Exception { - try { - final JsonWebEncryption receiverJwe = new JsonWebEncryption(); - - //set security constrains - receiverJwe.setAlgorithmConstraints( - new AlgorithmConstraints(ConstraintType.WHITELIST, - SL20Constants.SL20_ALGORITHM_WHITELIST_KEYENCRYPTION.toArray(new String[SL20Constants.SL20_ALGORITHM_WHITELIST_KEYENCRYPTION.size()]))); - receiverJwe.setContentEncryptionAlgorithmConstraints( - new AlgorithmConstraints(ConstraintType.WHITELIST, - SL20Constants.SL20_ALGORITHM_WHITELIST_ENCRYPTION.toArray(new String[SL20Constants.SL20_ALGORITHM_WHITELIST_ENCRYPTION.size()]))); - - //set payload - receiverJwe.setCompactSerialization(compactSerialization); - - - //validate key from header against key from config - final List<X509Certificate> x5cCerts = receiverJwe.getCertificateChainHeaderValue(); - final String x5t256 = receiverJwe.getX509CertSha256ThumbprintHeaderValue(); - if (x5cCerts != null) { - log.debug("Found x509 certificate in JOSE header ... "); - log.trace("Sorting received X509 certificates ... "); - final List<X509Certificate> sortedX5cCerts = X509Utils.sortCertificates(x5cCerts); - - if (!sortedX5cCerts.get(0).equals(encCertChain[0])) { - log.info("Certificate from JOSE header does NOT match encryption certificate"); - log.debug("JOSE certificate: " + sortedX5cCerts.get(0).toString()); - - try { - log.debug("Cert: " + Base64Utils.encode(sortedX5cCerts.get(0).getEncoded())); - } catch (final CertificateEncodingException e) { - e.printStackTrace(); - } - throw new SL20Exception("sl20.05", new Object[]{"Certificate from JOSE header does NOT match encryption certificate"}); - } - - } else if (StringUtils.isNotEmpty(x5t256)) { - log.debug("Found x5t256 fingerprint in JOSE header .... "); - final String certFingerPrint = X509Util.x5tS256(encCertChain[0]); - if (!certFingerPrint.equals(x5t256)) { - log.info("X5t256 from JOSE header does NOT match encryption certificate"); - log.debug("X5t256 from JOSE header: " + x5t256 + " Encrytption cert: " + certFingerPrint); - throw new SL20Exception("sl20.05", new Object[]{"X5t256 from JOSE header does NOT match encryption certificate"}); - - } - - } else { - log.info("Signed SL2.0 response contains NO signature certificate or NO certificate fingerprint"); - throw new SLCommandoParserException("Signed SL2.0 response contains NO signature certificate or NO certificate fingerprint"); - - } - - //set key - receiverJwe.setKey(encPrivKey); - - - //decrypt payload - return mapper.getMapper().readTree(receiverJwe.getPlaintextString()); - - } catch (final JoseException e) { - log.warn("SL2.0 result decryption FAILED", e); - throw new SL20SecurityException(new Object[]{e.getMessage()}, e); - - } catch ( final JsonParseException e) { - log.warn("Decrypted SL2.0 result is NOT a valid JSON.", e); - throw new SLCommandoParserException("Decrypted SL2.0 result is NOT a valid JSON.", e); - - } catch (final IOException e) { - log.warn("Decrypted SL2.0 result can not be parsed.", e); - throw new SLCommandoParserException("Decrypted SL2.0 result can not be parsed", e); - } - - } - - - - @Override - public X509Certificate getEncryptionCertificate() { - //TODO: maybe update after SL2.0 update on encryption certificate parts - if (encCertChain !=null && encCertChain.length > 0) - return encCertChain[0]; - else - return null; - } - - private String getKeyStoreFilePath() throws EAAFConfigurationException, MalformedURLException { - return FileUtils.makeAbsoluteURL( - authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_PATH), - authConfig.getConfigurationRootDirectory()); - } - - private String getKeyStorePassword() { - String value = authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_PASSWORD); - if (value != null) - value = value.trim(); - - return value; - - } - - private String getSigningKeyAlias() { - String value = authConfig.getBasicConfiguration( - Constants.CONFIG_PROP_SECURITY_KEYSTORE_KEY_SIGN_ALIAS).trim(); - if (value != null) - value = value.trim(); - - return value; - } - - private String getSigningKeyPassword() { - String value = authConfig.getBasicConfiguration( - Constants.CONFIG_PROP_SECURITY_KEYSTORE_KEY_SIGN_PASSWORD).trim(); - if (value != null) - value = value.trim(); - - return value; - } - - private String getEncryptionKeyAlias() { - String value = authConfig.getBasicConfiguration( - Constants.CONFIG_PROP_SECURITY_KEYSTORE_KEY_ENCRYPTION_ALIAS).trim(); - if (value != null) - value = value.trim(); - - return value; - } - - private String getEncryptionKeyPassword() { - String value = authConfig.getBasicConfiguration( - Constants.CONFIG_PROP_SECURITY_KEYSTORE_KEY_ENCRYPTION_PASSWORD).trim(); - if (value != null) - value = value.trim(); - - return value; - } - - @Nonnull - private List<X509Certificate> readCertsFromKeyStore(@Nonnull KeyStore keyStore) throws KeyStoreException { - final List<X509Certificate> result = new ArrayList<>(); - - final Enumeration<String> aliases = keyStore.aliases(); - while(aliases.hasMoreElements()) { - final String el = aliases.nextElement(); - log.trace("Process TrustStoreEntry: " + el); - if (keyStore.isCertificateEntry(el)) { - final Certificate cert = keyStore.getCertificate(el); - if (cert != null && cert instanceof X509Certificate) - result.add((X509Certificate) cert); - else - log.info("Can not process entry: " + el + ". Reason: " + cert.toString()); - - } - } - - return Collections.unmodifiableList(result); - } - +public class JsonSecurityUtils implements IJoseTools { + private static final Logger log = LoggerFactory.getLogger(JsonSecurityUtils.class); + + private static final String FRIENDLYNAME_KEYSTORE = "SL2.0 KeyStore"; + private static final String FRIENDLYNAME_TRUSTSTORE = "SL2.0 TrustStore"; + + @Autowired(required = true) + IConfiguration authConfig; + @Autowired(required = true) + EaafKeyStoreFactory keystoreFactory; + + private Pair<KeyStore, Provider> keyStore; + private Pair<KeyStore, Provider> trustStore; + + private static JsonMapper mapper = new JsonMapper(); + + @PostConstruct + protected void initalize() throws SL20Exception { + log.info("Initialize SL2.0 authentication security constrains ... "); + try { + // load KeyStore + final KeyStoreConfiguration keyStoreConfig = buildKeyStoreConfiguration(); + keyStore = keystoreFactory.buildNewKeyStore(keyStoreConfig); + + // load TrustStore + final KeyStoreConfiguration trustStoreConfig = buildTrustStoreConfiguration(); + trustStore = keystoreFactory.buildNewKeyStore(trustStoreConfig); + + // validate KeyStore entries + EaafKeyStoreUtils.getPrivateKeyAndCertificates(keyStore.getFirst(), getSigningKeyAlias(), + getSigningKeyPassword(), true, FRIENDLYNAME_KEYSTORE); + final Pair<Key, X509Certificate[]> encCredentials = + EaafKeyStoreUtils.getPrivateKeyAndCertificates(keyStore.getFirst(), getEncryptionKeyAlias(), + getEncryptionKeyPassword(), false, FRIENDLYNAME_TRUSTSTORE); + if (encCredentials == null) { + log.info("No encryption key for SL2.0 found. End-to-End encryption is not used."); + + } + + // validate TrustStore + final List<X509Certificate> trustedCerts = EaafKeyStoreUtils.readCertsFromKeyStore(trustStore + .getFirst()); + if (trustedCerts.isEmpty()) { + log.info("No certificates in TrustStore: {}. Signature validation will FAIL!", + FRIENDLYNAME_TRUSTSTORE); + + } else { + log.info("Find #{} certificates in TrustStore: {}", + trustedCerts.size(), FRIENDLYNAME_TRUSTSTORE); + + } + + log.info("SL2.0 authentication security constrains initialized."); + + } catch (final RuntimeException e) { + throw e; + + } catch (final Exception e) { + log.error("SL2.0 security constrains initialization FAILED."); + throw new SL20Exception("sl20.11", new Object[] { e.getMessage() }, e); + + } + + } + + @Override + public String createSignature(final String payLoad) throws SlCommandoBuildException { + return createSignature(payLoad, true); + + } + + @Override + public String createSignature(final String payLoad, boolean addFullCertChain) throws SlCommandoBuildException { + try { + final JsonWebSignature jws = new JsonWebSignature(); + + // set payload + jws.setPayload(payLoad); + + // set basic header + jws.setContentTypeHeaderValue(SL20Constants.SL20_CONTENTTYPE_SIGNED_COMMAND); + + // set signing information + jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256); + final Pair<Key, X509Certificate[]> signingCred = EaafKeyStoreUtils.getPrivateKeyAndCertificates( + keyStore.getFirst(), getSigningKeyAlias(), getSigningKeyPassword(), true, FRIENDLYNAME_KEYSTORE); + jws.setKey(signingCred.getFirst()); + + // set special provider if required + if (keyStore.getSecond() != null) { + log.trace("Injecting special Java Security Provider: {}", keyStore.getSecond().getName()); + final ProviderContext providerCtx = new ProviderContext(); + providerCtx.getSuppliedKeyProviderContext().setSignatureProvider( + keyStore.getSecond().getName()); + jws.setProviderContext(providerCtx); + + } + + if (addFullCertChain) { + jws.setCertificateChainHeaderValue(signingCred.getSecond()); + + } + + jws.setX509CertSha256ThumbprintHeaderValue(signingCred.getSecond()[0]); + + return jws.getCompactSerialization(); + + } catch (final JoseException | EaafKeyAccessException e) { + log.warn("Can NOT sign SL2.0 command.", e); + throw new SlCommandoBuildException("Can NOT sign SL2.0 command.", e); + + } + + } + + @Override + public VerificationResult validateSignature(final String serializedContent, final KeyStore trustStore, + final AlgorithmConstraints algconstraints) throws JoseException, IOException, KeyStoreException { + final List<X509Certificate> trustedCertificates = EaafKeyStoreUtils.readCertsFromKeyStore(trustStore); + return validateSignature(serializedContent, trustedCertificates, algconstraints); + + } + + @Override + @NonNull + public VerificationResult validateSignature(@Nonnull final String serializedContent, + @Nonnull final List<X509Certificate> trustedCerts, @Nonnull final AlgorithmConstraints constraints) + throws JoseException, IOException { + final JsonWebSignature jws = new JsonWebSignature(); + // set payload + jws.setCompactSerialization(serializedContent); + + // set security constrains + jws.setAlgorithmConstraints(constraints); + + // load signinc certs + Key selectedKey = null; + final List<X509Certificate> x5cCerts = jws.getCertificateChainHeaderValue(); + final String x5t256 = jws.getX509CertSha256ThumbprintHeaderValue(); + if (x5cCerts != null) { + log.debug("Found x509 certificate in JOSE header ... "); + log.trace("Sorting received X509 certificates ... "); + final List<X509Certificate> sortedX5cCerts = X509Utils.sortCertificates(x5cCerts); + + if (trustedCerts.contains(sortedX5cCerts.get(0))) { + selectedKey = sortedX5cCerts.get(0).getPublicKey(); + + } else { + log.info("Can NOT find JOSE certificate in truststore."); + try { + log.debug("Cert: " + Base64Utils.encodeToString(sortedX5cCerts.get(0).getEncoded())); + + } catch (final CertificateEncodingException e) { + e.printStackTrace(); + + } + + } + + } else if (StringUtils.isNotEmpty(x5t256)) { + log.debug("Found x5t256 fingerprint in JOSE header .... "); + final X509VerificationKeyResolver x509VerificationKeyResolver = new X509VerificationKeyResolver( + trustedCerts); + selectedKey = x509VerificationKeyResolver.resolveKey(jws, Collections.<JsonWebStructure>emptyList()); + + } else { + throw new JoseException("JWS contains NO signature certificate or NO certificate fingerprint"); + + } + + if (selectedKey == null) { + throw new JoseException("Can NOT select verification key for JWS. Signature verification FAILED"); + + } + + // set verification key + jws.setKey(selectedKey); + + // load payLoad + return new VerificationResult(mapper.getMapper().readTree(jws.getPayload()), null, jws.verifySignature()); + + } + + @Override + @Nonnull + public VerificationResult validateSignature(@Nonnull final String serializedContent) throws SL20Exception { + try { + final AlgorithmConstraints algConstraints = new AlgorithmConstraints(ConstraintType.WHITELIST, + SL20Constants.SL20_ALGORITHM_WHITELIST_SIGNING + .toArray(new String[SL20Constants.SL20_ALGORITHM_WHITELIST_SIGNING.size()])); + + final VerificationResult result = + validateSignature(serializedContent, EaafKeyStoreUtils.readCertsFromKeyStore(trustStore.getFirst()), + algConstraints); + + if (!result.isValidSigned()) { + log.info("JWS signature invalide. Stopping authentication process ..."); + log.debug("Received JWS msg: " + serializedContent); + throw new SL20SecurityException("JWS signature invalide."); + + } + + log.debug("SL2.0 commando signature validation sucessfull"); + return result; + + } catch (JoseException | JsonParseException | KeyStoreException e) { + log.warn("SL2.0 commando signature validation FAILED", e); + throw new SL20SecurityException(new Object[] { e.getMessage() }, e); + + } catch (final IOException e) { + log.warn("Decrypted SL2.0 result can not be parsed.", e); + throw new SlCommandoParserException("Decrypted SL2.0 result can not be parsed", e); + + } + + } + + @Override + public JsonNode decryptPayload(final String compactSerialization) throws SL20Exception { + try { + final JsonWebEncryption receiverJwe = new JsonWebEncryption(); + + // set security constrains + receiverJwe.setAlgorithmConstraints( + new AlgorithmConstraints(ConstraintType.WHITELIST, + SL20Constants.SL20_ALGORITHM_WHITELIST_KEYENCRYPTION + .toArray(new String[SL20Constants.SL20_ALGORITHM_WHITELIST_KEYENCRYPTION.size()]))); + receiverJwe.setContentEncryptionAlgorithmConstraints( + new AlgorithmConstraints(ConstraintType.WHITELIST, SL20Constants.SL20_ALGORITHM_WHITELIST_ENCRYPTION + .toArray(new String[SL20Constants.SL20_ALGORITHM_WHITELIST_ENCRYPTION.size()]))); + + // set payload + receiverJwe.setCompactSerialization(compactSerialization); + + final Pair<Key, X509Certificate[]> encryptionCred = EaafKeyStoreUtils.getPrivateKeyAndCertificates( + keyStore.getFirst(), getEncryptionKeyAlias(), getEncryptionKeyPassword(), true, + FRIENDLYNAME_KEYSTORE); + + // validate key from header against key from config + final List<X509Certificate> x5cCerts = receiverJwe.getCertificateChainHeaderValue(); + final String x5t256 = receiverJwe.getX509CertSha256ThumbprintHeaderValue(); + if (x5cCerts != null) { + log.debug("Found x509 certificate in JOSE header ... "); + log.trace("Sorting received X509 certificates ... "); + final List<X509Certificate> sortedX5cCerts = X509Utils.sortCertificates(x5cCerts); + + if (!sortedX5cCerts.get(0).equals(encryptionCred.getSecond()[0])) { + log.info("Certificate from JOSE header does NOT match encryption certificate"); + + try { + + log.debug("JOSE certificate: {}", Base64Utils.encode(sortedX5cCerts.get(0).getEncoded())); + } catch (final CertificateEncodingException e) { + e.printStackTrace(); + } + throw new SL20Exception("sl20.05", + new Object[] { "Certificate from JOSE header does NOT match encryption certificate" }); + } + + } else if (StringUtils.isNotEmpty(x5t256)) { + log.debug("Found x5t256 fingerprint in JOSE header .... "); + final String certFingerPrint = X509Util.x5tS256(encryptionCred.getSecond()[0]); + if (!certFingerPrint.equals(x5t256)) { + log.info("X5t256 from JOSE header does NOT match encryption certificate"); + log.debug("X5t256 from JOSE header: " + x5t256 + " Encrytption cert: " + certFingerPrint); + throw new SL20Exception("sl20.05", + new Object[] { "X5t256 from JOSE header does NOT match encryption certificate" }); + + } + + } else { + log.info("Signed SL2.0 response contains NO signature certificate or NO certificate fingerprint"); + throw new SlCommandoParserException( + "Signed SL2.0 response contains NO signature certificate or NO certificate fingerprint"); + + } + + // set key + receiverJwe.setKey(encryptionCred.getFirst()); + + // decrypt payload + return mapper.getMapper().readTree(receiverJwe.getPlaintextString()); + + } catch (final JoseException | EaafKeyAccessException e) { + log.warn("SL2.0 result decryption FAILED", e); + throw new SL20SecurityException(new Object[] { e.getMessage() }, e); + + } catch (final JsonParseException e) { + log.warn("Decrypted SL2.0 result is NOT a valid JSON.", e); + throw new SlCommandoParserException("Decrypted SL2.0 result is NOT a valid JSON.", e); + + } catch (final IOException e) { + log.warn("Decrypted SL2.0 result can not be parsed.", e); + throw new SlCommandoParserException("Decrypted SL2.0 result can not be parsed", e); + + } + } + + @Override + public X509Certificate getEncryptionCertificate() { + Pair<Key, X509Certificate[]> encryptionCred; + try { + encryptionCred = EaafKeyStoreUtils.getPrivateKeyAndCertificates(keyStore.getFirst(), + getEncryptionKeyAlias(), getEncryptionKeyPassword(), false, FRIENDLYNAME_KEYSTORE); + if (encryptionCred != null && encryptionCred.getSecond().length > 0) { + return encryptionCred.getSecond()[0]; + + } + + } catch (final EaafKeyAccessException e) { + log.trace("Exception is skipped because Encryption is not mandatory on this level", e); + + } + + return null; + + } + + private KeyStoreConfiguration buildKeyStoreConfiguration() throws EaafConfigurationException { + final KeyStoreConfiguration config = new KeyStoreConfiguration(); + config.setFriendlyName(FRIENDLYNAME_KEYSTORE); + + config.setKeyStoreType(authConfig.getBasicConfiguration( + authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_TYPE), + KeyStoreType.JKS.getKeyStoreType())); + config.setKeyStoreName( + authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_NAME)); + config.setSoftKeyStoreFilePath( + authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_PATH)); + config.setSoftKeyStorePassword( + authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_PASSWORD)); + + // validate configuration state + config.validate(); + + return config; + + } + + private KeyStoreConfiguration buildTrustStoreConfiguration() throws EaafConfigurationException { + final KeyStoreConfiguration config = new KeyStoreConfiguration(); + config.setFriendlyName(FRIENDLYNAME_TRUSTSTORE); + + config.setKeyStoreType(authConfig.getBasicConfiguration( + authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_TRUSTSTORE_TYPE), + KeyStoreType.JKS.getKeyStoreType())); + config.setKeyStoreName( + authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_TRUSTSTORE_NAME)); + config.setSoftKeyStoreFilePath( + authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_TRUSTSTORE_PATH)); + config.setSoftKeyStorePassword( + authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_TRUSTSTORE_PASSWORD)); + + // validate configuration state + config.validate(); + + return config; + } + + private String getSigningKeyAlias() { + String value = authConfig.getBasicConfiguration(Constants.CONFIG_PROP_SECURITY_KEYSTORE_KEY_SIGN_ALIAS); + if (value != null) { + value = value.trim(); + } + + return value; + } + + private char[] getSigningKeyPassword() { + final String value = authConfig.getBasicConfiguration( + Constants.CONFIG_PROP_SECURITY_KEYSTORE_KEY_SIGN_PASSWORD); + if (value != null) { + return value.trim().toCharArray(); + } + + return null; + } + + private String getEncryptionKeyAlias() { + String value = authConfig.getBasicConfiguration( + Constants.CONFIG_PROP_SECURITY_KEYSTORE_KEY_ENCRYPTION_ALIAS); + if (value != null) { + value = value.trim(); + } + + return value; + } + + private char[] getEncryptionKeyPassword() { + final String value = authConfig.getBasicConfiguration( + Constants.CONFIG_PROP_SECURITY_KEYSTORE_KEY_ENCRYPTION_PASSWORD); + if (value != null) { + return value.trim().toCharArray(); + } + + return null; + } + } diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20Constants.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20Constants.java index 06c36cff..01316b9b 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20Constants.java +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20Constants.java @@ -1,6 +1,7 @@ package at.gv.egiz.eaaf.modules.auth.sl20.utils; import java.util.Arrays; +import java.util.Collections; import java.util.List; import org.jose4j.jwe.ContentEncryptionAlgorithmIdentifiers; @@ -8,234 +9,255 @@ import org.jose4j.jwe.KeyManagementAlgorithmIdentifiers; import org.jose4j.jws.AlgorithmIdentifiers; public class SL20Constants { - public static final int CURRENT_SL20_VERSION = 10; - - //http binding parameters - public static final String PARAM_SL20_REQ_COMMAND_PARAM = "slcommand"; - public static final String PARAM_SL20_REQ_COMMAND_PARAM_OLD = "sl2command"; - - public static final String PARAM_SL20_REQ_ICP_RETURN_URL_PARAM = "slIPCReturnUrl"; - public static final String PARAM_SL20_REQ_TRANSACTIONID = "slTransactionID"; - - public static final String HTTP_HEADER_SL20_CLIENT_TYPE = "SL2ClientType"; - public static final String HTTP_HEADER_SL20_VDA_TYPE = "X-MOA-VDA"; - public static final String HTTP_HEADER_VALUE_NATIVE = "nativeApp"; - - public static final String HTTP_HEADER_SL20_RESP = "X-SL20Operation"; - - - //******************************************************************************************* - //JSON signing and encryption headers - public static final String JSON_ALGORITHM = "alg"; - public static final String JSON_CONTENTTYPE = "cty"; - public static final String JSON_X509_CERTIFICATE = "x5c"; - public static final String JSON_X509_FINGERPRINT = "x5t#S256"; - public static final String JSON_ENCRYPTION_PAYLOAD = "enc"; - - public static final String JSON_ALGORITHM_SIGNING_RS256 = AlgorithmIdentifiers.RSA_USING_SHA256; - public static final String JSON_ALGORITHM_SIGNING_RS512 = AlgorithmIdentifiers.RSA_USING_SHA512; - public static final String JSON_ALGORITHM_SIGNING_ES256 = AlgorithmIdentifiers.ECDSA_USING_P256_CURVE_AND_SHA256; - public static final String JSON_ALGORITHM_SIGNING_ES512 = AlgorithmIdentifiers.ECDSA_USING_P521_CURVE_AND_SHA512; - public static final String JSON_ALGORITHM_SIGNING_PS256 = AlgorithmIdentifiers.RSA_PSS_USING_SHA256; - public static final String JSON_ALGORITHM_SIGNING_PS512 = AlgorithmIdentifiers.RSA_PSS_USING_SHA512; - - public static final List<String> SL20_ALGORITHM_WHITELIST_SIGNING = Arrays.asList( - JSON_ALGORITHM_SIGNING_RS256, - JSON_ALGORITHM_SIGNING_RS512, - JSON_ALGORITHM_SIGNING_ES256, - JSON_ALGORITHM_SIGNING_ES512, - JSON_ALGORITHM_SIGNING_PS256, - JSON_ALGORITHM_SIGNING_PS512 - ); - - public static final String JSON_ALGORITHM_ENC_KEY_RSAOAEP = KeyManagementAlgorithmIdentifiers.RSA_OAEP; - public static final String JSON_ALGORITHM_ENC_KEY_RSAOAEP256 = KeyManagementAlgorithmIdentifiers.RSA_OAEP_256; - - public static final List<String> SL20_ALGORITHM_WHITELIST_KEYENCRYPTION = Arrays.asList( - JSON_ALGORITHM_ENC_KEY_RSAOAEP, - JSON_ALGORITHM_ENC_KEY_RSAOAEP256 - ); - - public static final String JSON_ALGORITHM_ENC_PAYLOAD_A128CBCHS256 = ContentEncryptionAlgorithmIdentifiers.AES_128_CBC_HMAC_SHA_256; - public static final String JSON_ALGORITHM_ENC_PAYLOAD_A256CBCHS512 = ContentEncryptionAlgorithmIdentifiers.AES_256_CBC_HMAC_SHA_512; - public static final String JSON_ALGORITHM_ENC_PAYLOAD_A128GCM = ContentEncryptionAlgorithmIdentifiers.AES_128_GCM; - public static final String JSON_ALGORITHM_ENC_PAYLOAD_A256GCM = ContentEncryptionAlgorithmIdentifiers.AES_256_GCM; - - public static final List<String> SL20_ALGORITHM_WHITELIST_ENCRYPTION = Arrays.asList( - JSON_ALGORITHM_ENC_PAYLOAD_A128CBCHS256, - JSON_ALGORITHM_ENC_PAYLOAD_A256CBCHS512, - JSON_ALGORITHM_ENC_PAYLOAD_A128GCM, - JSON_ALGORITHM_ENC_PAYLOAD_A256GCM - ); - - - //********************************************************************************************* - //Object identifier for generic transport container - public static final String SL20_CONTENTTYPE_SIGNED_COMMAND ="application/sl2.0;command"; - public static final String SL20_CONTENTTYPE_ENCRYPTED_RESULT ="application/sl2.0;result"; - - public static final String SL20_VERSION = "v"; - public static final String SL20_REQID = "reqID"; - public static final String SL20_RESPID = "respID"; - public static final String SL20_INRESPTO = "inResponseTo"; - public static final String SL20_TRANSACTIONID = "transactionID"; - public static final String SL20_PAYLOAD = "payload"; - public static final String SL20_SIGNEDPAYLOAD = "signedPayload"; - - //Generic Object identifier for commands - public static final String SL20_COMMAND_CONTAINER_NAME = "name"; - public static final String SL20_COMMAND_CONTAINER_PARAMS = "params"; - public static final String SL20_COMMAND_CONTAINER_RESULT = "result"; - public static final String SL20_COMMAND_CONTAINER_ENCRYPTEDRESULT = "encryptedResult"; - - //COMMAND Object identifier - public static final String SL20_COMMAND_IDENTIFIER_REDIRECT = "redirect"; - public static final String SL20_COMMAND_IDENTIFIER_CALL = "call"; - public static final String SL20_COMMAND_IDENTIFIER_ERROR = "error"; - @Deprecated public static final String SL20_COMMAND_IDENTIFIER_QUALIFIEDEID = "qualifiedeID"; - public static final String SL20_COMMAND_IDENTIFIER_QUALIFIEDEIDCONSENT = "qualifiedEIDConsent"; - //public static final String SL20_COMMAND_IDENTIFIER_QUALIFIEDSIG = "qualifiedSig"; - - public static final String SL20_COMMAND_IDENTIFIER_GETCERTIFICATE = "getCertificate"; - public static final String SL20_COMMAND_IDENTIFIER_CREATE_SIG_CADES = "createCAdES"; - - - public static final String SL20_COMMAND_IDENTIFIER_BINDING_CREATE_KEY = "createBindingKey"; - public static final String SL20_COMMAND_IDENTIFIER_BINDING_STORE_CERT = "storeBindingCert"; - - public static final String SL20_COMMAND_IDENTIFIER_AUTH_IDANDPASSWORD = "idAndPassword"; - public static final String SL20_COMMAND_IDENTIFIER_AUTH_JWSTOKENFACTOR = "jwsTokenAuth"; - public static final String SL20_COMMAND_IDENTIFIER_AUTH_QRCODEFACTOR = "qrCodeFactor"; - - //*****COMMAND parameter identifier****** - //general Identifier - public static final String SL20_COMMAND_PARAM_GENERAL_REQPARAMETER_VALUE = "value"; - public static final String SL20_COMMAND_PARAM_GENERAL_REQPARAMETER_KEY = "key"; - public static final String SL20_COMMAND_PARAM_GENERAL_DATAURL = "dataUrl"; - public static final String SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONCERTIFICATE = "x5cEnc"; - public static final String SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONJWK = "jwkEnc"; - - //Redirect command - public static final String SL20_COMMAND_PARAM_GENERAL_REDIRECT_URL = "url"; - public static final String SL20_COMMAND_PARAM_GENERAL_REDIRECT_COMMAND = "command"; - public static final String SL20_COMMAND_PARAM_GENERAL_REDIRECT_SIGNEDCOMMAND = "signedCommand"; - public static final String SL20_COMMAND_PARAM_GENERAL_REDIRECT_IPCREDIRECT = "IPCRedirect"; - - //Call command - public static final String SL20_COMMAND_PARAM_GENERAL_CALL_URL = SL20_COMMAND_PARAM_GENERAL_REDIRECT_URL; - public static final String SL20_COMMAND_PARAM_GENERAL_CALL_METHOD = "method"; - public static final String SL20_COMMAND_PARAM_GENERAL_CALL_METHOD_GET = "get"; - public static final String SL20_COMMAND_PARAM_GENERAL_CALL_METHOD_POST = "post"; - public static final String SL20_COMMAND_PARAM_GENERAL_CALL_INCLUDETRANSACTIONID = "includeTransactionID"; - public static final String SL20_COMMAND_PARAM_GENERAL_CALL_REQPARAMETER = "reqParams"; - - //error command - public static final String SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORCODE = "errorCode"; - public static final String SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORMESSAGE = "errorMessage"; - - //qualified eID command - @Deprecated public static final String SL20_COMMAND_PARAM_EID_AUTHBLOCKID = "authBlockTemplateID"; - public static final String SL20_COMMAND_PARAM_EID_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL; - @Deprecated public static final String SL20_COMMAND_PARAM_EID_ATTRIBUTES = "attributes"; - @Deprecated public static final String SL20_COMMAND_PARAM_EID_ATTRIBUTES_MANDATEREFVALUE = "MANDATE-REFERENCE-VALUE"; - @Deprecated public static final String SL20_COMMAND_PARAM_EID_ATTRIBUTES_SPUNIQUEID = "SP-UNIQUEID"; - @Deprecated public static final String SL20_COMMAND_PARAM_EID_ATTRIBUTES_SPFRIENDLYNAME = "SP-FRIENDLYNAME"; - @Deprecated public static final String SL20_COMMAND_PARAM_EID_ATTRIBUTES_SPCOUNTRYCODE = "SP-COUNTRYCODE"; - public static final String SL20_COMMAND_PARAM_EID_X5CENC = SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONCERTIFICATE; - public static final String SL20_COMMAND_PARAM_EID_JWKCENC = SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONJWK; - @Deprecated public static final String SL20_COMMAND_PARAM_EID_RESULT_IDL = "EID-IDENTITY-LINK"; - @Deprecated public static final String SL20_COMMAND_PARAM_EID_RESULT_AUTHBLOCK = "EID-AUTH-BLOCK"; - public static final String SL20_COMMAND_PARAM_EID_RESULT_CCSURL = "EID-CCS-URL"; - @Deprecated public static final String SL20_COMMAND_PARAM_EID_RESULT_LOA = "EID-CITIZEN-QAA-LEVEL"; - - public static final String SL20_COMMAND_PARAM_EID_CONSENTTEMPLATEID = "consentTemplateID"; - public static final String SL20_COMMAND_PARAM_EID_CONSENT = "consent"; - public static final String SL20_COMMAND_PARAM_EID_CONSENT_RESULT_MDS = "MDS"; - public static final String SL20_COMMAND_PARAM_EID_CONSENT_RESULT_VSZ = "vSZ"; - public static final String SL20_COMMAND_PARAM_EID_CONSENT_RESULT_SIGNEDCONSENT = "signedConsent"; - - //qualified Signature comamnd -// public static final String SL20_COMMAND_PARAM_QUALSIG_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL; -// public static final String SL20_COMMAND_PARAM_QUALSIG_X5CENC = SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONCERTIFICATE; - - - //getCertificate - public static final String SL20_COMMAND_PARAM_GETCERTIFICATE_KEYID = "keyId"; - public static final String SL20_COMMAND_PARAM_GETCERTIFICATE_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL; - public static final String SL20_COMMAND_PARAM_GETCERTIFICATE_X5CENC = SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONCERTIFICATE; - public static final String SL20_COMMAND_PARAM_GETCERTIFICATE_JWKCENC = SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONJWK; - public static final String SL20_COMMAND_PARAM_GETCERTIFICATE_RESULT_CERTIFICATE = "x5c"; - - //createCAdES Signture - public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_KEYID = "keyId"; - public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CONTENT = "content"; - public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_MIMETYPE = "mimeType"; - public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_PADES_COMBATIBILTY = "padesComatibility"; - public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_EXCLUDEBYTERANGE = "excludedByteRange"; - public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CADESLEVEL = "cadesLevel"; - public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL; - public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_X5CENC = SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONCERTIFICATE; - public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_JWKCENC = SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONJWK; - public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_RESULT_SIGNATURE = "signature"; - - public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CADESLEVEL_BASIC = "cAdES"; - public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CADESLEVEL_T = "cAdES-T"; - public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CADESLEVEL_C = "cAdES-C"; - public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CADESLEVEL_X = "cAdES-X"; - public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CADESLEVEL_XL = "cAdES-X-L"; - public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CADESLEVEL_A = "cAdES-A"; - - - - //create binding key command - public static final String SL20_COMMAND_PARAM_BINDING_CREATE_KONTOID = "kontoID"; - public static final String SL20_COMMAND_PARAM_BINDING_CREATE_SN = "SN"; - public static final String SL20_COMMAND_PARAM_BINDING_CREATE_KEYLENGTH = "keyLength"; - public static final String SL20_COMMAND_PARAM_BINDING_CREATE_KEYALG = "keyAlg"; - public static final String SL20_COMMAND_PARAM_BINDING_CREATE_POLICIES = "policies"; - public static final String SL20_COMMAND_PARAM_BINDING_CREATE_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL; - public static final String SL20_COMMAND_PARAM_BINDING_CREATE_X5CVDATRUST = "x5cVdaTrust"; - public static final String SL20_COMMAND_PARAM_BINDING_CREATE_REQUESTUSERPASSWORD = "reqUserPassword"; - public static final String SL20_COMMAND_PARAM_BINDING_CREATE_X5CENC = SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONCERTIFICATE; - - public static final String SL20_COMMAND_PARAM_BINDING_CREATE_KEYALG_RSA = "RSA"; - public static final String SL20_COMMAND_PARAM_BINDING_CREATE_KEYALG_SECPR256R1 = "secp256r1"; - - public static final String SL20_COMMAND_PARAM_BINDING_CREATE_POLICIES_LIFETIME = "lifeTime"; - public static final String SL20_COMMAND_PARAM_BINDING_CREATE_POLICIES_USESECUREELEMENT = "useSecureElement"; - public static final String SL20_COMMAND_PARAM_BINDING_CREATE_POLICIES_KEYTIMEOUT = "keyTimeout"; - public static final String SL20_COMMAND_PARAM_BINDING_CREATE_POLICIES_NEEDUSERAUTH = "needUserAuth"; - - public static final String SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_APPID = "appID"; - public static final String SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_CSR = "csr"; - public static final String SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_KEYATTESTATIONZERTIFICATE = "attCert"; - public static final String SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_USERPASSWORD = "encodedPass"; - - - //store binding certificate command - public static final String SL20_COMMAND_PARAM_BINDING_STORE_CERTIFICATE = "x5c"; - public static final String SL20_COMMAND_PARAM_BINDING_STORE_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL; - public static final String SL20_COMMAND_PARAM_BINDING_STORE_RESULT_SUCESS = "success"; - public static final String SL20_COMMAND_PARAM_BINDING_STORE_RESULT_SUCESS_VALUE = "OK"; - - // Username and password authentication - public static final String SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_KEYALG = "keyAlg"; - public static final String SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_KEYALG_VALUE_PLAIN = "plain"; - public static final String SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_KEYALG_VALUE_PBKDF2 = "PBKDF2"; - public static final String SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL; - public static final String SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_X5CENC = SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONCERTIFICATE; - public static final String SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_RESULT_KONTOID = SL20_COMMAND_PARAM_BINDING_CREATE_KONTOID; - public static final String SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_RESULT_USERPASSWORD = SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_USERPASSWORD; - - //JWS Token authentication - public static final String SL20_COMMAND_PARAM_AUTH_JWSTOKEN_NONCE = "nonce"; - public static final String SL20_COMMAND_PARAM_AUTH_JWSTOKEN_DISPLAYDATA = "displayData"; - public static final String SL20_COMMAND_PARAM_AUTH_JWSTOKEN_DISPLAYURL = "displayUrl"; - public static final String SL20_COMMAND_PARAM_AUTH_JWSTOKEN_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL; - public static final String SL20_COMMAND_PARAM_AUTH_JWSTOKEN_RESULT_NONCE = SL20_COMMAND_PARAM_AUTH_JWSTOKEN_NONCE; - - //QR-Code authentication - public static final String SL20_COMMAND_PARAM_AUTH_QRCODE_QRCODE = "qrCode"; - public static final String SL20_COMMAND_PARAM_AUTH_QRCODE_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL; - + public static final int CURRENT_SL20_VERSION = 10; + + // http binding parameters + public static final String PARAM_SL20_REQ_COMMAND_PARAM = "slcommand"; + public static final String PARAM_SL20_REQ_COMMAND_PARAM_OLD = "sl2command"; + + public static final String PARAM_SL20_REQ_ICP_RETURN_URL_PARAM = "slIPCReturnUrl"; + public static final String PARAM_SL20_REQ_TRANSACTIONID = "slTransactionID"; + + public static final String HTTP_HEADER_SL20_CLIENT_TYPE = "SL2ClientType"; + public static final String HTTP_HEADER_SL20_VDA_TYPE = "X-MOA-VDA"; + public static final String HTTP_HEADER_VALUE_NATIVE = "nativeApp"; + + public static final String HTTP_HEADER_SL20_RESP = "X-SL20Operation"; + + // ******************************************************************************************* + // JSON signing and encryption headers + public static final String JSON_ALGORITHM = "alg"; + public static final String JSON_CONTENTTYPE = "cty"; + public static final String JSON_X509_CERTIFICATE = "x5c"; + public static final String JSON_X509_FINGERPRINT = "x5t#S256"; + public static final String JSON_ENCRYPTION_PAYLOAD = "enc"; + + public static final String JSON_ALGORITHM_SIGNING_RS256 = AlgorithmIdentifiers.RSA_USING_SHA256; + public static final String JSON_ALGORITHM_SIGNING_RS512 = AlgorithmIdentifiers.RSA_USING_SHA512; + public static final String JSON_ALGORITHM_SIGNING_ES256 = + AlgorithmIdentifiers.ECDSA_USING_P256_CURVE_AND_SHA256; + public static final String JSON_ALGORITHM_SIGNING_ES512 = + AlgorithmIdentifiers.ECDSA_USING_P521_CURVE_AND_SHA512; + public static final String JSON_ALGORITHM_SIGNING_PS256 = AlgorithmIdentifiers.RSA_PSS_USING_SHA256; + public static final String JSON_ALGORITHM_SIGNING_PS512 = AlgorithmIdentifiers.RSA_PSS_USING_SHA512; + + public static final List<String> SL20_ALGORITHM_WHITELIST_SIGNING = Collections.unmodifiableList( + Arrays.asList(JSON_ALGORITHM_SIGNING_RS256, JSON_ALGORITHM_SIGNING_RS512, JSON_ALGORITHM_SIGNING_ES256, + JSON_ALGORITHM_SIGNING_ES512, JSON_ALGORITHM_SIGNING_PS256, JSON_ALGORITHM_SIGNING_PS512)); + + public static final String JSON_ALGORITHM_ENC_KEY_RSAOAEP = KeyManagementAlgorithmIdentifiers.RSA_OAEP; + public static final String JSON_ALGORITHM_ENC_KEY_RSAOAEP256 = + KeyManagementAlgorithmIdentifiers.RSA_OAEP_256; + + public static final List<String> SL20_ALGORITHM_WHITELIST_KEYENCRYPTION = Collections + .unmodifiableList(Arrays.asList(JSON_ALGORITHM_ENC_KEY_RSAOAEP, JSON_ALGORITHM_ENC_KEY_RSAOAEP256)); + + public static final String JSON_ALGORITHM_ENC_PAYLOAD_A128CBCHS256 = + ContentEncryptionAlgorithmIdentifiers.AES_128_CBC_HMAC_SHA_256; + public static final String JSON_ALGORITHM_ENC_PAYLOAD_A256CBCHS512 = + ContentEncryptionAlgorithmIdentifiers.AES_256_CBC_HMAC_SHA_512; + public static final String JSON_ALGORITHM_ENC_PAYLOAD_A128GCM = + ContentEncryptionAlgorithmIdentifiers.AES_128_GCM; + public static final String JSON_ALGORITHM_ENC_PAYLOAD_A256GCM = + ContentEncryptionAlgorithmIdentifiers.AES_256_GCM; + + public static final List<String> SL20_ALGORITHM_WHITELIST_ENCRYPTION = Collections + .unmodifiableList(Arrays.asList(JSON_ALGORITHM_ENC_PAYLOAD_A128CBCHS256, + JSON_ALGORITHM_ENC_PAYLOAD_A256CBCHS512, + JSON_ALGORITHM_ENC_PAYLOAD_A128GCM, JSON_ALGORITHM_ENC_PAYLOAD_A256GCM)); + + // ********************************************************************************************* + // Object identifier for generic transport container + public static final String SL20_CONTENTTYPE_SIGNED_COMMAND = "application/sl2.0;command"; + public static final String SL20_CONTENTTYPE_ENCRYPTED_RESULT = "application/sl2.0;result"; + + public static final String SL20_VERSION = "v"; + public static final String SL20_REQID = "reqID"; + public static final String SL20_RESPID = "respID"; + public static final String SL20_INRESPTO = "inResponseTo"; + public static final String SL20_TRANSACTIONID = "transactionID"; + public static final String SL20_PAYLOAD = "payload"; + public static final String SL20_SIGNEDPAYLOAD = "signedPayload"; + + // Generic Object identifier for commands + public static final String SL20_COMMAND_CONTAINER_NAME = "name"; + public static final String SL20_COMMAND_CONTAINER_PARAMS = "params"; + public static final String SL20_COMMAND_CONTAINER_RESULT = "result"; + public static final String SL20_COMMAND_CONTAINER_ENCRYPTEDRESULT = "encryptedResult"; + + // COMMAND Object identifier + public static final String SL20_COMMAND_IDENTIFIER_REDIRECT = "redirect"; + public static final String SL20_COMMAND_IDENTIFIER_CALL = "call"; + public static final String SL20_COMMAND_IDENTIFIER_ERROR = "error"; + @Deprecated + public static final String SL20_COMMAND_IDENTIFIER_QUALIFIEDEID = "qualifiedeID"; + public static final String SL20_COMMAND_IDENTIFIER_QUALIFIEDEIDCONSENT = "qualifiedEIDConsent"; + // public static final String SL20_COMMAND_IDENTIFIER_QUALIFIEDSIG = + // "qualifiedSig"; + + public static final String SL20_COMMAND_IDENTIFIER_GETCERTIFICATE = "getCertificate"; + public static final String SL20_COMMAND_IDENTIFIER_CREATE_SIG_CADES = "createCAdES"; + + public static final String SL20_COMMAND_IDENTIFIER_BINDING_CREATE_KEY = "createBindingKey"; + public static final String SL20_COMMAND_IDENTIFIER_BINDING_STORE_CERT = "storeBindingCert"; + + public static final String SL20_COMMAND_IDENTIFIER_AUTH_IDANDPASSWORD = "idAndPassword"; + public static final String SL20_COMMAND_IDENTIFIER_AUTH_JWSTOKENFACTOR = "jwsTokenAuth"; + public static final String SL20_COMMAND_IDENTIFIER_AUTH_QRCODEFACTOR = "qrCodeFactor"; + + // *****COMMAND parameter identifier****** + // general Identifier + public static final String SL20_COMMAND_PARAM_GENERAL_REQPARAMETER_VALUE = "value"; + public static final String SL20_COMMAND_PARAM_GENERAL_REQPARAMETER_KEY = "key"; + public static final String SL20_COMMAND_PARAM_GENERAL_DATAURL = "dataUrl"; + public static final String SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONCERTIFICATE = "x5cEnc"; + public static final String SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONJWK = "jwkEnc"; + + // Redirect command + public static final String SL20_COMMAND_PARAM_GENERAL_REDIRECT_URL = "url"; + public static final String SL20_COMMAND_PARAM_GENERAL_REDIRECT_COMMAND = "command"; + public static final String SL20_COMMAND_PARAM_GENERAL_REDIRECT_SIGNEDCOMMAND = "signedCommand"; + public static final String SL20_COMMAND_PARAM_GENERAL_REDIRECT_IPCREDIRECT = "IPCRedirect"; + + // Call command + public static final String SL20_COMMAND_PARAM_GENERAL_CALL_URL = SL20_COMMAND_PARAM_GENERAL_REDIRECT_URL; + public static final String SL20_COMMAND_PARAM_GENERAL_CALL_METHOD = "method"; + public static final String SL20_COMMAND_PARAM_GENERAL_CALL_METHOD_GET = "get"; + public static final String SL20_COMMAND_PARAM_GENERAL_CALL_METHOD_POST = "post"; + public static final String SL20_COMMAND_PARAM_GENERAL_CALL_INCLUDETRANSACTIONID = "includeTransactionID"; + public static final String SL20_COMMAND_PARAM_GENERAL_CALL_REQPARAMETER = "reqParams"; + + // error command + public static final String SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORCODE = "errorCode"; + public static final String SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORMESSAGE = "errorMessage"; + + // qualified eID command + @Deprecated + public static final String SL20_COMMAND_PARAM_EID_AUTHBLOCKID = "authBlockTemplateID"; + public static final String SL20_COMMAND_PARAM_EID_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL; + @Deprecated + public static final String SL20_COMMAND_PARAM_EID_ATTRIBUTES = "attributes"; + @Deprecated + public static final String SL20_COMMAND_PARAM_EID_ATTRIBUTES_MANDATEREFVALUE = "MANDATE-REFERENCE-VALUE"; + @Deprecated + public static final String SL20_COMMAND_PARAM_EID_ATTRIBUTES_SPUNIQUEID = "SP-UNIQUEID"; + @Deprecated + public static final String SL20_COMMAND_PARAM_EID_ATTRIBUTES_SPFRIENDLYNAME = "SP-FRIENDLYNAME"; + @Deprecated + public static final String SL20_COMMAND_PARAM_EID_ATTRIBUTES_SPCOUNTRYCODE = "SP-COUNTRYCODE"; + public static final String SL20_COMMAND_PARAM_EID_X5CENC = + SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONCERTIFICATE; + public static final String SL20_COMMAND_PARAM_EID_JWKCENC = + SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONJWK; + @Deprecated + public static final String SL20_COMMAND_PARAM_EID_RESULT_IDL = "EID-IDENTITY-LINK"; + @Deprecated + public static final String SL20_COMMAND_PARAM_EID_RESULT_AUTHBLOCK = "EID-AUTH-BLOCK"; + public static final String SL20_COMMAND_PARAM_EID_RESULT_CCSURL = "EID-CCS-URL"; + @Deprecated + public static final String SL20_COMMAND_PARAM_EID_RESULT_LOA = "EID-CITIZEN-QAA-LEVEL"; + + public static final String SL20_COMMAND_PARAM_EID_CONSENTTEMPLATEID = "consentTemplateID"; + public static final String SL20_COMMAND_PARAM_EID_CONSENT = "consent"; + @Deprecated + public static final String SL20_COMMAND_PARAM_EID_CONSENT_RESULT_MDS = "MDS"; + @Deprecated + public static final String SL20_COMMAND_PARAM_EID_CONSENT_RESULT_VSZ = "vSZ"; + public static final String SL20_COMMAND_PARAM_EID_CONSENT_RESULT_SIGNEDCONSENT = "signedConsent"; + public static final String SL20_COMMAND_PARAM_EID_CONSENT_RESULT_QCBIND = "qcBind"; + + // qualified Signature comamnd + // public static final String SL20_COMMAND_PARAM_QUALSIG_DATAURL = + // SL20_COMMAND_PARAM_GENERAL_DATAURL; + // public static final String SL20_COMMAND_PARAM_QUALSIG_X5CENC = + // SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONCERTIFICATE; + + // getCertificate + public static final String SL20_COMMAND_PARAM_GETCERTIFICATE_KEYID = "keyId"; + public static final String SL20_COMMAND_PARAM_GETCERTIFICATE_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL; + public static final String SL20_COMMAND_PARAM_GETCERTIFICATE_X5CENC = + SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONCERTIFICATE; + public static final String SL20_COMMAND_PARAM_GETCERTIFICATE_JWKCENC = + SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONJWK; + public static final String SL20_COMMAND_PARAM_GETCERTIFICATE_RESULT_CERTIFICATE = "x5c"; + + // createCAdES Signture + public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_KEYID = "keyId"; + public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CONTENT = "content"; + public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_MIMETYPE = "mimeType"; + public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_PADES_COMBATIBILTY = "padesComatibility"; + public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_EXCLUDEBYTERANGE = "excludedByteRange"; + public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CADESLEVEL = "cadesLevel"; + public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL; + public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_X5CENC = + SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONCERTIFICATE; + public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_JWKCENC = + SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONJWK; + public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_RESULT_SIGNATURE = "signature"; + + public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CADESLEVEL_BASIC = "cAdES"; + public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CADESLEVEL_T = "cAdES-T"; + public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CADESLEVEL_C = "cAdES-C"; + public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CADESLEVEL_X = "cAdES-X"; + public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CADESLEVEL_XL = "cAdES-X-L"; + public static final String SL20_COMMAND_PARAM_CREATE_SIG_CADES_CADESLEVEL_A = "cAdES-A"; + + // create binding key command + public static final String SL20_COMMAND_PARAM_BINDING_CREATE_KONTOID = "kontoID"; + public static final String SL20_COMMAND_PARAM_BINDING_CREATE_SN = "SN"; + public static final String SL20_COMMAND_PARAM_BINDING_CREATE_KEYLENGTH = "keyLength"; + public static final String SL20_COMMAND_PARAM_BINDING_CREATE_KEYALG = "keyAlg"; + public static final String SL20_COMMAND_PARAM_BINDING_CREATE_POLICIES = "policies"; + public static final String SL20_COMMAND_PARAM_BINDING_CREATE_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL; + public static final String SL20_COMMAND_PARAM_BINDING_CREATE_X5CVDATRUST = "x5cVdaTrust"; + public static final String SL20_COMMAND_PARAM_BINDING_CREATE_REQUESTUSERPASSWORD = "reqUserPassword"; + public static final String SL20_COMMAND_PARAM_BINDING_CREATE_X5CENC = + SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONCERTIFICATE; + + public static final String SL20_COMMAND_PARAM_BINDING_CREATE_KEYALG_RSA = "RSA"; + public static final String SL20_COMMAND_PARAM_BINDING_CREATE_KEYALG_SECPR256R1 = "secp256r1"; + + public static final String SL20_COMMAND_PARAM_BINDING_CREATE_POLICIES_LIFETIME = "lifeTime"; + public static final String SL20_COMMAND_PARAM_BINDING_CREATE_POLICIES_USESECUREELEMENT = "useSecureElement"; + public static final String SL20_COMMAND_PARAM_BINDING_CREATE_POLICIES_KEYTIMEOUT = "keyTimeout"; + public static final String SL20_COMMAND_PARAM_BINDING_CREATE_POLICIES_NEEDUSERAUTH = "needUserAuth"; + + public static final String SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_APPID = "appID"; + public static final String SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_CSR = "csr"; + public static final String SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_KEYATTESTATIONZERTIFICATE = "attCert"; + public static final String SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_USERPASSWORD = "encodedPass"; + + // store binding certificate command + public static final String SL20_COMMAND_PARAM_BINDING_STORE_CERTIFICATE = "x5c"; + public static final String SL20_COMMAND_PARAM_BINDING_STORE_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL; + public static final String SL20_COMMAND_PARAM_BINDING_STORE_RESULT_SUCESS = "success"; + public static final String SL20_COMMAND_PARAM_BINDING_STORE_RESULT_SUCESS_VALUE = "OK"; + + // Username and password authentication + public static final String SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_KEYALG = "keyAlg"; + public static final String SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_KEYALG_VALUE_PLAIN = "plain"; + public static final String SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_KEYALG_VALUE_PBKDF2 = "PBKDF2"; + public static final String SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_DATAURL = + SL20_COMMAND_PARAM_GENERAL_DATAURL; + public static final String SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_X5CENC = + SL20_COMMAND_PARAM_GENERAL_RESPONSEENCRYPTIONCERTIFICATE; + public static final String SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_RESULT_KONTOID = + SL20_COMMAND_PARAM_BINDING_CREATE_KONTOID; + public static final String SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_RESULT_USERPASSWORD = + SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_USERPASSWORD; + + // JWS Token authentication + public static final String SL20_COMMAND_PARAM_AUTH_JWSTOKEN_NONCE = "nonce"; + public static final String SL20_COMMAND_PARAM_AUTH_JWSTOKEN_DISPLAYDATA = "displayData"; + public static final String SL20_COMMAND_PARAM_AUTH_JWSTOKEN_DISPLAYURL = "displayUrl"; + public static final String SL20_COMMAND_PARAM_AUTH_JWSTOKEN_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL; + public static final String SL20_COMMAND_PARAM_AUTH_JWSTOKEN_RESULT_NONCE = + SL20_COMMAND_PARAM_AUTH_JWSTOKEN_NONCE; + + // QR-Code authentication + public static final String SL20_COMMAND_PARAM_AUTH_QRCODE_QRCODE = "qrCode"; + public static final String SL20_COMMAND_PARAM_AUTH_QRCODE_DATAURL = SL20_COMMAND_PARAM_GENERAL_DATAURL; + + + } diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20HttpBindingUtils.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20HttpBindingUtils.java index 4d8cabb7..1d7c9646 100644 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20HttpBindingUtils.java +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20HttpBindingUtils.java @@ -18,46 +18,47 @@ import org.springframework.http.MediaType; import com.fasterxml.jackson.databind.JsonNode; public class SL20HttpBindingUtils { - private static final Logger log = LoggerFactory.getLogger(SL20HttpBindingUtils.class); - - /** - * Write SL2.0 response into http-response object - * - * @param httpReq Current http request - * @param httpResp Current http response - * @param sl20Forward SL2.0 command that should be written to response - * @param redirectURL SL2.0 redirect URL in case of SL2.0 redirect command and no native client (see SL2.0 specification) - * @param httpCodeRedirect http redirect-code in case of SL2.0 redirect command and no native client (see SL2.0 specification) - * @throws IOException - * @throws URISyntaxException - */ - public static void writeIntoResponse(@Nonnull HttpServletRequest httpReq, @Nonnull HttpServletResponse httpResp, - @Nonnull JsonNode sl20Forward, @Nullable String redirectURL, - @Nonnull int httpCodeRedirect) throws IOException, URISyntaxException { - //forward SL2.0 command - httpResp.addIntHeader(SL20Constants.HTTP_HEADER_SL20_RESP, SL20Constants.CURRENT_SL20_VERSION); - - if (httpReq.getHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE) != null && - httpReq.getHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE).equals(SL20Constants.HTTP_HEADER_VALUE_NATIVE)) { - log.debug("Client request containts 'native client' header ... "); - final StringWriter writer = new StringWriter(); - writer.write(sl20Forward.toString()); - final byte[] content = writer.toString().getBytes("UTF-8"); - httpResp.setStatus(HttpServletResponse.SC_OK); - httpResp.setContentLength(content.length); - httpResp.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE); - httpResp.getOutputStream().write(content); - - } else { - log.debug("Client request containts is no native client ... "); - final URIBuilder clientRedirectURI = new URIBuilder(redirectURL); - clientRedirectURI.addParameter( - SL20Constants.PARAM_SL20_REQ_COMMAND_PARAM, - Base64Url.encode(sl20Forward.toString().getBytes())); - httpResp.setStatus(httpCodeRedirect); - httpResp.setHeader("Location", clientRedirectURI.build().toString()); - - } - - } + private static final Logger log = LoggerFactory.getLogger(SL20HttpBindingUtils.class); + + /** + * Write SL2.0 response into http-response object + * + * @param httpReq Current http request + * @param httpResp Current http response + * @param sl20Forward SL2.0 command that should be written to response + * @param redirectUrl SL2.0 redirect URL in case of SL2.0 redirect command + * and no native client (see SL2.0 specification) + * @param httpCodeRedirect http redirect-code in case of SL2.0 redirect command + * and no native client (see SL2.0 specification) + * @throws IOException In case of an IO error + * @throws URISyntaxException In case of a wrong URL + */ + public static void writeIntoResponse(@Nonnull final HttpServletRequest httpReq, + @Nonnull final HttpServletResponse httpResp, @Nonnull final JsonNode sl20Forward, + @Nullable final String redirectUrl, @Nonnull final int httpCodeRedirect) throws IOException, URISyntaxException { + // forward SL2.0 command + httpResp.addIntHeader(SL20Constants.HTTP_HEADER_SL20_RESP, SL20Constants.CURRENT_SL20_VERSION); + + if (httpReq.getHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE) != null && httpReq + .getHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE).equals(SL20Constants.HTTP_HEADER_VALUE_NATIVE)) { + log.debug("Client request containts 'native client' header ... "); + final StringWriter writer = new StringWriter(); + writer.write(sl20Forward.toString()); + final byte[] content = writer.toString().getBytes("UTF-8"); + httpResp.setStatus(HttpServletResponse.SC_OK); + httpResp.setContentLength(content.length); + httpResp.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE); + httpResp.getOutputStream().write(content); + + } else { + log.debug("Client request containts is no native client ... "); + final URIBuilder clientRedirectUri = new URIBuilder(redirectUrl); + clientRedirectUri.addParameter(SL20Constants.PARAM_SL20_REQ_COMMAND_PARAM, + Base64Url.encode(sl20Forward.toString().getBytes("UTF-8"))); + httpResp.setStatus(httpCodeRedirect); + httpResp.setHeader("Location", clientRedirectUri.build().toString()); + + } + + } } diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JSONBuilderUtils.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JSONBuilderUtils.java deleted file mode 100644 index ba069ac7..00000000 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JSONBuilderUtils.java +++ /dev/null @@ -1,640 +0,0 @@ -package at.gv.egiz.eaaf.modules.auth.sl20.utils; - -import java.security.cert.CertificateEncodingException; -import java.security.cert.X509Certificate; -import java.util.Arrays; -import java.util.Base64; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - -import com.fasterxml.jackson.databind.node.ArrayNode; -import com.fasterxml.jackson.databind.node.ObjectNode; - -import at.gv.egiz.eaaf.modules.auth.sl20.Constants; -import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SLCommandoBuildException; - -public class SL20JSONBuilderUtils { - - private static JsonMapper mapper = new JsonMapper(); - - /** - * Create command request - * @param name - * @param params - * @throws SLCommandoBuildException - * @return - */ - public static ObjectNode createCommand(String name, ObjectNode params) throws SLCommandoBuildException { - - final ObjectNode command = mapper.getMapper().createObjectNode(); - addSingleStringElement(command, SL20Constants.SL20_COMMAND_CONTAINER_NAME, name, true); - addSingleJSONElement(command, SL20Constants.SL20_COMMAND_CONTAINER_PARAMS, params, true); - return command; - - } - - /** - * Create signed command request - * - * @param name - * @param params - * @param signer - * @return - * @throws SLCommandoBuildException - */ - public static String createSignedCommand(String name, ObjectNode params, IJOSETools signer) throws SLCommandoBuildException { - final ObjectNode command = mapper.getMapper().createObjectNode(); - addSingleStringElement(command, SL20Constants.SL20_COMMAND_CONTAINER_NAME, name, true); - addSingleJSONElement(command, SL20Constants.SL20_COMMAND_CONTAINER_PARAMS, params, true); - return signer.createSignature(command.toString()); - - } - - - /** - * Create encrypted command result - * - * @param result - * @param encrypter - * @return - * @throws SLCommandoBuildException - */ - public static String createEncryptedCommandoResult(ObjectNode result, JsonSecurityUtils encrypter) throws SLCommandoBuildException { - //TODO: add real implementation - //create header and footer - final String dummyHeader = createJsonEncryptionHeader(encrypter).toString(); - final String payLoad = result.toString(); - final String dummyFooter = createJsonSignedFooter(encrypter); - - return Base64.getUrlEncoder().encodeToString(dummyHeader.getBytes()) + "." - + Base64.getUrlEncoder().encodeToString(payLoad.getBytes()) + "." - + Base64.getUrlEncoder().encodeToString(dummyFooter.getBytes()); - - } - - - /** - * Create command result - * - * @param name - * @param result - * @param encryptedResult - * @throws SLCommandoBuildException - * @return - */ - public static ObjectNode createCommandResponse(String name, ObjectNode result, String encryptedResult) throws SLCommandoBuildException { - final ObjectNode command = mapper.getMapper().createObjectNode(); - addSingleStringElement(command, SL20Constants.SL20_COMMAND_CONTAINER_NAME, name, true); - addOnlyOnceOfTwo(command, - SL20Constants.SL20_COMMAND_CONTAINER_RESULT, SL20Constants.SL20_COMMAND_CONTAINER_ENCRYPTEDRESULT, - result, encryptedResult); - return command; - - } - - /** - * Create command result - * - * @param name - * @param result - * @param encryptedResult - * @throws SLCommandoBuildException - * @return - */ - public static String createSignedCommandResponse(String name, ObjectNode result, String encryptedResult, JsonSecurityUtils signer) throws SLCommandoBuildException { - final ObjectNode command = mapper.getMapper().createObjectNode(); - addSingleStringElement(command, SL20Constants.SL20_COMMAND_CONTAINER_NAME, name, true); - addOnlyOnceOfTwo(command, - SL20Constants.SL20_COMMAND_CONTAINER_RESULT, SL20Constants.SL20_COMMAND_CONTAINER_ENCRYPTEDRESULT, - result, encryptedResult); - final String encodedCommand = command.toString(); - - //TODO: add real implementation - //create header and footer - final String dummyHeader = createJsonSignedHeader(signer).toString(); - final String dummyFooter = createJsonSignedFooter(signer); - - return Base64.getUrlEncoder().encodeToString(dummyHeader.getBytes()) + "." - + Base64.getUrlEncoder().encodeToString(encodedCommand.getBytes()) + "." - + Base64.getUrlEncoder().encodeToString(dummyFooter.getBytes()); - - } - - /** - * Create parameters for Redirect command - * - * @param url - * @param command - * @param signedCommand - * @param ipcRedirect - * @return - * @throws SLCommandoBuildException - */ - public static ObjectNode createRedirectCommandParameters(String url, ObjectNode command, ObjectNode signedCommand, Boolean ipcRedirect) throws SLCommandoBuildException{ - final ObjectNode redirectReqParams = mapper.getMapper().createObjectNode(); - addOnlyOnceOfTwo(redirectReqParams, - SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_COMMAND, SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_SIGNEDCOMMAND, - command, signedCommand); - addSingleStringElement(redirectReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_URL, url, false); - addSingleBooleanElement(redirectReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_IPCREDIRECT, ipcRedirect, false); - return redirectReqParams; - - } - - /** - * Create parameters for Call command - * - * @param url - * @param method - * @param includeTransactionId - * @param reqParameters - * @return - * @throws SLCommandoBuildException - */ - public static ObjectNode createCallCommandParameters(String url, String method, Boolean includeTransactionId, Map<String, String> reqParameters) throws SLCommandoBuildException { - final ObjectNode callReqParams = mapper.getMapper().createObjectNode(); - addSingleStringElement(callReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_CALL_URL, url, true); - addSingleStringElement(callReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_CALL_METHOD, method, true); - addSingleBooleanElement(callReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_CALL_INCLUDETRANSACTIONID, includeTransactionId, false); - addArrayOfStringElements(callReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_CALL_REQPARAMETER, reqParameters); - return callReqParams; - - } - - /** - * Create result for Error command - * - * @param errorCode - * @param errorMsg - * @return - * @throws SLCommandoBuildException - */ - public static ObjectNode createErrorCommandResult(String errorCode, String errorMsg) throws SLCommandoBuildException { - final ObjectNode result = mapper.getMapper().createObjectNode(); - addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORCODE, errorCode, true); - addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORMESSAGE, errorMsg, true); - return result; - - } - - /** - * Create parameters for qualifiedeID command - * - * @param consentTemplateId Identifier of the template that is used for consent visualization - * @param consent Consent that has to be signed by user - * @param dataUrl - * @param additionalReqParameters - * @param x5cEnc - * @return - * @throws CertificateEncodingException - * @throws SLCommandoBuildException - */ - public static ObjectNode createQualifiedeEIDConsent(String consentTemplateId, byte[] consent, String dataUrl, - X509Certificate x5cEnc) throws CertificateEncodingException, SLCommandoBuildException { - final ObjectNode params = mapper.getMapper().createObjectNode(); - addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_CONSENTTEMPLATEID, consentTemplateId, true); - addSingleByteElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_CONSENT, consent, true); - addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_DATAURL, dataUrl, true); - addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_X5CENC, x5cEnc, false); - return params; - - } - - - /** - * Create parameters for qualifiedeID command - * - * @param authBlockId - * @param dataUrl - * @param additionalReqParameters - * @param x5cEnc - * @return - * @throws CertificateEncodingException - * @throws SLCommandoBuildException - */ - @Deprecated - public static ObjectNode createQualifiedeIDCommandParameters(String authBlockId, String dataUrl, - Map<String, String> additionalReqParameters, X509Certificate x5cEnc) throws CertificateEncodingException, SLCommandoBuildException { - final ObjectNode params = mapper.getMapper().createObjectNode(); - addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_AUTHBLOCKID, authBlockId, true); - addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_DATAURL, dataUrl, true); - addArrayOfStringElements(params, SL20Constants.SL20_COMMAND_PARAM_EID_ATTRIBUTES, additionalReqParameters); - addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_X5CENC, x5cEnc, false); - return params; - - } - - /** - * Create result for qualifiedeID command - * - * @param idl - * @param authBlock - * @param ccsURL - * @param LoA - * @return - * @throws SLCommandoBuildException - */ - public static ObjectNode createQualifiedeIDCommandResult(byte[] idl, byte[] authBlock, String ccsURL, String LoA) throws SLCommandoBuildException { - final ObjectNode result = mapper.getMapper().createObjectNode(); - addSingleByteElement(result, SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_IDL, idl, true); - addSingleByteElement(result, SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_AUTHBLOCK, authBlock, true); - addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_CCSURL, ccsURL, true); - addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_LOA, LoA, true); - return result; - - } - - - /** - * Create Binding-Key command parameters - * - * @param kontoId - * @param subjectName - * @param keySize - * @param keyAlg - * @param policies - * @param dataUrl - * @param x5cVdaTrust - * @param reqUserPassword - * @param x5cEnc - * @return - * @throws SLCommandoBuildException - * @throws CertificateEncodingException - */ - public static ObjectNode createBindingKeyCommandParams(String kontoId, String subjectName, int keySize, String keyAlg, - Map<String, String> policies, String dataUrl, X509Certificate x5cVdaTrust, Boolean reqUserPassword, X509Certificate x5cEnc) throws SLCommandoBuildException, CertificateEncodingException { - final ObjectNode params = mapper.getMapper().createObjectNode(); - addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_KONTOID, kontoId, true); - addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_SN, subjectName, true); - addSingleNumberElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_KEYLENGTH, keySize, true); - addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_KEYALG, keyAlg, true); - addArrayOfStringElements(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_POLICIES, policies); - addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_DATAURL, dataUrl, true); - addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_X5CVDATRUST, x5cVdaTrust, false); - addSingleBooleanElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_REQUESTUSERPASSWORD, reqUserPassword, false); - addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_X5CENC, x5cEnc, false); - return params; - - } - - /** - * Create Binding-Key command result - * - * @param appId - * @param csr - * @param attCert - * @param password - * @return - * @throws SLCommandoBuildException - * @throws CertificateEncodingException - */ - public static ObjectNode createBindingKeyCommandResult(String appId, byte[] csr, X509Certificate attCert, byte[] password) throws SLCommandoBuildException, CertificateEncodingException { - final ObjectNode result = mapper.getMapper().createObjectNode(); - addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_APPID, appId, true); - addSingleByteElement(result, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_CSR, csr, true); - addSingleCertificateElement(result, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_KEYATTESTATIONZERTIFICATE, attCert, false); - addSingleByteElement(result, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_USERPASSWORD, password, false); - return result; - - } - - /** - * Create Store Binding-Certificate command parameters - * - * @param cert - * @param dataUrl - * @return - * @throws CertificateEncodingException - * @throws SLCommandoBuildException - */ - public static ObjectNode createStoreBindingCertCommandParams(X509Certificate cert, String dataUrl) throws CertificateEncodingException, SLCommandoBuildException { - final ObjectNode params = mapper.getMapper().createObjectNode(); - addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_STORE_CERTIFICATE, cert, true); - addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_STORE_DATAURL, dataUrl, true); - return params; - - } - - /** - * Create Store Binding-Certificate command result - * - * @return - * @throws SLCommandoBuildException - */ - public static ObjectNode createStoreBindingCertCommandSuccessResult() throws SLCommandoBuildException { - final ObjectNode result = mapper.getMapper().createObjectNode(); - addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_BINDING_STORE_RESULT_SUCESS, - SL20Constants.SL20_COMMAND_PARAM_BINDING_STORE_RESULT_SUCESS_VALUE, true); - return result; - - } - - - /** - * Create idAndPassword command parameters - * - * @param keyAlg - * @param dataUrl - * @param x5cEnc - * @return - * @throws SLCommandoBuildException - * @throws CertificateEncodingException - */ - public static ObjectNode createIdAndPasswordCommandParameters(String keyAlg, String dataUrl, X509Certificate x5cEnc) throws SLCommandoBuildException, CertificateEncodingException { - final ObjectNode params = mapper.getMapper().createObjectNode(); - addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_KEYALG, keyAlg, true); - addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_DATAURL, dataUrl, true); - addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_X5CENC, x5cEnc, false); - return params; - - } - - /** - * Create idAndPassword command result - * - * @param kontoId - * @param password - * @return - * @throws SLCommandoBuildException - */ - public static ObjectNode createIdAndPasswordCommandResult(String kontoId, byte[] password) throws SLCommandoBuildException { - final ObjectNode result = mapper.getMapper().createObjectNode(); - addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_RESULT_KONTOID, kontoId, true); - addSingleByteElement(result, SL20Constants.SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_RESULT_USERPASSWORD, password, true); - return result; - - } - - /** - * Create JWS Token Authentication command - * - * @param nonce - * @param dataUrl - * @param displayData - * @param displayUrl - * @return - * @throws SLCommandoBuildException - */ - public static ObjectNode createJwsTokenAuthCommandParams(String nonce, String dataUrl, List<String> displayData, List<String> displayUrl) throws SLCommandoBuildException { - final ObjectNode params = mapper.getMapper().createObjectNode(); - addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_JWSTOKEN_NONCE, nonce, true); - addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_JWSTOKEN_DATAURL, dataUrl, true); - addArrayOfStrings(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_JWSTOKEN_DISPLAYDATA, displayData); - addArrayOfStrings(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_JWSTOKEN_DISPLAYURL, displayUrl); - return params; - - } - - /** - * Create JWS Token Authentication command result - * - * @param nonce - * @return - * @throws SLCommandoBuildException - */ - public static ObjectNode createJwsTokenAuthCommandResult(String nonce) throws SLCommandoBuildException { - final ObjectNode result = mapper.getMapper().createObjectNode(); - addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_AUTH_JWSTOKEN_RESULT_NONCE, nonce, true); - return result; - - } - - - /** - * Create Generic Request Container - * - * @param reqId - * @param transactionId - * @param payLoad - * @param signedPayload - * @return - * @throws SLCommandoBuildException - */ - public static ObjectNode createGenericRequest(String reqId, String transactionId, ObjectNode payLoad, String signedPayload) throws SLCommandoBuildException { - final ObjectNode req = mapper.getMapper().createObjectNode(); - addSingleIntegerElement(req, SL20Constants.SL20_VERSION, SL20Constants.CURRENT_SL20_VERSION, true); - addSingleStringElement(req, SL20Constants.SL20_REQID, reqId, true); - addSingleStringElement(req, SL20Constants.SL20_TRANSACTIONID, transactionId, false); - addOnlyOnceOfTwo(req, SL20Constants.SL20_PAYLOAD, SL20Constants.SL20_SIGNEDPAYLOAD, - payLoad, signedPayload); - return req; - - } - - /** - * Create Generic Response Container - * - * @param respId - * @param inResponseTo - * @param transactionId - * @param payLoad - * @param signedPayload - * @return - * @throws SLCommandoBuildException - */ - public static final ObjectNode createGenericResponse(String respId, String inResponseTo, String transactionId, - ObjectNode payLoad, String signedPayload) throws SLCommandoBuildException { - final ObjectNode req = mapper.getMapper().createObjectNode(); - addSingleIntegerElement(req, SL20Constants.SL20_VERSION, SL20Constants.CURRENT_SL20_VERSION, true); - addSingleStringElement(req, SL20Constants.SL20_RESPID, respId, true); - addSingleStringElement(req, SL20Constants.SL20_INRESPTO, inResponseTo, false); - addSingleStringElement(req, SL20Constants.SL20_TRANSACTIONID, transactionId, false); - addOnlyOnceOfTwo(req, SL20Constants.SL20_PAYLOAD, SL20Constants.SL20_SIGNEDPAYLOAD, - payLoad, signedPayload); - return req; - - } - - /** - * Add one element of two possible elements <br> - * This method adds either the first element or the second element to parent JSON, but never both. - * - * @param parent Parent JSON element - * @param firstKeyId first element Id - * @param secondKeyId second element Id - * @param first first element - * @param second second element - * @throws SLCommandoBuildException - */ - public static void addOnlyOnceOfTwo(ObjectNode parent, String firstKeyId, String secondKeyId, ObjectNode first, String second) throws SLCommandoBuildException { - if (first == null && (second == null || second.isEmpty())) - throw new SLCommandoBuildException(firstKeyId + " and " + secondKeyId + " is NULL"); - - else if (first != null && second != null) - throw new SLCommandoBuildException(firstKeyId + " and " + secondKeyId + " can not SET TWICE"); - - else if (first != null) - parent.set(firstKeyId, first); - - else if (second != null && !second.isEmpty()) - parent.put(secondKeyId, second); - - else - throw new SLCommandoBuildException("Internal build error"); - } - - - - //TODO!!!! - private static ObjectNode createJsonSignedHeader(JsonSecurityUtils signer) throws SLCommandoBuildException { - final ObjectNode header = mapper.getMapper().createObjectNode(); - addSingleStringElement(header, SL20Constants.JSON_ALGORITHM, SL20Constants.JSON_ALGORITHM_SIGNING_RS256, true); - addSingleStringElement(header, SL20Constants.JSON_CONTENTTYPE, SL20Constants.SL20_CONTENTTYPE_SIGNED_COMMAND, true); - addArrayOfStrings(header, SL20Constants.JSON_X509_CERTIFICATE, Arrays.asList(Constants.DUMMY_SIGNING_CERT)); - - return header; - } - - //TODO!!!! - private static ObjectNode createJsonEncryptionHeader(JsonSecurityUtils signer) throws SLCommandoBuildException { - final ObjectNode header = mapper.getMapper().createObjectNode(); - addSingleStringElement(header, SL20Constants.JSON_ALGORITHM, SL20Constants.JSON_ALGORITHM_ENC_KEY_RSAOAEP, true); - addSingleStringElement(header, SL20Constants.JSON_ENCRYPTION_PAYLOAD, SL20Constants.JSON_ALGORITHM_ENC_PAYLOAD_A128CBCHS256, true); - addSingleStringElement(header, SL20Constants.JSON_CONTENTTYPE, SL20Constants.SL20_CONTENTTYPE_ENCRYPTED_RESULT, true); - addSingleStringElement(header, SL20Constants.JSON_X509_FINGERPRINT, Constants.DUMMY_SIGNING_CERT_FINGERPRINT, true); - - return header; - } - - //TODO!!!! - private static String createJsonSignedFooter(JsonSecurityUtils signer) { - return "cC4hiUPoj9Eetdgtv3hF80EGrhuB__dzERat0XF9g2VtQgr9PJbu3XOiZj5RZmh7\n" + - " AAuHIm4Bh-0Qc_lF5YKt_O8W2Fp5jujGbds9uJdbF9CUAr7t1dnZcAcQjbKBYNX4\n" + - " BAynRFdiuB--f_nZLgrnbyTyWzO75vRK5h6xBArLIARNPvkSjtQBMHlb1L07Qe7K\n" + - " 0GarZRmB_eSN9383LcOLn6_dO--xi12jzDwusC-eOkHWEsqtFZESc6BfI7noOPqv\n" + - " hJ1phCnvWh6IeYI2w9QOYEUipUTI8np6LbgGY9Fs98rqVt5AXLIhWkWywlVmtVrB\n" + - " p0igcN_IoypGlUPQGe77Rw"; - } - - - - private static void addArrayOfStrings(ObjectNode parent, String keyId, List<String> values) throws SLCommandoBuildException { - validateParentAndKey(parent, keyId); - if (values != null) { - final ArrayNode callReqParamsArray = mapper.getMapper().createArrayNode(); - parent.set(keyId, callReqParamsArray ); - for(final String el : values) - callReqParamsArray.add(el); - - } - } - - - private static void addArrayOfStringElements(ObjectNode parent, String keyId, Map<String, String> keyValuePairs) throws SLCommandoBuildException { - validateParentAndKey(parent, keyId); - if (keyValuePairs != null) { - final ArrayNode callReqParamsArray = mapper.getMapper().createArrayNode(); - parent.set(keyId, callReqParamsArray); - - for(final Entry<String, String> el : keyValuePairs.entrySet()) { - final ObjectNode callReqParams = mapper.getMapper().createObjectNode(); - callReqParams.put(el.getKey(), el.getValue()); - callReqParamsArray.add(callReqParams); - - } - } - } - - private static void addSingleCertificateElement(ObjectNode parent, String keyId, X509Certificate cert, boolean isRequired) throws CertificateEncodingException, SLCommandoBuildException { - if (cert != null) - addSingleByteElement(parent, keyId, cert.getEncoded(), isRequired); - - else if (isRequired) - throw new SLCommandoBuildException(keyId + " is marked as REQUIRED"); - - } - - - - private static void addSingleByteElement(ObjectNode parent, String keyId, byte[] value, boolean isRequired) throws SLCommandoBuildException { - validateParentAndKey(parent, keyId); - - if (isRequired && value == null) - throw new SLCommandoBuildException(keyId + " has NULL value"); - - else if (value != null) - parent.put(keyId, Base64.getEncoder().encodeToString(value)); - - } - - private static void addSingleBooleanElement(ObjectNode parent, String keyId, Boolean value, boolean isRequired) throws SLCommandoBuildException { - validateParentAndKey(parent, keyId); - - if (isRequired && value == null) - throw new SLCommandoBuildException(keyId + " has a NULL value"); - - else if (value != null) - parent.put(keyId, value); - - } - - private static void addSingleNumberElement(ObjectNode parent, String keyId, Integer value, boolean isRequired) throws SLCommandoBuildException { - validateParentAndKey(parent, keyId); - - if (isRequired && value == null) - throw new SLCommandoBuildException(keyId + " has a NULL value"); - - else if (value != null) - parent.put(keyId, value);; - - } - - private static void addSingleStringElement(ObjectNode parent, String keyId, String value, boolean isRequired) throws SLCommandoBuildException { - validateParentAndKey(parent, keyId); - - if (isRequired && (value == null || value.isEmpty())) - throw new SLCommandoBuildException(keyId + " has an empty value"); - - else if (value != null && !value.isEmpty()) - parent.put(keyId, value); - - } - - private static void addSingleIntegerElement(ObjectNode parent, String keyId, Integer value, boolean isRequired) throws SLCommandoBuildException { - validateParentAndKey(parent, keyId); - - if (isRequired && value == null) - throw new SLCommandoBuildException(keyId + " has an empty value"); - - else if (value != null) - parent.put(keyId, value); - - } - - private static void addSingleJSONElement(ObjectNode parent, String keyId, ObjectNode element, boolean isRequired) throws SLCommandoBuildException { - validateParentAndKey(parent, keyId); - - if (isRequired && element == null) - throw new SLCommandoBuildException("No commando name included"); - - else if (element != null) - parent.set(keyId, element); - - } - - private static void addOnlyOnceOfTwo(ObjectNode parent, String firstKeyId, String secondKeyId, ObjectNode first, ObjectNode second) throws SLCommandoBuildException { - if (first == null && second == null) - throw new SLCommandoBuildException(firstKeyId + " and " + secondKeyId + " is NULL"); - - else if (first != null && second != null) - throw new SLCommandoBuildException(firstKeyId + " and " + secondKeyId + " can not SET TWICE"); - - else if (first != null) - parent.set(firstKeyId, first); - - else if (second != null) - parent.set(secondKeyId, second); - - else - throw new SLCommandoBuildException("Internal build error"); - } - - private static void validateParentAndKey(ObjectNode parent, String keyId) throws SLCommandoBuildException { - if (parent == null) - throw new SLCommandoBuildException("NO parent JSON element"); - - if (keyId == null || keyId.isEmpty()) - throw new SLCommandoBuildException("NO JSON element identifier"); - } -} diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JSONExtractorUtils.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JSONExtractorUtils.java deleted file mode 100644 index 314dde17..00000000 --- a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JSONExtractorUtils.java +++ /dev/null @@ -1,368 +0,0 @@ -package at.gv.egiz.eaaf.modules.auth.sl20.utils; - -import java.util.ArrayList; -import java.util.Base64; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - -import org.apache.http.Header; -import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; -import org.apache.http.client.utils.URIBuilder; -import org.apache.http.util.EntityUtils; -import org.jose4j.base64url.Base64Url; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ObjectNode; - -import at.gv.egiz.eaaf.modules.auth.sl20.data.VerificationResult; -import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20Exception; -import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SLCommandoParserException; - -public class SL20JSONExtractorUtils { - private static final Logger log = LoggerFactory.getLogger(SL20JSONExtractorUtils.class); - private static JsonMapper mapper = new JsonMapper(); - - - /** - * Extract String value from JSON - * - * @param input - * @param keyID - * @param isRequired - * @return - * @throws SLCommandoParserException - */ - public static String getStringValue(JsonNode input, String keyID, boolean isRequired) throws SLCommandoParserException { - try { - final JsonNode internal = getAndCheck(input, keyID, isRequired); - - if (internal != null) - return internal.asText(); - else - return null; - - } catch (final SLCommandoParserException e) { - throw e; - - } catch (final Exception e) { - throw new SLCommandoParserException("Can not extract String value with keyId: " + keyID, e); - - } - } - - /** - * Extract Boolean value from JSON - * - * @param input - * @param keyID - * @param isRequired - * @return - * @throws SLCommandoParserException - */ - public static boolean getBooleanValue(ObjectNode input, String keyID, boolean isRequired, boolean defaultValue) throws SLCommandoParserException { - try { - final JsonNode internal = getAndCheck(input, keyID, isRequired); - - if (internal != null) - return internal.asBoolean(); - else - return defaultValue; - - } catch (final SLCommandoParserException e) { - throw e; - - } catch (final Exception e) { - throw new SLCommandoParserException("Can not extract Boolean value with keyId: " + keyID, e); - - } - } - - /** - * Extract JSONObject value from JSON - * - * @param input - * @param keyID - * @param isRequired - * @return - * @throws SLCommandoParserException - */ - public static JsonNode getJSONObjectValue(JsonNode input, String keyID, boolean isRequired) throws SLCommandoParserException { - try { - final JsonNode internal = getAndCheck(input, keyID, isRequired); - - if (internal != null) - return internal; - else - return null; - - } catch (final SLCommandoParserException e) { - throw e; - - } catch (final Exception e) { - throw new SLCommandoParserException("Can not extract Boolean value with keyId: " + keyID, e); - - } - } - - /** - * Extract a List of String elements from a JSON element - * - * @param input - * @return - * @throws SLCommandoParserException - */ - public static List<String> getListOfStringElements(JsonNode input) throws SLCommandoParserException { - final List<String> result = new ArrayList<String>(); - if (input != null) { - if (input.isArray()) { - final Iterator<JsonNode> arrayIterator = input.iterator(); - while(arrayIterator.hasNext()) { - final JsonNode next = arrayIterator.next(); - if (next.isTextual()) - result.add(next.asText()); - } - - } else if (input.isTextual()) { - result.add(input.asText()); - - } else { - log.warn("JSON Element IS NOT a JSON array or a JSON Primitive"); - throw new SLCommandoParserException("JSON Element IS NOT a JSON array or a JSON Primitive"); - - } - } - - return result; - } - - /** - * Extract Map of Key/Value pairs from a JSON Element - * - * @param input parent JSON object - * @param keyID KeyId of the child that should be parsed - * @param isRequired - * @return - * @throws SLCommandoParserException - */ - public static Map<String, String> getMapOfStringElements(JsonNode input, String keyID, boolean isRequired) throws SLCommandoParserException { - final JsonNode internal = getAndCheck(input, keyID, isRequired); - return getMapOfStringElements(internal); - - } - - /** - * Extract Map of Key/Value pairs from a JSON Element - * - * @param input - * @return - * @throws SLCommandoParserException - */ - public static Map<String, String> getMapOfStringElements(JsonNode input) throws SLCommandoParserException { - final Map<String, String> result = new HashMap<String, String>(); - - if (input != null) { - if (input.isArray()) { - final Iterator<JsonNode> arrayIterator = input.iterator(); - while(arrayIterator.hasNext()) { - final JsonNode next = arrayIterator.next(); - final Iterator<Entry<String, JsonNode>> entry = next.fields(); - entitySetToMap(result, entry); - - } - - } else if (input.isObject()) { - final Iterator<Entry<String, JsonNode>> objectKeys = input.fields(); - entitySetToMap(result, objectKeys); - - } else - throw new SLCommandoParserException("JSON Element IS NOT a JSON array or a JSON object"); - - } - - return result; - } - - private static void entitySetToMap(Map<String, String> result, Iterator<Entry<String, JsonNode>> entry) { - while (entry.hasNext()) { - final Entry<String, JsonNode> el = entry.next(); - if (result.containsKey(el.getKey())) - log.info("Attr. Map already contains Element with Key: " + el.getKey() + ". Overwrite element ... "); - - result.put(el.getKey(), el.getValue().asText()); - - } - - } - - - public static JsonNode extractSL20Result(JsonNode command, IJOSETools decrypter, boolean mustBeEncrypted) throws SL20Exception { - final JsonNode result = command.get(SL20Constants.SL20_COMMAND_CONTAINER_RESULT); - final JsonNode encryptedResult = command.get(SL20Constants.SL20_COMMAND_CONTAINER_ENCRYPTEDRESULT); - - if (result == null && encryptedResult == null) - throw new SLCommandoParserException("NO result OR encryptedResult FOUND."); - - else if (encryptedResult == null && mustBeEncrypted) - throw new SLCommandoParserException("result MUST be encrypted."); - - else if (encryptedResult != null && encryptedResult.isTextual()) { - try { - return decrypter.decryptPayload(encryptedResult.asText()); - - } catch (final Exception e) { - log.info("Can NOT decrypt SL20 result. Reason:" + e.getMessage()); - if (!mustBeEncrypted) { - log.warn("Decrypted results are disabled by configuration. Parse result in plain if it is possible"); - - //dummy code - try { - final String[] signedPayload = encryptedResult.toString().split("\\."); - final JsonNode payLoad = mapper.getMapper().readTree(new String(Base64.getUrlDecoder().decode(signedPayload[1]))); - return payLoad; - - } catch (final Exception e1) { - log.debug("DummyCode FAILED, Reason: " + e1.getMessage() + " Ignore it ..."); - throw new SL20Exception(e.getMessage(), null, e); - - } - - } else - throw e; - - } - - } else if (result != null) { - return result; - - } else - throw new SLCommandoParserException("Internal build error"); - - - } - - /** - * Extract payLoad from generic transport container - * - * @param container - * @param joseTools - * @return - * @throws SLCommandoParserException - */ - public static VerificationResult extractSL20PayLoad(JsonNode container, IJOSETools joseTools, boolean mustBeSigned) throws SL20Exception { - - final JsonNode sl20Payload = container.get(SL20Constants.SL20_PAYLOAD); - final JsonNode sl20SignedPayload = container.get(SL20Constants.SL20_SIGNEDPAYLOAD); - - if (mustBeSigned && joseTools == null) - throw new SLCommandoParserException("'joseTools' MUST be set if 'mustBeSigned' is 'true'"); - - if (sl20Payload == null && sl20SignedPayload == null) - throw new SLCommandoParserException("NO payLoad OR signedPayload FOUND."); - - else if (sl20SignedPayload == null && mustBeSigned) - throw new SLCommandoParserException("payLoad MUST be signed."); - - else if (joseTools != null && sl20SignedPayload != null && sl20SignedPayload.isTextual()) { - return joseTools.validateSignature(sl20SignedPayload.asText()); - - } else if (sl20Payload != null) - return new VerificationResult(sl20Payload); - - else - throw new SLCommandoParserException("Internal build error"); - - - } - - - /** - * Extract generic transport container from httpResponse - * - * @param httpResp - * @return - * @throws SLCommandoParserException - */ - public static JsonNode getSL20ContainerFromResponse(HttpResponse httpResp) throws SLCommandoParserException { - try { - JsonNode sl20Resp = null; - if (httpResp.getStatusLine().getStatusCode() == 303 || httpResp.getStatusLine().getStatusCode() == 307) { - final Header[] locationHeader = httpResp.getHeaders("Location"); - if (locationHeader == null) - throw new SLCommandoParserException("Find Redirect statuscode but not Location header"); - - final String sl20RespString = new URIBuilder(locationHeader[0].getValue()).getQueryParams().get(0).getValue(); - sl20Resp = mapper.getMapper().readTree(Base64Url.decode(sl20RespString)); - - } else if (httpResp.getStatusLine().getStatusCode() == 200) { - if (httpResp.getEntity().getContentType() == null) - throw new SLCommandoParserException("SL20 response contains NO ContentType"); - - if (!httpResp.getEntity().getContentType().getValue().startsWith("application/json")) - throw new SLCommandoParserException("SL20 response with a wrong ContentType: " + httpResp.getEntity().getContentType().getValue()); - sl20Resp = parseSL20ResultFromResponse(httpResp.getEntity()); - - } else if ( (httpResp.getStatusLine().getStatusCode() == 500) || - (httpResp.getStatusLine().getStatusCode() == 401) || - (httpResp.getStatusLine().getStatusCode() == 400) ) { - log.info("SL20 response with http-code: " + httpResp.getStatusLine().getStatusCode() - + ". Search for error message"); - - try { - sl20Resp = parseSL20ResultFromResponse(httpResp.getEntity()); - - } catch (final Exception e) { - log.warn("SL20 response contains no valid JSON", e); - throw new SLCommandoParserException("SL20 response with http-code: " + httpResp.getStatusLine().getStatusCode() - + " AND NO valid JSON errormsg", e); - - } - - - - } else - throw new SLCommandoParserException("SL20 response with http-code: " + httpResp.getStatusLine().getStatusCode()); - - log.info("Find JSON object in http response"); - return sl20Resp; - - } catch (final Exception e) { - throw new SLCommandoParserException("SL20 response parsing FAILED! Reason: " + e.getMessage(), e); - - } - } - - private static JsonNode parseSL20ResultFromResponse(HttpEntity resp) throws Exception { - if (resp != null && resp.getContent() != null) { - final String rawSL20Resp = EntityUtils.toString(resp); - final JsonNode sl20Resp = mapper.getMapper().readTree(rawSL20Resp); - - //TODO: check sl20Resp type like && sl20Resp.isJsonObject() - if (sl20Resp != null) { - return sl20Resp; - - } else - throw new SLCommandoParserException("SL2.0 can NOT parse to a JSON object"); - - - } else - throw new SLCommandoParserException("Can NOT find content in http response"); - - } - - - private static JsonNode getAndCheck(JsonNode input, String keyID, boolean isRequired) throws SLCommandoParserException { - final JsonNode internal = input.get(keyID); - - if (internal == null && isRequired) - throw new SLCommandoParserException("REQUIRED Element with keyId: " + keyID + " does not exist"); - - return internal; - - } -} diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JsonBuilderUtils.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JsonBuilderUtils.java new file mode 100644 index 00000000..eb17781b --- /dev/null +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JsonBuilderUtils.java @@ -0,0 +1,677 @@ +package at.gv.egiz.eaaf.modules.auth.sl20.utils; + +import java.io.UnsupportedEncodingException; +import java.security.cert.CertificateEncodingException; +import java.security.cert.X509Certificate; +import java.util.Arrays; +import java.util.Base64; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + +import at.gv.egiz.eaaf.modules.auth.sl20.Constants; +import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SlCommandoBuildException; + +public class SL20JsonBuilderUtils { + + private static JsonMapper mapper = new JsonMapper(); + + /** + * Create command request. + * + * @param name Commando name + * @param params Commando parameters + * @return JSON Object + * @throws SlCommandoBuildException In case of a build error + */ + public static ObjectNode createCommand(final String name, final ObjectNode params) throws SlCommandoBuildException { + + final ObjectNode command = mapper.getMapper().createObjectNode(); + addSingleStringElement(command, SL20Constants.SL20_COMMAND_CONTAINER_NAME, name, true); + addSingleJsonElement(command, SL20Constants.SL20_COMMAND_CONTAINER_PARAMS, params, true); + return command; + + } + + /** + * Create signed command request. + * + * @param name Commando name + * @param params commando parameter + * @param signer JWS signer implementation + * @return Serialized JWS + * @throws SlCommandoBuildException In case of a build error + */ + public static String createSignedCommand(final String name, final ObjectNode params, final IJoseTools signer) + throws SlCommandoBuildException { + final ObjectNode command = mapper.getMapper().createObjectNode(); + addSingleStringElement(command, SL20Constants.SL20_COMMAND_CONTAINER_NAME, name, true); + addSingleJsonElement(command, SL20Constants.SL20_COMMAND_CONTAINER_PARAMS, params, true); + return signer.createSignature(command.toString()); + + } + + /** + * Create encrypted command result. + * + * @param result JSON to encrypt + * @param encrypter JWE encrypter implementation + * @return Serialized JWE + * @throws SlCommandoBuildException In case of a processing error + */ + public static String createEncryptedCommandoResult(final ObjectNode result, final JsonSecurityUtils encrypter) + throws SlCommandoBuildException { + // TODO: add real implementation + // create header and footer + final String dummyHeader = createJsonEncryptionHeader().toString(); + final String payLoad = result.toString(); + final String dummyFooter = createJsonSignedFooter(); + + try { + return Base64.getUrlEncoder().encodeToString(dummyHeader.getBytes("UTF-8")) + "." + + Base64.getUrlEncoder().encodeToString(payLoad.getBytes("UTF-8")) + "." + + Base64.getUrlEncoder().encodeToString(dummyFooter.getBytes("UTF-8")); + } catch (final UnsupportedEncodingException e) { + throw new SlCommandoBuildException("No UTF-8 encoding", e); + } + + } + + /** + * Create command result. + * + * @param name Commando name + * @param result commande result + * @param encryptedResult encrypted commando result + * @return Result json + * @throws SlCommandoBuildException In case of an error + */ + public static ObjectNode createCommandResponse(final String name, final ObjectNode result, + final String encryptedResult) throws SlCommandoBuildException { + final ObjectNode command = mapper.getMapper().createObjectNode(); + addSingleStringElement(command, SL20Constants.SL20_COMMAND_CONTAINER_NAME, name, true); + addOnlyOnceOfTwo(command, SL20Constants.SL20_COMMAND_CONTAINER_RESULT, + SL20Constants.SL20_COMMAND_CONTAINER_ENCRYPTEDRESULT, result, encryptedResult); + return command; + + } + + /** + * Create signed command result. + * + * @param name commando name + * @param result commando result + * @param encryptedResult encrypted commando result + * @return JWS in serialized form + * @throws SlCommandoBuildException in case of an error + * + */ + public static String createSignedCommandResponse(final String name, final ObjectNode result, + final String encryptedResult, final JsonSecurityUtils signer) throws SlCommandoBuildException { + final ObjectNode command = mapper.getMapper().createObjectNode(); + addSingleStringElement(command, SL20Constants.SL20_COMMAND_CONTAINER_NAME, name, true); + addOnlyOnceOfTwo(command, SL20Constants.SL20_COMMAND_CONTAINER_RESULT, + SL20Constants.SL20_COMMAND_CONTAINER_ENCRYPTEDRESULT, result, encryptedResult); + final String encodedCommand = command.toString(); + + // TODO: add real implementation + // create header and footer + final String dummyHeader = createJsonSignedHeader().toString(); + final String dummyFooter = createJsonSignedFooter(); + + try { + return Base64.getUrlEncoder().encodeToString(dummyHeader.getBytes("UTF-8")) + "." + + Base64.getUrlEncoder().encodeToString(encodedCommand.getBytes("UTF-8")) + "." + + Base64.getUrlEncoder().encodeToString(dummyFooter.getBytes("UTF-8")); + + } catch (final UnsupportedEncodingException e) { + throw new SlCommandoBuildException("No UTF-8 encoding", e); + } + + } + + /** + * Create parameters for Redirect command. + * + * @param url redirect URL + * @param command embedded command + * @param signedCommand Signed embedded command + * @param ipcRedirect IPC redirect flag + * @return result JSON + * @throws SlCommandoBuildException In case of an error + */ + public static ObjectNode createRedirectCommandParameters(final String url, final ObjectNode command, + final ObjectNode signedCommand, final Boolean ipcRedirect) throws SlCommandoBuildException { + final ObjectNode redirectReqParams = mapper.getMapper().createObjectNode(); + addOnlyOnceOfTwo(redirectReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_COMMAND, + SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_SIGNEDCOMMAND, command, signedCommand); + addSingleStringElement(redirectReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_URL, url, false); + addSingleBooleanElement(redirectReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_REDIRECT_IPCREDIRECT, + ipcRedirect, false); + return redirectReqParams; + + } + + /** + * Create parameters for Call command. + * + * @param url http URL for Call command + * @param method http method used by call commando result + * @param includeTransactionId TransactionId + * @param reqParameters Request parameters on CALL command + * @return JSON + * @throws SlCommandoBuildException In case of an error + */ + public static ObjectNode createCallCommandParameters(final String url, final String method, + final Boolean includeTransactionId, final Map<String, String> reqParameters) throws SlCommandoBuildException { + final ObjectNode callReqParams = mapper.getMapper().createObjectNode(); + addSingleStringElement(callReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_CALL_URL, url, true); + addSingleStringElement(callReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_CALL_METHOD, method, true); + addSingleBooleanElement(callReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_CALL_INCLUDETRANSACTIONID, + includeTransactionId, false); + addArrayOfStringElements(callReqParams, SL20Constants.SL20_COMMAND_PARAM_GENERAL_CALL_REQPARAMETER, reqParameters); + return callReqParams; + + } + + /** + * Create result for Error command. + * + * @param errorCode Error-Code + * @param errorMsg Error-message + * @return JSON + * @throws SlCommandoBuildException In case of an error + */ + public static ObjectNode createErrorCommandResult(final String errorCode, final String errorMsg) + throws SlCommandoBuildException { + final ObjectNode result = mapper.getMapper().createObjectNode(); + addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORCODE, errorCode, true); + addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORMESSAGE, errorMsg, true); + return result; + + } + + /** + * Create parameters for qualifiedeID command. + * + * @param consentTemplateId Identifier of the template that is used for consent + * visualization + * @param consent Consent that has to be signed by user + * @param dataUrl DataURL for result + * @param x5cEnc Response encryption certificate + * @return JSON + * @throws CertificateEncodingException In case of a encryption certificate + * encoding problem + * @throws SlCommandoBuildException In case of a generel error + */ + public static ObjectNode createQualifiedeEidConsent(final String consentTemplateId, final byte[] consent, + final String dataUrl, final X509Certificate x5cEnc) + throws CertificateEncodingException, SlCommandoBuildException { + final ObjectNode params = mapper.getMapper().createObjectNode(); + addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_CONSENTTEMPLATEID, consentTemplateId, true); + addSingleByteElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_CONSENT, consent, true); + addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_DATAURL, dataUrl, true); + addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_X5CENC, x5cEnc, false); + return params; + + } + + /** + * Create parameters for qualifiedeID command. + * + * @param authBlockId AuthBlock transformation Id + * @param dataUrl DataURL for result + * @param additionalReqParameters additional parameters + * @param x5cEnc Response encryption certificate + * @return JSON + * @throws CertificateEncodingException In case of a encryption certificate + * encoding problem + * @throws SlCommandoBuildException In case of a generel error + */ + @Deprecated + public static ObjectNode createQualifiedEidCommandParameters(final String authBlockId, final String dataUrl, + final Map<String, String> additionalReqParameters, final X509Certificate x5cEnc) + throws CertificateEncodingException, SlCommandoBuildException { + final ObjectNode params = mapper.getMapper().createObjectNode(); + addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_AUTHBLOCKID, authBlockId, true); + addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_DATAURL, dataUrl, true); + addArrayOfStringElements(params, SL20Constants.SL20_COMMAND_PARAM_EID_ATTRIBUTES, additionalReqParameters); + addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_EID_X5CENC, x5cEnc, false); + return params; + + } + + /** + * Create result for qualifiedeID command. + * + * @param idl IdentityLink + * @param authBlock AuthBlock + * @param ccsUrl VDA URL + * @param loa LoA + * @return JSON + * @throws SlCommandoBuildException In case of an error + */ + public static ObjectNode createQualifiedEidCommandResult(final byte[] idl, final byte[] authBlock, + final String ccsUrl, final String loa) throws SlCommandoBuildException { + final ObjectNode result = mapper.getMapper().createObjectNode(); + addSingleByteElement(result, SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_IDL, idl, true); + addSingleByteElement(result, SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_AUTHBLOCK, authBlock, true); + addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_CCSURL, ccsUrl, true); + addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_LOA, loa, true); + return result; + + } + + /** + * Create Binding-Key command parameters. + * + * @param kontoId KontoId + * @param subjectName SubjectName + * @param keySize KeySize + * @param keyAlg Key-algorithm + * @param policies Key policy + * @param dataUrl DataURL + * @param x5cVdaTrust trusted certificate from VDA + * @param reqUserPassword User passwort initialize request + * @param x5cEnc Result encryption certificate + * @return JSON + * @throws SlCommandoBuildException in case of an errr + * @throws CertificateEncodingException In case of a certificate error + */ + public static ObjectNode createBindingKeyCommandParams(final String kontoId, final String subjectName, + final int keySize, final String keyAlg, final Map<String, String> policies, final String dataUrl, + final X509Certificate x5cVdaTrust, final Boolean reqUserPassword, final X509Certificate x5cEnc) + throws SlCommandoBuildException, CertificateEncodingException { + final ObjectNode params = mapper.getMapper().createObjectNode(); + addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_KONTOID, kontoId, true); + addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_SN, subjectName, true); + addSingleNumberElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_KEYLENGTH, keySize, true); + addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_KEYALG, keyAlg, true); + addArrayOfStringElements(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_POLICIES, policies); + addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_DATAURL, dataUrl, true); + addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_X5CVDATRUST, x5cVdaTrust, + false); + addSingleBooleanElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_REQUESTUSERPASSWORD, + reqUserPassword, false); + addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_X5CENC, x5cEnc, false); + return params; + + } + + /** + * Create Binding-Key command result. + * + * @param appId AppId + * @param csr CSR + * @param attCert Key-Attestation certificate + * @param password user's password + * @return JSON + * @throws SlCommandoBuildException In case of an error + * @throws CertificateEncodingException In case of a certificate processing + * error + */ + public static ObjectNode createBindingKeyCommandResult(final String appId, final byte[] csr, + final X509Certificate attCert, final byte[] password) + throws SlCommandoBuildException, CertificateEncodingException { + final ObjectNode result = mapper.getMapper().createObjectNode(); + addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_APPID, appId, true); + addSingleByteElement(result, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_CSR, csr, true); + addSingleCertificateElement(result, + SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_KEYATTESTATIONZERTIFICATE, attCert, false); + addSingleByteElement(result, SL20Constants.SL20_COMMAND_PARAM_BINDING_CREATE_RESULT_USERPASSWORD, password, false); + return result; + + } + + /** + * Create Store Binding-Certificate command parameters. + * + * @param cert Certificate + * @param dataUrl DATA URL + * @return JSON + * @throws CertificateEncodingException In case of a certificate processing + * error + * @throws SlCommandoBuildException In case of a error + */ + public static ObjectNode createStoreBindingCertCommandParams(final X509Certificate cert, final String dataUrl) + throws CertificateEncodingException, SlCommandoBuildException { + final ObjectNode params = mapper.getMapper().createObjectNode(); + addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_STORE_CERTIFICATE, cert, true); + addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_BINDING_STORE_DATAURL, dataUrl, true); + return params; + + } + + /** + * Create Store Binding-Certificate command result. + * + * @return JSON + * @throws SlCommandoBuildException In case of an error + */ + public static ObjectNode createStoreBindingCertCommandSuccessResult() throws SlCommandoBuildException { + final ObjectNode result = mapper.getMapper().createObjectNode(); + addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_BINDING_STORE_RESULT_SUCESS, + SL20Constants.SL20_COMMAND_PARAM_BINDING_STORE_RESULT_SUCESS_VALUE, true); + return result; + + } + + /** + * Create idAndPassword command parameters. + * + * @param keyAlg key algorithm + * @param dataUrl DATA Url + * @param x5cEnc result encryption certificate + * @return JSON + * @throws SlCommandoBuildException In case of an error + * @throws CertificateEncodingException In case of a certificate processing + * error + */ + public static ObjectNode createIdAndPasswordCommandParameters(final String keyAlg, final String dataUrl, + final X509Certificate x5cEnc) throws SlCommandoBuildException, CertificateEncodingException { + final ObjectNode params = mapper.getMapper().createObjectNode(); + addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_KEYALG, keyAlg, true); + addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_DATAURL, dataUrl, true); + addSingleCertificateElement(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_X5CENC, x5cEnc, false); + return params; + + } + + /** + * Create idAndPassword command result. + * + * @param kontoId User's Id + * @param password User's password + * @return JSON + * @throws SlCommandoBuildException In case of an error + */ + public static ObjectNode createIdAndPasswordCommandResult(final String kontoId, final byte[] password) + throws SlCommandoBuildException { + final ObjectNode result = mapper.getMapper().createObjectNode(); + addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_RESULT_KONTOID, kontoId, true); + addSingleByteElement(result, SL20Constants.SL20_COMMAND_PARAM_AUTH_IDANDPASSWORD_RESULT_USERPASSWORD, password, + true); + return result; + + } + + /** + * Create JWS Token Authentication command. + * + * @param nonce nonce that should be signed + * @param dataUrl Data URL + * @param displayData Data that should be displayed + * @param displayUrl URL to data that should be displayed + * @return JSON + * @throws SlCommandoBuildException In case of an error + */ + public static ObjectNode createJwsTokenAuthCommandParams(final String nonce, final String dataUrl, + final List<String> displayData, final List<String> displayUrl) throws SlCommandoBuildException { + final ObjectNode params = mapper.getMapper().createObjectNode(); + addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_JWSTOKEN_NONCE, nonce, true); + addSingleStringElement(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_JWSTOKEN_DATAURL, dataUrl, true); + addArrayOfStrings(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_JWSTOKEN_DISPLAYDATA, displayData); + addArrayOfStrings(params, SL20Constants.SL20_COMMAND_PARAM_AUTH_JWSTOKEN_DISPLAYURL, displayUrl); + return params; + + } + + /** + * Create JWS Token Authentication command result. + * + * @param nonce Serialzed JWS that contains the signed nonce + * @return JSON + * @throws SlCommandoBuildException In case of an error + */ + public static ObjectNode createJwsTokenAuthCommandResult(final String nonce) throws SlCommandoBuildException { + final ObjectNode result = mapper.getMapper().createObjectNode(); + addSingleStringElement(result, SL20Constants.SL20_COMMAND_PARAM_AUTH_JWSTOKEN_RESULT_NONCE, nonce, true); + return result; + + } + + /** + * Create Generic Request Container. + * + * @param reqId RequestId + * @param transactionId TransactionId + * @param payLoad unsigned payload + * @param signedPayload Signed payload + * @return JSON + * @throws SlCommandoBuildException In case of an error + */ + public static ObjectNode createGenericRequest(final String reqId, final String transactionId, + final ObjectNode payLoad, final String signedPayload) throws SlCommandoBuildException { + final ObjectNode req = mapper.getMapper().createObjectNode(); + addSingleIntegerElement(req, SL20Constants.SL20_VERSION, SL20Constants.CURRENT_SL20_VERSION, true); + addSingleStringElement(req, SL20Constants.SL20_REQID, reqId, true); + addSingleStringElement(req, SL20Constants.SL20_TRANSACTIONID, transactionId, false); + addOnlyOnceOfTwo(req, SL20Constants.SL20_PAYLOAD, SL20Constants.SL20_SIGNEDPAYLOAD, payLoad, signedPayload); + return req; + + } + + /** + * Create Generic Response Container. + * + * @param respId Response Id + * @param inResponseTo RequestId to this response + * @param transactionId transactionId + * @param payLoad Unsigned payload + * @param signedPayload Signed payload + * @return JSON + * @throws SlCommandoBuildException In case of an error + */ + public static final ObjectNode createGenericResponse(final String respId, final String inResponseTo, + final String transactionId, final ObjectNode payLoad, final String signedPayload) + throws SlCommandoBuildException { + final ObjectNode req = mapper.getMapper().createObjectNode(); + addSingleIntegerElement(req, SL20Constants.SL20_VERSION, SL20Constants.CURRENT_SL20_VERSION, true); + addSingleStringElement(req, SL20Constants.SL20_RESPID, respId, true); + addSingleStringElement(req, SL20Constants.SL20_INRESPTO, inResponseTo, false); + addSingleStringElement(req, SL20Constants.SL20_TRANSACTIONID, transactionId, false); + addOnlyOnceOfTwo(req, SL20Constants.SL20_PAYLOAD, SL20Constants.SL20_SIGNEDPAYLOAD, payLoad, signedPayload); + return req; + + } + + private static void addOnlyOnceOfTwo(final ObjectNode parent, final String firstKeyId, final String secondKeyId, + final ObjectNode first, final ObjectNode second) throws SlCommandoBuildException { + if (first == null && second == null) { + throw new SlCommandoBuildException(firstKeyId + " and " + secondKeyId + " is NULL"); + } else if (first != null && second != null) { + throw new SlCommandoBuildException(firstKeyId + " and " + secondKeyId + " can not SET TWICE"); + } else if (first != null) { + parent.set(firstKeyId, first); + } else if (second != null) { + parent.set(secondKeyId, second); + } else { + throw new SlCommandoBuildException("Internal build error"); + } + } + + /** + * Add one element of two possible elements <br> + * This method adds either the first element or the second element to parent + * JSON, but never both. + * + * @param parent Parent JSON element + * @param firstKeyId first element Id + * @param secondKeyId second element Id + * @param first first element + * @param second second element + * @throws SlCommandoBuildException In case of an error. + */ + public static void addOnlyOnceOfTwo(final ObjectNode parent, final String firstKeyId, final String secondKeyId, + final ObjectNode first, final String second) throws SlCommandoBuildException { + if (first == null && (second == null || second.isEmpty())) { + throw new SlCommandoBuildException(firstKeyId + " and " + secondKeyId + " is NULL"); + } else if (first != null && second != null) { + throw new SlCommandoBuildException(firstKeyId + " and " + secondKeyId + " can not SET TWICE"); + } else if (first != null) { + parent.set(firstKeyId, first); + } else if (second != null && !second.isEmpty()) { + parent.put(secondKeyId, second); + } else { + throw new SlCommandoBuildException("Internal build error"); + } + } + + // TODO!!!! + private static ObjectNode createJsonSignedHeader() throws SlCommandoBuildException { + final ObjectNode header = mapper.getMapper().createObjectNode(); + addSingleStringElement(header, SL20Constants.JSON_ALGORITHM, SL20Constants.JSON_ALGORITHM_SIGNING_RS256, true); + addSingleStringElement(header, SL20Constants.JSON_CONTENTTYPE, SL20Constants.SL20_CONTENTTYPE_SIGNED_COMMAND, true); + addArrayOfStrings(header, SL20Constants.JSON_X509_CERTIFICATE, Arrays.asList(Constants.DUMMY_SIGNING_CERT)); + + return header; + } + + // TODO!!!! + private static ObjectNode createJsonEncryptionHeader() throws SlCommandoBuildException { + final ObjectNode header = mapper.getMapper().createObjectNode(); + addSingleStringElement(header, SL20Constants.JSON_ALGORITHM, SL20Constants.JSON_ALGORITHM_ENC_KEY_RSAOAEP, true); + addSingleStringElement(header, SL20Constants.JSON_ENCRYPTION_PAYLOAD, + SL20Constants.JSON_ALGORITHM_ENC_PAYLOAD_A128CBCHS256, true); + addSingleStringElement(header, SL20Constants.JSON_CONTENTTYPE, SL20Constants.SL20_CONTENTTYPE_ENCRYPTED_RESULT, + true); + addSingleStringElement(header, SL20Constants.JSON_X509_FINGERPRINT, Constants.DUMMY_SIGNING_CERT_FINGERPRINT, true); + + return header; + } + + // TODO!!!! + private static String createJsonSignedFooter() { + return "cC4hiUPoj9Eetdgtv3hF80EGrhuB__dzERat0XF9g2VtQgr9PJbu3XOiZj5RZmh7\n" + + " AAuHIm4Bh-0Qc_lF5YKt_O8W2Fp5jujGbds9uJdbF9CUAr7t1dnZcAcQjbKBYNX4\n" + + " BAynRFdiuB--f_nZLgrnbyTyWzO75vRK5h6xBArLIARNPvkSjtQBMHlb1L07Qe7K\n" + + " 0GarZRmB_eSN9383LcOLn6_dO--xi12jzDwusC-eOkHWEsqtFZESc6BfI7noOPqv\n" + + " hJ1phCnvWh6IeYI2w9QOYEUipUTI8np6LbgGY9Fs98rqVt5AXLIhWkWywlVmtVrB\n" + " p0igcN_IoypGlUPQGe77Rw"; + } + + private static void addArrayOfStrings(final ObjectNode parent, final String keyId, final List<String> values) + throws SlCommandoBuildException { + validateParentAndKey(parent, keyId); + if (values != null) { + final ArrayNode callReqParamsArray = mapper.getMapper().createArrayNode(); + parent.set(keyId, callReqParamsArray); + for (final String el : values) { + callReqParamsArray.add(el); + } + + } + } + + private static void addArrayOfStringElements(final ObjectNode parent, final String keyId, + final Map<String, String> keyValuePairs) throws SlCommandoBuildException { + validateParentAndKey(parent, keyId); + if (keyValuePairs != null) { + final ArrayNode callReqParamsArray = mapper.getMapper().createArrayNode(); + parent.set(keyId, callReqParamsArray); + + for (final Entry<String, String> el : keyValuePairs.entrySet()) { + final ObjectNode callReqParams = mapper.getMapper().createObjectNode(); + callReqParams.put(el.getKey(), el.getValue()); + callReqParamsArray.add(callReqParams); + + } + } + } + + private static void addSingleCertificateElement(final ObjectNode parent, final String keyId, + final X509Certificate cert, final boolean isRequired) + throws CertificateEncodingException, SlCommandoBuildException { + if (cert != null) { + addSingleByteElement(parent, keyId, cert.getEncoded(), isRequired); + } else if (isRequired) { + throw new SlCommandoBuildException(keyId + " is marked as REQUIRED"); + } + + } + + private static void addSingleByteElement(final ObjectNode parent, final String keyId, final byte[] value, + final boolean isRequired) throws SlCommandoBuildException { + validateParentAndKey(parent, keyId); + + if (isRequired && value == null) { + throw new SlCommandoBuildException(keyId + " has NULL value"); + } else if (value != null) { + parent.put(keyId, Base64.getEncoder().encodeToString(value)); + } + + } + + private static void addSingleBooleanElement(final ObjectNode parent, final String keyId, final Boolean value, + final boolean isRequired) throws SlCommandoBuildException { + validateParentAndKey(parent, keyId); + + if (isRequired && value == null) { + throw new SlCommandoBuildException(keyId + " has a NULL value"); + } else if (value != null) { + parent.put(keyId, value); + } + + } + + private static void addSingleNumberElement(final ObjectNode parent, final String keyId, final Integer value, + final boolean isRequired) throws SlCommandoBuildException { + validateParentAndKey(parent, keyId); + + if (isRequired && value == null) { + throw new SlCommandoBuildException(keyId + " has a NULL value"); + } else if (value != null) { + parent.put(keyId, value); + } + + } + + private static void addSingleStringElement(final ObjectNode parent, final String keyId, final String value, + final boolean isRequired) throws SlCommandoBuildException { + validateParentAndKey(parent, keyId); + + if (isRequired && (value == null || value.isEmpty())) { + throw new SlCommandoBuildException(keyId + " has an empty value"); + } else if (value != null && !value.isEmpty()) { + parent.put(keyId, value); + } + + } + + private static void addSingleIntegerElement(final ObjectNode parent, final String keyId, final Integer value, + final boolean isRequired) throws SlCommandoBuildException { + validateParentAndKey(parent, keyId); + + if (isRequired && value == null) { + throw new SlCommandoBuildException(keyId + " has an empty value"); + } else if (value != null) { + parent.put(keyId, value); + } + + } + + private static void addSingleJsonElement(final ObjectNode parent, final String keyId, final ObjectNode element, + final boolean isRequired) throws SlCommandoBuildException { + validateParentAndKey(parent, keyId); + + if (isRequired && element == null) { + throw new SlCommandoBuildException("No commando name included"); + } else if (element != null) { + parent.set(keyId, element); + } + + } + + private static void validateParentAndKey(final ObjectNode parent, final String keyId) + throws SlCommandoBuildException { + if (parent == null) { + throw new SlCommandoBuildException("NO parent JSON element"); + } + + if (keyId == null || keyId.isEmpty()) { + throw new SlCommandoBuildException("NO JSON element identifier"); + } + } +} diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JsonExtractorUtils.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JsonExtractorUtils.java new file mode 100644 index 00000000..eb6de461 --- /dev/null +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20JsonExtractorUtils.java @@ -0,0 +1,389 @@ +package at.gv.egiz.eaaf.modules.auth.sl20.utils; + +import java.util.ArrayList; +import java.util.Base64; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.http.Header; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.util.EntityUtils; +import org.jose4j.base64url.Base64Url; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + +import at.gv.egiz.eaaf.modules.auth.sl20.data.VerificationResult; +import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20Exception; +import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SlCommandoParserException; + +public class SL20JsonExtractorUtils { + private static final Logger log = LoggerFactory.getLogger(SL20JsonExtractorUtils.class); + private static JsonMapper mapper = new JsonMapper(); + + /** + * Extract String value from JSON. + * + * @param input JSON + * @param keyID Element identifier + * @param isRequired true, if the element must not null + * @return Value of this element + * @throws SlCommandoParserException In case an error + */ + public static String getStringValue(final JsonNode input, final String keyID, final boolean isRequired) + throws SlCommandoParserException { + try { + final JsonNode internal = getAndCheck(input, keyID, isRequired); + + if (internal != null) { + return internal.asText(); + } else { + return null; + } + + } catch (final SlCommandoParserException e) { + throw e; + + } catch (final Exception e) { + throw new SlCommandoParserException("Can not extract String value with keyId: " + keyID, e); + + } + } + + /** + * Extract Boolean value from JSON. + * + * @param input JSON + * @param keyID Element identifier + * @param isRequired true, if the element must not null + * @return Boolean + * @throws SlCommandoParserException In case of an error + */ + public static boolean getBooleanValue(final ObjectNode input, final String keyID, final boolean isRequired, + final boolean defaultValue) throws SlCommandoParserException { + try { + final JsonNode internal = getAndCheck(input, keyID, isRequired); + + if (internal != null) { + return internal.asBoolean(); + } else { + return defaultValue; + } + + } catch (final SlCommandoParserException e) { + throw e; + + } catch (final Exception e) { + throw new SlCommandoParserException("Can not extract Boolean value with keyId: " + keyID, e); + + } + } + + /** + * Extract JSONObject value from JSON. + * + * @param input JSON + * @param keyID Element identifier + * @param isRequired true, if the element must not null + * @return JSON node + * @throws SlCommandoParserException In case of an error + */ + public static JsonNode getJsonObjectValue(final JsonNode input, final String keyID, final boolean isRequired) + throws SlCommandoParserException { + try { + final JsonNode internal = getAndCheck(input, keyID, isRequired); + + if (internal != null) { + return internal; + } else { + return null; + } + + } catch (final SlCommandoParserException e) { + throw e; + + } catch (final Exception e) { + throw new SlCommandoParserException("Can not extract Boolean value with keyId: " + keyID, e); + + } + } + + /** + * Extract a List of String elements from a JSON element. + * + * @param input JSON + * @return List of Elements in this node + * @throws SlCommandoParserException In case of an error + */ + public static List<String> getListOfStringElements(final JsonNode input) throws SlCommandoParserException { + final List<String> result = new ArrayList<>(); + if (input != null) { + if (input.isArray()) { + final Iterator<JsonNode> arrayIterator = input.iterator(); + while (arrayIterator.hasNext()) { + final JsonNode next = arrayIterator.next(); + if (next.isTextual()) { + result.add(next.asText()); + } + } + + } else if (input.isTextual()) { + result.add(input.asText()); + + } else { + log.warn("JSON Element IS NOT a JSON array or a JSON Primitive"); + throw new SlCommandoParserException("JSON Element IS NOT a JSON array or a JSON Primitive"); + + } + } + + return result; + } + + /** + * Extract Map of Key/Value pairs from a JSON Element. + * + * @param input parent JSON object + * @param keyID KeyId of the child that should be parsed + * @param isRequired true, if the element must not null + * @return Map of element pairs + * @throws SlCommandoParserException In case of an error + */ + public static Map<String, String> getMapOfStringElements(final JsonNode input, final String keyID, + final boolean isRequired) throws SlCommandoParserException { + final JsonNode internal = getAndCheck(input, keyID, isRequired); + return getMapOfStringElements(internal); + + } + + /** + * Extract Map of Key/Value pairs from a JSON Element. + * + * @param input JSON + * @return Map of element pairs + * @throws SlCommandoParserException in case of an error + */ + public static Map<String, String> getMapOfStringElements(final JsonNode input) throws SlCommandoParserException { + final Map<String, String> result = new HashMap<>(); + + if (input != null) { + if (input.isArray()) { + final Iterator<JsonNode> arrayIterator = input.iterator(); + while (arrayIterator.hasNext()) { + final JsonNode next = arrayIterator.next(); + final Iterator<Entry<String, JsonNode>> entry = next.fields(); + entitySetToMap(result, entry); + + } + + } else if (input.isObject()) { + final Iterator<Entry<String, JsonNode>> objectKeys = input.fields(); + entitySetToMap(result, objectKeys); + + } else { + throw new SlCommandoParserException("JSON Element IS NOT a JSON array or a JSON object"); + } + + } + + return result; + } + + private static void entitySetToMap(final Map<String, String> result, final Iterator<Entry<String, JsonNode>> entry) { + while (entry.hasNext()) { + final Entry<String, JsonNode> el = entry.next(); + if (result.containsKey(el.getKey())) { + log.info("Attr. Map already contains Element with Key: " + el.getKey() + ". Overwrite element ... "); + } + + result.put(el.getKey(), el.getValue().asText()); + + } + + } + + /** + * Extract Security-Layer 2.0 result from response object. + * + * @param command SL2.0 command + * @param decrypter JWS decrypter implementation + * @param mustBeEncrypted if <code>true</code>, the result must be encrypted + * @return decrypted JSON + * @throws SL20Exception In case of an error + */ + public static JsonNode extractSL20Result(final JsonNode command, final IJoseTools decrypter, + final boolean mustBeEncrypted) throws SL20Exception { + final JsonNode result = command.get(SL20Constants.SL20_COMMAND_CONTAINER_RESULT); + final JsonNode encryptedResult = command.get(SL20Constants.SL20_COMMAND_CONTAINER_ENCRYPTEDRESULT); + + if (result == null && encryptedResult == null) { + throw new SlCommandoParserException("NO result OR encryptedResult FOUND."); + } else if (encryptedResult == null && mustBeEncrypted) { + throw new SlCommandoParserException("result MUST be encrypted."); + } else if (encryptedResult != null && encryptedResult.isTextual()) { + try { + return decrypter.decryptPayload(encryptedResult.asText()); + + } catch (final Exception e) { + log.info("Can NOT decrypt SL20 result. Reason:" + e.getMessage()); + if (!mustBeEncrypted) { + log.warn("Decrypted results are disabled by configuration. Parse result in plain if it is possible"); + + // dummy code + try { + final String[] signedPayload = encryptedResult.toString().split("\\."); + final JsonNode payLoad = mapper.getMapper() + .readTree(new String(Base64.getUrlDecoder().decode(signedPayload[1]), "UTF-8")); + return payLoad; + + } catch (final Exception e1) { + log.debug("DummyCode FAILED, Reason: " + e1.getMessage() + " Ignore it ..."); + throw new SL20Exception(e.getMessage(), null, e); + + } + + } else { + throw e; + } + + } + + } else if (result != null) { + return result; + + } else { + throw new SlCommandoParserException("Internal build error"); + } + + } + + /** + * Extract payLoad from generic transport container. + * + * @param container JSON + * @param joseTools JWS implementation + * @return Signature verification result that contains the payLoad + * @throws SlCommandoParserException In case of an error + */ + public static VerificationResult extractSL20PayLoad(final JsonNode container, final IJoseTools joseTools, + final boolean mustBeSigned) throws SL20Exception { + + final JsonNode sl20Payload = container.get(SL20Constants.SL20_PAYLOAD); + final JsonNode sl20SignedPayload = container.get(SL20Constants.SL20_SIGNEDPAYLOAD); + + if (mustBeSigned && joseTools == null) { + throw new SlCommandoParserException("'joseTools' MUST be set if 'mustBeSigned' is 'true'"); + } + + if (sl20Payload == null && sl20SignedPayload == null) { + throw new SlCommandoParserException("NO payLoad OR signedPayload FOUND."); + } else if (sl20SignedPayload == null && mustBeSigned) { + throw new SlCommandoParserException("payLoad MUST be signed."); + } else if (joseTools != null && sl20SignedPayload != null && sl20SignedPayload.isTextual()) { + return joseTools.validateSignature(sl20SignedPayload.asText()); + + } else if (sl20Payload != null) { + return new VerificationResult(sl20Payload); + } else { + throw new SlCommandoParserException("Internal build error"); + } + + } + + /** + * Extract generic transport container from httpResponse. + * + * @param httpResp Http response object + * @return JSON with SL2.0 response + * @throws SlCommandoParserException In case of an error + */ + public static JsonNode getSL20ContainerFromResponse(final HttpResponse httpResp) throws SlCommandoParserException { + try { + JsonNode sl20Resp = null; + if (httpResp.getStatusLine().getStatusCode() == 303 || httpResp.getStatusLine().getStatusCode() == 307) { + final Header[] locationHeader = httpResp.getHeaders("Location"); + if (locationHeader == null) { + throw new SlCommandoParserException("Find Redirect statuscode but not Location header"); + } + + final String sl20RespString = new URIBuilder(locationHeader[0].getValue()).getQueryParams().get(0).getValue(); + sl20Resp = mapper.getMapper().readTree(Base64Url.decode(sl20RespString)); + + } else if (httpResp.getStatusLine().getStatusCode() == 200) { + if (httpResp.getEntity().getContentType() == null) { + throw new SlCommandoParserException("SL20 response contains NO ContentType"); + } + + if (!httpResp.getEntity().getContentType().getValue().startsWith("application/json")) { + throw new SlCommandoParserException( + "SL20 response with a wrong ContentType: " + httpResp.getEntity().getContentType().getValue()); + } + sl20Resp = parseSL20ResultFromResponse(httpResp.getEntity()); + + } else if (httpResp.getStatusLine().getStatusCode() == 500 || httpResp.getStatusLine().getStatusCode() == 401 + || httpResp.getStatusLine().getStatusCode() == 400) { + log.info( + "SL20 response with http-code: " + httpResp.getStatusLine().getStatusCode() + ". Search for error message"); + + try { + sl20Resp = parseSL20ResultFromResponse(httpResp.getEntity()); + + } catch (final Exception e) { + log.warn("SL20 response contains no valid JSON", e); + throw new SlCommandoParserException("SL20 response with http-code: " + + httpResp.getStatusLine().getStatusCode() + " AND NO valid JSON errormsg", e); + + } + + } else { + throw new SlCommandoParserException( + "SL20 response with http-code: " + httpResp.getStatusLine().getStatusCode()); + } + + log.info("Find JSON object in http response"); + return sl20Resp; + + } catch (final Exception e) { + throw new SlCommandoParserException("SL20 response parsing FAILED! Reason: " + e.getMessage(), e); + + } + } + + private static JsonNode parseSL20ResultFromResponse(final HttpEntity resp) throws Exception { + if (resp != null && resp.getContent() != null) { + final String rawSL20Resp = EntityUtils.toString(resp); + final JsonNode sl20Resp = mapper.getMapper().readTree(rawSL20Resp); + + // TODO: check sl20Resp type like && sl20Resp.isJsonObject() + if (sl20Resp != null) { + return sl20Resp; + + } else { + throw new SlCommandoParserException("SL2.0 can NOT parse to a JSON object"); + } + + } else { + throw new SlCommandoParserException("Can NOT find content in http response"); + } + + } + + private static JsonNode getAndCheck(final JsonNode input, final String keyID, final boolean isRequired) + throws SlCommandoParserException { + final JsonNode internal = input.get(keyID); + + if (internal == null && isRequired) { + throw new SlCommandoParserException("REQUIRED Element with keyId: " + keyID + " does not exist"); + } + + return internal; + + } +} diff --git a/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20ResponseUtils.java b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20ResponseUtils.java new file mode 100644 index 00000000..4bb91634 --- /dev/null +++ b/eaaf_modules/eaaf_module_auth_sl20/src/main/java/at/gv/egiz/eaaf/modules/auth/sl20/utils/SL20ResponseUtils.java @@ -0,0 +1,166 @@ +package at.gv.egiz.eaaf.modules.auth.sl20.utils; + +import java.io.IOException; +import java.io.StringWriter; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import at.gv.egiz.eaaf.core.api.IRequest; +import at.gv.egiz.eaaf.core.api.data.EaafConstants; +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.modules.auth.sl20.Constants; +import at.gv.egiz.eaaf.modules.auth.sl20.exceptions.SL20Exception; + +import org.apache.commons.lang3.StringUtils; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.entity.ContentType; + +import com.fasterxml.jackson.databind.node.ObjectNode; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class SL20ResponseUtils { + private static final String PATTERN_PENDING_REQ_ID = "#PENDINGREQID#"; + + /** + * Build a generic SL2.x error-response without redirect to AuthHandler. + * + * @param response http response object + * @param errorCode ErrorCode + * @param errorMsg Error message + * @throws Exception In case of a message generation error + */ + public static void buildErrorResponse(final HttpServletResponse response, + final String errorCode, final String errorMsg) + throws Exception { + final ObjectNode error = SL20JsonBuilderUtils.createErrorCommandResult(errorCode, errorMsg); + final ObjectNode errorCommand = SL20JsonBuilderUtils + .createCommandResponse(SL20Constants.SL20_COMMAND_IDENTIFIER_ERROR, error, null); + + final ObjectNode respContainer = SL20JsonBuilderUtils.createGenericResponse(UUID.randomUUID().toString(), null, + null, errorCommand, null); + + log.trace("SL20 response to VDA: " + respContainer); + final StringWriter writer = new StringWriter(); + writer.write(respContainer.toString()); + final byte[] content = writer.toString().getBytes("UTF-8"); + response.setStatus(HttpServletResponse.SC_OK); + response.setContentLength(content.length); + response.setContentType(ContentType.APPLICATION_JSON.toString()); + response.getOutputStream().write(content); + + } + + /** + * Build a Security-Layer 2.x conform redirect response. + * + * @param request http request + * @param response http response + * @param pendingReq Current pending request + * @param fullRedirectUrl Endpoint, where the auth. process should be resumed after redirect + * @param transactionId SL2.0 transactionId if available + * @param authConfig Basic application configuration + * @throws IOException In case of a http servlet error + * @throws SL20Exception In case of a SL2.0 request generation error + * @throws URISyntaxException In case of an invalid Redirect URL + */ + public static void buildResponse(final HttpServletRequest request, final HttpServletResponse response, + IRequest pendingReq, String fullRedirectUrl, String transactionId, IConfiguration authConfig) + throws IOException, SL20Exception, URISyntaxException { + // create response + final Map<String, String> reqParameters = new HashMap<>(); + + final URL redirectUrl = new URL(fullRedirectUrl); + if (redirectUrl.getQuery() != null) { + final String [] elements = redirectUrl.getQuery().split("&"); + for (final String element : elements) { + final String[] keyValue = element.split("="); + if (keyValue.length == 2) { + reqParameters.put(keyValue[0], keyValue[1]); + + } else { + log.warn("Ignore parameter with name: {}", keyValue[0]); + + } + } + } + + //reqParameters.put(EaafConstants.PARAM_HTTP_TARGET_PENDINGREQUESTID, pendingReq.getPendingRequestId()); + + final ObjectNode callReqParams = SL20JsonBuilderUtils.createCallCommandParameters( + fullRedirectUrl.split("\\?")[0], + SL20Constants.SL20_COMMAND_PARAM_GENERAL_CALL_METHOD_GET, false, reqParameters); + final ObjectNode callCommand = SL20JsonBuilderUtils.createCommand(SL20Constants.SL20_COMMAND_IDENTIFIER_CALL, + callReqParams); + + // build first redirect command for app + final ObjectNode redirectOneParams = SL20JsonBuilderUtils + .createRedirectCommandParameters(generateIpcRedirectUrlForDebugging( + pendingReq, + authConfig.getBasicConfiguration(Constants.CONFIG_PROP_IPC_RETURN_URL)), + callCommand, null, true); + final ObjectNode redirectOneCommand = SL20JsonBuilderUtils + .createCommand(SL20Constants.SL20_COMMAND_IDENTIFIER_REDIRECT, redirectOneParams); + + // build second redirect command for IDP + final ObjectNode redirectTwoParams = SL20JsonBuilderUtils.createRedirectCommandParameters( + fullRedirectUrl, + redirectOneCommand, null, false); + final ObjectNode redirectTwoCommand = SL20JsonBuilderUtils + .createCommand(SL20Constants.SL20_COMMAND_IDENTIFIER_REDIRECT, redirectTwoParams); + + // build generic SL2.0 response container + final ObjectNode respContainer = SL20JsonBuilderUtils.createGenericRequest(UUID.randomUUID().toString(), + transactionId, redirectTwoCommand, null); + + if (request.getHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE) != null && request + .getHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE).equals(SL20Constants.HTTP_HEADER_VALUE_NATIVE)) { + log.debug("Client request containts 'native client' header ... "); + log.trace("SL20 response to VDA: " + respContainer); + final StringWriter writer = new StringWriter(); + writer.write(respContainer.toString()); + final byte[] content = writer.toString().getBytes("UTF-8"); + response.setStatus(HttpServletResponse.SC_OK); + response.setContentLength(content.length); + response.setContentType(ContentType.APPLICATION_JSON.toString()); + response.getOutputStream().write(content); + + } else { + log.info("SL2.0 DataURL communication needs http header: '" + SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE + "'"); + + log.debug("Client request containts is no native client ... "); + final URIBuilder clientRedirectUri = new URIBuilder(fullRedirectUrl); + response.setStatus(Integer.parseInt(authConfig.getBasicConfiguration(Constants.CONFIG_PROP_HTTP_REDIRECT_CODE, + Constants.CONFIG_PROP_HTTP_REDIRECT_CODE_DEFAULT_VALUE))); + response.setHeader("Location", clientRedirectUri.build().toString()); + + } + } + + /** + * Generates a IPC redirect URL that is configured on IDP side. + * + * @return IPC ReturnURL, or null if no URL is configured + */ + private static String generateIpcRedirectUrlForDebugging(IRequest pendingReq, String ipcRedirectUrlConfig) { + if (StringUtils.isNotEmpty(ipcRedirectUrlConfig)) { + if (ipcRedirectUrlConfig.contains(PATTERN_PENDING_REQ_ID)) { + log.trace("Find 'pendingReqId' pattern in IPC redirect URL. Update url ... "); + ipcRedirectUrlConfig = ipcRedirectUrlConfig.replaceAll("#PENDINGREQID#", + EaafConstants.PARAM_HTTP_TARGET_PENDINGREQUESTID + "=" + pendingReq.getPendingRequestId()); + + } + + return ipcRedirectUrlConfig; + } + + return null; + + } +} diff --git a/eaaf_modules/eaaf_module_moa-sig/pom.xml b/eaaf_modules/eaaf_module_moa-sig/pom.xml index 7911d2cb..11b8cfd9 100644 --- a/eaaf_modules/eaaf_module_moa-sig/pom.xml +++ b/eaaf_modules/eaaf_module_moa-sig/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>at.gv.egiz.eaaf</groupId> <artifactId>eaaf_modules</artifactId> - <version>1.0.13.2</version> + <version>1.1.0</version> </parent> <artifactId>eaaf_module_moa-sig</artifactId> <name>MOA-Sig signature verification module</name> diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/api/ISignatureVerificationService.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/api/ISignatureVerificationService.java index a3243635..67e9e29d 100644 --- a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/api/ISignatureVerificationService.java +++ b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/api/ISignatureVerificationService.java @@ -2,83 +2,99 @@ package at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api; import java.util.List; -import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api.data.ICMSSignatureVerificationResponse; -import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api.data.IXMLSignatureVerificationResponse; -import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions.MOASigServiceException; +import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api.data.ICmsSignatureVerificationResponse; +import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api.data.IXmlSignatureVerificationResponse; +import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions.MoaSigServiceException; public interface ISignatureVerificationService { - /** - * Verify a CAdES or CMS signature - * <br><br> - * <i>This method only validates the first CMS or CAdES signature if more than one signature exists</i> - * - * @param signature Enveloped CMS or CAdES signature - * @param trustProfileID Id of the Trust-Profile from MOA-Sig configuration - * @return @link {@link ICMSSignatureVerificationResponse}, or null if no signature was found - * @throws MOASigServiceException on signatue-verification error - */ - ICMSSignatureVerificationResponse verifyCMSSignature(byte[] signature, String trustProfileID) - throws MOASigServiceException; + /** + * Verify a CAdES or CMS signature. <br> + * <br> + * <i>This method only validates the first CMS or CAdES signature if more than + * one signature exists</i> + * + * @param signature Enveloped CMS or CAdES signature + * @param trustProfileID Id of the Trust-Profile from MOA-Sig configuration + * @return @link {@link ICmsSignatureVerificationResponse}, or null if no + * signature was found + * @throws MoaSigServiceException on signatue-verification error + */ + ICmsSignatureVerificationResponse verifyCmsSignature(byte[] signature, String trustProfileID) + throws MoaSigServiceException; + /** + * Verify a XML or XAdES signature. <br> + * <br> + * <i>This method only validates the first XML or XAdES signature if more than + * one signature exists</i> + * + * @param signature Serialized XML or XAdES signature + * @param trustProfileID Id of the Trust-Profile from MOA-Sig configuration + * @return @link {@link IXmlSignatureVerificationResponse}, or null if no + * signature was found + * @throws MoaSigServiceException on signatue-verification error + */ + IXmlSignatureVerificationResponse verifyXmlSignature(byte[] signature, String trustProfileID) + throws MoaSigServiceException; + /** + * Verify a XML or XAdES signature. <br> + * <br> + * <i>This method only validates the first XML or XAdES signature if more than + * one signature exists</i> + * + * @param signature Serialized XML or XAdES signature + * @param trustProfileID Id of the Trust-Profile from MOA-Sig + * configuration + * @param verifyTransformsInfoProfileID {@link List} of XML Transformations that + * should be used for + * signature-verification + * @return @link {@link IXmlSignatureVerificationResponse}, or null if no + * signature was found + * @throws MoaSigServiceException on signatue-verification error + */ + IXmlSignatureVerificationResponse verifyXmlSignature(byte[] signature, String trustProfileID, + List<String> verifyTransformsInfoProfileID) throws MoaSigServiceException; - /** - * Verify a XML or XAdES signature - * <br><br> - * <i>This method only validates the first XML or XAdES signature if more than one signature exists</i> - * - * @param signature Serialized XML or XAdES signature - * @param trustProfileID Id of the Trust-Profile from MOA-Sig configuration - * @return @link {@link IXMLSignatureVerificationResponse}, or null if no signature was found - * @throws MOASigServiceException on signatue-verification error - */ - IXMLSignatureVerificationResponse verifyXMLSignature(byte[] signature, String trustProfileID) - throws MOASigServiceException; + /** + * Verify a XML or XAdES signature. <br> + * <br> + * <i>This method only validates the first XML or XAdES signature if more than + * one signature exists</i> + * + * @param signature Serialized XML or XAdES signature + * @param trustProfileID Id of the Trust-Profile from MOA-Sig + * configuration + * @param signatureLocationXpath Xpath that points to location of Signature + * element + * @return @link {@link IXmlSignatureVerificationResponse}, or null if no + * signature was found + * @throws MoaSigServiceException on signatue-verification error + */ + IXmlSignatureVerificationResponse verifyXmlSignature(byte[] signature, String trustProfileID, + String signatureLocationXpath) throws MoaSigServiceException; - /** - * Verify a XML or XAdES signature - * <br><br> - * <i>This method only validates the first XML or XAdES signature if more than one signature exists</i> - * - * @param signature Serialized XML or XAdES signature - * @param trustProfileID Id of the Trust-Profile from MOA-Sig configuration - * @param verifyTransformsInfoProfileID {@link List} of XML Transformations that should be used for signature-verification - * @return @link {@link IXMLSignatureVerificationResponse}, or null if no signature was found - * @throws MOASigServiceException on signatue-verification error - */ - IXMLSignatureVerificationResponse verifyXMLSignature(byte[] signature, String trustProfileID, - List<String> verifyTransformsInfoProfileID) throws MOASigServiceException; + /** + * Verify a XML or XAdES signature. <br> + * <br> + * <i>This method only validates the first XML or XAdES signature if more than + * one signature exists</i> + * + * @param signature Serialized XML or XAdES signature + * @param trustProfileID Id of the Trust-Profile from MOA-Sig + * configuration + * @param verifyTransformsInfoProfileID {@link List} of XML Transformations that + * should be used for + * signature-verification + * @param signatureLocationXpath Xpath that points to location of + * Signature element + * @return @link {@link IXmlSignatureVerificationResponse}, or null if no + * signature was found + * @throws MoaSigServiceException on signatue-verification error + */ + IXmlSignatureVerificationResponse verifyXmlSignature(byte[] signature, String trustProfileID, + List<String> verifyTransformsInfoProfileID, String signatureLocationXpath) + throws MoaSigServiceException; - - /** - * Verify a XML or XAdES signature - * <br><br> - * <i>This method only validates the first XML or XAdES signature if more than one signature exists</i> - * - * @param signature Serialized XML or XAdES signature - * @param trustProfileID Id of the Trust-Profile from MOA-Sig configuration - * @param signatureLocationXpath Xpath that points to location of Signature element - * @return @link {@link IXMLSignatureVerificationResponse}, or null if no signature was found - * @throws MOASigServiceException on signatue-verification error - */ - IXMLSignatureVerificationResponse verifyXMLSignature(byte[] signature, String trustProfileID, - String signatureLocationXpath) throws MOASigServiceException; - - /** - * Verify a XML or XAdES signature - * <br><br> - * <i>This method only validates the first XML or XAdES signature if more than one signature exists</i> - * - * @param signature Serialized XML or XAdES signature - * @param trustProfileID Id of the Trust-Profile from MOA-Sig configuration - * @param verifyTransformsInfoProfileID {@link List} of XML Transformations that should be used for signature-verification - * @param signatureLocationXpath Xpath that points to location of Signature element - * @return @link {@link IXMLSignatureVerificationResponse}, or null if no signature was found - * @throws MOASigServiceException on signatue-verification error - */ - IXMLSignatureVerificationResponse verifyXMLSignature(byte[] signature, String trustProfileID, - List<String> verifyTransformsInfoProfileID, - String signatureLocationXpath) throws MOASigServiceException; - -}
\ No newline at end of file +} diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/api/data/ICMSSignatureVerificationResponse.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/api/data/ICmsSignatureVerificationResponse.java index 57426751..5e7a4564 100644 --- a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/api/data/ICMSSignatureVerificationResponse.java +++ b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/api/data/ICmsSignatureVerificationResponse.java @@ -1,5 +1,5 @@ package at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api.data; -public interface ICMSSignatureVerificationResponse extends IGenericSignatureVerificationResponse { +public interface ICmsSignatureVerificationResponse extends IGenericSignatureVerificationResponse { } diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/api/data/IGenericSignatureVerificationResponse.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/api/data/IGenericSignatureVerificationResponse.java index 00d98c86..8ebd90be 100644 --- a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/api/data/IGenericSignatureVerificationResponse.java +++ b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/api/data/IGenericSignatureVerificationResponse.java @@ -1,69 +1,74 @@ package at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api.data; -import iaik.x509.X509Certificate; import java.util.Date; import org.springframework.lang.Nullable; -import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions.MOASigServiceException; - +import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions.MoaSigServiceException; +import iaik.x509.X509Certificate; public interface IGenericSignatureVerificationResponse { - /** - * Returns the signing time - * - * @return Signing time, or null if signature contains no time information - */ - @Nullable - Date getSigningDateTime(); - - /** - * Returns the signatureCheckCode. - * @return int - */ - int getSignatureCheckCode(); - - /** - * Returns the certificateCheckCode. - * @return int - */ - int getCertificateCheckCode(); + /** + * Returns the signing time. + * + * @return Signing time, or null if signature contains no time information + */ + @Nullable + Date getSigningDateTime(); + + /** + * Returns the signatureCheckCode. + * + * @return int + */ + int getSignatureCheckCode(); + + /** + * Returns the certificateCheckCode. + * + * @return int + */ + int getCertificateCheckCode(); + + /** + * Returns the qualifiedCertificate. + * + * @return boolean + */ + boolean isQualifiedCertificate(); + + /** + * Returns the X509 certificate. + * + * @return X509Certificate, or null if no certificate information exists + * @throws MoaSigServiceException if X509 certificate can not be deserialized + */ + @Nullable + X509Certificate getX509Certificate() throws MoaSigServiceException; - /** - * Returns the qualifiedCertificate. - * @return boolean - */ - boolean isQualifiedCertificate(); + /** + * Returns the X509 certificate in serialized form. + * + * @return Serialized X509 certificate, or null if no certificate information + * exists + */ + @Nullable + byte[] getX509CertificateEncoded(); - /** - * Returns the X509 certificate. - * @return X509Certificate, or null if no certificate information exists - * @throws MOASigServiceException if X509 certificate can not be deserialized - */ - @Nullable - X509Certificate getX509Certificate() throws MOASigServiceException; + /** + * Returns the publicAuthority. + * + * @return boolean + */ + boolean isPublicAuthority(); - - /** - * Returns the X509 certificate in serialized form - * - * @return Serialized X509 certificate, or null if no certificate information exists - */ - @Nullable - byte[] getX509CertificateEncoded(); - - /** - * Returns the publicAuthority. - * @return boolean - */ - boolean isPublicAuthority(); - - /** - * Returns the publicAuthorityCode. - * @return String OID, or null if no OID exists - */ - @Nullable - String getPublicAuthorityCode(); + /** + * Returns the publicAuthorityCode. + * + * @return String OID, or null if no OID exists + */ + @Nullable + String getPublicAuthorityCode(); } diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/api/data/ISchemaRessourceProvider.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/api/data/ISchemaRessourceProvider.java index 9548d96b..17d5fa59 100644 --- a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/api/data/ISchemaRessourceProvider.java +++ b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/api/data/ISchemaRessourceProvider.java @@ -4,17 +4,18 @@ import java.io.InputStream; import java.util.Map; /** - * Inject additional XML schemes into MOA-Sig - * + * Inject additional XML schemes into MOA-Sig. + * * @author tlenz * */ public interface ISchemaRessourceProvider { - /** - * Get a Map of additional XML schemes that should be injected into MOA-Sig - * - * @return A Set of {@link Entry} consist of Name of the Scheme and XML scheme as {@link InputStream} - */ - public Map<String, InputStream> getSchemas(); + /** + * Get a Map of additional XML schemes that should be injected into MOA-Sig. + * + * @return A Set of {@link Entry} consist of Name of the Scheme and XML scheme + * as {@link InputStream} + */ + Map<String, InputStream> getSchemas(); } diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/api/data/IXMLSignatureVerificationResponse.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/api/data/IXMLSignatureVerificationResponse.java deleted file mode 100644 index 3e86fb63..00000000 --- a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/api/data/IXMLSignatureVerificationResponse.java +++ /dev/null @@ -1,37 +0,0 @@ -package at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api.data; - -/** - * @author tlenz - * - */ -public interface IXMLSignatureVerificationResponse extends IGenericSignatureVerificationResponse { - - - /** - * Returns the xmlDSIGManifestCheckCode. - * @return int - */ - int getXmlDSIGManifestCheckCode(); - - /** - * Returns the xmlDsigSubjectName. - * @return String - */ - String getXmlDsigSubjectName(); - - - /** - * Returns the xmlDSIGManigest. - * @return boolean - */ - boolean isXmlDSIGManigest(); - - - /** - * Returns the the resulting code of the signature manifest check. - * - * @return The code of the sigature manifest check. - */ - int getSignatureManifestCheckCode(); - -}
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/api/data/IXmlSignatureVerificationResponse.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/api/data/IXmlSignatureVerificationResponse.java new file mode 100644 index 00000000..5b766917 --- /dev/null +++ b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/api/data/IXmlSignatureVerificationResponse.java @@ -0,0 +1,39 @@ +package at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api.data; + +/** + * XML signature verification result. + * + * @author tlenz + * + */ +public interface IXmlSignatureVerificationResponse extends IGenericSignatureVerificationResponse { + + /** + * Returns the xmlDSIGManifestCheckCode. + * + * @return int + */ + int getXmlDsigManifestCheckCode(); + + /** + * Returns the xmlDsigSubjectName. + * + * @return String + */ + String getXmlDsigSubjectName(); + + /** + * Returns the xmlDSIGManigest. + * + * @return boolean + */ + boolean isXmlDsigManigest(); + + /** + * Returns the the resulting code of the signature manifest check. + * + * @return The code of the sigature manifest check. + */ + int getSignatureManifestCheckCode(); + +} diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MOASigServiceBuilderException.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MOASigServiceBuilderException.java deleted file mode 100644 index ded3f900..00000000 --- a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MOASigServiceBuilderException.java +++ /dev/null @@ -1,14 +0,0 @@ -package at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions; - -public class MOASigServiceBuilderException extends MOASigServiceException { - - private static final long serialVersionUID = 5178393157255309476L; - - public MOASigServiceBuilderException(String errorId, Object[] params) { - super(errorId, params); - } - - public MOASigServiceBuilderException(String errorId, Object[] params, Throwable e) { - super(errorId, params, e); - } -} diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MOASigServiceConfigurationException.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MOASigServiceConfigurationException.java deleted file mode 100644 index f3c02fe1..00000000 --- a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MOASigServiceConfigurationException.java +++ /dev/null @@ -1,11 +0,0 @@ -package at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions; - -public class MOASigServiceConfigurationException extends MOASigServiceException { - - private static final long serialVersionUID = -4710795384615456488L; - - public MOASigServiceConfigurationException(String errorId, Object[] params, Throwable e) { - super(errorId, params, e); - } - -} diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MOASigServiceException.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MOASigServiceException.java deleted file mode 100644 index 243b4b1d..00000000 --- a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MOASigServiceException.java +++ /dev/null @@ -1,26 +0,0 @@ -package at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions; - -import at.gv.egiz.eaaf.core.exceptions.EAAFServiceException; - -public class MOASigServiceException extends EAAFServiceException { - - private static final long serialVersionUID = -6088238428550563658L; - private static final String MOA_SIG_SERVICE_ID = "MOA-SIG-VERIFY"; - - public MOASigServiceException(String errorId, Object[] params) { - super(errorId, params); - - } - - public MOASigServiceException(String errorId, Object[] params, Throwable e) { - super(errorId, params, e); - - } - - @Override - protected String getServiceIdentifier() { - return MOA_SIG_SERVICE_ID; - - } - -} diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MOASigServiceParserException.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MOASigServiceParserException.java deleted file mode 100644 index 63a51001..00000000 --- a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MOASigServiceParserException.java +++ /dev/null @@ -1,14 +0,0 @@ -package at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions; - -public class MOASigServiceParserException extends MOASigServiceException { - - private static final long serialVersionUID = 5178393157255309476L; - - public MOASigServiceParserException(String errorId, Object[] params) { - super(errorId, params); - } - - public MOASigServiceParserException(String errorId, Object[] params, Throwable e) { - super(errorId, params, e); - } -} diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MoaSigServiceBuilderException.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MoaSigServiceBuilderException.java new file mode 100644 index 00000000..e32ab932 --- /dev/null +++ b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MoaSigServiceBuilderException.java @@ -0,0 +1,14 @@ +package at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions; + +public class MoaSigServiceBuilderException extends MoaSigServiceException { + + private static final long serialVersionUID = 5178393157255309476L; + + public MoaSigServiceBuilderException(final String errorId, final Object[] params) { + super(errorId, params); + } + + public MoaSigServiceBuilderException(final String errorId, final Object[] params, final Throwable e) { + super(errorId, params, e); + } +} diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MoaSigServiceConfigurationException.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MoaSigServiceConfigurationException.java new file mode 100644 index 00000000..fd5f8caf --- /dev/null +++ b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MoaSigServiceConfigurationException.java @@ -0,0 +1,11 @@ +package at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions; + +public class MoaSigServiceConfigurationException extends MoaSigServiceException { + + private static final long serialVersionUID = -4710795384615456488L; + + public MoaSigServiceConfigurationException(final String errorId, final Object[] params, final Throwable e) { + super(errorId, params, e); + } + +} diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MoaSigServiceException.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MoaSigServiceException.java new file mode 100644 index 00000000..a4fb6290 --- /dev/null +++ b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MoaSigServiceException.java @@ -0,0 +1,26 @@ +package at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions; + +import at.gv.egiz.eaaf.core.exceptions.EaafServiceException; + +public class MoaSigServiceException extends EaafServiceException { + + private static final long serialVersionUID = -6088238428550563658L; + private static final String MOA_SIG_SERVICE_ID = "MOA-SIG-VERIFY"; + + public MoaSigServiceException(final String errorId, final Object[] params) { + super(errorId, params); + + } + + public MoaSigServiceException(final String errorId, final Object[] params, final Throwable e) { + super(errorId, params, e); + + } + + @Override + protected String getServiceIdentifier() { + return MOA_SIG_SERVICE_ID; + + } + +} diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MoaSigServiceParserException.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MoaSigServiceParserException.java new file mode 100644 index 00000000..a47b45e0 --- /dev/null +++ b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/exceptions/MoaSigServiceParserException.java @@ -0,0 +1,14 @@ +package at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions; + +public class MoaSigServiceParserException extends MoaSigServiceException { + + private static final long serialVersionUID = 5178393157255309476L; + + public MoaSigServiceParserException(final String errorId, final Object[] params) { + super(errorId, params); + } + + public MoaSigServiceParserException(final String errorId, final Object[] params, final Throwable e) { + super(errorId, params, e); + } +} diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/AbstractSignatureService.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/AbstractSignatureService.java index 7e65cec7..d2cab2ef 100644 --- a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/AbstractSignatureService.java +++ b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/AbstractSignatureService.java @@ -3,75 +3,77 @@ package at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.w3c.dom.Document; + import at.gv.egovernment.moa.spss.server.config.ConfigurationException; import at.gv.egovernment.moa.spss.server.config.ConfigurationProvider; import at.gv.egovernment.moa.spss.server.iaik.config.IaikConfigurator; -import at.gv.egovernment.moa.spss.server.logging.TransactionId; import at.gv.egovernment.moa.spss.server.transaction.TransactionContext; import at.gv.egovernment.moa.spss.server.transaction.TransactionContextManager; import at.gv.egovernment.moaspss.logging.LoggingContext; import at.gv.egovernment.moaspss.logging.LoggingContextManager; -import iaik.server.Configurator; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.w3c.dom.Document; public abstract class AbstractSignatureService { - private static final Logger log = LoggerFactory.getLogger(AbstractSignatureService.class); - - @Autowired(required = true) MoaSigInitializer moaSigConfig; - - /** - * Get a new {@link Document} from {@link DocumentBuilder} in synchronized form, because - * {@link DocumentBuilderFactory} and {@link DocumentBuilder} are not thread-safe. - * - * @return {@link Document} - * @throws ParserConfigurationException - */ - protected synchronized Document getNewDocumentBuilder() throws ParserConfigurationException { - final DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); - return docBuilder.newDocument(); - - } - - /** - * Set up the thread-local context information needed for calling the various - * <code>Invoker</code> classes. - * - * @throws ConfigurationException An error occurred setting up the - * configuration in the <code>TransactionContext</code>. - */ - protected final void setUpContexts( String transactionID) throws ConfigurationException { - final TransactionContextManager txMgr = TransactionContextManager.getInstance(); - final LoggingContextManager logMgr = LoggingContextManager.getInstance(); - - if (txMgr.getTransactionContext() == null) { - log.debug("Set not MOA-Sig transaction context"); - final TransactionContext ctx = new TransactionContext(transactionID, null, ConfigurationProvider.getInstance()); - txMgr.setTransactionContext(ctx); - - } - - if (logMgr.getLoggingContext() == null) { - final LoggingContext ctx = new LoggingContext(transactionID); - logMgr.setLoggingContext(ctx); - - } - - new IaikConfigurator().configure(ConfigurationProvider.getInstance()); - - } - - /** - * Tear down thread-local context information. - */ - protected void tearDownContexts() { - TransactionContextManager.getInstance().setTransactionContext(null); - LoggingContextManager.getInstance().setLoggingContext(null); - log.debug("Closing MOA-Sig transaction context"); - - } + private static final Logger log = LoggerFactory.getLogger(AbstractSignatureService.class); + + @Autowired(required = true) + MoaSigInitializer moaSigConfig; + + /** + * Get a new {@link Document} from {@link DocumentBuilder} in synchronized form, + * because {@link DocumentBuilderFactory} and {@link DocumentBuilder} are not + * thread-safe. + * + * @return {@link Document} + * @throws ParserConfigurationException In case of an error + */ + protected synchronized Document getNewDocumentBuilder() throws ParserConfigurationException { + final DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + return docBuilder.newDocument(); + + } + + /** + * Set up the thread-local context information needed for calling the various + * <code>Invoker</code> classes. + * + * @throws ConfigurationException An error occurred setting up the configuration + * in the <code>TransactionContext</code>. + */ + protected final void setUpContexts(final String transactionID) throws ConfigurationException { + final TransactionContextManager txMgr = TransactionContextManager.getInstance(); + final LoggingContextManager logMgr = LoggingContextManager.getInstance(); + + if (txMgr.getTransactionContext() == null) { + log.debug("Set not MOA-Sig transaction context"); + final TransactionContext ctx = + new TransactionContext(transactionID, null, ConfigurationProvider.getInstance()); + txMgr.setTransactionContext(ctx); + + } + + if (logMgr.getLoggingContext() == null) { + final LoggingContext ctx = new LoggingContext(transactionID); + logMgr.setLoggingContext(ctx); + + } + + new IaikConfigurator().configure(ConfigurationProvider.getInstance()); + + } + + /** + * Tear down thread-local context information. + */ + protected void tearDownContexts() { + TransactionContextManager.getInstance().setTransactionContext(null); + LoggingContextManager.getInstance().setLoggingContext(null); + log.debug("Closing MOA-Sig transaction context"); + + } } diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/MOASigSpringResourceProvider.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/MOASigSpringResourceProvider.java deleted file mode 100644 index ecda7eb1..00000000 --- a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/MOASigSpringResourceProvider.java +++ /dev/null @@ -1,27 +0,0 @@ -package at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl; - -import org.springframework.core.io.ClassPathResource; -import org.springframework.core.io.Resource; - -import at.gv.egiz.components.spring.api.SpringResourceProvider; - -public class MOASigSpringResourceProvider implements SpringResourceProvider { - - @Override - public Resource[] getResourcesToLoad() { - ClassPathResource moaSigConfig = new ClassPathResource("/moa-sig-service.beans.xml", MOASigSpringResourceProvider.class); - return new Resource[] {moaSigConfig}; - } - - @Override - public String[] getPackagesToScan() { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getName() { - return "Signature-verification service based on MOA-Sig (MOA-SPSS)"; - } - -} diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/MoaSigInitializer.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/MoaSigInitializer.java index 1628b71a..77bbc88b 100644 --- a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/MoaSigInitializer.java +++ b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/MoaSigInitializer.java @@ -9,118 +9,122 @@ import java.util.Map.Entry; import javax.annotation.Nonnull; import javax.annotation.PostConstruct; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; + import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api.data.ISchemaRessourceProvider; -import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions.MOASigServiceConfigurationException; +import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions.MoaSigServiceConfigurationException; import at.gv.egovernment.moa.spss.MOAException; import at.gv.egovernment.moa.spss.api.Configurator; import at.gv.egovernment.moaspss.logging.LoggingContext; import at.gv.egovernment.moaspss.logging.LoggingContextManager; import at.gv.egovernment.moaspss.util.DOMUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; import iaik.asn1.structures.AlgorithmID; import iaik.security.ec.provider.ECCelerate; import iaik.security.provider.IAIK; public class MoaSigInitializer { - private static final Logger log = LoggerFactory.getLogger(MoaSigInitializer.class); - - @Autowired(required=false) ISchemaRessourceProvider[] schemas; - - private Configurator moaSigConfigurator; - - - /** - * Get MOA-Sig configuration object - * - * @return moa-sig configuration - */ - @Nonnull - public Configurator getMoaSigConfigurator() { - return moaSigConfigurator; - - } - - @PostConstruct - private synchronized void initialize() throws MOASigServiceConfigurationException { - log.info("Initializing MOA-Sig signature-verification service ... "); - - log.info("Loading Java security providers."); - IAIK.addAsProvider(); - ECCelerate.addAsProvider(); - - try { - LoggingContextManager.getInstance().setLoggingContext( - new LoggingContext("startup")); - log.debug("MOA-Sig library initialization process ... "); - Configurator.getInstance().init(); - log.info("MOA-Sig library initialization complete "); - - Security.insertProviderAt(IAIK.getInstance(), 0); - - final ECCelerate eccProvider = ECCelerate.getInstance(); - if (Security.getProvider(eccProvider.getName()) != null) - Security.removeProvider(eccProvider.getName()); - Security.addProvider(new ECCelerate()); - - fixJava8_141ProblemWithSSLAlgorithms(); - - if (log.isDebugEnabled()) { - log.debug("Loaded Security Provider:"); - final Provider[] providerList = Security.getProviders(); - for (int i=0; i<providerList.length; i++) - log.debug(i + ": " + providerList[i].getName() + " Version " + providerList[i].getVersion()); + private static final Logger log = LoggerFactory.getLogger(MoaSigInitializer.class); + + @Autowired(required = false) + ISchemaRessourceProvider[] schemas; + + private Configurator moaSigConfigurator; + + /** + * Get MOA-Sig configuration object. + * + * @return moa-sig configuration + */ + @Nonnull + public Configurator getMoaSigConfigurator() { + return moaSigConfigurator; + + } + + @PostConstruct + private synchronized void initialize() throws MoaSigServiceConfigurationException { + log.info("Initializing MOA-Sig signature-verification service ... "); + + log.info("Loading Java security providers."); + IAIK.addAsProvider(); + ECCelerate.addAsProvider(); + + try { + LoggingContextManager.getInstance().setLoggingContext(new LoggingContext("startup")); + log.debug("MOA-Sig library initialization process ... "); + Configurator.getInstance().init(); + log.info("MOA-Sig library initialization complete "); + + Security.insertProviderAt(IAIK.getInstance(), 0); + + final ECCelerate eccProvider = ECCelerate.getInstance(); + if (Security.getProvider(eccProvider.getName()) != null) { + Security.removeProvider(eccProvider.getName()); + } + Security.addProvider(new ECCelerate()); + + fixJava8_141ProblemWithSslAlgorithms(); + + if (log.isDebugEnabled()) { + log.debug("Loaded Security Provider:"); + final Provider[] providerList = Security.getProviders(); + for (int i = 0; i < providerList.length; i++) { + log.debug( + i + ": " + providerList[i].getName() + " Version " + providerList[i].getVersion()); + } + + } + + // Inject additional XML schemes + if (schemas != null && schemas.length > 0) { + log.debug("Infjecting additional XML schemes ... "); + for (final ISchemaRessourceProvider el : schemas) { + final Iterator<Entry<String, InputStream>> xmlSchemeIt = + el.getSchemas().entrySet().iterator(); + while (xmlSchemeIt.hasNext()) { + final Entry<String, InputStream> xmlDef = xmlSchemeIt.next(); + try { + DOMUtils.addSchemaToPool(xmlDef.getValue(), xmlDef.getKey()); + log.info("Inject XML scheme: {}", xmlDef.getKey()); + + } catch (final IOException e) { + log.warn("Can NOT inject XML scheme: " + xmlDef.getKey(), e); } + } + } + } - //Inject additional XML schemes - if (schemas != null && schemas.length > 0) { - log.debug("Infjecting additional XML schemes ... "); - for (final ISchemaRessourceProvider el : schemas) { - final Iterator<Entry<String, InputStream>> xmlSchemeIt = el.getSchemas().entrySet().iterator(); - while (xmlSchemeIt.hasNext()) { - final Entry<String, InputStream> xmlDef = xmlSchemeIt.next(); - try { - DOMUtils.addSchemaToPool(xmlDef.getValue(), xmlDef.getKey()); - log.info("Inject XML scheme: {}", xmlDef.getKey()); - - } catch (final IOException e) { - log.warn("Can NOT inject XML scheme: " + xmlDef.getKey(), e); + moaSigConfigurator = Configurator.getInstance(); - } - - } - } - } - - moaSigConfigurator = Configurator.getInstance(); - - - } catch (final MOAException e) { - log.error("MOA-SP initialization FAILED!", e.getWrapped()); - throw new MOASigServiceConfigurationException("service.moasig.04", new Object[] { e - .toString() }, e); - } - - - } - - private static void fixJava8_141ProblemWithSSLAlgorithms() { - log.info("Change AlgorithmIDs to fix problems with Java8 >= 141 ..."); - //new AlgorithmID("1.2.840.113549.1.1.4", "md5WithRSAEncryption", new String[] { "MD5withRSA", "MD5/RSA", }, null, true); - new AlgorithmID("1.2.840.113549.1.1.5", "sha1WithRSAEncryption", - new String[] { "SHA1withRSA" , "SHA1/RSA", "SHA-1/RSA", "SHA/RSA", }, null, true); - new AlgorithmID("1.2.840.113549.1.1.14", "sha224WithRSAEncryption", - new String[] { "SHA224withRSA", "SHA224/RSA", "SHA-224/RSA", }, null, true); - new AlgorithmID("1.2.840.113549.1.1.11", "sha256WithRSAEncryption", - new String[] { "SHA256withRSA", "SHA256/RSA", "SHA-256/RSA", }, null, true); - new AlgorithmID("1.2.840.113549.1.1.12", "sha384WithRSAEncryption", - new String[] { "SHA384withRSA", "SHA384/RSA", "SHA-384/RSA", }, null, true); - new AlgorithmID("1.2.840.113549.1.1.13", "sha512WithRSAEncryption", - new String[] { "SHA512withRSA", "SHA512/RSA", "SHA-512/RSA" }, null, true); - - log.info("Change AlgorithmIDs finished"); + } catch (final MOAException e) { + log.error("MOA-SP initialization FAILED!", e.getWrapped()); + throw new MoaSigServiceConfigurationException("service.moasig.04", + new Object[] { e.toString() }, e); } + + } + + private static void fixJava8_141ProblemWithSslAlgorithms() { + log.info("Change AlgorithmIDs to fix problems with Java8 >= 141 ..."); + // new AlgorithmID("1.2.840.113549.1.1.4", "md5WithRSAEncryption", new String[] + // { "MD5withRSA", + // "MD5/RSA", }, null, true); + new AlgorithmID("1.2.840.113549.1.1.5", "sha1WithRSAEncryption", + new String[] { "SHA1withRSA", "SHA1/RSA", "SHA-1/RSA", "SHA/RSA", }, null, true); + new AlgorithmID("1.2.840.113549.1.1.14", "sha224WithRSAEncryption", + new String[] { "SHA224withRSA", "SHA224/RSA", "SHA-224/RSA", }, null, true); + new AlgorithmID("1.2.840.113549.1.1.11", "sha256WithRSAEncryption", + new String[] { "SHA256withRSA", "SHA256/RSA", "SHA-256/RSA", }, null, true); + new AlgorithmID("1.2.840.113549.1.1.12", "sha384WithRSAEncryption", + new String[] { "SHA384withRSA", "SHA384/RSA", "SHA-384/RSA", }, null, true); + new AlgorithmID("1.2.840.113549.1.1.13", "sha512WithRSAEncryption", + new String[] { "SHA512withRSA", "SHA512/RSA", "SHA-512/RSA" }, null, true); + + log.info("Change AlgorithmIDs finished"); + } } diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/MoaSigSpringResourceProvider.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/MoaSigSpringResourceProvider.java new file mode 100644 index 00000000..d09b26de --- /dev/null +++ b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/MoaSigSpringResourceProvider.java @@ -0,0 +1,28 @@ +package at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl; + +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; + +import at.gv.egiz.components.spring.api.SpringResourceProvider; + +public class MoaSigSpringResourceProvider implements SpringResourceProvider { + + @Override + public Resource[] getResourcesToLoad() { + final ClassPathResource moaSigConfig = + new ClassPathResource("/moa-sig-service.beans.xml", MoaSigSpringResourceProvider.class); + return new Resource[] { moaSigConfig }; + } + + @Override + public String[] getPackagesToScan() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getName() { + return "Signature-verification service based on MOA-Sig (MOA-SPSS)"; + } + +} diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/SignatureCreationService.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/SignatureCreationService.java index 59e7b516..559af62a 100644 --- a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/SignatureCreationService.java +++ b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/SignatureCreationService.java @@ -10,21 +10,23 @@ import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api.ISignatureCreatio import at.gv.egovernment.moa.spss.server.invoke.CMSSignatureCreationInvoker; import at.gv.egovernment.moa.spss.server.invoke.XMLSignatureCreationInvoker; -@Service(value="moaSigCreateService") -public class SignatureCreationService extends AbstractSignatureService implements ISignatureCreationService{ - private static final Logger log = LoggerFactory.getLogger(SignatureCreationService.class); - - private XMLSignatureCreationInvoker xadesInvoker; - private CMSSignatureCreationInvoker cadesInvoker; - - - @PostConstruct - protected void internalInitializer() { - log.debug("Instanzing SignatureCreationService implementation ... "); - xadesInvoker = XMLSignatureCreationInvoker.getInstance(); - cadesInvoker = CMSSignatureCreationInvoker.getInstance(); - log.info("MOA-Sig signature-creation service initialized"); - - } +@Service(value = "moaSigCreateService") +public class SignatureCreationService extends AbstractSignatureService + implements ISignatureCreationService { + private static final Logger log = LoggerFactory.getLogger(SignatureCreationService.class); + + private XMLSignatureCreationInvoker xadesInvoker; + private CMSSignatureCreationInvoker cadesInvoker; + + @PostConstruct + protected void internalInitializer() { + log.debug("Instanzing SignatureCreationService implementation ... "); + xadesInvoker = XMLSignatureCreationInvoker.getInstance(); + cadesInvoker = CMSSignatureCreationInvoker.getInstance(); + log.trace("XML_impl: {} , CMS_imp: {}", + xadesInvoker.getClass().getName(), cadesInvoker.getClass().getName()); + log.info("MOA-Sig signature-creation service initialized"); + + } } diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/SignatureVerificationService.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/SignatureVerificationService.java index f610e59e..8fc4086e 100644 --- a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/SignatureVerificationService.java +++ b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/SignatureVerificationService.java @@ -3,13 +3,24 @@ package at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl; import java.io.ByteArrayInputStream; import java.security.cert.CertificateEncodingException; import java.util.List; + import javax.annotation.PostConstruct; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.lang.Nullable; +import org.springframework.stereotype.Service; +import org.springframework.util.Base64Utils; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api.ISignatureVerificationService; -import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api.data.ICMSSignatureVerificationResponse; -import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api.data.IXMLSignatureVerificationResponse; -import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions.MOASigServiceBuilderException; -import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions.MOASigServiceException; -import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.parser.VerifyXMLSignatureResponseParser; +import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api.data.ICmsSignatureVerificationResponse; +import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api.data.IXmlSignatureVerificationResponse; +import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions.MoaSigServiceBuilderException; +import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions.MoaSigServiceException; +import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.parser.VerifyXmlSignatureResponseParser; import at.gv.egovernment.moa.spss.MOAException; import at.gv.egovernment.moa.spss.api.cmsverify.VerifyCMSSignatureRequest; import at.gv.egovernment.moa.spss.api.cmsverify.VerifyCMSSignatureResponse; @@ -22,281 +33,327 @@ import at.gv.egovernment.moa.spss.api.xmlverify.VerifyXMLSignatureResponse; import at.gv.egovernment.moa.spss.server.invoke.CMSSignatureVerificationInvoker; import at.gv.egovernment.moa.spss.server.invoke.XMLSignatureVerificationInvoker; import at.gv.egovernment.moaspss.util.Constants; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.lang.Nullable; -import org.springframework.stereotype.Service; -import org.springframework.util.Base64Utils; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; - /** + * MOA-Sig based signature verification implementation. + * * @author tlenz * */ -@Service(value="moaSigVerifyService") -public class SignatureVerificationService extends AbstractSignatureService implements ISignatureVerificationService { - private static final Logger log = LoggerFactory.getLogger(SignatureVerificationService.class); - - private static final String XMLNS_NS_URI = Constants.XMLNS_NS_URI; - private static final String MOA_NS_URI = Constants.MOA_NS_URI; - private static final String DSIG = Constants.DSIG_PREFIX + ":"; - private static final String DEFAULT_XPATH_SIGNATURE_LOCATION = "//" + DSIG + "Signature"; - - private CMSSignatureVerificationInvoker cadesInvoker; - private XMLSignatureVerificationInvoker xadesInvocer; - - /* (non-Javadoc) - * @see at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.ISignatureVerificationService#verifyCMSSignature(byte[], java.lang.String) - */ - @Override - @Nullable - public ICMSSignatureVerificationResponse verifyCMSSignature(byte[] signature, String trustProfileID) throws MOASigServiceException { - try { - //setup context - setUpContexts(Thread.currentThread().getName()); - - //verify signature - final VerifyCMSSignatureRequest cmsSigVerifyReq = buildVerfifyCMSRequest(signature, trustProfileID, false, false); - final VerifyCMSSignatureResponse cmsSigVerifyResp = cadesInvoker.verifyCMSSignature(cmsSigVerifyReq ); - return parseCMSVerificationResult(cmsSigVerifyResp); - - } catch (final MOAException e) { - log.warn("CMS signature verification has an error.", e); - throw new MOASigServiceException("service.03", new Object[] { e.toString()}, e); - - } catch (final CertificateEncodingException e) { - log.warn("Can NOT serialize X509 certificate from CMS/CAdES signature-verification response", e); - throw new MOASigServiceException("service.03", new Object[] { e.toString()}, e); - - } finally { - tearDownContexts(); +@Service(value = "moaSigVerifyService") +public class SignatureVerificationService extends AbstractSignatureService + implements ISignatureVerificationService { + private static final Logger log = LoggerFactory.getLogger(SignatureVerificationService.class); + + private static final String XMLNS_NS_URI = Constants.XMLNS_NS_URI; + private static final String MOA_NS_URI = Constants.MOA_NS_URI; + private static final String DSIG = Constants.DSIG_PREFIX + ":"; + private static final String DEFAULT_XPATH_SIGNATURE_LOCATION = "//" + DSIG + "Signature"; + + private CMSSignatureVerificationInvoker cadesInvoker; + private XMLSignatureVerificationInvoker xadesInvocer; + + /* + * (non-Javadoc) + * + * @see at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl. + * ISignatureVerificationService# verifyCMSSignature(byte[], java.lang.String) + */ + @Override + @Nullable + public ICmsSignatureVerificationResponse verifyCmsSignature(final byte[] signature, + final String trustProfileID) throws MoaSigServiceException { + try { + // setup context + setUpContexts(Thread.currentThread().getName()); + + // verify signature + final VerifyCMSSignatureRequest cmsSigVerifyReq = + buildVerfifyCmsRequest(signature, trustProfileID, false, false); + final VerifyCMSSignatureResponse cmsSigVerifyResp = + cadesInvoker.verifyCMSSignature(cmsSigVerifyReq); + return parseCmsVerificationResult(cmsSigVerifyResp); + + } catch (final MOAException e) { + log.warn("CMS signature verification has an error.", e); + throw new MoaSigServiceException("service.03", new Object[] { e.toString() }, e); + + } catch (final CertificateEncodingException e) { + log.warn("Can NOT serialize X509 certificate from CMS/CAdES signature-verification response", + e); + throw new MoaSigServiceException("service.03", new Object[] { e.toString() }, e); + + } finally { + tearDownContexts(); + + } + + } + + /* + * (non-Javadoc) + * + * @see at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl. + * ISignatureVerificationService# verifyXMLSignature(byte[], java.lang.String) + */ + @Override + public IXmlSignatureVerificationResponse verifyXmlSignature(final byte[] signature, + final String trustProfileID) throws MoaSigServiceException { + return verifyXmlSignature(signature, trustProfileID, null, DEFAULT_XPATH_SIGNATURE_LOCATION); + + } + + /* + * (non-Javadoc) + * + * @see at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl. + * ISignatureVerificationService# verifyXMLSignature(byte[], java.lang.String, + * java.util.List) + */ + @Override + public IXmlSignatureVerificationResponse verifyXmlSignature(final byte[] signature, + final String trustProfileID, final List<String> verifyTransformsInfoProfileID) + throws MoaSigServiceException { + return verifyXmlSignature(signature, trustProfileID, verifyTransformsInfoProfileID, + DEFAULT_XPATH_SIGNATURE_LOCATION); + } + + /* + * (non-Javadoc) + * + * @see at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl. + * ISignatureVerificationService# verifyXMLSignature(byte[], java.lang.String, + * java.lang.String) + */ + @Override + public IXmlSignatureVerificationResponse verifyXmlSignature(final byte[] signature, + final String trustProfileID, final String signatureLocationXpath) + throws MoaSigServiceException { + return verifyXmlSignature(signature, trustProfileID, null, signatureLocationXpath); + } + + /* + * (non-Javadoc) + * + * @see at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl. + * ISignatureVerificationService# verifyXMLSignature(byte[], java.lang.String, + * java.util.List, java.lang.String) + */ + @Override + public IXmlSignatureVerificationResponse verifyXmlSignature(final byte[] signature, + final String trustProfileID, final List<String> verifyTransformsInfoProfileID, + final String xpathSignatureLocation) throws MoaSigServiceException { + try { + // setup context + setUpContexts(Thread.currentThread().getName()); + + // build signature-verification request + final Element domVerifyXmlSignatureRequest = buildVerifyXmlRequest(signature, trustProfileID, + verifyTransformsInfoProfileID, xpathSignatureLocation); + + // send signature-verification to MOA-Sig + final VerifyXMLSignatureRequest vsrequest = + new VerifyXMLSignatureRequestParser().parse(domVerifyXmlSignatureRequest); + final VerifyXMLSignatureResponse vsresponse = xadesInvocer.verifyXMLSignature(vsrequest); + final Document result = new VerifyXMLSignatureResponseBuilder(true).build(vsresponse); + + // parses the <IXMLSignatureVerificationResponse> + final IXmlSignatureVerificationResponse verifyXmlSignatureResponse = + new VerifyXmlSignatureResponseParser(result.getDocumentElement()).parseData(); + + return verifyXmlSignatureResponse; + + } catch (final MoaSigServiceException e) { + throw e; + + } catch (final MOAException e) { + log.warn("MOA-Sig signature-verification has an internal error." + " MsgCode: " + + e.getMessageId() + " Msg: " + e.getMessage(), e); + throw new MoaSigServiceException("service.moasig.03", new Object[] { e.getMessage() }, e); + + } finally { + tearDownContexts(); + + } + } + + private ICmsSignatureVerificationResponse parseCmsVerificationResult( + final VerifyCMSSignatureResponse cmsSigVerifyResp) throws CertificateEncodingException { + + if (cmsSigVerifyResp.getResponseElements() == null + || cmsSigVerifyResp.getResponseElements().isEmpty()) { + log.info("No CMS signature FOUND. "); + return null; + + } + + if (cmsSigVerifyResp.getResponseElements().size() > 1) { + log.warn( + "CMS or CAdES signature contains more than one technical signatures. Only validate the first signature"); + } + + final VerifyCMSSignatureResponseElement firstSig = + (VerifyCMSSignatureResponseElement) cmsSigVerifyResp.getResponseElements().get(0); + + final at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.data.VerifyCmsSignatureResponse result = + new at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.data.VerifyCmsSignatureResponse(); + + // parse results into response container + result.setSignatureCheckCode(firstSig.getSignatureCheck().getCode()); + result.setCertificateCheckCode(firstSig.getCertificateCheck().getCode()); + + if (firstSig.getSignerInfo() != null) { + result.setSigningDateTime(firstSig.getSignerInfo().getSigningTime()); + result + .setX509CertificateEncoded(firstSig.getSignerInfo().getSignerCertificate().getEncoded()); + result.setQualifiedCertificate(firstSig.getSignerInfo().isQualifiedCertificate()); + + result.setPublicAuthority(firstSig.getSignerInfo().isPublicAuthority()); + result.setPublicAuthorityCode(firstSig.getSignerInfo().getPublicAuhtorityID()); + + } else { + log.info("CMS or CAdES verification result contains no SignerInfo"); + } + + return result; + } + + /** + * Build a VerifyCMS-Siganture request for MOA-Sig. <br> + * <br> + * This builder only generates verification-request for enveloped CMS or CAdES + * signatures <br> + * This + * + * @param signature CMS or CAdES signature + * @param trustProfileID trustProfileID MOA-Sig Trust-Profile + * @param isPdfSignature Make CAdES signature as part of an PAdES + * document + * @param performExtendedValidation To extended validation. See MOA-Sig + * documentation for detailed information + * @return + */ + private VerifyCMSSignatureRequest buildVerfifyCmsRequest(final byte[] signature, + final String trustProfileID, final boolean isPdfSignature, + final boolean performExtendedValidation) { + final VerifyCMSSignatureRequestImpl verifyCmsSignatureRequest = + new VerifyCMSSignatureRequestImpl(); + verifyCmsSignatureRequest.setDateTime(null); + verifyCmsSignatureRequest.setCMSSignature(new ByteArrayInputStream(signature)); + verifyCmsSignatureRequest.setDataObject(null); + verifyCmsSignatureRequest.setTrustProfileId(trustProfileID); + verifyCmsSignatureRequest.setSignatories(VerifyCMSSignatureRequest.ALL_SIGNATORIES); + verifyCmsSignatureRequest.setPDF(isPdfSignature); + verifyCmsSignatureRequest.setExtended(performExtendedValidation); + return verifyCmsSignatureRequest; + + } + + /** + * Build a VerifyXML-Signature request for MOA-Sig. + * + * @param signature Serialized XML signature + * @param trustProfileID MOA-Sig Trust-Profile + * @param verifyTransformsInfoProfileID {@link List} of Transformation-Profiles + * used for validation + * @param xpathSignatureLocation Xpath that points to location of + * Signature element + * @return MOA-Sig verification request element + * @throws MoaSigServiceBuilderException In case of an error + */ + private Element buildVerifyXmlRequest(final byte[] signature, final String trustProfileID, + final List<String> verifyTransformsInfoProfileID, final String xpathSignatureLocation) + throws MoaSigServiceBuilderException { + try { + // build empty document + final Document requestDoc_ = getNewDocumentBuilder(); + final Element requestElem_ = + requestDoc_.createElementNS(MOA_NS_URI, "VerifyXMLSignatureRequest"); + requestElem_.setAttributeNS(XMLNS_NS_URI, "xmlns", MOA_NS_URI); + requestElem_.setAttributeNS(XMLNS_NS_URI, "xmlns:" + Constants.DSIG_PREFIX, + Constants.DSIG_NS_URI); + requestDoc_.appendChild(requestElem_); + + // build the request + final Element verifiySignatureInfoElem = + requestDoc_.createElementNS(MOA_NS_URI, "VerifySignatureInfo"); + requestElem_.appendChild(verifiySignatureInfoElem); + final Element verifySignatureEnvironmentElem = + requestDoc_.createElementNS(MOA_NS_URI, "VerifySignatureEnvironment"); + verifiySignatureInfoElem.appendChild(verifySignatureEnvironmentElem); + final Element base64ContentElem = requestDoc_.createElementNS(MOA_NS_URI, "Base64Content"); + verifySignatureEnvironmentElem.appendChild(base64ContentElem); + + // insert the base64 encoded signature + String base64EncodedAssertion = Base64Utils.encodeToString(signature); + // replace all '\r' characters by no char. + final StringBuffer replaced = new StringBuffer(); + for (int i = 0; i < base64EncodedAssertion.length(); i++) { + final char c = base64EncodedAssertion.charAt(i); + if (c != '\r') { + replaced.append(c); + } + } + base64EncodedAssertion = replaced.toString(); + final Node base64Content = requestDoc_.createTextNode(base64EncodedAssertion); + base64ContentElem.appendChild(base64Content); + + // specify the signature location + final Element verifySignatureLocationElem = + requestDoc_.createElementNS(MOA_NS_URI, "VerifySignatureLocation"); + verifiySignatureInfoElem.appendChild(verifySignatureLocationElem); + final Node signatureLocation = requestDoc_.createTextNode(xpathSignatureLocation); + verifySignatureLocationElem.appendChild(signatureLocation); + + // signature manifest params + if (verifyTransformsInfoProfileID != null && !verifyTransformsInfoProfileID.isEmpty()) { + final Element signatureManifestCheckParamsElem = + requestDoc_.createElementNS(MOA_NS_URI, "SignatureManifestCheckParams"); + requestElem_.appendChild(signatureManifestCheckParamsElem); + signatureManifestCheckParamsElem.setAttribute("ReturnReferenceInputData", "false"); + + // verify transformations + final Element referenceInfoElem = requestDoc_.createElementNS(MOA_NS_URI, "ReferenceInfo"); + signatureManifestCheckParamsElem.appendChild(referenceInfoElem); + for (final String element : verifyTransformsInfoProfileID) { + final Element verifyTransformsInfoProfileIdElem = + requestDoc_.createElementNS(MOA_NS_URI, "VerifyTransformsInfoProfileID"); + referenceInfoElem.appendChild(verifyTransformsInfoProfileIdElem); + verifyTransformsInfoProfileIdElem.appendChild(requestDoc_.createTextNode(element)); } + } - } - - /* (non-Javadoc) - * @see at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.ISignatureVerificationService#verifyXMLSignature(byte[], java.lang.String) - */ - @Override - public IXMLSignatureVerificationResponse verifyXMLSignature(byte[] signature, String trustProfileID) throws MOASigServiceException { - return verifyXMLSignature(signature, trustProfileID, null, DEFAULT_XPATH_SIGNATURE_LOCATION); - - } - - /* (non-Javadoc) - * @see at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.ISignatureVerificationService#verifyXMLSignature(byte[], java.lang.String, java.util.List) - */ - @Override - public IXMLSignatureVerificationResponse verifyXMLSignature(byte[] signature, String trustProfileID, List<String> verifyTransformsInfoProfileID) throws MOASigServiceException { - return verifyXMLSignature(signature, trustProfileID, verifyTransformsInfoProfileID, DEFAULT_XPATH_SIGNATURE_LOCATION); - } - - /* (non-Javadoc) - * @see at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.ISignatureVerificationService#verifyXMLSignature(byte[], java.lang.String, java.lang.String) - */ - @Override - public IXMLSignatureVerificationResponse verifyXMLSignature(byte[] signature, String trustProfileID, String signatureLocationXpath) throws MOASigServiceException { - return verifyXMLSignature(signature, trustProfileID, null, signatureLocationXpath); - } - - /* (non-Javadoc) - * @see at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.ISignatureVerificationService#verifyXMLSignature(byte[], java.lang.String, java.util.List, java.lang.String) - */ - @Override - public IXMLSignatureVerificationResponse verifyXMLSignature(byte[] signature, String trustProfileID, List<String> verifyTransformsInfoProfileID, String xpathSignatureLocation) throws MOASigServiceException { - try { - //setup context - setUpContexts(Thread.currentThread().getName()); - - //build signature-verification request - final Element domVerifyXMLSignatureRequest = buildVerifyXMLRequest(signature, trustProfileID, verifyTransformsInfoProfileID, xpathSignatureLocation); - - //send signature-verification to MOA-Sig - final VerifyXMLSignatureRequest vsrequest = new VerifyXMLSignatureRequestParser().parse(domVerifyXMLSignatureRequest); - final VerifyXMLSignatureResponse vsresponse = xadesInvocer.verifyXMLSignature(vsrequest); - final Document result = new VerifyXMLSignatureResponseBuilder(true).build(vsresponse); - - // parses the <IXMLSignatureVerificationResponse> - final IXMLSignatureVerificationResponse verifyXMLSignatureResponse = new VerifyXMLSignatureResponseParser(result.getDocumentElement()).parseData(); - - return verifyXMLSignatureResponse; - - } catch (final MOASigServiceException e) { - throw e; - - } catch (final MOAException e) { - log.warn("MOA-Sig signature-verification has an internal error." - + " MsgCode: " + e.getMessageId() - + " Msg: " + e.getMessage(), - e); - throw new MOASigServiceException("service.moasig.03", new Object[]{e.getMessage()}, e); - - } finally { - tearDownContexts(); + // hashinput data + final Element returnHashInputDataElem = + requestDoc_.createElementNS(MOA_NS_URI, "ReturnHashInputData"); + requestElem_.appendChild(returnHashInputDataElem); - } - } - -private ICMSSignatureVerificationResponse parseCMSVerificationResult(VerifyCMSSignatureResponse cmsSigVerifyResp) throws CertificateEncodingException { - - if (cmsSigVerifyResp.getResponseElements() == null || - cmsSigVerifyResp.getResponseElements().isEmpty()) { - log.info("No CMS signature FOUND. "); - return null; - - } - - if (cmsSigVerifyResp.getResponseElements().size() > 1) - log.warn("CMS or CAdES signature contains more than one technical signatures. Only validate the first signature"); - - final VerifyCMSSignatureResponseElement firstSig = (VerifyCMSSignatureResponseElement) cmsSigVerifyResp.getResponseElements().get(0); - - final at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.data.VerifyCMSSignatureResponse result = - new at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.data.VerifyCMSSignatureResponse(); - - //parse results into response container - result.setSignatureCheckCode(firstSig.getSignatureCheck().getCode()); - result.setCertificateCheckCode(firstSig.getCertificateCheck().getCode()); - - if (firstSig.getSignerInfo() != null) { - result.setSigningDateTime(firstSig.getSignerInfo().getSigningTime()); - result.setX509CertificateEncoded(firstSig.getSignerInfo().getSignerCertificate().getEncoded()); - result.setQualifiedCertificate(firstSig.getSignerInfo().isQualifiedCertificate()); - - result.setPublicAuthority(firstSig.getSignerInfo().isPublicAuthority()); - result.setPublicAuthorityCode(firstSig.getSignerInfo().getPublicAuhtorityID()); - - } else - log.info("CMS or CAdES verification result contains no SignerInfo"); - - return result; - } - - /** - * Build a VerifyCMS-Siganture request for MOA-Sig. - * <br><br> - * This builder only generates verification-request for enveloped CMS or CAdES signatures - * <br> - * This - * - * @param signature CMS or CAdES signature - * @param trustProfileID trustProfileID MOA-Sig Trust-Profile - * @param isPdfSignature Make CAdES signature as part of an PAdES document - * @param performExtendedValidation To extended validation. See MOA-Sig documentation for detailed information - * @return - */ - private VerifyCMSSignatureRequest buildVerfifyCMSRequest(byte[] signature, String trustProfileID, - boolean isPdfSignature, boolean performExtendedValidation) { - final VerifyCMSSignatureRequestImpl verifyCMSSignatureRequest = new VerifyCMSSignatureRequestImpl(); - verifyCMSSignatureRequest.setDateTime(null); - verifyCMSSignatureRequest.setCMSSignature(new ByteArrayInputStream(signature)); - verifyCMSSignatureRequest.setDataObject(null); - verifyCMSSignatureRequest.setTrustProfileId(trustProfileID); - verifyCMSSignatureRequest.setSignatories(VerifyCMSSignatureRequest.ALL_SIGNATORIES); - verifyCMSSignatureRequest.setPDF(isPdfSignature); - verifyCMSSignatureRequest.setExtended(performExtendedValidation); - return verifyCMSSignatureRequest; - - } - - /** - * Build a VerifyXML-Signature request for MOA-Sig - * - * @param signature Serialized XML signature - * @param trustProfileID MOA-Sig Trust-Profile - * @param verifyTransformsInfoProfileID {@link List} of Transformation-Profiles used for validation - * @param xpathSignatureLocation Xpath that points to location of Signature element - * @return - * @throws MOASigServiceBuilderException - */ - private Element buildVerifyXMLRequest(byte[] signature, String trustProfileID, List<String> verifyTransformsInfoProfileID, String xpathSignatureLocation) throws MOASigServiceBuilderException { - try { - //build empty document - final Document requestDoc_ = getNewDocumentBuilder(); - final Element requestElem_ = requestDoc_.createElementNS(MOA_NS_URI, "VerifyXMLSignatureRequest"); - requestElem_.setAttributeNS(XMLNS_NS_URI, "xmlns", MOA_NS_URI); - requestElem_.setAttributeNS(XMLNS_NS_URI, "xmlns:" + Constants.DSIG_PREFIX, Constants.DSIG_NS_URI); - requestDoc_.appendChild(requestElem_); - - - // build the request - final Element verifiySignatureInfoElem = requestDoc_.createElementNS(MOA_NS_URI, "VerifySignatureInfo"); - requestElem_.appendChild(verifiySignatureInfoElem); - final Element verifySignatureEnvironmentElem = requestDoc_.createElementNS(MOA_NS_URI, "VerifySignatureEnvironment"); - verifiySignatureInfoElem.appendChild(verifySignatureEnvironmentElem); - final Element base64ContentElem = requestDoc_.createElementNS(MOA_NS_URI, "Base64Content"); - verifySignatureEnvironmentElem.appendChild(base64ContentElem); - - // insert the base64 encoded signature - String base64EncodedAssertion = Base64Utils.encodeToString(signature); - //replace all '\r' characters by no char. - final StringBuffer replaced = new StringBuffer(); - for (int i = 0; i < base64EncodedAssertion.length(); i ++) { - final char c = base64EncodedAssertion.charAt(i); - if (c != '\r') { - replaced.append(c); - } - } - base64EncodedAssertion = replaced.toString(); - final Node base64Content = requestDoc_.createTextNode(base64EncodedAssertion); - base64ContentElem.appendChild(base64Content); - - // specify the signature location - final Element verifySignatureLocationElem = requestDoc_.createElementNS(MOA_NS_URI, "VerifySignatureLocation"); - verifiySignatureInfoElem.appendChild(verifySignatureLocationElem); - final Node signatureLocation = requestDoc_.createTextNode(xpathSignatureLocation); - verifySignatureLocationElem.appendChild(signatureLocation); - - // signature manifest params - if (verifyTransformsInfoProfileID != null && !verifyTransformsInfoProfileID.isEmpty()) { - final Element signatureManifestCheckParamsElem = requestDoc_.createElementNS(MOA_NS_URI, "SignatureManifestCheckParams"); - requestElem_.appendChild(signatureManifestCheckParamsElem); - signatureManifestCheckParamsElem.setAttribute("ReturnReferenceInputData", "false"); - - //verify transformations - final Element referenceInfoElem = requestDoc_.createElementNS(MOA_NS_URI, "ReferenceInfo"); - signatureManifestCheckParamsElem.appendChild(referenceInfoElem); - for (final String element : verifyTransformsInfoProfileID) { - final Element verifyTransformsInfoProfileIDElem = requestDoc_.createElementNS(MOA_NS_URI, "VerifyTransformsInfoProfileID"); - referenceInfoElem.appendChild(verifyTransformsInfoProfileIDElem); - verifyTransformsInfoProfileIDElem.appendChild(requestDoc_.createTextNode(element)); - - } - } - - //hashinput data - final Element returnHashInputDataElem = requestDoc_.createElementNS(MOA_NS_URI, "ReturnHashInputData"); - requestElem_.appendChild(returnHashInputDataElem); - - //add trustProfileID - final Element trustProfileIDElem = requestDoc_.createElementNS(MOA_NS_URI, "TrustProfileID"); - trustProfileIDElem.appendChild(requestDoc_.createTextNode(trustProfileID)); - requestElem_.appendChild(trustProfileIDElem); - - return requestElem_; - - } catch (final Throwable t) { - log.warn("Can NOT build VerifyXML-Signature request for MOA-Sig", t); - throw new MOASigServiceBuilderException("service.moasig.03", new Object[] { t.getMessage() }, t); - - } - - } - - - - @PostConstruct - protected void internalInitializer() { - log.debug("Instanzing SignatureVerificationService implementation ... "); - //svs = at.gv.egovernment.moa.spss.api.SignatureVerificationService.getInstance(); - cadesInvoker = CMSSignatureVerificationInvoker.getInstance(); - xadesInvocer = XMLSignatureVerificationInvoker.getInstance(); - log.info("MOA-Sig signature-verification service initialized"); - - } + // add trustProfileID + final Element trustProfileIdElem = requestDoc_.createElementNS(MOA_NS_URI, "TrustProfileID"); + trustProfileIdElem.appendChild(requestDoc_.createTextNode(trustProfileID)); + requestElem_.appendChild(trustProfileIdElem); + + return requestElem_; + + } catch (final Throwable t) { + log.warn("Can NOT build VerifyXML-Signature request for MOA-Sig", t); + throw new MoaSigServiceBuilderException("service.moasig.03", new Object[] { t.getMessage() }, + t); + + } + + } + + @PostConstruct + protected void internalInitializer() { + log.debug("Instanzing SignatureVerificationService implementation ... "); + // svs = + // at.gv.egovernment.moa.spss.api.SignatureVerificationService.getInstance(); + cadesInvoker = CMSSignatureVerificationInvoker.getInstance(); + xadesInvocer = XMLSignatureVerificationInvoker.getInstance(); + log.info("MOA-Sig signature-verification service initialized"); + + } } diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/data/GenericSignatureVerificationResponse.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/data/GenericSignatureVerificationResponse.java index f3c724d8..0485f31f 100644 --- a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/data/GenericSignatureVerificationResponse.java +++ b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/data/GenericSignatureVerificationResponse.java @@ -2,129 +2,151 @@ package at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.data; import java.io.Serializable; import java.security.cert.CertificateException; -import iaik.x509.X509Certificate; import java.util.Date; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api.data.IGenericSignatureVerificationResponse; -import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions.MOASigServiceException; -import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions.MOASigServiceParserException; - -public class GenericSignatureVerificationResponse implements IGenericSignatureVerificationResponse, Serializable { - - private static final long serialVersionUID = -7751001050689401118L; - private static final Logger log = LoggerFactory.getLogger(GenericSignatureVerificationResponse.class); - - - /** The signing time */ - private Date signingDateTime; - - /** The signatureCheckCode to be stored */ - private int signatureCheckCode; - - /** The certificateCheckCode to be stored */ - private int certificateCheckCode; - - /** The publicAuthority to be stored */ - private boolean publicAuthority; - - /** The publicAuthorityCode to be stored */ - private String publicAuthorityCode; - - /** The qualifiedCertificate to be stored */ - private boolean qualifiedCertificate; - - private byte[] x509CertificateEncoded; - - @Override - public Date getSigningDateTime() { - return this.signingDateTime; - - } - - @Override - public int getSignatureCheckCode() { - return this.signatureCheckCode; - - } - - @Override - public int getCertificateCheckCode() { - return this.certificateCheckCode; - - } - - @Override - public boolean isQualifiedCertificate() { - return this.qualifiedCertificate; - - } - - @Override - public X509Certificate getX509Certificate() throws MOASigServiceException { - if (x509CertificateEncoded != null) { - try { - return new X509Certificate(x509CertificateEncoded); - - } catch (CertificateException e) { - log.error("Can NOT parse X509 certifcate in " + GenericSignatureVerificationResponse.class.getName(), e); - throw new MOASigServiceParserException("service.moasig.01", null, e); - } - - } - - return null; - - } - - @Override - public byte[] getX509CertificateEncoded() { - return this.getX509CertificateEncoded(); - - } - - @Override - public boolean isPublicAuthority() { - return this.publicAuthority; - - } - - @Override - public String getPublicAuthorityCode() { - return this.publicAuthorityCode; - - } - - public void setSigningDateTime(Date signingDateTime) { - this.signingDateTime = signingDateTime; - } - - public void setSignatureCheckCode(int signatureCheckCode) { - this.signatureCheckCode = signatureCheckCode; - } - - public void setCertificateCheckCode(int certificateCheckCode) { - this.certificateCheckCode = certificateCheckCode; - } - - public void setPublicAuthority(boolean publicAuthority) { - this.publicAuthority = publicAuthority; - } - - public void setPublicAuthorityCode(String publicAuthorityCode) { - this.publicAuthorityCode = publicAuthorityCode; - } - - public void setQualifiedCertificate(boolean qualifiedCertificate) { - this.qualifiedCertificate = qualifiedCertificate; - } - - public void setX509CertificateEncoded(byte[] x509CertificateEncoded) { - this.x509CertificateEncoded = x509CertificateEncoded; - } - - +import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions.MoaSigServiceException; +import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions.MoaSigServiceParserException; +import iaik.x509.X509Certificate; + +public class GenericSignatureVerificationResponse + implements IGenericSignatureVerificationResponse, Serializable { + + private static final long serialVersionUID = -7751001050689401118L; + private static final Logger log = + LoggerFactory.getLogger(GenericSignatureVerificationResponse.class); + + /** The signing time. */ + private Date signingDateTime; + + /** The signatureCheckCode to be stored. */ + private int signatureCheckCode; + + /** The certificateCheckCode to be stored. */ + private int certificateCheckCode; + + /** The publicAuthority to be stored. */ + private boolean publicAuthority; + + /** The publicAuthorityCode to be stored. */ + private String publicAuthorityCode; + + /** The qualifiedCertificate to be stored. */ + private boolean qualifiedCertificate; + + private byte[] x509CertificateEncoded; + + @Override + public Date getSigningDateTime() { + if (this.signingDateTime != null) { + return new Date(this.signingDateTime.getTime()); + } + return null; + + } + + @Override + public int getSignatureCheckCode() { + return this.signatureCheckCode; + + } + + @Override + public int getCertificateCheckCode() { + return this.certificateCheckCode; + + } + + @Override + public boolean isQualifiedCertificate() { + return this.qualifiedCertificate; + + } + + @Override + public X509Certificate getX509Certificate() throws MoaSigServiceException { + if (x509CertificateEncoded != null) { + try { + return new X509Certificate(x509CertificateEncoded); + + } catch (final CertificateException e) { + log.error("Can NOT parse X509 certifcate in " + + GenericSignatureVerificationResponse.class.getName(), e); + throw new MoaSigServiceParserException("service.moasig.01", null, e); + } + + } + + return null; + + } + + @Override + public byte[] getX509CertificateEncoded() { + if (this.x509CertificateEncoded != null) { + return this.x509CertificateEncoded.clone(); + + } + return null; + + } + + @Override + public boolean isPublicAuthority() { + return this.publicAuthority; + + } + + @Override + public String getPublicAuthorityCode() { + return this.publicAuthorityCode; + + } + + /** + * Set signature creation timestramp. + * + * @param signingDateTime timestamp + */ + public void setSigningDateTime(final Date signingDateTime) { + if (signingDateTime != null) { + this.signingDateTime = new Date(signingDateTime.getTime()); + } + } + + public void setSignatureCheckCode(final int signatureCheckCode) { + this.signatureCheckCode = signatureCheckCode; + } + + public void setCertificateCheckCode(final int certificateCheckCode) { + this.certificateCheckCode = certificateCheckCode; + } + + public void setPublicAuthority(final boolean publicAuthority) { + this.publicAuthority = publicAuthority; + } + + public void setPublicAuthorityCode(final String publicAuthorityCode) { + this.publicAuthorityCode = publicAuthorityCode; + } + + public void setQualifiedCertificate(final boolean qualifiedCertificate) { + this.qualifiedCertificate = qualifiedCertificate; + } + + /** + * Set encoded signer certificate. + * + * @param x509CertificateEncoded signer cerificate + */ + public void setX509CertificateEncoded(final byte[] x509CertificateEncoded) { + if (x509CertificateEncoded != null) { + this.x509CertificateEncoded = x509CertificateEncoded.clone(); + + } + } } diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/data/VerifyCMSSignatureResponse.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/data/VerifyCMSSignatureResponse.java deleted file mode 100644 index 2c177c71..00000000 --- a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/data/VerifyCMSSignatureResponse.java +++ /dev/null @@ -1,9 +0,0 @@ -package at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.data; - -import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api.data.ICMSSignatureVerificationResponse; - -public class VerifyCMSSignatureResponse extends GenericSignatureVerificationResponse implements ICMSSignatureVerificationResponse{ - - private static final long serialVersionUID = 708260904158070696L; - -} diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/data/VerifyCmsSignatureResponse.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/data/VerifyCmsSignatureResponse.java new file mode 100644 index 00000000..ed679828 --- /dev/null +++ b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/data/VerifyCmsSignatureResponse.java @@ -0,0 +1,10 @@ +package at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.data; + +import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api.data.ICmsSignatureVerificationResponse; + +public class VerifyCmsSignatureResponse extends GenericSignatureVerificationResponse + implements ICmsSignatureVerificationResponse { + + private static final long serialVersionUID = 708260904158070696L; + +} diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/data/VerifyXMLSignatureResponse.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/data/VerifyXMLSignatureResponse.java deleted file mode 100644 index 0646bda7..00000000 --- a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/data/VerifyXMLSignatureResponse.java +++ /dev/null @@ -1,93 +0,0 @@ -package at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.data; - -import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api.data.IXMLSignatureVerificationResponse; - -/** - * - * - * @author tlenz - * - */ - -public class VerifyXMLSignatureResponse extends GenericSignatureVerificationResponse implements IXMLSignatureVerificationResponse { - - private static final long serialVersionUID = 8386070769565711601L; - -/** The xmlDsigSubjectName to be stored */ - private String xmlDsigSubjectName; - - /** The xmlDSIGManifestCheckCode to be stored */ - private int xmlDSIGManifestCheckCode; - /** The xmlDSIGManigest to be stored */ - private boolean xmlDSIGManigest; - - /** - * The result of the signature manifest check. The default value <code>-1</code> - * indicates that the signature manifest has not been checked. - */ - private int signatureManifestCheckCode = -1; - - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.data.IVerifiyXMLSignatureResponse#getXmlDSIGManifestCheckCode() - */ - @Override -public int getXmlDSIGManifestCheckCode() { - return xmlDSIGManifestCheckCode; - } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.data.IVerifiyXMLSignatureResponse#getXmlDsigSubjectName() - */ - @Override -public String getXmlDsigSubjectName() { - return xmlDsigSubjectName; - } - - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.data.IVerifiyXMLSignatureResponse#setXmlDSIGManifestCheckCode(int) - */ -public void setXmlDSIGManifestCheckCode(int xmlDSIGManifestCheckCode) { - this.xmlDSIGManifestCheckCode = xmlDSIGManifestCheckCode; - } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.data.IVerifiyXMLSignatureResponse#setXmlDsigSubjectName(java.lang.String) - */ -public void setXmlDsigSubjectName(String xmlDsigSubjectName) { - this.xmlDsigSubjectName = xmlDsigSubjectName; - } - - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.data.IVerifiyXMLSignatureResponse#isXmlDSIGManigest() - */ - @Override -public boolean isXmlDSIGManigest() { - return xmlDSIGManigest; - } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.data.IVerifiyXMLSignatureResponse#setXmlDSIGManigest(boolean) - */ -public void setXmlDSIGManigest(boolean xmlDSIGManigest) { - this.xmlDSIGManigest = xmlDSIGManigest; - } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.data.IVerifiyXMLSignatureResponse#getSignatureManifestCheckCode() - */ - @Override -public int getSignatureManifestCheckCode() { - return signatureManifestCheckCode; - } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.auth.data.IVerifiyXMLSignatureResponse#setSignatureManifestCheckCode(int) - */ -public void setSignatureManifestCheckCode(int signatureManifestCheckCode) { - this.signatureManifestCheckCode = signatureManifestCheckCode; - } - -} diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/data/VerifyXmlSignatureResponse.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/data/VerifyXmlSignatureResponse.java new file mode 100644 index 00000000..4b0632b1 --- /dev/null +++ b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/data/VerifyXmlSignatureResponse.java @@ -0,0 +1,115 @@ +package at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.data; + +import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api.data.IXmlSignatureVerificationResponse; + +/** + * MOA-Sig signature verification response for XML based signatures. + * + * @author tlenz + * + */ + +public class VerifyXmlSignatureResponse extends GenericSignatureVerificationResponse + implements IXmlSignatureVerificationResponse { + + private static final long serialVersionUID = 8386070769565711601L; + + /** The xmlDsigSubjectName to be stored. */ + private String xmlDsigSubjectName; + + /** The xmlDSIGManifestCheckCode to be stored. */ + private int xmlDsigManifestCheckCode; + /** The xmlDSIGManigest to be stored. */ + private boolean xmlDsigManigest; + + /** + * The result of the signature manifest check. The default value <code>-1</code> + * indicates that the signature manifest has not been checked. + */ + private int signatureManifestCheckCode = -1; + + /* + * (non-Javadoc) + * + * @see at.gv.egovernment.moa.id.auth.data.IVerifiyXMLSignatureResponse# + * getXmlDSIGManifestCheckCode() + */ + @Override + public int getXmlDsigManifestCheckCode() { + return xmlDsigManifestCheckCode; + } + + /* + * (non-Javadoc) + * + * @see at.gv.egovernment.moa.id.auth.data.IVerifiyXMLSignatureResponse# + * getXmlDsigSubjectName() + */ + @Override + public String getXmlDsigSubjectName() { + return xmlDsigSubjectName; + } + + /* + * (non-Javadoc) + * + * @see at.gv.egovernment.moa.id.auth.data.IVerifiyXMLSignatureResponse# + * setXmlDSIGManifestCheckCode( int) + */ + public void setXmlDsigManifestCheckCode(final int xmlDsigManifestCheckCode) { + this.xmlDsigManifestCheckCode = xmlDsigManifestCheckCode; + } + + /* + * (non-Javadoc) + * + * @see at.gv.egovernment.moa.id.auth.data.IVerifiyXMLSignatureResponse# + * setXmlDsigSubjectName(java.lang .String) + */ + public void setXmlDsigSubjectName(final String xmlDsigSubjectName) { + this.xmlDsigSubjectName = xmlDsigSubjectName; + } + + /* + * (non-Javadoc) + * + * @see at.gv.egovernment.moa.id.auth.data.IVerifiyXMLSignatureResponse# + * isXmlDSIGManigest() + */ + @Override + public boolean isXmlDsigManigest() { + return xmlDsigManigest; + } + + /* + * (non-Javadoc) + * + * @see at.gv.egovernment.moa.id.auth.data.IVerifiyXMLSignatureResponse# + * setXmlDSIGManigest(boolean) + */ + public void setXmlDsigManigest(final boolean xmlDsigManigest) { + this.xmlDsigManigest = xmlDsigManigest; + } + + /* + * (non-Javadoc) + * + * @see at.gv.egovernment.moa.id.auth.data.IVerifiyXMLSignatureResponse# + * getSignatureManifestCheckCode() + */ + @Override + public int getSignatureManifestCheckCode() { + return signatureManifestCheckCode; + } + + /* + * (non-Javadoc) + * + * @see at.gv.egovernment.moa.id.auth.data.IVerifiyXMLSignatureResponse# + * setSignatureManifestCheckCode( int) + */ + public void setSignatureManifestCheckCode(final int signatureManifestCheckCode) { + this.signatureManifestCheckCode = signatureManifestCheckCode; + } + +} diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/parser/VerifyXMLSignatureResponseParser.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/parser/VerifyXMLSignatureResponseParser.java deleted file mode 100644 index e581394b..00000000 --- a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/parser/VerifyXMLSignatureResponseParser.java +++ /dev/null @@ -1,180 +0,0 @@ -package at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.parser; - -import java.io.ByteArrayInputStream; -import java.io.InputStream; - -import org.joda.time.DateTime; -import org.joda.time.format.ISODateTimeFormat; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.lang.NonNull; -import org.w3c.dom.Element; - -import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api.data.IXMLSignatureVerificationResponse; -import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions.MOASigServiceException; -import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions.MOASigServiceParserException; -import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.data.VerifyXMLSignatureResponse; -import at.gv.egovernment.moaspss.util.Constants; -import at.gv.egovernment.moaspss.util.DOMUtils; -import at.gv.egovernment.moaspss.util.XPathUtils; -import iaik.utils.Base64InputStream; -import iaik.x509.X509Certificate; - - -public class VerifyXMLSignatureResponseParser { - private static final Logger log = LoggerFactory.getLogger(VerifyXMLSignatureResponseParser.class); - - // - // XPath namespace prefix shortcuts - // - /** Xpath prefix for reaching MOA Namespaces */ - private static final String MOA = Constants.MOA_PREFIX + ":"; - /** Xpath prefix for reaching DSIG Namespaces */ - private static final String DSIG = Constants.DSIG_PREFIX + ":"; - /** Xpath expression to the root element */ - private static final String ROOT = "/" + MOA + "VerifyXMLSignatureResponse/"; - - /** Xpath expression to the X509SubjectName element */ - private static final String DSIG_SUBJECT_NAME_XPATH = - ROOT + MOA + "SignerInfo/" + DSIG + "X509Data/" + - DSIG + "X509SubjectName"; - /** Xpath expression to the X509Certificate element */ - private static final String DSIG_X509_CERTIFICATE_XPATH = - ROOT + MOA + "SignerInfo/" + DSIG + "X509Data/" + - DSIG + "X509Certificate"; - /** Xpath expression to the PublicAuthority element */ - private static final String PUBLIC_AUTHORITY_XPATH = - ROOT + MOA + "SignerInfo/" + DSIG + "X509Data/" + - MOA + "PublicAuthority"; - /** Xpath expression to the PublicAuthorityCode element */ - private static final String PUBLIC_AUTHORITY_CODE_XPATH = - PUBLIC_AUTHORITY_XPATH + "/" + MOA + "Code"; - /** Xpath expression to the QualifiedCertificate element */ - private static final String QUALIFIED_CERTIFICATE_XPATH = - ROOT + MOA + "SignerInfo/" + DSIG + "X509Data/" + - MOA + "QualifiedCertificate"; - - /** Xpath expression to the SignatureCheckCode element */ - private static final String SIGNATURE_CHECK_CODE_XPATH = - ROOT + MOA + "SignatureCheck/" + MOA + "Code"; - /** Xpath expression to the XMLDSIGManifestCheckCode element */ - private static final String XMLDSIG_MANIFEST_CHECK_CODE_XPATH = - ROOT + MOA + "XMLDSIGManifestCheck/" + MOA + "Code"; - /** Xpath expression to the SignatureManifestCheckCode element */ - private static final String SIGNATURE_MANIFEST_CHECK_CODE_XPATH = - ROOT + MOA + "SignatureManifestCheck/" + MOA + "Code"; - /** Xpath expression to the CertificateCheckCode element */ - private static final String CERTIFICATE_CHECK_CODE_XPATH = - ROOT + MOA + "CertificateCheck/" + MOA + "Code"; - - private static final String SIGNING_TIME_XPATH = - ROOT + MOA + "SigningTime"; - - - /** This is the root element of the XML-Document provided by the Security Layer Card*/ - private Element verifyXMLSignatureResponse; - - /** - * Constructor for VerifyXMLSignatureResponseParser. - * A DOM-representation of the incoming String will be created - * @param xmlResponse <code><InfoboxReadResponse></code> as String - * @throws MOASigServiceParserException on any parsing error - */ - public VerifyXMLSignatureResponseParser(String xmlResponse) throws MOASigServiceParserException { - try { - final InputStream s = new ByteArrayInputStream(xmlResponse.getBytes("UTF-8")); - verifyXMLSignatureResponse = DOMUtils.parseXmlValidating(s); - - } catch (final Throwable t) { - log.warn("Can not parse MOA-Sig response." , t); - throw new MOASigServiceParserException("service.moasig.02", new Object[] { t.toString() }, t); - - } - } - - /** - * Constructor for VerifyXMLSignatureResponseParser. - * A DOM-representation of the incoming Inputstream will be created - * @param xmlResponse <code><InfoboxReadResponse></code> as InputStream - * @throws MOASigServiceParserException on any parsing error - */ - public VerifyXMLSignatureResponseParser(InputStream xmlResponse) throws MOASigServiceParserException { - try { - verifyXMLSignatureResponse = DOMUtils.parseXmlValidating(xmlResponse); - - } catch (final Throwable t) { - log.warn("Can not parse MOA-Sig response." , t); - throw new MOASigServiceParserException("service.moasig.02", new Object[] { t.toString() }, t); - - } - } - - /** - * Constructor for VerifyXMLSignatureResponseParser. - * The incoming Element will be used for further operations - * @param xmlResponse <code><InfoboxReadResponse></code> as Element - */ - public VerifyXMLSignatureResponseParser(Element xmlResponse) { - verifyXMLSignatureResponse =xmlResponse; - - } - -/** - * Parse MOA-Sig signatur-verification result into {@link IXMLSignatureVerificationResponse} - * - * @return {@link IXMLSignatureVerificationResponse} - * @throws MOASigServiceException on any parsing error - */ - @NonNull - public IXMLSignatureVerificationResponse parseData() throws MOASigServiceException { - try { - final VerifyXMLSignatureResponse respData = new VerifyXMLSignatureResponse(); - respData.setXmlDsigSubjectName(XPathUtils.getElementValue(verifyXMLSignatureResponse,DSIG_SUBJECT_NAME_XPATH,"")); - final Element e = (Element)XPathUtils.selectSingleNode(verifyXMLSignatureResponse,QUALIFIED_CERTIFICATE_XPATH); - respData.setQualifiedCertificate(e!=null); - - final Base64InputStream in = new Base64InputStream(new ByteArrayInputStream(XPathUtils.getElementValue( - verifyXMLSignatureResponse,DSIG_X509_CERTIFICATE_XPATH,"").getBytes("UTF-8")),true); - - respData.setX509CertificateEncoded(new X509Certificate(in).getEncoded()); - - final Element publicAuthority = (Element)XPathUtils.selectSingleNode(verifyXMLSignatureResponse,PUBLIC_AUTHORITY_XPATH); - respData.setPublicAuthority(publicAuthority != null); - respData.setPublicAuthorityCode(XPathUtils.getElementValue(verifyXMLSignatureResponse,PUBLIC_AUTHORITY_CODE_XPATH,"")); - respData.setSignatureCheckCode(new Integer(XPathUtils.getElementValue(verifyXMLSignatureResponse,SIGNATURE_CHECK_CODE_XPATH,"")).intValue()); - - final String xmlDsigCheckCode = XPathUtils.getElementValue(verifyXMLSignatureResponse,XMLDSIG_MANIFEST_CHECK_CODE_XPATH,null); - if (xmlDsigCheckCode!=null) { - respData.setXmlDSIGManigest(true); - respData.setXmlDSIGManifestCheckCode(new Integer(xmlDsigCheckCode).intValue()); - - } else { - respData.setXmlDSIGManigest(false); - - } - - final String signatureManifestCheckCode = XPathUtils.getElementValue(verifyXMLSignatureResponse,SIGNATURE_MANIFEST_CHECK_CODE_XPATH,null); - if (signatureManifestCheckCode != null) { - respData.setSignatureManifestCheckCode(new Integer(signatureManifestCheckCode).intValue()); - - } - respData.setCertificateCheckCode(new Integer(XPathUtils.getElementValue(verifyXMLSignatureResponse,CERTIFICATE_CHECK_CODE_XPATH,"")).intValue()); - - final String signingTimeElement = XPathUtils.getElementValue(verifyXMLSignatureResponse,SIGNING_TIME_XPATH,""); - if (signingTimeElement != null && !signingTimeElement.isEmpty()) { - final DateTime datetime = ISODateTimeFormat.dateOptionalTimeParser().parseDateTime(signingTimeElement); - respData.setSigningDateTime(datetime.toDate()); - - } - - return respData; - - } catch (final Throwable t) { - log.warn("Can not parse MOA-Sig response." , t); - throw new MOASigServiceParserException("service.moasig.02", new Object[] { t.toString() }, t); - } - - } - - -} diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/parser/VerifyXmlSignatureResponseParser.java b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/parser/VerifyXmlSignatureResponseParser.java new file mode 100644 index 00000000..231cb94f --- /dev/null +++ b/eaaf_modules/eaaf_module_moa-sig/src/main/java/at/gv/egiz/eid/authhandler/modules/sigverify/moasig/impl/parser/VerifyXmlSignatureResponseParser.java @@ -0,0 +1,193 @@ +package at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.parser; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +import org.joda.time.DateTime; +import org.joda.time.format.ISODateTimeFormat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.lang.NonNull; +import org.w3c.dom.Element; + +import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.api.data.IXmlSignatureVerificationResponse; +import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions.MoaSigServiceException; +import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.exceptions.MoaSigServiceParserException; +import at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.data.VerifyXmlSignatureResponse; +import at.gv.egovernment.moaspss.util.Constants; +import at.gv.egovernment.moaspss.util.DOMUtils; +import at.gv.egovernment.moaspss.util.XPathUtils; +import iaik.utils.Base64InputStream; +import iaik.x509.X509Certificate; + +public class VerifyXmlSignatureResponseParser { + private static final Logger log = LoggerFactory.getLogger(VerifyXmlSignatureResponseParser.class); + + // + // XPath namespace prefix shortcuts + // + /** Xpath prefix for reaching MOA Namespaces. */ + private static final String MOA = Constants.MOA_PREFIX + ":"; + /** Xpath prefix for reaching DSIG Namespaces. */ + private static final String DSIG = Constants.DSIG_PREFIX + ":"; + /** Xpath expression to the root element. */ + private static final String ROOT = "/" + MOA + "VerifyXMLSignatureResponse/"; + + /** Xpath expression to the X509SubjectName element. */ + private static final String DSIG_SUBJECT_NAME_XPATH = + ROOT + MOA + "SignerInfo/" + DSIG + "X509Data/" + DSIG + "X509SubjectName"; + /** Xpath expression to the X509Certificate element. */ + private static final String DSIG_X509_CERTIFICATE_XPATH = + ROOT + MOA + "SignerInfo/" + DSIG + "X509Data/" + DSIG + "X509Certificate"; + /** Xpath expression to the PublicAuthority element. */ + private static final String PUBLIC_AUTHORITY_XPATH = + ROOT + MOA + "SignerInfo/" + DSIG + "X509Data/" + MOA + "PublicAuthority"; + /** Xpath expression to the PublicAuthorityCode element. */ + private static final String PUBLIC_AUTHORITY_CODE_XPATH = + PUBLIC_AUTHORITY_XPATH + "/" + MOA + "Code"; + /** Xpath expression to the QualifiedCertificate element. */ + private static final String QUALIFIED_CERTIFICATE_XPATH = + ROOT + MOA + "SignerInfo/" + DSIG + "X509Data/" + MOA + "QualifiedCertificate"; + + /** Xpath expression to the SignatureCheckCode element. */ + private static final String SIGNATURE_CHECK_CODE_XPATH = + ROOT + MOA + "SignatureCheck/" + MOA + "Code"; + /** Xpath expression to the XMLDSIGManifestCheckCode element. */ + private static final String XMLDSIG_MANIFEST_CHECK_CODE_XPATH = + ROOT + MOA + "XMLDSIGManifestCheck/" + MOA + "Code"; + /** Xpath expression to the SignatureManifestCheckCode element. */ + private static final String SIGNATURE_MANIFEST_CHECK_CODE_XPATH = + ROOT + MOA + "SignatureManifestCheck/" + MOA + "Code"; + /** Xpath expression to the CertificateCheckCode element. */ + private static final String CERTIFICATE_CHECK_CODE_XPATH = + ROOT + MOA + "CertificateCheck/" + MOA + "Code"; + + private static final String SIGNING_TIME_XPATH = ROOT + MOA + "SigningTime"; + + /** + * This is the root element of the XML-Document provided by the Security Layer + * Card. + */ + private Element verifyXmlSignatureResponse; + + /** + * Constructor for VerifyXMLSignatureResponseParser. A DOM-representation of the + * incoming String will be created + * + * @param xmlResponse <code><InfoboxReadResponse></code> as String + * @throws MoaSigServiceParserException on any parsing error + */ + public VerifyXmlSignatureResponseParser(final String xmlResponse) + throws MoaSigServiceParserException { + try { + final InputStream s = new ByteArrayInputStream(xmlResponse.getBytes("UTF-8")); + verifyXmlSignatureResponse = DOMUtils.parseXmlValidating(s); + + } catch (final Throwable t) { + log.warn("Can not parse MOA-Sig response.", t); + throw new MoaSigServiceParserException("service.moasig.02", new Object[] { t.toString() }, t); + + } + } + + /** + * Constructor for VerifyXMLSignatureResponseParser. A DOM-representation of the + * incoming Inputstream will be created + * + * @param xmlResponse <code><InfoboxReadResponse></code> as InputStream + * @throws MoaSigServiceParserException on any parsing error + */ + public VerifyXmlSignatureResponseParser(final InputStream xmlResponse) + throws MoaSigServiceParserException { + try { + verifyXmlSignatureResponse = DOMUtils.parseXmlValidating(xmlResponse); + + } catch (final Throwable t) { + log.warn("Can not parse MOA-Sig response.", t); + throw new MoaSigServiceParserException("service.moasig.02", new Object[] { t.toString() }, t); + + } + } + + /** + * Constructor for VerifyXMLSignatureResponseParser. The incoming Element will + * be used for further operations + * + * @param xmlResponse <code><InfoboxReadResponse></code> as Element + */ + public VerifyXmlSignatureResponseParser(final Element xmlResponse) { + verifyXmlSignatureResponse = xmlResponse; + + } + + /** + * Parse MOA-Sig signatur-verification result into + * {@link IXmlSignatureVerificationResponse}. + * + * @return {@link IXmlSignatureVerificationResponse} + * @throws MoaSigServiceException on any parsing error + */ + @NonNull + public IXmlSignatureVerificationResponse parseData() throws MoaSigServiceException { + try { + final VerifyXmlSignatureResponse respData = new VerifyXmlSignatureResponse(); + respData.setXmlDsigSubjectName( + XPathUtils.getElementValue(verifyXmlSignatureResponse, DSIG_SUBJECT_NAME_XPATH, "")); + final Element e = (Element) XPathUtils.selectSingleNode(verifyXmlSignatureResponse, + QUALIFIED_CERTIFICATE_XPATH); + respData.setQualifiedCertificate(e != null); + + final Base64InputStream in = new Base64InputStream(new ByteArrayInputStream( + XPathUtils.getElementValue(verifyXmlSignatureResponse, DSIG_X509_CERTIFICATE_XPATH, "") + .getBytes("UTF-8")), + true); + + respData.setX509CertificateEncoded(new X509Certificate(in).getEncoded()); + + final Element publicAuthority = + (Element) XPathUtils.selectSingleNode(verifyXmlSignatureResponse, PUBLIC_AUTHORITY_XPATH); + respData.setPublicAuthority(publicAuthority != null); + respData.setPublicAuthorityCode( + XPathUtils.getElementValue(verifyXmlSignatureResponse, PUBLIC_AUTHORITY_CODE_XPATH, "")); + respData.setSignatureCheckCode(Integer.parseInt( + XPathUtils.getElementValue(verifyXmlSignatureResponse, SIGNATURE_CHECK_CODE_XPATH, ""))); + + final String xmlDsigCheckCode = XPathUtils.getElementValue(verifyXmlSignatureResponse, + XMLDSIG_MANIFEST_CHECK_CODE_XPATH, null); + if (xmlDsigCheckCode != null) { + respData.setXmlDsigManigest(true); + respData.setXmlDsigManifestCheckCode(Integer.parseInt(xmlDsigCheckCode)); + + } else { + respData.setXmlDsigManigest(false); + + } + + final String signatureManifestCheckCode = XPathUtils + .getElementValue(verifyXmlSignatureResponse, SIGNATURE_MANIFEST_CHECK_CODE_XPATH, null); + if (signatureManifestCheckCode != null) { + respData.setSignatureManifestCheckCode(Integer.parseInt(signatureManifestCheckCode)); + + } + respData.setCertificateCheckCode(Integer.parseInt( + XPathUtils.getElementValue(verifyXmlSignatureResponse, CERTIFICATE_CHECK_CODE_XPATH, ""))); + + final String signingTimeElement = + XPathUtils.getElementValue(verifyXmlSignatureResponse, SIGNING_TIME_XPATH, ""); + if (signingTimeElement != null && !signingTimeElement.isEmpty()) { + final DateTime datetime = + ISODateTimeFormat.dateOptionalTimeParser().parseDateTime(signingTimeElement); + respData.setSigningDateTime(datetime.toDate()); + + } + + return respData; + + } catch (final Throwable t) { + log.warn("Can not parse MOA-Sig response.", t); + throw new MoaSigServiceParserException("service.moasig.02", new Object[] { t.toString() }, t); + } + + } + +} diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider b/eaaf_modules/eaaf_module_moa-sig/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider index ebc25602..2f0ae67f 100644 --- a/eaaf_modules/eaaf_module_moa-sig/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider +++ b/eaaf_modules/eaaf_module_moa-sig/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider @@ -1 +1 @@ -at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.MOASigSpringResourceProvider
\ No newline at end of file +at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.MoaSigSpringResourceProvider
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_moa-sig/src/main/resources/moa-sig-service.beans.xml b/eaaf_modules/eaaf_module_moa-sig/src/main/resources/moa-sig-service.beans.xml index 60b75f3c..c5e05853 100644 --- a/eaaf_modules/eaaf_module_moa-sig/src/main/resources/moa-sig-service.beans.xml +++ b/eaaf_modules/eaaf_module_moa-sig/src/main/resources/moa-sig-service.beans.xml @@ -1,25 +1,25 @@ <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xmlns:context="http://www.springframework.org/schema/context" - xmlns:tx="http://www.springframework.org/schema/tx" - xmlns:aop="http://www.springframework.org/schema/aop" - xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd - http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd - http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd - http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:context="http://www.springframework.org/schema/context" + xmlns:tx="http://www.springframework.org/schema/tx" + xmlns:aop="http://www.springframework.org/schema/aop" + xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd + http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> - <context:annotation-config /> + <context:annotation-config /> + + <bean id="moaSigInitializer" + class="at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.MoaSigInitializer" /> + + <bean id="moaSigVerifyService" + class="at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.SignatureVerificationService" + depends-on="moaSigInitializer" /> + + <bean id="moaSigCreateService" + class="at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.SignatureCreationService" + depends-on="moaSigInitializer" /> - <bean id="moaSigInitializer" - class="at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.MoaSigInitializer" /> - - <bean id="moaSigVerifyService" - class="at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.SignatureVerificationService" - depends-on="moaSigInitializer" /> - - <bean id="moaSigCreateService" - class="at.gv.egiz.eid.authhandler.modules.sigverify.moasig.impl.SignatureCreationService" - depends-on="moaSigInitializer" /> - </beans>
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_moa-sig/src/test/java/artifacts/MavenArtifactInstaller.java b/eaaf_modules/eaaf_module_moa-sig/src/test/java/artifacts/MavenArtifactInstaller.java index 7b9e2748..11c84ec0 100644 --- a/eaaf_modules/eaaf_module_moa-sig/src/test/java/artifacts/MavenArtifactInstaller.java +++ b/eaaf_modules/eaaf_module_moa-sig/src/test/java/artifacts/MavenArtifactInstaller.java @@ -6,54 +6,65 @@ import java.text.MessageFormat; public class MavenArtifactInstaller { - public static final String MVN_INSTALL_PATH = "F:\\local_work\\program\\apache-maven-3.5.2-bin\\bin\\"; - public static final String CONFIG = "/settings.xml"; - public static final String REPO_SCAN_PATH = "/repository/iaik/prod"; - - public static final String GROUP = "iaik.prod"; - public static final String PACKAGE = "jar"; - public static final String COMMAND_TEMPLATE = "{6}mvn.cmd install:install-file -s {0} -DgroupId={1} -DartifactId={2} -Dversion={3} -Dpackaging={4} -Dfile={5}"; - - public static void main(String[] args) { - String currentLocation = new java.io.File( "." ).toURI().toString(); - currentLocation = currentLocation.substring("file:/".length(), currentLocation.length() - 2); - final String settingLocation = currentLocation + CONFIG; - final File settingsFile = new File(settingLocation); - if (!settingsFile.exists()) { - System.out.println("Maven settings does not exist"); - System.exit(-1); - - } - - final String pathToScan = currentLocation + REPO_SCAN_PATH; - - final File toScan = new File(pathToScan); - - int counter=0; - for (final File dir : toScan.listFiles()) { - final String artifactName = dir.getName(); - for (final File version : dir.listFiles()) { - final String libVersion = version.getName(); - final String jarPath = version.getAbsolutePath() + "/" + artifactName + "-" + libVersion + ".jar"; - final File jar = new File(jarPath ); - if (jar.exists()) { - final String mvnCommand = MessageFormat.format(COMMAND_TEMPLATE, settingsFile.getAbsoluteFile(), GROUP, artifactName, libVersion, PACKAGE, jar.getAbsolutePath(), MVN_INSTALL_PATH); - System.out.println("Execute: " + mvnCommand); - try { - Runtime.getRuntime().exec(mvnCommand); - counter++; - } catch (final IOException e) { - e.printStackTrace(); - - } - - } else - System.out.print("Can NOT find jar with path: " + jarPath); - - } - - } - System.out.println("Install #" + counter + " maven artifacts"); - } + public static final String MVN_INSTALL_PATH = + "F:\\local_work\\program\\apache-maven-3.5.2-bin\\bin\\"; + public static final String CONFIG = "/settings.xml"; + public static final String REPO_SCAN_PATH = "/repository/iaik/prod"; + + public static final String GROUP = "iaik.prod"; + public static final String PACKAGE = "jar"; + public static final String COMMAND_TEMPLATE = + "{6}mvn.cmd install:install-file -s {0} -DgroupId={1} -DartifactId={2} -Dversion={3} -Dpackaging={4} -Dfile={5}"; + + /** + * Only for test-deployment of maven artifacts. + * + * @param args System parameters + */ + public static void main(final String[] args) { + String currentLocation = new java.io.File(".").toURI().toString(); + currentLocation = currentLocation.substring("file:/".length(), currentLocation.length() - 2); + final String settingLocation = currentLocation + CONFIG; + final File settingsFile = new File(settingLocation); + if (!settingsFile.exists()) { + System.out.println("Maven settings does not exist"); + System.exit(-1); + + } + + final String pathToScan = currentLocation + REPO_SCAN_PATH; + + final File toScan = new File(pathToScan); + + int counter = 0; + for (final File dir : toScan.listFiles()) { + final String artifactName = dir.getName(); + for (final File version : dir.listFiles()) { + final String libVersion = version.getName(); + final String jarPath = + version.getAbsolutePath() + "/" + artifactName + "-" + libVersion + ".jar"; + final File jar = new File(jarPath); + if (jar.exists()) { + final String mvnCommand = + MessageFormat.format(COMMAND_TEMPLATE, settingsFile.getAbsoluteFile(), GROUP, + artifactName, libVersion, PACKAGE, jar.getAbsolutePath(), MVN_INSTALL_PATH); + System.out.println("Execute: " + mvnCommand); + try { + Runtime.getRuntime().exec(mvnCommand); + counter++; + } catch (final IOException e) { + e.printStackTrace(); + + } + + } else { + System.out.print("Can NOT find jar with path: " + jarPath); + } + + } + + } + System.out.println("Install #" + counter + " maven artifacts"); + } } diff --git a/eaaf_modules/eaaf_module_pvp2_core/pom.xml b/eaaf_modules/eaaf_module_pvp2_core/pom.xml index cf3f3df0..31110bfd 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/pom.xml +++ b/eaaf_modules/eaaf_module_pvp2_core/pom.xml @@ -1,11 +1,13 @@ <?xml version="1.0"?> -<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> +<project + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" + xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>at.gv.egiz.eaaf</groupId> <artifactId>eaaf_modules</artifactId> - <version>1.0.13.2</version> + <version>1.1.0</version> </parent> <artifactId>eaaf_module_pvp2_core</artifactId> <name>eaaf_module_pvp2_core</name> @@ -13,74 +15,84 @@ <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> - + <dependencies> - <dependency> - <groupId>at.gv.egiz.eaaf</groupId> - <artifactId>eaaf-core</artifactId> - <version>${egiz.eaaf.version}</version> - </dependency> - - <dependency> - <groupId>org.opensaml</groupId> - <artifactId>opensaml</artifactId> - <exclusions> - <exclusion> - <groupId>org.slf4j</groupId> - <artifactId>log4j-over-slf4j</artifactId> - </exclusion> - </exclusions> - </dependency> - <dependency> - <groupId>org.opensaml</groupId> - <artifactId>xmltooling</artifactId> - <exclusions> - <exclusion> - <groupId>org.slf4j</groupId> - <artifactId>log4j-over-slf4j</artifactId> - </exclusion> - </exclusions> - </dependency> - <dependency> - <groupId>org.opensaml</groupId> - <artifactId>openws</artifactId> - <exclusions> - <exclusion> - <groupId>org.slf4j</groupId> - <artifactId>log4j-over-slf4j</artifactId> - </exclusion> - </exclusions> - </dependency> - <dependency> - <groupId>org.apache.santuario</groupId> - <artifactId>xmlsec</artifactId> - </dependency> - <dependency> - <groupId>org.bouncycastle</groupId> - <artifactId>bcprov-jdk15on</artifactId> - </dependency> - - <dependency> - <groupId>org.owasp.esapi</groupId> - <artifactId>esapi</artifactId> - </dependency> - <dependency> - <groupId>javax.servlet</groupId> - <artifactId>javax.servlet-api</artifactId> - <scope>provided</scope> - </dependency> - - <!-- Testing --> + <dependency> + <groupId>at.gv.egiz.eaaf</groupId> + <artifactId>eaaf-core</artifactId> + <version>${egiz.eaaf.version}</version> + </dependency> + <dependency> + <groupId>org.opensaml</groupId> + <artifactId>opensaml-core</artifactId> + </dependency> + <dependency> + <groupId>org.opensaml</groupId> + <artifactId>opensaml-saml-impl</artifactId> + </dependency> + <dependency> + <groupId>org.opensaml</groupId> + <artifactId>opensaml-xmlsec-api</artifactId> + </dependency> + <dependency> + <groupId>org.opensaml</groupId> + <artifactId>opensaml-xmlsec-impl</artifactId> + </dependency> + <dependency> + <groupId>org.apache.santuario</groupId> + <artifactId>xmlsec</artifactId> + </dependency> + <dependency> + <groupId>org.bouncycastle</groupId> + <artifactId>bcprov-jdk15on</artifactId> + </dependency> + + <dependency> + <groupId>javax.servlet</groupId> + <artifactId>javax.servlet-api</artifactId> + <scope>provided</scope> + </dependency> + + <!-- Testing --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-test</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>at.gv.egiz.eaaf</groupId> + <artifactId>eaaf_core_utils</artifactId> + <scope>test</scope> + <type>test-jar</type> + </dependency> + <dependency> + <groupId>at.gv.egiz.eaaf</groupId> + <artifactId>eaaf-core</artifactId> + <scope>test</scope> + <type>test-jar</type> + </dependency> + <dependency> + <groupId>com.squareup.okhttp3</groupId> + <artifactId>mockwebserver</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>xml-apis</groupId> + <artifactId>xml-apis</artifactId> + <version>1.4.01</version> + <scope>test</scope> + </dependency> + </dependencies> - + <build> <finalName>eaaf_module_pvp2_core</finalName> - + <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> @@ -90,25 +102,44 @@ <source>1.8</source> <target>1.8</target> </configuration> + <executions> + <execution> + <goals> + <goal>compile</goal> + <goal>testCompile</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jar-plugin</artifactId> + <version>3.1.0</version> + <executions> + <execution> + <goals> + <goal>test-jar</goal> + </goals> + </execution> + </executions> </plugin> - + <!-- enable co-existence of testng and junit --> - <plugin> - <artifactId>maven-surefire-plugin</artifactId> - <version>${surefire.version}</version> - <configuration> - <threadCount>1</threadCount> - <argLine>--add-modules java.xml.bind</argLine> - </configuration> - <dependencies> - <dependency> - <groupId>org.apache.maven.surefire</groupId> - <artifactId>surefire-junit47</artifactId> - <version>${surefire.version}</version> - </dependency> - </dependencies> - </plugin> - + <plugin> + <artifactId>maven-surefire-plugin</artifactId> + <version>${surefire.version}</version> + <configuration> + <threadCount>1</threadCount> + </configuration> + <dependencies> + <dependency> + <groupId>org.apache.maven.surefire</groupId> + <artifactId>surefire-junit47</artifactId> + <version>${surefire.version}</version> + </dependency> + </dependencies> + </plugin> + </plugins> </build> </project> diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/PVP2SProfileCoreSpringResourceProvider.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/PVP2SProfileCoreSpringResourceProvider.java deleted file mode 100644 index c72db697..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/PVP2SProfileCoreSpringResourceProvider.java +++ /dev/null @@ -1,54 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2; - -import org.springframework.core.io.ClassPathResource; -import org.springframework.core.io.Resource; - -import at.gv.egiz.components.spring.api.SpringResourceProvider; - -public class PVP2SProfileCoreSpringResourceProvider implements SpringResourceProvider { - - @Override - public String getName() { - return "EAAF PVP2 S-Profile Core SpringResourceProvider"; - } - - @Override - public String[] getPackagesToScan() { - // TODO Auto-generated method stub - return null; - } - - @Override - public Resource[] getResourcesToLoad() { - ClassPathResource sl20AuthConfig = new ClassPathResource("/eaaf_pvp.beans.xml", PVP2SProfileCoreSpringResourceProvider.class); - - return new Resource[] {sl20AuthConfig}; - } - -} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/PVPConstants.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/PVPConstants.java deleted file mode 100644 index 3b57a7e3..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/PVPConstants.java +++ /dev/null @@ -1,139 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import javax.xml.namespace.QName; - -import org.opensaml.xml.encryption.EncryptionConstants; -import org.opensaml.xml.signature.SignatureConstants; - -import at.gv.egiz.eaaf.core.api.data.PVPAttributeDefinitions; -import at.gv.egiz.eaaf.core.impl.data.Trible; - -public interface PVPConstants extends PVPAttributeDefinitions { - - public static final String DEFAULT_SIGNING_METHODE = SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256; - public static final String DEFAULT_DIGESTMETHODE = SignatureConstants.ALGO_ID_DIGEST_SHA256; - public static final String DEFAULT_SYM_ENCRYPTION_METHODE = EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES256; - public static final String DEFAULT_ASYM_ENCRYPTION_METHODE = EncryptionConstants.ALGO_ID_KEYTRANSPORT_RSAOAEP; - - public static final String ENTITY_CATEGORY_ATTRIBITE = "http://macedir.org/entity-category"; - public static final String EGOVTOKEN = "http://www.ref.gv.at/ns/names/agiz/pvp/egovtoken"; - public static final String CITIZENTOKEN = "http://www.ref.gv.at/ns/names/agiz/pvp/citizentoken"; - - @Deprecated - public static final String STORK_ATTRIBUTE_PREFIX = "http://www.stork.gov.eu/"; - - public static final String REDIRECT = "Redirect"; - public static final String POST = "Post"; - public static final String SOAP = "Soap"; - public static final String METADATA = "Metadata"; - public static final String ATTRIBUTEQUERY = "AttributeQuery"; - public static final String SINGLELOGOUT = "SingleLogOut"; - - /** - * - * Get required PVP attributes for egovtoken - * First : PVP attribute name (OID) - * Second: FriendlyName - * Third: Required - * - */ - public static final List<Trible<String, String, Boolean>> EGOVTOKEN_PVP_ATTRIBUTES = - Collections.unmodifiableList(new ArrayList<Trible<String, String, Boolean>>() { - private static final long serialVersionUID = 1L; - { - //currently supported attributes - add(Trible.newInstance(PVP_VERSION_NAME, PVP_VERSION_FRIENDLY_NAME, true)); - add(Trible.newInstance(PRINCIPAL_NAME_NAME, PRINCIPAL_NAME_FRIENDLY_NAME, true)); - - //currently not supported attributes - add(Trible.newInstance(USERID_NAME, USERID_FRIENDLY_NAME, false)); - add(Trible.newInstance(GID_NAME, GID_FRIENDLY_NAME, false)); - add(Trible.newInstance(PARTICIPANT_ID_NAME, PARTICIPANT_ID_FRIENDLY_NAME, false)); - add(Trible.newInstance(OU_GV_OU_ID_NAME, OU_GV_OU_ID_FRIENDLY_NAME, false)); - add(Trible.newInstance(OU_NAME, OU_FRIENDLY_NAME, false)); - add(Trible.newInstance(SECCLASS_NAME, SECCLASS_FRIENDLY_NAME, false)); - - - } - }); - - /** - * - * Get required PVP attributes for citizenToken - * First : PVP attribute name (OID) - * Second: FriendlyName - * Third: Required - * - */ - public static final List<Trible<String, String, Boolean>> CITIZENTOKEN_PVP_ATTRIBUTES = - Collections.unmodifiableList(new ArrayList<Trible<String, String, Boolean>>() { - private static final long serialVersionUID = 1L; - { - //required attributes - eIDAS minimal-data set - add(Trible.newInstance(PVP_VERSION_NAME, PVP_VERSION_FRIENDLY_NAME, true)); - add(Trible.newInstance(PRINCIPAL_NAME_NAME, PRINCIPAL_NAME_FRIENDLY_NAME, true)); - add(Trible.newInstance(GIVEN_NAME_NAME, GIVEN_NAME_FRIENDLY_NAME, true)); - add(Trible.newInstance(BIRTHDATE_NAME, BIRTHDATE_FRIENDLY_NAME, true)); - add(Trible.newInstance(BPK_NAME, BPK_FRIENDLY_NAME, true)); - - - //not required attributes - add(Trible.newInstance(EID_CITIZEN_EIDAS_QAA_LEVEL_NAME, EID_CITIZEN_EIDAS_QAA_LEVEL_FRIENDLY_NAME, false)); - add(Trible.newInstance(EID_ISSUING_NATION_NAME, EID_ISSUING_NATION_FRIENDLY_NAME, false)); - add(Trible.newInstance(EID_SECTOR_FOR_IDENTIFIER_NAME, EID_SECTOR_FOR_IDENTIFIER_FRIENDLY_NAME, false)); - add(Trible.newInstance(MANDATE_TYPE_NAME, MANDATE_TYPE_FRIENDLY_NAME, false)); - add(Trible.newInstance(MANDATE_TYPE_OID_NAME, MANDATE_TYPE_OID_FRIENDLY_NAME, false)); - add(Trible.newInstance(MANDATE_LEG_PER_SOURCE_PIN_NAME, MANDATE_LEG_PER_SOURCE_PIN_FRIENDLY_NAME, false)); - add(Trible.newInstance(MANDATE_LEG_PER_SOURCE_PIN_TYPE_NAME, MANDATE_LEG_PER_SOURCE_PIN_TYPE_FRIENDLY_NAME, false)); - add(Trible.newInstance(MANDATE_NAT_PER_BPK_NAME, MANDATE_NAT_PER_BPK_FRIENDLY_NAME, false)); - add(Trible.newInstance(MANDATE_NAT_PER_GIVEN_NAME_NAME, MANDATE_NAT_PER_GIVEN_NAME_FRIENDLY_NAME, false)); - add(Trible.newInstance(MANDATE_NAT_PER_FAMILY_NAME_NAME, MANDATE_NAT_PER_FAMILY_NAME_FRIENDLY_NAME, false)); - add(Trible.newInstance(MANDATE_NAT_PER_BIRTHDATE_NAME, MANDATE_NAT_PER_BIRTHDATE_FRIENDLY_NAME, false)); - add(Trible.newInstance(MANDATE_LEG_PER_FULL_NAME_NAME, MANDATE_LEG_PER_FULL_NAME_FRIENDLY_NAME, false)); - add(Trible.newInstance(MANDATE_PROF_REP_OID_NAME, MANDATE_PROF_REP_OID_FRIENDLY_NAME, false)); - add(Trible.newInstance(MANDATE_PROF_REP_DESC_NAME, MANDATE_PROF_REP_DESC_FRIENDLY_NAME, false)); - add(Trible.newInstance(MANDATE_REFERENCE_VALUE_NAME, MANDATE_REFERENCE_VALUE_FRIENDLY_NAME, false)); - - - - } - }); - - //constants for requested SAML2 attribtes by using own namespace - public static final String EIDAT10_SAML_NS = "http://eid.gv.at/eID/attributes/saml-extensions"; - public static final String EIDAT10_PREFIX = "eid"; - - public static final QName EIDAS_REQUESTED_ATTRIBUTE_VALUE_TYPE = - new QName(EIDAT10_SAML_NS, "AttributeValue", EIDAT10_PREFIX); - -} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/PVPEventConstants.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/PVPEventConstants.java deleted file mode 100644 index d1f619bf..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/PVPEventConstants.java +++ /dev/null @@ -1,36 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2; - -public class PVPEventConstants { - - //TODO!!! - public static final int AUTHPROTOCOL_PVP_METADATA = 3100; - public static final int AUTHPROTOCOL_PVP_REQUEST_AUTHREQUEST = 3101; - public static final int AUTHPROTOCOL_PVP_RESPONSE_ASSERTION = 3105; - -} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/Pvp2SProfileCoreSpringResourceProvider.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/Pvp2SProfileCoreSpringResourceProvider.java new file mode 100644 index 00000000..232e4ae9 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/Pvp2SProfileCoreSpringResourceProvider.java @@ -0,0 +1,48 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2; + +import at.gv.egiz.components.spring.api.SpringResourceProvider; + +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; + +public class Pvp2SProfileCoreSpringResourceProvider implements SpringResourceProvider { + + @Override + public String getName() { + return "EAAF PVP2 S-Profile Core SpringResourceProvider"; + } + + @Override + public String[] getPackagesToScan() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Resource[] getResourcesToLoad() { + final ClassPathResource sl20AuthConfig = + new ClassPathResource("/eaaf_pvp.beans.xml", Pvp2SProfileCoreSpringResourceProvider.class); + + return new Resource[] { sl20AuthConfig }; + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/PvpConstants.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/PvpConstants.java new file mode 100644 index 00000000..69b94255 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/PvpConstants.java @@ -0,0 +1,178 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import javax.xml.namespace.QName; + +import at.gv.egiz.eaaf.core.api.data.PvpAttributeDefinitions; +import at.gv.egiz.eaaf.core.impl.data.Triple; + +import org.apache.xml.security.algorithms.MessageDigestAlgorithm; +import org.apache.xml.security.signature.XMLSignature; +import org.opensaml.xmlsec.encryption.support.EncryptionConstants; +import org.opensaml.xmlsec.signature.support.SignatureConstants; + +import com.google.common.collect.ImmutableMap; + +public interface PvpConstants extends PvpAttributeDefinitions { + // module configuration parameters + String CONFIG_PROP_SEC_SIGNING_RSA_ALG = "pvp2.security.alg.signing.rsa"; + String CONFIG_PROP_SEC_SIGNING_EC_ALG = "pvp2.security.alg.signing.ec"; + String CONFIG_PROP_SEC_ENCRYPTION_DATA = "pvp2.security.alg.enc.data"; + String CONFIG_PROP_SEC_ENCRYPTION_KEY_RSA_ALG = "pvp2.security.alg.enc.key.rsa"; + String CONFIG_PROP_SEC_ENCRYPTION_KEY_EC_ALG = "pvp2.security.alg.enc.key.ec"; + String CONFIG_PROPERTY_PVP2_ENABLE_ENCRYPTION = "pvp2.assertion.encryption.active"; + + // Default values + String DEFAULT_SIGNING_METHODE_RSA = + SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256; + String DEFAULT_SIGNING_METHODE_EC = + SignatureConstants.ALGO_ID_SIGNATURE_ECDSA_SHA256; + + String DEFAULT_DIGESTMETHODE = SignatureConstants.ALGO_ID_DIGEST_SHA256; + + String DEFAULT_SYM_ENCRYPTION_METHODE = + EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES128_GCM; + String DEFAULT_ASYM_ENCRYPTION_METHODE_RSA = + EncryptionConstants.ALGO_ID_KEYTRANSPORT_RSAOAEP; + String DEFAULT_ASYM_ENCRYPTION_METHODE_EC = + EncryptionConstants.ALGO_ID_KEYAGREEMENT_DH; + + // PVP entity categories + String ENTITY_CATEGORY_ATTRIBITE = "http://macedir.org/entity-category"; + String EGOVTOKEN = "http://www.ref.gv.at/ns/names/agiz/pvp/egovtoken"; + String CITIZENTOKEN = "http://www.ref.gv.at/ns/names/agiz/pvp/citizentoken"; + + @Deprecated + String STORK_ATTRIBUTE_PREFIX = "http://www.stork.gov.eu/"; + + String REDIRECT = "Redirect"; + String POST = "Post"; + String SOAP = "Soap"; + String METADATA = "Metadata"; + String ATTRIBUTEQUERY = "AttributeQuery"; + String SINGLELOGOUT = "SingleLogOut"; + + /** + * Get required PVP attributes for egovtoken First : PVP attribute name (OID) + * Second: FriendlyName Third: Required. + * + */ + List<Triple<String, String, Boolean>> EGOVTOKEN_PVP_ATTRIBUTES = + Collections.unmodifiableList(new ArrayList<Triple<String, String, Boolean>>() { + private static final long serialVersionUID = 1L; + + { + // currently supported attributes + add(Triple.newInstance(PVP_VERSION_NAME, PVP_VERSION_FRIENDLY_NAME, true)); + add(Triple.newInstance(PRINCIPAL_NAME_NAME, PRINCIPAL_NAME_FRIENDLY_NAME, true)); + + // currently not supported attributes + add(Triple.newInstance(USERID_NAME, USERID_FRIENDLY_NAME, false)); + add(Triple.newInstance(GID_NAME, GID_FRIENDLY_NAME, false)); + add(Triple.newInstance(PARTICIPANT_ID_NAME, PARTICIPANT_ID_FRIENDLY_NAME, false)); + add(Triple.newInstance(OU_GV_OU_ID_NAME, OU_GV_OU_ID_FRIENDLY_NAME, false)); + add(Triple.newInstance(OU_NAME, OU_FRIENDLY_NAME, false)); + add(Triple.newInstance(SECCLASS_NAME, SECCLASS_FRIENDLY_NAME, false)); + + } + }); + + /** + * Get required PVP attributes for citizenToken First : PVP attribute name (OID) + * Second: FriendlyName Third: Required. + * + */ + List<Triple<String, String, Boolean>> CITIZENTOKEN_PVP_ATTRIBUTES = + Collections.unmodifiableList(new ArrayList<Triple<String, String, Boolean>>() { + private static final long serialVersionUID = -5947165770657082581L; + + { + // required attributes - eIDAS minimal-data set + add(Triple.newInstance(PVP_VERSION_NAME, PVP_VERSION_FRIENDLY_NAME, true)); + add(Triple.newInstance(PRINCIPAL_NAME_NAME, PRINCIPAL_NAME_FRIENDLY_NAME, true)); + add(Triple.newInstance(GIVEN_NAME_NAME, GIVEN_NAME_FRIENDLY_NAME, true)); + add(Triple.newInstance(BIRTHDATE_NAME, BIRTHDATE_FRIENDLY_NAME, true)); + add(Triple.newInstance(BPK_NAME, BPK_FRIENDLY_NAME, true)); + + // not required attributes + add(Triple.newInstance(EID_CITIZEN_EIDAS_QAA_LEVEL_NAME, + EID_CITIZEN_EIDAS_QAA_LEVEL_FRIENDLY_NAME, false)); + add(Triple.newInstance(EID_ISSUING_NATION_NAME, EID_ISSUING_NATION_FRIENDLY_NAME, false)); + add(Triple.newInstance(EID_SECTOR_FOR_IDENTIFIER_NAME, + EID_SECTOR_FOR_IDENTIFIER_FRIENDLY_NAME, false)); + add(Triple.newInstance(MANDATE_TYPE_NAME, MANDATE_TYPE_FRIENDLY_NAME, false)); + add(Triple.newInstance(MANDATE_TYPE_OID_NAME, MANDATE_TYPE_OID_FRIENDLY_NAME, false)); + add(Triple.newInstance(MANDATE_LEG_PER_SOURCE_PIN_NAME, + MANDATE_LEG_PER_SOURCE_PIN_FRIENDLY_NAME, false)); + add(Triple.newInstance(MANDATE_LEG_PER_SOURCE_PIN_TYPE_NAME, + MANDATE_LEG_PER_SOURCE_PIN_TYPE_FRIENDLY_NAME, false)); + add(Triple.newInstance(MANDATE_NAT_PER_BPK_NAME, MANDATE_NAT_PER_BPK_FRIENDLY_NAME, + false)); + add(Triple.newInstance(MANDATE_NAT_PER_GIVEN_NAME_NAME, + MANDATE_NAT_PER_GIVEN_NAME_FRIENDLY_NAME, false)); + add(Triple.newInstance(MANDATE_NAT_PER_FAMILY_NAME_NAME, + MANDATE_NAT_PER_FAMILY_NAME_FRIENDLY_NAME, false)); + add(Triple.newInstance(MANDATE_NAT_PER_BIRTHDATE_NAME, + MANDATE_NAT_PER_BIRTHDATE_FRIENDLY_NAME, false)); + add(Triple.newInstance(MANDATE_LEG_PER_FULL_NAME_NAME, + MANDATE_LEG_PER_FULL_NAME_FRIENDLY_NAME, false)); + add(Triple.newInstance(MANDATE_PROF_REP_OID_NAME, MANDATE_PROF_REP_OID_FRIENDLY_NAME, + false)); + add(Triple.newInstance(MANDATE_PROF_REP_DESC_NAME, MANDATE_PROF_REP_DESC_FRIENDLY_NAME, + false)); + add(Triple.newInstance(MANDATE_REFERENCE_VALUE_NAME, + MANDATE_REFERENCE_VALUE_FRIENDLY_NAME, false)); + + } + }); + + // constants for requested SAML2 attribtes by using own namespace + String EIDAT10_SAML_NS = "http://eid.gv.at/eID/attributes/saml-extensions"; + String EIDAT10_PREFIX = "eid"; + + QName EIDAS_REQUESTED_ATTRIBUTE_VALUE_TYPE = + new QName(EIDAT10_SAML_NS, "AttributeValue", EIDAT10_PREFIX); + + ImmutableMap<String, String> SIGNATURE_TO_DIGEST_ALGORITHM_MAP = + ImmutableMap.<String, String>builder() + .put(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256, SignatureConstants.ALGO_ID_DIGEST_SHA256) + .put(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA384, SignatureConstants.ALGO_ID_DIGEST_SHA384) + .put(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA512, SignatureConstants.ALGO_ID_DIGEST_SHA512) + .put(SignatureConstants.ALGO_ID_SIGNATURE_ECDSA_SHA256, SignatureConstants.ALGO_ID_DIGEST_SHA256) + .put(SignatureConstants.ALGO_ID_SIGNATURE_ECDSA_SHA384, SignatureConstants.ALGO_ID_DIGEST_SHA384) + .put(SignatureConstants.ALGO_ID_SIGNATURE_ECDSA_SHA512, SignatureConstants.ALGO_ID_DIGEST_SHA512) + .put(XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA256_MGF1, SignatureConstants.ALGO_ID_DIGEST_SHA256) + .put(XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA384_MGF1, SignatureConstants.ALGO_ID_DIGEST_SHA384) + .put(XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA512_MGF1, SignatureConstants.ALGO_ID_DIGEST_SHA512) + .put(XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA3_256_MGF1, + MessageDigestAlgorithm.ALGO_ID_DIGEST_SHA3_256) + .put(XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA3_384_MGF1, + MessageDigestAlgorithm.ALGO_ID_DIGEST_SHA3_384) + .put(XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA3_512_MGF1, + MessageDigestAlgorithm.ALGO_ID_DIGEST_SHA3_512) + + .build(); + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/PvpEventConstants.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/PvpEventConstants.java new file mode 100644 index 00000000..41b64470 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/PvpEventConstants.java @@ -0,0 +1,29 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2; + +public class PvpEventConstants { + + // TODO!!! + public static final int AUTHPROTOCOL_PVP_METADATA = 3100; + public static final int AUTHPROTOCOL_PVP_REQUEST_AUTHREQUEST = 3101; + public static final int AUTHPROTOCOL_PVP_RESPONSE_ASSERTION = 3105; + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/IPVP2BasicConfiguration.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/IPVP2BasicConfiguration.java deleted file mode 100644 index 48b0efc5..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/IPVP2BasicConfiguration.java +++ /dev/null @@ -1,50 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.api; - -import java.util.List; - -import org.opensaml.saml2.metadata.ContactPerson; -import org.opensaml.saml2.metadata.Organization; - -import at.gv.egiz.eaaf.core.exceptions.EAAFException; - -public interface IPVP2BasicConfiguration { - - public String getIDPEntityId(String authURL) throws EAAFException; - - public String getIDPSSOPostService(String authURL) throws EAAFException; - - public String getIDPSSORedirectService(String authURL) throws EAAFException; - - public Object getIDPSSOSOAPService(String extractAuthURLFromRequest) throws EAAFException; - - public List<ContactPerson> getIDPContacts() throws EAAFException; - - public Organization getIDPOrganisation() throws EAAFException; - -} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/IPvp2BasicConfiguration.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/IPvp2BasicConfiguration.java new file mode 100644 index 00000000..a54eb0b8 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/IPvp2BasicConfiguration.java @@ -0,0 +1,109 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.api; + +import java.util.List; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.core.exceptions.EaafException; + +import org.opensaml.saml.saml2.metadata.ContactPerson; +import org.opensaml.saml.saml2.metadata.Organization; + +/** + * Basic SAML2 configuration object that provide information for SAML2 metadata. + * + * @author tlenz + * + */ +public interface IPvp2BasicConfiguration { + + /** + * SAML2 EntityId. + * + * @param authUrl The Public-URL prefix of the application that always ends without / + * @return EntityId + * @throws EaafException In case of an error. + */ + @Nonnull + String getIdpEntityId(@Nonnull String authUrl) throws EaafException; + + /** + * Authentication end-point for POST-Binding in case of an IDP. + * + * @param authUrl The Public-URL prefix of the application that always ends without / + * @return IDP SSO endpoint + * @throws EaafException In case of an error. + */ + @Nullable + String getIdpSsoPostService(@Nonnull String authUrl) throws EaafException; + + /** + * Authentication end-point for POST-Redirect in case of an IDP. + * + * @param authUrl The Public-URL prefix of the application that always ends without / + * @return IDP SSO endpoint + * @throws EaafException In case of an error. + */ + @Nullable + String getIdpSsoRedirectService(@Nonnull String authUrl) throws EaafException; + + /** + * Authentication end-point for POST-SOAP in case of an IDP. + * + * @param authUrl The Public-URL prefix of the application that always ends without / + * @return IDP SSO endpoint + * @throws EaafException In case of an error. + */ + @Nullable + String getIdpSsoSoapService(@Nonnull String authUrl) throws EaafException; + + /** + * Contact information for SAML2 Metadata. + * + * @return SAML2 Contact object + * @throws EaafException In case of an error. + */ + @Nonnull + List<ContactPerson> getIdpContacts() throws EaafException; + + /** + * Organization information for SAML2 Metadata. + * + * @return SAML2 Organization object + * @throws EaafException In case of an error. + */ + @Nonnull + Organization getIdpOrganisation() throws EaafException; + + /** + * Get the basic {@link IConfiguration} object that was + * used to generate this {@link IPvp2BasicConfiguration}. + * + * @return Basic application configuration + */ + @Nonnull + IConfiguration getBasicConfiguration(); + + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/binding/IDecoder.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/binding/IDecoder.java index 3b264b6d..83bfee84 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/binding/IDecoder.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/binding/IDecoder.java @@ -1,49 +1,40 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 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: + * Licensed under the EUPL, Version 1.2 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: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * 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. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * 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.egiz.eaaf.modules.pvp2.api.binding; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; - -import org.opensaml.common.binding.decoding.URIComparator; -import org.opensaml.saml2.metadata.provider.MetadataProvider; -import org.opensaml.ws.message.decoder.MessageDecodingException; -import org.opensaml.xml.security.SecurityException; +import javax.xml.namespace.QName; import at.gv.egiz.eaaf.modules.pvp2.api.message.InboundMessageInterface; -import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; +import net.shibboleth.utilities.java.support.net.URIComparator; public interface IDecoder { - public InboundMessageInterface decode(HttpServletRequest req, - HttpServletResponse resp, MetadataProvider metadataProvider, boolean isSPEndPoint, URIComparator comparator) - throws MessageDecodingException, SecurityException, PVP2Exception; - - public boolean handleDecode(String action, HttpServletRequest req); - - public String getSAML2BindingName(); + InboundMessageInterface decode(HttpServletRequest req, HttpServletResponse resp, + IPvp2MetadataProvider metadataProvider, QName peerEntityRole, URIComparator comparator) + throws Pvp2Exception; + + boolean handleDecode(String action, HttpServletRequest req); + + String getSaml2BindingName(); } diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/binding/IEncoder.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/binding/IEncoder.java index ec400e7a..5a8bc4fb 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/binding/IEncoder.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/binding/IEncoder.java @@ -1,75 +1,68 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 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: + * Licensed under the EUPL, Version 1.2 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: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * 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. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * 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.egiz.eaaf.modules.pvp2.api.binding; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.opensaml.saml2.core.RequestAbstractType; -import org.opensaml.saml2.core.StatusResponseType; -import org.opensaml.ws.message.encoder.MessageEncodingException; -import org.opensaml.xml.security.SecurityException; -import org.opensaml.xml.security.credential.Credential; - import at.gv.egiz.eaaf.core.api.IRequest; -import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception; +import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; + +import org.opensaml.saml.saml2.core.RequestAbstractType; +import org.opensaml.saml.saml2.core.StatusResponseType; +import org.opensaml.security.SecurityException; public interface IEncoder { - - /** - * - * @param req The http request - * @param resp The http response - * @param request The SAML2 request object - * @param targetLocation URL, where the request should be transmit - * @param relayState token for session handling - * @param credentials Credential to sign the request object - * @param pendingReq Internal MOA-ID request object that contains session-state informations but never null - * @throws MessageEncodingException - * @throws SecurityException - * @throws PVP2Exception - */ - public void encodeRequest(HttpServletRequest req, - HttpServletResponse resp, RequestAbstractType request, String targetLocation, String relayState, Credential credentials, IRequest pendingReq) - throws MessageEncodingException, SecurityException, PVP2Exception; - - /** - * Encoder SAML Response - * @param req The http request - * @param resp The http response - * @param response The SAML2 repsonse object - * @param targetLocation URL, where the request should be transmit - * @param relayState token for session handling - * @param credentials Credential to sign the response object - * @param pendingReq Internal MOA-ID request object that contains session-state informations but never null - * @throws MessageEncodingException - * @throws SecurityException - */ - public void encodeRespone(HttpServletRequest req, - HttpServletResponse resp, StatusResponseType response, String targetLocation, String relayState, Credential credentials, IRequest pendingReq) - throws MessageEncodingException, SecurityException, PVP2Exception; + + /** + * SAML2 Request encoder. + * + * @param req The http request + * @param resp The http response + * @param request The SAML2 request object + * @param targetLocation URL, where the request should be transmit + * @param relayState token for session handling + * @param credentials Credential to sign the request object + * @param pendingReq Internal MOA-ID request object that contains + * session-state informations but never null + * @throws Pvp2Exception In case of an error + */ + void encodeRequest(HttpServletRequest req, HttpServletResponse resp, + RequestAbstractType request, String targetLocation, String relayState, EaafX509Credential credentials, + IRequest pendingReq) throws Pvp2Exception; + + /** + * Encoder SAML Response. + * + * @param req The http request + * @param resp The http response + * @param response The SAML2 repsonse object + * @param targetLocation URL, where the request should be transmit + * @param relayState token for session handling + * @param credentials Credential to sign the response object + * @param pendingReq Internal MOA-ID request object that contains + * session-state informations but never null + * @throws SecurityException In case of an error + */ + void encodeResponse(HttpServletRequest req, HttpServletResponse resp, + StatusResponseType response, String targetLocation, String relayState, EaafX509Credential credentials, + IRequest pendingReq) throws Pvp2Exception; } diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/credential/EaafX509Credential.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/credential/EaafX509Credential.java new file mode 100644 index 00000000..95070167 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/credential/EaafX509Credential.java @@ -0,0 +1,42 @@ +package at.gv.egiz.eaaf.modules.pvp2.api.credential; + +import javax.annotation.Nonnull; + +import org.opensaml.security.x509.X509Credential; + +public interface EaafX509Credential extends X509Credential { + + /** + * Get the signature algorithm that has to be used with this credential. + * + * @return Signature-algorithm identifier + */ + @Nonnull + String getSignatureAlgorithmForSigning(); + + /** + * Set the signature algorithm that has to be used with this credential. + * + * @param sigAlg Signature-algorithm identifier + */ + void setSignatureAlgorithmForSigning(@Nonnull String sigAlg); + + + /** + * Get the key-encryption algorithm that has to be used with this credential + * in case of data-encryption operations. + * + * @return Key-encryption algorithm-identifier + */ + @Nonnull + String getKeyEncryptionAlgorithmForDataEncryption(); + + /** + * Set the key-encryption algorithm that has to be used with this credential + * in case of data-encryption operations. + * + * @param sigAlg Key-encryption algorithm-identifier + */ + void setKeyEncryptionAlgorithmForDataEncryption(@Nonnull String sigAlg); + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/message/InboundMessageInterface.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/message/InboundMessageInterface.java index 416672a1..e5b253a2 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/message/InboundMessageInterface.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/message/InboundMessageInterface.java @@ -1,42 +1,34 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 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: + * Licensed under the EUPL, Version 1.2 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: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * 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. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * 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.egiz.eaaf.modules.pvp2.api.message; import org.w3c.dom.Element; -/** - * @author tlenz - * - */ public interface InboundMessageInterface { - - public String getRelayState(); - public String getEntityID(); - public boolean isVerified(); - public Element getInboundMessage(); - + + String getRelayState(); + + String getEntityID(); + + boolean isVerified(); + + Element getInboundMessage(); + } diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPVPMetadataBuilderConfiguration.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPVPMetadataBuilderConfiguration.java deleted file mode 100644 index c041ec72..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPVPMetadataBuilderConfiguration.java +++ /dev/null @@ -1,243 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.api.metadata; - -import java.util.Collection; -import java.util.List; - -import org.opensaml.saml2.core.Attribute; -import org.opensaml.saml2.metadata.ContactPerson; -import org.opensaml.saml2.metadata.Organization; -import org.opensaml.saml2.metadata.RequestedAttribute; -import org.opensaml.xml.security.credential.Credential; - -import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException; - -/** - * @author tlenz - * - */ -public interface IPVPMetadataBuilderConfiguration { - - - /** - * Defines a unique name for this PVP Service-provider, which is used for logging - * - * @return - */ - public String getSPNameForLogging(); - - /** - * Set metadata valid area - * - * @return valid until in hours [h] - */ - public int getMetadataValidUntil(); - - /** - * Build a SAML2 Entities element as metadata root element - * - * @return true, if the metadata should start with entities element - */ - public boolean buildEntitiesDescriptorAsRootElement(); - - /** - * - * - * @return true, if an IDP SSO-descriptor element should be generated - */ - public boolean buildIDPSSODescriptor(); - - /** - * - * - * @return true, if an SP SSO-descriptor element should be generated - */ - public boolean buildSPSSODescriptor(); - - /** - * Set the PVP entityID for this SAML2 metadata. - * The entityID must be an URL and must be start with the public-URL prefix of the server - * - * @return PVP entityID postfix as String - */ - public String getEntityID(); - - /** - * Set a friendlyName for this PVP entity - * - * @return - */ - public String getEntityFriendlyName(); - - /** - * Set the contact information for this metadata entity - * - * @return - */ - public List<ContactPerson> getContactPersonInformation(); - - /** - * Set organisation information for this metadata entity - * - * @return - */ - public Organization getOrgansiationInformation(); - - - /** - * Set the credential for metadata signing - * - * @return - * @throws CredentialsNotAvailableException - */ - public Credential getMetadataSigningCredentials() throws CredentialsNotAvailableException; - - /** - * Set the credential for request/response signing - * IDP metadata: this credential is used for SAML2 response signing - * SP metadata: this credential is used for SAML2 response signing - * - * @return - * @throws CredentialsNotAvailableException - */ - public Credential getRequestorResponseSigningCredentials() throws CredentialsNotAvailableException; - - /** - * Set the credential for response encryption - * - * @return - * @throws CredentialsNotAvailableException - */ - public Credential getEncryptionCredentials() throws CredentialsNotAvailableException; - - /** - * Set the IDP Post-Binding URL for WebSSO - * - * @return - */ - public String getIDPWebSSOPostBindingURL(); - - /** - * Set the IDP Redirect-Binding URL for WebSSO - * - * @return - */ - public String getIDPWebSSORedirectBindingURL(); - - /** - * Set the IDP Post-Binding URL for Single LogOut - * - * @return - */ - public String getIDPSLOPostBindingURL(); - - /** - * Set the IDP Redirect-Binding URL for Single LogOut - * - * @return - */ - public String getIDPSLORedirectBindingURL(); - - /** - * Set the SP Post-Binding URL for for the Assertion-Consumer Service - * - * @return - */ - public String getSPAssertionConsumerServicePostBindingURL(); - - /** - * Set the SP Redirect-Binding URL for the Assertion-Consumer Service - * - * @return - */ - public String getSPAssertionConsumerServiceRedirectBindingURL(); - - /** - * Set the SP Post-Binding URL for Single LogOut - * - * @return - */ - public String getSPSLOPostBindingURL(); - - /** - * Set the SP Redirect-Binding URL for Single LogOut - * - * @return - */ - public String getSPSLORedirectBindingURL(); - - /** - * Set the SP SOAP-Binding URL for Single LogOut - * - * @return - */ - public String getSPSLOSOAPBindingURL(); - - - /** - * Set all SAML2 attributes which could be provided by this IDP - * - * @return - */ - public List<Attribute> getIDPPossibleAttributes(); - - /** - * Set all nameID types which could be provided by this IDP - * - * @return a List of SAML2 nameID types - */ - public List<String> getIDPPossibleNameITTypes(); - - /** - * Set all SAML2 attributes which are required by the SP - * - * @return - */ - public Collection<RequestedAttribute> getSPRequiredAttributes(); - - /** - * Set all nameID types which allowed from the SP - * - * @return a List of SAML2 nameID types - */ - public List<String> getSPAllowedNameITTypes(); - - /** - * Set the 'wantAssertionSigned' attribute in SP metadata - * - * @return - */ - public boolean wantAssertionSigned(); - - /** - * Set the 'wantAuthnRequestSigned' attribute - * - * @return - */ - public boolean wantAuthnRequestSigned(); -} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPVPMetadataConfigurationFactory.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPVPMetadataConfigurationFactory.java deleted file mode 100644 index be36a878..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPVPMetadataConfigurationFactory.java +++ /dev/null @@ -1,35 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.api.metadata; - -import at.gv.egiz.eaaf.modules.pvp2.impl.utils.AbstractCredentialProvider; - -public interface IPVPMetadataConfigurationFactory { - - public IPVPMetadataBuilderConfiguration generateMetadataBuilderConfiguration(String authURL, AbstractCredentialProvider pvpIDPCredentials); - -} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPVPMetadataProvider.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPVPMetadataProvider.java deleted file mode 100644 index f5c6a35a..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPVPMetadataProvider.java +++ /dev/null @@ -1,61 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.api.metadata; - -import java.util.List; - -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.MetadataFilter; -import org.opensaml.saml2.metadata.provider.MetadataProvider; -import org.opensaml.saml2.metadata.provider.MetadataProviderException; -import org.opensaml.xml.XMLObject; - -public interface IPVPMetadataProvider extends MetadataProvider { - - boolean requireValidMetadata(); - - void setRequireValidMetadata(boolean requireValidMetadata); - - MetadataFilter getMetadataFilter(); - - void setMetadataFilter(MetadataFilter newFilter) throws MetadataProviderException; - - XMLObject getMetadata() throws MetadataProviderException; - - EntitiesDescriptor getEntitiesDescriptor(String entitiesID) throws MetadataProviderException; - - EntityDescriptor getEntityDescriptor(String entityID) throws MetadataProviderException; - - List<RoleDescriptor> getRole(String entityID, QName roleName) throws MetadataProviderException; - - RoleDescriptor getRole(String entityID, QName roleName, String supportedProtocol) throws MetadataProviderException; - -}
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvp2MetadataProvider.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvp2MetadataProvider.java new file mode 100644 index 00000000..2f058af8 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvp2MetadataProvider.java @@ -0,0 +1,42 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.api.metadata; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import org.opensaml.saml.metadata.resolver.ExtendedRefreshableMetadataResolver; +import org.opensaml.saml.saml2.metadata.EntityDescriptor; + +import net.shibboleth.utilities.java.support.resolver.ResolverException; + +public interface IPvp2MetadataProvider extends ExtendedRefreshableMetadataResolver { + + /** + * Get a SAML2 EntityDescriptor with an EntityId from metadata provider. + * + * @param entityID Unique EntityId of the application + * @return SAML2 {@link EntityDescriptor} + * @throws ResolverException In case of an internal resolver error. + */ + @Nullable + EntityDescriptor getEntityDescriptor(@Nonnull String entityID) throws ResolverException; + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvpAddableChainingMetadataProvider.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvpAddableChainingMetadataProvider.java new file mode 100644 index 00000000..8e5eb715 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvpAddableChainingMetadataProvider.java @@ -0,0 +1,22 @@ +package at.gv.egiz.eaaf.modules.pvp2.api.metadata; + +import javax.annotation.Nonnull; + +import at.gv.egiz.eaaf.core.api.IGarbageCollectorProcessing; + +import org.opensaml.saml.metadata.resolver.MetadataResolver; + +public interface IPvpAddableChainingMetadataProvider { + + /** + * Manually add a metadata resolver into a chaining metadata provider. + * <br> + * <b>If the chaining metadata provider also implements + * {@link IGarbageCollectorProcessing} manually added provider + * can be removed by garbage-collector process. This behavior + * depends on chaining metadata-provider implementation. </b> + * + * @param resolver Metadata provider that should be added + */ + void addMetadataResolverIntoChain(@Nonnull MetadataResolver resolver); +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvpMetadataBuilderConfiguration.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvpMetadataBuilderConfiguration.java new file mode 100644 index 00000000..3d9125fe --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvpMetadataBuilderConfiguration.java @@ -0,0 +1,238 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.api.metadata; + +import java.util.Collection; +import java.util.List; + +import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential; +import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException; + +import org.opensaml.saml.saml2.core.Attribute; +import org.opensaml.saml.saml2.metadata.ContactPerson; +import org.opensaml.saml.saml2.metadata.Organization; +import org.opensaml.saml.saml2.metadata.RequestedAttribute; +import org.opensaml.security.credential.Credential; + +/** + * PVP Metadata builder configuration. + * + * @author tlenz + * + */ +public interface IPvpMetadataBuilderConfiguration { + + /** + * Defines a unique name for this PVP Service-provider, which is used for + * logging. + * + * @return + */ + String getSpNameForLogging(); + + /** + * Set metadata valid area. + * + * @return valid until in hours [h] + */ + int getMetadataValidUntil(); + + /** + * Build a SAML2 Entities element as metadata root element. + * + * @return true, if the metadata should start with entities element + */ + boolean buildEntitiesDescriptorAsRootElement(); + + /** + * Build an IDP SSO Descriptor. + * + * @return true, if an IDP SSO-descriptor element should be generated + */ + boolean buildIdpSsoDescriptor(); + + /** + * Build a SP Descriptor. + * + * @return true, if an SP SSO-descriptor element should be generated + */ + boolean buildSpSsoDescriptor(); + + /** + * Set the PVP entityID for this SAML2 metadata. The entityID must be an URL and + * must be start with the public-URL prefix of the server. + * + * @return PVP entityID postfix as String + */ + String getEntityID(); + + /** + * Set a friendlyName for this PVP entity. + * + * @return + */ + String getEntityFriendlyName(); + + /** + * Set the contact information for this metadata entity. + * + * @return + */ + List<ContactPerson> getContactPersonInformation(); + + /** + * Set organisation information for this metadata entity. + * + * @return + */ + Organization getOrgansiationInformation(); + + /** + * Set the credential for metadata signing. + * + * @return Credentials + * @throws CredentialsNotAvailableException In case of an error + */ + EaafX509Credential getMetadataSigningCredentials() throws CredentialsNotAvailableException; + + /** + * Set the credential for request/response signing IDP metadata: this credential + * is used for SAML2 response signing SP metadata: this credential is used for + * SAML2 response signing. + * + * @return Credentials + * @throws CredentialsNotAvailableException In case of an error + */ + Credential getRequestorResponseSigningCredentials() + throws CredentialsNotAvailableException; + + /** + * Set the credential for response encryption. + * + * @return Credentials + * @throws CredentialsNotAvailableException In case of an error + */ + Credential getEncryptionCredentials() throws CredentialsNotAvailableException; + + /** + * Set the IDP Post-Binding URL for WebSSO. + * + * @return + */ + String getIdpWebSsoPostBindingUrl(); + + /** + * Set the IDP Redirect-Binding URL for WebSSO. + * + * @return + */ + String getIdpWebSsoRedirectBindingUrl(); + + /** + * Set the IDP Post-Binding URL for Single LogOut. + * + * @return + */ + String getIdpSloPostBindingUrl(); + + /** + * Set the IDP Redirect-Binding URL for Single LogOut. + * + * @return + */ + String getIdpSloRedirectBindingUrl(); + + /** + * Set the SP Post-Binding URL for for the Assertion-Consumer Service. + * + * @return + */ + String getSpAssertionConsumerServicePostBindingUrl(); + + /** + * Set the SP Redirect-Binding URL for the Assertion-Consumer Service. + * + * @return + */ + String getSpAssertionConsumerServiceRedirectBindingUrl(); + + /** + * Set the SP Post-Binding URL for Single LogOut. + * + * @return + */ + String getSpSloPostBindingUrl(); + + /** + * Set the SP Redirect-Binding URL for Single LogOut. + * + * @return + */ + String getSpSloRedirectBindingUrl(); + + /** + * Set the SP SOAP-Binding URL for Single LogOut. + * + * @return + */ + String getSpSloSoapBindingUrl(); + + /** + * Set all SAML2 attributes which could be provided by this IDP. + * + * @return + */ + List<Attribute> getIdpPossibleAttributes(); + + /** + * Set all nameID types which could be provided by this IDP. + * + * @return a List of SAML2 nameID types + */ + List<String> getIdpPossibleNameIdTypes(); + + /** + * Set all SAML2 attributes which are required by the SP. + * + * @return + */ + Collection<RequestedAttribute> getSpRequiredAttributes(); + + /** + * Set all nameID types which allowed from the SP. + * + * @return a List of SAML2 nameID types + */ + List<String> getSpAllowedNameIdTypes(); + + /** + * Set the 'wantAssertionSigned' attribute in SP metadata. + * + * @return + */ + boolean wantAssertionSigned(); + + /** + * Set the 'wantAuthnRequestSigned' attribute. + * + * @return + */ + boolean wantAuthnRequestSigned(); +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvpMetadataConfigurationFactory.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvpMetadataConfigurationFactory.java new file mode 100644 index 00000000..fb1352ce --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IPvpMetadataConfigurationFactory.java @@ -0,0 +1,29 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.api.metadata; + +import at.gv.egiz.eaaf.modules.pvp2.api.utils.IPvp2CredentialProvider; + +public interface IPvpMetadataConfigurationFactory { + + IPvpMetadataBuilderConfiguration generateMetadataBuilderConfiguration(String authUrl, + IPvp2CredentialProvider pvpIdpCredentials); + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IRefreshableMetadataProvider.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IRefreshableMetadataProvider.java index 2f9e5fea..cc492345 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IRefreshableMetadataProvider.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/metadata/IRefreshableMetadataProvider.java @@ -1,42 +1,39 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 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: + * Licensed under the EUPL, Version 1.2 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: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * 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. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * 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.egiz.eaaf.modules.pvp2.api.metadata; +import org.opensaml.saml.metadata.resolver.RefreshableMetadataResolver; + /** + * Metadata provider that supports dynamic refreshing on external events. + * * @author tlenz * */ -public interface IRefreshableMetadataProvider { +public interface IRefreshableMetadataProvider extends RefreshableMetadataResolver { - /** - * Refresh a entity or load a entity in a metadata provider - * - * @param entityID - * @return true, if refresh is success, otherwise false - */ - public boolean refreshMetadataProvider(String entityID); + /** + * Refresh a entity or load a entity in a metadata provider. + * + * @param entityID EntityId + * @return true, if refresh is success, otherwise false + */ + boolean refreshMetadataProvider(String entityID); } diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/reqattr/EAAFRequestedAttribute.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/reqattr/EAAFRequestedAttribute.java deleted file mode 100644 index 0501a990..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/reqattr/EAAFRequestedAttribute.java +++ /dev/null @@ -1,154 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.api.reqattr; - -import java.util.List; - -import javax.xml.namespace.QName; - -import org.opensaml.common.SAMLObject; -import org.opensaml.xml.AttributeExtensibleXMLObject; -import org.opensaml.xml.XMLObject; -import org.opensaml.xml.schema.XSBooleanValue; - -import at.gv.egiz.eaaf.modules.pvp2.PVPConstants; - -public interface EAAFRequestedAttribute extends SAMLObject, AttributeExtensibleXMLObject , org.opensaml.saml2.metadata.RequestedAttribute{ - - /** Element local name. */ - String DEF_LOCAL_NAME = "RequestedAttribute"; - - /** Local name of the XSI type. */ - String TYPE_LOCAL_NAME = "RequestedAttributeAbstractType"; - - - /** Default element name. */ - QName DEFAULT_ELEMENT_NAME = new QName(PVPConstants.EIDAT10_SAML_NS, DEF_LOCAL_NAME, - PVPConstants.EIDAT10_PREFIX); - - /** QName of the XSI type. */ - QName TYPE_NAME = new QName(PVPConstants.EIDAT10_SAML_NS, TYPE_LOCAL_NAME, - PVPConstants.EIDAT10_PREFIX); - - - - /** NAME_ATTRIB_NAME attribute name. */ - String NAME_ATTRIB_NAME = "Name"; - - /** NAME_FORMAT_ATTRIB_NAME attribute name. */ - String NAME_FORMAT_ATTR = "NameFormat"; - - /** IS_REQUIRED_ATTRIB_NAME attribute name. */ - String IS_REQUIRED_ATTR = "isRequired"; - - /** FRIENDLY_NAME_ATTRIB_NAME attribute name. */ - String FRIENDLY_NAME_ATT = "FriendlyName"; - - /** Unspecified attribute format ID. */ - String UNSPECIFIED = "urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified"; - - /** URI reference attribute format ID. */ - String URI_REFERENCE = "urn:oasis:names:tc:SAML:2.0:attrname-format:uri"; - - /** Basic attribute format ID. */ - String BASIC = "urn:oasis:names:tc:SAML:2.0:attrname-format:basic"; - - /** - * Gets the name. - * - * @return the name - */ - String getName(); - - /** - * Sets the name. - * - * @param name the new name - */ - void setName(String name); - - /** - * Gets the name format. - * - * @return the name format - */ - String getNameFormat(); - - /** - * Sets the name format. - * - * @param nameFormat the new name format - */ - void setNameFormat(String nameFormat); - - /** - * Gets the friendly name. - * - * @return the friendly name - */ - String getFriendlyName(); - - /** - * Sets the friendly name. - * - * @param friendlyName the new friendly name - */ - void setFriendlyName(String friendlyName); - -/* *//** - * Gets the checks if is required. - * - * @return the checks if is required - *//* - String isRequired();*/ - - /** - * Gets the checks if is required xs boolean. - * - * @return the checks if is required xs boolean - */ - String getIsRequiredXSBoolean(); - - /** - * Sets the checks if is required. - * - * @param newIsRequired the new checks if is required - */ - void setIsRequired(String newIsRequired); - - /** - * Gets the attribute values. - * - * @return the attribute values - */ - List<XMLObject> getAttributeValues(); - - XSBooleanValue isRequiredXSBoolean(); - - void setIsRequired(Boolean aBoolean); - - void setIsRequired(XSBooleanValue xsBooleanValue); - -} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/reqattr/EAAFRequestedAttributes.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/reqattr/EAAFRequestedAttributes.java deleted file mode 100644 index 768d5c36..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/reqattr/EAAFRequestedAttributes.java +++ /dev/null @@ -1,56 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.api.reqattr; - -import java.util.List; - -import javax.xml.namespace.QName; - -import org.opensaml.common.SAMLObject; - -import at.gv.egiz.eaaf.modules.pvp2.PVPConstants; - -public interface EAAFRequestedAttributes extends SAMLObject { - /** The Constant DEFAULT_ELEMENT_LOCAL_NAME. */ - String DEF_LOCAL_NAME = "RequestedAttributes"; - - /** Default element name. */ - QName DEFAULT_ELEMENT_NAME = new QName(PVPConstants.EIDAT10_SAML_NS, DEF_LOCAL_NAME, - PVPConstants.EIDAT10_PREFIX); - - /** Local name of the XSI type. */ - String TYPE_LOCAL_NAME = "RequestedAttributesType"; - - /** QName of the XSI type. */ - QName TYPE_NAME = new QName(PVPConstants.EIDAT10_SAML_NS, TYPE_LOCAL_NAME, - PVPConstants.EIDAT10_PREFIX); - - /** - * Gets the attributes. - * - * @return the attributes - */ - List<EAAFRequestedAttribute> getAttributes(); -} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/reqattr/EaafRequestedAttribute.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/reqattr/EaafRequestedAttribute.java new file mode 100644 index 00000000..ae5fccea --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/reqattr/EaafRequestedAttribute.java @@ -0,0 +1,151 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.api.reqattr; + +import java.util.List; + +import javax.xml.namespace.QName; + +import at.gv.egiz.eaaf.modules.pvp2.PvpConstants; + +import org.opensaml.core.xml.AttributeExtensibleXMLObject; +import org.opensaml.core.xml.XMLObject; +import org.opensaml.core.xml.schema.XSBooleanValue; +import org.opensaml.saml.common.SAMLObject; +import org.opensaml.saml.saml2.metadata.RequestedAttribute; + +public interface EaafRequestedAttribute extends SAMLObject, AttributeExtensibleXMLObject, + RequestedAttribute { + + /** Element local name. */ + String DEF_LOCAL_NAME = "RequestedAttribute"; + + /** Local name of the XSI type. */ + String TYPE_LOCAL_NAME = "RequestedAttributeAbstractType"; + + /** Default element name. */ + QName DEFAULT_ELEMENT_NAME = + new QName(PvpConstants.EIDAT10_SAML_NS, DEF_LOCAL_NAME, PvpConstants.EIDAT10_PREFIX); + + /** QName of the XSI type. */ + QName TYPE_NAME = + new QName(PvpConstants.EIDAT10_SAML_NS, TYPE_LOCAL_NAME, PvpConstants.EIDAT10_PREFIX); + + /** NAME_ATTRIB_NAME attribute name. */ + String NAME_ATTRIB_NAME = "Name"; + + /** NAME_FORMAT_ATTRIB_NAME attribute name. */ + String NAME_FORMAT_ATTR = "NameFormat"; + + /** IS_REQUIRED_ATTRIB_NAME attribute name. */ + String IS_REQUIRED_ATTR = "isRequired"; + + /** FRIENDLY_NAME_ATTRIB_NAME attribute name. */ + String FRIENDLY_NAME_ATT = "FriendlyName"; + + /** Unspecified attribute format ID. */ + String UNSPECIFIED = "urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified"; + + /** URI reference attribute format ID. */ + String URI_REFERENCE = "urn:oasis:names:tc:SAML:2.0:attrname-format:uri"; + + /** Basic attribute format ID. */ + String BASIC = "urn:oasis:names:tc:SAML:2.0:attrname-format:basic"; + + /** + * Gets the name. + * + * @return the name + */ + @Override + String getName(); + + /** + * Sets the name. + * + * @param name the new name + */ + @Override + void setName(String name); + + /** + * Gets the name format. + * + * @return the name format + */ + @Override + String getNameFormat(); + + /** + * Sets the name format. + * + * @param nameFormat the new name format + */ + @Override + void setNameFormat(String nameFormat); + + /** + * Gets the friendly name. + * + * @return the friendly name + */ + @Override + String getFriendlyName(); + + /** + * Sets the friendly name. + * + * @param friendlyName the new friendly name + */ + @Override + void setFriendlyName(String friendlyName); + + /** + * Gets the checks if is required xs boolean. + * + * @return the checks if is required xs boolean + */ + String getIsRequiredXsBoolean(); + + @Override + void setIsRequired(Boolean aboolean); + + @Override + void setIsRequired(XSBooleanValue xsBooleanValue); + + /** + * Sets the checks if is required. + * + * @param newIsRequired the new checks if is required + */ + void setIsRequired(String newIsRequired); + + /** + * Gets the attribute values. + * + * @return the attribute values + */ + @Override + List<XMLObject> getAttributeValues(); + + @Override + XSBooleanValue isRequiredXSBoolean(); + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/reqattr/EaafRequestedAttributes.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/reqattr/EaafRequestedAttributes.java new file mode 100644 index 00000000..6e8d6202 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/reqattr/EaafRequestedAttributes.java @@ -0,0 +1,51 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.api.reqattr; + +import java.util.List; + +import javax.xml.namespace.QName; + +import at.gv.egiz.eaaf.modules.pvp2.PvpConstants; + +import org.opensaml.saml.common.SAMLObject; + +public interface EaafRequestedAttributes extends SAMLObject { + /** The Constant DEFAULT_ELEMENT_LOCAL_NAME. */ + String DEF_LOCAL_NAME = "RequestedAttributes"; + + /** Default element name. */ + QName DEFAULT_ELEMENT_NAME = + new QName(PvpConstants.EIDAT10_SAML_NS, DEF_LOCAL_NAME, PvpConstants.EIDAT10_PREFIX); + + /** Local name of the XSI type. */ + String TYPE_LOCAL_NAME = "RequestedAttributesType"; + + /** QName of the XSI type. */ + QName TYPE_NAME = + new QName(PvpConstants.EIDAT10_SAML_NS, TYPE_LOCAL_NAME, PvpConstants.EIDAT10_PREFIX); + + /** + * Gets the attributes. + * + * @return the attributes + */ + List<EaafRequestedAttribute> getAttributes(); +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/utils/IPvp2CredentialProvider.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/utils/IPvp2CredentialProvider.java new file mode 100644 index 00000000..a564efb2 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/utils/IPvp2CredentialProvider.java @@ -0,0 +1,55 @@ +package at.gv.egiz.eaaf.modules.pvp2.api.utils; + +import java.security.cert.X509Certificate; +import java.util.List; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential; +import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException; + +public interface IPvp2CredentialProvider { + + /** + * Get Credentials to sign metadata. + * + * @return Credentials + * @throws CredentialsNotAvailableException In case of a credential error + */ + @Nonnull + EaafX509Credential getMetaDataSigningCredential() throws CredentialsNotAvailableException; + + /** + * Get Credentials to sign SAML2 messages, like AuthnRequest, Response, + * Assertions as some examples. + * + * @return Credentials + * @throws CredentialsNotAvailableException In case of a credential error + */ + @Nonnull + EaafX509Credential getMessageSigningCredential() throws CredentialsNotAvailableException; + + /** + * Get Credentials to encrypt messages, like Assertion as example. + * + * @return Credentials + * @throws CredentialsNotAvailableException In case of a credential error + */ + @Nullable + EaafX509Credential getMessageEncryptionCredential() + throws CredentialsNotAvailableException; + + /** + * Get a List of trusted {@link X509Certificate} that are available in this + * KeyStore. + * + * @return List of trusted {@link X509Certificate}, or an emptry {@link List} if + * no certificates are available + * @throws CredentialsNotAvailableException In case of a KeyStore error + */ + @Nonnull + List<X509Certificate> getTrustedCertificates() + throws CredentialsNotAvailableException; + +}
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/validation/IAuthnRequestPostProcessor.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/validation/IAuthnRequestPostProcessor.java index b23c230e..9f7a5980 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/validation/IAuthnRequestPostProcessor.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/validation/IAuthnRequestPostProcessor.java @@ -24,14 +24,15 @@ import javax.servlet.http.HttpServletRequest; import at.gv.egiz.eaaf.core.api.IRequest; import at.gv.egiz.eaaf.core.exceptions.AuthnRequestValidatorException; -import org.opensaml.saml2.core.AuthnRequest; -import org.opensaml.saml2.metadata.SPSSODescriptor; +import org.opensaml.saml.saml2.core.AuthnRequest; +import org.opensaml.saml.saml2.metadata.SPSSODescriptor; /** * SAML2 Authn. request post-processor. * * <p> - * Implementations of this interface are executed before user authentication starts. + * Implementations of this interface are executed before user authentication + * starts. * </p> * * @author tlenz @@ -42,12 +43,13 @@ public interface IAuthnRequestPostProcessor { /** * Authn. request post-processor * - * @param httpReq http request - * @param pendingReq current pending request - * @param authReq received SAML2 authentication request + * @param httpReq http request + * @param pendingReq current pending request + * @param authReq received SAML2 authentication request * @param spSsoDescriptor Metadata descriptor of the requested SP - * @throws AuthnRequestValidatorException In case of a validation error, - * if post processor implements additional validation + * @throws AuthnRequestValidatorException In case of a validation error, if post + * processor implements additional + * validation */ void process(HttpServletRequest httpReq, IRequest pendingReq, AuthnRequest authReq, SPSSODescriptor spSsoDescriptor) throws AuthnRequestValidatorException; diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/validation/ISAMLValidator.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/validation/ISAMLValidator.java deleted file mode 100644 index 4b8ddea6..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/validation/ISAMLValidator.java +++ /dev/null @@ -1,35 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.api.validation; - -import org.opensaml.saml2.core.RequestAbstractType; - -import at.gv.egiz.eaaf.core.exceptions.EAAFException; - -public interface ISAMLValidator { - public void validateRequest(RequestAbstractType request) throws EAAFException; -} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/validation/ISamlValidator.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/validation/ISamlValidator.java new file mode 100644 index 00000000..9042d874 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/api/validation/ISamlValidator.java @@ -0,0 +1,28 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.api.validation; + +import at.gv.egiz.eaaf.core.exceptions.EaafException; + +import org.opensaml.saml.saml2.core.RequestAbstractType; + +public interface ISamlValidator { + void validateRequest(RequestAbstractType request) throws EaafException; +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/AttributQueryException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/AttributQueryException.java index 189dc91e..78529e23 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/AttributQueryException.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/AttributQueryException.java @@ -1,48 +1,34 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 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: + * Licensed under the EUPL, Version 1.2 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: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * 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. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * 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.egiz.eaaf.modules.pvp2.exception; -/** - * @author tlenz - * - */ -public class AttributQueryException extends PVP2Exception { +public class AttributQueryException extends Pvp2Exception { + + private static final long serialVersionUID = -4302422507173728748L; - /** - * - */ - private static final long serialVersionUID = -4302422507173728748L; + public AttributQueryException(final String messageId, final Object[] parameters) { + super(messageId, parameters); + } - public AttributQueryException(String messageId, Object[] parameters) { - super(messageId, parameters); - } - - public AttributQueryException(String messageId, Object[] parameters, Throwable e) { - super(messageId, parameters, e); - } + public AttributQueryException(final String messageId, final Object[] parameters, final Throwable e) { + super(messageId, parameters, e); + } } diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/BindingNotSupportedException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/BindingNotSupportedException.java index d966e4a1..cc01aa43 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/BindingNotSupportedException.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/BindingNotSupportedException.java @@ -1,45 +1,33 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 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: + * Licensed under the EUPL, Version 1.2 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: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * 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. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * 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.egiz.eaaf.modules.pvp2.exception; -import org.opensaml.saml2.core.StatusCode; +import org.opensaml.saml.saml2.core.StatusCode; -public class BindingNotSupportedException extends PVP2Exception { +public class BindingNotSupportedException extends Pvp2Exception { - public BindingNotSupportedException(String binding) { - super("pvp2.11", new Object[] {binding}); - this.statusCodeValue = StatusCode.UNSUPPORTED_BINDING_URI; - } + private static final long serialVersionUID = -7227603941387879360L; - /** - * - */ - private static final long serialVersionUID = -7227603941387879360L; + public BindingNotSupportedException(final String binding) { + super("pvp2.11", new Object[] { binding }); + this.statusCodeValue = StatusCode.UNSUPPORTED_BINDING; + } - - } diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/CredentialsNotAvailableException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/CredentialsNotAvailableException.java index e079cdef..ede00366 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/CredentialsNotAvailableException.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/CredentialsNotAvailableException.java @@ -1,48 +1,37 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 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: + * Licensed under the EUPL, Version 1.2 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: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * 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. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * 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.egiz.eaaf.modules.pvp2.exception; -import at.gv.egiz.eaaf.core.exceptions.EAAFException; +import at.gv.egiz.eaaf.core.exceptions.EaafException; + +public class CredentialsNotAvailableException extends EaafException { -public class CredentialsNotAvailableException extends EAAFException { + private static final long serialVersionUID = -2564476345552842599L; - public CredentialsNotAvailableException(String messageId, - Object[] parameters) { - super(messageId, parameters); - } + public CredentialsNotAvailableException(final String messageId, final Object[] parameters) { + super(messageId, parameters); + } - public CredentialsNotAvailableException(String messageId, - Object[] parameters, Throwable e) { - super(messageId, parameters, e); - } - - /** - * - */ - private static final long serialVersionUID = -2564476345552842599L; + public CredentialsNotAvailableException(final String messageId, final Object[] parameters, + final Throwable e) { + super(messageId, parameters, e); + } } diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/InvalidDateFormatException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/InvalidDateFormatException.java index 6bcddf8a..b71ab2c6 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/InvalidDateFormatException.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/InvalidDateFormatException.java @@ -1,43 +1,33 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 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: + * Licensed under the EUPL, Version 1.2 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: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * 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. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * 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.egiz.eaaf.modules.pvp2.exception; -import org.opensaml.saml2.core.StatusCode; +import org.opensaml.saml.saml2.core.StatusCode; -public class InvalidDateFormatException extends PVP2Exception { +public class InvalidDateFormatException extends Pvp2Exception { - public InvalidDateFormatException() { - super("pvp2.02", null); - this.statusCodeValue = StatusCode.REQUESTER_URI; - } + private static final long serialVersionUID = -6867976890237846085L; - /** - * - */ - private static final long serialVersionUID = -6867976890237846085L; + public InvalidDateFormatException() { + super("pvp2.02", null); + this.statusCodeValue = StatusCode.REQUESTER; + } } diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/InvalidPVPRequestException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/InvalidPVPRequestException.java deleted file mode 100644 index 1d79ae2e..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/InvalidPVPRequestException.java +++ /dev/null @@ -1,40 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.exception; - -public class InvalidPVPRequestException extends PVP2Exception { - - /** - * - */ - private static final long serialVersionUID = 1L; - - public InvalidPVPRequestException(String messageId, Object[] parameters) { - super(messageId, parameters); - } - -} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/InvalidPvpRequestException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/InvalidPvpRequestException.java new file mode 100644 index 00000000..e13731d6 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/InvalidPvpRequestException.java @@ -0,0 +1,30 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.exception; + +public class InvalidPvpRequestException extends Pvp2Exception { + + private static final long serialVersionUID = 1L; + + public InvalidPvpRequestException(final String messageId, final Object[] parameters) { + super(messageId, parameters); + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/NameIDFormatNotSupportedException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/NameIDFormatNotSupportedException.java deleted file mode 100644 index a5ff811d..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/NameIDFormatNotSupportedException.java +++ /dev/null @@ -1,46 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.exception; - -import org.opensaml.saml2.core.StatusCode; - -import at.gv.egiz.eaaf.core.exceptions.AuthnRequestValidatorException; - -public class NameIDFormatNotSupportedException extends AuthnRequestValidatorException { - - public NameIDFormatNotSupportedException(String nameIDFormat) { - super("pvp2.12", new Object[] {nameIDFormat}); - statusCodeValue = StatusCode.INVALID_NAMEID_POLICY_URI; - - } - - /** - * - */ - private static final long serialVersionUID = -2270762519437873336L; - -} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/NameIdFormatNotSupportedException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/NameIdFormatNotSupportedException.java new file mode 100644 index 00000000..57f40e8f --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/NameIdFormatNotSupportedException.java @@ -0,0 +1,41 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.exception; + +import at.gv.egiz.eaaf.core.exceptions.AuthnRequestValidatorException; + +import org.opensaml.saml.saml2.core.StatusCode; + +public class NameIdFormatNotSupportedException extends AuthnRequestValidatorException { + + private static final long serialVersionUID = -2270762519437873336L; + + /** + * Invalid nameIdFormat in SAML2 request. + * + * @param nameIdFormat requested NameIdFormat + */ + public NameIdFormatNotSupportedException(final String nameIdFormat) { + super("pvp2.12", new Object[] { nameIdFormat }); + statusCodeValue = StatusCode.INVALID_NAMEID_POLICY; + + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/NoMetadataInformationException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/NoMetadataInformationException.java index e600a1c7..16dfa09f 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/NoMetadataInformationException.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/NoMetadataInformationException.java @@ -1,43 +1,33 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 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: + * Licensed under the EUPL, Version 1.2 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: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * 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. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * 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.egiz.eaaf.modules.pvp2.exception; -import org.opensaml.saml2.core.StatusCode; +import org.opensaml.saml.saml2.core.StatusCode; -public class NoMetadataInformationException extends PVP2Exception { +public class NoMetadataInformationException extends Pvp2Exception { - public NoMetadataInformationException() { - super("pvp2.15", null); - this.statusCodeValue = StatusCode.UNKNOWN_PRINCIPAL_URI; - } + private static final long serialVersionUID = -4608068445208032193L; - /** - * - */ - private static final long serialVersionUID = -4608068445208032193L; + public NoMetadataInformationException() { + super("pvp2.15", null); + this.statusCodeValue = StatusCode.UNKNOWN_PRINCIPAL; + } } diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/PVP2Exception.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/PVP2Exception.java deleted file mode 100644 index cfe4ca9d..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/PVP2Exception.java +++ /dev/null @@ -1,66 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.exception; - -import org.opensaml.saml2.core.StatusCode; - -import at.gv.egiz.eaaf.core.exceptions.EAAFException; - -public abstract class PVP2Exception extends EAAFException { - //TODO:!!!!! - - protected String statusCodeValue = StatusCode.RESPONDER_URI; - protected String statusMessageValue = null; - - public PVP2Exception(String messageId, Object[] parameters, - Throwable wrapped) { - super(messageId, parameters, wrapped); - this.statusMessageValue = this.getMessage(); - } - - public PVP2Exception(String messageId, Object[] parameters) { - super(messageId, parameters); - this.statusMessageValue = this.getMessage(); - } - - - public String getStatusCodeValue() { - return (this.statusCodeValue); - } - - public String getStatusMessageValue() { - return (this.statusMessageValue); - } - - /** - * - */ - private static final long serialVersionUID = 7669537952484421069L; - - - -} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/PVP2MetadataException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/PVP2MetadataException.java deleted file mode 100644 index 379fe19f..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/PVP2MetadataException.java +++ /dev/null @@ -1,41 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.exception; - -public class PVP2MetadataException extends PVP2Exception { - - private static final long serialVersionUID = 1L; - - public PVP2MetadataException(String messageId, Object[] parameters) { - super(messageId, parameters); - } - - public PVP2MetadataException(String messageId, Object[] parameters, Throwable wrapped) { - super(messageId, parameters, wrapped); - } - -} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/Pvp2Exception.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/Pvp2Exception.java new file mode 100644 index 00000000..54d0c5ef --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/Pvp2Exception.java @@ -0,0 +1,50 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.exception; + +import at.gv.egiz.eaaf.core.exceptions.EaafException; + +import org.opensaml.saml.saml2.core.StatusCode; + +public abstract class Pvp2Exception extends EaafException { + private static final long serialVersionUID = 7669537952484421069L; + + protected String statusCodeValue = StatusCode.RESPONDER; + protected String statusMessageValue = null; + + public Pvp2Exception(final String messageId, final Object[] parameters, final Throwable wrapped) { + super(messageId, parameters, wrapped); + this.statusMessageValue = this.getMessage(); + } + + public Pvp2Exception(final String messageId, final Object[] parameters) { + super(messageId, parameters); + this.statusMessageValue = this.getMessage(); + } + + public String getStatusCodeValue() { + return this.statusCodeValue; + } + + public String getStatusMessageValue() { + return this.statusMessageValue; + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/Pvp2InternalErrorException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/Pvp2InternalErrorException.java new file mode 100644 index 00000000..0b69897b --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/Pvp2InternalErrorException.java @@ -0,0 +1,12 @@ +package at.gv.egiz.eaaf.modules.pvp2.exception; + +public class Pvp2InternalErrorException extends Pvp2Exception { + + private static final long serialVersionUID = 496637421176810375L; + + public Pvp2InternalErrorException(Throwable wrapped) { + super("internal.pvp.98", new Object[] { wrapped.getMessage() }, wrapped); + + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/Pvp2MetadataException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/Pvp2MetadataException.java new file mode 100644 index 00000000..5ed7c99d --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/Pvp2MetadataException.java @@ -0,0 +1,34 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.exception; + +public class Pvp2MetadataException extends Pvp2Exception { + + private static final long serialVersionUID = 1L; + + public Pvp2MetadataException(final String messageId, final Object[] parameters) { + super(messageId, parameters); + } + + public Pvp2MetadataException(final String messageId, final Object[] parameters, final Throwable wrapped) { + super(messageId, parameters, wrapped); + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/QAANotAllowedException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/QAANotAllowedException.java deleted file mode 100644 index a8012d85..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/QAANotAllowedException.java +++ /dev/null @@ -1,44 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.exception; - -import org.opensaml.saml2.core.StatusCode; - - -public class QAANotAllowedException extends PVP2Exception { - - public QAANotAllowedException(String qaa_auth, String qaa_request, String mode) { - super("pvp2.17", new Object[] {qaa_auth, qaa_request, mode}); - this.statusCodeValue = StatusCode.REQUESTER_URI; - } - - /** - * - */ - private static final long serialVersionUID = -3964192953884089323L; - -} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/QAANotSupportedException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/QAANotSupportedException.java deleted file mode 100644 index 0b53ae23..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/QAANotSupportedException.java +++ /dev/null @@ -1,44 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.exception; - -import org.opensaml.saml2.core.StatusCode; - - -public class QAANotSupportedException extends PVP2Exception { - - public QAANotSupportedException(String qaa) { - super("pvp2.05", new Object[] {qaa}); - this.statusCodeValue = StatusCode.REQUESTER_URI; - } - - /** - * - */ - private static final long serialVersionUID = -3964192953884089323L; - -} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/QaaNotAllowedException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/QaaNotAllowedException.java new file mode 100644 index 00000000..5f109b67 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/QaaNotAllowedException.java @@ -0,0 +1,32 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.exception; + +import org.opensaml.saml.saml2.core.StatusCode; + +public class QaaNotAllowedException extends Pvp2Exception { + + private static final long serialVersionUID = -3964192953884089323L; + + public QaaNotAllowedException(final String qaaAuth, final String qaaRequest, final String mode) { + super("pvp2.17", new Object[] { qaaAuth, qaaRequest, mode }); + this.statusCodeValue = StatusCode.REQUESTER; + } +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/QaaNotSupportedException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/QaaNotSupportedException.java new file mode 100644 index 00000000..fce44542 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/QaaNotSupportedException.java @@ -0,0 +1,33 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.exception; + +import org.opensaml.saml.saml2.core.StatusCode; + +public class QaaNotSupportedException extends Pvp2Exception { + + private static final long serialVersionUID = -3964192953884089323L; + + public QaaNotSupportedException(final String qaa) { + super("pvp2.05", new Object[] { qaa }); + this.statusCodeValue = StatusCode.REQUESTER; + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SAMLMetadataSignatureException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SAMLMetadataSignatureException.java deleted file mode 100644 index 9e35871d..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SAMLMetadataSignatureException.java +++ /dev/null @@ -1,48 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.exception; - -import org.opensaml.saml2.core.StatusCode; - -public class SAMLMetadataSignatureException extends PVP2Exception { - - public SAMLMetadataSignatureException() { - super("pvp2.25", null); - this.statusCodeValue = StatusCode.REQUESTER_URI; - } - - public SAMLMetadataSignatureException(Throwable e) { - super("pvp2.25", null, e); - this.statusCodeValue = StatusCode.REQUESTER_URI; - } - - /** - * - */ - private static final long serialVersionUID = 1L; - -} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SamlAssertionValidationExeption.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SamlAssertionValidationExeption.java new file mode 100644 index 00000000..9ba7ccb2 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SamlAssertionValidationExeption.java @@ -0,0 +1,28 @@ +package at.gv.egiz.eaaf.modules.pvp2.exception; + +public class SamlAssertionValidationExeption extends SamlMessageValidationException { + + private static final long serialVersionUID = 2054578783736917817L; + + /** + * In case of a SAML2-Assertion validation error. + * + * @param messageId errorId + * @param parameters Message parameters + */ + public SamlAssertionValidationExeption(String messageId, Object[] parameters) { + super(messageId, parameters); + } + + /** + * In case of a SAML2-Assertion validation error. + * + * @param messageId errorId + * @param parameters Message parameters + * @param wrapped Exception that was thrown + */ + public SamlAssertionValidationExeption(String messageId, Object[] parameters, Throwable wrapped) { + super(messageId, parameters, wrapped); + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SamlBindingException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SamlBindingException.java new file mode 100644 index 00000000..9f079584 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SamlBindingException.java @@ -0,0 +1,12 @@ +package at.gv.egiz.eaaf.modules.pvp2.exception; + +public class SamlBindingException extends Pvp2Exception { + + private static final long serialVersionUID = 7122051055002687486L; + + public SamlBindingException(String messageId, Object[] parameters, Throwable wrapped) { + super(messageId, parameters, wrapped); + + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SamlMessageValidationException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SamlMessageValidationException.java new file mode 100644 index 00000000..56d8c4a5 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SamlMessageValidationException.java @@ -0,0 +1,30 @@ +package at.gv.egiz.eaaf.modules.pvp2.exception; + +public class SamlMessageValidationException extends Pvp2Exception { + + private static final long serialVersionUID = 2545822499416501014L; + + /** + * In case of a SAML2-message validation error. + * + * @param messageId errorId + * @param parameters Message parameters + */ + public SamlMessageValidationException(String messageId, Object[] parameters) { + super(messageId, parameters); + + } + + /** + * In case of a SAML2-message validation error. + * + * @param messageId errorId + * @param parameters Message parameters + * @param wrapped Exception that was thrown + */ + public SamlMessageValidationException(String messageId, Object[] parameters, Throwable wrapped) { + super(messageId, parameters, wrapped); + + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SamlMetadataSignatureException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SamlMetadataSignatureException.java new file mode 100644 index 00000000..9ef3a673 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SamlMetadataSignatureException.java @@ -0,0 +1,53 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.exception; + +import org.opensaml.saml.saml2.core.StatusCode; + +public class SamlMetadataSignatureException extends Pvp2MetadataException { + private static final long serialVersionUID = 1L; + + /** + * In case of a SAML2 metadata-signature verification error. + * + * @param metadataUrl Path metadata that should be loaded + * @param reason Details on error + * + */ + public SamlMetadataSignatureException(String metadataUrl, String reason) { + super("internal.pvp.07", new Object[] { metadataUrl, reason }); + this.statusCodeValue = StatusCode.REQUESTER; + + } + + /** + * In case of a SAML2 metadata-signature verification error. + * + * @param metadataUrl Path metadata that should be loaded + * @param reason Details on error + * @param e Error + */ + public SamlMetadataSignatureException(String metadataUrl, String reason, final Throwable e) { + super("internal.pvp.07", new Object[] { metadataUrl, reason }, e); + this.statusCodeValue = StatusCode.REQUESTER; + + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SamlSigningException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SamlSigningException.java new file mode 100644 index 00000000..e1a5a9d9 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SamlSigningException.java @@ -0,0 +1,17 @@ +package at.gv.egiz.eaaf.modules.pvp2.exception; + +public class SamlSigningException extends Pvp2Exception { + + private static final long serialVersionUID = 1L; + + public SamlSigningException(String messageId, Object[] parameters, Throwable wrapped) { + super(messageId, parameters, wrapped); + + } + + public SamlSigningException(String messageId, Object[] parameters) { + super(messageId, parameters); + + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SchemaValidationException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SchemaValidationException.java index f9adbf6d..14ad34a5 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SchemaValidationException.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SchemaValidationException.java @@ -1,56 +1,34 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 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: + * Licensed under the EUPL, Version 1.2 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: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * 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. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * 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.egiz.eaaf.modules.pvp2.exception; -/** - * @author tlenz - * - */ -public class SchemaValidationException extends PVP2Exception { +public class SchemaValidationException extends Pvp2Exception { + + private static final long serialVersionUID = 1L; - /** - * - */ - private static final long serialVersionUID = 1L; + public SchemaValidationException(final String messageId, final Object[] parameters) { + super(messageId, parameters); + } - /** - * @param messageId - * @param parameters - */ - public SchemaValidationException(String messageId, Object[] parameters) { - super(messageId, parameters); - } - - /** - * @param messageId - * @param parameters - */ - public SchemaValidationException(String messageId, Object[] parameters, Throwable e) { - super(messageId, parameters, e); - } + public SchemaValidationException(final String messageId, final Object[] parameters, final Throwable e) { + super(messageId, parameters, e); + } } diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SignatureValidationException.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SignatureValidationException.java index 1f1f46e5..6a39336c 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SignatureValidationException.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/exception/SignatureValidationException.java @@ -1,62 +1,41 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 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: + * Licensed under the EUPL, Version 1.2 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: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * 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. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * 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.egiz.eaaf.modules.pvp2.exception; -import org.opensaml.saml2.metadata.provider.FilterException; +import org.opensaml.saml.metadata.resolver.filter.FilterException; -/** - * @author tlenz - * - */ public class SignatureValidationException extends FilterException { - /** - * @param string - */ - public SignatureValidationException(String string) { - super(string); - - } - - /** - * @param e - */ - public SignatureValidationException(Exception e) { - super(e); - } - - /** - * @param string - * @param object - */ - public SignatureValidationException(String string, Exception e) { - super(string, e); - } - - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; + + public SignatureValidationException(final String string) { + super(string); + + } + + public SignatureValidationException(final Exception e) { + super(e); + } + + public SignatureValidationException(final String string, final Exception e) { + super(string, e); + } } diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/AbstractBinding.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/AbstractBinding.java new file mode 100644 index 00000000..3543d85a --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/AbstractBinding.java @@ -0,0 +1,219 @@ +package at.gv.egiz.eaaf.modules.pvp2.impl.binding; + +import javax.xml.namespace.QName; + +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential; +import at.gv.egiz.eaaf.modules.pvp2.api.message.InboundMessageInterface; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2InternalErrorException; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlBindingException; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlMessageValidationException; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlSigningException; +import at.gv.egiz.eaaf.modules.pvp2.impl.message.InboundMessage; +import at.gv.egiz.eaaf.modules.pvp2.impl.message.PvpSProfileRequest; +import at.gv.egiz.eaaf.modules.pvp2.impl.message.PvpSProfileResponse; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils; +import at.gv.egiz.eaaf.modules.pvp2.impl.validation.TrustEngineFactory; +import at.gv.egiz.eaaf.modules.pvp2.impl.verification.PvpSamlMessageHandlerChain; + +import org.opensaml.core.config.ConfigurationService; +import org.opensaml.messaging.context.BaseContext; +import org.opensaml.messaging.context.MessageContext; +import org.opensaml.messaging.decoder.MessageDecodingException; +import org.opensaml.messaging.decoder.servlet.HttpServletRequestMessageDecoder; +import org.opensaml.messaging.handler.MessageHandlerException; +import org.opensaml.saml.common.SAMLObject; +import org.opensaml.saml.common.SignableSAMLObject; +import org.opensaml.saml.common.binding.SAMLBindingSupport; +import org.opensaml.saml.common.binding.encoding.SAMLMessageEncoder; +import org.opensaml.saml.common.messaging.context.SAMLEndpointContext; +import org.opensaml.saml.common.messaging.context.SAMLMessageInfoContext; +import org.opensaml.saml.common.messaging.context.SAMLPeerEntityContext; +import org.opensaml.saml.common.messaging.context.SAMLProtocolContext; +import org.opensaml.saml.common.xml.SAMLConstants; +import org.opensaml.saml.saml2.core.RequestAbstractType; +import org.opensaml.saml.saml2.core.StatusResponseType; +import org.opensaml.saml.saml2.metadata.SingleSignOnService; +import org.opensaml.saml.saml2.metadata.impl.SingleSignOnServiceBuilder; +import org.opensaml.xmlsec.SignatureSigningParameters; +import org.opensaml.xmlsec.SignatureValidationConfiguration; +import org.opensaml.xmlsec.SignatureValidationParameters; +import org.opensaml.xmlsec.context.SecurityParametersContext; +import org.opensaml.xmlsec.signature.support.SignatureConstants; +import org.springframework.beans.factory.annotation.Autowired; + +import com.google.common.base.Optional; +import com.google.common.base.Predicates; +import com.google.common.base.Throwables; +import com.google.common.collect.FluentIterable; +import lombok.extern.slf4j.Slf4j; +import net.shibboleth.utilities.java.support.component.ComponentInitializationException; + +/** + * Abstract Binding implements common code for SAML2 binding implementations. + * + * @author tlenz + * + */ +@Slf4j +public abstract class AbstractBinding { + + @Autowired + protected IConfiguration basicConfig; + + public abstract String getSaml2BindingName(); + + protected MessageContext<SAMLObject> internalMessageDecode( + HttpServletRequestMessageDecoder<SAMLObject> decoder, + String binding) throws Pvp2Exception { + try { + decoder.initialize(); + decoder.decode(); + + } catch (final ComponentInitializationException e) { + log.warn("Internal initialization error. Reason: {}", e.getMessage()); + throw new Pvp2InternalErrorException(e); + + } catch (final MessageDecodingException e) { + final Optional<Throwable> pvpException = FluentIterable.from( + Throwables.getCausalChain(e)).filter( + Predicates.instanceOf(Pvp2Exception.class)).first(); + + if (pvpException.isPresent()) { + throw (Pvp2Exception) pvpException.get(); + + } else { + throw new SamlBindingException("internal.pvp.95", + new Object[] { binding, "decoding", e.getMessage() }, + e); + + } + + } + + return decoder.getMessageContext(); + + } + + protected MessageContext<SAMLObject> buildBasicMessageContext( + SAMLMessageEncoder encoder, SignableSAMLObject response) { + final MessageContext<SAMLObject> messageContext = new MessageContext<>(); + messageContext.setMessage(response); + encoder.setMessageContext(messageContext); + return messageContext; + + } + + protected BaseContext injectSigningInfos(EaafX509Credential credentials) throws SamlSigningException { + final SecurityParametersContext securityParamContext = new SecurityParametersContext(); + final SignatureSigningParameters signingParams = new SignatureSigningParameters(); + securityParamContext.setSignatureSigningParameters(signingParams); + + signingParams.setSigningCredential(credentials); + signingParams.setSignatureCanonicalizationAlgorithm( + SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS); + signingParams.setSignatureReferenceCanonicalizationAlgorithm( + SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS); + signingParams.setSignatureAlgorithm(credentials.getSignatureAlgorithmForSigning()); + signingParams.setSignatureReferenceDigestMethod( + Saml2Utils.getDigestAlgorithm(signingParams.getSignatureAlgorithm())); + + signingParams.setKeyInfoGenerator(Saml2Utils.getKeyInfoGenerator(credentials, true)); + + return securityParamContext; + + } + + protected BaseContext injectEndpointInfos(final SignableSAMLObject response, String targetLocation) { + SAMLBindingSupport.setSAML2Destination(response, targetLocation); + final SingleSignOnService service = new SingleSignOnServiceBuilder().buildObject(); + service.setBinding(getSaml2BindingName()); + service.setLocation(targetLocation); + final SAMLPeerEntityContext peerEntityContext = new SAMLPeerEntityContext(); + final SAMLEndpointContext endpointContext = new SAMLEndpointContext(); + endpointContext.setEndpoint(service); + peerEntityContext.addSubcontext(endpointContext); + return peerEntityContext; + + } + + protected void injectInboundMessageContexts(MessageContext<SAMLObject> messageContext, + IPvp2MetadataProvider metadataProvider, QName peerEntityRole) throws Pvp2InternalErrorException { + final SAMLPeerEntityContext peerEntityContext = new SAMLPeerEntityContext(); + peerEntityContext.setRole(peerEntityRole); + messageContext.addSubcontext(peerEntityContext); + messageContext.addSubcontext(new SAMLMessageInfoContext()); + + final SAMLProtocolContext protocolContext = new SAMLProtocolContext(); + protocolContext.setProtocol(SAMLConstants.SAML20P_NS); + messageContext.addSubcontext(protocolContext); + + final SecurityParametersContext securityParameterContext = new SecurityParametersContext(); + final SignatureValidationParameters sigValParameters = new SignatureValidationParameters(); + securityParameterContext.setSignatureValidationParameters(sigValParameters); + messageContext.addSubcontext(securityParameterContext); + + sigValParameters.setBlacklistedAlgorithms( + ConfigurationService.get(SignatureValidationConfiguration.class) + .getBlacklistedAlgorithms()); + sigValParameters.setSignatureTrustEngine( + TrustEngineFactory.getSignatureKnownKeysTrustEngine(metadataProvider)); + + } + + protected void performMessageValidation(PvpSamlMessageHandlerChain messageValidatorChain, + MessageContext<SAMLObject> messageContext) throws Pvp2Exception { + try { + messageValidatorChain.initialize(); + messageValidatorChain.invoke(messageContext); + + } catch (final ComponentInitializationException e) { + log.warn("Internal initialization error. Reason: {}", e.getMessage()); + throw new Pvp2InternalErrorException(e); + + } catch (final MessageHandlerException e) { + log.info("SAML message validation error. Reason: {}", e.getMessage()); + final Optional<Throwable> pvpException = FluentIterable.from( + Throwables.getCausalChain(e)).filter( + Predicates.instanceOf(Pvp2Exception.class)).first(); + + if (pvpException.isPresent()) { + throw (Pvp2Exception) pvpException.get(); + + } else { + throw new SamlMessageValidationException("internal.pvp.11", + new Object[] { e.getMessage() }, e); + + } + } + } + + protected InboundMessageInterface performMessageDecodePostProcessing( + MessageContext<SAMLObject> messageContext, boolean isVerified) { + InboundMessage msg = null; + if (messageContext.getMessage() instanceof RequestAbstractType) { + final RequestAbstractType inboundMessage = + (RequestAbstractType) messageContext.getMessage(); + msg = new PvpSProfileRequest(inboundMessage, getSaml2BindingName()); + msg.setEntityID(inboundMessage.getIssuer().getValue()); + + } else if (messageContext.getMessage() instanceof StatusResponseType) { + final StatusResponseType inboundMessage = + (StatusResponseType) messageContext.getMessage(); + msg = new PvpSProfileResponse(inboundMessage); + msg.setEntityID(inboundMessage.getIssuer().getValue()); + + } else { + // create empty container if request type is unknown + msg = new InboundMessage(); + + } + + msg.setVerified(isVerified); + msg.setRelayState(SAMLBindingSupport.getRelayState(messageContext)); + + return msg; + } +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/PostBinding.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/PostBinding.java index 79578788..c679de20 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/PostBinding.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/PostBinding.java @@ -1,242 +1,237 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 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: + * Licensed under the EUPL, Version 1.2 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: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * 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. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * 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.egiz.eaaf.modules.pvp2.impl.binding; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.lang3.StringUtils; -import org.opensaml.common.SAMLObject; -import org.opensaml.common.binding.BasicSAMLMessageContext; -import org.opensaml.common.binding.decoding.URIComparator; -import org.opensaml.common.xml.SAMLConstants; -import org.opensaml.saml2.binding.decoding.HTTPPostDecoder; -import org.opensaml.saml2.core.RequestAbstractType; -import org.opensaml.saml2.core.StatusResponseType; -import org.opensaml.saml2.metadata.IDPSSODescriptor; -import org.opensaml.saml2.metadata.SPSSODescriptor; -import org.opensaml.saml2.metadata.SingleSignOnService; -import org.opensaml.saml2.metadata.impl.SingleSignOnServiceBuilder; -import org.opensaml.saml2.metadata.provider.MetadataProvider; -import org.opensaml.ws.message.decoder.MessageDecodingException; -import org.opensaml.ws.message.encoder.MessageEncodingException; -import org.opensaml.ws.security.SecurityPolicyResolver; -import org.opensaml.ws.security.provider.BasicSecurityPolicy; -import org.opensaml.ws.security.provider.StaticSecurityPolicyResolver; -import org.opensaml.ws.transport.http.HttpServletRequestAdapter; -import org.opensaml.ws.transport.http.HttpServletResponseAdapter; -import org.opensaml.xml.parse.BasicParserPool; -import org.opensaml.xml.security.SecurityException; -import org.opensaml.xml.security.credential.Credential; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; +import javax.xml.namespace.QName; import at.gv.egiz.eaaf.core.api.IRequest; -import at.gv.egiz.eaaf.core.api.gui.IGUIBuilderConfigurationFactory; -import at.gv.egiz.eaaf.core.api.gui.IVelocityGUIBuilderConfiguration; +import at.gv.egiz.eaaf.core.api.gui.IGuiBuilderConfigurationFactory; +import at.gv.egiz.eaaf.core.api.gui.IVelocityGuiBuilderConfiguration; import at.gv.egiz.eaaf.core.api.gui.IVelocityGuiFormBuilder; import at.gv.egiz.eaaf.core.api.idp.IConfiguration; -import at.gv.egiz.eaaf.core.impl.gui.velocity.VelocityProvider; -import at.gv.egiz.eaaf.modules.pvp2.PVPConstants; +import at.gv.egiz.eaaf.modules.pvp2.PvpConstants; import at.gv.egiz.eaaf.modules.pvp2.api.binding.IDecoder; import at.gv.egiz.eaaf.modules.pvp2.api.binding.IEncoder; +import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential; import at.gv.egiz.eaaf.modules.pvp2.api.message.InboundMessageInterface; -import at.gv.egiz.eaaf.modules.pvp2.impl.message.InboundMessage; -import at.gv.egiz.eaaf.modules.pvp2.impl.message.PVPSProfileRequest; -import at.gv.egiz.eaaf.modules.pvp2.impl.message.PVPSProfileResponse; -import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.HTTPPostEncoderWithOwnTemplate; -import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EAAFDefaultSAML2Bootstrap; -import at.gv.egiz.eaaf.modules.pvp2.impl.validation.TrustEngineFactory; -import at.gv.egiz.eaaf.modules.pvp2.impl.verification.PVPSignedRequestPolicyRule; - -@Service("PVPPOSTBinding") -public class PostBinding implements IDecoder, IEncoder { - private static final Logger log = LoggerFactory.getLogger(PostBinding.class); - - @Autowired(required=true) IConfiguration authConfig; - @Autowired(required=true) IVelocityGuiFormBuilder guiBuilder; - @Autowired(required=true) IGUIBuilderConfigurationFactory guiConfigFactory; - - @Override - public void encodeRequest(HttpServletRequest req, HttpServletResponse resp, - RequestAbstractType request, String targetLocation, String relayState, Credential credentials, IRequest pendingReq) - throws MessageEncodingException, SecurityException { - - try { - //load default PVP security configurations - EAAFDefaultSAML2Bootstrap.initializeDefaultPVPConfiguration(); - - //initialize POST binding encoder with template decoration - final IVelocityGUIBuilderConfiguration guiConfig = guiConfigFactory.getSPSpecificSAML2PostConfiguration( - pendingReq, - "pvp_postbinding_template.html", - authConfig.getConfigurationRootDirectory()); - - final HTTPPostEncoderWithOwnTemplate encoder = new HTTPPostEncoderWithOwnTemplate(guiConfig, guiBuilder, - VelocityProvider.getClassPathVelocityEngine()); - - //set OpenSAML2 process parameter into binding context dao - final HttpServletResponseAdapter responseAdapter = new HttpServletResponseAdapter( - resp, true); - final BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject> context = new BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject>(); - final SingleSignOnService service = new SingleSignOnServiceBuilder().buildObject(); - service.setBinding("urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"); - service.setLocation(targetLocation);; - - context.setOutboundSAMLMessageSigningCredential(credentials); - context.setPeerEntityEndpoint(service); - context.setOutboundSAMLMessage(request); - context.setOutboundMessageTransport(responseAdapter); - context.setRelayState(relayState); - - encoder.encode(context); - - } catch (final Exception e) { - log.warn("Can not encode SAML2 request", e); - throw new SecurityException(e); - - } - } - - @Override - public void encodeRespone(HttpServletRequest req, HttpServletResponse resp, - StatusResponseType response, String targetLocation, String relayState, Credential credentials, IRequest pendingReq) - throws MessageEncodingException, SecurityException { - - try { - //load default PVP security configurations - EAAFDefaultSAML2Bootstrap.initializeDefaultPVPConfiguration(); - - log.debug("create SAML POSTBinding response"); - - //initialize POST binding encoder with template decoration - final IVelocityGUIBuilderConfiguration guiConfig = guiConfigFactory.getSPSpecificSAML2PostConfiguration( - pendingReq, - "pvp_postbinding_template.html", - authConfig.getConfigurationRootDirectory()); - final HTTPPostEncoderWithOwnTemplate encoder = new HTTPPostEncoderWithOwnTemplate(guiConfig, guiBuilder, - VelocityProvider.getClassPathVelocityEngine()); - - //set OpenSAML2 process parameter into binding context dao - final HttpServletResponseAdapter responseAdapter = new HttpServletResponseAdapter( - resp, true); - final BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject> context = new BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject>(); - final SingleSignOnService service = new SingleSignOnServiceBuilder() - .buildObject(); - service.setBinding(SAMLConstants.SAML2_POST_BINDING_URI); - service.setLocation(targetLocation); - context.setOutboundSAMLMessageSigningCredential(credentials); - context.setPeerEntityEndpoint(service); - // context.setOutboundMessage(authReq); - context.setOutboundSAMLMessage(response); - context.setOutboundMessageTransport(responseAdapter); - context.setRelayState(relayState); - - encoder.encode(context); - - } catch (final Exception e) { - log.warn("Can not encode SAML2 response", e); - throw new SecurityException(e); - - } - } - - @Override - public InboundMessageInterface decode(HttpServletRequest req, - HttpServletResponse resp, MetadataProvider metadataProvider, boolean isSPEndPoint, URIComparator comparator) throws MessageDecodingException, - SecurityException { - - final HTTPPostDecoder decode = new HTTPPostDecoder(new BasicParserPool()); - final BasicSAMLMessageContext<SAMLObject, ?, ?> messageContext = new BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject>(); - messageContext - .setInboundMessageTransport(new HttpServletRequestAdapter(req)); - //set metadata descriptor type - if (isSPEndPoint) { - messageContext.setPeerEntityRole(IDPSSODescriptor.DEFAULT_ELEMENT_NAME); - decode.setURIComparator(comparator); - - } else { - messageContext.setPeerEntityRole(SPSSODescriptor.DEFAULT_ELEMENT_NAME); - decode.setURIComparator(comparator); - } - - messageContext.setMetadataProvider(metadataProvider); - - //set security policy context - final BasicSecurityPolicy policy = new BasicSecurityPolicy(); - policy.getPolicyRules().add( - new PVPSignedRequestPolicyRule(metadataProvider, - TrustEngineFactory.getSignatureKnownKeysTrustEngine(metadataProvider), - messageContext.getPeerEntityRole())); - final SecurityPolicyResolver secResolver = new StaticSecurityPolicyResolver(policy); - messageContext.setSecurityPolicyResolver(secResolver); - - decode.decode(messageContext); - - InboundMessage msg = null; - if (messageContext.getInboundMessage() instanceof RequestAbstractType) { - final RequestAbstractType inboundMessage = (RequestAbstractType) messageContext - .getInboundMessage(); - msg = new PVPSProfileRequest(inboundMessage, getSAML2BindingName()); - msg.setEntityID(inboundMessage.getIssuer().getValue()); - - } else if (messageContext.getInboundMessage() instanceof StatusResponseType){ - final StatusResponseType inboundMessage = (StatusResponseType) messageContext.getInboundMessage(); - msg = new PVPSProfileResponse(inboundMessage); - msg.setEntityID(inboundMessage.getIssuer().getValue()); - - } else - //create empty container if request type is unknown - msg = new InboundMessage(); - - if (messageContext.getPeerEntityMetadata() != null) - msg.setEntityID(messageContext.getPeerEntityMetadata().getEntityID()); - - else { - if (StringUtils.isEmpty(msg.getEntityID())) - log.info("No Metadata found for OA with EntityID " + messageContext.getInboundMessageIssuer()); - } - - - msg.setVerified(true); - msg.setRelayState(messageContext.getRelayState()); - - return msg; - } - - @Override - public boolean handleDecode(String action, HttpServletRequest req) { - return (req.getMethod().equals("POST") && action.equals(PVPConstants.POST)); - } - - @Override - public String getSAML2BindingName() { - return SAMLConstants.SAML2_POST_BINDING_URI; - } +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.exception.InvalidPvpRequestException; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlBindingException; +import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.EaafHttpPostDecoder; +import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.HttpPostEncoderWithOwnTemplate; +import at.gv.egiz.eaaf.modules.pvp2.impl.verification.EaafSamlProtocolMessageXmlSignatureSecurityHandler; +import at.gv.egiz.eaaf.modules.pvp2.impl.verification.PvpSamlMessageHandlerChain; + +import org.opensaml.messaging.context.MessageContext; +import org.opensaml.saml.common.SAMLObject; +import org.opensaml.saml.common.binding.SAMLBindingSupport; +import org.opensaml.saml.common.binding.impl.CheckMessageVersionHandler; +import org.opensaml.saml.common.binding.security.impl.MessageLifetimeSecurityHandler; +import org.opensaml.saml.common.binding.security.impl.ReceivedEndpointSecurityHandler; +import org.opensaml.saml.common.messaging.SAMLMessageSecuritySupport; +import org.opensaml.saml.common.xml.SAMLConstants; +import org.opensaml.saml.saml2.core.RequestAbstractType; +import org.opensaml.saml.saml2.core.StatusResponseType; +import org.springframework.beans.factory.annotation.Autowired; + +import lombok.extern.slf4j.Slf4j; +import net.shibboleth.utilities.java.support.net.URIComparator; + +@Slf4j +public class PostBinding extends AbstractBinding implements IDecoder, IEncoder { + + @Autowired(required = true) + IConfiguration authConfig; + @Autowired(required = true) + IVelocityGuiFormBuilder guiBuilder; + @Autowired(required = true) + IGuiBuilderConfigurationFactory guiConfigFactory; + + @Override + public void encodeRequest(final HttpServletRequest httpReq, final HttpServletResponse httpResp, + final RequestAbstractType request, final String targetLocation, final String relayState, + final EaafX509Credential credentials, final IRequest pendingReq) + throws Pvp2Exception { + + try { + // initialize POST binding encoder with template decoration + final IVelocityGuiBuilderConfiguration guiConfig = + guiConfigFactory.getSpSpecificSaml2PostConfiguration(pendingReq, + "pvp_postbinding_template.html", authConfig.getConfigurationRootDirectory()); + + final HttpPostEncoderWithOwnTemplate encoder = new HttpPostEncoderWithOwnTemplate(guiConfig, + guiBuilder); + + encoder.setHttpServletResponse(httpResp); + + // inject message context + final MessageContext<SAMLObject> messageContext = buildBasicMessageContext(encoder, request); + + // inject signing context + messageContext.addSubcontext(injectSigningInfos(credentials)); + + // set endpoint url + messageContext.addSubcontext(injectEndpointInfos(request, targetLocation)); + + // set relayState of exists + SAMLBindingSupport.setRelayState(messageContext, relayState); + + // sign SAML2 message + SAMLMessageSecuritySupport.signMessage(messageContext); + + // encode message + encoder.initialize(); + encoder.encode(); + + } catch (final Exception e) { + log.warn("Can not encode SAML2 Post-Binding request", e); + throw new SamlBindingException("internal.pvp.95", + new Object[] { PvpConstants.POST, "encoding", e.getMessage() }, + e); + + } + } + + @Override + public void encodeResponse(final HttpServletRequest httpReq, final HttpServletResponse httpResp, + final StatusResponseType response, final String targetLocation, final String relayState, + final EaafX509Credential credentials, final IRequest pendingReq) + throws Pvp2Exception { + + try { + log.debug("create SAML POSTBinding response"); + + // initialize POST binding encoder with template decoration + final IVelocityGuiBuilderConfiguration guiConfig = + guiConfigFactory.getSpSpecificSaml2PostConfiguration(pendingReq, + "pvp_postbinding_template.html", authConfig.getConfigurationRootDirectory()); + final HttpPostEncoderWithOwnTemplate encoder = + new HttpPostEncoderWithOwnTemplate(guiConfig, guiBuilder); + + encoder.setHttpServletResponse(httpResp); + + // inject message context + final MessageContext<SAMLObject> messageContext = buildBasicMessageContext(encoder, response); + + // inject signing context + messageContext.addSubcontext(injectSigningInfos(credentials)); + + // set endpoint url + messageContext.addSubcontext(injectEndpointInfos(response, targetLocation)); + + // set relayState of exists + SAMLBindingSupport.setRelayState(messageContext, relayState); + + // sign SAML2 message + SAMLMessageSecuritySupport.signMessage(messageContext); + + // encode message + encoder.initialize(); + encoder.encode(); + + } catch (final Exception e) { + log.warn("Can not encode SAML2 Post-Binding response", e); + throw new SamlBindingException("internal.pvp.95", + new Object[] { PvpConstants.POST, "encoding", e.getMessage() }, + e); + + } + } + + @Override + public InboundMessageInterface decode(final HttpServletRequest req, + final HttpServletResponse resp, final IPvp2MetadataProvider metadataProvider, + QName peerEntityRole, final URIComparator comparator) + throws Pvp2Exception { + + final EaafHttpPostDecoder decode = new EaafHttpPostDecoder(req); + final MessageContext<SAMLObject> messageContext = internalMessageDecode(decode, PvpConstants.POST); + + // check if PVP2 AuthnRequest is signed + if (!SAMLBindingSupport.isMessageSigned(messageContext)) { + log.info("SAML Post-Binding message contains no signature. Message will be rejected"); + throw new InvalidPvpRequestException("internal.pvp.02", null); + + } + + // inject informations into message context that are required for further + // processing + injectInboundMessageContexts(messageContext, metadataProvider, peerEntityRole); + final PvpSamlMessageHandlerChain messageValidatorChain = + buildMessageValidationChain(req, comparator, metadataProvider); + + log.trace("Message validation (Signature, ...) on binding-level starts ... "); + performMessageValidation(messageValidatorChain, messageContext); + + log.trace("Message validation successful"); + return performMessageDecodePostProcessing(messageContext, true); + + } + + @Override + public boolean handleDecode(final String action, final HttpServletRequest req) { + return req.getMethod().equals("POST") && action.equals(PvpConstants.POST); + + } + + @Override + public String getSaml2BindingName() { + return SAMLConstants.SAML2_POST_BINDING_URI; + + } + + private PvpSamlMessageHandlerChain buildMessageValidationChain(HttpServletRequest req, + URIComparator comparator, IPvp2MetadataProvider metadataProvider) { + final PvpSamlMessageHandlerChain messageValidatorChain = new PvpSamlMessageHandlerChain(); + + final ReceivedEndpointSecurityHandler endpointSecurityHandler = new ReceivedEndpointSecurityHandler(); + endpointSecurityHandler.setHttpServletRequest(req); + endpointSecurityHandler.setURIComparator(comparator); + + messageValidatorChain.addHandler(new CheckMessageVersionHandler()); + messageValidatorChain.addHandler(endpointSecurityHandler); + messageValidatorChain.addHandler( + new EaafSamlProtocolMessageXmlSignatureSecurityHandler(metadataProvider)); + messageValidatorChain.addHandler(new MessageLifetimeSecurityHandler()); + + /* + * TODO: maybe we add it in a later version Because: - AuthnRequest replay + * should not be a problem on IDP side - Response replay will be not possible, + * because EAAF PVP implements countermeasure based on one-time tokens for each + * request + * + */ + // final MessageReplaySecurityHandler replaySecurityHandler = new + // MessageReplaySecurityHandler(); + // final StorageService replayCacheStorage = null; + // final ReplayCache replayCache = new ReplayCache(); + // replayCache.setId("Message replay cache"); + // replayCache.setStrict(true); + // replayCache.setStorage(replayCacheStorage); + // replaySecurityHandler.setReplayCache(replayCache ); + // messageValidatorChain.addHandler(replaySecurityHandler); + + return messageValidatorChain; + + } } diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/RedirectBinding.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/RedirectBinding.java index ca9b3d98..f62f8a11 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/RedirectBinding.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/RedirectBinding.java @@ -1,239 +1,205 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 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: + * Licensed under the EUPL, Version 1.2 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: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * 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. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * 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.egiz.eaaf.modules.pvp2.impl.binding; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.lang3.StringUtils; -import org.opensaml.common.SAMLObject; -import org.opensaml.common.binding.BasicSAMLMessageContext; -import org.opensaml.common.binding.decoding.URIComparator; -import org.opensaml.common.xml.SAMLConstants; -import org.opensaml.saml2.binding.decoding.HTTPRedirectDeflateDecoder; -import org.opensaml.saml2.binding.encoding.HTTPRedirectDeflateEncoder; -import org.opensaml.saml2.binding.security.SAML2HTTPRedirectDeflateSignatureRule; -import org.opensaml.saml2.core.RequestAbstractType; -import org.opensaml.saml2.core.StatusResponseType; -import org.opensaml.saml2.metadata.IDPSSODescriptor; -import org.opensaml.saml2.metadata.SPSSODescriptor; -import org.opensaml.saml2.metadata.SingleSignOnService; -import org.opensaml.saml2.metadata.impl.SingleSignOnServiceBuilder; -import org.opensaml.saml2.metadata.provider.MetadataProvider; -import org.opensaml.ws.message.decoder.MessageDecodingException; -import org.opensaml.ws.message.encoder.MessageEncodingException; -import org.opensaml.ws.security.SecurityPolicyResolver; -import org.opensaml.ws.security.provider.BasicSecurityPolicy; -import org.opensaml.ws.security.provider.StaticSecurityPolicyResolver; -import org.opensaml.ws.transport.http.HttpServletRequestAdapter; -import org.opensaml.ws.transport.http.HttpServletResponseAdapter; -import org.opensaml.xml.parse.BasicParserPool; -import org.opensaml.xml.security.SecurityException; -import org.opensaml.xml.security.credential.Credential; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Service; +import javax.xml.namespace.QName; import at.gv.egiz.eaaf.core.api.IRequest; -import at.gv.egiz.eaaf.modules.pvp2.PVPConstants; +import at.gv.egiz.eaaf.modules.pvp2.PvpConstants; import at.gv.egiz.eaaf.modules.pvp2.api.binding.IDecoder; import at.gv.egiz.eaaf.modules.pvp2.api.binding.IEncoder; +import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential; import at.gv.egiz.eaaf.modules.pvp2.api.message.InboundMessageInterface; -import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IRefreshableMetadataProvider; -import at.gv.egiz.eaaf.modules.pvp2.impl.message.InboundMessage; -import at.gv.egiz.eaaf.modules.pvp2.impl.message.PVPSProfileRequest; -import at.gv.egiz.eaaf.modules.pvp2.impl.message.PVPSProfileResponse; -import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EAAFDefaultSAML2Bootstrap; -import at.gv.egiz.eaaf.modules.pvp2.impl.validation.TrustEngineFactory; -import at.gv.egiz.eaaf.modules.pvp2.impl.verification.PVPAuthRequestSignedRole; - -@Service("PVPRedirectBinding") -public class RedirectBinding implements IDecoder, IEncoder { - - private static final Logger log = LoggerFactory.getLogger(RedirectBinding.class); - - public void encodeRequest(HttpServletRequest req, HttpServletResponse resp, - RequestAbstractType request, String targetLocation, String relayState, Credential credentials, IRequest pendingReq) - throws MessageEncodingException, SecurityException { - - //load default PVP security configurations - EAAFDefaultSAML2Bootstrap.initializeDefaultPVPConfiguration(); - - log.debug("create SAML RedirectBinding response"); - - HTTPRedirectDeflateEncoder encoder = new HTTPRedirectDeflateEncoder(); - HttpServletResponseAdapter responseAdapter = new HttpServletResponseAdapter( - resp, true); - BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject> context = new BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject>(); - SingleSignOnService service = new SingleSignOnServiceBuilder() - .buildObject(); - service.setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI); - service.setLocation(targetLocation); - context.setOutboundSAMLMessageSigningCredential(credentials); - context.setPeerEntityEndpoint(service); - context.setOutboundSAMLMessage(request); - context.setOutboundMessageTransport(responseAdapter); - context.setRelayState(relayState); - - encoder.encode(context); - } - - public void encodeRespone(HttpServletRequest req, HttpServletResponse resp, - StatusResponseType response, String targetLocation, String relayState, - Credential credentials, IRequest pendingReq) throws MessageEncodingException, SecurityException { - - //load default PVP security configurations - EAAFDefaultSAML2Bootstrap.initializeDefaultPVPConfiguration(); - - log.debug("create SAML RedirectBinding response"); - - HTTPRedirectDeflateEncoder encoder = new HTTPRedirectDeflateEncoder(); - HttpServletResponseAdapter responseAdapter = new HttpServletResponseAdapter( - resp, true); - BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject> context = new BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject>(); - SingleSignOnService service = new SingleSignOnServiceBuilder() - .buildObject(); - service.setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI); - service.setLocation(targetLocation); - context.setOutboundSAMLMessageSigningCredential(credentials); - context.setPeerEntityEndpoint(service); - context.setOutboundSAMLMessage(response); - context.setOutboundMessageTransport(responseAdapter); - context.setRelayState(relayState); - - encoder.encode(context); - - } - - public InboundMessageInterface decode(HttpServletRequest req, - HttpServletResponse resp, MetadataProvider metadataProvider, boolean isSPEndPoint, URIComparator comparator) throws MessageDecodingException, - SecurityException { - - HTTPRedirectDeflateDecoder decode = new HTTPRedirectDeflateDecoder( - new BasicParserPool()); - - BasicSAMLMessageContext<SAMLObject, ?, ?> messageContext = new BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject>(); - messageContext - .setInboundMessageTransport(new HttpServletRequestAdapter(req)); - - //set metadata descriptor type - if (isSPEndPoint) { - messageContext.setPeerEntityRole(IDPSSODescriptor.DEFAULT_ELEMENT_NAME); - decode.setURIComparator(comparator); - - } else { - messageContext.setPeerEntityRole(SPSSODescriptor.DEFAULT_ELEMENT_NAME); - decode.setURIComparator(comparator); - } - - messageContext.setMetadataProvider(metadataProvider); - - SAML2HTTPRedirectDeflateSignatureRule signatureRule = new SAML2HTTPRedirectDeflateSignatureRule( - TrustEngineFactory.getSignatureKnownKeysTrustEngine(metadataProvider)); - PVPAuthRequestSignedRole signedRole = new PVPAuthRequestSignedRole(); - BasicSecurityPolicy policy = new BasicSecurityPolicy(); - policy.getPolicyRules().add(signedRole); - policy.getPolicyRules().add(signatureRule); - SecurityPolicyResolver resolver = new StaticSecurityPolicyResolver( - policy); - messageContext.setSecurityPolicyResolver(resolver); - - //set metadata descriptor type - if (isSPEndPoint) - messageContext.setPeerEntityRole(IDPSSODescriptor.DEFAULT_ELEMENT_NAME); - else - messageContext.setPeerEntityRole(SPSSODescriptor.DEFAULT_ELEMENT_NAME); - - try { - decode.decode(messageContext); - - //check signature - signatureRule.evaluate(messageContext); - - } catch (SecurityException e) { - if (StringUtils.isEmpty(messageContext.getInboundMessageIssuer())) { - throw e; - - } - - if (metadataProvider instanceof IRefreshableMetadataProvider) { - log.debug("PVP2X message validation FAILED. Reload metadata for entityID: " + messageContext.getInboundMessageIssuer()); - if (!((IRefreshableMetadataProvider) metadataProvider).refreshMetadataProvider(messageContext.getInboundMessageIssuer())) - throw e; - - else { - log.trace("PVP2X metadata reload finished. Check validate message again."); - decode.decode(messageContext); - - //check signature - signatureRule.evaluate(messageContext); - - } - log.trace("Second PVP2X message validation finished"); - - } else { - throw e; - - } - } - - InboundMessage msg = null; - if (messageContext.getInboundMessage() instanceof RequestAbstractType) { - RequestAbstractType inboundMessage = (RequestAbstractType) messageContext - .getInboundMessage(); - msg = new PVPSProfileRequest(inboundMessage, getSAML2BindingName()); - - - } else if (messageContext.getInboundMessage() instanceof StatusResponseType){ - StatusResponseType inboundMessage = (StatusResponseType) messageContext.getInboundMessage(); - msg = new PVPSProfileResponse(inboundMessage); - - } else - //create empty container if request type is unknown - msg = new InboundMessage(); - - if (messageContext.getPeerEntityMetadata() != null) - msg.setEntityID(messageContext.getPeerEntityMetadata().getEntityID()); - - else - log.info("No Metadata found for OA with EntityID " + messageContext.getInboundMessageIssuer()); - - msg.setVerified(true); - msg.setRelayState(messageContext.getRelayState()); - - return msg; - } - - public boolean handleDecode(String action, HttpServletRequest req) { - return ((action.equals(PVPConstants.REDIRECT) || action.equals(PVPConstants.SINGLELOGOUT)) - && req.getMethod().equals("GET")); - } - - public String getSAML2BindingName() { - return SAMLConstants.SAML2_REDIRECT_BINDING_URI; - } +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.exception.InvalidPvpRequestException; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlBindingException; +import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.EaafHttpRedirectDeflateDecoder; +import at.gv.egiz.eaaf.modules.pvp2.impl.verification.EaafSaml2HttpRedirectDeflateSignatureSecurityHandler; +import at.gv.egiz.eaaf.modules.pvp2.impl.verification.PvpSamlMessageHandlerChain; + +import org.opensaml.messaging.context.MessageContext; +import org.opensaml.saml.common.SAMLObject; +import org.opensaml.saml.common.binding.SAMLBindingSupport; +import org.opensaml.saml.common.binding.impl.CheckMessageVersionHandler; +import org.opensaml.saml.common.binding.security.impl.MessageLifetimeSecurityHandler; +import org.opensaml.saml.common.messaging.context.SAMLBindingContext; +import org.opensaml.saml.common.xml.SAMLConstants; +import org.opensaml.saml.saml2.binding.encoding.impl.HTTPRedirectDeflateEncoder; +import org.opensaml.saml.saml2.core.RequestAbstractType; +import org.opensaml.saml.saml2.core.StatusResponseType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import net.shibboleth.utilities.java.support.net.URIComparator; + +public class RedirectBinding extends AbstractBinding implements IDecoder, IEncoder { + + private static final Logger log = LoggerFactory.getLogger(RedirectBinding.class); + + @Override + public void encodeRequest(final HttpServletRequest req, final HttpServletResponse resp, + final RequestAbstractType request, final String targetLocation, final String relayState, + final EaafX509Credential credentials, final IRequest pendingReq) + throws Pvp2Exception { + + try { + log.debug("create SAML RedirectBinding response"); + final HTTPRedirectDeflateEncoder encoder = new HTTPRedirectDeflateEncoder(); + encoder.setHttpServletResponse(resp); + + final MessageContext<SAMLObject> messageContext = buildBasicMessageContext(encoder, request); + + // set endpoint url + messageContext.addSubcontext(injectEndpointInfos(request, targetLocation)); + + // inject signing context + messageContext.addSubcontext(injectSigningInfos(credentials)); + + // set relayState of exists + SAMLBindingSupport.setRelayState(messageContext, relayState); + + // encode message + encoder.initialize(); + encoder.encode(); + + } catch (final Exception e) { + log.warn("Can not encode SAML2 Redirect-Binding request", e); + throw new SamlBindingException("internal.pvp.95", + new Object[] { PvpConstants.REDIRECT, "encoding", e.getMessage() }, + e); + + } + + } + + @Override + public void encodeResponse(final HttpServletRequest req, final HttpServletResponse resp, + final StatusResponseType response, final String targetLocation, final String relayState, + final EaafX509Credential credentials, final IRequest pendingReq) + throws Pvp2Exception { + + try { + log.debug("create SAML RedirectBinding response"); + + final HTTPRedirectDeflateEncoder encoder = new HTTPRedirectDeflateEncoder(); + encoder.setHttpServletResponse(resp); + + final MessageContext<SAMLObject> messageContext = buildBasicMessageContext(encoder, response); + + // set endpoint url + messageContext.addSubcontext(injectEndpointInfos(response, targetLocation)); + + // inject signing context + messageContext.addSubcontext(injectSigningInfos(credentials)); + + // set relayState of exists + SAMLBindingSupport.setRelayState(messageContext, relayState); + + // encode message + encoder.initialize(); + encoder.encode(); + + } catch (final Exception e) { + log.warn("Can not encode SAML2 Redirect-Binding request", e); + throw new SamlBindingException("internal.pvp.95", + new Object[] { PvpConstants.REDIRECT, "encoding", e.getMessage() }, + e); + + } + + } + + @Override + public InboundMessageInterface decode(final HttpServletRequest req, + final HttpServletResponse resp, final IPvp2MetadataProvider metadataProvider, + QName peerEntityRole, final URIComparator comparator) + throws Pvp2Exception { + + final EaafHttpRedirectDeflateDecoder decode = new EaafHttpRedirectDeflateDecoder(req); + final MessageContext<SAMLObject> messageContext = internalMessageDecode(decode, PvpConstants.REDIRECT); + + final SAMLBindingContext bindingContext = messageContext.getSubcontext(SAMLBindingContext.class, true); + if (!bindingContext.hasBindingSignature()) { + log.info("SAML Redirect-Binding message contains no signature. Message will be rejected"); + throw new InvalidPvpRequestException("internal.pvp.02", null); + + } + + // inject informations into message context that are required for further + // processing + injectInboundMessageContexts(messageContext, metadataProvider, peerEntityRole); + final PvpSamlMessageHandlerChain messageValidatorChain = + buildMessageValidationChain(req, metadataProvider); + + log.trace("Message validation (Signature, ...) on binding-level starts ... "); + performMessageValidation(messageValidatorChain, messageContext); + + log.trace("Message validation successful"); + return performMessageDecodePostProcessing(messageContext, true); + + } + + @Override + public boolean handleDecode(final String action, final HttpServletRequest req) { + return (action.equals(PvpConstants.REDIRECT) || action.equals(PvpConstants.SINGLELOGOUT)) + && req.getMethod().equals("GET"); + } + + @Override + public String getSaml2BindingName() { + return SAMLConstants.SAML2_REDIRECT_BINDING_URI; + + } + + private PvpSamlMessageHandlerChain buildMessageValidationChain(HttpServletRequest req, + IPvp2MetadataProvider metadataProvider) { + final PvpSamlMessageHandlerChain messageValidatorChain = new PvpSamlMessageHandlerChain(); + final EaafSaml2HttpRedirectDeflateSignatureSecurityHandler redirectBindingSignaturHandler = + new EaafSaml2HttpRedirectDeflateSignatureSecurityHandler(metadataProvider); + redirectBindingSignaturHandler.setHttpServletRequest(req); + + messageValidatorChain.addHandler(new CheckMessageVersionHandler()); + messageValidatorChain.addHandler(redirectBindingSignaturHandler); + messageValidatorChain.addHandler(new MessageLifetimeSecurityHandler()); + + /* + * TODO: maybe we add it in a later version Because: - AuthnRequest replay + * should not be a problem on IDP side - Response replay will be not possible, + * because EAAF PVP implements countermeasure based on one-time tokens for each + * request + * + */ + // final MessageReplaySecurityHandler replaySecurityHandler = new + // MessageReplaySecurityHandler(); + // final StorageService replayCacheStorage = null; + // final ReplayCache replayCache = new ReplayCache(); + // replayCache.setId("Message replay cache"); + // replayCache.setStrict(true); + // replayCache.setStorage(replayCacheStorage); + // replaySecurityHandler.setReplayCache(replayCache ); + // messageValidatorChain.addHandler(replaySecurityHandler); + + return messageValidatorChain; + + } } diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/SoapBinding.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/SoapBinding.java index c70060ad..49e93f0a 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/SoapBinding.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/SoapBinding.java @@ -1,172 +1,181 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 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: + * Licensed under the EUPL, Version 1.2 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: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * 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.egiz.eaaf.modules.pvp2.impl.binding; + * 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. +*/ -import java.util.List; +package at.gv.egiz.eaaf.modules.pvp2.impl.binding; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.lang3.StringUtils; -import org.opensaml.common.SAMLObject; -import org.opensaml.common.binding.BasicSAMLMessageContext; -import org.opensaml.common.binding.decoding.URIComparator; -import org.opensaml.common.xml.SAMLConstants; -import org.opensaml.saml2.binding.encoding.HTTPSOAP11Encoder; -import org.opensaml.saml2.core.RequestAbstractType; -import org.opensaml.saml2.core.StatusResponseType; -import org.opensaml.saml2.metadata.SPSSODescriptor; -import org.opensaml.saml2.metadata.provider.MetadataProvider; -import org.opensaml.ws.message.decoder.MessageDecodingException; -import org.opensaml.ws.message.encoder.MessageEncodingException; -import org.opensaml.ws.soap.soap11.Envelope; -import org.opensaml.ws.soap.soap11.decoder.http.HTTPSOAP11Decoder; -import org.opensaml.ws.transport.http.HttpServletRequestAdapter; -import org.opensaml.ws.transport.http.HttpServletResponseAdapter; -import org.opensaml.xml.XMLObject; -import org.opensaml.xml.parse.BasicParserPool; -import org.opensaml.xml.security.SecurityException; -import org.opensaml.xml.security.credential.Credential; -import org.opensaml.xml.signature.SignableXMLObject; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Service; +import javax.xml.namespace.QName; import at.gv.egiz.eaaf.core.api.IRequest; -import at.gv.egiz.eaaf.modules.pvp2.PVPConstants; +import at.gv.egiz.eaaf.modules.pvp2.PvpConstants; import at.gv.egiz.eaaf.modules.pvp2.api.binding.IDecoder; import at.gv.egiz.eaaf.modules.pvp2.api.binding.IEncoder; +import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential; import at.gv.egiz.eaaf.modules.pvp2.api.message.InboundMessageInterface; -import at.gv.egiz.eaaf.modules.pvp2.exception.AttributQueryException; -import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception; -import at.gv.egiz.eaaf.modules.pvp2.impl.message.PVPSProfileRequest; -import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EAAFDefaultSAML2Bootstrap; - -@Service("PVPSOAPBinding") -public class SoapBinding implements IDecoder, IEncoder { - - private static final Logger log = LoggerFactory.getLogger(SoapBinding.class); - public InboundMessageInterface decode(HttpServletRequest req, - HttpServletResponse resp, MetadataProvider metadataProvider, boolean isSPEndPoint, URIComparator comparator) throws MessageDecodingException, - SecurityException, PVP2Exception { - HTTPSOAP11Decoder soapDecoder = new HTTPSOAP11Decoder(new BasicParserPool()); - BasicSAMLMessageContext<SAMLObject, ?, ?> messageContext = - new BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject>(); - messageContext - .setInboundMessageTransport(new HttpServletRequestAdapter( - req)); - messageContext.setMetadataProvider(metadataProvider); - - //TODO: update in a futher version: - // requires a special SignedSOAPRequestPolicyRole because - // messageContext.getInboundMessage() is not directly signed - - //set security context -// BasicSecurityPolicy policy = new BasicSecurityPolicy(); -// policy.getPolicyRules().add( -// new MOAPVPSignedRequestPolicyRule( -// TrustEngineFactory.getSignatureKnownKeysTrustEngine(), -// SPSSODescriptor.DEFAULT_ELEMENT_NAME)); -// SecurityPolicyResolver resolver = new StaticSecurityPolicyResolver( -// policy); -// messageContext.setSecurityPolicyResolver(resolver); - - //decode message - soapDecoder.decode(messageContext); - - Envelope inboundMessage = (Envelope) messageContext - .getInboundMessage(); - - if (inboundMessage.getBody() != null) { - List<XMLObject> xmlElemList = inboundMessage.getBody().getUnknownXMLObjects(); - - if (!xmlElemList.isEmpty()) { - SignableXMLObject attrReq = (SignableXMLObject) xmlElemList.get(0); - PVPSProfileRequest request = new PVPSProfileRequest(attrReq, getSAML2BindingName()); - - if (messageContext.getPeerEntityMetadata() != null) - request.setEntityID(messageContext.getPeerEntityMetadata().getEntityID()); - - else if (attrReq instanceof RequestAbstractType) { - RequestAbstractType attributeRequest = (RequestAbstractType) attrReq; - try { - if (StringUtils.isNotEmpty(attributeRequest.getIssuer().getValue()) && - metadataProvider.getRole( - attributeRequest.getIssuer().getValue(), - SPSSODescriptor.DEFAULT_ELEMENT_NAME) != null) - request.setEntityID(attributeRequest.getIssuer().getValue()); - - } catch (Exception e) { - log.warn("No Metadata found with EntityID " + attributeRequest.getIssuer().getValue()); - } - } - - request.setVerified(false); - return request; - - } - } - - log.error("Receive empty PVP 2.1 attributequery request."); - throw new AttributQueryException("Receive empty PVP 2.1 attributequery request.", null); - } - - public boolean handleDecode(String action, HttpServletRequest req) { - return (req.getMethod().equals("POST") && - (action.equals(PVPConstants.SOAP) || action.equals(PVPConstants.ATTRIBUTEQUERY))); - } - - public void encodeRequest(HttpServletRequest req, HttpServletResponse resp, - RequestAbstractType request, String targetLocation, String relayState, Credential credentials, IRequest pendingReq) - throws MessageEncodingException, SecurityException, PVP2Exception { - - } - - public void encodeRespone(HttpServletRequest req, HttpServletResponse resp, - StatusResponseType response, String targetLocation, String relayState, Credential credentials, IRequest pendingReq) - throws MessageEncodingException, SecurityException, PVP2Exception { - - //load default PVP security configurations - EAAFDefaultSAML2Bootstrap.initializeDefaultPVPConfiguration(); - - HTTPSOAP11Encoder encoder = new HTTPSOAP11Encoder(); - HttpServletResponseAdapter responseAdapter = new HttpServletResponseAdapter( - resp, true); - BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject> context = new BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject>(); - context.setOutboundSAMLMessageSigningCredential(credentials); - context.setOutboundSAMLMessage(response); - context.setOutboundMessageTransport(responseAdapter); - - encoder.encode(context); - - } - - public String getSAML2BindingName() { - return SAMLConstants.SAML2_SOAP11_BINDING_URI; - } +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.exception.InvalidPvpRequestException; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2InternalErrorException; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlBindingException; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils; +import at.gv.egiz.eaaf.modules.pvp2.impl.verification.EaafMessageContextInitializationHandler; +import at.gv.egiz.eaaf.modules.pvp2.impl.verification.EaafSamlProtocolMessageXmlSignatureSecurityHandler; +import at.gv.egiz.eaaf.modules.pvp2.impl.verification.PvpSamlMessageHandlerChain; + +import org.opensaml.messaging.context.MessageContext; +import org.opensaml.saml.common.SAMLObject; +import org.opensaml.saml.common.binding.SAMLBindingSupport; +import org.opensaml.saml.common.binding.impl.CheckMessageVersionHandler; +import org.opensaml.saml.common.binding.impl.SAMLProtocolAndRoleHandler; +import org.opensaml.saml.common.binding.impl.SAMLSOAPDecoderBodyHandler; +import org.opensaml.saml.common.binding.security.impl.MessageLifetimeSecurityHandler; +import org.opensaml.saml.common.messaging.SAMLMessageSecuritySupport; +import org.opensaml.saml.common.xml.SAMLConstants; +import org.opensaml.saml.saml2.binding.decoding.impl.HTTPSOAP11Decoder; +import org.opensaml.saml.saml2.binding.encoding.impl.HTTPSOAP11Encoder; +import org.opensaml.saml.saml2.core.RequestAbstractType; +import org.opensaml.saml.saml2.core.StatusResponseType; +import org.opensaml.soap.messaging.context.SOAP11Context; + +import lombok.extern.slf4j.Slf4j; +import net.shibboleth.utilities.java.support.component.ComponentInitializationException; +import net.shibboleth.utilities.java.support.net.URIComparator; + +@Slf4j +public class SoapBinding extends AbstractBinding implements IDecoder, IEncoder { + + @Override + public InboundMessageInterface decode(final HttpServletRequest req, + final HttpServletResponse resp, final IPvp2MetadataProvider metadataProvider, + QName peerEntityRole, final URIComparator comparator) + throws Pvp2Exception { + + final HTTPSOAP11Decoder soapDecoder = new HTTPSOAP11Decoder(); + soapDecoder.setHttpServletRequest(req); + + injectMessageHandlerChain(soapDecoder, metadataProvider, peerEntityRole); + + final MessageContext<SAMLObject> messageContext = + internalMessageDecode(soapDecoder, PvpConstants.SOAP); + + // check if PVP2 AuthnRequest is signed + if (!SAMLBindingSupport.isMessageSigned(messageContext)) { + log.info("SAML Post-Binding message contains no signature. Message will be rejected"); + throw new InvalidPvpRequestException("internal.pvp.02", null); + + } + + return performMessageDecodePostProcessing(messageContext, true); + } + + private void injectMessageHandlerChain(HTTPSOAP11Decoder soapDecoder, + IPvp2MetadataProvider metadataProvider, QName peerEntityRole) throws Pvp2InternalErrorException { + try { + final PvpSamlMessageHandlerChain messageValidatorChain = new PvpSamlMessageHandlerChain(); + messageValidatorChain.addHandler(new EaafMessageContextInitializationHandler(metadataProvider)); + messageValidatorChain.addHandler(new SAMLSOAPDecoderBodyHandler()); + + final SAMLProtocolAndRoleHandler samlProtocolHandler = new SAMLProtocolAndRoleHandler(); + samlProtocolHandler.setProtocol(SAMLConstants.SAML20P_NS); + samlProtocolHandler.setRole(peerEntityRole); + messageValidatorChain.addHandler(samlProtocolHandler); + + messageValidatorChain.addHandler(new CheckMessageVersionHandler()); + messageValidatorChain.addHandler( + new EaafSamlProtocolMessageXmlSignatureSecurityHandler(metadataProvider)); + messageValidatorChain.addHandler(new MessageLifetimeSecurityHandler()); + + messageValidatorChain.initialize(); + + soapDecoder.setBodyHandler(messageValidatorChain); + + } catch (final ComponentInitializationException e) { + log.warn("Internal initialization error. Reason: {}", e.getMessage()); + throw new Pvp2InternalErrorException(e); + + } + + + } + + @Override + public boolean handleDecode(final String action, final HttpServletRequest req) { + return req.getMethod().equals("POST") + && action.equals(PvpConstants.SOAP) || action.equals(PvpConstants.ATTRIBUTEQUERY); + } + + @Override + public void encodeRequest(final HttpServletRequest req, final HttpServletResponse resp, + final RequestAbstractType request, final String targetLocation, final String relayState, + final EaafX509Credential credentials, final IRequest pendingReq) + throws Pvp2Exception { + throw new RuntimeException("Method not supported!!!"); + + } + + @Override + public void encodeResponse(final HttpServletRequest req, final HttpServletResponse resp, + final StatusResponseType response, final String targetLocation, final String relayState, + final EaafX509Credential credentials, final IRequest pendingReq) + throws Pvp2Exception { + + try { + final HTTPSOAP11Encoder encoder = new HTTPSOAP11Encoder(); + encoder.setHttpServletResponse(resp); + + // inject message context + final MessageContext<SAMLObject> messageContext = buildBasicMessageContext(encoder, response); + + //inject SOAP enveloped + final SOAP11Context soap11Context = new SOAP11Context(); + soap11Context.setEnvelope(Saml2Utils.buildSoap11Envelope(response)); + messageContext.addSubcontext(soap11Context); + + // inject signing context + messageContext.addSubcontext(injectSigningInfos(credentials)); + + // set endpoint url + messageContext.addSubcontext(injectEndpointInfos(response, targetLocation)); + + // set relayState of exists + SAMLBindingSupport.setRelayState(messageContext, relayState); + + // sign SAML2 message + SAMLMessageSecuritySupport.signMessage(messageContext); + + // encode message + encoder.initialize(); + encoder.encode(); + + } catch (final Exception e) { + log.warn("Can not encode SAML2 SOAP-Binding response", e); + throw new SamlBindingException("internal.pvp.95", + new Object[] { PvpConstants.SOAP, "encoding", e.getMessage() }, + e); + + } + } + + @Override + public String getSaml2BindingName() { + return SAMLConstants.SAML2_SOAP11_BINDING_URI; + } } diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/CitizenTokenBuilder.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/CitizenTokenBuilder.java index c38b04bd..bf201803 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/CitizenTokenBuilder.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/CitizenTokenBuilder.java @@ -1,121 +1,148 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 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: + * Licensed under the EUPL, Version 1.2 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: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * 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. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * 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.egiz.eaaf.modules.pvp2.impl.builder; -import org.opensaml.saml2.core.Attribute; -import org.opensaml.saml2.core.AttributeValue; -import org.opensaml.xml.Configuration; -import org.opensaml.xml.XMLObject; -import org.opensaml.xml.schema.XSInteger; -import org.opensaml.xml.schema.XSString; -import org.opensaml.xml.schema.impl.XSIntegerBuilder; -import org.opensaml.xml.schema.impl.XSStringBuilder; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils; -import at.gv.egiz.eaaf.modules.pvp2.impl.utils.SAML2Utils; +import org.opensaml.core.xml.XMLObject; +import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport; +import org.opensaml.core.xml.schema.XSInteger; +import org.opensaml.core.xml.schema.XSString; +import org.opensaml.core.xml.schema.impl.XSIntegerBuilder; +import org.opensaml.core.xml.schema.impl.XSStringBuilder; +import org.opensaml.saml.saml2.core.Attribute; +import org.opensaml.saml.saml2.core.AttributeValue; +/** + * Build all attributes from PVP2 citizen-token. + * + * @author tlenz + * + */ public class CitizenTokenBuilder { - public static XMLObject buildAttributeStringValue(String value) { - XSStringBuilder stringBuilder = (XSStringBuilder) Configuration.getBuilderFactory().getBuilder(XSString.TYPE_NAME); - XSString stringValue = stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, XSString.TYPE_NAME); - stringValue.setValue(value); - return stringValue; - } - - public static XMLObject buildAttributeIntegerValue(int value) { - XSIntegerBuilder integerBuilder = (XSIntegerBuilder) Configuration.getBuilderFactory().getBuilder(XSInteger.TYPE_NAME); - XSInteger integerValue = integerBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, XSInteger.TYPE_NAME); - integerValue.setValue(value); - return integerValue; - } - - public static Attribute buildStringAttribute(String friendlyName, - String name, String value) { - Attribute attribute = - SAML2Utils.createSAMLObject(Attribute.class); - attribute.setFriendlyName(friendlyName); - attribute.setName(name); - attribute.getAttributeValues().add(buildAttributeStringValue(value)); - return attribute; - } - - public static Attribute buildIntegerAttribute(String friendlyName, - String name, int value) { - Attribute attribute = - SAML2Utils.createSAMLObject(Attribute.class); - attribute.setFriendlyName(friendlyName); - attribute.setName(name); - attribute.getAttributeValues().add(buildAttributeIntegerValue(value)); - return attribute; - } - - public static Attribute buildPVPVersion(String value) { - return buildStringAttribute("PVP-VERSION", - "urn:oid:1.2.40.0.10.2.1.1.261.10", value); - } - - public static Attribute buildSecClass(int value) { - return buildIntegerAttribute("SECCLASS", - "", value); - } - - public static Attribute buildPrincipalName(String value) { - return buildStringAttribute("PRINCIPAL-NAME", - "urn:oid:1.2.40.0.10.2.1.1.261.20", value); - } - - public static Attribute buildGivenName(String value) { - return buildStringAttribute("GIVEN-NAME", - "urn:oid:2.5.4.42", value); - } - - public static Attribute buildBirthday(String value) { - return buildStringAttribute("BIRTHDATE", - "urn:oid:1.2.40.0.10.2.1.1.55", value); - } - - public static Attribute buildBPK(String value) { - return buildStringAttribute("BPK", - "urn:oid:1.2.40.0.10.2.1.1.149", value); - } - - public static Attribute buildEID_CITIZEN_QAALEVEL(int value) { - return buildIntegerAttribute("EID-CITIZEN-QAA-LEVEL", - "urn:oid:1.2.40.0.10.2.1.1.261.94", value); - } - - public static Attribute buildEID_ISSUING_NATION(String value) { - return buildStringAttribute("EID-ISSUING-NATION", - "urn:oid:1.2.40.0.10.2.1.1.261.32", value); - } - - public static Attribute buildEID_SECTOR_FOR_IDENTIFIER(String value) { - return buildStringAttribute("EID-SECTOR-FOR-IDENTIFIER", - "urn:oid:1.2.40.0.10.2.1.1.261.34", value); - } - + /** + * Build simple attribute. + * + * @param value Attributevalue + * @return XML attribute + */ + public static XMLObject buildAttributeStringValue(final String value) { + final XSStringBuilder stringBuilder = + (XSStringBuilder) XMLObjectProviderRegistrySupport.getBuilderFactory().getBuilder(XSString.TYPE_NAME); + final XSString stringValue = + stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, XSString.TYPE_NAME); + stringValue.setValue(value); + return stringValue; + } + + /** + * Build simple attribute. + * + * @param value Attributevalue + * @return XML attribute + */ + public static XMLObject buildAttributeIntegerValue(final int value) { + final XSIntegerBuilder integerBuilder = + (XSIntegerBuilder) XMLObjectProviderRegistrySupport.getBuilderFactory().getBuilder( + XSInteger.TYPE_NAME); + final XSInteger integerValue = + integerBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, XSInteger.TYPE_NAME); + integerValue.setValue(value); + return integerValue; + } + + /** + * Build simple attribute. + * + * @param friendlyName attribute friendly-name + * @param value Attributevalue + * @return XML attribute + */ + public static Attribute buildStringAttribute(final String friendlyName, final String name, + final String value) { + final Attribute attribute = Saml2Utils.createSamlObject(Attribute.class); + attribute.setFriendlyName(friendlyName); + attribute.setName(name); + attribute.getAttributeValues().add(buildAttributeStringValue(value)); + return attribute; + } + + /** + * Build simple attribute. + * + * @param friendlyName attribute friendly-name + * @param value Attributevalue + * @return XML attribute + */ + public static Attribute buildIntegerAttribute(final String friendlyName, final String name, + final int value) { + final Attribute attribute = Saml2Utils.createSamlObject(Attribute.class); + attribute.setFriendlyName(friendlyName); + attribute.setName(name); + attribute.getAttributeValues().add(buildAttributeIntegerValue(value)); + return attribute; + } + + /** + * Build PVP version attribute. + * + * @param value PVP Version + * @return SAML2 Attribute + */ + public static Attribute buildPvpVersion(final String value) { + return buildStringAttribute("PVP-VERSION", "urn:oid:1.2.40.0.10.2.1.1.261.10", value); + } + + public static Attribute buildSecClass(final int value) { + return buildIntegerAttribute("SECCLASS", "", value); + } + + public static Attribute buildPrincipalName(final String value) { + return buildStringAttribute("PRINCIPAL-NAME", "urn:oid:1.2.40.0.10.2.1.1.261.20", value); + } + + public static Attribute buildGivenName(final String value) { + return buildStringAttribute("GIVEN-NAME", "urn:oid:2.5.4.42", value); + } + + public static Attribute buildBirthday(final String value) { + return buildStringAttribute("BIRTHDATE", "urn:oid:1.2.40.0.10.2.1.1.55", value); + } + + public static Attribute buildBpk(final String value) { + return buildStringAttribute("BPK", "urn:oid:1.2.40.0.10.2.1.1.149", value); + } + + public static Attribute buildEid_Citizen_QaaLevel(final int value) { + return buildIntegerAttribute("EID-CITIZEN-QAA-LEVEL", "urn:oid:1.2.40.0.10.2.1.1.261.94", + value); + } + + public static Attribute buildEid_Issuing_Nation(final String value) { + return buildStringAttribute("EID-ISSUING-NATION", "urn:oid:1.2.40.0.10.2.1.1.261.32", value); + } + + public static Attribute buildEid_Sector_For_Identifier(final String value) { + return buildStringAttribute("EID-SECTOR-FOR-IDENTIFIER", "urn:oid:1.2.40.0.10.2.1.1.261.34", + value); + } + } diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/PVPAttributeBuilder.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/PVPAttributeBuilder.java deleted file mode 100644 index 0d9e38e0..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/PVPAttributeBuilder.java +++ /dev/null @@ -1,221 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.impl.builder; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.ServiceLoader; - -import org.opensaml.saml2.core.Attribute; -import org.opensaml.saml2.metadata.RequestedAttribute; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder; -import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator; -import at.gv.egiz.eaaf.core.api.idp.IAuthData; -import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration; -import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; -import at.gv.egiz.eaaf.core.exceptions.InvalidDateFormatAttributeException; -import at.gv.egiz.eaaf.core.exceptions.UnavailableAttributeException; -import at.gv.egiz.eaaf.core.impl.idp.builder.attributes.PVPMETADATA; -import at.gv.egiz.eaaf.modules.pvp2.exception.InvalidDateFormatException; -import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception; -import at.gv.egiz.eaaf.modules.pvp2.impl.utils.SAML2Utils; - -public class PVPAttributeBuilder { - - private static final Logger log = LoggerFactory.getLogger(PVPAttributeBuilder.class); - - private static IAttributeGenerator<Attribute> generator = new SamlAttributeGenerator(); - private static HashMap<String, IAttributeBuilder> builders; - - private static ServiceLoader<IAttributeBuilder> attributBuilderLoader = - ServiceLoader.load(IAttributeBuilder.class); - - private static void addBuilder(IAttributeBuilder builder) { - builders.put(builder.getName(), builder); - } - - static { - builders = new HashMap<String, IAttributeBuilder>(); - - log.info("Loading protocol attribut-builder modules:"); - if (attributBuilderLoader != null ) { - Iterator<IAttributeBuilder> moduleLoaderInterator = attributBuilderLoader.iterator(); - while (moduleLoaderInterator.hasNext()) { - try { - IAttributeBuilder modul = moduleLoaderInterator.next(); - log.info("Loading attribut-builder Modul Information: " + modul.getName()); - addBuilder(modul); - - } catch(Throwable e) { - log.error("Check configuration! " + "Some attribute-builder modul" + - " is not a valid IAttributeBuilder", e); - } - } - } - - log.info("Loading attribute-builder modules done"); - - } - - - /** - * Get a specific attribute builder - * - * @param name Attribute-builder friendly name - * - * @return Attribute-builder with this name or null if builder does not exists - */ - public static IAttributeBuilder getAttributeBuilder(String name) { - return builders.get(name); - - } - - public static Attribute buildAttribute(String name, ISPConfiguration oaParam, - IAuthData authData) throws PVP2Exception, AttributeBuilderException { - if (builders.containsKey(name)) { - try { - return builders.get(name).build(oaParam, authData, generator); - } - catch (AttributeBuilderException e) { - if (e instanceof UnavailableAttributeException) { - throw e; - - } else if (e instanceof InvalidDateFormatAttributeException) { - throw new InvalidDateFormatException(); - - } else { - throw new UnavailableAttributeException(name); - - } - } - } - return null; - } - - public static Attribute buildEmptyAttribute(String name) { - if (builders.containsKey(name)) { - return builders.get(name).buildEmpty(generator); - } - return null; - } - - public static Attribute buildAttribute(String name, String value) { - if (builders.containsKey(name)) { - return builders.get(name).buildEmpty(generator); - } - return null; - } - - - /** - * Return all attributes that has a {@link PVPMETADATA} annotation - * - * @return - */ - public static List<Attribute> buildSupportedEmptyAttributes() { - List<Attribute> attributes = new ArrayList<Attribute>(); - Iterator<IAttributeBuilder> builderIt = builders.values().iterator(); - while (builderIt.hasNext()) { - IAttributeBuilder builder = builderIt.next(); - if (builder.getClass().isAnnotationPresent(PVPMETADATA.class)) { - Attribute emptyAttribute = builder.buildEmpty(generator); - if (emptyAttribute != null) { - attributes.add(emptyAttribute); - } - - } else { - log.trace(builder.getName() + "is no PVP Metadata attribute"); - - } - } - return attributes; - } - - public static RequestedAttribute buildReqAttribute(String name, String friendlyName, boolean required) { - RequestedAttribute attribute = SAML2Utils.createSAMLObject(RequestedAttribute.class); - attribute.setIsRequired(required); - attribute.setName(name); - attribute.setFriendlyName(friendlyName); - attribute.setNameFormat(Attribute.URI_REFERENCE); - return attribute; - } - - /** - * Build a set of PVP Response-Attributes - * <br><br> - * <b>INFO:</b> If a specific attribute can not be build, a info is logged, but no execpetion is thrown. - * Therefore, the return List must not include all requested attributes. - * - * @param authData AuthenticationData <code>IAuthData</code> which is used to build the attribute values, but never <code>null</code> - * @param reqAttributenName List of PVP attribute names which are requested, but never <code>null</code> - * @return List of PVP attributes, but never <code>null</code> - */ - public static List<Attribute> buildSetOfResponseAttributes(IAuthData authData, - Collection<String> reqAttributenName) { - List<Attribute> attrList = new ArrayList<Attribute>(); - if (reqAttributenName != null) { - Iterator<String> it = reqAttributenName.iterator(); - while (it.hasNext()) { - String reqAttributName = it.next(); - try { - Attribute attr = PVPAttributeBuilder.buildAttribute( - reqAttributName, null, authData); - if (attr == null) { - log.info( - "Attribute generation failed! for " - + reqAttributName); - - } else { - attrList.add(attr); - - } - - } catch (PVP2Exception e) { - log.info( - "Attribute generation failed! for " - + reqAttributName); - - } catch (Exception e) { - log.warn( - "General Attribute generation failed! for " - + reqAttributName, e); - - } - } - } - - return attrList; - } - - -} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/PVPMetadataBuilder.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/PVPMetadataBuilder.java deleted file mode 100644 index 61c6006b..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/PVPMetadataBuilder.java +++ /dev/null @@ -1,450 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.impl.builder; - -import java.io.IOException; -import java.io.StringWriter; -import java.util.Collection; -import java.util.List; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerException; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.TransformerFactoryConfigurationError; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.stream.StreamResult; - -import org.apache.commons.httpclient.auth.CredentialsNotAvailableException; -import org.apache.commons.lang3.StringUtils; -import org.joda.time.DateTime; -import org.opensaml.Configuration; -import org.opensaml.common.xml.SAMLConstants; -import org.opensaml.saml2.metadata.AssertionConsumerService; -import org.opensaml.saml2.metadata.AttributeConsumingService; -import org.opensaml.saml2.metadata.ContactPerson; -import org.opensaml.saml2.metadata.EntitiesDescriptor; -import org.opensaml.saml2.metadata.EntityDescriptor; -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.RequestedAttribute; -import org.opensaml.saml2.metadata.RoleDescriptor; -import org.opensaml.saml2.metadata.SPSSODescriptor; -import org.opensaml.saml2.metadata.ServiceName; -import org.opensaml.saml2.metadata.SingleLogoutService; -import org.opensaml.saml2.metadata.SingleSignOnService; -import org.opensaml.xml.io.Marshaller; -import org.opensaml.xml.io.MarshallingException; -import org.opensaml.xml.security.SecurityException; -import org.opensaml.xml.security.SecurityHelper; -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.Signature; -import org.opensaml.xml.signature.SignatureException; -import org.opensaml.xml.signature.Signer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Service; -import org.w3c.dom.Document; - -import at.gv.egiz.eaaf.core.exceptions.EAAFException; -import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPVPMetadataBuilderConfiguration; -import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EAAFDefaultSAML2Bootstrap; -import at.gv.egiz.eaaf.modules.pvp2.impl.utils.AbstractCredentialProvider; -import at.gv.egiz.eaaf.modules.pvp2.impl.utils.SAML2Utils; - -/** - * @author tlenz - * - */ - -@Service("PVPMetadataBuilder") -public class PVPMetadataBuilder { - - private static final Logger log = LoggerFactory.getLogger(PVPMetadataBuilder.class); - - X509KeyInfoGeneratorFactory keyInfoFactory = null; - - /** - * - */ - public PVPMetadataBuilder() { - keyInfoFactory = new X509KeyInfoGeneratorFactory(); - keyInfoFactory.setEmitEntityIDAsKeyName(true); - keyInfoFactory.setEmitEntityCertificate(true); - - } - - - /** - * - * Build PVP 2.1 conform SAML2 metadata - * - * @param config - * PVPMetadataBuilder configuration - * - * @return PVP metadata as XML String - * @throws SecurityException - * @throws ConfigurationException - * @throws CredentialsNotAvailableException - * @throws TransformerFactoryConfigurationError - * @throws MarshallingException - * @throws TransformerException - * @throws ParserConfigurationException - * @throws IOException - * @throws SignatureException - */ - public String buildPVPMetadata(IPVPMetadataBuilderConfiguration config) throws CredentialsNotAvailableException, EAAFException, SecurityException, TransformerFactoryConfigurationError, MarshallingException, TransformerException, ParserConfigurationException, IOException, SignatureException { - DateTime date = new DateTime(); - EntityDescriptor entityDescriptor = SAML2Utils - .createSAMLObject(EntityDescriptor.class); - - //set entityID - entityDescriptor.setEntityID(config.getEntityID()); - - //set contact and organisation information - List<ContactPerson> contactPersons = config.getContactPersonInformation(); - if (contactPersons != null) - entityDescriptor.getContactPersons().addAll(contactPersons); - - Organization organisation = config.getOrgansiationInformation(); - if (organisation != null) - entityDescriptor.setOrganization(organisation); - - //set IDP metadata - if (config.buildIDPSSODescriptor()) { - RoleDescriptor idpSSODesc = generateIDPMetadata(config); - if (idpSSODesc != null) - entityDescriptor.getRoleDescriptors().add(idpSSODesc); - - } - - //set SP metadata for interfederation - if (config.buildSPSSODescriptor()) { - RoleDescriptor spSSODesc = generateSPMetadata(config); - if (spSSODesc != null) - entityDescriptor.getRoleDescriptors().add(spSSODesc); - - } - - //set metadata signature parameters - Credential metadataSignCred = config.getMetadataSigningCredentials(); - Signature signature = AbstractCredentialProvider.getIDPSignature(metadataSignCred); - SecurityHelper.prepareSignatureParams(signature, metadataSignCred, null, null); - - //initialize XML document builder - DocumentBuilder builder; - DocumentBuilderFactory factory = DocumentBuilderFactory - .newInstance(); - - builder = factory.newDocumentBuilder(); - Document document = builder.newDocument(); - - - //build entities descriptor - if (config.buildEntitiesDescriptorAsRootElement()) { - EntitiesDescriptor entitiesDescriptor = - SAML2Utils.createSAMLObject(EntitiesDescriptor.class); - entitiesDescriptor.setName(config.getEntityFriendlyName()); - entitiesDescriptor.setID(SAML2Utils.getSecureIdentifier()); - entitiesDescriptor.setValidUntil(date.plusHours(config.getMetadataValidUntil())); - entitiesDescriptor.getEntityDescriptors().add(entityDescriptor); - - //load default PVP security configurations - EAAFDefaultSAML2Bootstrap.initializeDefaultPVPConfiguration(); - entitiesDescriptor.setSignature(signature); - - - //marshall document - Marshaller out = Configuration.getMarshallerFactory() - .getMarshaller(entitiesDescriptor); - out.marshall(entitiesDescriptor, document); - - } else { - entityDescriptor.setValidUntil(date.plusHours(config.getMetadataValidUntil())); - entityDescriptor.setID(SAML2Utils.getSecureIdentifier()); - - entityDescriptor.setSignature(signature); - - - - //marshall document - Marshaller out = Configuration.getMarshallerFactory() - .getMarshaller(entityDescriptor); - out.marshall(entityDescriptor, document); - - } - - //sign metadata - Signer.signObject(signature); - - //transform metadata object to XML string - Transformer transformer = TransformerFactory.newInstance() - .newTransformer(); - - StringWriter sw = new StringWriter(); - StreamResult sr = new StreamResult(sw); - DOMSource source = new DOMSource(document); - transformer.transform(source, sr); - sw.close(); - - return sw.toString(); - } - - - private RoleDescriptor generateSPMetadata(IPVPMetadataBuilderConfiguration config) throws CredentialsNotAvailableException, SecurityException, EAAFException { - SPSSODescriptor spSSODescriptor = SAML2Utils.createSAMLObject(SPSSODescriptor.class); - spSSODescriptor.addSupportedProtocol(SAMLConstants.SAML20P_NS); - spSSODescriptor.setAuthnRequestsSigned(config.wantAuthnRequestSigned()); - spSSODescriptor.setWantAssertionsSigned(config.wantAssertionSigned()); - - KeyInfoGenerator keyInfoGenerator = keyInfoFactory.newInstance(); - - //Set AuthRequest Signing certificate - Credential authcredential = config.getRequestorResponseSigningCredentials(); - if (authcredential == null) { - log.warn("SP Metadata generation FAILED! --> Builder has NO request signing-credential. "); - return null; - - } else { - KeyDescriptor signKeyDescriptor = SAML2Utils - .createSAMLObject(KeyDescriptor.class); - signKeyDescriptor.setUse(UsageType.SIGNING); - signKeyDescriptor.setKeyInfo(keyInfoGenerator.generate(authcredential)); - spSSODescriptor.getKeyDescriptors().add(signKeyDescriptor); - - } - - //Set assertion encryption credentials - Credential authEncCredential = config.getEncryptionCredentials(); - - if (authEncCredential != null) { - KeyDescriptor encryKeyDescriptor = SAML2Utils - .createSAMLObject(KeyDescriptor.class); - encryKeyDescriptor.setUse(UsageType.ENCRYPTION); - encryKeyDescriptor.setKeyInfo(keyInfoGenerator.generate(authEncCredential)); - spSSODescriptor.getKeyDescriptors().add(encryKeyDescriptor); - - } else { - log.warn("No Assertion Encryption-Key defined. This setting is not recommended!"); - - } - - //check nameID formates - if (config.getSPAllowedNameITTypes() == null || config.getSPAllowedNameITTypes().size() == 0) { - log.warn("SP Metadata generation FAILED! --> Builder has NO provideable SAML2 nameIDFormats. "); - return null; - - } else { - for (String format : config.getSPAllowedNameITTypes()) { - NameIDFormat nameIDFormat = SAML2Utils.createSAMLObject(NameIDFormat.class); - nameIDFormat.setFormat(format); - spSSODescriptor.getNameIDFormats().add(nameIDFormat); - - } - } - - - //add POST-Binding assertion consumer services - if (StringUtils.isNotEmpty(config.getSPAssertionConsumerServicePostBindingURL())) { - AssertionConsumerService postassertionConsumerService = SAML2Utils.createSAMLObject(AssertionConsumerService.class); - postassertionConsumerService.setIndex(0); - postassertionConsumerService.setBinding(SAMLConstants.SAML2_POST_BINDING_URI); - postassertionConsumerService.setLocation(config.getSPAssertionConsumerServicePostBindingURL()); - postassertionConsumerService.setIsDefault(true); - spSSODescriptor.getAssertionConsumerServices().add(postassertionConsumerService); - - } - - //add POST-Binding assertion consumer services - if (StringUtils.isNotEmpty(config.getSPAssertionConsumerServiceRedirectBindingURL())) { - AssertionConsumerService redirectassertionConsumerService = SAML2Utils.createSAMLObject(AssertionConsumerService.class); - redirectassertionConsumerService.setIndex(1); - redirectassertionConsumerService.setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI); - redirectassertionConsumerService.setLocation(config.getSPAssertionConsumerServiceRedirectBindingURL()); - spSSODescriptor.getAssertionConsumerServices().add(redirectassertionConsumerService); - - } - - //validate WebSSO endpoints - if (spSSODescriptor.getAssertionConsumerServices().size() == 0) { - log.warn("SP Metadata generation FAILED! --> NO SAML2 AssertionConsumerService endpoint found. "); - return null; - - } - - //add POST-Binding SLO descriptor - if (StringUtils.isNotEmpty(config.getSPSLOPostBindingURL())) { - SingleLogoutService postSLOService = SAML2Utils.createSAMLObject(SingleLogoutService.class); - postSLOService.setLocation(config.getSPSLOPostBindingURL()); - postSLOService.setBinding(SAMLConstants.SAML2_POST_BINDING_URI); - spSSODescriptor.getSingleLogoutServices().add(postSLOService); - - } - - //add POST-Binding SLO descriptor - if (StringUtils.isNotEmpty(config.getSPSLORedirectBindingURL())) { - SingleLogoutService redirectSLOService = SAML2Utils.createSAMLObject(SingleLogoutService.class); - redirectSLOService.setLocation(config.getSPSLORedirectBindingURL()); - redirectSLOService.setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI); - spSSODescriptor.getSingleLogoutServices().add(redirectSLOService); - - } - - //add POST-Binding SLO descriptor - if (StringUtils.isNotEmpty(config.getSPSLOSOAPBindingURL())) { - SingleLogoutService soapSLOService = SAML2Utils.createSAMLObject(SingleLogoutService.class); - soapSLOService.setLocation(config.getSPSLOSOAPBindingURL()); - soapSLOService.setBinding(SAMLConstants.SAML2_SOAP11_BINDING_URI); - spSSODescriptor.getSingleLogoutServices().add(soapSLOService); - - } - - - //add required attributes - Collection<RequestedAttribute> reqSPAttr = config.getSPRequiredAttributes(); - AttributeConsumingService attributeService = SAML2Utils.createSAMLObject(AttributeConsumingService.class); - - attributeService.setIndex(0); - attributeService.setIsDefault(true); - ServiceName serviceName = SAML2Utils.createSAMLObject(ServiceName.class); - serviceName.setName(new LocalizedString("Default Service", "en")); - attributeService.getNames().add(serviceName); - - if (reqSPAttr != null && reqSPAttr.size() > 0) { - log.debug("Add " + reqSPAttr.size() + " attributes to SP metadata"); - attributeService.getRequestAttributes().addAll(reqSPAttr); - - } else { - log.debug("SP metadata contains NO requested attributes."); - - } - - spSSODescriptor.getAttributeConsumingServices().add(attributeService); - - return spSSODescriptor; - } - - private IDPSSODescriptor generateIDPMetadata(IPVPMetadataBuilderConfiguration config) throws EAAFException, CredentialsNotAvailableException, SecurityException { - //check response signing credential - Credential responseSignCred = config.getRequestorResponseSigningCredentials(); - if (responseSignCred == null) { - log.warn("IDP Metadata generation FAILED! --> Builder has NO Response signing credential. "); - return null; - - } - - //check nameID formates - if (config.getIDPPossibleNameITTypes() == null || config.getIDPPossibleNameITTypes().size() == 0) { - log.warn("IDP Metadata generation FAILED! --> Builder has NO provideable SAML2 nameIDFormats. "); - return null; - - } - - // build SAML2 IDP-SSO descriptor element - IDPSSODescriptor idpSSODescriptor = SAML2Utils - .createSAMLObject(IDPSSODescriptor.class); - - idpSSODescriptor.addSupportedProtocol(SAMLConstants.SAML20P_NS); - - //set ass default value, because PVP 2.x specification defines this feature as MUST - idpSSODescriptor.setWantAuthnRequestsSigned(config.wantAuthnRequestSigned()); - - // add WebSSO descriptor for POST-Binding - if (StringUtils.isNotEmpty(config.getIDPWebSSOPostBindingURL())) { - SingleSignOnService postSingleSignOnService = SAML2Utils.createSAMLObject(SingleSignOnService.class); - postSingleSignOnService.setLocation(config.getIDPWebSSOPostBindingURL()); - postSingleSignOnService.setBinding(SAMLConstants.SAML2_POST_BINDING_URI); - idpSSODescriptor.getSingleSignOnServices().add(postSingleSignOnService); - - } - - // add WebSSO descriptor for Redirect-Binding - if (StringUtils.isNotEmpty(config.getIDPWebSSORedirectBindingURL())) { - SingleSignOnService postSingleSignOnService = SAML2Utils.createSAMLObject(SingleSignOnService.class); - postSingleSignOnService.setLocation(config.getIDPWebSSORedirectBindingURL()); - postSingleSignOnService.setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI); - idpSSODescriptor.getSingleSignOnServices().add(postSingleSignOnService); - - } - - //add Single LogOut POST-Binding endpoing - if (StringUtils.isNotEmpty(config.getIDPSLOPostBindingURL())) { - SingleLogoutService postSLOService = SAML2Utils.createSAMLObject(SingleLogoutService.class); - postSLOService.setLocation(config.getIDPSLOPostBindingURL()); - postSLOService.setBinding(SAMLConstants.SAML2_POST_BINDING_URI); - idpSSODescriptor.getSingleLogoutServices().add(postSLOService); - - } - - //add Single LogOut Redirect-Binding endpoing - if (StringUtils.isNotEmpty(config.getIDPSLORedirectBindingURL())) { - SingleLogoutService redirectSLOService = SAML2Utils.createSAMLObject(SingleLogoutService.class); - redirectSLOService.setLocation(config.getIDPSLORedirectBindingURL()); - redirectSLOService.setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI); - idpSSODescriptor.getSingleLogoutServices().add(redirectSLOService); - - } - - //validate WebSSO endpoints - if (idpSSODescriptor.getSingleSignOnServices().size() == 0) { - log.warn("IDP Metadata generation FAILED! --> NO SAML2 SingleSignOnService endpoint found. "); - return null; - - } - - //set assertion signing key - KeyDescriptor signKeyDescriptor = SAML2Utils - .createSAMLObject(KeyDescriptor.class); - signKeyDescriptor.setUse(UsageType.SIGNING); - KeyInfoGenerator keyInfoGenerator = keyInfoFactory.newInstance(); - signKeyDescriptor.setKeyInfo(keyInfoGenerator.generate(config.getRequestorResponseSigningCredentials())); - idpSSODescriptor.getKeyDescriptors().add(signKeyDescriptor); - - //set IDP attribute set - idpSSODescriptor.getAttributes().addAll(config.getIDPPossibleAttributes()); - - //set providable nameID formats - for (String format : config.getIDPPossibleNameITTypes()) { - NameIDFormat nameIDFormat = SAML2Utils.createSAMLObject(NameIDFormat.class); - nameIDFormat.setFormat(format); - idpSSODescriptor.getNameIDFormats().add(nameIDFormat); - - } - - return idpSSODescriptor; - - } - -} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/PvpAttributeBuilder.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/PvpAttributeBuilder.java new file mode 100644 index 00000000..92e75e17 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/PvpAttributeBuilder.java @@ -0,0 +1,242 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.impl.builder; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.ServiceLoader; + +import at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder; +import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator; +import at.gv.egiz.eaaf.core.api.idp.IAuthData; +import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration; +import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; +import at.gv.egiz.eaaf.core.exceptions.InvalidDateFormatAttributeException; +import at.gv.egiz.eaaf.core.exceptions.UnavailableAttributeException; +import at.gv.egiz.eaaf.core.impl.idp.builder.attributes.PvpMetadata; +import at.gv.egiz.eaaf.modules.pvp2.exception.InvalidDateFormatException; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils; + +import org.opensaml.saml.saml2.core.Attribute; +import org.opensaml.saml.saml2.metadata.RequestedAttribute; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class PvpAttributeBuilder { + + private static final Logger log = LoggerFactory.getLogger(PvpAttributeBuilder.class); + + private static IAttributeGenerator<Attribute> generator = new SamlAttributeGenerator(); + private static HashMap<String, IAttributeBuilder> builders; + + private static ServiceLoader<IAttributeBuilder> attributBuilderLoader = + ServiceLoader.load(IAttributeBuilder.class); + + private static void addBuilder(final IAttributeBuilder builder) { + builders.put(builder.getName(), builder); + } + + static { + builders = new HashMap<>(); + + log.info("Loading protocol attribut-builder modules:"); + if (attributBuilderLoader != null) { + final Iterator<IAttributeBuilder> moduleLoaderInterator = attributBuilderLoader.iterator(); + while (moduleLoaderInterator.hasNext()) { + try { + final IAttributeBuilder modul = moduleLoaderInterator.next(); + log.info("Loading attribut-builder Modul Information: " + modul.getName()); + addBuilder(modul); + + } catch (final Throwable e) { + log.error("Check configuration! " + "Some attribute-builder modul" + + " is not a valid IAttributeBuilder", e); + } + } + } + + log.info("Loading attribute-builder modules done"); + + } + + /** + * Get a specific attribute builder. + * + * @param name Attribute-builder friendly name + * + * @return Attribute-builder with this name or null if builder does not exists + */ + public static IAttributeBuilder getAttributeBuilder(final String name) { + return builders.get(name); + + } + + /** + * Build an SAML2 attribute. + * + * @param name attribute name + * @param value attribute value + * @return SAML2 attribute + */ + public static Attribute buildAttribute(final String name, final String value) { + log.warn("Attribute value: {} is NOT injected", value); + + if (builders.containsKey(name)) { + return builders.get(name).buildEmpty(generator); + } + return null; + } + + /** + * Build a SAML2 attribute. + * + * @param name attribute name + * @param oaParam Service-Provider configuration + * @param authData serice-provider specific authentication data + * @return SAML2 attribute + * @throws Pvp2Exception In case of a general error + * @throws AttributeBuilderException In case of an attribute builder error + */ + public static Attribute buildAttribute(final String name, final ISpConfiguration oaParam, + final IAuthData authData) throws Pvp2Exception, AttributeBuilderException { + if (builders.containsKey(name)) { + try { + return builders.get(name).build(oaParam, authData, generator); + } catch (final AttributeBuilderException e) { + if (e instanceof UnavailableAttributeException) { + throw e; + + } else if (e instanceof InvalidDateFormatAttributeException) { + throw new InvalidDateFormatException(); + + } else { + throw new UnavailableAttributeException(name); + + } + } + } + return null; + } + + /** + * Build an empty attribute. + * + * @param name attributename + * @return SAML2 attribute + */ + public static Attribute buildEmptyAttribute(final String name) { + if (builders.containsKey(name)) { + return builders.get(name).buildEmpty(generator); + } + return null; + } + + /** + * Return all attributes that has a {@link PvpMetadata} annotation. + * + * @return + */ + public static List<Attribute> buildSupportedEmptyAttributes() { + final List<Attribute> attributes = new ArrayList<>(); + final Iterator<IAttributeBuilder> builderIt = builders.values().iterator(); + while (builderIt.hasNext()) { + final IAttributeBuilder builder = builderIt.next(); + if (builder.getClass().isAnnotationPresent(PvpMetadata.class)) { + final Attribute emptyAttribute = builder.buildEmpty(generator); + if (emptyAttribute != null) { + attributes.add(emptyAttribute); + } + + } else { + log.trace(builder.getName() + "is no PVP Metadata attribute"); + + } + } + return attributes; + } + + /** + * Build a requested attribute. + * + * @param name attribute name + * @param friendlyName attribute friendlyname + * @param required is attribute mandatory + * @return SAML2 requested attribute + */ + public static RequestedAttribute buildReqAttribute(final String name, final String friendlyName, + final boolean required) { + final RequestedAttribute attribute = Saml2Utils.createSamlObject(RequestedAttribute.class); + attribute.setIsRequired(required); + attribute.setName(name); + attribute.setFriendlyName(friendlyName); + attribute.setNameFormat(Attribute.URI_REFERENCE); + return attribute; + } + + /** + * Build a set of PVP Response-Attributes <br> + * <br> + * <b>INFO:</b> If a specific attribute can not be build, a info is logged, but + * no execpetion is thrown. Therefore, the return List must not include all + * requested attributes. + * + * @param authData AuthenticationData <code>IAuthData</code> which is + * used to build the attribute values, but never + * <code>null</code> + * @param reqAttributenName List of PVP attribute names which are requested, but + * never <code>null</code> + * @return List of PVP attributes, but never <code>null</code> + */ + public static List<Attribute> buildSetOfResponseAttributes(final IAuthData authData, + final Collection<String> reqAttributenName) { + final List<Attribute> attrList = new ArrayList<>(); + if (reqAttributenName != null) { + final Iterator<String> it = reqAttributenName.iterator(); + while (it.hasNext()) { + final String reqAttributName = it.next(); + try { + final Attribute attr = + PvpAttributeBuilder.buildAttribute(reqAttributName, null, authData); + if (attr == null) { + log.info("Attribute generation failed! for " + reqAttributName); + + } else { + attrList.add(attr); + + } + + } catch (final Pvp2Exception e) { + log.info("Attribute generation failed! for " + reqAttributName); + + } catch (final Exception e) { + log.warn("General Attribute generation failed! for " + reqAttributName, e); + + } + } + } + + return attrList; + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/PvpMetadataBuilder.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/PvpMetadataBuilder.java new file mode 100644 index 00000000..92922e09 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/PvpMetadataBuilder.java @@ -0,0 +1,436 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.impl.builder; + +import java.io.IOException; +import java.text.MessageFormat; +import java.util.Collection; +import java.util.List; + +import javax.naming.ConfigurationException; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactoryConfigurationError; + +import at.gv.egiz.eaaf.core.exceptions.EaafBuilderException; +import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvpMetadataBuilderConfiguration; +import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils; + +import org.apache.commons.lang3.StringUtils; +import org.joda.time.DateTime; +import org.opensaml.core.xml.io.MarshallingException; +import org.opensaml.core.xml.util.XMLObjectSupport; +import org.opensaml.saml.common.SignableSAMLObject; +import org.opensaml.saml.common.xml.SAMLConstants; +import org.opensaml.saml.saml2.metadata.AssertionConsumerService; +import org.opensaml.saml.saml2.metadata.AttributeConsumingService; +import org.opensaml.saml.saml2.metadata.ContactPerson; +import org.opensaml.saml.saml2.metadata.EntitiesDescriptor; +import org.opensaml.saml.saml2.metadata.EntityDescriptor; +import org.opensaml.saml.saml2.metadata.IDPSSODescriptor; +import org.opensaml.saml.saml2.metadata.KeyDescriptor; +import org.opensaml.saml.saml2.metadata.NameIDFormat; +import org.opensaml.saml.saml2.metadata.Organization; +import org.opensaml.saml.saml2.metadata.RequestedAttribute; +import org.opensaml.saml.saml2.metadata.RoleDescriptor; +import org.opensaml.saml.saml2.metadata.SPSSODescriptor; +import org.opensaml.saml.saml2.metadata.ServiceName; +import org.opensaml.saml.saml2.metadata.SingleLogoutService; +import org.opensaml.saml.saml2.metadata.SingleSignOnService; +import org.opensaml.security.SecurityException; +import org.opensaml.security.credential.Credential; +import org.opensaml.security.credential.UsageType; +import org.opensaml.xmlsec.keyinfo.KeyInfoGenerator; +import org.opensaml.xmlsec.keyinfo.impl.X509KeyInfoGeneratorFactory; +import org.opensaml.xmlsec.signature.support.SignatureException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Element; + +import net.shibboleth.utilities.java.support.xml.SerializeSupport; + +/** + * PVP metadata builder implementation. + * + * @author tlenz + * + */ + +public class PvpMetadataBuilder { + + private static final String ERROR_ROLE_DESCR = "Can not build {0}"; + + private static final Logger log = LoggerFactory.getLogger(PvpMetadataBuilder.class); + + X509KeyInfoGeneratorFactory keyInfoFactory = null; + + /** + * PVP metadata builder. + * + */ + public PvpMetadataBuilder() { + keyInfoFactory = new X509KeyInfoGeneratorFactory(); + keyInfoFactory.setEmitEntityIDAsKeyName(true); + keyInfoFactory.setEmitEntityCertificate(true); + + } + + /** + * Build PVP 2.1 conform SAML2 metadata. + * + * @param config PVPMetadataBuilder configuration* + * @return PVP metadata as XML String + * @throws SecurityException In case of an error + * @throws ConfigurationException In case of an error + * @throws CredentialsNotAvailableException In case of an error + * @throws TransformerFactoryConfigurationError In case of an error + * @throws MarshallingException In case of an error + * @throws TransformerException In case of an error + * @throws ParserConfigurationException In case of an error + * @throws IOException In case of an error + * @throws SignatureException In case of an error + */ + public String buildPvpMetadata(final IPvpMetadataBuilderConfiguration config) + throws CredentialsNotAvailableException, EaafException, SecurityException, + TransformerFactoryConfigurationError, MarshallingException, TransformerException, + ParserConfigurationException, IOException, SignatureException { + final DateTime date = new DateTime(); + final EntityDescriptor entityDescriptor = Saml2Utils.createSamlObject(EntityDescriptor.class); + + // set entityID + entityDescriptor.setEntityID(config.getEntityID()); + + // set contact and organisation information + final List<ContactPerson> contactPersons = config.getContactPersonInformation(); + if (contactPersons != null) { + entityDescriptor.getContactPersons().addAll(contactPersons); + } + + final Organization organisation = config.getOrgansiationInformation(); + if (organisation != null) { + entityDescriptor.setOrganization(organisation); + } + + // set IDP metadata + if (config.buildIdpSsoDescriptor()) { + final RoleDescriptor idpSsoDesc = generateIdpMetadata(config); + if (idpSsoDesc != null) { + entityDescriptor.getRoleDescriptors().add(idpSsoDesc); + + } else { + final String msg = MessageFormat.format(ERROR_ROLE_DESCR, + IDPSSODescriptor.DEFAULT_ELEMENT_LOCAL_NAME); + throw new EaafBuilderException("internal.pvp.13", new Object[] { msg }, msg); + + } + + } + + // set SP metadata for interfederation + if (config.buildSpSsoDescriptor()) { + final RoleDescriptor spSsoDesc = generateSpMetadata(config); + if (spSsoDesc != null) { + entityDescriptor.getRoleDescriptors().add(spSsoDesc); + + } else { + final String msg = MessageFormat.format(ERROR_ROLE_DESCR, SPSSODescriptor.DEFAULT_ELEMENT_LOCAL_NAME); + throw new EaafBuilderException("internal.pvp.13", new Object[] { msg }, msg); + + } + + } + + SignableSAMLObject metadataToSign; + + // build entities descriptor + if (config.buildEntitiesDescriptorAsRootElement()) { + final EntitiesDescriptor entitiesDescriptor = + Saml2Utils.createSamlObject(EntitiesDescriptor.class); + entitiesDescriptor.setName(config.getEntityFriendlyName()); + entitiesDescriptor.setID(Saml2Utils.getSecureIdentifier()); + entitiesDescriptor.setValidUntil(date.plusHours(config.getMetadataValidUntil())); + entitiesDescriptor.getEntityDescriptors().add(entityDescriptor); + metadataToSign = entitiesDescriptor; + + } else { + entityDescriptor.setValidUntil(date.plusHours(config.getMetadataValidUntil())); + entityDescriptor.setID(Saml2Utils.getSecureIdentifier()); + metadataToSign = entityDescriptor; + + } + + // sign metadata + final EaafX509Credential metadataSignCred = config.getMetadataSigningCredentials(); + final SignableSAMLObject signedMetadata = Saml2Utils.signSamlObject(metadataToSign, metadataSignCred, + true); + + // Serialize metadata + final Element document = XMLObjectSupport.marshall(signedMetadata); + final String serializedMetadata = SerializeSupport.nodeToString(document); + return serializedMetadata; + + } + + private RoleDescriptor generateSpMetadata(final IPvpMetadataBuilderConfiguration config) + throws SecurityException, EaafException { + final SPSSODescriptor spSsoDescriptor = Saml2Utils.createSamlObject(SPSSODescriptor.class); + spSsoDescriptor.addSupportedProtocol(SAMLConstants.SAML20P_NS); + spSsoDescriptor.setAuthnRequestsSigned(config.wantAuthnRequestSigned()); + spSsoDescriptor.setWantAssertionsSigned(config.wantAssertionSigned()); + + final KeyInfoGenerator keyInfoGenerator = keyInfoFactory.newInstance(); + + // Set AuthRequest Signing certificate + final Credential authcredential = config.getRequestorResponseSigningCredentials(); + if (authcredential == null) { + log.warn("SP Metadata generation FAILED! --> Builder has NO request signing-credential. "); + return null; + + } else { + final KeyDescriptor signKeyDescriptor = Saml2Utils.createSamlObject(KeyDescriptor.class); + signKeyDescriptor.setUse(UsageType.SIGNING); + signKeyDescriptor.setKeyInfo(keyInfoGenerator.generate(authcredential)); + spSsoDescriptor.getKeyDescriptors().add(signKeyDescriptor); + + } + + // Set assertion encryption credentials + final Credential authEncCredential = config.getEncryptionCredentials(); + + if (authEncCredential != null) { + final KeyDescriptor encryKeyDescriptor = Saml2Utils.createSamlObject(KeyDescriptor.class); + encryKeyDescriptor.setUse(UsageType.ENCRYPTION); + encryKeyDescriptor.setKeyInfo(keyInfoGenerator.generate(authEncCredential)); + spSsoDescriptor.getKeyDescriptors().add(encryKeyDescriptor); + + } else { + log.warn("No Assertion Encryption-Key defined. This setting is not recommended!"); + + } + + // check nameID formates + if (config.getSpAllowedNameIdTypes() == null || config.getSpAllowedNameIdTypes().size() == 0) { + log.warn( + "SP Metadata generation FAILED! --> Builder has NO provideable SAML2 nameIDFormats. "); + return null; + + } else { + for (final String format : config.getSpAllowedNameIdTypes()) { + final NameIDFormat nameIdFormat = Saml2Utils.createSamlObject(NameIDFormat.class); + nameIdFormat.setFormat(format); + spSsoDescriptor.getNameIDFormats().add(nameIdFormat); + + } + } + + // add POST-Binding assertion consumer services + if (StringUtils.isNotEmpty(config.getSpAssertionConsumerServicePostBindingUrl())) { + final AssertionConsumerService postassertionConsumerService = + Saml2Utils.createSamlObject(AssertionConsumerService.class); + postassertionConsumerService.setIndex(0); + postassertionConsumerService.setBinding(SAMLConstants.SAML2_POST_BINDING_URI); + postassertionConsumerService + .setLocation(config.getSpAssertionConsumerServicePostBindingUrl()); + postassertionConsumerService.setIsDefault(true); + spSsoDescriptor.getAssertionConsumerServices().add(postassertionConsumerService); + + } + + // add POST-Binding assertion consumer services + if (StringUtils.isNotEmpty(config.getSpAssertionConsumerServiceRedirectBindingUrl())) { + final AssertionConsumerService redirectassertionConsumerService = + Saml2Utils.createSamlObject(AssertionConsumerService.class); + redirectassertionConsumerService.setIndex(1); + redirectassertionConsumerService.setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI); + redirectassertionConsumerService + .setLocation(config.getSpAssertionConsumerServiceRedirectBindingUrl()); + spSsoDescriptor.getAssertionConsumerServices().add(redirectassertionConsumerService); + + } + + // validate WebSSO endpoints + if (spSsoDescriptor.getAssertionConsumerServices().size() == 0) { + log.warn( + "SP Metadata generation FAILED! --> NO SAML2 AssertionConsumerService endpoint found. "); + return null; + + } + + // add POST-Binding SLO descriptor + if (StringUtils.isNotEmpty(config.getSpSloPostBindingUrl())) { + final SingleLogoutService postSloService = + Saml2Utils.createSamlObject(SingleLogoutService.class); + postSloService.setLocation(config.getSpSloPostBindingUrl()); + postSloService.setBinding(SAMLConstants.SAML2_POST_BINDING_URI); + spSsoDescriptor.getSingleLogoutServices().add(postSloService); + + } + + // add POST-Binding SLO descriptor + if (StringUtils.isNotEmpty(config.getSpSloRedirectBindingUrl())) { + final SingleLogoutService redirectSloService = + Saml2Utils.createSamlObject(SingleLogoutService.class); + redirectSloService.setLocation(config.getSpSloRedirectBindingUrl()); + redirectSloService.setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI); + spSsoDescriptor.getSingleLogoutServices().add(redirectSloService); + + } + + // add POST-Binding SLO descriptor + if (StringUtils.isNotEmpty(config.getSpSloSoapBindingUrl())) { + final SingleLogoutService soapSloService = + Saml2Utils.createSamlObject(SingleLogoutService.class); + soapSloService.setLocation(config.getSpSloSoapBindingUrl()); + soapSloService.setBinding(SAMLConstants.SAML2_SOAP11_BINDING_URI); + spSsoDescriptor.getSingleLogoutServices().add(soapSloService); + + } + + // add required attributes + final Collection<RequestedAttribute> reqSpAttr = config.getSpRequiredAttributes(); + final AttributeConsumingService attributeService = + Saml2Utils.createSamlObject(AttributeConsumingService.class); + + attributeService.setIndex(0); + attributeService.setIsDefault(true); + final ServiceName serviceName = Saml2Utils.createSamlObject(ServiceName.class); + serviceName.setValue("Default Service"); + serviceName.setXMLLang("en"); + attributeService.getNames().add(serviceName); + + if (reqSpAttr != null && reqSpAttr.size() > 0) { + log.debug("Add " + reqSpAttr.size() + " attributes to SP metadata"); + attributeService.getRequestAttributes().addAll(reqSpAttr); + + } else { + log.debug("SP metadata contains NO requested attributes."); + + } + + spSsoDescriptor.getAttributeConsumingServices().add(attributeService); + + return spSsoDescriptor; + } + + private IDPSSODescriptor generateIdpMetadata(final IPvpMetadataBuilderConfiguration config) + throws EaafException, SecurityException { + // check response signing credential + final Credential responseSignCred = config.getRequestorResponseSigningCredentials(); + if (responseSignCred == null) { + log.warn("IDP Metadata generation FAILED! --> Builder has NO Response signing credential. "); + return null; + + } + + // check nameID formates + if (config.getIdpPossibleNameIdTypes() == null + || config.getIdpPossibleNameIdTypes().size() == 0) { + log.warn( + "IDP Metadata generation FAILED! --> Builder has NO provideable SAML2 nameIDFormats. "); + return null; + + } + + // build SAML2 IDP-SSO descriptor element + final IDPSSODescriptor idpSsoDescriptor = Saml2Utils.createSamlObject(IDPSSODescriptor.class); + + idpSsoDescriptor.addSupportedProtocol(SAMLConstants.SAML20P_NS); + + // set ass default value, because PVP 2.x specification defines this feature as + // MUST + idpSsoDescriptor.setWantAuthnRequestsSigned(config.wantAuthnRequestSigned()); + + // add WebSSO descriptor for POST-Binding + if (StringUtils.isNotEmpty(config.getIdpWebSsoPostBindingUrl())) { + final SingleSignOnService postSingleSignOnService = + Saml2Utils.createSamlObject(SingleSignOnService.class); + postSingleSignOnService.setLocation(config.getIdpWebSsoPostBindingUrl()); + postSingleSignOnService.setBinding(SAMLConstants.SAML2_POST_BINDING_URI); + idpSsoDescriptor.getSingleSignOnServices().add(postSingleSignOnService); + + } + + // add WebSSO descriptor for Redirect-Binding + if (StringUtils.isNotEmpty(config.getIdpWebSsoRedirectBindingUrl())) { + final SingleSignOnService postSingleSignOnService = + Saml2Utils.createSamlObject(SingleSignOnService.class); + postSingleSignOnService.setLocation(config.getIdpWebSsoRedirectBindingUrl()); + postSingleSignOnService.setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI); + idpSsoDescriptor.getSingleSignOnServices().add(postSingleSignOnService); + + } + + // add Single LogOut POST-Binding endpoing + if (StringUtils.isNotEmpty(config.getIdpSloPostBindingUrl())) { + final SingleLogoutService postSloService = + Saml2Utils.createSamlObject(SingleLogoutService.class); + postSloService.setLocation(config.getIdpSloPostBindingUrl()); + postSloService.setBinding(SAMLConstants.SAML2_POST_BINDING_URI); + idpSsoDescriptor.getSingleLogoutServices().add(postSloService); + + } + + // add Single LogOut Redirect-Binding endpoing + if (StringUtils.isNotEmpty(config.getIdpSloRedirectBindingUrl())) { + final SingleLogoutService redirectSloService = + Saml2Utils.createSamlObject(SingleLogoutService.class); + redirectSloService.setLocation(config.getIdpSloRedirectBindingUrl()); + redirectSloService.setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI); + idpSsoDescriptor.getSingleLogoutServices().add(redirectSloService); + + } + + // validate WebSSO endpoints + if (idpSsoDescriptor.getSingleSignOnServices().size() == 0) { + log.warn("IDP Metadata generation FAILED! --> NO SAML2 SingleSignOnService endpoint found. "); + return null; + + } + + // set assertion signing key + final KeyDescriptor signKeyDescriptor = Saml2Utils.createSamlObject(KeyDescriptor.class); + signKeyDescriptor.setUse(UsageType.SIGNING); + final KeyInfoGenerator keyInfoGenerator = keyInfoFactory.newInstance(); + signKeyDescriptor + .setKeyInfo(keyInfoGenerator.generate(config.getRequestorResponseSigningCredentials())); + idpSsoDescriptor.getKeyDescriptors().add(signKeyDescriptor); + + // set IDP attribute set + if (config.getIdpPossibleAttributes() != null) { + idpSsoDescriptor.getAttributes().addAll(config.getIdpPossibleAttributes()); + + } + + // set providable nameID formats + for (final String format : config.getIdpPossibleNameIdTypes()) { + final NameIDFormat nameIdFormat = Saml2Utils.createSamlObject(NameIDFormat.class); + nameIdFormat.setFormat(format); + idpSsoDescriptor.getNameIDFormats().add(nameIdFormat); + + } + + return idpSsoDescriptor; + + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/SamlAttributeGenerator.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/SamlAttributeGenerator.java index cb4a4608..5c44af24 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/SamlAttributeGenerator.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/SamlAttributeGenerator.java @@ -1,92 +1,97 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 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: + * Licensed under the EUPL, Version 1.2 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: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * 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.egiz.eaaf.modules.pvp2.impl.builder; + * 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. +*/ -import org.opensaml.saml2.core.Attribute; -import org.opensaml.saml2.core.AttributeValue; -import org.opensaml.xml.Configuration; -import org.opensaml.xml.XMLObject; -import org.opensaml.xml.schema.XSInteger; -import org.opensaml.xml.schema.XSString; -import org.opensaml.xml.schema.impl.XSIntegerBuilder; -import org.opensaml.xml.schema.impl.XSStringBuilder; +package at.gv.egiz.eaaf.modules.pvp2.impl.builder; import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator; -import at.gv.egiz.eaaf.modules.pvp2.impl.utils.SAML2Utils; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils; + +import org.opensaml.core.xml.XMLObject; +import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport; +import org.opensaml.core.xml.schema.XSInteger; +import org.opensaml.core.xml.schema.XSString; +import org.opensaml.core.xml.schema.impl.XSIntegerBuilder; +import org.opensaml.core.xml.schema.impl.XSStringBuilder; +import org.opensaml.saml.saml2.core.Attribute; +import org.opensaml.saml.saml2.core.AttributeValue; public class SamlAttributeGenerator implements IAttributeGenerator<Attribute> { - - private XMLObject buildAttributeStringValue(String value) { - XSStringBuilder stringBuilder = (XSStringBuilder) Configuration.getBuilderFactory().getBuilder(XSString.TYPE_NAME); - XSString stringValue = stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, XSString.TYPE_NAME); - stringValue.setValue(value); - return stringValue; - } - - private XMLObject buildAttributeIntegerValue(int value) { - XSIntegerBuilder integerBuilder = (XSIntegerBuilder) Configuration.getBuilderFactory().getBuilder(XSInteger.TYPE_NAME); - XSInteger integerValue = integerBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, XSInteger.TYPE_NAME); - integerValue.setValue(value); - return integerValue; - } - - public Attribute buildStringAttribute(final String friendlyName, final String name, final String value) { - Attribute attribute = SAML2Utils.createSAMLObject(Attribute.class); - attribute.setFriendlyName(friendlyName); - attribute.setName(name); - attribute.setNameFormat(Attribute.URI_REFERENCE); - attribute.getAttributeValues().add(buildAttributeStringValue(value)); - return attribute; - } - - public Attribute buildIntegerAttribute(final String friendlyName, final String name, final int value) { - Attribute attribute = SAML2Utils.createSAMLObject(Attribute.class); - attribute.setFriendlyName(friendlyName); - attribute.setName(name); - attribute.setNameFormat(Attribute.URI_REFERENCE); - attribute.getAttributeValues().add(buildAttributeIntegerValue(value)); - return attribute; - } - - public Attribute buildEmptyAttribute(final String friendlyName, final String name) { - Attribute attribute = SAML2Utils.createSAMLObject(Attribute.class); - attribute.setFriendlyName(friendlyName); - attribute.setName(name); - attribute.setNameFormat(Attribute.URI_REFERENCE); - return attribute; - } - public Attribute buildLongAttribute(String friendlyName, String name, long value) { - Attribute attribute = SAML2Utils.createSAMLObject(Attribute.class); - attribute.setFriendlyName(friendlyName); - attribute.setName(name); - attribute.setNameFormat(Attribute.URI_REFERENCE); - attribute.getAttributeValues().add(buildAttributeIntegerValue((int) value)); - return attribute; - } - + private XMLObject buildAttributeStringValue(final String value) { + final XSStringBuilder stringBuilder = + (XSStringBuilder) XMLObjectProviderRegistrySupport.getBuilderFactory().getBuilder(XSString.TYPE_NAME); + final XSString stringValue = + stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, XSString.TYPE_NAME); + stringValue.setValue(value); + return stringValue; + } + + private XMLObject buildAttributeIntegerValue(final int value) { + final XSIntegerBuilder integerBuilder = + (XSIntegerBuilder) XMLObjectProviderRegistrySupport.getBuilderFactory().getBuilder( + XSInteger.TYPE_NAME); + final XSInteger integerValue = + integerBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, XSInteger.TYPE_NAME); + integerValue.setValue(value); + return integerValue; + } + + @Override + public Attribute buildStringAttribute(final String friendlyName, final String name, + final String value) { + final Attribute attribute = Saml2Utils.createSamlObject(Attribute.class); + attribute.setFriendlyName(friendlyName); + attribute.setName(name); + attribute.setNameFormat(Attribute.URI_REFERENCE); + attribute.getAttributeValues().add(buildAttributeStringValue(value)); + return attribute; + } + + @Override + public Attribute buildIntegerAttribute(final String friendlyName, final String name, + final int value) { + final Attribute attribute = Saml2Utils.createSamlObject(Attribute.class); + attribute.setFriendlyName(friendlyName); + attribute.setName(name); + attribute.setNameFormat(Attribute.URI_REFERENCE); + attribute.getAttributeValues().add(buildAttributeIntegerValue(value)); + return attribute; + } + + @Override + public Attribute buildEmptyAttribute(final String friendlyName, final String name) { + final Attribute attribute = Saml2Utils.createSamlObject(Attribute.class); + attribute.setFriendlyName(friendlyName); + attribute.setName(name); + attribute.setNameFormat(Attribute.URI_REFERENCE); + return attribute; + } + + @Override + public Attribute buildLongAttribute(final String friendlyName, final String name, + final long value) { + final Attribute attribute = Saml2Utils.createSamlObject(Attribute.class); + attribute.setFriendlyName(friendlyName); + attribute.setName(name); + attribute.setNameFormat(Attribute.URI_REFERENCE); + attribute.getAttributeValues().add(buildAttributeIntegerValue((int) value)); + return attribute; + } + } diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFExtensionImplementation.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFExtensionImplementation.java deleted file mode 100644 index 817ca2f6..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFExtensionImplementation.java +++ /dev/null @@ -1,36 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.impl.builder.reqattr; - -import org.opensaml.saml2.common.impl.ExtensionsImpl; - -public class EAAFExtensionImplementation extends ExtensionsImpl { - - protected EAAFExtensionImplementation(String namespaceURI, String elementLocalName, String namespacePrefix) { - super(namespaceURI, elementLocalName, namespacePrefix); - - } - -} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFRequestExtensionBuilder.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFRequestExtensionBuilder.java deleted file mode 100644 index 431784cf..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFRequestExtensionBuilder.java +++ /dev/null @@ -1,45 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.impl.builder.reqattr; - -import org.opensaml.common.impl.AbstractSAMLObjectBuilder; -import org.opensaml.common.xml.SAMLConstants; -import org.opensaml.saml2.common.Extensions; - -public class EAAFRequestExtensionBuilder extends AbstractSAMLObjectBuilder<Extensions> { - - @Override - public Extensions buildObject() { - return buildObject(SAMLConstants.SAML20P_NS, Extensions.LOCAL_NAME, SAMLConstants.SAML20P_PREFIX); - - } - - @Override - public Extensions buildObject(String namespaceURI, String localName, String namespacePrefix) { - return new EAAFExtensionImplementation(namespaceURI, localName, namespacePrefix); - - } - -} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFRequestedAttributeBuilder.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFRequestedAttributeBuilder.java deleted file mode 100644 index 33868544..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFRequestedAttributeBuilder.java +++ /dev/null @@ -1,45 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.impl.builder.reqattr; - -import org.opensaml.common.impl.AbstractSAMLObjectBuilder; - -import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EAAFRequestedAttribute; -import at.gv.egiz.eaaf.modules.pvp2.impl.reqattr.EAAFRequestedAttributeImpl; - -public class EAAFRequestedAttributeBuilder extends AbstractSAMLObjectBuilder<EAAFRequestedAttribute> { - - @Override - public EAAFRequestedAttribute buildObject() { - return buildObject(EAAFRequestedAttribute.DEFAULT_ELEMENT_NAME); - } - - @Override - public EAAFRequestedAttribute buildObject(String namespaceURI, String localName, String namespacePrefix) { - return new EAAFRequestedAttributeImpl(namespaceURI, localName, - namespacePrefix); - } - -} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFRequestedAttributeMarshaller.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFRequestedAttributeMarshaller.java deleted file mode 100644 index d95adc8f..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFRequestedAttributeMarshaller.java +++ /dev/null @@ -1,76 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.impl.builder.reqattr; - -import java.util.Map.Entry; - -import javax.xml.namespace.QName; - -import org.opensaml.Configuration; -import org.opensaml.common.impl.AbstractSAMLObjectMarshaller; -import org.opensaml.xml.XMLObject; -import org.opensaml.xml.io.MarshallingException; -import org.opensaml.xml.util.XMLHelper; -import org.w3c.dom.Attr; -import org.w3c.dom.Element; - -import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EAAFRequestedAttribute; - -public class EAAFRequestedAttributeMarshaller extends AbstractSAMLObjectMarshaller { - protected final void marshallAttributes(final XMLObject samlElement, - final Element domElement) throws MarshallingException { - final EAAFRequestedAttribute requestedAttr = (EAAFRequestedAttribute) samlElement; - - if (requestedAttr.getName() != null) { - domElement.setAttributeNS(null, EAAFRequestedAttribute.NAME_ATTRIB_NAME, requestedAttr.getName()); - } - - if (requestedAttr.getNameFormat() != null) { - domElement.setAttributeNS(null, EAAFRequestedAttribute.NAME_FORMAT_ATTR, requestedAttr.getNameFormat()); - } - - if (requestedAttr.getFriendlyName() != null) { - domElement.setAttributeNS(null, EAAFRequestedAttribute.FRIENDLY_NAME_ATT, requestedAttr.getFriendlyName()); - } - - if (requestedAttr.getIsRequiredXSBoolean() != null) { - domElement.setAttributeNS(null, EAAFRequestedAttribute.IS_REQUIRED_ATTR, requestedAttr.getIsRequiredXSBoolean()); - } - - Attr attr; - for (Entry<QName, String> entry : requestedAttr.getUnknownAttributes() - .entrySet()) { - attr = XMLHelper.constructAttribute(domElement.getOwnerDocument(), - entry.getKey()); - attr.setValue(entry.getValue()); - domElement.setAttributeNodeNS(attr); - if (Configuration.isIDAttribute(entry.getKey()) - || requestedAttr.getUnknownAttributes().isIDAttribute( - entry.getKey())) { - attr.getOwnerElement().setIdAttributeNode(attr, true); - } - } - } -} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFRequestedAttributeUnmarshaller.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFRequestedAttributeUnmarshaller.java deleted file mode 100644 index a4515707..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFRequestedAttributeUnmarshaller.java +++ /dev/null @@ -1,75 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.impl.builder.reqattr; - -import javax.xml.namespace.QName; - -import org.opensaml.common.impl.AbstractSAMLObjectUnmarshaller; -import org.opensaml.xml.XMLObject; -import org.opensaml.xml.io.UnmarshallingException; -import org.opensaml.xml.util.XMLHelper; -import org.w3c.dom.Attr; - -import at.gv.egiz.eaaf.modules.pvp2.PVPConstants; -import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EAAFRequestedAttribute; - -public class EAAFRequestedAttributeUnmarshaller extends AbstractSAMLObjectUnmarshaller { - protected final void processChildElement(final XMLObject parentSAMLObject, final XMLObject childSAMLObject) throws UnmarshallingException { - final EAAFRequestedAttribute requestedAttr = (EAAFRequestedAttribute) parentSAMLObject; - final QName childQName = childSAMLObject.getElementQName(); - - if ("AttributeValue".equals(childQName.getLocalPart()) - && childQName.getNamespaceURI().equals(PVPConstants.EIDAT10_SAML_NS)) { - requestedAttr.getAttributeValues().add(childSAMLObject); - - } else - super.processChildElement(parentSAMLObject, childSAMLObject); - - } - - protected final void processAttribute(final XMLObject samlObject, final Attr attribute) throws UnmarshallingException { - final EAAFRequestedAttribute requestedAttr = (EAAFRequestedAttribute) samlObject; - if (attribute.getLocalName().equals(EAAFRequestedAttribute.NAME_ATTRIB_NAME)) { - requestedAttr.setName(attribute.getValue()); - - } else if (attribute.getLocalName().equals(EAAFRequestedAttribute.NAME_FORMAT_ATTR)) { - requestedAttr.setNameFormat(attribute.getValue()); - - } else if (attribute.getLocalName().equals(EAAFRequestedAttribute.FRIENDLY_NAME_ATT)) { - requestedAttr.setFriendlyName(attribute.getValue()); - - } else if (attribute.getLocalName().equals(EAAFRequestedAttribute.IS_REQUIRED_ATTR)) { - requestedAttr.setIsRequired(attribute.getValue()); - - } else { - final QName attribQName = XMLHelper.getNodeQName(attribute); - if (attribute.isId()) { - requestedAttr.getUnknownAttributes().registerID(attribQName); - } - requestedAttr.getUnknownAttributes().put(attribQName, - attribute.getValue()); - } - } -} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFRequestedAttributesBuilder.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFRequestedAttributesBuilder.java deleted file mode 100644 index 6e432b25..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFRequestedAttributesBuilder.java +++ /dev/null @@ -1,45 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.impl.builder.reqattr; - -import org.opensaml.common.impl.AbstractSAMLObjectBuilder; - -import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EAAFRequestedAttributes; -import at.gv.egiz.eaaf.modules.pvp2.impl.reqattr.EAAFRequestedAttributesImpl; - -public class EAAFRequestedAttributesBuilder extends AbstractSAMLObjectBuilder<EAAFRequestedAttributes> { - - @Override - public EAAFRequestedAttributes buildObject() { - return buildObject(EAAFRequestedAttributes.DEFAULT_ELEMENT_NAME); - } - - @Override - public EAAFRequestedAttributes buildObject(String namespaceURI, String localName, String namespacePrefix) { - return new EAAFRequestedAttributesImpl(namespaceURI, localName, - namespacePrefix); - } - -} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFRequestedAttributesMarshaller.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFRequestedAttributesMarshaller.java deleted file mode 100644 index 28d50422..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFRequestedAttributesMarshaller.java +++ /dev/null @@ -1,31 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.impl.builder.reqattr; - -import org.opensaml.common.impl.AbstractSAMLObjectMarshaller; - -public class EAAFRequestedAttributesMarshaller extends AbstractSAMLObjectMarshaller { - -} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFRequestedAttributesUnmarshaller.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFRequestedAttributesUnmarshaller.java deleted file mode 100644 index b2758326..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EAAFRequestedAttributesUnmarshaller.java +++ /dev/null @@ -1,45 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.impl.builder.reqattr; - -import org.opensaml.common.impl.AbstractSAMLObjectUnmarshaller; -import org.opensaml.xml.XMLObject; -import org.opensaml.xml.io.UnmarshallingException; - -import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EAAFRequestedAttribute; -import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EAAFRequestedAttributes; - -public class EAAFRequestedAttributesUnmarshaller extends AbstractSAMLObjectUnmarshaller { - protected final void processChildElement(final XMLObject parentObject, - final XMLObject childObject) throws UnmarshallingException { - final EAAFRequestedAttributes attrStatement = (EAAFRequestedAttributes) parentObject; - if (childObject instanceof EAAFRequestedAttribute) { - attrStatement.getAttributes().add((EAAFRequestedAttribute) childObject); - - } else - super.processChildElement(parentObject, childObject); - - } -} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafExtensionImplementation.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafExtensionImplementation.java new file mode 100644 index 00000000..726a2960 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafExtensionImplementation.java @@ -0,0 +1,32 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.impl.builder.reqattr; + +import org.opensaml.saml.saml2.core.impl.ExtensionsImpl; + +public class EaafExtensionImplementation extends ExtensionsImpl { + + protected EaafExtensionImplementation(final String namespaceUri, final String elementLocalName, + final String namespacePrefix) { + super(namespaceUri, elementLocalName, namespacePrefix); + + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestExtensionBuilder.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestExtensionBuilder.java new file mode 100644 index 00000000..c77193fd --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestExtensionBuilder.java @@ -0,0 +1,42 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.impl.builder.reqattr; + +import org.opensaml.saml.common.AbstractSAMLObjectBuilder; +import org.opensaml.saml.common.xml.SAMLConstants; +import org.opensaml.saml.saml2.core.Extensions; + +public class EaafRequestExtensionBuilder extends AbstractSAMLObjectBuilder<Extensions> { + + @Override + public Extensions buildObject() { + return buildObject(SAMLConstants.SAML20P_NS, Extensions.DEFAULT_ELEMENT_LOCAL_NAME, + SAMLConstants.SAML20P_PREFIX); + + } + + @Override + public Extensions buildObject(final String namespaceUri, final String localName, + final String namespacePrefix) { + return new EaafExtensionImplementation(namespaceUri, localName, namespacePrefix); + + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributeBuilder.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributeBuilder.java new file mode 100644 index 00000000..fde79998 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributeBuilder.java @@ -0,0 +1,41 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.impl.builder.reqattr; + +import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttribute; +import at.gv.egiz.eaaf.modules.pvp2.impl.reqattr.EaafRequestedAttributeImpl; + +import org.opensaml.saml.common.AbstractSAMLObjectBuilder; + +public class EaafRequestedAttributeBuilder + extends AbstractSAMLObjectBuilder<EaafRequestedAttribute> { + + @Override + public EaafRequestedAttribute buildObject() { + return buildObject(EaafRequestedAttribute.DEFAULT_ELEMENT_NAME); + } + + @Override + public EaafRequestedAttribute buildObject(final String namespaceUri, final String localName, + final String namespacePrefix) { + return new EaafRequestedAttributeImpl(namespaceUri, localName, namespacePrefix); + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributeMarshaller.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributeMarshaller.java new file mode 100644 index 00000000..4acee141 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributeMarshaller.java @@ -0,0 +1,75 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.impl.builder.reqattr; + +import java.util.Map.Entry; + +import javax.xml.namespace.QName; + +import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttribute; + +import org.opensaml.core.xml.XMLObject; +import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport; +import org.opensaml.core.xml.io.MarshallingException; +import org.opensaml.saml.common.AbstractSAMLObjectMarshaller; +import org.w3c.dom.Attr; +import org.w3c.dom.Element; + +import net.shibboleth.utilities.java.support.xml.AttributeSupport; + +public class EaafRequestedAttributeMarshaller extends AbstractSAMLObjectMarshaller { + @Override + protected final void marshallAttributes(final XMLObject samlElement, final Element domElement) + throws MarshallingException { + final EaafRequestedAttribute requestedAttr = (EaafRequestedAttribute) samlElement; + + if (requestedAttr.getName() != null) { + domElement.setAttributeNS(null, EaafRequestedAttribute.NAME_ATTRIB_NAME, + requestedAttr.getName()); + } + + if (requestedAttr.getNameFormat() != null) { + domElement.setAttributeNS(null, EaafRequestedAttribute.NAME_FORMAT_ATTR, + requestedAttr.getNameFormat()); + } + + if (requestedAttr.getFriendlyName() != null) { + domElement.setAttributeNS(null, EaafRequestedAttribute.FRIENDLY_NAME_ATT, + requestedAttr.getFriendlyName()); + } + + if (requestedAttr.getIsRequiredXsBoolean() != null) { + domElement.setAttributeNS(null, EaafRequestedAttribute.IS_REQUIRED_ATTR, + requestedAttr.getIsRequiredXsBoolean()); + } + + Attr attr; + for (final Entry<QName, String> entry : requestedAttr.getUnknownAttributes().entrySet()) { + + attr = AttributeSupport.constructAttribute(domElement.getOwnerDocument(), entry.getKey()); + attr.setValue(entry.getValue()); + domElement.setAttributeNodeNS(attr); + if (XMLObjectProviderRegistrySupport.isIDAttribute(entry.getKey()) + || requestedAttr.getUnknownAttributes().isIDAttribute(entry.getKey())) { + attr.getOwnerElement().setIdAttributeNode(attr, true); + } + } + } +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributeUnmarshaller.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributeUnmarshaller.java new file mode 100644 index 00000000..5313f340 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributeUnmarshaller.java @@ -0,0 +1,75 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.impl.builder.reqattr; + +import javax.xml.namespace.QName; + +import at.gv.egiz.eaaf.modules.pvp2.PvpConstants; +import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttribute; + +import org.opensaml.core.xml.XMLObject; +import org.opensaml.core.xml.io.UnmarshallingException; +import org.opensaml.saml.common.AbstractSAMLObjectUnmarshaller; +import org.w3c.dom.Attr; + +import net.shibboleth.utilities.java.support.xml.QNameSupport; + +public class EaafRequestedAttributeUnmarshaller extends AbstractSAMLObjectUnmarshaller { + @Override + protected final void processChildElement(final XMLObject parentSamlObject, + final XMLObject childSamlObject) throws UnmarshallingException { + final EaafRequestedAttribute requestedAttr = (EaafRequestedAttribute) parentSamlObject; + final QName childQName = childSamlObject.getElementQName(); + + if ("AttributeValue".equals(childQName.getLocalPart()) + && childQName.getNamespaceURI().equals(PvpConstants.EIDAT10_SAML_NS)) { + requestedAttr.getAttributeValues().add(childSamlObject); + + } else { + super.processChildElement(parentSamlObject, childSamlObject); + } + + } + + @Override + protected final void processAttribute(final XMLObject samlObject, final Attr attribute) + throws UnmarshallingException { + final EaafRequestedAttribute requestedAttr = (EaafRequestedAttribute) samlObject; + if (attribute.getLocalName().equals(EaafRequestedAttribute.NAME_ATTRIB_NAME)) { + requestedAttr.setName(attribute.getValue()); + + } else if (attribute.getLocalName().equals(EaafRequestedAttribute.NAME_FORMAT_ATTR)) { + requestedAttr.setNameFormat(attribute.getValue()); + + } else if (attribute.getLocalName().equals(EaafRequestedAttribute.FRIENDLY_NAME_ATT)) { + requestedAttr.setFriendlyName(attribute.getValue()); + + } else if (attribute.getLocalName().equals(EaafRequestedAttribute.IS_REQUIRED_ATTR)) { + requestedAttr.setIsRequired(attribute.getValue()); + + } else { + final QName attribQName = QNameSupport.getNodeQName(attribute); + if (attribute.isId()) { + requestedAttr.getUnknownAttributes().registerID(attribQName); + } + requestedAttr.getUnknownAttributes().put(attribQName, attribute.getValue()); + } + } +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributesBuilder.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributesBuilder.java new file mode 100644 index 00000000..2d2de292 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributesBuilder.java @@ -0,0 +1,41 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.impl.builder.reqattr; + +import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttributes; +import at.gv.egiz.eaaf.modules.pvp2.impl.reqattr.EaafRequestedAttributesImpl; + +import org.opensaml.saml.common.AbstractSAMLObjectBuilder; + +public class EaafRequestedAttributesBuilder + extends AbstractSAMLObjectBuilder<EaafRequestedAttributes> { + + @Override + public EaafRequestedAttributes buildObject() { + return buildObject(EaafRequestedAttributes.DEFAULT_ELEMENT_NAME); + } + + @Override + public EaafRequestedAttributes buildObject(final String namespaceUri, final String localName, + final String namespacePrefix) { + return new EaafRequestedAttributesImpl(namespaceUri, localName, namespacePrefix); + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributesMarshaller.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributesMarshaller.java new file mode 100644 index 00000000..5d1e0679 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributesMarshaller.java @@ -0,0 +1,26 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.impl.builder.reqattr; + +import org.opensaml.saml.common.AbstractSAMLObjectMarshaller; + +public class EaafRequestedAttributesMarshaller extends AbstractSAMLObjectMarshaller { + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributesUnmarshaller.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributesUnmarshaller.java new file mode 100644 index 00000000..9934c502 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/builder/reqattr/EaafRequestedAttributesUnmarshaller.java @@ -0,0 +1,42 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.impl.builder.reqattr; + +import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttribute; +import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttributes; + +import org.opensaml.core.xml.XMLObject; +import org.opensaml.core.xml.io.UnmarshallingException; +import org.opensaml.saml.common.AbstractSAMLObjectUnmarshaller; + +public class EaafRequestedAttributesUnmarshaller extends AbstractSAMLObjectUnmarshaller { + @Override + protected final void processChildElement(final XMLObject parentObject, + final XMLObject childObject) throws UnmarshallingException { + final EaafRequestedAttributes attrStatement = (EaafRequestedAttributes) parentObject; + if (childObject instanceof EaafRequestedAttribute) { + attrStatement.getAttributes().add((EaafRequestedAttribute) childObject); + + } else { + super.processChildElement(parentObject, childObject); + } + + } +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/logging/PvpModuleMessageSource.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/logging/PvpModuleMessageSource.java new file mode 100644 index 00000000..227ff30e --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/logging/PvpModuleMessageSource.java @@ -0,0 +1,16 @@ +package at.gv.egiz.eaaf.modules.pvp2.impl.logging; + +import java.util.Arrays; +import java.util.List; + +import at.gv.egiz.eaaf.core.api.logging.IMessageSourceLocation; + +public class PvpModuleMessageSource implements IMessageSourceLocation { + + @Override + public List<String> getMessageSourceLocation() { + return Arrays.asList("classpath:messages/pvp_messages"); + + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/InboundMessage.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/InboundMessage.java index 452fa553..f77243c2 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/InboundMessage.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/InboundMessage.java @@ -1,123 +1,167 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 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: + * Licensed under the EUPL, Version 1.2 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: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * 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. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * 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.egiz.eaaf.modules.pvp2.impl.message; +import java.io.IOException; import java.io.Serializable; -import org.opensaml.saml2.metadata.EntityDescriptor; -import org.opensaml.saml2.metadata.provider.MetadataProviderException; +import javax.annotation.Nonnull; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.TransformerException; + +import org.opensaml.saml.saml2.metadata.EntityDescriptor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Element; +import org.xml.sax.SAXException; +import at.gv.egiz.eaaf.core.impl.utils.DomUtils; import at.gv.egiz.eaaf.modules.pvp2.api.message.InboundMessageInterface; -import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPVPMetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; import at.gv.egiz.eaaf.modules.pvp2.exception.NoMetadataInformationException; - -/** - * @author tlenz - * - */ -public class InboundMessage implements InboundMessageInterface, Serializable{ - private static final Logger log = LoggerFactory.getLogger(InboundMessage.class); - - private static final long serialVersionUID = 2395131650841669663L; - - private Element samlMessage = null; - private boolean verified = false; - private String entityID = null; - private String relayState = null; - - - public EntityDescriptor getEntityMetadata(IPVPMetadataProvider metadataProvider) throws NoMetadataInformationException { - try { - if (metadataProvider == null) - throw new NullPointerException("No PVP MetadataProvider found."); - - return metadataProvider.getEntityDescriptor(this.entityID); - - } catch (MetadataProviderException e) { - log.warn("No Metadata for EntitiyID " + entityID); - throw new NoMetadataInformationException(); - } - } - - /** - * @param entitiyID the entitiyID to set - */ - public void setEntityID(String entitiyID) { - this.entityID = entitiyID; - } - - public void setVerified(boolean verified) { - this.verified = verified; - } - - /** - * @param relayState the relayState to set - */ - public void setRelayState(String relayState) { - this.relayState = relayState; - } - - public void setSAMLMessage(Element msg) { - this.samlMessage = msg; - } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.protocols.pvp2x.messages.PVP21InboundMessage#getRelayState() - */ - @Override - public String getRelayState() { - return relayState; - } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.protocols.pvp2x.messages.PVP21InboundMessage#getEntityID() - */ - @Override - public String getEntityID() { - return entityID; - } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.protocols.pvp2x.messages.PVP21InboundMessage#isVerified() - */ - @Override - public boolean isVerified() { - return verified; - } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.protocols.pvp2x.messages.PVP21InboundMessage#getInboundMessage() - */ - @Override - public Element getInboundMessage() { - return samlMessage; - } +import net.shibboleth.utilities.java.support.resolver.ResolverException; + +public class InboundMessage implements InboundMessageInterface, Serializable { + private static final Logger log = LoggerFactory.getLogger(InboundMessage.class); + + private static final long serialVersionUID = 2395131650841669663L; + + private transient Element samlMessage = null; + private boolean verified = false; + private String entityID = null; + private String relayState = null; + + private String serializedSamlMessage; + + /** + * Get SAML2 metadata for Entity that sends this request. + * + * @param metadataProvider Metadataprovider + * @return EntityDescriptor from metadata + * @throws NoMetadataInformationException In case of an error + */ + public EntityDescriptor getEntityMetadata(@Nonnull final IPvp2MetadataProvider metadataProvider) + throws NoMetadataInformationException { + try { + return metadataProvider.getEntityDescriptor(this.entityID); + + } catch (final ResolverException e) { + log.warn("No Metadata for EntitiyID " + entityID); + throw new NoMetadataInformationException(); + + } + } + + /** + * Set EntitId of requester. + * + * @param entitiyID the entitiyID to set + */ + public void setEntityID(final String entitiyID) { + this.entityID = entitiyID; + } + + public void setVerified(final boolean verified) { + this.verified = verified; + } + + /** + * Set relayState from requester. + * + * @param relayState the relayState to set + */ + public void setRelayState(final String relayState) { + this.relayState = relayState; + } + + /** + * Set full SAML2 message. + * + * @param msg message + */ + public void setSamlMessage(final Element msg) { + this.samlMessage = msg; + try { + this.serializedSamlMessage = DomUtils.serializeNode(msg); + + } catch (TransformerException | IOException e) { + log.warn("Can not serialize message", e); + + } + } + + /* + * (non-Javadoc) + * + * @see at.gv.egovernment.moa.id.protocols.pvp2x.messages.PVP21InboundMessage# + * getRelayState() + */ + @Override + public String getRelayState() { + return relayState; + } + + /* + * (non-Javadoc) + * + * @see at.gv.egovernment.moa.id.protocols.pvp2x.messages.PVP21InboundMessage# + * getEntityID() + */ + @Override + public String getEntityID() { + return entityID; + } + + /* + * (non-Javadoc) + * + * @see at.gv.egovernment.moa.id.protocols.pvp2x.messages.PVP21InboundMessage# + * isVerified() + */ + @Override + public boolean isVerified() { + return verified; + } + + /* + * (non-Javadoc) + * + * @see at.gv.egovernment.moa.id.protocols.pvp2x.messages.PVP21InboundMessage# + * getInboundMessage() + */ + @Override + public Element getInboundMessage() { + if (this.samlMessage != null) { + return samlMessage; + + } else { + try { + return DomUtils.parseDocument(serializedSamlMessage, false, null, null).getDocumentElement(); + + } catch (SAXException | IOException | ParserConfigurationException e) { + throw new RuntimeException(e); + + } + + } + + } } diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/PVPSProfileRequest.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/PVPSProfileRequest.java deleted file mode 100644 index 9c9c913d..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/PVPSProfileRequest.java +++ /dev/null @@ -1,69 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.impl.message; - - -import org.opensaml.Configuration; -import org.opensaml.xml.io.Unmarshaller; -import org.opensaml.xml.io.UnmarshallerFactory; -import org.opensaml.xml.io.UnmarshallingException; -import org.opensaml.xml.signature.SignableXMLObject; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class PVPSProfileRequest extends InboundMessage{ - private static final Logger log = LoggerFactory.getLogger(PVPSProfileRequest.class); - - private static final long serialVersionUID = 8613921176727607896L; - - private String binding = null; - - public PVPSProfileRequest(SignableXMLObject inboundMessage, String binding) { - setSAMLMessage(inboundMessage.getDOM()); - this.binding = binding; - - } - - public String getRequestBinding() { - return binding; - } - - public SignableXMLObject getSamlRequest() { - UnmarshallerFactory unmarshallerFactory = Configuration.getUnmarshallerFactory(); - Unmarshaller unmashaller = unmarshallerFactory.getUnmarshaller(getInboundMessage()); - - try { - return (SignableXMLObject) unmashaller.unmarshall(getInboundMessage()); - - } catch (UnmarshallingException e) { - log.warn("AuthnRequest Unmarshaller error", e); - return null; - } - - } - -} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/PVPSProfileResponse.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/PVPSProfileResponse.java deleted file mode 100644 index 107aa731..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/PVPSProfileResponse.java +++ /dev/null @@ -1,61 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.impl.message; - -import org.opensaml.Configuration; -import org.opensaml.saml2.core.StatusResponseType; -import org.opensaml.xml.io.Unmarshaller; -import org.opensaml.xml.io.UnmarshallerFactory; -import org.opensaml.xml.io.UnmarshallingException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class PVPSProfileResponse extends InboundMessage { - - private static final Logger log = LoggerFactory.getLogger(PVPSProfileResponse.class); - - private static final long serialVersionUID = -1133012928130138501L; - - public PVPSProfileResponse(StatusResponseType response) { - setSAMLMessage(response.getDOM()); - } - - public StatusResponseType getResponse() { - UnmarshallerFactory unmarshallerFactory = Configuration.getUnmarshallerFactory(); - Unmarshaller unmashaller = unmarshallerFactory.getUnmarshaller(getInboundMessage()); - - try { - return (StatusResponseType) unmashaller.unmarshall(getInboundMessage()); - - } catch (UnmarshallingException e) { - log.warn("AuthnResponse Unmarshaller error", e); - return null; - } - - } - -} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/PvpSProfileRequest.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/PvpSProfileRequest.java new file mode 100644 index 00000000..c6068769 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/PvpSProfileRequest.java @@ -0,0 +1,73 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.impl.message; + +import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport; +import org.opensaml.core.xml.io.Unmarshaller; +import org.opensaml.core.xml.io.UnmarshallerFactory; +import org.opensaml.core.xml.io.UnmarshallingException; +import org.opensaml.xmlsec.signature.SignableXMLObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class PvpSProfileRequest extends InboundMessage { + private static final Logger log = LoggerFactory.getLogger(PvpSProfileRequest.class); + + private static final long serialVersionUID = 8613921176727607896L; + + private String binding = null; + + /** + * PVP2 S-Profil request DAO. + * + * @param inboundMessage SAML2 request object + * @param binding Used SAML2 binding + */ + public PvpSProfileRequest(final SignableXMLObject inboundMessage, final String binding) { + setSamlMessage(inboundMessage.getDOM()); + this.binding = binding; + + } + + public String getRequestBinding() { + return binding; + } + + /** + * Get SAML2 request object. + * + * @return + */ + public SignableXMLObject getSamlRequest() { + final UnmarshallerFactory unmarshallerFactory = + XMLObjectProviderRegistrySupport.getUnmarshallerFactory(); + final Unmarshaller unmashaller = unmarshallerFactory.getUnmarshaller(getInboundMessage()); + + try { + return (SignableXMLObject) unmashaller.unmarshall(getInboundMessage()); + + } catch (final UnmarshallingException e) { + log.warn("AuthnRequest Unmarshaller error", e); + return null; + } + + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/PvpSProfileResponse.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/PvpSProfileResponse.java new file mode 100644 index 00000000..4ad21fbc --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/message/PvpSProfileResponse.java @@ -0,0 +1,60 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.impl.message; + +import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport; +import org.opensaml.core.xml.io.Unmarshaller; +import org.opensaml.core.xml.io.UnmarshallerFactory; +import org.opensaml.core.xml.io.UnmarshallingException; +import org.opensaml.saml.saml2.core.StatusResponseType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class PvpSProfileResponse extends InboundMessage { + + private static final Logger log = LoggerFactory.getLogger(PvpSProfileResponse.class); + + private static final long serialVersionUID = -1133012928130138501L; + + public PvpSProfileResponse(final StatusResponseType response) { + setSamlMessage(response.getDOM()); + } + + /** + * Get SAML2 Response object. + * + * @return + */ + public StatusResponseType getResponse() { + final UnmarshallerFactory unmarshallerFactory = + XMLObjectProviderRegistrySupport.getUnmarshallerFactory(); + final Unmarshaller unmashaller = unmarshallerFactory.getUnmarshaller(getInboundMessage()); + + try { + return (StatusResponseType) unmashaller.unmarshall(getInboundMessage()); + + } catch (final UnmarshallingException e) { + log.warn("AuthnResponse Unmarshaller error", e); + return null; + } + + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/AbstractChainingMetadataProvider.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/AbstractChainingMetadataProvider.java index 08ef26ab..40448b45 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/AbstractChainingMetadataProvider.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/AbstractChainingMetadataProvider.java @@ -1,470 +1,530 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 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: + * Licensed under the EUPL, Version 1.2 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: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * 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. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * 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.egiz.eaaf.modules.pvp2.impl.metadata; import java.io.IOException; import java.security.cert.CertificateException; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Timer; -import javax.xml.namespace.QName; - -import org.apache.commons.lang3.StringUtils; -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.HTTPMetadataProvider; -import org.opensaml.saml2.metadata.provider.MetadataFilter; -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.slf4j.Logger; -import org.slf4j.LoggerFactory; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import javax.naming.ConfigurationException; import at.gv.egiz.components.spring.api.IDestroyableObject; import at.gv.egiz.eaaf.core.api.IGarbageCollectorProcessing; -import at.gv.egiz.eaaf.core.exceptions.EAAFConfigurationException; -import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPVPMetadataProvider; +import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvpAddableChainingMetadataProvider; import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IRefreshableMetadataProvider; -public abstract class AbstractChainingMetadataProvider extends SimpleMetadataProvider - implements ObservableMetadataProvider, IGarbageCollectorProcessing, - IRefreshableMetadataProvider, IDestroyableObject, IPVPMetadataProvider { - - private static final Logger log = LoggerFactory.getLogger(AbstractChainingMetadataProvider.class); - - private MetadataProvider internalProvider = null; - private static Object mutex = new Object(); - private Timer timer = null; - - - public AbstractChainingMetadataProvider() { - internalProvider = new ChainingMetadataProvider(); - - } - - public final Timer getTimer() { - return this.timer; - - } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.config.auth.IGarbageCollectorProcessing#runGarbageCollector() - */ - @Override - public void runGarbageCollector() { - synchronized (mutex) { - /**add new Metadataprovider or remove Metadataprovider which are not in use any more.**/ - try { - log.trace("Check consistence of PVP2X metadata"); - addAndRemoveMetadataProvider(); - - } catch (EAAFConfigurationException e) { - log.error("Access to MOA-ID configuration FAILED.", e); - - } - } - - } - - public void fullyDestroy() { - internalDestroy(); - - } - - @Override - public synchronized boolean refreshMetadataProvider(String entityID) { - try { - //check if metadata provider is already loaded - try { - if (internalProvider.getEntityDescriptor(entityID) != null) - return true; - - } catch (MetadataProviderException e) {} - - - //reload metadata provider - String metadataURL = getMetadataURL(entityID); - if (StringUtils.isNotEmpty(metadataURL)) { - Map<String, HTTPMetadataProvider> actuallyLoadedProviders = getAllActuallyLoadedProviders(); - - // check if MetadataProvider is actually loaded - if (actuallyLoadedProviders.containsKey(metadataURL)) { - actuallyLoadedProviders.get(metadataURL).refresh(); - log.info("SAML2 metadata for service provider: " - + entityID + " is refreshed."); - return true; - - } else { - //load new Metadata Provider - if (timer == null) - timer = new Timer(true); - - ChainingMetadataProvider chainProvider = (ChainingMetadataProvider) internalProvider; - chainProvider.addMetadataProvider(createNewMetadataProvider(entityID)); - - emitChangeEvent(); - log.info("SAML2 metadata for service provider: " - + entityID + " is added."); - return true; - - } - - } else - log.debug("Can not refresh SAML2 metadata: NO SAML2 metadata URL for SP with Id: " + entityID); - - } catch (MetadataProviderException e) { - log.warn("Refresh SAML2 metadata for service provider: " - + entityID + " FAILED.", e); - - } catch (IOException e) { - log.warn("Refresh SAML2 metadata for service provider: " - + entityID + " FAILED.", e); - - } catch (EAAFConfigurationException e) { - log.warn("Refresh SAML2 metadata for service provider: " - + entityID + " FAILED.", e); - - } catch (CertificateException e) { - log.warn("Refresh SAML2 metadata for service provider: " - + entityID + " FAILED.", e); - - } - - return false; - - } - - public void internalDestroy() { - if (internalProvider != null && internalProvider instanceof ChainingMetadataProvider) { - log.info("Destrorying PVP-Authentication MetaDataProvider."); - ChainingMetadataProvider chainProvider = (ChainingMetadataProvider) internalProvider; - - List<MetadataProvider> providers = chainProvider.getProviders(); - for (MetadataProvider provider : providers) { - if (provider instanceof HTTPMetadataProvider) { - HTTPMetadataProvider httpprovider = (HTTPMetadataProvider) provider; - log.debug("Destroy HTTPMetadataProvider +" + httpprovider.getMetadataURI()); - httpprovider.destroy(); - - } else { - log.warn("MetadataProvider can not be destroyed."); - } - } - - internalProvider = new ChainingMetadataProvider(); - - if (timer != null) - timer.cancel(); - - } else { - log.warn("ReInitalize MOAMetaDataProvider is not possible! MOA-ID Instance has to be restarted manualy"); - } - } - - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.protocols.pvp2x.metadata.IEAAFMetadataProvider#requireValidMetadata() - */ - @Override - public boolean requireValidMetadata() { - return internalProvider.requireValidMetadata(); - } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.protocols.pvp2x.metadata.IEAAFMetadataProvider#setRequireValidMetadata(boolean) - */ - @Override - public void setRequireValidMetadata(boolean requireValidMetadata) { - internalProvider.setRequireValidMetadata(requireValidMetadata); - } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.protocols.pvp2x.metadata.IEAAFMetadataProvider#getMetadataFilter() - */ - @Override - public MetadataFilter getMetadataFilter() { - return internalProvider.getMetadataFilter(); - } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.protocols.pvp2x.metadata.IEAAFMetadataProvider#setMetadataFilter(org.opensaml.saml2.metadata.provider.MetadataFilter) - */ - @Override - public void setMetadataFilter(MetadataFilter newFilter) - throws MetadataProviderException { - internalProvider.setMetadataFilter(newFilter); - } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.protocols.pvp2x.metadata.IEAAFMetadataProvider#getMetadata() - */ - @Override - public XMLObject getMetadata() throws MetadataProviderException { - return internalProvider.getMetadata(); - } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.protocols.pvp2x.metadata.IEAAFMetadataProvider#getEntitiesDescriptor(java.lang.String) - */ - @Override - public EntitiesDescriptor getEntitiesDescriptor(String entitiesID) - throws MetadataProviderException { - EntitiesDescriptor entitiesDesc = null; - try { - entitiesDesc = internalProvider.getEntitiesDescriptor(entitiesID); - - if (entitiesDesc == null) { - log.debug("Can not find PVP metadata for entityID: " + entitiesID - + " Start refreshing process ..."); - if (refreshMetadataProvider(entitiesID)) - return internalProvider.getEntitiesDescriptor(entitiesID); - - } - - } catch (MetadataProviderException e) { - log.debug("Can not find PVP metadata for entityID: " + entitiesID - + " Start refreshing process ..."); - if (refreshMetadataProvider(entitiesID)) - return internalProvider.getEntitiesDescriptor(entitiesID); - - } - - return entitiesDesc; - } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.protocols.pvp2x.metadata.IEAAFMetadataProvider#getEntityDescriptor(java.lang.String) - */ - @Override - public EntityDescriptor getEntityDescriptor(String entityID) - throws MetadataProviderException { - EntityDescriptor entityDesc = null; - try { - entityDesc = internalProvider.getEntityDescriptor(entityID); - if (entityDesc == null) { - log.debug("Can not find PVP metadata for entityID: " + entityID - + " Start refreshing process ..."); - if (refreshMetadataProvider(entityID)) - return internalProvider.getEntityDescriptor(entityID); - - } - - } catch (MetadataProviderException e) { - log.debug("Can not find PVP metadata for entityID: " + entityID - + " Start refreshing process ..."); - if (refreshMetadataProvider(entityID)) - return internalProvider.getEntityDescriptor(entityID); - - } - -// if (entityDesc != null) -// lastAccess.put(entityID, new Date()); - - return entityDesc; - } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.protocols.pvp2x.metadata.IEAAFMetadataProvider#getRole(java.lang.String, javax.xml.namespace.QName) - */ - @Override - public List<RoleDescriptor> getRole(String entityID, QName roleName) - throws MetadataProviderException { - List<RoleDescriptor> result = internalProvider.getRole(entityID, roleName); - -// if (result != null) -// lastAccess.put(entityID, new Date()); - - return result; - } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.protocols.pvp2x.metadata.IEAAFMetadataProvider#getRole(java.lang.String, javax.xml.namespace.QName, java.lang.String) - */ - @Override - public RoleDescriptor getRole(String entityID, QName roleName, - String supportedProtocol) throws MetadataProviderException { - RoleDescriptor result = internalProvider.getRole(entityID, roleName, supportedProtocol); - -// if (result != null) -// lastAccess.put(entityID, new Date()); - - return result; - } - - /* (non-Javadoc) - * @see org.opensaml.saml2.metadata.provider.ObservableMetadataProvider#getObservers() - */ - @Override - public List<Observer> getObservers() { - return ((ChainingMetadataProvider) internalProvider).getObservers(); - } - - - /** - * Get the URL to metadata for a specific entityID - * - * @param entityId - * @return - * @throws EAAFConfigurationException - */ - protected abstract String getMetadataURL(String entityId) throws EAAFConfigurationException; - - /** - * Creates a new implementation specific SAML2 metadata provider - * - * @param entityId - * @return - * @throws EAAFConfigurationException - * @throws IOException - * @throws CertificateException - * @throws ConfigurationException - */ - protected abstract MetadataProvider createNewMetadataProvider(String entityId) throws EAAFConfigurationException, IOException, CertificateException; - - /** - * Get a List of metadata URLs for all SAML2 SPs from configuration - * - * @throws EAAFConfigurationException - */ - protected abstract List<String> getAllMetadataURLsFromConfiguration() throws EAAFConfigurationException; - - - protected void emitChangeEvent() { - if ((getObservers() == null) || (getObservers().size() == 0)) { - return; - } - - List<Observer> tempObserverList = new ArrayList<Observer>(getObservers()); - for (ObservableMetadataProvider.Observer observer : tempObserverList) - if (observer != null) - observer.onEvent(this); - } - - private Map<String, HTTPMetadataProvider> getAllActuallyLoadedProviders() { - Map<String, HTTPMetadataProvider> loadedproviders = new HashMap<String, HTTPMetadataProvider>(); - ChainingMetadataProvider chainProvider = (ChainingMetadataProvider) internalProvider; - - //make a Map of all actually loaded HTTPMetadataProvider - List<MetadataProvider> providers = chainProvider.getProviders(); - for (MetadataProvider provider : providers) { - if (provider instanceof HTTPMetadataProvider) { - HTTPMetadataProvider httpprovider = (HTTPMetadataProvider) provider; - loadedproviders.put(httpprovider.getMetadataURI(), httpprovider); - - } - } - - return loadedproviders; - } - - private void addAndRemoveMetadataProvider() throws EAAFConfigurationException { - if (internalProvider != null && internalProvider instanceof ChainingMetadataProvider) { - log.info("Reload MOAMetaDataProvider."); - - /*OpenSAML ChainingMetadataProvider can not remove a MetadataProvider (UnsupportedOperationException) - *The ChainingMetadataProvider use internal a unmodifiableList to hold all registrated MetadataProviders.*/ - Map<String, MetadataProvider> providersinuse = new HashMap<String, MetadataProvider>(); - ChainingMetadataProvider chainProvider = (ChainingMetadataProvider) internalProvider; - - //get all actually loaded metadata providers - Map<String, HTTPMetadataProvider> loadedproviders = getAllActuallyLoadedProviders(); - - /* TODO: maybe add metadata provider destroy after timeout. - * But could be a problem if one Metadataprovider load an EntitiesDescriptor - * with more the multiple EntityDescriptors. If one of this EntityDesciptors - * are expired the full EntitiesDescriptor is removed. - * - * Timeout requires a better solution in this case! - */ - - //load all SAML2 SPs form configuration and - //compare actually loaded Providers with configured SAML2 SPs - List<String> allMetadataURLs = getAllMetadataURLsFromConfiguration(); - - if (allMetadataURLs != null) { - Iterator<String> metadataURLInterator = allMetadataURLs.iterator(); - while (metadataURLInterator.hasNext()) { - String metadataurl = metadataURLInterator.next(); - try { - if (StringUtils.isNotEmpty(metadataurl)) { - if (loadedproviders.containsKey(metadataurl)) { - // SAML2 SP is actually loaded, to nothing - providersinuse.put(metadataurl, loadedproviders.get(metadataurl)); - loadedproviders.remove(metadataurl); - - } - } - } catch (Throwable e) { - log.error( - "Failed to add Metadata (unhandled reason: " + e.getMessage(), e); - - } - } - } - - //remove all actually loaded MetadataProviders with are not in ConfigurationDB any more - Collection<HTTPMetadataProvider> notusedproviders = loadedproviders.values(); - for (HTTPMetadataProvider provider : notusedproviders) { - String metadataurl = provider.getMetadataURI(); - try { - provider.destroy(); - - /*OpenSAML ChainingMetadataProvider can not remove a MetadataProvider (UnsupportedOperationException) - *The ChainingMetadataProvider use internal a unmodifiableList to hold all registrated MetadataProviders.*/ - //chainProvider.removeMetadataProvider(provider); - log.info("Remove not used MetadataProvider with MetadataURL " + metadataurl); - - } catch (Throwable e) { - log.error("HTTPMetadataProvider with URL " + metadataurl - + " can not be removed from the list of actually loaded Providers.", e); - - } - - } - - try { - chainProvider.setProviders(new ArrayList<MetadataProvider>(providersinuse.values())); - emitChangeEvent(); - - } catch (MetadataProviderException e) { - log.warn("ReInitalize AbstractMetaDataProvider is not possible! Service has to be restarted manualy", e); - - } - - } else - log.warn("ReInitalize AbstractMetaDataProvider is not possible! Service has to be restarted manualy"); - - } +import org.apache.commons.lang3.StringUtils; +import org.joda.time.DateTime; +import org.opensaml.core.criterion.EntityIdCriterion; +import org.opensaml.saml.metadata.resolver.ClearableMetadataResolver; +import org.opensaml.saml.metadata.resolver.MetadataResolver; +import org.opensaml.saml.metadata.resolver.RefreshableMetadataResolver; +import org.opensaml.saml.metadata.resolver.filter.MetadataFilter; +import org.opensaml.saml.metadata.resolver.impl.AbstractMetadataResolver; +import org.opensaml.saml.saml2.metadata.EntityDescriptor; + +import lombok.extern.slf4j.Slf4j; +import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements; +import net.shibboleth.utilities.java.support.component.IdentifiedComponent; +import net.shibboleth.utilities.java.support.resolver.CriteriaSet; +import net.shibboleth.utilities.java.support.resolver.ResolverException; + +@Slf4j +public abstract class AbstractChainingMetadataProvider implements IGarbageCollectorProcessing, + IRefreshableMetadataProvider, IPvpAddableChainingMetadataProvider, + IDestroyableObject, IPvp2MetadataProvider, ClearableMetadataResolver { + + @Nonnull + @NonnullElements + private final List<MetadataResolver> internalResolvers; + private DateTime lastRefeshTimestamp; + private boolean lastRefeshSuccessful; + private static Object mutex = new Object(); + + /** + * Build a chaining metadata resolver that requires valid metadata. + * + */ + public AbstractChainingMetadataProvider() { + internalResolvers = Collections.synchronizedList(new ArrayList<>()); + + } + + /* + * (non-Javadoc) + * + * @see at.gv.egovernment.moa.id.config.auth.IGarbageCollectorProcessing# + * runGarbageCollector() + */ + @Override + public void runGarbageCollector() { + synchronized (mutex) { + /* + * add new Metadataprovider or remove Metadataprovider which are not in use any + * more. + */ + try { + log.trace("Check consistence of PVP2X metadata"); + addAndRemoveMetadataProvider(); + + } catch (final EaafConfigurationException e) { + log.error("Access to MOA-ID configuration FAILED.", e); + + } + } + + } + + @Override + public void fullyDestroy() { + internalDestroy(); + + } + + @Override + public synchronized boolean refreshMetadataProvider(final String entityId) { + try { + //if (resolveEntityDescriporForRefesh(entityId)) { + // return true; + // + //} + + // reload metadata provider + final String metadataUrl = getMetadataUrl(entityId); + if (StringUtils.isNotEmpty(metadataUrl)) { + final Map<String, MetadataResolver> actuallyLoadedResolver = + getAllActuallyLoadedResolvers(); + + // check if MetadataProvider is actually loaded + final MetadataResolver loadedResover = actuallyLoadedResolver.get(metadataUrl); + if (loadedResover instanceof RefreshableMetadataResolver) { + try { + ((RefreshableMetadataResolver) loadedResover).refresh(); + log.info("SAML2 metadata for service provider: {} is refreshed.", entityId); + return true; + + } catch (final ResolverException e) { + log.info("Can not refresh SAML2 metadata for entityId: {}. Reason: {}", entityId, e.getMessage()); + destroyMetadataResolver(loadedResover); + internalResolvers.remove(loadedResover); + + } + + } else { + // load new Metadata Provider + internalResolvers.add(createNewMetadataProvider(metadataUrl)); + + log.info("SAML2 metadata for service provider: {} is added.", entityId); + return true; + + } + + } else { + log.debug( + "Can not refresh SAML2 metadata: NO SAML2 metadata URL for SP with Id: {}", entityId); + } + + } catch (final IOException | EaafConfigurationException | CertificateException e) { + log.warn("Refresh SAML2 metadata for service provider: " + entityId + " FAILED.", e); + + } + + return false; + + } + + + @Override + public final MetadataFilter getMetadataFilter() { + log.warn("{} does NOT support {}", AbstractChainingMetadataProvider.class.getName(), + MetadataFilter.class.getName()); + return null; + } + + @Override + public final void setMetadataFilter(final MetadataFilter newFilter) { + log.warn("{} does NOT support {}", AbstractChainingMetadataProvider.class.getName(), + MetadataFilter.class.getName()); + throw new UnsupportedOperationException( + "Metadata filters are not supported on AbstractChainingMetadataProvider"); + } + + /* + * (non-Javadoc) + * + * @see at.gv.egovernment.moa.id.protocols.pvp2x.metadata.IEAAFMetadataProvider# + * getEntityDescriptor( java.lang.String) + */ + @Override + public final EntityDescriptor getEntityDescriptor(final String entityID) + throws ResolverException { + EntityDescriptor entityDesc = null; + try { + entityDesc = resolveEntityDescripor(entityID); + if (entityDesc == null) { + log.debug("Can not find PVP metadata for entityID: " + entityID + + " Start refreshing process ..."); + if (refreshMetadataProvider(entityID)) { + return resolveEntityDescripor(entityID); + } + } + + } catch (final ResolverException e) { + log.debug( + "Can not find PVP metadata for entityID: " + entityID + " Start refreshing process ..."); + if (refreshMetadataProvider(entityID)) { + return resolveEntityDescripor(entityID); + + } + + } + + return entityDesc; + } + + @Override + @Nullable + public final EntityDescriptor resolveSingle(@Nullable final CriteriaSet criteria) + throws ResolverException { + EntityDescriptor result = internalResolveSingle(criteria); + if (result == null && criteria != null) { + final EntityIdCriterion entityIdCriteria = criteria.get(EntityIdCriterion.class); + if (entityIdCriteria != null + && refreshMetadataProvider(entityIdCriteria.getEntityId())) { + log.debug("Can not find PVP metadata for entityID: {}. Metadata refreshing was done ... ", + entityIdCriteria.getEntityId()); + result = internalResolveSingle(criteria); + + } + } + + return result; + + } + + @Override + @Nonnull + public final Iterable<EntityDescriptor> resolve(@Nullable final CriteriaSet criteria) + throws ResolverException { + Iterable<EntityDescriptor> result = internalResolve(criteria); + if (criteria != null) { + final EntityIdCriterion entityIdCriteria = criteria.get(EntityIdCriterion.class); + if (!result.iterator().hasNext() && entityIdCriteria != null + && refreshMetadataProvider(entityIdCriteria.getEntityId())) { + log.debug("Can not find PVP metadata for entityID: {}. Metadata refreshing was done ... ", + entityIdCriteria.getEntityId()); + result = internalResolve(criteria); + } + } + + return result; + } + + @Override + public final void clear() throws ResolverException { + for (final MetadataResolver resolver : internalResolvers) { + if (resolver instanceof ClearableMetadataResolver) { + ((ClearableMetadataResolver) resolver).clear(); + } + } + } + + @Override + public final void clear(String entityID) throws ResolverException { + for (final MetadataResolver resolver : internalResolvers) { + if (resolver instanceof ClearableMetadataResolver) { + ((ClearableMetadataResolver) resolver).clear(entityID); + } + } + } + + @Override + public final void refresh() throws ResolverException { + this.lastRefeshSuccessful = false; + for (final MetadataResolver resolver : internalResolvers) { + if (resolver instanceof RefreshableMetadataResolver) { + ((RefreshableMetadataResolver) resolver).refresh(); + + } + } + + this.lastRefeshTimestamp = DateTime.now(); + this.lastRefeshSuccessful = true; + } + + @Override + @Nullable + public final DateTime getLastUpdate() { + DateTime ret = null; + for (final MetadataResolver resolver : internalResolvers) { + if (resolver instanceof RefreshableMetadataResolver) { + final DateTime lastUpdate = ((RefreshableMetadataResolver) resolver).getLastUpdate(); + if (ret == null || ret.isBefore(lastUpdate)) { + ret = lastUpdate; + } + } + } + + return ret; + } + + @Override + @Nullable + public final DateTime getLastRefresh() { + DateTime ret = null; + for (final MetadataResolver resolver : internalResolvers) { + if (resolver instanceof RefreshableMetadataResolver) { + final DateTime lastRefresh = ((RefreshableMetadataResolver) resolver).getLastRefresh(); + if (ret == null || ret.isBefore(lastRefresh)) { + ret = lastRefresh; + } + } + } + + return ret; + } + + @Override + public final DateTime getLastSuccessfulRefresh() { + return this.lastRefeshTimestamp; + + } + + @Override + public final Boolean wasLastRefreshSuccess() { + return this.lastRefeshSuccessful; + + } + + @Override + public final boolean isRequireValidMetadata() { + log.warn("Attempt to access unsupported requireValidMetadata property on ChainingMetadataResolver"); + return false; + } + + @Override + public final void setRequireValidMetadata(final boolean requireValidMetadata) { + throw new UnsupportedOperationException( + "Setting requireValidMetadata is not supported on chaining resolver"); + } + + @Override + public final String getId() { + return getMetadataProviderId(); + + } + + @Override + public final void addMetadataResolverIntoChain(MetadataResolver resolver) { + internalResolvers.add(resolver); + + } + + /** + * Get the URL to metadata for a specific entityID. + * + * @param entityId EntityId + * @return URL to metadata + * @throws EaafConfigurationException In case of an error + */ + protected abstract String getMetadataUrl(String entityId) throws EaafConfigurationException; + + /** + * Creates a new implementation specific SAML2 metadata provider. + * + * @param entityId EntityId + * @return MetadataResolver + * @throws EaafConfigurationException In case of an error + * @throws IOException In case of an error + * @throws CertificateException In case of an error + * @throws ConfigurationException In case of an error + */ + protected abstract MetadataResolver createNewMetadataProvider(String entityId) + throws EaafConfigurationException, IOException, CertificateException; + + /** + * Get a List of metadata URLs for all SAML2 SPs from configuration. + * + * @throws EaafConfigurationException In case of an error + */ + @Nonnull + protected abstract List<String> getAllMetadataUrlsFromConfiguration() + throws EaafConfigurationException; + + /** + * Get a Id for this metadata provider. + * + * @return + */ + @Nonnull + protected abstract String getMetadataProviderId(); + + protected final MetadataResolver getMetadataResolver() { + log.warn("{} does NOT support 'getMetadataResolver'", AbstractChainingMetadataProvider.class.getName()); + return null; + + } + + private Map<String, MetadataResolver> getAllActuallyLoadedResolvers() { + final Map<String, MetadataResolver> loadedproviders = + new HashMap<>(); + + // make a Map of all actually loaded HTTPMetadataProvider + for (final MetadataResolver resolver : internalResolvers) { + loadedproviders.put(((IdentifiedComponent) resolver).getId(), resolver); + + } + + return loadedproviders; + } + + private void addAndRemoveMetadataProvider() throws EaafConfigurationException { + log.info("EAAF chaining metadata resolver starting internal managment task .... "); + + // get all actually loaded metadata providers + final Map<String, MetadataResolver> loadedproviders = getAllActuallyLoadedResolvers(); + + /* + * TODO: maybe add metadata provider destroy after timeout. But could be a + * problem if one Metadataprovider load an EntitiesDescriptor with more the + * multiple EntityDescriptors. If one of this EntityDesciptors are expired the + * full EntitiesDescriptor is removed. + * + * Timeout requires a better solution in this case! + */ + + // load all SAML2 SPs form configuration and + // compare actually loaded Providers with configured SAML2 SPs + final List<String> allMetadataUrls = getAllMetadataUrlsFromConfiguration(); + + final Iterator<String> metadataUrlInterator = allMetadataUrls.iterator(); + while (metadataUrlInterator.hasNext()) { + final String metadataurl = metadataUrlInterator.next(); + try { + if (StringUtils.isNotEmpty(metadataurl) + && loadedproviders.containsKey(metadataurl)) { + // SAML2 SP is actually loaded, to nothing + loadedproviders.remove(metadataurl); + + } + } catch (final Throwable e) { + log.error("Failed to add Metadata (unhandled reason: " + e.getMessage(), e); + + } + } + + // remove all actually loaded MetadataProviders with are not in ConfigurationDB + // any more + final Collection<MetadataResolver> notusedproviders = loadedproviders.values(); + for (final MetadataResolver resolver : notusedproviders) { + log.info("Remove not used MetadataProvider with MetadataURL " + resolver.getId()); + destroyMetadataResolver(resolver); + internalResolvers.remove(resolver); + + } + + } + + private EntityDescriptor resolveEntityDescripor(String entityId) throws ResolverException { + final CriteriaSet criteria = new CriteriaSet(); + criteria.add(new EntityIdCriterion(entityId)); + return internalResolveSingle(criteria); + + } + + private void destroyMetadataResolver(MetadataResolver resolver) { + if (resolver instanceof AbstractMetadataResolver) { + final AbstractMetadataResolver httpprovider = (AbstractMetadataResolver) resolver; + log.debug("Destroy metadata resolver with id: {}", httpprovider.getId()); + httpprovider.destroy(); + + } else { + log.warn("Metadata resolver: {} can not be destroyed. Reason: unsupported type: {}", + resolver.getId(), resolver.getClass().getName()); + + } + } + + /** + * Close metadata provider and remove all loaded metadata. + * + */ + private void internalDestroy() { + log.info("Destroying chained metadata resolvers ..."); + + for (final MetadataResolver resolver : internalResolvers) { + destroyMetadataResolver(resolver); + } + + internalResolvers.clear(); + + } + + @Nullable + private EntityDescriptor internalResolveSingle(@Nullable final CriteriaSet criteria) + throws ResolverException { + for (final MetadataResolver resolver : internalResolvers) { + try { + final EntityDescriptor descriptors = resolver.resolveSingle(criteria); + if (descriptors != null) { + return descriptors; + } + + } catch (final ResolverException e) { + continue; + + } + } + + return null; + + } + + @Nonnull + private Iterable<EntityDescriptor> internalResolve(@Nullable final CriteriaSet criteria) + throws ResolverException { + for (final MetadataResolver resolver : internalResolvers) { + try { + final Iterable<EntityDescriptor> descriptors = resolver.resolve(criteria); + if (descriptors != null && descriptors.iterator().hasNext()) { + return descriptors; + + } + + } catch (final ResolverException e) { + continue; + + } + } + + return Collections.emptyList(); + } + } diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/MetadataFilterChain.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/MetadataFilterChain.java deleted file mode 100644 index 06065a82..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/MetadataFilterChain.java +++ /dev/null @@ -1,80 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.impl.metadata; - -import java.util.ArrayList; -import java.util.List; - -import org.opensaml.saml2.metadata.provider.FilterException; -import org.opensaml.saml2.metadata.provider.MetadataFilter; -import org.opensaml.xml.XMLObject; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - - -/** - * @author tlenz - * - */ -public class MetadataFilterChain implements MetadataFilter { - private static final Logger log = LoggerFactory.getLogger(MetadataFilterChain.class); - - - private List<MetadataFilter> filters = new ArrayList<MetadataFilter>(); - - /** - * Return all actually used Metadata filters - * - * @return List of Metadata filters - */ - public List<MetadataFilter> getFilters() { - return filters; - } - - /** - * Add a new Metadata filter to filterchain - * - * @param filter - */ - public void addFilter(MetadataFilter filter) { - filters.add(filter); - } - - - /* (non-Javadoc) - * @see org.opensaml.saml2.metadata.provider.MetadataFilter#doFilter(org.opensaml.xml.XMLObject) - */ - @Override - public void doFilter(XMLObject arg0) throws FilterException { - for (MetadataFilter filter : filters) { - log.trace("Use EAAFMetadataFilter " + filter.getClass().getName()); - filter.doFilter(arg0); - } - - } - -} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/PvpMetadataResolverAdapter.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/PvpMetadataResolverAdapter.java new file mode 100644 index 00000000..d2b861dc --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/PvpMetadataResolverAdapter.java @@ -0,0 +1,115 @@ +package at.gv.egiz.eaaf.modules.pvp2.impl.metadata; + +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IRefreshableMetadataProvider; + +import org.joda.time.DateTime; +import org.opensaml.core.criterion.EntityIdCriterion; +import org.opensaml.saml.metadata.resolver.ExtendedRefreshableMetadataResolver; +import org.opensaml.saml.metadata.resolver.filter.MetadataFilter; +import org.opensaml.saml.saml2.metadata.EntityDescriptor; + +import lombok.extern.slf4j.Slf4j; +import net.shibboleth.utilities.java.support.resolver.CriteriaSet; +import net.shibboleth.utilities.java.support.resolver.ResolverException; + +@Slf4j +public class PvpMetadataResolverAdapter implements IPvp2MetadataProvider, IRefreshableMetadataProvider { + + private final ExtendedRefreshableMetadataResolver internalProvider; + + public PvpMetadataResolverAdapter(ExtendedRefreshableMetadataResolver provider) { + this.internalProvider = provider; + } + + @Override + public void refresh() throws ResolverException { + internalProvider.refresh(); + + } + + @Override + public DateTime getLastRefresh() { + return internalProvider.getLastRefresh(); + + } + + @Override + public DateTime getLastUpdate() { + return internalProvider.getLastUpdate(); + } + + @Override + public boolean isRequireValidMetadata() { + return internalProvider.isRequireValidMetadata(); + + } + + @Override + public void setRequireValidMetadata(boolean requireValidMetadata) { + internalProvider.setRequireValidMetadata(requireValidMetadata); + + } + + @Override + public MetadataFilter getMetadataFilter() { + return internalProvider.getMetadataFilter(); + + } + + @Override + public void setMetadataFilter(MetadataFilter newFilter) { + internalProvider.setMetadataFilter(newFilter); + + } + + @Override + public Iterable<EntityDescriptor> resolve(CriteriaSet criteria) throws ResolverException { + return internalProvider.resolve(criteria); + } + + @Override + public EntityDescriptor resolveSingle(CriteriaSet criteria) throws ResolverException { + return internalProvider.resolveSingle(criteria); + + } + + @Override + public String getId() { + return internalProvider.getId(); + } + + @Override + public EntityDescriptor getEntityDescriptor(String entityId) throws ResolverException { + final CriteriaSet criteria = new CriteriaSet(); + criteria.add(new EntityIdCriterion(entityId)); + return internalProvider.resolveSingle(criteria); + + } + + @Override + public DateTime getLastSuccessfulRefresh() { + return internalProvider.getLastSuccessfulRefresh(); + } + + @Override + public Boolean wasLastRefreshSuccess() { + return internalProvider.wasLastRefreshSuccess(); + } + + @Override + public boolean refreshMetadataProvider(String entityID) { + try { + log.trace("Refeshing metadata-provider: {} ... ", getId()); + internalProvider.refresh(); + return true; + + } catch (final ResolverException e) { + log.warn("Refreshing of metadata-provider: {} failed. Reason: {}", + getId(), e.getMessage()); + return false; + + } + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/PvpMetadataResolverFactory.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/PvpMetadataResolverFactory.java new file mode 100644 index 00000000..0b505e56 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/PvpMetadataResolverFactory.java @@ -0,0 +1,278 @@ +package at.gv.egiz.eaaf.modules.pvp2.impl.metadata; + +import java.io.IOException; +import java.util.Timer; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import javax.annotation.PostConstruct; +import javax.net.ssl.SSLHandshakeException; + +import at.gv.egiz.components.spring.api.IDestroyableObject; +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.core.impl.utils.FileUtils; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2MetadataException; +import at.gv.egiz.eaaf.modules.pvp2.exception.SchemaValidationException; +import at.gv.egiz.eaaf.modules.pvp2.exception.SignatureValidationException; +import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.OpenSaml3ResourceAdapter; + +import org.apache.http.client.HttpClient; +import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport; +import org.opensaml.saml.metadata.resolver.ExtendedRefreshableMetadataResolver; +import org.opensaml.saml.metadata.resolver.filter.MetadataFilter; +import org.opensaml.saml.metadata.resolver.impl.AbstractReloadingMetadataResolver; +import org.opensaml.saml.metadata.resolver.impl.HTTPMetadataResolver; +import org.opensaml.saml.metadata.resolver.impl.ResourceBackedMetadataResolver; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.ResourceLoader; + +import com.google.common.base.Predicates; +import com.google.common.base.Throwables; +import com.google.common.collect.FluentIterable; +import lombok.extern.slf4j.Slf4j; +import net.shibboleth.utilities.java.support.component.ComponentInitializationException; +import net.shibboleth.utilities.java.support.resolver.ResolverException; +import net.shibboleth.utilities.java.support.resource.Resource; +import net.shibboleth.utilities.java.support.xml.ParserPool; + +@Slf4j +public class PvpMetadataResolverFactory implements IDestroyableObject { + + private static final String URI_PREFIX_HTTP = "http:"; + private static final String URI_PREFIX_HTTPS = "https:"; + + private static final String NOT_SUCCESS = "Maybe metadata was expired"; + + private Timer timer = null; + + @Autowired + private IConfiguration authConfig; + @Autowired + private ResourceLoader resourceLoader; + + /** + * Create a single SAML2 metadata provider by using the default OpenSAML3 + * parser-pool. + * + * @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 httpClient Apache commons 4.x http client + * + * @return SAML2 Metadata Provider, or null if the metadata provider can not + * initialized + * @throws Pvp2MetadataException In case of an initialization error + */ + @Nullable + public IPvp2MetadataProvider createMetadataProvider(@Nonnull final String metadataLocation, + @Nullable final MetadataFilter filter, @Nonnull final String idForLogging, + @Nullable final HttpClient httpClient) throws Pvp2MetadataException { + return createMetadataProvider(metadataLocation, filter, idForLogging, + XMLObjectProviderRegistrySupport.getParserPool(), + httpClient); + + } + + /** + * Create a single SAML2 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 httpClient Apache commons 4.x http client + * + * @return SAML2 Metadata Provider, or null if the metadata provider can not + * initialized + * @throws Pvp2MetadataException In case of an initialization error + */ + @Nullable + public IPvp2MetadataProvider createMetadataProvider(@Nonnull final String metadataLocation, + @Nullable final MetadataFilter filter, @Nonnull final String idForLogging, + @Nullable final ParserPool pool, @Nullable final HttpClient httpClient) throws Pvp2MetadataException { + + ExtendedRefreshableMetadataResolver internalProvider = null; + + try { + if (metadataLocation.startsWith(URI_PREFIX_HTTP) + || metadataLocation.startsWith(URI_PREFIX_HTTPS)) { + internalProvider = createNewHttpMetaDataProvider(metadataLocation, filter, + idForLogging, timer, pool, httpClient); + + } else { + final String absoluteMetadataLocation = + FileUtils.makeAbsoluteUrl(metadataLocation, authConfig.getConfigurationRootDirectory()); + final org.springframework.core.io.Resource resource = + resourceLoader.getResource(absoluteMetadataLocation); + + if (resource.exists()) { + internalProvider = createNewFileSystemMetaDataProvider( + new OpenSaml3ResourceAdapter(resource), + filter, idForLogging, timer, + pool); + + } else { + log.warn( + "SAML2 metadata file: {} not found or not exist", absoluteMetadataLocation); + throw new Pvp2MetadataException("internal.pvp.05", + new Object[] { absoluteMetadataLocation, "File NOT found or exist." }); + + } + } + + } catch (final ComponentInitializationException e) { + log.warn("Failed to load Metadata file for {} [ {} ]", + idForLogging, e.getMessage()); + checkResolverInitializationError(e, metadataLocation); + + } catch (final Exception e) { + throw new Pvp2MetadataException("internal.pvp.09", new Object[] { metadataLocation, e.getMessage() }); + + } + + if (!internalProvider.wasLastRefreshSuccess()) { + log.info("Metadata loading from source: {} failed. {}", metadataLocation, NOT_SUCCESS); + throw new Pvp2MetadataException("internal.pvp.09", new Object[] { metadataLocation, NOT_SUCCESS }); + + } + + return new PvpMetadataResolverAdapter(internalProvider); + + } + + @Override + public void fullyDestroy() { + if (timer != null) { + log.info("Stopping timer-thread for PVP metadata resolver ... "); + timer.cancel(); + } + } + + @PostConstruct + private void initialize() { + log.info("Initializing timer-thread for PVP metadata resolver ... "); + timer = new Timer("PVP metadata-resolver refresh"); + + } + + /** + * 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 SAML2 parser pool that should be used + * + * @return SAML2 Metadata Provider + * @throws IOException In case of a metadata resource error + * @throws ComponentInitializationException In case of a metadata resolver + * initialization error + */ + private ExtendedRefreshableMetadataResolver createNewFileSystemMetaDataProvider(final Resource metadataFile, + final MetadataFilter filter, final String idForLogging, final Timer timer, + final ParserPool pool) throws IOException, ComponentInitializationException { + ResourceBackedMetadataResolver fileSystemResolver = null; + fileSystemResolver = new ResourceBackedMetadataResolver(timer, metadataFile); + injectMetadataResolverConfiguration(fileSystemResolver, filter, pool); + fileSystemResolver.setId(metadataFile.getURI().toASCIIString()); + fileSystemResolver.initialize(); + + log.trace("Set-up metadata-resolver with ID: {} as: {}", + idForLogging, fileSystemResolver.getClass().getSimpleName()); + + return fileSystemResolver; + + } + + /** + * Create a single SAML2 HTTP metadata provider. + * + * @param metadataUrl URL, 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 SAML2 parser pool that should be used + * @return SAML2 Metadata Provider + * @throws ComponentInitializationException In case of a metadata resolver + * initialization error + * @throws ResolverException In case of an internal OpenSAML + * resolver error + */ + private ExtendedRefreshableMetadataResolver createNewHttpMetaDataProvider(final String metadataUrl, + final MetadataFilter filter, final String idForLogging, final Timer timer, + final ParserPool pool, final HttpClient httpClient) throws ComponentInitializationException, + ResolverException { + HTTPMetadataResolver httpMetadataResolver = null; + httpMetadataResolver = new HTTPMetadataResolver(timer, httpClient, metadataUrl); + injectMetadataResolverConfiguration(httpMetadataResolver, filter, pool); + httpMetadataResolver.setId(metadataUrl); + httpMetadataResolver.initialize(); + + log.trace("Set-up metadata-resolver with ID: {} as: {}", + idForLogging, httpMetadataResolver.getClass().getSimpleName()); + + return httpMetadataResolver; + + } + + private void injectMetadataResolverConfiguration(AbstractReloadingMetadataResolver resolver, + final MetadataFilter filter, final ParserPool pool) { + if (pool != null) { + resolver.setParserPool(pool); + + } else { + resolver.setParserPool( + XMLObjectProviderRegistrySupport.getParserPool()); + + } + + resolver.setRequireValidMetadata(true); + resolver.setMinRefreshDelay(1000 * 60 * 15); // 15 minutes + resolver.setMaxRefreshDelay(1000 * 60 * 60 * 24); // 24 hours + resolver.setMetadataFilter(filter); + + } + + private void checkResolverInitializationError(ComponentInitializationException e, String metadataLocation) + throws Pvp2MetadataException { + if (FluentIterable.from(Throwables.getCausalChain(e)).filter( + Predicates.instanceOf(SSLHandshakeException.class)).first().isPresent()) { + log.info("SSL-Server certificate for metadata: {} not trusted.", metadataLocation, null, e); + throw new Pvp2MetadataException("internal.pvp.06", new Object[] { metadataLocation, e.getMessage() }, + e); + + } else if (FluentIterable.from(Throwables.getCausalChain(e)).filter( + Predicates.instanceOf(SignatureValidationException.class)).first().isPresent()) { + log.info("Signature verification for metadata: {} FAILED.", metadataLocation, null, e); + throw new Pvp2MetadataException("internal.pvp.07", new Object[] { metadataLocation, e.getMessage() }, + e); + + } else if (FluentIterable.from(Throwables.getCausalChain(e)).filter( + Predicates.instanceOf(SchemaValidationException.class)).first().isPresent()) { + log.info("Schema validation for metadata: {} FAILED.", metadataLocation, null, e); + throw new Pvp2MetadataException("internal.pvp.08", new Object[] { metadataLocation, e.getMessage() }, + e); + + } else { + log.info("Generic initialization error for metadata: {}", metadataLocation, null, e); + throw new Pvp2MetadataException("internal.pvp.09", new Object[] { metadataLocation, e.getMessage() }, + e); + + } + + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/SimpleMetadataProvider.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/SimpleMetadataProvider.java deleted file mode 100644 index c16ca5fd..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/SimpleMetadataProvider.java +++ /dev/null @@ -1,236 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.impl.metadata; - -import java.io.File; -import java.net.MalformedURLException; -import java.util.Timer; - -import javax.net.ssl.SSLHandshakeException; - -import org.apache.commons.httpclient.HttpClient; -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.ParserPool; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; - -import at.gv.egiz.eaaf.core.api.idp.IConfiguration; -import at.gv.egiz.eaaf.core.impl.utils.FileUtils; -import at.gv.egiz.eaaf.modules.pvp2.exception.SchemaValidationException; -import at.gv.egiz.eaaf.modules.pvp2.exception.SignatureValidationException; - -/** - * @author tlenz - * - */ -public abstract class SimpleMetadataProvider implements MetadataProvider{ - private static final Logger log = LoggerFactory.getLogger(SimpleMetadataProvider.class); - - 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 IConfiguration authConfig; - - - /** - * Create a single SAML2 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 - * @param httpClient Apache commons 3.x http client - * - * @return SAML2 Metadata Provider, or null if the metadata provider can not initialized - */ - protected MetadataProvider createNewSimpleMetadataProvider(String metadataLocation, MetadataFilter filter, - String IdForLogging, Timer timer, ParserPool pool, HttpClient httpClient) { - if (metadataLocation.startsWith(URI_PREFIX_HTTP) || metadataLocation.startsWith(URI_PREFIX_HTTPS)) { - if (httpClient != null) - return createNewHTTPMetaDataProvider(metadataLocation, filter, IdForLogging, timer, pool, httpClient); - - else { - log.warn("Can not load http(s) based SAML2 metadata without a HTTP client"); - return null; - } - - } else { - String absoluteMetadataLocation; - try { - absoluteMetadataLocation = FileUtils.makeAbsoluteURL( - metadataLocation, - authConfig.getConfigurationRootDirectory()); - - if (absoluteMetadataLocation.startsWith(URI_PREFIX_FILE)) { - File metadataFile = new File(absoluteMetadataLocation); - if (metadataFile.exists()) - return createNewFileSystemMetaDataProvider(metadataFile, filter, IdForLogging, timer, pool); - - else { - log.warn("SAML2 metadata file: " + absoluteMetadataLocation + " not found or not exist"); - return null; - } - - } - - - } catch (MalformedURLException e) { - log.warn("SAML2 metadata URL is invalid: " + metadataLocation, e); - - } - - } - - log.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) { - log.warn( - "Failed to load Metadata file for " - + IdForLogging + "[ " - + "File: " + metadataFile.getAbsolutePath() - + " Msg: " + e.getMessage() + " ]", e); - - - log.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 - * - * @param metadataURL URL, 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 createNewHTTPMetaDataProvider(String metadataURL, MetadataFilter filter, String IdForLogging, Timer timer, ParserPool pool, HttpClient httpClient) { - HTTPMetadataProvider httpProvider = null; - try { - httpProvider = new HTTPMetadataProvider(timer, httpClient, - metadataURL); - httpProvider.setParserPool(pool); - httpProvider.setRequireValidMetadata(true); - httpProvider.setMinRefreshDelay(1000*60*15); //15 minutes - httpProvider.setMaxRefreshDelay(1000*60*60*24); //24 hours - //httpProvider.setRefreshDelayFactor(0.1F); - - httpProvider.setMetadataFilter(filter); - httpProvider.initialize(); - - httpProvider.setRequireValidMetadata(true); - - return httpProvider; - - } catch (Throwable e) { - if (e.getCause() != null && e.getCause().getCause() instanceof SSLHandshakeException) { - log.warn("SSL-Server certificate for metadata " - + metadataURL + " not trusted.", e); - - } if (e.getCause() != null && e.getCause().getCause() instanceof SignatureValidationException) { - log.warn("Signature verification for metadata" - + metadataURL + " FAILED.", e); - - } if (e.getCause() != null && e.getCause().getCause() instanceof SchemaValidationException) { - log.warn("Schema validation for metadata " - + metadataURL + " FAILED.", e); - } - - log.warn( - "Failed to load Metadata file for " - + IdForLogging + "[ " - + e.getMessage() + " ]", e); - - if (httpProvider != null) { - log.debug("Destroy failed Metadata provider"); - httpProvider.destroy(); - } - -// if (timer != null) { -// log.debug("Destroy Timer."); -// timer.cancel(); -// } - - - } - - return null; - } - -} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafHttpPostDecoder.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafHttpPostDecoder.java new file mode 100644 index 00000000..fdd44b9a --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafHttpPostDecoder.java @@ -0,0 +1,79 @@ +package at.gv.egiz.eaaf.modules.pvp2.impl.opensaml; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; + +import javax.servlet.http.HttpServletRequest; + +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.SamlHttpUtils; + +import org.opensaml.core.xml.XMLObject; +import org.opensaml.messaging.decoder.MessageDecodingException; +import org.opensaml.saml.saml2.binding.decoding.impl.HTTPPostDecoder; + +import com.google.common.base.Strings; +import lombok.extern.slf4j.Slf4j; +import net.shibboleth.utilities.java.support.codec.Base64Support; + +/** + * SAML2 Post-Binding decoder with same EAAF specific hardening regarding http + * request-parameter processing. + * + * @author tlenz + * + */ +@Slf4j +public class EaafHttpPostDecoder extends HTTPPostDecoder { + + private static final String SAML_REQ_PARAM_NAME = "SAMLRequest"; + private static final String SAML_RESP_PARAM_NAME = "SAMLResponse"; + + public EaafHttpPostDecoder(HttpServletRequest req) { + setHttpServletRequest(req); + } + + @Override + protected InputStream getBase64DecodedMessage(final HttpServletRequest request) + throws MessageDecodingException { + + log.debug("Getting Base64 encoded message from request"); + String encodedMessage = SamlHttpUtils.getLastParameterFromRequest(request, SAML_REQ_PARAM_NAME); + if (Strings.isNullOrEmpty(encodedMessage)) { + encodedMessage = SamlHttpUtils.getLastParameterFromRequest(request, SAML_RESP_PARAM_NAME); + + } + + if (Strings.isNullOrEmpty(encodedMessage)) { + log.info("Request did not contain either a SAMLRequest or " + + "SAMLResponse paramter. Invalid request for SAML 2 HTTP POST binding."); + throw new MessageDecodingException("No SAML message present in request"); + } + + log.trace("Base64 decoding SAML message: {}", encodedMessage); + final byte[] decodedBytes = Base64Support.decode(encodedMessage); + + try { + log.trace("Decoded SAML message: {}", new String(decodedBytes, "UTF-8")); + + } catch (final UnsupportedEncodingException e) { + log.warn("Logging of incomming message failed", e); + + } + + return new ByteArrayInputStream(decodedBytes); + } + + /** + * EAAF specific unmarshaller perform XML schema validation before unmarshalling + * the SAML message. + * + */ + @Override + protected XMLObject unmarshallMessage(final InputStream messageStream) throws MessageDecodingException { + return Saml2Utils.unmarshallMessage(messageStream); + + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafHttpRedirectDeflateDecoder.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafHttpRedirectDeflateDecoder.java new file mode 100644 index 00000000..c5174f02 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafHttpRedirectDeflateDecoder.java @@ -0,0 +1,97 @@ +package at.gv.egiz.eaaf.modules.pvp2.impl.opensaml; + +import java.io.InputStream; + +import javax.servlet.http.HttpServletRequest; + +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.SamlHttpUtils; + +import org.opensaml.core.xml.XMLObject; +import org.opensaml.messaging.context.MessageContext; +import org.opensaml.messaging.decoder.MessageDecodingException; +import org.opensaml.saml.common.SAMLObject; +import org.opensaml.saml.common.binding.SAMLBindingSupport; +import org.opensaml.saml.common.xml.SAMLConstants; +import org.opensaml.saml.saml2.binding.decoding.impl.HTTPRedirectDeflateDecoder; + +import com.google.common.base.Strings; +import lombok.extern.slf4j.Slf4j; +import net.shibboleth.utilities.java.support.primitive.StringSupport; + +/** + * SAML2 Redirect-Binding deflate decoder with same EAAF specific hardening + * regarding http request-parameter processing. + * + * @author tlenz + * + */ +@Slf4j +public class EaafHttpRedirectDeflateDecoder extends HTTPRedirectDeflateDecoder { + + private static final String SAML_REQ_PARAM_NAME = "SAMLRequest"; + private static final String SAML_RESP_PARAM_NAME = "SAMLResponse"; + + public EaafHttpRedirectDeflateDecoder(HttpServletRequest req) { + setHttpServletRequest(req); + + } + + @Override + protected void doDecode() throws MessageDecodingException { + final MessageContext<SAMLObject> messageContext = new MessageContext<>(); + final HttpServletRequest request = getHttpServletRequest(); + + if (!"GET".equalsIgnoreCase(request.getMethod())) { + throw new MessageDecodingException("This message decoder only supports the HTTP GET method"); + } + + final String samlEncoding = StringSupport.trimOrNull(request.getParameter("SAMLEncoding")); + if (samlEncoding != null && !SAMLConstants.SAML2_BINDING_URL_ENCODING_DEFLATE_URI.equals(samlEncoding)) { + throw new MessageDecodingException("Request indicated an unsupported SAMLEncoding: " + samlEncoding); + + } + + final String relayState = request.getParameter("RelayState"); + log.debug("Decoded RelayState: {}", relayState); + SAMLBindingSupport.setRelayState(messageContext, relayState); + + final InputStream samlMessageIns; + + // implement parameter extraction as same as in + // SAML2HTTPRedirectDeflateSignatureSecurityHandler.java + final String samlReq = SamlHttpUtils.getLastParameterFromRequest(request, SAML_REQ_PARAM_NAME); + final String samlResp = SamlHttpUtils.getLastParameterFromRequest(request, SAML_RESP_PARAM_NAME); + if (!Strings.isNullOrEmpty(samlReq)) { + samlMessageIns = decodeMessage(samlReq); + + } else if (!Strings.isNullOrEmpty(samlResp)) { + samlMessageIns = decodeMessage(samlResp); + + } else { + throw new MessageDecodingException( + "No SAMLRequest or SAMLResponse query path parameter, invalid SAML 2 HTTP Redirect message"); + } + + final SAMLObject samlMessage = (SAMLObject) unmarshallMessage(samlMessageIns); + messageContext.setMessage(samlMessage); + log.debug("Decoded SAML message"); + + populateBindingContext(messageContext); + + setMessageContext(messageContext); + + } + + /** + * EAAF specific unmarshaller perform XML schema validation before unmarshalling + * the SAML message. + * + */ + @Override + protected XMLObject unmarshallMessage(final InputStream messageStream) throws MessageDecodingException { + return Saml2Utils.unmarshallMessage(messageStream); + + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafKeyStoreX509CredentialAdapter.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafKeyStoreX509CredentialAdapter.java new file mode 100644 index 00000000..1611d623 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/EaafKeyStoreX509CredentialAdapter.java @@ -0,0 +1,122 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.impl.opensaml; + +import java.security.KeyStore; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import at.gv.egiz.eaaf.modules.pvp2.PvpConstants; +import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential; +import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlSigningException; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils; + +import org.opensaml.security.x509.X509Credential; +import org.opensaml.security.x509.impl.KeyStoreX509CredentialAdapter; + +import lombok.extern.slf4j.Slf4j; + +/** + * OpenSAML2 KeyStore adapter. + * + * @author tlenz + * + */ +@Slf4j +public class EaafKeyStoreX509CredentialAdapter extends KeyStoreX509CredentialAdapter + implements EaafX509Credential { + + private String signatureAlgorithmtToUse; + private String keyEncryptionAlgorithmtToUse; + + /** + * Get an OpenSAML2 keystore. + * + * @param store Java KeyStore + * @param alias Key alias + * @param password key Password + * @param keyStoreFriendlyName Friendlyname of this keystore for logging + * purposes + * @throws CredentialsNotAvailableException In case of an initialization + * exception + */ + public EaafKeyStoreX509CredentialAdapter(@Nonnull final KeyStore store, @Nonnull final String alias, + @Nullable final char[] password, @Nonnull String keyStoreFriendlyName) + throws CredentialsNotAvailableException { + super(store, alias, password); + + if (getPrivateKey() == null && getSecretKey() == null) { + log.error("KeyStore: {} Key with alias: {} not found or contains no PrivateKey.", + keyStoreFriendlyName, alias); + throw new CredentialsNotAvailableException("internal.pvp.00", + new Object[] { keyStoreFriendlyName, alias }); + + } + + try { + setSignatureAlgorithmForSigning(Saml2Utils.getKeyOperationAlgorithmFromCredential(this, + PvpConstants.DEFAULT_SIGNING_METHODE_RSA, + PvpConstants.DEFAULT_SIGNING_METHODE_EC)); + + setKeyEncryptionAlgorithmForDataEncryption( + Saml2Utils.getKeyOperationAlgorithmFromCredential(this, + PvpConstants.DEFAULT_ASYM_ENCRYPTION_METHODE_RSA, + PvpConstants.DEFAULT_ASYM_ENCRYPTION_METHODE_EC)); + + } catch (final SamlSigningException e) { + throw new CredentialsNotAvailableException("internal.pvp.01", new Object[] { keyStoreFriendlyName, + alias }, e); + + } + + } + + @Override + public Class<? extends X509Credential> getCredentialType() { + return X509Credential.class; + } + + @Override + public String getSignatureAlgorithmForSigning() { + return this.signatureAlgorithmtToUse; + + } + + @Override + public void setSignatureAlgorithmForSigning(String sigAlg) { + this.signatureAlgorithmtToUse = sigAlg; + + } + + @Override + public String getKeyEncryptionAlgorithmForDataEncryption() { + return this.keyEncryptionAlgorithmtToUse; + + } + + @Override + public void setKeyEncryptionAlgorithmForDataEncryption(String sigAlg) { + this.keyEncryptionAlgorithmtToUse = sigAlg; + + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/HTTPPostEncoderWithOwnTemplate.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/HTTPPostEncoderWithOwnTemplate.java deleted file mode 100644 index 8af12acc..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/HTTPPostEncoderWithOwnTemplate.java +++ /dev/null @@ -1,122 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.impl.opensaml; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.io.Writer; - -import org.apache.velocity.VelocityContext; -import org.apache.velocity.app.VelocityEngine; -import org.opensaml.common.binding.SAMLMessageContext; -import org.opensaml.saml2.binding.encoding.HTTPPostEncoder; -import org.opensaml.ws.message.encoder.MessageEncodingException; -import org.opensaml.ws.transport.http.HTTPOutTransport; -import org.opensaml.ws.transport.http.HTTPTransportUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import at.gv.egiz.eaaf.core.api.gui.IVelocityGUIBuilderConfiguration; -import at.gv.egiz.eaaf.core.api.gui.IVelocityGuiFormBuilder; - -/** - * @author tlenz - * - */ -public class HTTPPostEncoderWithOwnTemplate extends HTTPPostEncoder { - private static final Logger log = LoggerFactory.getLogger(HTTPPostEncoderWithOwnTemplate.class); - - - private final VelocityEngine velocityEngine; - private final IVelocityGUIBuilderConfiguration guiConfig; - private final IVelocityGuiFormBuilder guiBuilder; - - /** - * @param engine - * @param templateId - */ - public HTTPPostEncoderWithOwnTemplate(IVelocityGUIBuilderConfiguration guiConfig, IVelocityGuiFormBuilder guiBuilder, VelocityEngine engine) { - super(engine, null); - this.velocityEngine = engine; - this.guiConfig = guiConfig; - this.guiBuilder = guiBuilder; - - } - - /** - * Base64 and POST encodes the outbound message and writes it to the outbound transport. - * - * @param messageContext current message context - * @param endpointURL endpoint URL to which to encode message - * - * @throws MessageEncodingException thrown if there is a problem encoding the message - */ - @Override - protected void postEncode(SAMLMessageContext messageContext, String endpointURL) throws MessageEncodingException { - log.debug("Invoking Velocity template to create POST body"); - InputStream is = null; - try { - //build Velocity Context from GUI input paramters - final VelocityContext context = guiBuilder.generateVelocityContextFromConfiguration(guiConfig); - - //load template - is = guiBuilder.getTemplateInputStream(guiConfig); - - //populate velocity context with SAML2 parameters - populateVelocityContext(context, messageContext, endpointURL); - - //populate transport parameter - final HTTPOutTransport outTransport = (HTTPOutTransport) messageContext.getOutboundMessageTransport(); - HTTPTransportUtils.addNoCacheHeaders(outTransport); - HTTPTransportUtils.setUTF8Encoding(outTransport); - HTTPTransportUtils.setContentType(outTransport, "text/html"); - - //evaluate template and write content to response - final Writer out = new OutputStreamWriter(outTransport.getOutgoingStream(), "UTF-8"); - velocityEngine.evaluate(context, out, "SAML2_POST_BINDING", new BufferedReader(new InputStreamReader(is))); - out.flush(); - - } catch (final Exception e) { - log.error("Error invoking Velocity template", e); - throw new MessageEncodingException("Error creating output document", e); - - } finally { - if (is != null) { - try { - is.close(); - - } catch (final IOException e) { - log.error("Can NOT close GUI-Template InputStream.", e); - } - } - - } - } -} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/HttpPostEncoderWithOwnTemplate.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/HttpPostEncoderWithOwnTemplate.java new file mode 100644 index 00000000..fa77b73c --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/HttpPostEncoderWithOwnTemplate.java @@ -0,0 +1,125 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.impl.opensaml; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.Writer; + +import javax.servlet.http.HttpServletResponse; + +import at.gv.egiz.eaaf.core.api.gui.IVelocityGuiBuilderConfiguration; +import at.gv.egiz.eaaf.core.api.gui.IVelocityGuiFormBuilder; +import at.gv.egiz.eaaf.core.impl.gui.velocity.VelocityProvider; + +import org.apache.velocity.VelocityContext; +import org.apache.velocity.app.Velocity; +import org.opensaml.messaging.context.MessageContext; +import org.opensaml.messaging.encoder.MessageEncodingException; +import org.opensaml.saml.common.SAMLObject; +import org.opensaml.saml.saml2.binding.encoding.impl.HTTPPostEncoder; + +import lombok.extern.slf4j.Slf4j; +import net.shibboleth.utilities.java.support.net.HttpServletSupport; + +/** + * OpenSAML2 Post-Binding encoder that uses dynamic loaded templates. + * + * @author tlenz + * + */ +@Slf4j +public class HttpPostEncoderWithOwnTemplate extends HTTPPostEncoder { + + private final IVelocityGuiBuilderConfiguration guiConfig; + private final IVelocityGuiFormBuilder guiBuilder; + + /** + * Own Post-Binding encoder. + * + * @param guiConfig GUI configuration + * @param guiBuilder GUI builder implementation + * @throws Exception In case of a {@link Velocity} initialization error + */ + public HttpPostEncoderWithOwnTemplate(final IVelocityGuiBuilderConfiguration guiConfig, + final IVelocityGuiFormBuilder guiBuilder) throws Exception { + this.guiConfig = guiConfig; + this.guiBuilder = guiBuilder; + + setVelocityEngine(VelocityProvider.getClassPathVelocityEngine()); + + } + + /** + * Base64 and POST encodes the out-bound message and writes it to the out-bound + * transport. + * + * @param messageContext current message context + * + * @throws MessageEncodingException thrown if there is a problem encoding the + * message + */ + @Override + protected void postEncode(final MessageContext<SAMLObject> messageContext, final String endpointUrl) + throws MessageEncodingException { + log.debug("Invoking Velocity template to create POST body"); + InputStream is = null; + try { + // build Velocity Context from GUI input paramters + final VelocityContext context = + guiBuilder.generateVelocityContextFromConfiguration(guiConfig); + + // load template + is = guiBuilder.getTemplateInputStream(guiConfig); + + populateVelocityContext(context, messageContext, endpointUrl); + + final HttpServletResponse response = getHttpServletResponse(); + + HttpServletSupport.addNoCacheHeaders(response); + HttpServletSupport.setUTF8Encoding(response); + HttpServletSupport.setContentType(response, "text/html"); + + final Writer out = new OutputStreamWriter(response.getOutputStream(), "UTF-8"); + getVelocityEngine().evaluate(context, out, "SAML2_POST_BINDING", + new BufferedReader(new InputStreamReader(is, "UTF-8"))); + out.flush(); + + } catch (final Exception e) { + log.error("Error invoking Velocity template", e); + throw new MessageEncodingException("Error creating output document", e); + + } finally { + if (is != null) { + try { + is.close(); + + } catch (final IOException e) { + log.error("Can NOT close GUI-Template InputStream.", e); + } + } + + } + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/KeyStoreX509CredentialAdapter.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/KeyStoreX509CredentialAdapter.java deleted file mode 100644 index 2f3912ca..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/KeyStoreX509CredentialAdapter.java +++ /dev/null @@ -1,56 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.impl.opensaml; - -import java.security.KeyStore; - -import org.opensaml.xml.security.x509.X509Credential; - - -/** - * @author tlenz - * - */ -public class KeyStoreX509CredentialAdapter extends - org.opensaml.xml.security.x509.KeyStoreX509CredentialAdapter { - - /** - * @param store - * @param alias - * @param password - */ - public KeyStoreX509CredentialAdapter(KeyStore store, String alias, - char[] password) { - super(store, alias, password); - } - - public Class<? extends X509Credential> getCredentialType() { - return X509Credential.class; - } - - -} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/OpenSaml3ResourceAdapter.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/OpenSaml3ResourceAdapter.java new file mode 100644 index 00000000..f474267f --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/OpenSaml3ResourceAdapter.java @@ -0,0 +1,86 @@ +package at.gv.egiz.eaaf.modules.pvp2.impl.opensaml; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.URL; + +import net.shibboleth.utilities.java.support.resource.Resource; + +/** + * Adapter that connects a Spring {@link org.springframework.core.io.Resource} + * to a {@link Resource}. + * + * @author tlenz + * + */ +public class OpenSaml3ResourceAdapter implements Resource { + + private final org.springframework.core.io.Resource internalResource; + + public OpenSaml3ResourceAdapter(org.springframework.core.io.Resource resource) { + this.internalResource = resource; + } + + @Override + public boolean exists() { + return internalResource.exists(); + } + + @Override + public boolean isReadable() { + return internalResource.isReadable(); + } + + @Override + public boolean isOpen() { + return internalResource.isOpen(); + } + + @Override + public URL getURL() throws IOException { + return internalResource.getURL(); + } + + @Override + public URI getURI() throws IOException { + return internalResource.getURI(); + } + + @Override + public File getFile() throws IOException { + return internalResource.getFile(); + } + + @Override + public InputStream getInputStream() throws IOException { + return internalResource.getInputStream(); + } + + @Override + public long contentLength() throws IOException { + return internalResource.contentLength(); + } + + @Override + public long lastModified() throws IOException { + return internalResource.lastModified(); + } + + @Override + public Resource createRelativeResource(String relativePath) throws IOException { + throw new IOException("This method is not supperted by this adapter"); + } + + @Override + public String getFilename() { + return internalResource.getFilename(); + } + + @Override + public String getDescription() { + return internalResource.getDescription(); + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/StringRedirectDeflateEncoder.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/StringRedirectDeflateEncoder.java index 544dc9f5..38735fb8 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/StringRedirectDeflateEncoder.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/StringRedirectDeflateEncoder.java @@ -1,81 +1,66 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 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: + * Licensed under the EUPL, Version 1.2 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: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * 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. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * 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.egiz.eaaf.modules.pvp2.impl.opensaml; -import org.opensaml.common.binding.SAMLMessageContext; -import org.opensaml.saml2.binding.encoding.HTTPRedirectDeflateEncoder; -import org.opensaml.ws.message.MessageContext; -import org.opensaml.ws.message.encoder.MessageEncodingException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.opensaml.messaging.context.MessageContext; +import org.opensaml.messaging.encoder.MessageEncodingException; +import org.opensaml.saml.common.SAMLObject; +import org.opensaml.saml.saml2.binding.encoding.impl.HTTPRedirectDeflateEncoder; -import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EAAFDefaultSAML2Bootstrap; +import lombok.extern.slf4j.Slf4j; /** + * Create deflate encoded SAML2 redirect-binding informations. + * * @author tlenz * */ + +@Slf4j public class StringRedirectDeflateEncoder extends HTTPRedirectDeflateEncoder { - private static final Logger log = LoggerFactory.getLogger(StringRedirectDeflateEncoder.class); - - private String redirectURL = null; - - public void encode(MessageContext messageContext) - throws MessageEncodingException { - if (!(messageContext instanceof SAMLMessageContext)) { - log.error("Invalid message context type, this encoder only support SAMLMessageContext"); - throw new MessageEncodingException( - "Invalid message context type, this encoder only support SAMLMessageContext"); - } + private String redirectUrl = null; + + @Override + protected void doEncode() throws MessageEncodingException { + final MessageContext<SAMLObject> messageContext = getMessageContext(); + final SAMLObject outboundMessage = messageContext.getMessage(); + + final String endpointUrl = getEndpointURL(messageContext).toString(); - //load default PVP security configurations - EAAFDefaultSAML2Bootstrap.initializeDefaultPVPConfiguration(); - - SAMLMessageContext samlMsgCtx = (SAMLMessageContext) messageContext; + removeSignature(outboundMessage); - String endpointURL = getEndpointURL(samlMsgCtx).buildURL(); + final String encodedMessage = deflateAndBase64Encode(outboundMessage); - setResponseDestination(samlMsgCtx.getOutboundSAMLMessage(), endpointURL); + redirectUrl = buildRedirectURL(messageContext, endpointUrl, encodedMessage); - removeSignature(samlMsgCtx); + log.trace("SAML2 redirect-binding URL was generated as: {}", redirectUrl); - String encodedMessage = deflateAndBase64Encode(samlMsgCtx - .getOutboundSAMLMessage()); + } - redirectURL = buildRedirectURL(samlMsgCtx, endpointURL, - encodedMessage); - } + /** + * Get generated redirect URL. + * + * @return the redirectURL + */ + public String getRedirectUrl() { + return redirectUrl; + } - /** - * @return the redirectURL - */ - public String getRedirectURL() { - return redirectURL; - } - - } diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EAAFDefaultSAML2Bootstrap.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EAAFDefaultSAML2Bootstrap.java deleted file mode 100644 index 266b6e5f..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EAAFDefaultSAML2Bootstrap.java +++ /dev/null @@ -1,94 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.impl.opensaml.initialize; - -import org.opensaml.Configuration; -import org.opensaml.DefaultBootstrap; -import org.opensaml.xml.ConfigurationException; - -import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EAAFRequestedAttribute; -import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EAAFRequestedAttributes; -import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EAAFRequestedAttributeBuilder; -import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EAAFRequestedAttributeMarshaller; -import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EAAFRequestedAttributeUnmarshaller; -import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EAAFRequestedAttributesBuilder; -import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EAAFRequestedAttributesMarshaller; -import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EAAFRequestedAttributesUnmarshaller; - -/** - * @author tlenz - * - */ -public class EAAFDefaultSAML2Bootstrap extends DefaultBootstrap { - - public static synchronized void bootstrap() throws ConfigurationException { - - initializeXMLSecurity(); - - initializeXMLTooling(); - - initializeArtifactBuilderFactories(); - - initializeGlobalSecurityConfiguration(); - - initializeParserPool(); - - initializeESAPI(); - - initializeExtenstions(); - - } - - private static void initializeExtenstions() { - Configuration.registerObjectProvider( - EAAFRequestedAttribute.DEFAULT_ELEMENT_NAME, - new EAAFRequestedAttributeBuilder(), - new EAAFRequestedAttributeMarshaller(), - new EAAFRequestedAttributeUnmarshaller() - ); - - Configuration.registerObjectProvider( - EAAFRequestedAttributes.DEFAULT_ELEMENT_NAME, - new EAAFRequestedAttributesBuilder(), - new EAAFRequestedAttributesMarshaller(), - new EAAFRequestedAttributesUnmarshaller() - ); - - } - - public static void initializeDefaultPVPConfiguration() { - initializeGlobalSecurityConfiguration(); - - } - - /** - * Initializes the default global security configuration. - */ - protected static void initializeGlobalSecurityConfiguration() { - Configuration.setGlobalSecurityConfiguration(EAAFDefaultSecurityConfigurationBootstrap.buildDefaultConfig()); - } -} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EAAFDefaultSecurityConfigurationBootstrap.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EAAFDefaultSecurityConfigurationBootstrap.java deleted file mode 100644 index ddd5b13e..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EAAFDefaultSecurityConfigurationBootstrap.java +++ /dev/null @@ -1,156 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.impl.opensaml.initialize; - -import org.opensaml.xml.encryption.EncryptionConstants; -import org.opensaml.xml.security.BasicSecurityConfiguration; -import org.opensaml.xml.security.DefaultSecurityConfigurationBootstrap; -import org.opensaml.xml.security.credential.BasicKeyInfoGeneratorFactory; -import org.opensaml.xml.security.keyinfo.KeyInfoGeneratorManager; -import org.opensaml.xml.security.keyinfo.NamedKeyInfoGeneratorManager; -import org.opensaml.xml.security.x509.X509KeyInfoGeneratorFactory; -import org.opensaml.xml.signature.SignatureConstants; - -/** - * @author tlenz - * - */ -public class EAAFDefaultSecurityConfigurationBootstrap extends - DefaultSecurityConfigurationBootstrap { - - public static BasicSecurityConfiguration buildDefaultConfig() { - BasicSecurityConfiguration config = new BasicSecurityConfiguration(); - - populateSignatureParams(config); - populateEncryptionParams(config); - populateKeyInfoCredentialResolverParams(config); - populateKeyInfoGeneratorManager(config); - populateKeyParams(config); - - return config; - } - - protected static void populateKeyInfoGeneratorManager( - BasicSecurityConfiguration config) { - NamedKeyInfoGeneratorManager namedManager = new NamedKeyInfoGeneratorManager(); - config.setKeyInfoGeneratorManager(namedManager); - - namedManager.setUseDefaultManager(true); - KeyInfoGeneratorManager defaultManager = namedManager - .getDefaultManager(); - - BasicKeyInfoGeneratorFactory basicFactory = new BasicKeyInfoGeneratorFactory(); - basicFactory.setEmitPublicKeyValue(true); - - X509KeyInfoGeneratorFactory x509Factory = new X509KeyInfoGeneratorFactory(); - x509Factory.setEmitEntityCertificate(true); - - defaultManager.registerFactory(basicFactory); - defaultManager.registerFactory(x509Factory); - } - - protected static void populateSignatureParams( - BasicSecurityConfiguration config) { - - //use SHA256 instead of SHA1 - config.registerSignatureAlgorithmURI("RSA", - SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256); - - config.registerSignatureAlgorithmURI("DSA", - "http://www.w3.org/2000/09/xmldsig#dsa-sha1"); - - //use SHA256 instead of SHA1 - config.registerSignatureAlgorithmURI("EC", - SignatureConstants.ALGO_ID_SIGNATURE_ECDSA_SHA256); - - //use SHA256 instead of SHA1 - config.registerSignatureAlgorithmURI("AES", - SignatureConstants.ALGO_ID_MAC_HMAC_SHA256); - - - config.registerSignatureAlgorithmURI("DESede", - SignatureConstants.ALGO_ID_MAC_HMAC_SHA256); - - config.setSignatureCanonicalizationAlgorithm("http://www.w3.org/2001/10/xml-exc-c14n#"); - config.setSignatureHMACOutputLength(null); - - //use SHA256 instead of SHA1 - config.setSignatureReferenceDigestMethod(SignatureConstants.ALGO_ID_DIGEST_SHA256); - } - - protected static void populateEncryptionParams( - BasicSecurityConfiguration config) { - config.registerDataEncryptionAlgorithmURI("AES", Integer.valueOf(128), - "http://www.w3.org/2001/04/xmlenc#aes128-cbc"); - config.registerDataEncryptionAlgorithmURI("AES", Integer.valueOf(192), - "http://www.w3.org/2001/04/xmlenc#aes192-cbc"); - config.registerDataEncryptionAlgorithmURI("AES", Integer.valueOf(256), - "http://www.w3.org/2001/04/xmlenc#aes256-cbc"); - - //support GCM mode - config.registerDataEncryptionAlgorithmURI("AES", Integer.valueOf(128), - EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES128_GCM); - - config.registerDataEncryptionAlgorithmURI("AES", Integer.valueOf(192), - EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES192_GCM); - - config.registerDataEncryptionAlgorithmURI("AES", Integer.valueOf(256), - EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES256_GCM); - - - config.registerDataEncryptionAlgorithmURI("DESede", - Integer.valueOf(168), - "http://www.w3.org/2001/04/xmlenc#tripledes-cbc"); - config.registerDataEncryptionAlgorithmURI("DESede", - Integer.valueOf(192), - "http://www.w3.org/2001/04/xmlenc#tripledes-cbc"); - - config.registerKeyTransportEncryptionAlgorithmURI("RSA", null, "AES", - "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"); - - config.registerKeyTransportEncryptionAlgorithmURI("RSA", null, - "DESede", "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"); - - config.registerKeyTransportEncryptionAlgorithmURI("AES", - Integer.valueOf(128), null, - "http://www.w3.org/2001/04/xmlenc#kw-aes128"); - config.registerKeyTransportEncryptionAlgorithmURI("AES", - Integer.valueOf(192), null, - "http://www.w3.org/2001/04/xmlenc#kw-aes192"); - config.registerKeyTransportEncryptionAlgorithmURI("AES", - Integer.valueOf(256), null, - "http://www.w3.org/2001/04/xmlenc#kw-aes256"); - config.registerKeyTransportEncryptionAlgorithmURI("DESede", - Integer.valueOf(168), null, - "http://www.w3.org/2001/04/xmlenc#kw-tripledes"); - config.registerKeyTransportEncryptionAlgorithmURI("DESede", - Integer.valueOf(192), null, - "http://www.w3.org/2001/04/xmlenc#kw-tripledes"); - - config.setAutoGeneratedDataEncryptionKeyAlgorithmURI("http://www.w3.org/2001/04/xmlenc#aes128-cbc"); - } -} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EaafDefaultSecurityConfigurationBootstrap.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EaafDefaultSecurityConfigurationBootstrap.java new file mode 100644 index 00000000..97f0f225 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EaafDefaultSecurityConfigurationBootstrap.java @@ -0,0 +1,177 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.impl.opensaml.initialize; + +import java.util.Arrays; +import java.util.Collections; + +import org.opensaml.xmlsec.config.impl.DefaultSecurityConfigurationBootstrap; +import org.opensaml.xmlsec.encryption.support.EncryptionConstants; +import org.opensaml.xmlsec.encryption.support.RSAOAEPParameters; +import org.opensaml.xmlsec.impl.BasicDecryptionConfiguration; +import org.opensaml.xmlsec.impl.BasicEncryptionConfiguration; +import org.opensaml.xmlsec.impl.BasicSignatureSigningConfiguration; +import org.opensaml.xmlsec.impl.BasicSignatureValidationConfiguration; +import org.opensaml.xmlsec.signature.support.SignatureConstants; + +/** + * EAAF specific OpenSAML2 security configuration. + * + * @author tlenz + * + */ +public class EaafDefaultSecurityConfigurationBootstrap + extends DefaultSecurityConfigurationBootstrap { + + /** + * Set EAAF specific encryption configuration to OpenSAML 3.x. + * + * @return + */ + public static BasicEncryptionConfiguration buildEaafEncryptionConfiguration() { + final BasicEncryptionConfiguration config = new BasicEncryptionConfiguration(); + + config.setBlacklistedAlgorithms(Arrays.asList( + EncryptionConstants.ALGO_ID_KEYTRANSPORT_RSA15, + EncryptionConstants.ALGO_ID_BLOCKCIPHER_TRIPLEDES, + EncryptionConstants.ALGO_ID_KEYWRAP_TRIPLEDES)); + + config.setDataEncryptionAlgorithms(Arrays.asList( + // The order of these is significant. + EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES128, + EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES192, + EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES256, + + // register GCM algorithms + EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES128_GCM, + EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES192_GCM, + EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES256_GCM)); + + config.setKeyTransportEncryptionAlgorithms(Arrays.asList( + // The order of the RSA algos is significant. + EncryptionConstants.ALGO_ID_KEYTRANSPORT_RSAOAEP, + EncryptionConstants.ALGO_ID_KEYTRANSPORT_RSAOAEP11, + + // The order of these is not significant. + // These aren't really "preferences" per se. They just need to be registered + // so that they can be used if a credential with a key of that type and size is + // seen. + EncryptionConstants.ALGO_ID_KEYWRAP_AES128, + EncryptionConstants.ALGO_ID_KEYWRAP_AES192, + EncryptionConstants.ALGO_ID_KEYWRAP_AES256)); + + config.setRSAOAEPParameters(new RSAOAEPParameters( + SignatureConstants.ALGO_ID_DIGEST_SHA1, + EncryptionConstants.ALGO_ID_MGF1_SHA1, + null)); + + config.setDataKeyInfoGeneratorManager(buildDataEncryptionKeyInfoGeneratorManager()); + config.setKeyTransportKeyInfoGeneratorManager(buildKeyTransportEncryptionKeyInfoGeneratorManager()); + + return config; + } + + /** + * Set EAAF specific decryption configuration to OpenSAML 3.x. + * + * @return + */ + public static BasicDecryptionConfiguration buildEaaftDecryptionConfiguration() { + final BasicDecryptionConfiguration config = new BasicDecryptionConfiguration(); + + config.setBlacklistedAlgorithms(Collections.singletonList( + EncryptionConstants.ALGO_ID_KEYTRANSPORT_RSA15)); + + config.setEncryptedKeyResolver(buildBasicEncryptedKeyResolver()); + + return config; + } + + /** + * Set EAAF specific signature-creation configuration to OpenSAML 3.x. + * + * @return + */ + public static BasicSignatureSigningConfiguration buildEaafSignatureSigningConfiguration() { + final BasicSignatureSigningConfiguration config = new BasicSignatureSigningConfiguration(); + + config.setBlacklistedAlgorithms(Arrays.asList( + SignatureConstants.ALGO_ID_DIGEST_NOT_RECOMMENDED_MD5, + SignatureConstants.ALGO_ID_SIGNATURE_NOT_RECOMMENDED_RSA_MD5, + SignatureConstants.ALGO_ID_MAC_HMAC_NOT_RECOMMENDED_MD5, + SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA1, + SignatureConstants.ALGO_ID_SIGNATURE_ECDSA_SHA1, + SignatureConstants.ALGO_ID_SIGNATURE_DSA_SHA1, + SignatureConstants.ALGO_ID_DIGEST_SHA1)); + + config.setSignatureAlgorithms(Arrays.asList( + // The order within each key group is significant. + // The order of the key groups themselves is not significant. + + // RSA + SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256, + SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA384, + SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA512, + + // ECDSA + SignatureConstants.ALGO_ID_SIGNATURE_ECDSA_SHA256, + SignatureConstants.ALGO_ID_SIGNATURE_ECDSA_SHA384, + SignatureConstants.ALGO_ID_SIGNATURE_ECDSA_SHA512 + + // HMAC (all symmetric keys) + // SignatureConstants.ALGO_ID_MAC_HMAC_SHA256, + // SignatureConstants.ALGO_ID_MAC_HMAC_SHA384, + // SignatureConstants.ALGO_ID_MAC_HMAC_SHA512, + // SignatureConstants.ALGO_ID_MAC_HMAC_SHA1 + )); + + config.setSignatureReferenceDigestMethods(Arrays.asList( + // The order of these is significant. + SignatureConstants.ALGO_ID_DIGEST_SHA256, + SignatureConstants.ALGO_ID_DIGEST_SHA384, + SignatureConstants.ALGO_ID_DIGEST_SHA512)); + + config.setSignatureCanonicalizationAlgorithm(SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS); + + config.setKeyInfoGeneratorManager(buildSignatureKeyInfoGeneratorManager()); + + return config; + } + + /** + * Set EAAF specific signature-verification configuration to OpenSAML 3.x. + * + * @return + */ + public static BasicSignatureValidationConfiguration buildEaafSignatureValidationConfiguration() { + final BasicSignatureValidationConfiguration config = new BasicSignatureValidationConfiguration(); + + config.setBlacklistedAlgorithms(Arrays.asList( + SignatureConstants.ALGO_ID_DIGEST_NOT_RECOMMENDED_MD5, + SignatureConstants.ALGO_ID_SIGNATURE_NOT_RECOMMENDED_RSA_MD5, + SignatureConstants.ALGO_ID_MAC_HMAC_NOT_RECOMMENDED_MD5, + SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA1, + SignatureConstants.ALGO_ID_SIGNATURE_ECDSA_SHA1, + SignatureConstants.ALGO_ID_SIGNATURE_DSA_SHA1, + SignatureConstants.ALGO_ID_DIGEST_SHA1)); + + return config; + } +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EaafOpenSaml3xInitializer.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EaafOpenSaml3xInitializer.java new file mode 100644 index 00000000..5c6d861d --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/opensaml/initialize/EaafOpenSaml3xInitializer.java @@ -0,0 +1,158 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.impl.opensaml.initialize; + +import java.util.HashMap; +import java.util.Map; + +import javax.annotation.Nonnull; +import javax.xml.XMLConstants; + +import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttribute; +import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttributes; +import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EaafRequestedAttributeBuilder; +import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EaafRequestedAttributeMarshaller; +import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EaafRequestedAttributeUnmarshaller; +import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EaafRequestedAttributesBuilder; +import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EaafRequestedAttributesMarshaller; +import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EaafRequestedAttributesUnmarshaller; + +import org.opensaml.core.config.ConfigurationService; +import org.opensaml.core.config.InitializationException; +import org.opensaml.core.config.InitializationService; +import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport; +import org.opensaml.xmlsec.DecryptionConfiguration; +import org.opensaml.xmlsec.EncryptionConfiguration; +import org.opensaml.xmlsec.SignatureSigningConfiguration; +import org.opensaml.xmlsec.SignatureValidationConfiguration; + +import lombok.extern.slf4j.Slf4j; +import net.shibboleth.utilities.java.support.component.ComponentInitializationException; +import net.shibboleth.utilities.java.support.xml.BasicParserPool; +import net.shibboleth.utilities.java.support.xml.ParserPool; + +/** + * EAAF specific OpenSAML Initializer. + * + * @author tlenz + * + */ +@Slf4j +public class EaafOpenSaml3xInitializer extends InitializationService { + + /** + * EAAF specific OpenSAML3.x initialization. + * + * @throws InitializationException In case of an error + * @throws ComponentInitializationException In case of an OpenSAML3 + * initialization error + */ + public static synchronized void eaafInitialize() throws InitializationException, + ComponentInitializationException { + log.debug("Initializing OpenSAML 3.x ... "); + initialize(); + + log.debug("Injecting EAAF-specific configuration into OpenSAML 3.x ... "); + injectEaafSecurityProperty(); + injectEaafExtenstions(); + + XMLObjectProviderRegistrySupport.setParserPool(eaafSecuredBasicParserPool()); + + log.info("OpenSAML3.x with EAAF extensions initialized"); + + } + + private static void injectEaafSecurityProperty() { + ConfigurationService.register(EncryptionConfiguration.class, + EaafDefaultSecurityConfigurationBootstrap.buildEaafEncryptionConfiguration()); + + ConfigurationService.register(DecryptionConfiguration.class, + EaafDefaultSecurityConfigurationBootstrap.buildEaaftDecryptionConfiguration()); + + ConfigurationService.register(SignatureSigningConfiguration.class, + EaafDefaultSecurityConfigurationBootstrap.buildEaafSignatureSigningConfiguration()); + + ConfigurationService.register(SignatureValidationConfiguration.class, + EaafDefaultSecurityConfigurationBootstrap.buildEaafSignatureValidationConfiguration()); + + } + + private static void injectEaafExtenstions() { + XMLObjectProviderRegistrySupport.registerObjectProvider( + EaafRequestedAttribute.DEFAULT_ELEMENT_NAME, new EaafRequestedAttributeBuilder(), + new EaafRequestedAttributeMarshaller(), new EaafRequestedAttributeUnmarshaller()); + + XMLObjectProviderRegistrySupport.registerObjectProvider( + EaafRequestedAttributes.DEFAULT_ELEMENT_NAME, new EaafRequestedAttributesBuilder(), + new EaafRequestedAttributesMarshaller(), new EaafRequestedAttributesUnmarshaller()); + + } + + /** + * Build a secured OpenSAML 3.x XML parser-pool. + * + * @return {@link ParserPool} + * @throws ComponentInitializationException In case of an initialization error + */ + @Nonnull + private static ParserPool eaafSecuredBasicParserPool() throws ComponentInitializationException { + // Get parser pool manager + final BasicParserPool ppMgr = new BasicParserPool(); + // Note: this is necessary due to an unresolved Xerces deferred DOM issue/bug + ppMgr.setBuilderFeatures(getSecureDocumentBuilderFeatures()); + ppMgr.setNamespaceAware(true); + ppMgr.setIgnoreComments(true); + ppMgr.setExpandEntityReferences(false); + ppMgr.setXincludeAware(false); + ppMgr.initialize(); + return ppMgr; + } + + @Nonnull + private static Map<String, Boolean> getSecureDocumentBuilderFeatures() { + final Map<String, Boolean> features = new HashMap<>(); + features.put(XMLConstants.FEATURE_SECURE_PROCESSING, Boolean.TRUE); + + // Ignore the external DTD completely + // Note: this is for Xerces only: + features.put("http://apache.org/xml/features/nonvalidating/load-external-dtd", Boolean.FALSE); + // This is the PRIMARY defense. If DTDs (doctypes) are disallowed, almost all + // XML entity attacks are prevented + // Xerces 2 only - + // http://xerces.apache.org/xerces2-j/features.html#disallow-doctype-decl + features.put("http://apache.org/xml/features/disallow-doctype-decl", Boolean.TRUE); + + // If you can't completely disable DTDs, then at least do the following: + // Xerces 1 - + // http://xerces.apache.org/xerces-j/features.html#external-general-entities + // Xerces 2 - + // http://xerces.apache.org/xerces2-j/features.html#external-general-entities + features.put("http://xml.org/sax/features/external-general-entities", Boolean.FALSE); + + // Xerces 1 - + // http://xerces.apache.org/xerces-j/features.html#external-parameter-entities + // Xerces 2 - + // http://xerces.apache.org/xerces2-j/features.html#external-parameter-entities + features.put("http://xml.org/sax/features/external-parameter-entities", Boolean.FALSE); + + return features; + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/reqattr/EAAFRequestedAttributeImpl.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/reqattr/EAAFRequestedAttributeImpl.java deleted file mode 100644 index ed169d8c..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/reqattr/EAAFRequestedAttributeImpl.java +++ /dev/null @@ -1,133 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.impl.reqattr; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import org.opensaml.common.impl.AbstractSAMLObject; -import org.opensaml.xml.XMLObject; -import org.opensaml.xml.schema.XSBooleanValue; -import org.opensaml.xml.util.AttributeMap; -import org.opensaml.xml.util.XMLObjectChildrenList; - -import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EAAFRequestedAttribute; - -public class EAAFRequestedAttributeImpl extends AbstractSAMLObject implements EAAFRequestedAttribute { - - private final XMLObjectChildrenList<XMLObject> attributeValues; - private String friendlyName; - private String isRequired; - private String name; - private String nameFormat; - private AttributeMap unknownAttributes; - - public EAAFRequestedAttributeImpl(String namespaceURI, String elementLocalName, String namespacePrefix) { - super(namespaceURI, elementLocalName, namespacePrefix); - unknownAttributes = new AttributeMap(this); - attributeValues = new XMLObjectChildrenList<XMLObject>(this); - - } - - public final List<XMLObject> getAttributeValues() { - return attributeValues; - } - - public final String getFriendlyName() { - return friendlyName; - } - - public final String getIsRequiredXSBoolean() { - return isRequired; - } - - public final String getName() { - return name; - } - - public final String getNameFormat() { - return nameFormat; - } - - public final List<XMLObject> getOrderedChildren() { - final List<XMLObject> children = new ArrayList<XMLObject>(); - children.addAll(attributeValues); - return Collections.unmodifiableList(children); - } - - - public final AttributeMap getUnknownAttributes() { - return unknownAttributes; - } - - - public final void setFriendlyName(final String newFriendlyName) { - this.friendlyName = prepareForAssignment(this.friendlyName, - newFriendlyName); - } - - - public final void setIsRequired(final String newIsRequired) { - isRequired = prepareForAssignment(this.isRequired, newIsRequired); - - } - - - public final void setName(final String newName) { - this.name = prepareForAssignment(this.name, newName); - } - - - public final void setNameFormat(final String newNameFormat) { - this.nameFormat = prepareForAssignment(this.nameFormat, newNameFormat); - } - - - public final void setUnknownAttributes(final AttributeMap newUnknownAttr) { - this.unknownAttributes = newUnknownAttr; - } - - @Override - public XSBooleanValue isRequiredXSBoolean() { - return XSBooleanValue.valueOf(isRequired); - } - - @Override - public void setIsRequired(Boolean aBoolean) { - this.isRequired = String.valueOf(aBoolean); - } - - @Override - public void setIsRequired(XSBooleanValue xsBooleanValue) { - this.isRequired = String.valueOf(xsBooleanValue); - } - - @Override - public Boolean isRequired() { - return Boolean.parseBoolean(isRequired); - } - -} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/reqattr/EAAFRequestedAttributesImpl.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/reqattr/EAAFRequestedAttributesImpl.java deleted file mode 100644 index b85d4791..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/reqattr/EAAFRequestedAttributesImpl.java +++ /dev/null @@ -1,61 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.impl.reqattr; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import org.opensaml.common.impl.AbstractSAMLObject; -import org.opensaml.xml.XMLObject; -import org.opensaml.xml.util.IndexedXMLObjectChildrenList; - -import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EAAFRequestedAttribute; -import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EAAFRequestedAttributes; - -public class EAAFRequestedAttributesImpl extends AbstractSAMLObject implements EAAFRequestedAttributes { - - private final IndexedXMLObjectChildrenList<XMLObject> indexedChildren; - - public EAAFRequestedAttributesImpl(String namespaceURI, String elementLocalName, String namespacePrefix) { - super(namespaceURI, elementLocalName, namespacePrefix); - indexedChildren = new IndexedXMLObjectChildrenList<XMLObject>(this); - } - - @Override - public List<XMLObject> getOrderedChildren() { - final List<XMLObject> children = new ArrayList<XMLObject>(); - children.addAll(indexedChildren); - return Collections.unmodifiableList(children); - - } - - @Override - public List<EAAFRequestedAttribute> getAttributes() { - return (List<EAAFRequestedAttribute>) indexedChildren - .subList(EAAFRequestedAttribute.DEFAULT_ELEMENT_NAME); - } - -} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/reqattr/EaafRequestedAttributeImpl.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/reqattr/EaafRequestedAttributeImpl.java new file mode 100644 index 00000000..e391bb31 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/reqattr/EaafRequestedAttributeImpl.java @@ -0,0 +1,141 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.impl.reqattr; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttribute; + +import org.opensaml.core.xml.XMLObject; +import org.opensaml.core.xml.schema.XSBooleanValue; +import org.opensaml.core.xml.util.AttributeMap; +import org.opensaml.core.xml.util.XMLObjectChildrenList; +import org.opensaml.saml.common.AbstractSAMLObject; + +public class EaafRequestedAttributeImpl extends AbstractSAMLObject + implements EaafRequestedAttribute { + + private final XMLObjectChildrenList<XMLObject> attributeValues; + private String friendlyName; + private String isRequired; + private String name; + private String nameFormat; + private AttributeMap unknownAttributes; + + /** + * Build an EAAF specific requested attribute. + * + * @param namespaceUri Attribute namespace + * @param elementLocalName Attribute name + * @param namespacePrefix Attribute namespace prefix + */ + public EaafRequestedAttributeImpl(final String namespaceUri, final String elementLocalName, + final String namespacePrefix) { + super(namespaceUri, elementLocalName, namespacePrefix); + unknownAttributes = new AttributeMap(this); + attributeValues = new XMLObjectChildrenList<>(this); + + } + + @Override + public final List<XMLObject> getAttributeValues() { + return attributeValues; + } + + @Override + public final String getFriendlyName() { + return friendlyName; + } + + @Override + public final String getIsRequiredXsBoolean() { + return isRequired; + } + + @Override + public final String getName() { + return name; + } + + @Override + public final String getNameFormat() { + return nameFormat; + } + + @Override + public final List<XMLObject> getOrderedChildren() { + final List<XMLObject> children = new ArrayList<>(); + children.addAll(attributeValues); + return Collections.unmodifiableList(children); + } + + @Override + public final AttributeMap getUnknownAttributes() { + return unknownAttributes; + } + + @Override + public final void setFriendlyName(final String newFriendlyName) { + this.friendlyName = prepareForAssignment(this.friendlyName, newFriendlyName); + } + + @Override + public void setIsRequired(final Boolean aboolean) { + this.isRequired = String.valueOf(aboolean); + } + + @Override + public void setIsRequired(final XSBooleanValue xsBooleanValue) { + this.isRequired = String.valueOf(xsBooleanValue); + } + + @Override + public final void setIsRequired(final String newIsRequired) { + isRequired = prepareForAssignment(this.isRequired, newIsRequired); + + } + + @Override + public final void setName(final String newName) { + this.name = prepareForAssignment(this.name, newName); + } + + @Override + public final void setNameFormat(final String newNameFormat) { + this.nameFormat = prepareForAssignment(this.nameFormat, newNameFormat); + } + + public final void setUnknownAttributes(final AttributeMap newUnknownAttr) { + this.unknownAttributes = newUnknownAttr; + } + + @Override + public XSBooleanValue isRequiredXSBoolean() { + return XSBooleanValue.valueOf(isRequired); + } + + @Override + public Boolean isRequired() { + return Boolean.parseBoolean(isRequired); + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/reqattr/EaafRequestedAttributesImpl.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/reqattr/EaafRequestedAttributesImpl.java new file mode 100644 index 00000000..9c251233 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/reqattr/EaafRequestedAttributesImpl.java @@ -0,0 +1,58 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.impl.reqattr; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttribute; +import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttributes; + +import org.opensaml.core.xml.XMLObject; +import org.opensaml.core.xml.util.IndexedXMLObjectChildrenList; +import org.opensaml.saml.common.AbstractSAMLObject; + +public class EaafRequestedAttributesImpl extends AbstractSAMLObject + implements EaafRequestedAttributes { + + private final IndexedXMLObjectChildrenList<XMLObject> indexedChildren; + + public EaafRequestedAttributesImpl(final String namespaceUri, final String elementLocalName, + final String namespacePrefix) { + super(namespaceUri, elementLocalName, namespacePrefix); + indexedChildren = new IndexedXMLObjectChildrenList<>(this); + } + + @Override + public List<XMLObject> getOrderedChildren() { + final List<XMLObject> children = new ArrayList<>(); + children.addAll(indexedChildren); + return Collections.unmodifiableList(children); + + } + + @Override + public List<EaafRequestedAttribute> getAttributes() { + return (List<EaafRequestedAttribute>) indexedChildren + .subList(EaafRequestedAttribute.DEFAULT_ELEMENT_NAME); + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/AbstractCredentialProvider.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/AbstractCredentialProvider.java index acc5357e..26a5c5f6 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/AbstractCredentialProvider.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/AbstractCredentialProvider.java @@ -1,225 +1,328 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 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: + * Licensed under the EUPL, Version 1.2 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: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * 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. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * 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.egiz.eaaf.modules.pvp2.impl.utils; import java.security.KeyStore; -import java.security.PrivateKey; -import java.security.interfaces.ECPrivateKey; -import java.security.interfaces.RSAPrivateKey; +import java.security.KeyStoreException; +import java.security.Provider; +import java.security.cert.Certificate; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration; +import java.util.List; -import org.apache.commons.lang3.StringUtils; -import org.opensaml.xml.security.credential.Credential; -import org.opensaml.xml.security.credential.UsageType; -import org.opensaml.xml.security.x509.X509Credential; -import org.opensaml.xml.signature.Signature; -import org.opensaml.xml.signature.SignatureConstants; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import at.gv.egiz.eaaf.core.exceptions.EAAFException; -import at.gv.egiz.eaaf.core.impl.utils.KeyStoreUtils; +import javax.annotation.Nonnull; +import javax.annotation.PostConstruct; + +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException; +import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.core.impl.credential.EaafKeyStoreFactory; +import at.gv.egiz.eaaf.core.impl.credential.KeyStoreConfiguration; +import at.gv.egiz.eaaf.core.impl.data.Pair; +import at.gv.egiz.eaaf.modules.pvp2.PvpConstants; +import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential; +import at.gv.egiz.eaaf.modules.pvp2.api.utils.IPvp2CredentialProvider; import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException; -import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.KeyStoreX509CredentialAdapter; - -public abstract class AbstractCredentialProvider { - - private static final Logger log = LoggerFactory.getLogger(AbstractCredentialProvider.class); - - private KeyStore keyStore = null; - - /** - * Get a friendlyName for this keyStore implementation - * This friendlyName is used for logging - * - * @return keyStore friendlyName - */ - public abstract String getFriendlyName(); - - /** - * Get KeyStore - * - * @return URL to the keyStore - * @throws EAAFException - */ - public abstract String getKeyStoreFilePath() throws EAAFException; - - /** - * Get keyStore password - * - * @return Password of the keyStore - */ - public abstract String getKeyStorePassword(); - - /** - * Get alias of key for metadata signing - * - * @return key alias - */ - public abstract String getMetadataKeyAlias(); - - /** - * Get password of key for metadata signing - * - * @return key password - */ - public abstract String getMetadataKeyPassword(); - - /** - * Get alias of key for request/response signing - * - * @return key alias - */ - public abstract String getSignatureKeyAlias(); - - /** - * Get password of key for request/response signing - * - * @return key password - */ - public abstract String getSignatureKeyPassword(); - - /** - * Get alias of key for IDP response encryption - * - * @return key alias - */ - public abstract String getEncryptionKeyAlias(); - - /** - * Get password of key for IDP response encryption - * - * @return key password - */ - public abstract String getEncryptionKeyPassword(); - - - public X509Credential getIDPMetaDataSigningCredential() - throws CredentialsNotAvailableException { - try { - - if (keyStore == null) - keyStore = KeyStoreUtils.loadKeyStore(getKeyStoreFilePath(), - getKeyStorePassword()); - - KeyStoreX509CredentialAdapter credentials = new KeyStoreX509CredentialAdapter( - keyStore, getMetadataKeyAlias(), getMetadataKeyPassword().toCharArray()); - - credentials.setUsageType(UsageType.SIGNING); - if (credentials.getPrivateKey() == null && credentials.getSecretKey() == null) { - log.error(getFriendlyName() + " Metadata Signing credentials is not found or contains no PrivateKey."); - throw new CredentialsNotAvailableException("config.27", new Object[]{getFriendlyName() + " Assertion Signing credentials (Alias: " - + getMetadataKeyAlias() + ") is not found or contains no PrivateKey."}); - - } - return credentials; - } catch (Exception e) { - log.error("Failed to generate " + getFriendlyName() + " Metadata Signing credentials"); - e.printStackTrace(); - throw new CredentialsNotAvailableException("config.27", new Object[]{e.getMessage()}, e); - } - } - - public X509Credential getIDPAssertionSigningCredential() - throws CredentialsNotAvailableException { - try { - if (keyStore == null) - keyStore = KeyStoreUtils.loadKeyStore(getKeyStoreFilePath(), - getKeyStorePassword()); - - KeyStoreX509CredentialAdapter credentials = new KeyStoreX509CredentialAdapter( - keyStore, getSignatureKeyAlias(), getSignatureKeyPassword().toCharArray()); - - credentials.setUsageType(UsageType.SIGNING); - if (credentials.getPrivateKey() == null && credentials.getSecretKey() == null) { - log.error(getFriendlyName() + " Assertion Signing credentials is not found or contains no PrivateKey."); - throw new CredentialsNotAvailableException("config.27", new Object[]{getFriendlyName() + " Assertion Signing credentials (Alias: " - + getSignatureKeyAlias() + ") is not found or contains no PrivateKey."}); - - } - - return (X509Credential) credentials; - } catch (Exception e) { - log.error("Failed to generate " + getFriendlyName() + " Assertion Signing credentials"); - e.printStackTrace(); - throw new CredentialsNotAvailableException("config.27", new Object[]{e.getMessage()}, e); - } - } - - public X509Credential getIDPAssertionEncryptionCredential() - throws CredentialsNotAvailableException { - try { - if (keyStore == null) - keyStore = KeyStoreUtils.loadKeyStore(getKeyStoreFilePath(), - getKeyStorePassword()); - - //if no encryption key is configured return null - if (StringUtils.isEmpty(getEncryptionKeyAlias())) - return null; - - KeyStoreX509CredentialAdapter credentials = new KeyStoreX509CredentialAdapter( - keyStore, getEncryptionKeyAlias(), getEncryptionKeyPassword().toCharArray()); - - credentials.setUsageType(UsageType.ENCRYPTION); - - if (credentials.getPrivateKey() == null && credentials.getSecretKey() == null) { - log.error(getFriendlyName() + " Assertion Encryption credentials is not found or contains no PrivateKey."); - throw new CredentialsNotAvailableException("config.27", new Object[]{getFriendlyName() + " Assertion Encryption credentials (Alias: " - + getEncryptionKeyAlias() + ") is not found or contains no PrivateKey."}); - - } - - return (X509Credential) credentials; - - } catch (Exception e) { - log.error("Failed to generate " + getFriendlyName() + " Assertion Encryption credentials"); - e.printStackTrace(); - throw new CredentialsNotAvailableException("config.27", new Object[]{e.getMessage()}, e); - } - } - - public static Signature getIDPSignature(Credential credentials) { - PrivateKey privatekey = credentials.getPrivateKey(); - Signature signer = SAML2Utils.createSAMLObject(Signature.class); - - if (privatekey instanceof RSAPrivateKey) { - signer.setSignatureAlgorithm(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256); - - } else if (privatekey instanceof ECPrivateKey) { - signer.setSignatureAlgorithm(SignatureConstants.ALGO_ID_SIGNATURE_ECDSA_SHA256); - - } else { - log.warn("Could NOT evaluate the Private-Key type from " + credentials.getEntityId() + " credential."); - - - } - - signer.setCanonicalizationAlgorithm(SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS); - signer.setSigningCredential(credentials); - return signer; - - } +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlSigningException; +import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.EaafKeyStoreX509CredentialAdapter; + +import org.apache.commons.lang3.StringUtils; +import org.apache.xml.security.algorithms.JCEMapper; +import org.opensaml.security.credential.UsageType; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.ResourceLoader; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public abstract class AbstractCredentialProvider implements IPvp2CredentialProvider { + + private static final String TRUSTED_CERTIFICATES_OPERATION = "Trusted Certificate Entries"; + + @Autowired + protected ResourceLoader resourceLoader; + @Autowired + protected IConfiguration basicConfig; + + @Autowired + private EaafKeyStoreFactory keyStoreFactory; + + private Pair<KeyStore, Provider> keyStore = null; + + /** + * Get a friendlyName for this keyStore implementation This friendlyName is used + * for logging. + * + * @return keyStore friendlyName + */ + public final String getFriendlyName() { + try { + return getBasicKeyStoreConfig().getFriendlyName(); + + } catch (final EaafConfigurationException e) { + return "No KeyStoreName"; + + } + + } + + /** + * Get the basic KeyStore configuration object for this SAML2 credential. + * + * @return KeyStore configuration object + * @throws EaafConfigurationException In case of a configuration error + */ + @Nonnull + public abstract KeyStoreConfiguration getBasicKeyStoreConfig() throws EaafConfigurationException; + + /** + * Get alias of key for metadata signing. + * + * @return key alias + */ + public abstract String getMetadataKeyAlias(); + + /** + * Get password of key for metadata signing. + * + * @return key password + */ + public abstract String getMetadataKeyPassword(); + + /** + * Get alias of key for request/response signing. + * + * @return key alias + */ + public abstract String getSignatureKeyAlias(); + + /** + * Get password of key for request/response signing. + * + * @return key password + */ + public abstract String getSignatureKeyPassword(); + + /** + * Get alias of key for IDP response encryption. + * + * @return key alias + */ + public abstract String getEncryptionKeyAlias(); + + /** + * Get password of key for IDP response encryption. + * + * @return key password + */ + public abstract String getEncryptionKeyPassword(); + + /** + * Get Credentials to sign metadata. + * + * @return Credentials + * @throws CredentialsNotAvailableException In case of a credential error + */ + @Override + public EaafX509Credential getMetaDataSigningCredential() throws CredentialsNotAvailableException { + try { + final EaafKeyStoreX509CredentialAdapter credentials = new EaafKeyStoreX509CredentialAdapter( + keyStore.getFirst(), getMetadataKeyAlias(), + getPassCharArrayOrNull(getMetadataKeyPassword()), getFriendlyName()); + credentials.setUsageType(UsageType.SIGNING); + credentials.setSignatureAlgorithmForSigning(selectSigningAlgorithm(credentials)); + credentials.setKeyEncryptionAlgorithmForDataEncryption(selectKeyEncryptionAlgorithm(credentials)); + return credentials; + + } catch (final Exception e) { + throw new CredentialsNotAvailableException("internal.pvp.01", + new Object[] { getFriendlyName(), getMetadataKeyAlias() }, e); + + } + } + + /** + * Get Credentials to sign SAML2 messages, like AuthnRequest, Response, + * Assertions as some examples. + * + * @return Credentials + * @throws CredentialsNotAvailableException In case of a credential error + */ + @Override + public EaafX509Credential getMessageSigningCredential() throws CredentialsNotAvailableException { + try { + final EaafKeyStoreX509CredentialAdapter credentials = new EaafKeyStoreX509CredentialAdapter( + keyStore.getFirst(), getSignatureKeyAlias(), + getPassCharArrayOrNull(getSignatureKeyPassword()), getFriendlyName()); + credentials.setUsageType(UsageType.SIGNING); + credentials.setSignatureAlgorithmForSigning(selectSigningAlgorithm(credentials)); + credentials.setKeyEncryptionAlgorithmForDataEncryption(selectKeyEncryptionAlgorithm(credentials)); + return credentials; + + } catch (final Exception e) { + throw new CredentialsNotAvailableException("internal.pvp.01", + new Object[] { getFriendlyName(), getSignatureKeyAlias() }, e); + + } + } + + /** + * Get Credentials to encrypt messages, like Assertion as example. + * + * @return Credentials + * @throws CredentialsNotAvailableException In case of a credential error + */ + @Override + public EaafX509Credential getMessageEncryptionCredential() + throws CredentialsNotAvailableException { + // if no encryption key is configured return null + if (StringUtils.isEmpty(getEncryptionKeyAlias())) { + return null; + } + + try { + final EaafKeyStoreX509CredentialAdapter credentials = new EaafKeyStoreX509CredentialAdapter( + keyStore.getFirst(), getEncryptionKeyAlias(), + getPassCharArrayOrNull(getEncryptionKeyPassword()), getFriendlyName()); + credentials.setUsageType(UsageType.ENCRYPTION); + credentials.setSignatureAlgorithmForSigning(selectSigningAlgorithm(credentials)); + credentials.setKeyEncryptionAlgorithmForDataEncryption(selectKeyEncryptionAlgorithm(credentials)); + return credentials; + + } catch (final Exception e) { + throw new CredentialsNotAvailableException("internal.pvp.01", + new Object[] { getFriendlyName(), getEncryptionKeyAlias() }, e); + + } + + } + + /** + * Get a List of trusted {@link X509Certificate} that are available in this + * KeyStore. + * + * @return List of trusted {@link X509Certificate}, or an emptry {@link List} if + * no certificates are available + * @throws CredentialsNotAvailableException In case of a KeyStore error + */ + @Override + @Nonnull + public List<X509Certificate> getTrustedCertificates() + throws CredentialsNotAvailableException { + final List<X509Certificate> result = new ArrayList<>(); + + try { + final Enumeration<String> aliases = keyStore.getFirst().aliases(); + while (aliases.hasMoreElements()) { + final String el = aliases.nextElement(); + log.trace("Process TrustStoreEntry: " + el); + if (keyStore.getFirst().isCertificateEntry(el)) { + final Certificate cert = keyStore.getFirst().getCertificate(el); + if (cert != null && cert instanceof X509Certificate) { + result.add((X509Certificate) cert); + + } else { + log.info("Can not process entry: {}. Reason: {}", + el, cert != null ? cert.getType() : "cert is null"); + + } + } + } + } catch (final KeyStoreException e) { + throw new CredentialsNotAvailableException("internal.pvp.01", + new Object[] { getFriendlyName(), TRUSTED_CERTIFICATES_OPERATION }, e); + } + + return Collections.unmodifiableList(result); + + } + + @PostConstruct + private void initialize() throws Exception { + try { + final KeyStoreConfiguration keyStoreConfig = getBasicKeyStoreConfig(); + keyStore = keyStoreFactory.buildNewKeyStore(keyStoreConfig); + + if (JCEMapper.getProviderId() != null && keyStore.getSecond() != null + && !JCEMapper.getProviderId().equals(keyStore.getSecond().getName())) { + log.error("OpenSAML3.x can ONLY use a single type of CryptoProvider in an application. " + + "Can NOT set: {}, because {} was already set", keyStore.getSecond().getName(), + JCEMapper.getProviderId()); + throw new EaafConfigurationException(EaafKeyStoreFactory.ERRORCODE_06, + new Object[] { keyStoreConfig.getFriendlyName(), + "OpenSAML3.x can ONLY use a single type of CryptoProvider" }); + + } + + // Set JCEMapper only in case of HSM based KeyStores because Software KeyStores + // can use + // the default SecurityProvider system in OpenSAML3.x signing engine + if (keyStore.getSecond() != null + && JCEMapper.getProviderId() == null) { + log.info("Register CryptoProvider: {} as defaut for OpenSAML3.x", + keyStore.getSecond().getName()); + JCEMapper.setProviderId(keyStore.getSecond().getName()); + + } + + } catch (final EaafException e) { + log.error("Can not initialize KeyStore for eIDAS authentication client.", e); + throw e; + + } + } + + private String selectSigningAlgorithm(EaafKeyStoreX509CredentialAdapter credentials) + throws SamlSigningException { + return Saml2Utils.getKeyOperationAlgorithmFromCredential( + credentials, + basicConfig.getBasicConfiguration( + PvpConstants.CONFIG_PROP_SEC_SIGNING_RSA_ALG, + PvpConstants.DEFAULT_SIGNING_METHODE_RSA), + basicConfig.getBasicConfiguration( + PvpConstants.CONFIG_PROP_SEC_SIGNING_EC_ALG, + PvpConstants.DEFAULT_SIGNING_METHODE_EC)); + } + + private String selectKeyEncryptionAlgorithm(EaafKeyStoreX509CredentialAdapter credentials) + throws SamlSigningException { + return Saml2Utils.getKeyOperationAlgorithmFromCredential( + credentials, + basicConfig.getBasicConfiguration( + PvpConstants.CONFIG_PROP_SEC_ENCRYPTION_KEY_RSA_ALG, + PvpConstants.DEFAULT_ASYM_ENCRYPTION_METHODE_RSA), + basicConfig.getBasicConfiguration( + PvpConstants.CONFIG_PROP_SEC_ENCRYPTION_KEY_EC_ALG, + PvpConstants.DEFAULT_ASYM_ENCRYPTION_METHODE_EC)); + } + + private char[] getPassCharArrayOrNull(String metadataKeyPassword) { + char[] keyPassChar = null; + if (metadataKeyPassword != null) { + keyPassChar = metadataKeyPassword.toCharArray(); + + } + + return keyPassChar; + } + } diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/QAALevelVerifier.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/QAALevelVerifier.java deleted file mode 100644 index 8e7183d3..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/QAALevelVerifier.java +++ /dev/null @@ -1,104 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.impl.utils; - -import java.util.List; - -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import at.gv.egiz.eaaf.core.api.data.EAAFConstants; -import at.gv.egiz.eaaf.modules.pvp2.exception.QAANotAllowedException; - -/** - * @author tlenz - * - */ -public class QAALevelVerifier { - - private static final Logger log = LoggerFactory.getLogger(QAALevelVerifier.class); - - private static boolean verifyQAALevel(String qaaAuth, String requiredLoA, String matchingMode) throws QAANotAllowedException { - //to MINIMUM machting - if (EAAFConstants.EIDAS_LOA_MATCHING_MINIMUM.equals(matchingMode)) { - log.trace("Perfom LoA matching in 'MINIMUM' mode ... "); - if (EAAFConstants.EIDAS_LOA_LOW.equals(requiredLoA) && - (EAAFConstants.EIDAS_LOA_LOW.equals(qaaAuth) || - EAAFConstants.EIDAS_LOA_SUBSTANTIAL.equals(qaaAuth) || - EAAFConstants.EIDAS_LOA_HIGH.equals(qaaAuth)) - ) - return true; - - else if (EAAFConstants.EIDAS_LOA_SUBSTANTIAL.equals(requiredLoA) && - (EAAFConstants.EIDAS_LOA_SUBSTANTIAL.equals(qaaAuth) || - EAAFConstants.EIDAS_LOA_HIGH.equals(qaaAuth)) - ) - return true; - - else if (EAAFConstants.EIDAS_LOA_HIGH.equals(requiredLoA) && EAAFConstants.EIDAS_LOA_HIGH.equals(qaaAuth)) - return true; - - } else if (EAAFConstants.EIDAS_LOA_MATCHING_EXACT.equals(matchingMode)) { - //to EXACT matching - log.trace("Perfom LoA matching in 'EXACT' mode ... "); - if (qaaAuth.equals(requiredLoA)) { - log.debug("Required LoA fits LoA from authentication. Continue auth process ... "); - return true; - - } - - } else { - log.warn("LoA matching-mode:" + matchingMode + " is NOT supported by this implementation"); - throw new QAANotAllowedException(qaaAuth, requiredLoA, matchingMode); - - } - - return false; - - } - - public static void verifyQAALevel(String qaaAuth, List<String> requiredLoAs, String matchingMode) throws QAANotAllowedException { - log.trace("Starting LoA verification: authLoA: " + qaaAuth - + " requiredLoA: " + StringUtils.join(requiredLoAs, "|") - + " matchingMode: " + matchingMode); - - boolean hasMatch = false; - for (String loa : requiredLoAs) { - if (verifyQAALevel(qaaAuth, loa, matchingMode)) - hasMatch = true; - - } - - if (!hasMatch) - throw new QAANotAllowedException(qaaAuth, StringUtils.join(requiredLoAs, "|"), matchingMode); - - else - log.debug("Requesed LoA fits LoA from authentication. Continue auth process ... "); - - } -} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/QaaLevelVerifier.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/QaaLevelVerifier.java new file mode 100644 index 00000000..ca6f29e4 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/QaaLevelVerifier.java @@ -0,0 +1,109 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.impl.utils; + +import java.util.List; + +import at.gv.egiz.eaaf.core.api.data.EaafConstants; +import at.gv.egiz.eaaf.modules.pvp2.exception.QaaNotAllowedException; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * EAAF LoA Level verifier checks if requested LoA matchs to LoA of + * authentication. + * + * + * @author tlenz + * + */ +public class QaaLevelVerifier { + + private static final Logger log = LoggerFactory.getLogger(QaaLevelVerifier.class); + + private static boolean verifyQaaLevel(final String qaaAuth, final String requiredLoA, + final String matchingMode) throws QaaNotAllowedException { + // to MINIMUM machting + if (EaafConstants.EIDAS_LOA_MATCHING_MINIMUM.equals(matchingMode)) { + log.trace("Perfom LoA matching in 'MINIMUM' mode ... "); + if (EaafConstants.EIDAS_LOA_LOW.equals(requiredLoA) + && (EaafConstants.EIDAS_LOA_LOW.equals(qaaAuth) + || EaafConstants.EIDAS_LOA_SUBSTANTIAL.equals(qaaAuth) + || EaafConstants.EIDAS_LOA_HIGH.equals(qaaAuth))) { + return true; + } else if (EaafConstants.EIDAS_LOA_SUBSTANTIAL.equals(requiredLoA) + && (EaafConstants.EIDAS_LOA_SUBSTANTIAL.equals(qaaAuth) + || EaafConstants.EIDAS_LOA_HIGH.equals(qaaAuth))) { + return true; + } else if (EaafConstants.EIDAS_LOA_HIGH.equals(requiredLoA) + && EaafConstants.EIDAS_LOA_HIGH.equals(qaaAuth)) { + return true; + } + + } else if (EaafConstants.EIDAS_LOA_MATCHING_EXACT.equals(matchingMode)) { + // to EXACT matching + log.trace("Perfom LoA matching in 'EXACT' mode ... "); + if (qaaAuth.equals(requiredLoA)) { + log.debug("Required LoA fits LoA from authentication. Continue auth process ... "); + return true; + + } + + } else { + log.warn("LoA matching-mode:" + matchingMode + " is NOT supported by this implementation"); + throw new QaaNotAllowedException(qaaAuth, requiredLoA, matchingMode); + + } + + return false; + + } + + /** + * Check LoA level. + * + * @param qaaAuth LoA of authentication + * @param requiredLoAs List of allowed LoA levels + * @param matchingMode LoA matching mode + * @throws QaaNotAllowedException If LoA does not match + */ + public static void verifyQaaLevel(final String qaaAuth, final List<String> requiredLoAs, + final String matchingMode) throws QaaNotAllowedException { + log.trace("Starting LoA verification: authLoA: " + qaaAuth + " requiredLoA: " + + StringUtils.join(requiredLoAs, "|") + " matchingMode: " + matchingMode); + + boolean hasMatch = false; + for (final String loa : requiredLoAs) { + if (verifyQaaLevel(qaaAuth, loa, matchingMode)) { + hasMatch = true; + } + + } + + if (!hasMatch) { + throw new QaaNotAllowedException(qaaAuth, StringUtils.join(requiredLoAs, "|"), matchingMode); + } else { + log.debug("Requesed LoA fits LoA from authentication. Continue auth process ... "); + } + + } +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/SAML2Utils.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/SAML2Utils.java deleted file mode 100644 index d33ee6c6..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/SAML2Utils.java +++ /dev/null @@ -1,201 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.impl.utils; - -import java.io.IOException; -import java.security.NoSuchAlgorithmException; -import java.util.List; - -import javax.xml.namespace.QName; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.transform.TransformerException; -import javax.xml.transform.dom.DOMSource; -import javax.xml.validation.Schema; -import javax.xml.validation.Validator; - -import org.apache.commons.lang3.StringUtils; -import org.opensaml.Configuration; -import org.opensaml.common.impl.SecureRandomIdentifierGenerator; -import org.opensaml.common.xml.SAMLSchemaBuilder; -import org.opensaml.saml2.core.Attribute; -import org.opensaml.saml2.core.Status; -import org.opensaml.saml2.core.StatusCode; -import org.opensaml.saml2.metadata.AssertionConsumerService; -import org.opensaml.saml2.metadata.SPSSODescriptor; -import org.opensaml.ws.soap.soap11.Body; -import org.opensaml.ws.soap.soap11.Envelope; -import org.opensaml.xml.XMLObject; -import org.opensaml.xml.XMLObjectBuilderFactory; -import org.opensaml.xml.io.Marshaller; -import org.opensaml.xml.io.MarshallingException; -import org.opensaml.xml.schema.XSString; -import org.opensaml.xml.schema.impl.XSStringBuilder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; - -import at.gv.egiz.eaaf.core.impl.utils.Random; -import at.gv.egiz.eaaf.modules.pvp2.PVPConstants; -import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EAAFRequestedAttribute; - -public class SAML2Utils { - private static final Logger log = LoggerFactory.getLogger(SAML2Utils.class); - - public static <T> T createSAMLObject(final Class<T> clazz) { - try { - XMLObjectBuilderFactory builderFactory = Configuration - .getBuilderFactory(); - - QName defaultElementName = (QName) clazz.getDeclaredField( - "DEFAULT_ELEMENT_NAME").get(null); - @SuppressWarnings("unchecked") - T object = (T) builderFactory.getBuilder(defaultElementName) - .buildObject(defaultElementName); - return object; - } catch (Throwable e) { - e.printStackTrace(); - return null; - } - } - - public static String getSecureIdentifier() { - return "_".concat(Random.nextHexRandom16()); - - /*Bug-Fix: There are open problems with RandomNumberGenerator via Java SPI and Java JDK 8.121 - * Generation of a 16bit Random identifier FAILES with an Caused by: java.lang.ArrayIndexOutOfBoundsException - * Caused by: java.lang.ArrayIndexOutOfBoundsException - at iaik.security.random.o.engineNextBytes(Unknown Source) - at iaik.security.random.SecRandomSpi.engineNextBytes(Unknown Source) - at java.security.SecureRandom.nextBytes(SecureRandom.java:468) - at org.opensaml.common.impl.SecureRandomIdentifierGenerator.generateIdentifier(SecureRandomIdentifierGenerator.java:62) - at org.opensaml.common.impl.SecureRandomIdentifierGenerator.generateIdentifier(SecureRandomIdentifierGenerator.java:56) - at at.gv.egovernment.moa.id.protocols.pvp2x.utils.SAML2Utils.getSecureIdentifier(SAML2Utils.java:69) - */ - //return idGenerator.generateIdentifier(); - } - - private static SecureRandomIdentifierGenerator idGenerator; - - private static DocumentBuilder builder; - static { - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - factory.setNamespaceAware(true); - try { - builder = factory.newDocumentBuilder(); - } catch (ParserConfigurationException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - try { - idGenerator = new SecureRandomIdentifierGenerator(); - } catch(NoSuchAlgorithmException e) { - e.printStackTrace(); - } - } - - public static Document asDOMDocument(XMLObject object) throws IOException, - MarshallingException, TransformerException { - Document document = builder.newDocument(); - Marshaller out = Configuration.getMarshallerFactory().getMarshaller( - object); - out.marshall(object, document); - return document; - } - - public static Status getSuccessStatus() { - Status status = SAML2Utils.createSAMLObject(Status.class); - StatusCode statusCode = SAML2Utils.createSAMLObject(StatusCode.class); - statusCode.setValue(StatusCode.SUCCESS_URI); - status.setStatusCode(statusCode); - return status; - } - - public static int getDefaultAssertionConsumerServiceIndex(SPSSODescriptor spSSODescriptor) { - - List<AssertionConsumerService> assertionConsumerList = spSSODescriptor.getAssertionConsumerServices(); - - for (AssertionConsumerService el : assertionConsumerList) { - if (el.isDefault()) - return el.getIndex(); - - } - - return 0; - } - - public static Envelope buildSOAP11Envelope(XMLObject payload) { - XMLObjectBuilderFactory bf = Configuration.getBuilderFactory(); - Envelope envelope = (Envelope) bf.getBuilder(Envelope.DEFAULT_ELEMENT_NAME).buildObject(Envelope.DEFAULT_ELEMENT_NAME); - Body body = (Body) bf.getBuilder(Body.DEFAULT_ELEMENT_NAME).buildObject(Body.DEFAULT_ELEMENT_NAME); - - body.getUnknownXMLObjects().add(payload); - envelope.setBody(body); - - return envelope; - } - - public static EAAFRequestedAttribute generateReqAuthnAttributeSimple(Attribute attr, boolean isRequired, String value) { - EAAFRequestedAttribute requested = SAML2Utils.createSAMLObject(EAAFRequestedAttribute.class); - requested.setName(attr.getName()); - requested.setNameFormat(attr.getNameFormat()); - requested.setFriendlyName(attr.getFriendlyName()); - requested.setIsRequired(String.valueOf(isRequired)); - List<XMLObject> attributeValues = requested.getAttributeValues(); - if (StringUtils.isNotEmpty(value)) { - XMLObject attributeValueForRequest = createAttributeValue(PVPConstants.EIDAS_REQUESTED_ATTRIBUTE_VALUE_TYPE, value); - attributeValues.add(attributeValueForRequest); - } - return requested; - - } - - public static void schemeValidation(XMLObject xmlObject) throws Exception { - try { - Schema test = SAMLSchemaBuilder.getSAML11Schema(); - Validator val = test.newValidator(); - DOMSource source = new DOMSource(xmlObject.getDOM()); - val.validate(source); - log.debug("SAML2 Scheme validation successful"); - return; - - } catch (Exception e) { - log.warn("SAML2 scheme validation FAILED.", e); - throw e; - - } - } - - private static XMLObject createAttributeValue(QName attributeValueType, String value) { - XSStringBuilder stringBuilder = (XSStringBuilder) Configuration.getBuilderFactory().getBuilder(XSString.TYPE_NAME); - XSString stringValue = stringBuilder.buildObject(attributeValueType, XSString.TYPE_NAME); - stringValue.setValue(value); - return stringValue; - - } -} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/Saml2Utils.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/Saml2Utils.java new file mode 100644 index 00000000..5059b1fb --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/Saml2Utils.java @@ -0,0 +1,493 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.impl.utils; + +import java.io.IOException; +import java.io.InputStream; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.interfaces.ECPrivateKey; +import java.security.interfaces.ECPublicKey; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.RSAPublicKey; +import java.util.List; + +import javax.annotation.Nonnull; +import javax.xml.namespace.QName; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.TransformerException; +import javax.xml.transform.dom.DOMSource; +import javax.xml.validation.Schema; +import javax.xml.validation.Validator; + +import at.gv.egiz.eaaf.core.impl.utils.DomUtils; +import at.gv.egiz.eaaf.core.impl.utils.Random; +import at.gv.egiz.eaaf.modules.pvp2.PvpConstants; +import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential; +import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttribute; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlSigningException; +import at.gv.egiz.eaaf.modules.pvp2.exception.SchemaValidationException; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.opensaml.core.xml.XMLObject; +import org.opensaml.core.xml.XMLObjectBuilderFactory; +import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport; +import org.opensaml.core.xml.io.Marshaller; +import org.opensaml.core.xml.io.MarshallingException; +import org.opensaml.core.xml.io.Unmarshaller; +import org.opensaml.core.xml.io.UnmarshallingException; +import org.opensaml.core.xml.schema.XSString; +import org.opensaml.core.xml.schema.impl.XSStringBuilder; +import org.opensaml.core.xml.util.XMLObjectSupport; +import org.opensaml.messaging.decoder.MessageDecodingException; +import org.opensaml.saml.common.SAMLObjectContentReference; +import org.opensaml.saml.common.xml.SAMLSchemaBuilder; +import org.opensaml.saml.common.xml.SAMLSchemaBuilder.SAML1Version; +import org.opensaml.saml.saml2.core.Attribute; +import org.opensaml.saml.saml2.core.Status; +import org.opensaml.saml.saml2.core.StatusCode; +import org.opensaml.saml.saml2.metadata.AssertionConsumerService; +import org.opensaml.saml.saml2.metadata.SPSSODescriptor; +import org.opensaml.security.SecurityException; +import org.opensaml.security.x509.X509Credential; +import org.opensaml.soap.soap11.Body; +import org.opensaml.soap.soap11.Envelope; +import org.opensaml.xmlsec.SecurityConfigurationSupport; +import org.opensaml.xmlsec.SignatureSigningConfiguration; +import org.opensaml.xmlsec.keyinfo.KeyInfoGenerator; +import org.opensaml.xmlsec.keyinfo.KeyInfoGeneratorFactory; +import org.opensaml.xmlsec.keyinfo.KeyInfoGeneratorManager; +import org.opensaml.xmlsec.keyinfo.NamedKeyInfoGeneratorManager; +import org.opensaml.xmlsec.keyinfo.impl.BasicKeyInfoGeneratorFactory; +import org.opensaml.xmlsec.signature.KeyInfo; +import org.opensaml.xmlsec.signature.SignableXMLObject; +import org.opensaml.xmlsec.signature.Signature; +import org.opensaml.xmlsec.signature.support.ContentReference; +import org.opensaml.xmlsec.signature.support.SignatureConstants; +import org.opensaml.xmlsec.signature.support.SignatureException; +import org.opensaml.xmlsec.signature.support.Signer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.SAXException; + +import net.shibboleth.utilities.java.support.xml.QNameSupport; +import net.shibboleth.utilities.java.support.xml.SerializeSupport; + +public class Saml2Utils { + private static final Logger log = LoggerFactory.getLogger(Saml2Utils.class); + + private static DocumentBuilder builder; + private static SAMLSchemaBuilder schemaBuilder; + + static { + schemaBuilder = new SAMLSchemaBuilder(SAML1Version.SAML_11); + + final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + factory.setNamespaceAware(true); + + try { + builder = factory.newDocumentBuilder(); + + } catch (final ParserConfigurationException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + /** + * Sign a OpenSAML 3.x object with a {@link X509Credential}. <br> + * <p> + * This method used {@link PvpConstants.DEFAULT_SIGNING_METHODE_RSA} or + * {@link PvpConstants.DEFAULT_SIGNING_METHODE_EC} as algorithm + * </p> + * + * @param <T> {@link SignableXMLObject} + * @param toSign object that should be signed + * @param signingCredential Credentials that should be used for signing + * @param injectCertificate true, if certificate should be part of the signature + * @return Signed object + * @throws SamlSigningException In case of a signing error + */ + public static <T extends SignableXMLObject> T signSamlObject(@Nonnull T toSign, + @Nonnull EaafX509Credential signingCredential, boolean injectCertificate) throws SamlSigningException { + + try { + final String usedSigAlg = signingCredential.getSignatureAlgorithmForSigning(); + final Signature signature = createSignature(signingCredential, usedSigAlg, injectCertificate); + toSign.setSignature(signature); + + final String digestAlgorithm = getDigestAlgorithm(usedSigAlg); + final List<ContentReference> contentReferences = signature.getContentReferences(); + if (!CollectionUtils.isEmpty(contentReferences)) { + ((SAMLObjectContentReference) contentReferences.get(0)).setDigestAlgorithm(digestAlgorithm); + + } else { + log.error("Unable to set DigestMethodAlgorithm - algorithm {} not set", digestAlgorithm); + + } + + log.trace("Marshall samlToken."); + XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(toSign).marshall(toSign); + + log.trace("Sign samlToken."); + Signer.signObject(signature); + + return toSign; + + } catch (final SignatureException | MarshallingException | SecurityException e) { + throw new SamlSigningException("internal.pvp.96", + new Object[] { signingCredential.getEntityId(), e.getMessage() }, e); + + } + + } + + /** + * SAML2 message unmarshaller that performs schema validation before unmarshall + * the message. + * + * @param messageStream SAML2 message that shoulld be unmarshalled + * @return OpenSAML XML object + * @throws MessageDecodingException In case of a schema-validation or + * unmarshalling error + */ + public static XMLObject unmarshallMessage(final InputStream messageStream) throws MessageDecodingException { + try { + final Element samlElement = DomUtils.parseXmlValidating(messageStream); + + if (log.isTraceEnabled()) { + log.trace("Resultant DOM message was:"); + log.trace(SerializeSupport.nodeToString(samlElement)); + } + + log.debug("Unmarshalling DOM parsed from InputStream"); + final Unmarshaller unmarshaller = XMLObjectSupport.getUnmarshaller(samlElement); + if (unmarshaller == null) { + log.error("Unable to unmarshall InputStream, no unmarshaller registered for element " + + QNameSupport.getNodeQName(samlElement)); + throw new UnmarshallingException( + "Unable to unmarshall InputStream, no unmarshaller registered for element " + + QNameSupport.getNodeQName(samlElement)); + } + + final XMLObject message = unmarshaller.unmarshall(samlElement); + + log.debug("InputStream succesfully unmarshalled"); + + return message; + + } catch (final UnmarshallingException e) { + log.error("Error unmarshalling message from input stream", e); + throw new MessageDecodingException("Error unmarshalling message from input stream", e); + + } catch (ParserConfigurationException | SAXException e) { + log.warn("Message schema-validation failed."); + throw new MessageDecodingException("Message schema-validation failed.", + new SchemaValidationException("internal.pvp.03", new Object[] { e.getMessage() }, e)); + + } catch (final IOException e) { + log.error("Error read message from input stream", e); + throw new MessageDecodingException("Error read message from input stream", e); + + } + } + + /** + * Select signature algorithm for a given credential. + * + * @param credentials {@link X509Credential} that will be used for key operations + * @param rsaSigAlgorithm RSA based algorithm that should be used in + * case of RSA credential + * @param ecSigAlgorithm EC based algorithm that should be used in case + * of RSA credential + * @return either the RSA based algorithm or the EC based algorithm + * @throws SamlSigningException In case of an unsupported credential + */ + public static String getKeyOperationAlgorithmFromCredential(X509Credential credentials, + String rsaSigAlgorithm, String ecSigAlgorithm) throws SamlSigningException { + final PrivateKey privatekey = credentials.getPrivateKey(); + final PublicKey publickey = credentials.getPublicKey(); + if (privatekey instanceof RSAPrivateKey + || publickey instanceof RSAPublicKey) { + return rsaSigAlgorithm; + + } else if (privatekey instanceof ECPrivateKey + || publickey instanceof ECPublicKey) { + return ecSigAlgorithm; + + } else { + log.warn("Could NOT evaluate the Private-Key type from " + credentials.getEntityId() + + " credential."); + throw new SamlSigningException("internal.pvp.97", + new Object[] { credentials.getEntityId(), + privatekey != null ? privatekey.getClass().getName() : publickey.getClass().getName() + }); + + } + } + + /** + * Select a digest algorithm for a already selected signing algorithm. + * + * @param signatureAlgorithmName Signing algorithm that will be used + * @return Digest algorithm identifier + */ + public static String getDigestAlgorithm(String signatureAlgorithmName) { + if (StringUtils.isBlank(signatureAlgorithmName)) { + return PvpConstants.DEFAULT_DIGESTMETHODE; + } + + final String canonicalAlgorithm = signatureAlgorithmName.trim(); + final String digestAlgorithm = PvpConstants.SIGNATURE_TO_DIGEST_ALGORITHM_MAP.get(canonicalAlgorithm); + if (null != digestAlgorithm) { + return digestAlgorithm; + + } + + log.warn("Signing algorithm: {} does not contain a known digist algorithm. Use: {} as default", + signatureAlgorithmName, PvpConstants.DEFAULT_DIGESTMETHODE); + return PvpConstants.DEFAULT_DIGESTMETHODE; + + } + + /** + * Get a {@link KeyInfoGenerator} that injects key information into XML + * signature. + * + * @param credential @link X509Credential} that will be used for signing + * @param injectCertificate Set <code>true</code> if the certificate should be + * added to KeyInfo + * @return Generator for a XML signature key-information + */ + public static KeyInfoGenerator getKeyInfoGenerator(X509Credential credential, boolean injectCertificate) { + // OpenSAML3 only support RSA and DSA for direct key injection + KeyInfoGeneratorFactory keyInfoGenFac = null; + if (injectCertificate || credential.getPublicKey() instanceof ECPublicKey) { + final SignatureSigningConfiguration secConfiguration = SecurityConfigurationSupport + .getGlobalSignatureSigningConfiguration(); + final NamedKeyInfoGeneratorManager keyInfoManager = secConfiguration.getKeyInfoGeneratorManager(); + final KeyInfoGeneratorManager keyInfoGenManager = keyInfoManager.getDefaultManager(); + keyInfoGenFac = keyInfoGenManager.getFactory(credential); + + } else { + keyInfoGenFac = createKeyInfoWithoutCertificate(); + + } + + return keyInfoGenFac.newInstance(); + + } + + /** + * Create a SAML2 object. + * + * @param <T> SAML2 object class + * @param clazz object class + * @return SAML2 object + */ + public static <T> T createSamlObject(final Class<T> clazz) { + try { + final XMLObjectBuilderFactory builderFactory = + XMLObjectProviderRegistrySupport.getBuilderFactory(); + + final QName defaultElementName = + (QName) clazz.getDeclaredField("DEFAULT_ELEMENT_NAME").get(null); + @SuppressWarnings("unchecked") + final T object = + (T) builderFactory.getBuilder(defaultElementName).buildObject(defaultElementName); + return object; + } catch (final Throwable e) { + e.printStackTrace(); + return null; + } + } + + /** + * Get a new SAML2 conform random value. + * + * @return + */ + public static String getSecureIdentifier() { + return "_".concat(Random.nextHexRandom16()); + + } + + /** + * Transform SAML2 Object to Element. + * + * @param object SAML2 object + * @return Element + * @throws IOException In case of an transformation error + * @throws MarshallingException In case of an transformation error + * @throws TransformerException In case of an transformation error + */ + public static Document asDomDocument(final XMLObject object) + throws IOException, MarshallingException, TransformerException { + final Document document = builder.newDocument(); + final Marshaller out = + XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(object); + out.marshall(object, document); + return document; + } + + /** + * Build success status element. + * + * @return + */ + public static Status getSuccessStatus() { + final Status status = Saml2Utils.createSamlObject(Status.class); + final StatusCode statusCode = Saml2Utils.createSamlObject(StatusCode.class); + statusCode.setValue(StatusCode.SUCCESS); + status.setStatusCode(statusCode); + return status; + } + + /** + * Get AssertionConsumerService Index from metadata element. + * + * @param spSsoDescriptor metadata element + * @return + */ + public static int getDefaultAssertionConsumerServiceIndex(final SPSSODescriptor spSsoDescriptor) { + + final List<AssertionConsumerService> assertionConsumerList = + spSsoDescriptor.getAssertionConsumerServices(); + + for (final AssertionConsumerService el : assertionConsumerList) { + if (el.isDefault()) { + return el.getIndex(); + } + + } + + return 0; + } + + /** + * Build SOAP11 body from SAML2 object. + * + * @param payload SAML2 object + * @return + */ + public static Envelope buildSoap11Envelope(final XMLObject payload) { + final XMLObjectBuilderFactory bf = XMLObjectProviderRegistrySupport.getBuilderFactory(); + final Envelope envelope = (Envelope) bf.getBuilder(Envelope.DEFAULT_ELEMENT_NAME) + .buildObject(Envelope.DEFAULT_ELEMENT_NAME); + final Body body = + (Body) bf.getBuilder(Body.DEFAULT_ELEMENT_NAME).buildObject(Body.DEFAULT_ELEMENT_NAME); + + body.getUnknownXMLObjects().add(payload); + envelope.setBody(body); + + return envelope; + } + + /** + * Generate EAAF specific requested attribute. + * + * @param attr SAML2 attribute definition + * @param isRequired is-mandatory flag + * @param value Attribute value + * @return + */ + public static EaafRequestedAttribute generateReqAuthnAttributeSimple( + final Attribute attr, final boolean isRequired, final String value) { + final EaafRequestedAttribute requested = + Saml2Utils.createSamlObject(EaafRequestedAttribute.class); + requested.setName(attr.getName()); + requested.setNameFormat(attr.getNameFormat()); + requested.setFriendlyName(attr.getFriendlyName()); + requested.setIsRequired(String.valueOf(isRequired)); + final List<XMLObject> attributeValues = requested.getAttributeValues(); + if (StringUtils.isNotEmpty(value)) { + final XMLObject attributeValueForRequest = + createAttributeValue(PvpConstants.EIDAS_REQUESTED_ATTRIBUTE_VALUE_TYPE, value); + attributeValues.add(attributeValueForRequest); + } + return requested; + + } + + /** + * Perform XML schema-validation on SAML2 object. + * + * @param xmlObject SAML2 object + * @throws Exception In case of a validation error + */ + public static void schemeValidation(final XMLObject xmlObject) throws Exception { + try { + + final Schema test = schemaBuilder.getSAMLSchema(); + final Validator val = test.newValidator(); + final DOMSource source = new DOMSource(xmlObject.getDOM()); + val.validate(source); + log.debug("SAML2 Scheme validation successful"); + return; + + } catch (final Exception e) { + log.warn("SAML2 scheme validation FAILED.", e); + throw e; + + } + } + + private static XMLObject createAttributeValue(final QName attributeValueType, + final String value) { + final XSStringBuilder stringBuilder = (XSStringBuilder) XMLObjectProviderRegistrySupport + .getBuilderFactory().getBuilder(XSString.TYPE_NAME); + final XSString stringValue = stringBuilder.buildObject(attributeValueType, XSString.TYPE_NAME); + stringValue.setValue(value); + return stringValue; + + } + + private static Signature createSignature(X509Credential signingCredential, + String usedSigAlg, boolean injectCertificate) + throws SecurityException, SamlSigningException { + log.trace("Generating OpenSAML signature object ... "); + final Signature signature = (Signature) XMLObjectProviderRegistrySupport.getBuilderFactory() + .getBuilder(Signature.DEFAULT_ELEMENT_NAME) + .buildObject(Signature.DEFAULT_ELEMENT_NAME); + signature.setSigningCredential(signingCredential); + signature.setSignatureAlgorithm(usedSigAlg); + final KeyInfo keyInfo = getKeyInfoGenerator(signingCredential, injectCertificate).generate( + signingCredential); + signature.setKeyInfo(keyInfo); + signature.setCanonicalizationAlgorithm(SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS); + return signature; + + } + + private static KeyInfoGeneratorFactory createKeyInfoWithoutCertificate() { + final KeyInfoGeneratorFactory keyInfoGenFac = new BasicKeyInfoGeneratorFactory(); + ((BasicKeyInfoGeneratorFactory) keyInfoGenFac).setEmitPublicKeyValue(true); + ((BasicKeyInfoGeneratorFactory) keyInfoGenFac).setEmitEntityIDAsKeyName(true); + ((BasicKeyInfoGeneratorFactory) keyInfoGenFac).setEmitKeyNames(true); + ((BasicKeyInfoGeneratorFactory) keyInfoGenFac).setEmitPublicDEREncodedKeyValue(true); + return keyInfoGenFac; + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/SamlHttpUtils.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/SamlHttpUtils.java new file mode 100644 index 00000000..2e02bf22 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/SamlHttpUtils.java @@ -0,0 +1,33 @@ +package at.gv.egiz.eaaf.modules.pvp2.impl.utils; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import javax.servlet.http.HttpServletRequest; + +public class SamlHttpUtils { + + /** + * Always read the last parameter with this name from request to get a strict + * deterministic behavior. <br> + * <br> + * <b><i>If more than one parameters with the same name exists, this method + * always select the last parameter value.</i></b> + * + * @param request Incoming http request + * @param paramName Name of the http parameter + * @return the last parameter value with this name, or <code>null</code> if the + * parameter not exists + */ + @Nullable + public static String getLastParameterFromRequest(@Nonnull HttpServletRequest request, + @Nonnull String paramName) { + final String[] values = request.getParameterValues(paramName); + if (values != null && values.length > 0) { + return values[values.length - 1]; + + } + + return null; + + } +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/EAAFURICompare.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/EAAFURICompare.java deleted file mode 100644 index 30b7dcf9..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/EAAFURICompare.java +++ /dev/null @@ -1,60 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.impl.validation; - -import org.opensaml.common.binding.decoding.URIComparator; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - - -public class EAAFURICompare implements URIComparator { - private static final Logger log = LoggerFactory.getLogger(EAAFURICompare.class); - - private String serviceURL = ""; - - /** - * - * - * @param serviceURL public URL of the PVP S-Profile endpoint - */ - public EAAFURICompare(String serviceURL) { - this.serviceURL = serviceURL; - } - - public boolean compare(String uri1, String uri2) { - if (this.serviceURL.equals(uri1)) - return true; - - else { - log.warn("PVP request destination-endpoint: " + uri1 - + " does not match to IDP endpoint:" + serviceURL); - return false; - - } - } - -} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/EaafUriCompare.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/EaafUriCompare.java new file mode 100644 index 00000000..9015c40b --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/EaafUriCompare.java @@ -0,0 +1,53 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.impl.validation; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import net.shibboleth.utilities.java.support.net.URIComparator; + +public class EaafUriCompare implements URIComparator { + private static final Logger log = LoggerFactory.getLogger(EaafUriCompare.class); + + private String serviceUrl = ""; + + /** + * SAML2 URL comperator. + * + * @param serviceUrl public URL of the PVP S-Profile endpoint + */ + public EaafUriCompare(final String serviceUrl) { + this.serviceUrl = serviceUrl; + } + + @Override + public boolean compare(final String uri1, final String uri2) { + if (this.serviceUrl.equals(uri1)) { + return true; + } else { + log.warn("PVP request destination-endpoint: " + uri1 + " does not match to IDP endpoint:" + + serviceUrl); + return false; + + } + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/TrustEngineFactory.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/TrustEngineFactory.java index 18ee5797..f0758706 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/TrustEngineFactory.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/TrustEngineFactory.java @@ -1,65 +1,86 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 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: + * Licensed under the EUPL, Version 1.2 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: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * 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. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * 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.egiz.eaaf.modules.pvp2.impl.validation; import java.util.ArrayList; import java.util.List; -import org.opensaml.saml2.metadata.provider.MetadataProvider; -import org.opensaml.security.MetadataCredentialResolver; -import org.opensaml.xml.security.keyinfo.BasicProviderKeyInfoCredentialResolver; -import org.opensaml.xml.security.keyinfo.KeyInfoCredentialResolver; -import org.opensaml.xml.security.keyinfo.KeyInfoProvider; -import org.opensaml.xml.security.keyinfo.provider.DSAKeyValueProvider; -import org.opensaml.xml.security.keyinfo.provider.InlineX509DataProvider; -import org.opensaml.xml.security.keyinfo.provider.RSAKeyValueProvider; -import org.opensaml.xml.signature.SignatureTrustEngine; -import org.opensaml.xml.signature.impl.ExplicitKeySignatureTrustEngine; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2InternalErrorException; + +import org.opensaml.saml.metadata.resolver.impl.PredicateRoleDescriptorResolver; +import org.opensaml.saml.security.impl.MetadataCredentialResolver; +import org.opensaml.xmlsec.keyinfo.KeyInfoCredentialResolver; +import org.opensaml.xmlsec.keyinfo.impl.BasicProviderKeyInfoCredentialResolver; +import org.opensaml.xmlsec.keyinfo.impl.KeyInfoProvider; +import org.opensaml.xmlsec.keyinfo.impl.provider.DSAKeyValueProvider; +import org.opensaml.xmlsec.keyinfo.impl.provider.InlineX509DataProvider; +import org.opensaml.xmlsec.keyinfo.impl.provider.RSAKeyValueProvider; +import org.opensaml.xmlsec.signature.support.SignatureTrustEngine; +import org.opensaml.xmlsec.signature.support.impl.ExplicitKeySignatureTrustEngine; +import lombok.extern.slf4j.Slf4j; +import net.shibboleth.utilities.java.support.component.ComponentInitializationException; + +@Slf4j public class TrustEngineFactory { - public static SignatureTrustEngine getSignatureKnownKeysTrustEngine(MetadataProvider provider) { - MetadataCredentialResolver resolver; + /** + * Get OpenSAML2 TrustEngine. + * + * @param mdResolver Metadata provider + * @return TrustEngine for SAML2 message validation + * @throws Pvp2InternalErrorException In case of a TrustEngine initialization + * error + */ + public static SignatureTrustEngine getSignatureKnownKeysTrustEngine( + final IPvp2MetadataProvider mdResolver) throws Pvp2InternalErrorException { + try { + final List<KeyInfoProvider> keyInfoProvider = new ArrayList<>(); + keyInfoProvider.add(new DSAKeyValueProvider()); + keyInfoProvider.add(new RSAKeyValueProvider()); + keyInfoProvider.add(new InlineX509DataProvider()); + final KeyInfoCredentialResolver keyInfoCredentialResolver = new BasicProviderKeyInfoCredentialResolver( + keyInfoProvider); + + final PredicateRoleDescriptorResolver roleDescriptorResolver = new PredicateRoleDescriptorResolver( + mdResolver); + roleDescriptorResolver.setRequireValidMetadata(true); + roleDescriptorResolver.initialize(); - resolver = new MetadataCredentialResolver(provider); + final MetadataCredentialResolver resolver = new MetadataCredentialResolver(); + resolver.setRoleDescriptorResolver(roleDescriptorResolver); + resolver.setKeyInfoCredentialResolver(keyInfoCredentialResolver); + resolver.initialize(); - List<KeyInfoProvider> keyInfoProvider = new ArrayList<KeyInfoProvider>(); - keyInfoProvider.add(new DSAKeyValueProvider()); - keyInfoProvider.add(new RSAKeyValueProvider()); - keyInfoProvider.add(new InlineX509DataProvider()); + final ExplicitKeySignatureTrustEngine engine = + new ExplicitKeySignatureTrustEngine(resolver, keyInfoCredentialResolver); - KeyInfoCredentialResolver keyInfoResolver = new BasicProviderKeyInfoCredentialResolver( - keyInfoProvider); + return engine; - ExplicitKeySignatureTrustEngine engine = new ExplicitKeySignatureTrustEngine( - resolver, keyInfoResolver); + } catch (final ComponentInitializationException e) { + log.warn("Initialization of SignatureTrustEngine FAILED.", e); + throw new Pvp2InternalErrorException(e); - return engine; + } - } + } } diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/AbstractMetadataSignatureFilter.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/AbstractMetadataSignatureFilter.java index 424c4431..c28dd7fb 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/AbstractMetadataSignatureFilter.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/AbstractMetadataSignatureFilter.java @@ -1,154 +1,151 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 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: + * Licensed under the EUPL, Version 1.2 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: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * 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. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * 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.egiz.eaaf.modules.pvp2.impl.validation.metadata; import java.util.ArrayList; import java.util.Iterator; import java.util.List; -import org.opensaml.saml2.metadata.EntitiesDescriptor; -import org.opensaml.saml2.metadata.EntityDescriptor; -import org.opensaml.saml2.metadata.provider.MetadataFilter; -import org.opensaml.xml.XMLObject; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import javax.annotation.Nullable; -import at.gv.egiz.eaaf.core.exceptions.EAAFException; -import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2MetadataException; +import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2MetadataException; import at.gv.egiz.eaaf.modules.pvp2.exception.SignatureValidationException; +import org.opensaml.core.xml.XMLObject; +import org.opensaml.saml.metadata.resolver.filter.MetadataFilter; +import org.opensaml.saml.saml2.metadata.EntitiesDescriptor; +import org.opensaml.saml.saml2.metadata.EntityDescriptor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + public abstract class AbstractMetadataSignatureFilter implements MetadataFilter { - private static final Logger log = LoggerFactory.getLogger(AbstractMetadataSignatureFilter.class); - - public void doFilter(XMLObject metadata) throws SignatureValidationException { - try { - if (metadata instanceof EntitiesDescriptor) { - EntitiesDescriptor entitiesDescriptor = (EntitiesDescriptor) metadata; - if(entitiesDescriptor.getSignature() == null) { - throw new PVP2MetadataException("pvp2.26", - new Object[] {"Root element of metadata file has to be signed"}); - } - processEntitiesDescriptor(entitiesDescriptor); - - - if (entitiesDescriptor.getEntityDescriptors().size() == 0) { - throw new PVP2MetadataException("pvp2.26", - new Object[] {"No valid entity in metadata " + entitiesDescriptor.getName()}); - } - - - } else if (metadata instanceof EntityDescriptor) { - EntityDescriptor entityDescriptor = (EntityDescriptor) metadata; - processEntityDescriptorr(entityDescriptor); - - } else - throw new PVP2MetadataException("pvp2.26", - new Object[] {"Invalid Metadata file Root element is unknown"}); - - - - log.info("Metadata signature policy check done OK"); - } catch (EAAFException e) { - log.warn("Metadata signature policy check FAILED.", e); - throw new SignatureValidationException(e); - - } - } - - /** - * Signature verification of a SAML2 EntityDescriptor element - * - * @param desc - * @throws PVP2MetadataException if the signature is not valid or can not verified - */ - protected abstract void verify(EntityDescriptor desc) throws PVP2MetadataException; - - /** - * Signature verification of a SAML2 EntitiesDescriptor element - * - * @param desc - * @throws PVP2MetadataException if the signature is not valid or can not verified - */ - protected abstract void verify(EntitiesDescriptor desc) throws PVP2MetadataException; - - /** - * Verify a EntityDescriptor element of an EntitiesDescriptor - * - * @param entity EntityDescriptor to verify - * @param desc Full EntitiesDescriptor that contains the EntityDescriptor - * @throws PVP2MetadataException - */ - protected abstract void verify(EntityDescriptor entity, EntitiesDescriptor desc) throws PVP2MetadataException; - - - private void processEntityDescriptorr(EntityDescriptor desc) throws EAAFException { - verify(desc); - - } - - private void processEntitiesDescriptor(EntitiesDescriptor desc) throws EAAFException { - Iterator<EntitiesDescriptor> entID = desc.getEntitiesDescriptors().iterator(); - - if(desc.getSignature() != null) { - verify(desc); - - } - - while(entID.hasNext()) { - processEntitiesDescriptor(entID.next()); - } - - Iterator<EntityDescriptor> entIT = desc.getEntityDescriptors().iterator(); - List<EntityDescriptor> verifiedEntIT = new ArrayList<EntityDescriptor>(); - - //check every Entity - while(entIT.hasNext()) { - EntityDescriptor entity = entIT.next(); - log.debug("Validate metadata for entityID: " + entity.getEntityID() + " ..... "); - try { - verify(entity, desc); - - //add entity to verified entity-list - verifiedEntIT.add(entity); - log.debug("Metadata for entityID: " + entity.getEntityID() + " valid"); - - - } catch (Exception e) { - //remove entity of signature can not be verified. - log.info("Entity " + entity.getEntityID() + " is removed from metadata " - + desc.getName() + ". Entity verification error: " + e.getMessage()); - - } - - } - - //set only verified entity elements - desc.getEntityDescriptors().clear(); - desc.getEntityDescriptors().addAll(verifiedEntIT); - } + private static final Logger log = LoggerFactory.getLogger(AbstractMetadataSignatureFilter.class); + + @Override + public XMLObject filter(@Nullable final XMLObject metadata) throws SignatureValidationException { + try { + if (metadata instanceof EntitiesDescriptor) { + final EntitiesDescriptor entitiesDescriptor = (EntitiesDescriptor) metadata; + if (entitiesDescriptor.getSignature() == null) { + throw new Pvp2MetadataException("pvp2.26", + new Object[] { "Root element of metadata file has to be signed" }); + } + processEntitiesDescriptor(entitiesDescriptor); + + if (entitiesDescriptor.getEntityDescriptors().size() == 0) { + throw new Pvp2MetadataException("pvp2.26", + new Object[] { "No valid entity in metadata " + entitiesDescriptor.getName() }); + } + + } else if (metadata instanceof EntityDescriptor) { + final EntityDescriptor entityDescriptor = (EntityDescriptor) metadata; + processEntityDescriptorr(entityDescriptor); + + } else { + throw new Pvp2MetadataException("pvp2.26", + new Object[] { "Invalid Metadata file Root element is unknown" }); + } + + log.info("Metadata signature policy check done OK"); + } catch (final EaafException e) { + log.warn("Metadata signature policy check FAILED.", e); + throw new SignatureValidationException(e); + + } + + return metadata; + + } + + /** + * Signature verification of a SAML2 EntityDescriptor element. + * + * @param desc EntityDescriptor + * @throws Pvp2MetadataException if the signature is not valid or can not + * verified + */ + protected abstract void verify(EntityDescriptor desc) throws Pvp2MetadataException; + + /** + * Signature verification of a SAML2 EntitiesDescriptor element. + * + * @param desc EntitiesDescriptor + * @throws Pvp2MetadataException if the signature is not valid or can not + * verified + */ + protected abstract void verify(EntitiesDescriptor desc) throws Pvp2MetadataException; + + /** + * Verify a EntityDescriptor element of an EntitiesDescriptor. + * + * @param entity EntityDescriptor to verify + * @param desc Full EntitiesDescriptor that contains the EntityDescriptor + * @throws Pvp2MetadataException In case of an verification error + */ + protected abstract void verify(EntityDescriptor entity, EntitiesDescriptor desc) + throws Pvp2MetadataException; + + private void processEntityDescriptorr(final EntityDescriptor desc) throws EaafException { + verify(desc); + + } + + private void processEntitiesDescriptor(final EntitiesDescriptor desc) throws EaafException { + final Iterator<EntitiesDescriptor> entID = desc.getEntitiesDescriptors().iterator(); + + if (desc.getSignature() != null) { + verify(desc); + + } + + while (entID.hasNext()) { + processEntitiesDescriptor(entID.next()); + } + + final Iterator<EntityDescriptor> entIT = desc.getEntityDescriptors().iterator(); + final List<EntityDescriptor> verifiedEntIT = new ArrayList<>(); + + // check every Entity + while (entIT.hasNext()) { + final EntityDescriptor entity = entIT.next(); + log.debug("Validate metadata for entityID: " + entity.getEntityID() + " ..... "); + try { + verify(entity, desc); + + // add entity to verified entity-list + verifiedEntIT.add(entity); + log.debug("Metadata for entityID: " + entity.getEntityID() + " valid"); + + } catch (final Exception e) { + // remove entity of signature can not be verified. + log.info("Entity " + entity.getEntityID() + " is removed from metadata " + desc.getName() + + ". Entity verification error: " + e.getMessage()); + + } + + } + + // set only verified entity elements + desc.getEntityDescriptors().clear(); + desc.getEntityDescriptors().addAll(verifiedEntIT); + } } diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/PVPEntityCategoryFilter.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/PVPEntityCategoryFilter.java deleted file mode 100644 index 87ab31fb..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/PVPEntityCategoryFilter.java +++ /dev/null @@ -1,236 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.impl.validation.metadata; - -import java.util.ArrayList; -import java.util.List; - -import org.opensaml.common.xml.SAMLConstants; -import org.opensaml.saml2.common.Extensions; -import org.opensaml.saml2.core.Attribute; -import org.opensaml.saml2.metadata.AttributeConsumingService; -import org.opensaml.saml2.metadata.EntitiesDescriptor; -import org.opensaml.saml2.metadata.EntityDescriptor; -import org.opensaml.saml2.metadata.LocalizedString; -import org.opensaml.saml2.metadata.RequestedAttribute; -import org.opensaml.saml2.metadata.SPSSODescriptor; -import org.opensaml.saml2.metadata.ServiceName; -import org.opensaml.saml2.metadata.provider.FilterException; -import org.opensaml.saml2.metadata.provider.MetadataFilter; -import org.opensaml.samlext.saml2mdattr.EntityAttributes; -import org.opensaml.xml.XMLObject; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import at.gv.egiz.eaaf.core.impl.data.Trible; -import at.gv.egiz.eaaf.modules.pvp2.PVPConstants; -import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2MetadataException; -import at.gv.egiz.eaaf.modules.pvp2.impl.builder.PVPAttributeBuilder; -import at.gv.egiz.eaaf.modules.pvp2.impl.utils.SAML2Utils; - -/** - * @author tlenz - * - */ -public class PVPEntityCategoryFilter implements MetadataFilter { - private static final Logger log = LoggerFactory.getLogger(PVPEntityCategoryFilter.class); - - private boolean isUsed = false; - - /** - * Filter to map PVP EntityCategories into a set of single PVP attributes - * - * @param isUsed if true PVP EntityCategories are mapped, otherwise they are ignored - * - */ - public PVPEntityCategoryFilter(boolean isUsed) { - this.isUsed = isUsed; - } - - - /* (non-Javadoc) - * @see org.opensaml.saml2.metadata.provider.MetadataFilter#doFilter(org.opensaml.xml.XMLObject) - */ - @Override - public void doFilter(XMLObject metadata) throws FilterException { - - if (isUsed) { - log.trace("Map PVP EntityCategory to single PVP Attributes ... "); - String entityId = null; - try { - if (metadata instanceof EntitiesDescriptor) { - log.trace("Find EnitiesDescriptor ... "); - EntitiesDescriptor entitiesDesc = (EntitiesDescriptor) metadata; - if (entitiesDesc.getEntityDescriptors() != null) { - for (EntityDescriptor el : entitiesDesc.getEntityDescriptors()) - resolveEntityCategoriesToAttributes(el); - - } - - } else if (metadata instanceof EntityDescriptor) { - log.trace("Find EntityDescriptor"); - resolveEntityCategoriesToAttributes((EntityDescriptor)metadata); - - - } else - throw new PVP2MetadataException("pvp2.26", - new Object[] {"Invalid Metadata file Root element is no Entities- or EntityDescriptor"}); - - - - } catch (Exception e) { - log.warn("SAML2 Metadata processing FAILED: Can not resolve EntityCategories for metadata: " + entityId, e); - - } - - } else - log.trace("Filter to map PVP EntityCategory to single PVP Attributes is deactivated"); - - } - - private void resolveEntityCategoriesToAttributes(EntityDescriptor metadata) { - log.debug("Resolving EntityCategorie for Entity: " + metadata.getEntityID() + " ..."); - Extensions extensions = metadata.getExtensions(); - if (extensions != null) { - List<XMLObject> listOfExt = extensions.getUnknownXMLObjects(); - if (listOfExt != null && !listOfExt.isEmpty()) { - log.trace("Find #" + listOfExt.size() + " 'Extension' elements "); - for (XMLObject el : listOfExt) { - log.trace("Find ExtensionElement: " + el.getElementQName().toString()); - if (el instanceof EntityAttributes) { - EntityAttributes entityAttrElem = (EntityAttributes)el; - if (entityAttrElem.getAttributes() != null) { - log.trace("Find EntityAttributes. Start attribute processing ..."); - for (Attribute entityAttr : entityAttrElem.getAttributes()) { - if (entityAttr.getName().equals(PVPConstants.ENTITY_CATEGORY_ATTRIBITE)) { - if (!entityAttr.getAttributeValues().isEmpty()) { - String entityAttrValue = entityAttr.getAttributeValues().get(0).getDOM().getTextContent(); - if (PVPConstants.EGOVTOKEN.equals(entityAttrValue)) { - log.debug("Find 'EGOVTOKEN' EntityAttribute. Adding single pvp attributes ... "); - addAttributesToEntityDescriptor(metadata, - buildAttributeList(PVPConstants.EGOVTOKEN_PVP_ATTRIBUTES), - entityAttrValue); - - - } else if (PVPConstants.CITIZENTOKEN.equals(entityAttrValue)) { - log.debug("Find 'CITIZENTOKEN' EntityAttribute. Adding single pvp attributes ... "); - addAttributesToEntityDescriptor(metadata, - buildAttributeList(PVPConstants.CITIZENTOKEN_PVP_ATTRIBUTES), - entityAttrValue); - - } else - log.info("EntityAttributeValue: " + entityAttrValue + " is UNKNOWN!"); - - } else - log.info("EntityAttribute: No attribute value"); - - } else - log.info("EntityAttribute: " + entityAttr.getName() + " is NOT supported"); - - } - - } else - log.info("Can NOT resolve EntityAttributes! Reason: Only EntityAttributes are supported!"); - - } - } - - } else - log.trace("'Extension' element is 'null' or empty"); - - } else - log.trace("No 'Extension' element found"); - - } - - /** - * @param metadata - * @param attrList - */ - private void addAttributesToEntityDescriptor(EntityDescriptor metadata, List<RequestedAttribute> attrList, String entityAttr) { - SPSSODescriptor spSSODesc = metadata.getSPSSODescriptor(SAMLConstants.SAML20P_NS); - if (spSSODesc != null) { - if (spSSODesc.getAttributeConsumingServices() == null || - spSSODesc.getAttributeConsumingServices().isEmpty()) { - log.trace("No 'AttributeConsumingServices' found. Added it ..."); - - AttributeConsumingService attributeService = SAML2Utils.createSAMLObject(AttributeConsumingService.class); - attributeService.setIndex(0); - attributeService.setIsDefault(true); - ServiceName serviceName = SAML2Utils.createSAMLObject(ServiceName.class); - serviceName.setName(new LocalizedString("Default Service", "en")); - attributeService.getNames().add(serviceName); - - if (attrList != null && !attrList.isEmpty()) { - attributeService.getRequestAttributes().addAll(attrList); - log.info("Add " + attrList.size() + " attributes for 'EntityAttribute': " + entityAttr); - - } - - spSSODesc.getAttributeConsumingServices().add(attributeService); - - } else { - log.debug("Find 'AttributeConsumingServices'. Starting updating process ... "); - for (AttributeConsumingService el : spSSODesc.getAttributeConsumingServices()) { - log.debug("Update 'AttributeConsumingService' with Index: " + el.getIndex()); - - //load currently requested attributes - List<String> currentlyReqAttr = new ArrayList<String>(); - for (RequestedAttribute reqAttr : el.getRequestAttributes()) - currentlyReqAttr.add(reqAttr.getName()); - - - //check against EntityAttribute List - for (RequestedAttribute entityAttrListEl : attrList) { - if (!currentlyReqAttr.contains(entityAttrListEl.getName())) { - el.getRequestAttributes().add(entityAttrListEl); - - } else - log.debug("'AttributeConsumingService' already contains attr: " + entityAttrListEl.getName()); - - } - - } - - } - - } else - log.info("Can ONLY add 'EntityAttributes' to 'SPSSODescriptor'"); - - } - - private List<RequestedAttribute> buildAttributeList(List<Trible<String, String, Boolean>> attrSet) { - List<RequestedAttribute> requestedAttributes = new ArrayList<RequestedAttribute>(); - for (Trible<String, String, Boolean> el : attrSet) - requestedAttributes.add(PVPAttributeBuilder.buildReqAttribute(el.getFirst(), el.getSecond(), el.getThird())); - - return requestedAttributes; - - - } - -} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/PvpEntityCategoryFilter.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/PvpEntityCategoryFilter.java new file mode 100644 index 00000000..efbeb7e5 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/PvpEntityCategoryFilter.java @@ -0,0 +1,252 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.impl.validation.metadata; + +import java.util.ArrayList; +import java.util.List; + +import at.gv.egiz.eaaf.core.impl.data.Triple; +import at.gv.egiz.eaaf.modules.pvp2.PvpConstants; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2MetadataException; +import at.gv.egiz.eaaf.modules.pvp2.impl.builder.PvpAttributeBuilder; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils; + +import org.opensaml.core.xml.XMLObject; +import org.opensaml.saml.common.xml.SAMLConstants; +import org.opensaml.saml.ext.saml2mdattr.EntityAttributes; +import org.opensaml.saml.metadata.resolver.filter.FilterException; +import org.opensaml.saml.metadata.resolver.filter.MetadataFilter; +import org.opensaml.saml.saml2.core.Attribute; +import org.opensaml.saml.saml2.metadata.AttributeConsumingService; +import org.opensaml.saml.saml2.metadata.EntitiesDescriptor; +import org.opensaml.saml.saml2.metadata.EntityDescriptor; +import org.opensaml.saml.saml2.metadata.Extensions; +import org.opensaml.saml.saml2.metadata.RequestedAttribute; +import org.opensaml.saml.saml2.metadata.SPSSODescriptor; +import org.opensaml.saml.saml2.metadata.ServiceName; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Metadata filter that inject requested attributes based on Metadata + * EntityCategories. + * + * @author tlenz + * + */ +public class PvpEntityCategoryFilter implements MetadataFilter { + private static final Logger log = LoggerFactory.getLogger(PvpEntityCategoryFilter.class); + + private boolean isUsed = false; + + /** + * Filter to map PVP EntityCategories into a set of single PVP attributes. + * + * @param isUsed if true PVP EntityCategories are mapped, otherwise they are + * ignored + * + */ + public PvpEntityCategoryFilter(final boolean isUsed) { + this.isUsed = isUsed; + } + + /* + * (non-Javadoc) + * + * @see + * org.opensaml.saml2.metadata.provider.MetadataFilter#doFilter(org.opensaml.xml + * .XMLObject) + */ + @Override + public XMLObject filter(final XMLObject metadata) throws FilterException { + + if (isUsed) { + log.trace("Map PVP EntityCategory to single PVP Attributes ... "); + final String entityId = null; + try { + if (metadata instanceof EntitiesDescriptor) { + log.trace("Find EnitiesDescriptor ... "); + final EntitiesDescriptor entitiesDesc = (EntitiesDescriptor) metadata; + if (entitiesDesc.getEntityDescriptors() != null) { + for (final EntityDescriptor el : entitiesDesc.getEntityDescriptors()) { + resolveEntityCategoriesToAttributes(el); + } + + } + + } else if (metadata instanceof EntityDescriptor) { + log.trace("Find EntityDescriptor"); + resolveEntityCategoriesToAttributes((EntityDescriptor) metadata); + + } else { + throw new Pvp2MetadataException("pvp2.26", new Object[] { + "Invalid Metadata file Root element is no Entities- or EntityDescriptor" }); + } + + } catch (final Exception e) { + log.warn("SAML2 Metadata processing FAILED: Can not resolve EntityCategories for metadata: " + + entityId, e); + + } + + } else { + log.trace("Filter to map PVP EntityCategory to single PVP Attributes is deactivated"); + + } + + return metadata; + + } + + private void resolveEntityCategoriesToAttributes(final EntityDescriptor metadata) { + log.debug("Resolving EntityCategorie for Entity: " + metadata.getEntityID() + " ..."); + final Extensions extensions = metadata.getExtensions(); + if (extensions != null) { + final List<XMLObject> listOfExt = extensions.getUnknownXMLObjects(); + if (listOfExt != null && !listOfExt.isEmpty()) { + log.trace("Find #" + listOfExt.size() + " 'Extension' elements "); + for (final XMLObject el : listOfExt) { + log.trace("Find ExtensionElement: " + el.getElementQName().toString()); + if (el instanceof EntityAttributes) { + final EntityAttributes entityAttrElem = (EntityAttributes) el; + if (entityAttrElem.getAttributes() != null) { + log.trace("Find EntityAttributes. Start attribute processing ..."); + for (final Attribute entityAttr : entityAttrElem.getAttributes()) { + if (entityAttr.getName().equals(PvpConstants.ENTITY_CATEGORY_ATTRIBITE)) { + if (!entityAttr.getAttributeValues().isEmpty()) { + final String entityAttrValue = + entityAttr.getAttributeValues().get(0).getDOM().getTextContent(); + if (PvpConstants.EGOVTOKEN.equals(entityAttrValue)) { + log.debug( + "Find 'EGOVTOKEN' EntityAttribute. Adding single pvp attributes ... "); + addAttributesToEntityDescriptor(metadata, + buildAttributeList(PvpConstants.EGOVTOKEN_PVP_ATTRIBUTES), + entityAttrValue); + + } else if (PvpConstants.CITIZENTOKEN.equals(entityAttrValue)) { + log.debug( + "Find 'CITIZENTOKEN' EntityAttribute. Adding single pvp attributes ... "); + addAttributesToEntityDescriptor(metadata, + buildAttributeList(PvpConstants.CITIZENTOKEN_PVP_ATTRIBUTES), + entityAttrValue); + + } else { + log.info("EntityAttributeValue: " + entityAttrValue + " is UNKNOWN!"); + } + + } else { + log.info("EntityAttribute: No attribute value"); + } + + } else { + log.info("EntityAttribute: " + entityAttr.getName() + " is NOT supported"); + } + + } + + } else { + log.info( + "Can NOT resolve EntityAttributes! Reason: Only EntityAttributes are supported!"); + } + + } + } + + } else { + log.trace("'Extension' element is 'null' or empty"); + } + + } else { + log.trace("No 'Extension' element found"); + } + + } + + private void addAttributesToEntityDescriptor(final EntityDescriptor metadata, + final List<RequestedAttribute> attrList, final String entityAttr) { + final SPSSODescriptor spSsoDesc = metadata.getSPSSODescriptor(SAMLConstants.SAML20P_NS); + if (spSsoDesc != null) { + if (spSsoDesc.getAttributeConsumingServices() == null + || spSsoDesc.getAttributeConsumingServices().isEmpty()) { + log.trace("No 'AttributeConsumingServices' found. Added it ..."); + + final AttributeConsumingService attributeService = + Saml2Utils.createSamlObject(AttributeConsumingService.class); + attributeService.setIndex(0); + attributeService.setIsDefault(true); + final ServiceName serviceName = Saml2Utils.createSamlObject(ServiceName.class); + serviceName.setValue("Default Service"); + serviceName.setXMLLang("en"); + attributeService.getNames().add(serviceName); + + if (attrList != null && !attrList.isEmpty()) { + attributeService.getRequestAttributes().addAll(attrList); + log.info("Add " + attrList.size() + " attributes for 'EntityAttribute': " + entityAttr); + + } + + spSsoDesc.getAttributeConsumingServices().add(attributeService); + + } else { + log.debug("Find 'AttributeConsumingServices'. Starting updating process ... "); + for (final AttributeConsumingService el : spSsoDesc.getAttributeConsumingServices()) { + log.debug("Update 'AttributeConsumingService' with Index: " + el.getIndex()); + + // load currently requested attributes + final List<String> currentlyReqAttr = new ArrayList<>(); + for (final RequestedAttribute reqAttr : el.getRequestAttributes()) { + currentlyReqAttr.add(reqAttr.getName()); + } + + // check against EntityAttribute List + for (final RequestedAttribute entityAttrListEl : attrList) { + if (!currentlyReqAttr.contains(entityAttrListEl.getName())) { + el.getRequestAttributes().add(entityAttrListEl); + + } else { + log.debug("'AttributeConsumingService' already contains attr: " + + entityAttrListEl.getName()); + } + + } + + } + + } + + } else { + log.info("Can ONLY add 'EntityAttributes' to 'SPSSODescriptor'"); + } + + } + + private List<RequestedAttribute> buildAttributeList( + final List<Triple<String, String, Boolean>> attrSet) { + final List<RequestedAttribute> requestedAttributes = new ArrayList<>(); + for (final Triple<String, String, Boolean> el : attrSet) { + requestedAttributes + .add(PvpAttributeBuilder.buildReqAttribute(el.getFirst(), el.getSecond(), el.getThird())); + } + + return requestedAttributes; + + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/SchemaValidationFilter.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/SchemaValidationFilter.java index b5de4b21..b9e0c37f 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/SchemaValidationFilter.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/SchemaValidationFilter.java @@ -1,106 +1,96 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 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: + * Licensed under the EUPL, Version 1.2 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: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * 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. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * 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.egiz.eaaf.modules.pvp2.impl.validation.metadata; import javax.xml.transform.dom.DOMSource; import javax.xml.validation.Schema; import javax.xml.validation.Validator; -import org.opensaml.common.xml.SAMLSchemaBuilder; -import org.opensaml.saml2.metadata.provider.FilterException; -import org.opensaml.saml2.metadata.provider.MetadataFilter; -import org.opensaml.xml.XMLObject; +import at.gv.egiz.eaaf.modules.pvp2.exception.SchemaValidationException; + +import org.opensaml.core.xml.XMLObject; +import org.opensaml.saml.common.xml.SAMLSchemaBuilder; +import org.opensaml.saml.common.xml.SAMLSchemaBuilder.SAML1Version; +import org.opensaml.saml.metadata.resolver.filter.FilterException; +import org.opensaml.saml.metadata.resolver.filter.MetadataFilter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.xml.sax.SAXException; -import at.gv.egiz.eaaf.modules.pvp2.exception.SchemaValidationException; - -/** - * @author tlenz - * - */ public class SchemaValidationFilter implements MetadataFilter { - private static final Logger log = LoggerFactory.getLogger(SchemaValidationFilter.class); - private boolean isActive = true; - - public SchemaValidationFilter() { - } - - /** - * - */ - public SchemaValidationFilter(boolean useSchemaValidation) { - this.isActive = useSchemaValidation; - } - - - /* (non-Javadoc) - * @see org.opensaml.saml2.metadata.provider.MetadataFilter#doFilter(org.opensaml.xml.XMLObject) - */ - @Override - public void doFilter(XMLObject arg0) throws FilterException { - - String errString = null; - - if (isActive) { - try { - Schema test = SAMLSchemaBuilder.getSAML11Schema(); - Validator val = test.newValidator(); - DOMSource source = new DOMSource(arg0.getDOM()); - val.validate(source); - log.info("Metadata Schema validation check done OK"); - return; - - } catch (SAXException e) { - if (log.isDebugEnabled() || log.isTraceEnabled()) - log.warn("Metadata Schema validation FAILED with exception:", e); - else - log.warn("Metadata Schema validation FAILED with message: "+ e.getMessage()); - - errString = e.getMessage(); - - } catch (Exception e) { - if (log.isDebugEnabled() || log.isTraceEnabled()) - log.warn("Metadata Schema validation FAILED with exception:", e); - else - log.warn("Metadata Schema validation FAILED with message: "+ e.getMessage()); - - errString = e.getMessage(); - - } - - throw new FilterException( - new SchemaValidationException("pvp2.26", - new Object[] {"Metadata Schema validation FAILED with message: " + errString})); - - } else - log.info("Metadata Schema validation check is DEACTIVATED!"); - - } + private static final Logger log = LoggerFactory.getLogger(SchemaValidationFilter.class); + private boolean isActive = true; + + private static SAMLSchemaBuilder schemaBuilder = new SAMLSchemaBuilder(SAML1Version.SAML_11); + + /** + * XML Schema validation filter for SAML2 metadata. + * <p>Schemavalidation is active by default</p> + */ + public SchemaValidationFilter() { + + } + + /** + * XML Schema validation filter for SAML2 metadata. + * + * @param useSchemaValidation <code>true</code> XML schema validation is active, otherwise <code>false</code> + */ + public SchemaValidationFilter(final boolean useSchemaValidation) { + this.isActive = useSchemaValidation; + } + + /* + * (non-Javadoc) + * + * @see + * org.opensaml.saml2.metadata.provider.MetadataFilter#doFilter(org.opensaml.xml + * .XMLObject) + */ + @Override + public XMLObject filter(final XMLObject arg0) throws FilterException { + + if (isActive) { + try { + final Schema test = schemaBuilder.getSAMLSchema(); + final Validator val = test.newValidator(); + final DOMSource source = new DOMSource(arg0.getDOM()); + val.validate(source); + log.info("Metadata Schema validation check done OK"); + + } catch (final Exception e) { + if (log.isDebugEnabled() || log.isTraceEnabled()) { + log.warn("Metadata Schema validation FAILED with exception:", e); + } else { + log.warn("Metadata Schema validation FAILED with message: " + e.getMessage()); + } + + throw new FilterException(new SchemaValidationException("internal.pvp.03", + new Object[] { e.getMessage() }, e)); + } + + } else { + log.info("Metadata Schema validation check is DEACTIVATED!"); + + } + + return arg0; + } } diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/SimpleMetadataSignatureVerificationFilter.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/SimpleMetadataSignatureVerificationFilter.java new file mode 100644 index 00000000..ef09e5c4 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/SimpleMetadataSignatureVerificationFilter.java @@ -0,0 +1,146 @@ +/* + * Copyright 2018 A-SIT Plus GmbH + * AT-specific eIDAS Connector has been developed in a cooperation between EGIZ, + * A-SIT Plus GmbH, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "License"); + * You may not use this work except in compliance with the License. + * You may obtain a copy of the License at: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * 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.egiz.eaaf.modules.pvp2.impl.validation.metadata; + +import java.util.ArrayList; +import java.util.List; + +import javax.annotation.Nonnull; + +import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2MetadataException; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlMetadataSignatureException; + +import org.opensaml.saml.common.SignableSAMLObject; +import org.opensaml.saml.saml2.metadata.EntitiesDescriptor; +import org.opensaml.saml.saml2.metadata.EntityDescriptor; +import org.opensaml.saml.security.impl.SAMLSignatureProfileValidator; +import org.opensaml.security.x509.BasicX509Credential; +import org.opensaml.xmlsec.signature.support.SignatureException; +import org.opensaml.xmlsec.signature.support.SignatureValidator; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class SimpleMetadataSignatureVerificationFilter extends AbstractMetadataSignatureFilter { + + private final String metadataUrl; + private final List<BasicX509Credential> trustedCredential = new ArrayList<>(); + + private static final String ERROR_07 = "internal.pvp.07"; + private static final String ERROR_12 = "internal.pvp.12"; + private static final String ERROR_MSG_ENTITIESDESC = "EntitiesDescritors are NOT supported"; + private static final String ERROR_MSG_SIGNOTVALID = "Signature not valid or no trusted certificate found"; + + /** + * SAML2 metadata-signature verification-filter that uses a simple {@link List} + * of trusted {@link BasicX509Credential} as truststore. <br> + * <p> + * This filter only validates {@link EntityDescriptor} elements.<br> + * SAML2 metadata with {@link EntitiesDescriptor} <b>are not supported.</b> + * </p> + * + * @param credentials Trust X509 certificates + * @param metadataUrl Metadata URL for logging purposes + */ + public SimpleMetadataSignatureVerificationFilter(@Nonnull List<BasicX509Credential> credentials, + @Nonnull String metadataUrl) { + this.metadataUrl = metadataUrl; + this.trustedCredential.addAll(credentials); + + } + + @Override + protected void verify(EntityDescriptor desc) throws Pvp2MetadataException { + try { + internalVerify(desc); + + } catch (final EaafException e) { + log.info("Metadata verification FAILED for: {} Reason: {}", metadataUrl, e.getMessage()); + throw new Pvp2MetadataException(ERROR_07, + new Object[] { metadataUrl, e.getMessage() }, e); + + } + } + + @Override + protected void verify(EntitiesDescriptor desc) throws Pvp2MetadataException { + throw new Pvp2MetadataException(ERROR_07, + new Object[] { metadataUrl, ERROR_MSG_ENTITIESDESC }); + + } + + @Override + protected void verify(EntityDescriptor entity, EntitiesDescriptor desc) throws Pvp2MetadataException { + throw new Pvp2MetadataException(ERROR_07, + new Object[] { metadataUrl, ERROR_MSG_ENTITIESDESC }); + + } + + private void internalVerify(SignableSAMLObject signedElement) + throws EaafException { + // check if signature exists + if (signedElement.getSignature() == null) { + throw new Pvp2MetadataException(ERROR_12, + new Object[] { metadataUrl }); + + } + + // perform general signature validation + try { + final SAMLSignatureProfileValidator sigValidator = new SAMLSignatureProfileValidator(); + sigValidator.validate(signedElement.getSignature()); + + } catch (final SignatureException e) { + log.error("Failed to validate Signature", e); + throw new Pvp2MetadataException(ERROR_07, + new Object[] { metadataUrl, e.getMessage() }, e); + + } + + // perform cryptographic signature verification + boolean isTrusted = false; + for (final BasicX509Credential cred : trustedCredential) { + log.trace("Validating signature with credential: {} ... ", + cred.getEntityCertificate().getSubjectDN()); + try { + SignatureValidator.validate(signedElement.getSignature(), cred); + isTrusted = true; + + } catch (final SignatureException e) { + log.debug("Failed to verfiy Signature with cert: {} Reason: {}", + cred.getEntityCertificate().getSubjectDN(), e.getMessage()); + + } + } + + if (!isTrusted) { + log.info("PVP2 metadata: " + metadataUrl + " are NOT trusted!"); + throw new SamlMetadataSignatureException(metadataUrl, ERROR_MSG_SIGNOTVALID); + + } + + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/AbstractRequestSignedSecurityPolicyRule.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/AbstractRequestSignedSecurityPolicyRule.java deleted file mode 100644 index f1dd1269..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/AbstractRequestSignedSecurityPolicyRule.java +++ /dev/null @@ -1,195 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.impl.verification; - -import javax.xml.namespace.QName; -import javax.xml.transform.dom.DOMSource; -import javax.xml.validation.Schema; -import javax.xml.validation.Validator; - -import org.apache.commons.lang3.StringUtils; -import org.opensaml.common.SignableSAMLObject; -import org.opensaml.common.xml.SAMLConstants; -import org.opensaml.common.xml.SAMLSchemaBuilder; -import org.opensaml.security.MetadataCriteria; -import org.opensaml.security.SAMLSignatureProfileValidator; -import org.opensaml.ws.message.MessageContext; -import org.opensaml.ws.security.SecurityPolicyException; -import org.opensaml.ws.security.SecurityPolicyRule; -import org.opensaml.xml.XMLObject; -import org.opensaml.xml.security.CriteriaSet; -import org.opensaml.xml.security.credential.UsageType; -import org.opensaml.xml.security.criteria.EntityIDCriteria; -import org.opensaml.xml.security.criteria.UsageCriteria; -import org.opensaml.xml.signature.SignatureTrustEngine; -import org.opensaml.xml.validation.ValidationException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Element; -import org.xml.sax.SAXException; - -import at.gv.egiz.eaaf.modules.pvp2.exception.SchemaValidationException; - -/** - * @author tlenz - * - */ -public abstract class AbstractRequestSignedSecurityPolicyRule implements SecurityPolicyRule { - - private static final Logger log = LoggerFactory.getLogger(AbstractRequestSignedSecurityPolicyRule.class); - - - private SignatureTrustEngine trustEngine = null; - private QName peerEntityRole = null; - /** - * @param peerEntityRole - * - */ - public AbstractRequestSignedSecurityPolicyRule(SignatureTrustEngine trustEngine, QName peerEntityRole) { - this.trustEngine = trustEngine; - this.peerEntityRole = peerEntityRole; - - } - - - /** - * Reload the PVP metadata for a given entity - * - * @param entityID for which the metadata should be refreshed. - * @return true if the refresh was successful, otherwise false - */ - protected abstract boolean refreshMetadataProvider(String entityID); - - - protected abstract SignableSAMLObject getSignedSAMLObject(XMLObject inboundData); - - /* (non-Javadoc) - * @see org.opensaml.ws.security.SecurityPolicyRule#evaluate(org.opensaml.ws.message.MessageContext) - */ - @Override - public void evaluate(MessageContext context) throws SecurityPolicyException { - try { - verifySignature(context); - - } catch (SecurityPolicyException e) { - if (StringUtils.isEmpty(context.getInboundMessageIssuer())) { - throw e; - - } - log.debug("PVP2X message validation FAILED. Reload metadata for entityID: " + context.getInboundMessageIssuer()); - if (!refreshMetadataProvider(context.getInboundMessageIssuer())) - throw e; - - else { - log.trace("PVP2X metadata reload finished. Check validate message again."); - verifySignature(context); - - } - log.trace("Second PVP2X message validation finished"); - - } - - - } - - private void verifySignature(MessageContext context) throws SecurityPolicyException { - SignableSAMLObject samlObj = getSignedSAMLObject(context.getInboundMessage()); - if (samlObj != null && samlObj.getSignature() != null) { - - SAMLSignatureProfileValidator profileValidator = new SAMLSignatureProfileValidator(); - try { - profileValidator.validate(samlObj.getSignature()); - performSchemaValidation(samlObj.getDOM()); - - } catch (ValidationException e) { - log.warn("Signature is not conform to SAML signature profile", e); - throw new SecurityPolicyException("Signature is not conform to SAML signature profile"); - - } catch (SchemaValidationException e) { - log.warn("Signature is not conform to SAML signature profile", e); - throw new SecurityPolicyException("Signature is not conform to SAML signature profile"); - - } - - - - CriteriaSet criteriaSet = new CriteriaSet(); - criteriaSet.add( new EntityIDCriteria(context.getInboundMessageIssuer()) ); - criteriaSet.add( new MetadataCriteria(peerEntityRole, SAMLConstants.SAML20P_NS) ); - criteriaSet.add( new UsageCriteria(UsageType.SIGNING) ); - - try { - if (!trustEngine.validate(samlObj.getSignature(), criteriaSet)) { - throw new SecurityPolicyException("Signature validation FAILED."); - - } - log.debug("PVP message signature valid."); - - } catch (org.opensaml.xml.security.SecurityException e) { - log.info("PVP2x message signature validation FAILED. Message:" + e.getMessage()); - throw new SecurityPolicyException("Signature validation FAILED."); - - } - - } else { - throw new SecurityPolicyException("PVP Message is not signed."); - - } - - } - - private void performSchemaValidation(Element source) throws SchemaValidationException { - - String err = null; - try { - Schema test = SAMLSchemaBuilder.getSAML11Schema(); - Validator val = test.newValidator(); - val.validate(new DOMSource(source)); - log.debug("Schema validation check done OK"); - return; - - } catch (SAXException e) { - err = e.getMessage(); - if (log.isDebugEnabled() || log.isTraceEnabled()) - log.warn("Schema validation FAILED with exception:", e); - else - log.warn("Schema validation FAILED with message: "+ e.getMessage()); - - } catch (Exception e) { - err = e.getMessage(); - if (log.isDebugEnabled() || log.isTraceEnabled()) - log.warn("Schema validation FAILED with exception:", e); - else - log.warn("Schema validation FAILED with message: "+ e.getMessage()); - - } - - throw new SchemaValidationException("pvp2.22", new Object[]{err}); - - } - -} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/EaafMessageContextInitializationHandler.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/EaafMessageContextInitializationHandler.java new file mode 100644 index 00000000..aba0a68b --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/EaafMessageContextInitializationHandler.java @@ -0,0 +1,64 @@ +package at.gv.egiz.eaaf.modules.pvp2.impl.verification; + +import javax.annotation.Nonnull; + +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2InternalErrorException; +import at.gv.egiz.eaaf.modules.pvp2.impl.validation.TrustEngineFactory; + +import org.opensaml.core.config.ConfigurationService; +import org.opensaml.messaging.context.MessageContext; +import org.opensaml.messaging.handler.AbstractMessageHandler; +import org.opensaml.messaging.handler.MessageHandlerException; +import org.opensaml.saml.common.SAMLObject; +import org.opensaml.saml.common.messaging.context.SAMLMessageInfoContext; +import org.opensaml.saml.common.messaging.context.SAMLPeerEntityContext; +import org.opensaml.xmlsec.SignatureValidationConfiguration; +import org.opensaml.xmlsec.SignatureValidationParameters; +import org.opensaml.xmlsec.context.SecurityParametersContext; +import org.opensaml.xmlsec.signature.support.SignatureTrustEngine; + +import lombok.extern.slf4j.Slf4j; +import net.shibboleth.utilities.java.support.component.ComponentInitializationException; + +@Slf4j +public class EaafMessageContextInitializationHandler extends AbstractMessageHandler<SAMLObject> { + + private final IPvp2MetadataProvider internalMetadataProvider; + private SignatureTrustEngine trustEngine; + + public EaafMessageContextInitializationHandler(@Nonnull IPvp2MetadataProvider metadataProvider) { + internalMetadataProvider = metadataProvider; + } + + @Override + protected void doInitialize() throws ComponentInitializationException { + try { + trustEngine = TrustEngineFactory.getSignatureKnownKeysTrustEngine(internalMetadataProvider); + + } catch (final Pvp2InternalErrorException e) { + throw new ComponentInitializationException("TrustEngine injection FAILED", e); + + } + } + + + @Override + protected void doInvoke(MessageContext<SAMLObject> messageContext) throws MessageHandlerException { + log.trace("Injecting sub-context to SAML2 message ... "); + messageContext.addSubcontext(new SAMLPeerEntityContext()); + messageContext.addSubcontext(new SAMLMessageInfoContext()); + + + final SecurityParametersContext securityParameterContext = new SecurityParametersContext(); + final SignatureValidationParameters sigValParameters = new SignatureValidationParameters(); + securityParameterContext.setSignatureValidationParameters(sigValParameters); + messageContext.addSubcontext(securityParameterContext); + + sigValParameters.setBlacklistedAlgorithms( + ConfigurationService.get(SignatureValidationConfiguration.class) + .getBlacklistedAlgorithms()); + sigValParameters.setSignatureTrustEngine(trustEngine); + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/EaafSaml2HttpRedirectDeflateSignatureSecurityHandler.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/EaafSaml2HttpRedirectDeflateSignatureSecurityHandler.java new file mode 100644 index 00000000..204229ee --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/EaafSaml2HttpRedirectDeflateSignatureSecurityHandler.java @@ -0,0 +1,107 @@ +package at.gv.egiz.eaaf.modules.pvp2.impl.verification; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IRefreshableMetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlSigningException; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.SamlHttpUtils; + +import org.opensaml.messaging.context.MessageContext; +import org.opensaml.messaging.handler.MessageHandlerException; +import org.opensaml.saml.common.messaging.context.SAMLPeerEntityContext; +import org.opensaml.saml.saml2.binding.security.impl.SAML2HTTPRedirectDeflateSignatureSecurityHandler; + +import com.google.common.base.Strings; +import lombok.extern.slf4j.Slf4j; +import net.shibboleth.utilities.java.support.codec.Base64Support; + +/** + * Always extracts the last http parameter with a specific name from request, if + * more than one with the same name exists. + * + * @author tlenz + * + */ +@Slf4j +public class EaafSaml2HttpRedirectDeflateSignatureSecurityHandler extends + SAML2HTTPRedirectDeflateSignatureSecurityHandler { + + public static final String HTTP_REDIRECT_SIGALG = "SigAlg"; + public static final String HTTP_REDIRECT_SIGNATURE = "Signature"; + + private IRefreshableMetadataProvider refreshableMetadataProvider = null; + + /** + * Signature verification handler that reloads SAML2 metadata if signature + * verification fails. + * + * @param metadataProvider Metadata provider implementation. Refreshing is only + * possible, if that provider implements + * {@link IRefreshableMetadataProvider} + */ + public EaafSaml2HttpRedirectDeflateSignatureSecurityHandler( + @Nullable IPvp2MetadataProvider metadataProvider) { + if (metadataProvider != null) { + if (metadataProvider instanceof IRefreshableMetadataProvider) { + refreshableMetadataProvider = (IRefreshableMetadataProvider) metadataProvider; + + } else { + log.trace("Refreshing is not supported by {} metadata-provider", + metadataProvider.getClass().getSimpleName()); + + } + } + } + + @Override + protected void doInvoke(@Nonnull final MessageContext messageContext) throws MessageHandlerException { + try { + super.doInvoke(messageContext); + + } catch (final MessageHandlerException e) { + if (refreshableMetadataProvider != null) { + + log.debug("Starting metadata refresh process ... "); + if (refreshableMetadataProvider.refreshMetadataProvider( + messageContext.getSubcontext(SAMLPeerEntityContext.class).getEntityId())) { + log.trace("Refreshing successful. Restarting message evaluation ... "); + + try { + super.doInvoke(messageContext); + return; + + } catch (final MessageHandlerException e1) { + log.debug("Signature validation fails twice with second error: {}", e.getMessage()); + + } + } + } + + log.info("Signature validation of SAML message failed. Reason: {}", e.getMessage()); + throw new MessageHandlerException( + new SamlSigningException("internal.pvp.10", new Object[] { e.getMessage() }, e)); + } + } + + @Override + @Nullable + protected byte[] getSignature() throws MessageHandlerException { + final String signature = SamlHttpUtils.getLastParameterFromRequest( + getHttpServletRequest(), HTTP_REDIRECT_SIGNATURE); + + if (Strings.isNullOrEmpty(signature)) { + return null; + + } + return Base64Support.decode(signature); + } + + @Override + @Nullable + protected String getSignatureAlgorithm() throws MessageHandlerException { + return SamlHttpUtils.getLastParameterFromRequest(getHttpServletRequest(), HTTP_REDIRECT_SIGALG); + + } +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/EaafSamlProtocolMessageXmlSignatureSecurityHandler.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/EaafSamlProtocolMessageXmlSignatureSecurityHandler.java new file mode 100644 index 00000000..9f6bc864 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/EaafSamlProtocolMessageXmlSignatureSecurityHandler.java @@ -0,0 +1,75 @@ +package at.gv.egiz.eaaf.modules.pvp2.impl.verification; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IRefreshableMetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlSigningException; + +import org.opensaml.messaging.context.MessageContext; +import org.opensaml.messaging.handler.MessageHandlerException; +import org.opensaml.saml.common.binding.security.impl.SAMLProtocolMessageXMLSignatureSecurityHandler; +import org.opensaml.saml.common.messaging.context.SAMLPeerEntityContext; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class EaafSamlProtocolMessageXmlSignatureSecurityHandler extends + SAMLProtocolMessageXMLSignatureSecurityHandler { + + private IRefreshableMetadataProvider refreshableMetadataProvider = null; + + /** + * Signature verification handler that reloads SAML2 metadata if signature + * verification fails. + * + * @param metadataProvider Metadata provider implementation. Refreshing is only + * possible, if that provider implements + * {@link IRefreshableMetadataProvider} + */ + public EaafSamlProtocolMessageXmlSignatureSecurityHandler( + @Nullable IPvp2MetadataProvider metadataProvider) { + if (metadataProvider != null) { + if (metadataProvider instanceof IRefreshableMetadataProvider) { + refreshableMetadataProvider = (IRefreshableMetadataProvider) metadataProvider; + + } else { + log.trace("Refreshing is not supported by {} metadata-provider", + metadataProvider.getClass().getSimpleName()); + + } + } + } + + @Override + public void doInvoke(@Nonnull final MessageContext messageContext) throws MessageHandlerException { + try { + super.doInvoke(messageContext); + + } catch (final MessageHandlerException e) { + if (refreshableMetadataProvider != null) { + + log.debug("Starting metadata refresh process ... "); + if (refreshableMetadataProvider.refreshMetadataProvider( + messageContext.getSubcontext(SAMLPeerEntityContext.class).getEntityId())) { + log.trace("Refreshing successful. Restarting message evaluation ... "); + + try { + super.doInvoke(messageContext); + return; + + } catch (final MessageHandlerException e1) { + log.debug("Signature validation fails twice with second error: {}", e.getMessage()); + + } + } + } + + log.info("Signature validation of SAML message failed. Reason: {}", e.getMessage()); + throw new MessageHandlerException( + new SamlSigningException("internal.pvp.10", new Object[] { e.getMessage() }, e)); + } + + } +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PVPAuthRequestSignedRole.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PVPAuthRequestSignedRole.java deleted file mode 100644 index 6d5fdff8..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PVPAuthRequestSignedRole.java +++ /dev/null @@ -1,66 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.impl.verification; - -import java.util.List; - -import org.opensaml.common.binding.SAMLMessageContext; -import org.opensaml.saml2.binding.security.SAML2AuthnRequestsSignedRule; -import org.opensaml.ws.transport.http.HTTPInTransport; -import org.opensaml.xml.util.DatatypeHelper; - -/** - * @author tlenz - * - */ -public class PVPAuthRequestSignedRole extends SAML2AuthnRequestsSignedRule { - - @Override - protected boolean isMessageSigned(SAMLMessageContext messageContext) { - // This handles HTTP-Redirect and HTTP-POST-SimpleSign bindings. - HTTPInTransport inTransport = (HTTPInTransport) messageContext.getInboundMessageTransport(); - - //Check signature parameter exists only once and is not empty - List<String> sigParam = inTransport.getParameterValues("Signature"); - boolean isValidSigned = sigParam.size() == 1 && !DatatypeHelper.isEmpty(sigParam.get(0)); - - //Check signature-algorithm parameter exists only once and is not empty - List<String> sigAlgParam = inTransport.getParameterValues("SigAlg"); - boolean isValidSigAlgExists = sigAlgParam.size() == 1 && !DatatypeHelper.isEmpty(sigAlgParam.get(0)); - - //Check signature-content parameter exists only once and is not empty - List<String> samlReqParam = inTransport.getParameterValues("SAMLRequest"); - List<String> samlRespParam = inTransport.getParameterValues("SAMLResponse"); - boolean isValidContent = ( ( samlReqParam.size() == 1 && !DatatypeHelper.isEmpty(samlReqParam.get(0)) ) - || ( samlRespParam.size() == 1 && !DatatypeHelper.isEmpty(samlRespParam.get(0)) ) - ) && !(samlReqParam.size() == 1 && samlRespParam.size() == 1) - ; - - return isValidSigned && isValidSigAlgExists && isValidContent; - - } -} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PVPSignedRequestPolicyRule.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PVPSignedRequestPolicyRule.java deleted file mode 100644 index eecaf4f0..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PVPSignedRequestPolicyRule.java +++ /dev/null @@ -1,84 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.impl.verification; - -import javax.xml.namespace.QName; - -import org.opensaml.common.SignableSAMLObject; -import org.opensaml.saml2.metadata.provider.MetadataProvider; -import org.opensaml.xml.XMLObject; -import org.opensaml.xml.signature.SignatureTrustEngine; - -import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IRefreshableMetadataProvider; - -/** - * @author tlenz - * - */ -public class PVPSignedRequestPolicyRule extends - AbstractRequestSignedSecurityPolicyRule { - - private IRefreshableMetadataProvider metadataProvider = null; - - /** - * @param metadataProvider - * @param trustEngine - * @param peerEntityRole - */ - public PVPSignedRequestPolicyRule(MetadataProvider metadataProvider, SignatureTrustEngine trustEngine, - QName peerEntityRole) { - super(trustEngine, peerEntityRole); - if (metadataProvider instanceof IRefreshableMetadataProvider) - this.metadataProvider = (IRefreshableMetadataProvider) metadataProvider; - - } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.protocols.pvp2x.validation.AbstractRequestSignedSecurityPolicyRule#refreshMetadataProvider(java.lang.String) - */ - @Override - protected boolean refreshMetadataProvider(String entityID) { - if (metadataProvider != null) - return metadataProvider.refreshMetadataProvider(entityID); - - return false; - - } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.protocols.pvp2x.validation.AbstractRequestSignedSecurityPolicyRule#getSignedSAMLObject(org.opensaml.xml.XMLObject) - */ - @Override - protected SignableSAMLObject getSignedSAMLObject(XMLObject inboundData) { - if (inboundData instanceof SignableSAMLObject) - return (SignableSAMLObject) inboundData; - - else - return null; - } - -} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PvpSamlMessageHandlerChain.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PvpSamlMessageHandlerChain.java new file mode 100644 index 00000000..a1365023 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PvpSamlMessageHandlerChain.java @@ -0,0 +1,71 @@ +package at.gv.egiz.eaaf.modules.pvp2.impl.verification; + +import java.util.ArrayList; +import java.util.List; + +import org.opensaml.messaging.context.MessageContext; +import org.opensaml.messaging.handler.MessageHandler; +import org.opensaml.messaging.handler.MessageHandlerChain; +import org.opensaml.messaging.handler.MessageHandlerException; +import org.opensaml.saml.common.SAMLObject; + +import lombok.extern.slf4j.Slf4j; +import net.shibboleth.utilities.java.support.component.ComponentInitializationException; + +@Slf4j +public class PvpSamlMessageHandlerChain implements MessageHandlerChain<SAMLObject> { + private final List<MessageHandler<SAMLObject>> handlers = new ArrayList<>(); + private boolean isInitialized = false; + + @Override + public void invoke(MessageContext<SAMLObject> messageContext) throws MessageHandlerException { + if (!isInitialized) { + throw new RuntimeException("Component: " + + PvpSamlMessageHandlerChain.class.getName() + " not initialized"); + + } + + for (final MessageHandler<SAMLObject> handler : getHandlers()) { + log.trace("Initializing SAML message handler: {}", handler.getClass().getName()); + handler.invoke(messageContext); + + } + } + + @Override + public boolean isInitialized() { + return isInitialized; + + } + + @Override + public void initialize() throws ComponentInitializationException { + if (!isInitialized) { + for (final MessageHandler<SAMLObject> handler : getHandlers()) { + log.trace("Initializing SAML message handler: {}", handler.getClass().getName()); + handler.initialize(); + + } + + isInitialized = true; + } + + } + + @Override + public List<MessageHandler<SAMLObject>> getHandlers() { + return handlers; + + } + + public void addHandler(MessageHandler<SAMLObject> handler) { + handlers.add(handler); + + } + + public void addHandlers(List<MessageHandler<SAMLObject>> handlerList) { + handlers.addAll(handlerList); + + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/SAMLVerificationEngine.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/SAMLVerificationEngine.java deleted file mode 100644 index 078e4ac0..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/SAMLVerificationEngine.java +++ /dev/null @@ -1,207 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.impl.verification; - -import javax.xml.namespace.QName; -import javax.xml.transform.dom.DOMSource; -import javax.xml.validation.Schema; -import javax.xml.validation.Validator; - -import org.apache.commons.lang3.StringUtils; -import org.opensaml.common.xml.SAMLConstants; -import org.opensaml.common.xml.SAMLSchemaBuilder; -import org.opensaml.saml2.core.RequestAbstractType; -import org.opensaml.saml2.core.StatusResponseType; -import org.opensaml.saml2.metadata.IDPSSODescriptor; -import org.opensaml.saml2.metadata.SPSSODescriptor; -import org.opensaml.security.MetadataCriteria; -import org.opensaml.security.SAMLSignatureProfileValidator; -import org.opensaml.xml.security.CriteriaSet; -import org.opensaml.xml.security.credential.UsageType; -import org.opensaml.xml.security.criteria.EntityIDCriteria; -import org.opensaml.xml.security.criteria.UsageCriteria; -import org.opensaml.xml.signature.SignatureTrustEngine; -import org.opensaml.xml.validation.ValidationException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.w3c.dom.Element; -import org.xml.sax.SAXException; - -import at.gv.egiz.eaaf.core.exceptions.InvalidProtocolRequestException; -import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPVPMetadataProvider; -import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IRefreshableMetadataProvider; -import at.gv.egiz.eaaf.modules.pvp2.exception.SchemaValidationException; -import at.gv.egiz.eaaf.modules.pvp2.impl.message.InboundMessage; -import at.gv.egiz.eaaf.modules.pvp2.impl.message.PVPSProfileRequest; -import at.gv.egiz.eaaf.modules.pvp2.impl.message.PVPSProfileResponse; - -@Service("SAMLVerificationEngine") -public class SAMLVerificationEngine { - private static final Logger log = LoggerFactory.getLogger(SAMLVerificationEngine.class); - - - @Autowired(required=true) IPVPMetadataProvider metadataProvider; - - public void verify(InboundMessage msg, SignatureTrustEngine sigTrustEngine ) throws org.opensaml.xml.security.SecurityException, Exception { - try { - if (msg instanceof PVPSProfileRequest && - ((PVPSProfileRequest)msg).getSamlRequest() instanceof RequestAbstractType) - verifyRequest(((RequestAbstractType)((PVPSProfileRequest)msg).getSamlRequest()), sigTrustEngine); - - else - verifyIDPResponse(((PVPSProfileResponse)msg).getResponse(), sigTrustEngine); - - } catch (InvalidProtocolRequestException e) { - if (StringUtils.isEmpty(msg.getEntityID())) { - throw e; - - } - log.debug("PVP2X message validation FAILED. Relead metadata for entityID: " + msg.getEntityID()); - - if (metadataProvider == null || - !(metadataProvider instanceof IRefreshableMetadataProvider) || - !((IRefreshableMetadataProvider)metadataProvider).refreshMetadataProvider(msg.getEntityID())) - throw e; - - else { - log.trace("PVP2X metadata reload finished. Check validate message again."); - - if (msg instanceof PVPSProfileRequest && - ((PVPSProfileRequest)msg).getSamlRequest() instanceof RequestAbstractType) - verifyRequest(((RequestAbstractType)((PVPSProfileRequest)msg).getSamlRequest()), sigTrustEngine); - - else - verifyIDPResponse(((PVPSProfileResponse)msg).getResponse(), sigTrustEngine); - - } - log.trace("Second PVP2X message validation finished"); - } - } - - public void verifySLOResponse(StatusResponseType samlObj, SignatureTrustEngine sigTrustEngine ) throws InvalidProtocolRequestException { - verifyResponse(samlObj, sigTrustEngine, SPSSODescriptor.DEFAULT_ELEMENT_NAME); - - } - - public void verifyIDPResponse(StatusResponseType samlObj, SignatureTrustEngine sigTrustEngine) throws InvalidProtocolRequestException{ - verifyResponse(samlObj, sigTrustEngine, IDPSSODescriptor.DEFAULT_ELEMENT_NAME); - - } - - private void verifyResponse(StatusResponseType samlObj, SignatureTrustEngine sigTrustEngine, QName defaultElementName) throws InvalidProtocolRequestException{ - SAMLSignatureProfileValidator profileValidator = new SAMLSignatureProfileValidator(); - try { - profileValidator.validate(samlObj.getSignature()); - performSchemaValidation(samlObj.getDOM()); - - } catch (ValidationException e) { - log.warn("Signature is not conform to SAML signature profile", e); - throw new InvalidProtocolRequestException("pvp2.21", new Object[] {}); - - } catch (SchemaValidationException e) { - throw new InvalidProtocolRequestException("pvp2.22", new Object[] {e.getMessage()}); - - } - - CriteriaSet criteriaSet = new CriteriaSet(); - criteriaSet.add( new EntityIDCriteria(samlObj.getIssuer().getValue()) ); - criteriaSet.add( new MetadataCriteria(defaultElementName, SAMLConstants.SAML20P_NS) ); - criteriaSet.add( new UsageCriteria(UsageType.SIGNING) ); - - try { - if (!sigTrustEngine.validate(samlObj.getSignature(), criteriaSet)) { - throw new InvalidProtocolRequestException("pvp2.21", new Object[] {}); - } - } catch (org.opensaml.xml.security.SecurityException e) { - log.warn("PVP2x message signature validation FAILED.", e); - throw new InvalidProtocolRequestException("pvp2.21", new Object[] {}); - } - } - - private void verifyRequest(RequestAbstractType samlObj, SignatureTrustEngine sigTrustEngine ) throws InvalidProtocolRequestException { - SAMLSignatureProfileValidator profileValidator = new SAMLSignatureProfileValidator(); - try { - profileValidator.validate(samlObj.getSignature()); - performSchemaValidation(samlObj.getDOM()); - - } catch (ValidationException e) { - log.warn("Signature is not conform to SAML signature profile", e); - throw new InvalidProtocolRequestException("pvp2.21", new Object[] {}); - - } catch (SchemaValidationException e) { - throw new InvalidProtocolRequestException("pvp2.22", new Object[] {e.getMessage()}); - - } - - CriteriaSet criteriaSet = new CriteriaSet(); - criteriaSet.add( new EntityIDCriteria(samlObj.getIssuer().getValue()) ); - criteriaSet.add( new MetadataCriteria(SPSSODescriptor.DEFAULT_ELEMENT_NAME, SAMLConstants.SAML20P_NS) ); - criteriaSet.add( new UsageCriteria(UsageType.SIGNING) ); - - try { - if (!sigTrustEngine.validate(samlObj.getSignature(), criteriaSet)) { - throw new InvalidProtocolRequestException("pvp2.21", new Object[] {}); - } - } catch (org.opensaml.xml.security.SecurityException e) { - log.warn("PVP2x message signature validation FAILED.", e); - throw new InvalidProtocolRequestException("pvp2.21", new Object[] {}); - } - } - - protected void performSchemaValidation(Element source) throws SchemaValidationException { - - String err = null; - try { - Schema test = SAMLSchemaBuilder.getSAML11Schema(); - Validator val = test.newValidator(); - val.validate(new DOMSource(source)); - log.debug("Schema validation check done OK"); - return; - - } catch (SAXException e) { - err = e.getMessage(); - if (log.isDebugEnabled() || log.isTraceEnabled()) - log.warn("Schema validation FAILED with exception:", e); - else - log.warn("Schema validation FAILED with message: "+ e.getMessage()); - - } catch (Exception e) { - err = e.getMessage(); - if (log.isDebugEnabled() || log.isTraceEnabled()) - log.warn("Schema validation FAILED with exception:", e); - else - log.warn("Schema validation FAILED with message: "+ e.getMessage()); - - } - - throw new SchemaValidationException("pvp2.22", new Object[]{err}); - - } - -} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/SamlVerificationEngine.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/SamlVerificationEngine.java new file mode 100644 index 00000000..e0a3ab8e --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/SamlVerificationEngine.java @@ -0,0 +1,516 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.impl.verification; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.namespace.QName; +import javax.xml.transform.dom.DOMSource; +import javax.xml.validation.Schema; +import javax.xml.validation.Validator; + +import at.gv.egiz.eaaf.core.exceptions.EaafProtocolException; +import at.gv.egiz.eaaf.core.exceptions.InvalidProtocolRequestException; +import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IRefreshableMetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlAssertionValidationExeption; +import at.gv.egiz.eaaf.modules.pvp2.exception.SchemaValidationException; +import at.gv.egiz.eaaf.modules.pvp2.impl.message.InboundMessage; +import at.gv.egiz.eaaf.modules.pvp2.impl.message.PvpSProfileRequest; +import at.gv.egiz.eaaf.modules.pvp2.impl.message.PvpSProfileResponse; + +import org.apache.commons.lang3.StringUtils; +import org.joda.time.DateTime; +import org.opensaml.core.criterion.EntityIdCriterion; +import org.opensaml.saml.common.xml.SAMLConstants; +import org.opensaml.saml.common.xml.SAMLSchemaBuilder; +import org.opensaml.saml.common.xml.SAMLSchemaBuilder.SAML1Version; +import org.opensaml.saml.criterion.EntityRoleCriterion; +import org.opensaml.saml.criterion.ProtocolCriterion; +import org.opensaml.saml.saml2.core.Assertion; +import org.opensaml.saml.saml2.core.Audience; +import org.opensaml.saml.saml2.core.AudienceRestriction; +import org.opensaml.saml.saml2.core.Conditions; +import org.opensaml.saml.saml2.core.EncryptedAssertion; +import org.opensaml.saml.saml2.core.RequestAbstractType; +import org.opensaml.saml.saml2.core.Response; +import org.opensaml.saml.saml2.core.StatusCode; +import org.opensaml.saml.saml2.core.StatusResponseType; +import org.opensaml.saml.saml2.encryption.Decrypter; +import org.opensaml.saml.saml2.encryption.EncryptedElementTypeEncryptedKeyResolver; +import org.opensaml.saml.saml2.metadata.IDPSSODescriptor; +import org.opensaml.saml.saml2.metadata.SPSSODescriptor; +import org.opensaml.saml.security.impl.SAMLSignatureProfileValidator; +import org.opensaml.security.credential.UsageType; +import org.opensaml.security.criteria.UsageCriterion; +import org.opensaml.xmlsec.encryption.support.ChainingEncryptedKeyResolver; +import org.opensaml.xmlsec.encryption.support.DecryptionException; +import org.opensaml.xmlsec.encryption.support.EncryptedKeyResolver; +import org.opensaml.xmlsec.encryption.support.InlineEncryptedKeyResolver; +import org.opensaml.xmlsec.encryption.support.SimpleRetrievalMethodEncryptedKeyResolver; +import org.opensaml.xmlsec.keyinfo.impl.StaticKeyInfoCredentialResolver; +import org.opensaml.xmlsec.signature.support.SignatureException; +import org.opensaml.xmlsec.signature.support.SignatureTrustEngine; +import org.springframework.beans.factory.annotation.Autowired; +import org.w3c.dom.Element; +import org.xml.sax.SAXException; + +import lombok.extern.slf4j.Slf4j; +import net.shibboleth.utilities.java.support.net.BasicURLComparator; +import net.shibboleth.utilities.java.support.net.URIException; +import net.shibboleth.utilities.java.support.resolver.CriteriaSet; + +@Slf4j +public class SamlVerificationEngine { + private static SAMLSchemaBuilder schemaBuilder = new SAMLSchemaBuilder(SAML1Version.SAML_11); + + private static final String ERROR_03 = "internal.pvp.03"; + private static final String ERROR_10 = "internal.pvp.10"; + private static final String ERROR_14 = "internal.pvp.14"; + private static final String ERROR_15 = "internal.pvp.15"; + private static final String ERROR_16 = "internal.pvp.16"; + private static final String ERROR_17 = "internal.pvp.17"; + + private static final Object SIG_VAL_ERROR_MSG = "Signature verification return false"; + + /** + * 5 allow 3 minutes time jitter in before validation. + */ + private static final int TIME_JITTER = 3; + + + + + + @Autowired(required = true) + IPvp2MetadataProvider metadataProvider; + + /** + * Verify signature of a signed SAML2 object. + * + *<p>This method only perform signature verification</p> + * + * @param msg SAML2 message + * @param sigTrustEngine TrustEngine + * @throws org.opensaml.xml.security.SecurityException In case of invalid + * signature + * @throws Exception In case of a general + * error + */ + public void verify(final InboundMessage msg, final SignatureTrustEngine sigTrustEngine) + throws SecurityException, Exception { + try { + if (msg instanceof PvpSProfileRequest + && ((PvpSProfileRequest) msg).getSamlRequest() instanceof RequestAbstractType) { + verifyRequest((RequestAbstractType) ((PvpSProfileRequest) msg).getSamlRequest(), + sigTrustEngine); + } else if (msg instanceof PvpSProfileResponse) { + verifyIdpResponse(((PvpSProfileResponse) msg).getResponse(), sigTrustEngine); + + } else { + log.warn("SAML2 message type: {} not supported", msg.getClass().getName()); + throw new EaafProtocolException("internal.pvp.99", null); + + } + + } catch (final InvalidProtocolRequestException e) { + if (StringUtils.isEmpty(msg.getEntityID())) { + throw e; + + } + log.debug("PVP2X message validation FAILED. Relead metadata for entityID: {}", + msg.getEntityID()); + + if (metadataProvider == null || !(metadataProvider instanceof IRefreshableMetadataProvider) + || !((IRefreshableMetadataProvider) metadataProvider) + .refreshMetadataProvider(msg.getEntityID())) { + throw e; + + } else { + log.trace("PVP2X metadata reload finished. Check validate message again."); + + if (msg instanceof PvpSProfileRequest + && ((PvpSProfileRequest) msg).getSamlRequest() instanceof RequestAbstractType) { + verifyRequest((RequestAbstractType) ((PvpSProfileRequest) msg).getSamlRequest(), + sigTrustEngine); + + } else { + verifyIdpResponse(((PvpSProfileResponse) msg).getResponse(), sigTrustEngine); + + } + + } + log.trace("Second PVP2X message validation finished"); + + } + } + + /** + * Verify the signature of a signed SAML2 object from ServiceProvider. + * + * @param samlObj signed Response from ServiceProvider + * @param sigTrustEngine TrustEngie for verification + * @throws InvalidProtocolRequestException In case of a verification error + */ + public void verifySloResponse(final StatusResponseType samlObj, + final SignatureTrustEngine sigTrustEngine) throws InvalidProtocolRequestException { + verifyResponse(samlObj, sigTrustEngine, SPSSODescriptor.DEFAULT_ELEMENT_NAME); + + } + + /** + * Verify the signature of a signed SAML2 object from IDP. + * + * <p>This method only perform signature verification</p> + * + * @param samlObj signed SAML2 message from IDP + * @param sigTrustEngine TrustEngie for verification + * @throws InvalidProtocolRequestException In case of a verification error + */ + public void verifyIdpResponse(final StatusResponseType samlObj, + final SignatureTrustEngine sigTrustEngine) throws InvalidProtocolRequestException { + verifyResponse(samlObj, sigTrustEngine, IDPSSODescriptor.DEFAULT_ELEMENT_NAME); + + } + + /** + * Validate a PVP response and all included assertions. + * + *<p> + * If the SAML2 assertions are encrypted than they will be decrypted afterwards + * </p> + * + *<p>This method <b>DOES NOT</b> verify the <i>Destination</i> attribute in SAML2 Response</p> + * + * @param samlResp SAML2 Response object + * @param assertionDecryption Assertion decryption-credentials to decrypt SAML2 + * assertions + * @param spEntityID EntityId of the SAML2 client + * @param loggerName Name for logging purposes + * @throws SamlAssertionValidationExeption In case of a validation error + */ + public void validateAssertion(Response samlResp, + EaafX509Credential assertionDecryption, String spEntityID, String loggerName) + throws SamlAssertionValidationExeption { + validateAssertion(samlResp, assertionDecryption, spEntityID, loggerName, true); + + } + + /** + * Validate each SAML2 assertions in a SAML2 response. <br> + * <p> + * If the SAML2 assertions are encrypted than they will be decrypted afterwards + * </p> + * + *<p>This method <b>DOES NOT</b> verify the <i>Destination</i> attribute in SAML2 Response</p> + * + * @param samlResp SAML2 Response object + * @param assertionDecryption Assertion decryption-credentials to decrypt SAML2 + * assertions + * @param spEntityID EntityId of the SAML2 client + * @param loggerName Name for logging purposes + * @param validateDateTime <code>true</code> if <i>getIssueInstant</i> + * attribute should be validated, otherwise false + * @throws SamlAssertionValidationExeption In case of a validation error + */ + public void validateAssertion(Response samlResp, EaafX509Credential assertionDecryption, + String spEntityID, String loggerName, boolean validateDateTime) + throws SamlAssertionValidationExeption { + try { + // pre-validate the SAML2 response + assertionPreValidation(samlResp, loggerName, validateDateTime); + + // get Assertion from response and decrypt them if the are encrypted + final List<Assertion> saml2assertions = getOrDecryptAndGetAssertions(samlResp, assertionDecryption); + + // validate each assertion + final List<Assertion> validatedassertions = new ArrayList<>(); + for (final Assertion saml2assertion : saml2assertions) { + if (internalAssertionValidation(saml2assertion, spEntityID, validateDateTime)) { + log.debug("Add valid Assertion:" + saml2assertion.getID()); + validatedassertions.add(saml2assertion); + + } else { + log.warn("Remove non-valid Assertion:" + saml2assertion.getID()); + } + + } + + if (validatedassertions.isEmpty()) { + log.info("No valid PVP 2.1 assertion received."); + throw new SamlAssertionValidationExeption(ERROR_15, new Object[] { loggerName }); + + } + + samlResp.getAssertions().clear(); + samlResp.getEncryptedAssertions().clear(); + samlResp.getAssertions().addAll(validatedassertions); + + } catch (final DecryptionException e) { + log.warn("Assertion decrypt FAILED.", e); + throw new SamlAssertionValidationExeption(ERROR_16, + new Object[] { e.getMessage() }, e); + +// } catch (final ConfigurationException e) { +// throw new AssertionValidationExeption("pvp.12", +// new Object[]{loggerName, e.getMessage()}, e); + } + } + + private boolean internalAssertionValidation(Assertion saml2assertion, String spEntityId, + boolean validateDateTime) { + boolean isAssertionValid = true; + try { + // schema validation + performSchemaValidation(saml2assertion.getDOM()); + + // validate DateTime conditions + final Conditions conditions = saml2assertion.getConditions(); + if (conditions != null) { + final DateTime notbefore = conditions.getNotBefore().minusMinutes(5); + final DateTime notafter = conditions.getNotOnOrAfter(); + if (validateDateTime + && (notbefore.isAfterNow() || notafter.isBeforeNow())) { + isAssertionValid = false; + log.info("Assertion with ID:{} is out of Date. [ Current:{} NotBefore:{} NotAfter:{} ]", + saml2assertion.getID(), new DateTime(), notbefore, notafter); + + } + + // validate audienceRestrictions are valid for this SP + final List<AudienceRestriction> audienceRest = conditions.getAudienceRestrictions(); + if (audienceRest == null || audienceRest.size() == 0) { + log.info("Assertion with ID:{} has not 'AudienceRestriction' element", + saml2assertion.getID()); + isAssertionValid = false; + + } else { + for (final AudienceRestriction el : audienceRest) { + for (final Audience audience : el.getAudiences()) { + if (!urlCompare(spEntityId, audience.getAudienceURI())) { + log.info("Assertion with ID:{} 'AudienceRestriction' is not valid.", + saml2assertion.getID()); + isAssertionValid = false; + + } + } + } + } + + } else { + log.info("Assertion with ID:{} contains not 'Conditions' element", + saml2assertion.getID()); + isAssertionValid = false; + + } + + } catch (final SchemaValidationException e) { + isAssertionValid = false; + log.info("Assertion with ID:{} FAILED Schema validation. Msg: {}", + saml2assertion.getID(), e.getMessage()); + + } catch (final URIException e) { + isAssertionValid = false; + log.info("Assertion with ID:{} FAILED AudienceRestriction validation. Msg:", + saml2assertion.getID(), e.getMessage()); + + } + + return isAssertionValid; + + } + + private List<Assertion> getOrDecryptAndGetAssertions(Response samlResp, + EaafX509Credential assertionDecryption) throws DecryptionException { + final List<Assertion> saml2assertions = new ArrayList<>(); + + // check encrypted Assertions + final List<EncryptedAssertion> encryAssertionList = samlResp.getEncryptedAssertions(); + if (encryAssertionList != null && encryAssertionList.size() > 0) { + // decrypt assertions + log.debug("Found encryped assertion. Start decryption ..."); + final List<EncryptedKeyResolver> listOfKeyResolvers = new ArrayList<>(); + listOfKeyResolvers.add(new InlineEncryptedKeyResolver()); + listOfKeyResolvers.add(new EncryptedElementTypeEncryptedKeyResolver()); + listOfKeyResolvers.add(new SimpleRetrievalMethodEncryptedKeyResolver()); + + final Decrypter samlDecrypter = new Decrypter(null, + new StaticKeyInfoCredentialResolver(assertionDecryption), + new ChainingEncryptedKeyResolver(listOfKeyResolvers)); + + for (final EncryptedAssertion encAssertion : encryAssertionList) { + saml2assertions.add(samlDecrypter.decrypt(encAssertion)); + + } + log.debug("Assertion decryption finished. "); + + } + + saml2assertions.addAll(samlResp.getAssertions()); + + return saml2assertions; + + } + + private void performSchemaValidation(final Element source) throws SchemaValidationException { + + String err = null; + try { + final Schema test = schemaBuilder.getSAMLSchema(); + final Validator val = test.newValidator(); + val.validate(new DOMSource(source)); + log.debug("Schema validation check done OK"); + return; + + } catch (final SAXException e) { + err = e.getMessage(); + if (log.isDebugEnabled() || log.isTraceEnabled()) { + log.warn("Schema validation FAILED with exception:", e); + } else { + log.warn("Schema validation FAILED with message: " + e.getMessage()); + } + + } catch (final Exception e) { + err = e.getMessage(); + if (log.isDebugEnabled() || log.isTraceEnabled()) { + log.warn("Schema validation FAILED with exception:", e); + } else { + log.warn("Schema validation FAILED with message: " + e.getMessage()); + } + + } + + throw new SchemaValidationException(ERROR_03, new Object[] { err }); + + } + + private void verifyResponse(final StatusResponseType samlObj, + final SignatureTrustEngine sigTrustEngine, final QName defaultElementName) + throws InvalidProtocolRequestException { + + final SAMLSignatureProfileValidator profileValidator = new SAMLSignatureProfileValidator(); + try { + profileValidator.validate(samlObj.getSignature()); + performSchemaValidation(samlObj.getDOM()); + + } catch (final SignatureException e) { + log.warn("Signature is not conform to SAML signature profile", e); + throw new InvalidProtocolRequestException(ERROR_10, new Object[] {e.getMessage() }, e); + + } catch (final SchemaValidationException e) { + throw new InvalidProtocolRequestException(ERROR_03, new Object[] { e.getMessage() }, e); + + } + + final CriteriaSet criteriaSet = new CriteriaSet(); + criteriaSet.add(new EntityIdCriterion(samlObj.getIssuer().getValue())); + criteriaSet.add(new ProtocolCriterion(SAMLConstants.SAML20P_NS)); + criteriaSet.add(new EntityRoleCriterion(defaultElementName)); + criteriaSet.add(new UsageCriterion(UsageType.SIGNING)); + + try { + if (!sigTrustEngine.validate(samlObj.getSignature(), criteriaSet)) { + throw new InvalidProtocolRequestException(ERROR_10, new Object[] {SIG_VAL_ERROR_MSG}); + + } + + } catch (final org.opensaml.security.SecurityException e) { + log.warn("PVP2x message signature validation FAILED.", e); + throw new InvalidProtocolRequestException(ERROR_10, new Object[] {e.getMessage()}, e); + + } + } + + private void verifyRequest(final RequestAbstractType samlObj, + final SignatureTrustEngine sigTrustEngine) throws InvalidProtocolRequestException { + final SAMLSignatureProfileValidator profileValidator = new SAMLSignatureProfileValidator(); + try { + profileValidator.validate(samlObj.getSignature()); + performSchemaValidation(samlObj.getDOM()); + + } catch (final SignatureException e) { + log.warn("Signature is not conform to SAML signature profile", e); + throw new InvalidProtocolRequestException(ERROR_10, new Object[] {e.getMessage()}, e); + + } catch (final SchemaValidationException e) { + throw new InvalidProtocolRequestException(ERROR_03, new Object[] { e.getMessage() }, e); + + } + + final CriteriaSet criteriaSet = new CriteriaSet(); + criteriaSet.add(new EntityIdCriterion(samlObj.getIssuer().getValue())); + criteriaSet.add(new ProtocolCriterion(SAMLConstants.SAML20P_NS)); + criteriaSet.add(new EntityRoleCriterion(SPSSODescriptor.DEFAULT_ELEMENT_NAME)); + criteriaSet.add(new UsageCriterion(UsageType.SIGNING)); + + try { + if (!sigTrustEngine.validate(samlObj.getSignature(), criteriaSet)) { + throw new InvalidProtocolRequestException(ERROR_10, new Object[] {SIG_VAL_ERROR_MSG}); + + } + } catch (final org.opensaml.security.SecurityException e) { + log.warn("PVP2x message signature validation FAILED.", e); + throw new InvalidProtocolRequestException(ERROR_10, new Object[] {e.getMessage()}, e); + + } + + } + + private void assertionPreValidation(Response samlResp, String loggerName, boolean validateDateTime) + throws SamlAssertionValidationExeption { + if (samlResp.getStatus().getStatusCode().getValue().equals(StatusCode.SUCCESS)) { + // validate response issueInstant + final DateTime issueInstant = samlResp.getIssueInstant(); + if (issueInstant == null) { + log.warn("PVP response does not include a 'IssueInstant' attribute"); + throw new SamlAssertionValidationExeption(ERROR_14, + new Object[] { loggerName, "'IssueInstant' attribute is not included" }); + + } + if (validateDateTime && issueInstant.minusMinutes(TIME_JITTER).isAfterNow()) { + log.warn("PVP response: IssueInstant DateTime is not valid anymore."); + throw new SamlAssertionValidationExeption(ERROR_14, + new Object[] { loggerName, "'IssueInstant' Time is not valid any more" }); + + } + + } else { + log.info("PVP 2.x assertion includes an error. Receive errorcode " + + samlResp.getStatus().getStatusCode().getValue()); + throw new SamlAssertionValidationExeption(ERROR_17, + new Object[] { loggerName, + samlResp.getIssuer().getValue(), + samlResp.getStatus().getStatusCode().getValue(), + samlResp.getStatus().getStatusMessage() != null + ? samlResp.getStatus().getStatusMessage().getMessage() + : " no status message" }); + + } + } + + private static boolean urlCompare(String url1, String url2) throws URIException { + final BasicURLComparator comparator = new BasicURLComparator(); + comparator.setCaseInsensitive(false); + return comparator.compare(url1, url2); + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider b/eaaf_modules/eaaf_module_pvp2_core/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider index 9c60d724..8bc7508c 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider @@ -1 +1 @@ -at.gv.egiz.eaaf.modules.pvp2.PVP2SProfileCoreSpringResourceProvider
\ No newline at end of file +at.gv.egiz.eaaf.modules.pvp2.Pvp2SProfileCoreSpringResourceProvider
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/resources/eaaf_pvp.beans.xml b/eaaf_modules/eaaf_module_pvp2_core/src/main/resources/eaaf_pvp.beans.xml index 2cbcce20..72cf9677 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/resources/eaaf_pvp.beans.xml +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/resources/eaaf_pvp.beans.xml @@ -1,30 +1,34 @@ <?xml version="1.0" encoding="UTF-8"?> -<!-- - --> - -<!-- - --> <beans xmlns="http://www.springframework.org/schema/beans" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xmlns:context="http://www.springframework.org/schema/context" - xmlns:tx="http://www.springframework.org/schema/tx" - xmlns:aop="http://www.springframework.org/schema/aop" - xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd - http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd - http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd - http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> - - <bean id="PVPMetadataBuilder" - class="at.gv.egiz.eaaf.modules.pvp2.impl.builder.PVPMetadataBuilder" /> - - <bean id="PVPPOSTBinding" - class="at.gv.egiz.eaaf.modules.pvp2.impl.binding.PostBinding" /> - - <bean id="PVPRedirectBinding" - class="at.gv.egiz.eaaf.modules.pvp2.impl.binding.RedirectBinding" /> - - <bean id="PVPSOAPBinding" - class="at.gv.egiz.eaaf.modules.pvp2.impl.binding.SoapBinding" /> - + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:context="http://www.springframework.org/schema/context" + xmlns:tx="http://www.springframework.org/schema/tx" + xmlns:aop="http://www.springframework.org/schema/aop" + xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd + http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> + + <bean id="pvpLogMessageSource" + class="at.gv.egiz.eaaf.modules.pvp2.impl.logging.PvpModuleMessageSource" /> + + <bean id="pvpMetadataResolverFactory" + class="at.gv.egiz.eaaf.modules.pvp2.impl.metadata.PvpMetadataResolverFactory"/> + + <bean id="PVPMetadataBuilder" + class="at.gv.egiz.eaaf.modules.pvp2.impl.builder.PvpMetadataBuilder" /> + + <bean id="PvpPostBinding" + class="at.gv.egiz.eaaf.modules.pvp2.impl.binding.PostBinding" /> + + <bean id="PvpRedirectBinding" + class="at.gv.egiz.eaaf.modules.pvp2.impl.binding.RedirectBinding" /> + + <bean id="PvpSoapBinding" + class="at.gv.egiz.eaaf.modules.pvp2.impl.binding.SoapBinding" /> + + <bean id="samlVerificationEngine" + class="at.gv.egiz.eaaf.modules.pvp2.impl.verification.SamlVerificationEngine" /> + </beans>
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/resources/messages/pvp_messages.properties b/eaaf_modules/eaaf_module_pvp2_core/src/main/resources/messages/pvp_messages.properties new file mode 100644 index 00000000..824f17d4 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/resources/messages/pvp_messages.properties @@ -0,0 +1,31 @@ +internal.pvp.00=KeyStore: {0} Key with alias: {0} not found or contains no PrivateKey. +internal.pvp.01=KeyStore: {0} contains an unsupported key with alias: {1} +internal.pvp.02=PVP message contains no signature. +internal.pvp.03=Schema-validation of SAML2 message failed with error: {0} +internal.pvp.04=Can not initialize metadata provider for metadata: {0} +internal.pvp.05=Can not initialize metadata provider for metadata: {0}. Reason: {1} +internal.pvp.06=SSL-Server certificate for metadata: {0} not trusted. Details: {1} +internal.pvp.07=Signature verification for metadata: {0} FAILED. Details: {1} +internal.pvp.08=Schema validation for metadata: {0} FAILED. Details: {1} +internal.pvp.09=Can not initialize metadata provider for metadata: {0}. Details: {1} +internal.pvp.10=Signature verification of SAML2 message FAILED. Reason: {0} +internal.pvp.11=General SAML2 message validation error. Reason: {0} +internal.pvp.12=SAML2 metadata: {0} is NOT signed +internal.pvp.13=SAML2 metadata generation failed. Reason: {0} +internal.pvp.14=SAML2 assertion validator: {0} found an error: Reason {1} +internal.pvp.15=SAML2 assertion validator: {0} find NO valid assertion in SAML2 response. +internal.pvp.16=Decryption of SAML2 assertion FAILED with reason: {0} +internal.pvp.17=SAML2 assertion validator:{0} find invalid PVP Response from Issuer:{1}. StatusCodes:{2} Msg:{3} + +pvp2.21=Signature validation of SAML2 Authn. request failed. Reason: {0} +pvp2.22=Validation of SAML2 Authn. request failed. Reason: {0} +pvp2.24=General error during SAML2 Auth. request pre-processing. Reason: {0} + +internal.pvp.95=OpenSAML {0}-binding message {1} failed. Reason: {2} +internal.pvp.96=OpenSAML signing FAILED with key: {0}. Reason: {1} +internal.pvp.97=Key with EntityIdentifier: {0} has an unsupported type: {1} +internal.pvp.98=PVP module has an internal error. Reason: {0} +internal.pvp.99=PVP module has an generic internal error. + + + diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/AbstractSamlVerificationEngine.java b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/AbstractSamlVerificationEngine.java new file mode 100644 index 00000000..d5186857 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/AbstractSamlVerificationEngine.java @@ -0,0 +1,328 @@ +package at.gv.egiz.eaaf.modules.pvp2.test; + +import java.util.ArrayList; +import java.util.List; + +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.core.exceptions.InvalidProtocolRequestException; +import at.gv.egiz.eaaf.core.impl.data.Pair; +import at.gv.egiz.eaaf.modules.pvp2.PvpConstants; +import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2InternalErrorException; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2MetadataException; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlSigningException; +import at.gv.egiz.eaaf.modules.pvp2.impl.message.PvpSProfileRequest; +import at.gv.egiz.eaaf.modules.pvp2.impl.message.PvpSProfileResponse; +import at.gv.egiz.eaaf.modules.pvp2.impl.metadata.PvpMetadataResolverFactory; +import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafOpenSaml3xInitializer; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils; +import at.gv.egiz.eaaf.modules.pvp2.impl.validation.TrustEngineFactory; +import at.gv.egiz.eaaf.modules.pvp2.impl.verification.SamlVerificationEngine; +import at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyCredentialProvider; +import at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyMetadataProvider; + +import org.joda.time.DateTime; +import org.junit.BeforeClass; +import org.junit.Test; +import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport; +import org.opensaml.core.xml.io.UnmarshallingException; +import org.opensaml.core.xml.util.XMLObjectSupport; +import org.opensaml.saml.common.xml.SAMLConstants; +import org.opensaml.saml.saml2.core.Assertion; +import org.opensaml.saml.saml2.core.AuthnRequest; +import org.opensaml.saml.saml2.core.EncryptedAssertion; +import org.opensaml.saml.saml2.core.Issuer; +import org.opensaml.saml.saml2.core.Response; +import org.opensaml.saml.saml2.encryption.Encrypter; +import org.opensaml.saml.saml2.encryption.Encrypter.KeyPlacement; +import org.opensaml.security.x509.X509Credential; +import org.opensaml.xmlsec.SecurityConfigurationSupport; +import org.opensaml.xmlsec.encryption.support.DataEncryptionParameters; +import org.opensaml.xmlsec.encryption.support.EncryptionException; +import org.opensaml.xmlsec.encryption.support.KeyEncryptionParameters; +import org.opensaml.xmlsec.keyinfo.KeyInfoGeneratorFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.Assert; + +import net.shibboleth.utilities.java.support.xml.XMLParserException; + + +public abstract class AbstractSamlVerificationEngine { + + @Autowired + private PvpMetadataResolverFactory metadataResolverFactory; + @Autowired + private SamlVerificationEngine verifyEngine; + @Autowired + protected DummyCredentialProvider credentialProvider; + + @Autowired DummyMetadataProvider metadataProvider; + @Autowired IConfiguration authConfig; + + /** + * JUnit class initializer. + * + * @throws Exception In case of an OpenSAML3 initialization error + */ + @BeforeClass + public static void classInitializer() throws Exception { + EaafOpenSaml3xInitializer.eaafInitialize(); + + } + protected abstract String getMetadataJunitJKeystore(); + + protected abstract String getMetadataClassPathEntityPath(); + + protected abstract String getAuthnRequestWithoutSigPath(); + + protected abstract String getResponseWithSigPath(); + + protected abstract String getResponseWithoutSigPath(); + + + @Test + public void validateSamlRequestSuccess() throws SecurityException, Exception { + + final String authnReqPath = getAuthnRequestWithoutSigPath(); + final String metadataPath = getMetadataClassPathEntityPath(); + final String spEntityId = metadataPath; + + final Pair<AuthnRequest, IPvp2MetadataProvider> inputMsg = + initializeAuthnRequest(spEntityId, metadataPath, authnReqPath, + credentialProvider.getMetaDataSigningCredential()); + + final PvpSProfileRequest msg = new PvpSProfileRequest( + inputMsg.getFirst(), + SAMLConstants.SAML2_POST_BINDING_URI); + msg.setEntityID(spEntityId); + + verifyEngine.verify(msg, + TrustEngineFactory.getSignatureKnownKeysTrustEngine(metadataProvider)); + + } + + @Test + public void validateSamlRequestWrongSignature() throws SecurityException, Exception { + + final String authnReqPath = getAuthnRequestWithoutSigPath(); + final String metadataPath = getMetadataJunitJKeystore(); + final String spEntityId = metadataPath; + + final Pair<AuthnRequest, IPvp2MetadataProvider> inputMsg = + initializeAuthnRequest(spEntityId, metadataPath, authnReqPath, + credentialProvider.getMetaDataSigningCredential()); + + metadataProvider.addMetadataResolverIntoChain(inputMsg.getSecond()); + + final PvpSProfileRequest msg = new PvpSProfileRequest( + inputMsg.getFirst(), + SAMLConstants.SAML2_POST_BINDING_URI); + msg.setEntityID(spEntityId); + + try { + verifyEngine.verify(msg, + TrustEngineFactory.getSignatureKnownKeysTrustEngine(metadataProvider)); + org.junit.Assert.fail("Wrong signature not detected"); + + } catch (final Exception e) { + Assert.isInstanceOf(InvalidProtocolRequestException.class, e, "Wrong exceptionType"); + org.junit.Assert.assertEquals("Wrong errorcode", "internal.pvp.10", ((EaafException) e).getErrorId()); + + } + } + + @Test + public void verifyResponseSuccessTest() throws Pvp2InternalErrorException, SecurityException, Exception { + metadataProvider.runGarbageCollector(); + + final String authnReqPath = getResponseWithoutSigPath(); + final String metadataPath = getMetadataClassPathEntityPath(); + final String spEntityId = metadataPath; + + final Pair<Response, IPvp2MetadataProvider> inputMsg = + initializeResponse(spEntityId, metadataPath, authnReqPath, + credentialProvider.getMetaDataSigningCredential()); + + final PvpSProfileResponse msg = new PvpSProfileResponse( + inputMsg.getFirst()); + msg.setEntityID(spEntityId); + + verifyEngine.verify(msg, + TrustEngineFactory.getSignatureKnownKeysTrustEngine(metadataProvider)); + + } + + @Test + public void verifyResponseSuccessSecondTest() + throws Pvp2InternalErrorException, SecurityException, Exception { + + final String authnReqPath = getResponseWithoutSigPath(); + final String metadataPath = getMetadataClassPathEntityPath(); + final String spEntityId = metadataPath; + + final Pair<Response, IPvp2MetadataProvider> inputMsg = + initializeResponse(spEntityId, metadataPath, authnReqPath, + credentialProvider.getMetaDataSigningCredential()); + + verifyEngine.verifyIdpResponse(inputMsg.getFirst(), + TrustEngineFactory.getSignatureKnownKeysTrustEngine(metadataProvider)); + + } + + @Test + public void verifySpResponse() + throws Pvp2InternalErrorException, SecurityException, Exception { + + final String authnReqPath = getResponseWithoutSigPath(); + final String metadataPath = getMetadataClassPathEntityPath(); + final String spEntityId = metadataPath; + + final Pair<Response, IPvp2MetadataProvider> inputMsg = + initializeResponse(spEntityId, metadataPath, authnReqPath, + credentialProvider.getMetaDataSigningCredential()); + + verifyEngine.verifySloResponse(inputMsg.getFirst(), + TrustEngineFactory.getSignatureKnownKeysTrustEngine(metadataProvider)); + + } + + @Test + public void verifyResponseWithoutId() throws Pvp2InternalErrorException, SecurityException, Exception { + + final String authnReqPath = getResponseWithSigPath(); + final String metadataPath = getMetadataClassPathEntityPath(); + final String spEntityId = metadataPath; + + final Pair<Response, IPvp2MetadataProvider> inputMsg = + initializeResponse(spEntityId, metadataPath, authnReqPath, + credentialProvider.getMetaDataSigningCredential()); + + final PvpSProfileResponse msg = new PvpSProfileResponse( + inputMsg.getFirst()); + msg.setEntityID(spEntityId); + + try { + verifyEngine.verify(msg, + TrustEngineFactory.getSignatureKnownKeysTrustEngine(metadataProvider)); + org.junit.Assert.fail("Wrong XML schema not detected"); + + } catch (final Exception e) { + Assert.isInstanceOf(InvalidProtocolRequestException.class, e, "Wrong exceptionType"); + org.junit.Assert.assertEquals("Wrong errorcode", "internal.pvp.03", ((EaafException) e).getErrorId()); + + } + } + + @Test + public void verifyResponseWrongTrust() throws Pvp2InternalErrorException, SecurityException, Exception { + + final String authnReqPath = getResponseWithoutSigPath(); + final String metadataPath = getMetadataJunitJKeystore(); + final String spEntityId = metadataPath; + + final Pair<Response, IPvp2MetadataProvider> inputMsg = + initializeResponse(spEntityId, metadataPath, authnReqPath, + credentialProvider.getMetaDataSigningCredential()); + + final PvpSProfileResponse msg = new PvpSProfileResponse( + inputMsg.getFirst()); + msg.setEntityID(spEntityId); + + try { + verifyEngine.verify(msg, + TrustEngineFactory.getSignatureKnownKeysTrustEngine(metadataProvider)); + org.junit.Assert.fail("No TrustedCert not detected"); + + } catch (final Exception e) { + Assert.isInstanceOf(InvalidProtocolRequestException.class, e, "Wrong exceptionType"); + org.junit.Assert.assertEquals("Wrong errorcode", "internal.pvp.10", ((EaafException) e).getErrorId()); + + } + } + + protected Pair<Response, IPvp2MetadataProvider> initializeResponse(String spEntityId, String metadataPath, + String authnReqPath, EaafX509Credential credential) + throws SamlSigningException, XMLParserException, UnmarshallingException, Pvp2MetadataException { + final IPvp2MetadataProvider mdResolver = metadataResolverFactory.createMetadataProvider( + metadataPath, null, "jUnit metadata resolver", null); + + final Response authnReq = (Response) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + AbstractSamlVerificationEngine.class.getResourceAsStream(authnReqPath)); + authnReq.setIssueInstant(DateTime.now()); + final Issuer issuer = Saml2Utils.createSamlObject(Issuer.class); + issuer.setValue(spEntityId); + authnReq.setIssuer(issuer); + + return Pair.newInstance( + Saml2Utils.signSamlObject(authnReq, credential, true), + mdResolver); + } + + protected Pair<AuthnRequest, IPvp2MetadataProvider> initializeAuthnRequest(String spEntityId, + String metadataPath, String authnReqPath, EaafX509Credential credential) + throws SamlSigningException, CredentialsNotAvailableException, + XMLParserException, UnmarshallingException, Pvp2InternalErrorException, Pvp2MetadataException { + + final IPvp2MetadataProvider mdResolver = metadataResolverFactory.createMetadataProvider( + metadataPath, null, "jUnit metadata resolver", null); + + final AuthnRequest authnReq = (AuthnRequest) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + AbstractSamlVerificationEngine.class.getResourceAsStream(authnReqPath)); + authnReq.setIssueInstant(DateTime.now()); + final Issuer issuer = Saml2Utils.createSamlObject(Issuer.class); + issuer.setValue(spEntityId); + authnReq.setIssuer(issuer); + + return Pair.newInstance( + Saml2Utils.signSamlObject(authnReq, credential, true), + mdResolver); + + } + + protected static EncryptedAssertion doEncryption(Assertion assertion, + X509Credential encryptionCredentials, IConfiguration authConfig) + throws Exception { + try { + final String keyEncAlg = Saml2Utils.getKeyOperationAlgorithmFromCredential( + encryptionCredentials, + authConfig.getBasicConfiguration( + PvpConstants.CONFIG_PROP_SEC_ENCRYPTION_KEY_RSA_ALG, + PvpConstants.DEFAULT_ASYM_ENCRYPTION_METHODE_RSA), + authConfig.getBasicConfiguration( + PvpConstants.CONFIG_PROP_SEC_ENCRYPTION_KEY_EC_ALG, + PvpConstants.DEFAULT_ASYM_ENCRYPTION_METHODE_EC)); + + final DataEncryptionParameters dataEncParams = new DataEncryptionParameters(); + dataEncParams.setAlgorithm(authConfig.getBasicConfiguration( + PvpConstants.CONFIG_PROP_SEC_ENCRYPTION_DATA, PvpConstants.DEFAULT_SYM_ENCRYPTION_METHODE)); + + final List<KeyEncryptionParameters> keyEncParamList = new ArrayList<>(); + final KeyEncryptionParameters keyEncParam = new KeyEncryptionParameters(); + keyEncParam.setEncryptionCredential(encryptionCredentials); + keyEncParam.setAlgorithm(keyEncAlg); + + final KeyInfoGeneratorFactory kigf = + SecurityConfigurationSupport.getGlobalEncryptionConfiguration() + .getKeyTransportKeyInfoGeneratorManager().getDefaultManager().getFactory(encryptionCredentials); + keyEncParam.setKeyInfoGenerator(kigf.newInstance()); + keyEncParamList.add(keyEncParam); + + final Encrypter samlEncrypter = new Encrypter(dataEncParams, keyEncParamList); + samlEncrypter.setKeyPlacement(KeyPlacement.PEER); + + return samlEncrypter.encrypt(assertion); + + } catch (final EncryptionException | SamlSigningException e1) { + throw new Exception(e1); + + } + + } + + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/CredentialProviderTest.java b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/CredentialProviderTest.java new file mode 100644 index 00000000..c784e392 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/CredentialProviderTest.java @@ -0,0 +1,613 @@ +package at.gv.egiz.eaaf.modules.pvp2.test; + +import java.security.cert.X509Certificate; +import java.util.List; + +import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException; +import at.gv.egiz.eaaf.core.exceptions.EaafFactoryException; +import at.gv.egiz.eaaf.core.impl.credential.EaafKeyStoreFactory; +import at.gv.egiz.eaaf.core.impl.credential.KeyStoreConfiguration; +import at.gv.egiz.eaaf.core.impl.idp.module.test.DummyAuthConfigMap; +import at.gv.egiz.eaaf.modules.pvp2.PvpConstants; +import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential; +import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException; +import at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyCredentialProvider; + +import org.apache.commons.lang3.RandomStringUtils; +import org.apache.xml.security.algorithms.JCEMapper; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration({ + "/spring/test_eaaf_core_map_config.beans.xml", + "/spring/SpringTest-context_lazy.xml", + "/spring/eaaf_utils.beans.xml" + }) +public class CredentialProviderTest { + + private static final String HSM_FACASE_HOST = "eid.a-sit.at"; + private static final String HSM_FACASE_PORT = "9050"; + private static final String HSM_FACASE_SSL_TRUST = "src/test/resources/data/hsm_facade_trust_root.crt"; + private static final String HSM_FACASE_USERNAME = "authhandler-junit"; + private static final String HSM_FACASE_PASSWORD = "supersecret123"; + private static final String PATH_JKS_WITH_TRUST_CERTS = "src/test/resources/data/junit.jks"; + private static final String PATH_JKS_WITHOUT_TRUST_CERTS = "src/test/resources/data/junit_without_trustcerts.jks"; + + private static final String HSM_FACASE_KEYSTORE_NAME = "authhandler"; + + private static final String ALIAS_METADATA = "meta"; + private static final String ALIAS_SIGN = "sig"; + private static final String ALIAS_ENC = "meta"; + + private static final String PASSWORD = "password"; + + private static final String HSM_FACADE_KEY_ALIAS = "authhandler-sign"; + + + @Autowired private ApplicationContext context; + @Autowired private DummyAuthConfigMap config; + + /** + * jUnit test initializer. + */ + @Before + public void initialize() { + config.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_HOST, HSM_FACASE_HOST); + config.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_PORT, HSM_FACASE_PORT); + config.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_SSLTRUST, HSM_FACASE_SSL_TRUST); + config.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_CLIENT_USERNAME, HSM_FACASE_USERNAME); + config.putConfigValue(EaafKeyStoreFactory.CONFIG_PROP_HSM_FACADE_CLIENT_PASSWORD, HSM_FACASE_PASSWORD); + + config.putConfigValue(DummyCredentialProvider.KEYSTORE_NAME, HSM_FACASE_KEYSTORE_NAME); + + config.putConfigValue(DummyCredentialProvider.KEYSTORE_PATH, PATH_JKS_WITH_TRUST_CERTS); + config.putConfigValue(DummyCredentialProvider.KEYSTORE_PASSWORD, PASSWORD); + + config.removeConfigValue(DummyCredentialProvider.KEY_METADATA_ALIAS); + config.removeConfigValue(DummyCredentialProvider.KEY_METADATA_PASSWORD); + + config.removeConfigValue(DummyCredentialProvider.KEY_SIGNING_ALIAS); + config.removeConfigValue(DummyCredentialProvider.KEY_SIGNING_PASSWORD); + + config.removeConfigValue(DummyCredentialProvider.KEY_ENCRYPTION_ALIAS); + config.removeConfigValue(DummyCredentialProvider.KEY_ENCRYPTION_PASSWORD); + + JCEMapper.setProviderId(null); + + } + + @Test + @DirtiesContext + public void noKeyStoreUrl() { + config.removeConfigValue(DummyCredentialProvider.KEYSTORE_PATH); + try { + context.getBean(DummyCredentialProvider.class); + Assert.fail("No KeyStore not detected"); + + } catch (final BeansException e) { + org.springframework.util.Assert.isInstanceOf(EaafConfigurationException.class, + e.getCause(), "Wrong exception"); + } + + } + + @Test + @DirtiesContext + public void noKeyStore() { + config.putConfigValue(DummyCredentialProvider.KEYSTORE_PATH, "src/test/resources/config/notExist.p12"); + try { + context.getBean(DummyCredentialProvider.class); + Assert.fail("No KeyStore not detected"); + + } catch (final BeansException e) { + org.springframework.util.Assert.isInstanceOf(EaafConfigurationException.class, + e.getCause(), "Wrong exception"); + } + + } + + @Test + @DirtiesContext + public void noWrongKeyStorePassword() { + config.putConfigValue(DummyCredentialProvider.KEYSTORE_PASSWORD, "test"); + try { + context.getBean(DummyCredentialProvider.class); + Assert.fail("No KeyStore not detected"); + + } catch (final BeansException e) { + org.springframework.util.Assert.isInstanceOf(EaafFactoryException.class, + e.getCause(), "Wrong exception"); + + } + + } + + @Test + @DirtiesContext + public void notKeyConfigurationWrongAlias() { + final DummyCredentialProvider credential = context.getBean(DummyCredentialProvider.class); + + Assert.assertNotNull("Credetialprovider", credential); + Assert.assertNotNull("Friendlyname", credential.getFriendlyName()); + + try { + config.putConfigValue(DummyCredentialProvider.KEY_METADATA_ALIAS, + RandomStringUtils.randomAlphabetic(5)); + credential.getMetaDataSigningCredential(); + Assert.fail("No Metadata signing credentials not detected"); + + } catch (final CredentialsNotAvailableException e) { + Assert.assertTrue("Wrong errorCode", e.getMessage().contains("internal.pvp.01")); + + } + + try { + config.putConfigValue(DummyCredentialProvider.KEY_SIGNING_ALIAS, + RandomStringUtils.randomAlphabetic(5)); + credential.getMessageSigningCredential(); + Assert.fail("No Metadata signing credentials not detected"); + + } catch (final CredentialsNotAvailableException e) { + Assert.assertTrue("Wrong errorCode", e.getMessage().contains("internal.pvp.01")); + + } + + try { + config.putConfigValue(DummyCredentialProvider.KEY_ENCRYPTION_ALIAS, + RandomStringUtils.randomAlphabetic(5)); + credential.getMessageEncryptionCredential(); + Assert.fail("No Metadata signing credentials not detected"); + + } catch (final CredentialsNotAvailableException e) { + Assert.assertTrue("Wrong errorCode", e.getMessage().contains("internal.pvp.01")); + + } + + } + + @Test + @DirtiesContext + public void notKeyConfigurationWrongPassword() { + final DummyCredentialProvider credential = context.getBean(DummyCredentialProvider.class); + + Assert.assertNotNull("Credetialprovider", credential); + Assert.assertNotNull("Friendlyname", credential.getFriendlyName()); + + try { + config.putConfigValue(DummyCredentialProvider.KEY_METADATA_PASSWORD, + RandomStringUtils.randomAlphabetic(5)); + credential.getMetaDataSigningCredential(); + Assert.fail("No Metadata signing credentials not detected"); + + } catch (final CredentialsNotAvailableException e) { + Assert.assertTrue("Wrong errorCode", e.getMessage().contains("internal.pvp.01")); + + } + + try { + config.putConfigValue(DummyCredentialProvider.KEY_SIGNING_PASSWORD, + RandomStringUtils.randomAlphabetic(5)); + credential.getMessageSigningCredential(); + Assert.fail("No message signing credentials not detected"); + + } catch (final CredentialsNotAvailableException e) { + Assert.assertTrue("Wrong errorCode", e.getMessage().contains("internal.pvp.01")); + + } + + try { + config.putConfigValue(DummyCredentialProvider.KEY_ENCRYPTION_PASSWORD, + RandomStringUtils.randomAlphabetic(5)); + final EaafX509Credential encCred = credential.getMessageEncryptionCredential(); + Assert.assertNull("No encryption credentials not detected", encCred); + + } catch (final CredentialsNotAvailableException e) { + Assert.assertTrue("Wrong errorCode", e.getMessage().contains("internal.pvp.01")); + + } + + } + + @Test + @DirtiesContext + public void notKeyConfigurationValidAliasWrongPassword() { + final DummyCredentialProvider credential = context.getBean(DummyCredentialProvider.class); + + Assert.assertNotNull("Credetialprovider", credential); + Assert.assertNotNull("Friendlyname", credential.getFriendlyName()); + + try { + config.putConfigValue(DummyCredentialProvider.KEY_METADATA_ALIAS, + ALIAS_METADATA); + config.putConfigValue(DummyCredentialProvider.KEY_METADATA_PASSWORD, + RandomStringUtils.randomAlphabetic(5)); + credential.getMetaDataSigningCredential(); + Assert.fail("No Metadata signing credentials not detected"); + + } catch (final CredentialsNotAvailableException e) { + Assert.assertTrue("Wrong errorCode", e.getMessage().contains("internal.pvp.01")); + + } + + try { + config.putConfigValue(DummyCredentialProvider.KEY_SIGNING_ALIAS, + ALIAS_SIGN); + config.putConfigValue(DummyCredentialProvider.KEY_SIGNING_PASSWORD, + RandomStringUtils.randomAlphabetic(5)); + credential.getMessageSigningCredential(); + Assert.fail("No Metadata signing credentials not detected"); + + } catch (final CredentialsNotAvailableException e) { + Assert.assertTrue("Wrong errorCode", e.getMessage().contains("internal.pvp.01")); + + } + + try { + config.putConfigValue(DummyCredentialProvider.KEY_ENCRYPTION_ALIAS, + ALIAS_ENC); + config.putConfigValue(DummyCredentialProvider.KEY_ENCRYPTION_PASSWORD, + RandomStringUtils.randomAlphabetic(5)); + credential.getMessageEncryptionCredential(); + Assert.fail("No Metadata signing credentials not detected"); + + } catch (final CredentialsNotAvailableException e) { + Assert.assertTrue("Wrong errorCode", e.getMessage().contains("internal.pvp.01")); + + } + } + + @Test + @DirtiesContext + public void notKeyConfigurationWrongAliasValidPassword() { + final DummyCredentialProvider credential = context.getBean(DummyCredentialProvider.class); + + Assert.assertNotNull("Credetialprovider", credential); + Assert.assertNotNull("Friendlyname", credential.getFriendlyName()); + + try { + config.putConfigValue(DummyCredentialProvider.KEY_METADATA_ALIAS, + RandomStringUtils.randomAlphabetic(5)); + config.putConfigValue(DummyCredentialProvider.KEY_METADATA_PASSWORD, + PASSWORD); + credential.getMetaDataSigningCredential(); + Assert.fail("No Metadata signing credentials not detected"); + + } catch (final CredentialsNotAvailableException e) { + Assert.assertTrue("Wrong errorCode", e.getMessage().contains("internal.pvp.01")); + + } + + try { + config.putConfigValue(DummyCredentialProvider.KEY_SIGNING_ALIAS, + RandomStringUtils.randomAlphabetic(5)); + config.putConfigValue(DummyCredentialProvider.KEY_SIGNING_PASSWORD, + PASSWORD); + credential.getMessageSigningCredential(); + Assert.fail("No Metadata signing credentials not detected"); + + } catch (final CredentialsNotAvailableException e) { + Assert.assertTrue("Wrong errorCode", e.getMessage().contains("internal.pvp.01")); + + } + + try { + config.putConfigValue(DummyCredentialProvider.KEY_ENCRYPTION_ALIAS, + RandomStringUtils.randomAlphabetic(5)); + config.putConfigValue(DummyCredentialProvider.KEY_ENCRYPTION_PASSWORD, + PASSWORD); + credential.getMessageEncryptionCredential(); + Assert.fail("No Metadata signing credentials not detected"); + + } catch (final CredentialsNotAvailableException e) { + Assert.assertTrue("Wrong errorCode", e.getMessage().contains("internal.pvp.01")); + + } + } + + @Test + @DirtiesContext + public void validonfiguration() throws CredentialsNotAvailableException { + final DummyCredentialProvider credential = context.getBean(DummyCredentialProvider.class); + + Assert.assertNotNull("Credetialprovider", credential); + Assert.assertNotNull("Friendlyname", credential.getFriendlyName()); + + + config.putConfigValue(DummyCredentialProvider.KEY_METADATA_ALIAS, + ALIAS_METADATA); + config.putConfigValue(DummyCredentialProvider.KEY_METADATA_PASSWORD, + PASSWORD); + + checkCredential(credential.getMetaDataSigningCredential(), + PvpConstants.DEFAULT_SIGNING_METHODE_RSA, + PvpConstants.DEFAULT_ASYM_ENCRYPTION_METHODE_RSA); + + config.putConfigValue(DummyCredentialProvider.KEY_SIGNING_ALIAS, + ALIAS_SIGN); + config.putConfigValue(DummyCredentialProvider.KEY_SIGNING_PASSWORD, + PASSWORD); + checkCredential(credential.getMessageSigningCredential(), + PvpConstants.DEFAULT_SIGNING_METHODE_EC, + PvpConstants.DEFAULT_ASYM_ENCRYPTION_METHODE_EC); + + config.putConfigValue(DummyCredentialProvider.KEY_ENCRYPTION_ALIAS, + ALIAS_ENC); + config.putConfigValue(DummyCredentialProvider.KEY_ENCRYPTION_PASSWORD, + PASSWORD); + checkCredential(credential.getMessageEncryptionCredential(), + PvpConstants.DEFAULT_SIGNING_METHODE_RSA, + PvpConstants.DEFAULT_ASYM_ENCRYPTION_METHODE_RSA); + + + final List<X509Certificate> trustCerts = credential.getTrustedCertificates(); + Assert.assertNotNull("TrustCerts are null", trustCerts); + Assert.assertFalse("TrustCerts not empty", trustCerts.isEmpty()); + Assert.assertEquals("# of Trustcerts", 2, trustCerts.size()); + + } + + @Test + @DirtiesContext + public void validonfigurationWithOutTrustCerts() throws CredentialsNotAvailableException { + config.putConfigValue(DummyCredentialProvider.KEYSTORE_PATH, PATH_JKS_WITHOUT_TRUST_CERTS); + + config.putConfigValue(PvpConstants.CONFIG_PROP_SEC_SIGNING_RSA_ALG, + "RSA-SIG_" + RandomStringUtils.randomAlphabetic(10)); + config.putConfigValue(PvpConstants.CONFIG_PROP_SEC_SIGNING_EC_ALG, + "EC-SIG_" + RandomStringUtils.randomAlphabetic(10)); + config.putConfigValue(PvpConstants.CONFIG_PROP_SEC_ENCRYPTION_KEY_RSA_ALG, + "RSA_ENC_" + RandomStringUtils.randomAlphabetic(10)); + config.putConfigValue(PvpConstants.CONFIG_PROP_SEC_ENCRYPTION_KEY_EC_ALG, + "EC-ENC_" + RandomStringUtils.randomAlphabetic(10)); + + final DummyCredentialProvider credential = context.getBean(DummyCredentialProvider.class); + + Assert.assertNotNull("Credetialprovider", credential); + Assert.assertNotNull("Friendlyname", credential.getFriendlyName()); + + config.putConfigValue(DummyCredentialProvider.KEY_METADATA_ALIAS, + ALIAS_METADATA); + config.putConfigValue(DummyCredentialProvider.KEY_METADATA_PASSWORD, + PASSWORD); + + checkCredential(credential.getMetaDataSigningCredential(), + config.getBasicConfiguration(PvpConstants.CONFIG_PROP_SEC_SIGNING_RSA_ALG), + config.getBasicConfiguration(PvpConstants.CONFIG_PROP_SEC_ENCRYPTION_KEY_RSA_ALG)); + + config.putConfigValue(DummyCredentialProvider.KEY_SIGNING_ALIAS, + ALIAS_SIGN); + config.putConfigValue(DummyCredentialProvider.KEY_SIGNING_PASSWORD, + PASSWORD); + checkCredential(credential.getMessageSigningCredential(), + config.getBasicConfiguration(PvpConstants.CONFIG_PROP_SEC_SIGNING_EC_ALG), + config.getBasicConfiguration(PvpConstants.CONFIG_PROP_SEC_ENCRYPTION_KEY_EC_ALG)); + + config.putConfigValue(DummyCredentialProvider.KEY_ENCRYPTION_ALIAS, + ALIAS_ENC); + config.putConfigValue(DummyCredentialProvider.KEY_ENCRYPTION_PASSWORD, + PASSWORD); + checkCredential(credential.getMessageEncryptionCredential(), + config.getBasicConfiguration(PvpConstants.CONFIG_PROP_SEC_SIGNING_RSA_ALG), + config.getBasicConfiguration(PvpConstants.CONFIG_PROP_SEC_ENCRYPTION_KEY_RSA_ALG)); + + final List<X509Certificate> trustCerts = credential.getTrustedCertificates(); + Assert.assertNotNull("TrustCerts are null", trustCerts); + Assert.assertTrue("TrustCerts not empty", trustCerts.isEmpty()); + + } + + @Test + @DirtiesContext + public void otherKeyStoreTypeAlreadyLoaded() throws CredentialsNotAvailableException { + config.putConfigValue(DummyCredentialProvider.KEYSTORE_PATH, PATH_JKS_WITHOUT_TRUST_CERTS); + + config.putConfigValue(PvpConstants.CONFIG_PROP_SEC_SIGNING_RSA_ALG, + "RSA-SIG_" + RandomStringUtils.randomAlphabetic(10)); + config.putConfigValue(PvpConstants.CONFIG_PROP_SEC_SIGNING_EC_ALG, + "EC-SIG_" + RandomStringUtils.randomAlphabetic(10)); + config.putConfigValue(PvpConstants.CONFIG_PROP_SEC_ENCRYPTION_KEY_RSA_ALG, + "RSA_ENC_" + RandomStringUtils.randomAlphabetic(10)); + config.putConfigValue(PvpConstants.CONFIG_PROP_SEC_ENCRYPTION_KEY_EC_ALG, + "EC-ENC_" + RandomStringUtils.randomAlphabetic(10)); + + try { + JCEMapper.setProviderId(RandomStringUtils.randomAlphabetic(5)); + + context.getBean(DummyCredentialProvider.class); + + } catch (final BeansException e) { + org.springframework.util.Assert.isInstanceOf(EaafConfigurationException.class, + e.getCause(), "Wrong exception"); + + } + + } + + @Test + @DirtiesContext + public void notKeyConfiguration() { + final DummyCredentialProvider credential = context.getBean(DummyCredentialProvider.class); + + Assert.assertNotNull("Credetialprovider", credential); + Assert.assertNotNull("Friendlyname", credential.getFriendlyName()); + + try { + credential.getMetaDataSigningCredential(); + Assert.fail("No Metadata signing credentials not detected"); + + } catch (final CredentialsNotAvailableException e) { + Assert.assertTrue("Wrong errorCode", e.getMessage().contains("internal.pvp.01")); + + } + + try { + credential.getMessageSigningCredential(); + Assert.fail("No Metadata signing credentials not detected"); + + } catch (final CredentialsNotAvailableException e) { + Assert.assertTrue("Wrong errorCode", e.getMessage().contains("internal.pvp.01")); + + } + + try { + final EaafX509Credential encCred = credential.getMessageEncryptionCredential(); + Assert.assertNull("No encryption signing credentials not detected", encCred); + + } catch (final CredentialsNotAvailableException e) { + Assert.assertTrue("Wrong errorCode", e.getMessage().contains("internal.pvp.01")); + + } + + } + + @Test + @DirtiesContext + public void notKeyConfigurationPkcs12() { + config.putConfigValue(DummyCredentialProvider.KEYSTORE_PATH, + "src/test/resources/data/junit_without_trustcerts.p12"); + final DummyCredentialProvider credential = context.getBean(DummyCredentialProvider.class); + + Assert.assertNotNull("Credetialprovider", credential); + Assert.assertNotNull("Friendlyname", credential.getFriendlyName()); + + try { + credential.getMetaDataSigningCredential(); + Assert.fail("No Metadata signing credentials not detected"); + + } catch (final CredentialsNotAvailableException e) { + Assert.assertTrue("Wrong errorCode", e.getMessage().contains("internal.pvp.01")); + + } + + try { + credential.getMessageSigningCredential(); + Assert.fail("No message signing credentials not detected"); + + } catch (final CredentialsNotAvailableException e) { + Assert.assertTrue("Wrong errorCode", e.getMessage().contains("internal.pvp.01")); + + } + + try { + final EaafX509Credential encCred = credential.getMessageEncryptionCredential(); + Assert.assertNull("No encryption signing credentials not detected", encCred); + + } catch (final CredentialsNotAvailableException e) { + Assert.assertTrue("Wrong errorCode", e.getMessage().contains("internal.pvp.01")); + + } + } + + @Test + @DirtiesContext + public void hasFacadeMissingKeyStoreName() { + config.putConfigValue(DummyCredentialProvider.KEYSTORE_TYPE, + KeyStoreConfiguration.KeyStoreType.HSMFACADE.getKeyStoreType()); + config.removeConfigValue(DummyCredentialProvider.KEYSTORE_NAME); + + try { + context.getBean(DummyCredentialProvider.class); + Assert.fail("No KeyStore not detected"); + + } catch (final BeansException e) { + org.springframework.util.Assert.isInstanceOf(EaafConfigurationException.class, + e.getCause(), "Wrong exception"); + + } + + } + + @Test + @DirtiesContext + public void hasFacadeWrongAlias() { + config.putConfigValue(DummyCredentialProvider.KEYSTORE_TYPE, + KeyStoreConfiguration.KeyStoreType.HSMFACADE.getKeyStoreType()); + config.putConfigValue(DummyCredentialProvider.KEYSTORE_NAME, HSM_FACASE_KEYSTORE_NAME); + + final DummyCredentialProvider credential = context.getBean(DummyCredentialProvider.class); + + Assert.assertNotNull("Credetialprovider", credential); + Assert.assertNotNull("Friendlyname", credential.getFriendlyName()); + + config.putConfigValue(DummyCredentialProvider.KEY_METADATA_ALIAS, + RandomStringUtils.randomAlphabetic(5)); + + try { + checkCredential(credential.getMetaDataSigningCredential(), + PvpConstants.DEFAULT_SIGNING_METHODE_RSA, + PvpConstants.DEFAULT_ASYM_ENCRYPTION_METHODE_RSA); + Assert.fail("Wrong 'alias' not detected"); + + } catch (final CredentialsNotAvailableException e) { + Assert.assertEquals("Wrong errorCode", "internal.pvp.01", e.getErrorId()); + + } + + } + + @Test + @DirtiesContext + public void validConfigurationHsmFacade() throws CredentialsNotAvailableException { + + config.putConfigValue(DummyCredentialProvider.KEYSTORE_TYPE, + KeyStoreConfiguration.KeyStoreType.HSMFACADE.getKeyStoreType()); + config.putConfigValue(DummyCredentialProvider.KEYSTORE_NAME, HSM_FACASE_KEYSTORE_NAME); + + final DummyCredentialProvider credential = context.getBean(DummyCredentialProvider.class); + + Assert.assertNotNull("Credetialprovider", credential); + Assert.assertNotNull("Friendlyname", credential.getFriendlyName()); + + config.putConfigValue(DummyCredentialProvider.KEY_METADATA_ALIAS, + HSM_FACADE_KEY_ALIAS); + config.putConfigValue(DummyCredentialProvider.KEY_METADATA_PASSWORD, + PASSWORD); + + + checkCredential(credential.getMetaDataSigningCredential(), + PvpConstants.DEFAULT_SIGNING_METHODE_RSA, + PvpConstants.DEFAULT_ASYM_ENCRYPTION_METHODE_RSA); + + config.putConfigValue(DummyCredentialProvider.KEY_SIGNING_ALIAS, + HSM_FACADE_KEY_ALIAS); + + checkCredential(credential.getMessageSigningCredential(), + PvpConstants.DEFAULT_SIGNING_METHODE_RSA, + PvpConstants.DEFAULT_ASYM_ENCRYPTION_METHODE_RSA); + + + final List<X509Certificate> trustCerts = credential.getTrustedCertificates(); + Assert.assertNotNull("TrustCerts are null", trustCerts); + Assert.assertTrue("TrustCerts not empty", trustCerts.isEmpty()); + + } + + + private void checkCredential(EaafX509Credential metaDataSigningCredential, String sigAlg, String keyEncAlg) { + Assert.assertNotNull("No metadata signing credentials", metaDataSigningCredential); + Assert.assertNotNull("SigAlg is null", + metaDataSigningCredential.getSignatureAlgorithmForSigning()); + Assert.assertNotNull("KeyEncAlg is null", + metaDataSigningCredential.getKeyEncryptionAlgorithmForDataEncryption()); + Assert.assertFalse("SigAlg is empty", + metaDataSigningCredential.getSignatureAlgorithmForSigning().isEmpty()); + Assert.assertFalse("KeyEncAlg is empty", + metaDataSigningCredential.getKeyEncryptionAlgorithmForDataEncryption().isEmpty()); + + Assert.assertEquals("Wrong SigAlg", sigAlg, + metaDataSigningCredential.getSignatureAlgorithmForSigning()); + Assert.assertEquals("Wrong KeyEncAlg", keyEncAlg, + metaDataSigningCredential.getKeyEncryptionAlgorithmForDataEncryption()); + + } +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/Pvp2SProfileCoreSpringResourceProviderTest.java b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/Pvp2SProfileCoreSpringResourceProviderTest.java new file mode 100644 index 00000000..67c59dec --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/Pvp2SProfileCoreSpringResourceProviderTest.java @@ -0,0 +1,56 @@ +package at.gv.egiz.eaaf.modules.pvp2.test; + +import java.io.IOException; +import java.io.InputStream; + +import org.apache.commons.io.IOUtils; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.BlockJUnit4ClassRunner; +import org.springframework.core.io.Resource; + +import at.gv.egiz.eaaf.core.test.TestConstants; +import at.gv.egiz.eaaf.modules.pvp2.Pvp2SProfileCoreSpringResourceProvider; + + + +@RunWith(BlockJUnit4ClassRunner.class) +public class Pvp2SProfileCoreSpringResourceProviderTest { + + @Test + public void testSpringConfig() { + final Pvp2SProfileCoreSpringResourceProvider test = + new Pvp2SProfileCoreSpringResourceProvider(); + for (final Resource el : test.getResourcesToLoad()) { + try { + IOUtils.toByteArray(el.getInputStream()); + + } catch (final IOException e) { + Assert.fail("Ressouce: " + el.getFilename() + " not found"); + } + + } + + Assert.assertNotNull("no Name", test.getName()); + Assert.assertNull("Find package definitions", test.getPackagesToScan()); + + } + + @Test + public void testSpILoaderConfig() { + final InputStream el = this.getClass().getResourceAsStream(TestConstants.TEST_SPI_LOADER_PATH); + try { + final String spiFile = IOUtils.toString(el, "UTF-8"); + + Assert.assertEquals("Wrong classpath in SPI file", + Pvp2SProfileCoreSpringResourceProvider.class.getName(), spiFile); + + + } catch (final IOException e) { + Assert.fail("Ressouce: " + TestConstants.TEST_SPI_LOADER_PATH + " not found"); + + } + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/PvpCoreMessageSourceTest.java b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/PvpCoreMessageSourceTest.java new file mode 100644 index 00000000..b94ed8cc --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/PvpCoreMessageSourceTest.java @@ -0,0 +1,43 @@ +package at.gv.egiz.eaaf.modules.pvp2.test; + +import java.util.List; + +import at.gv.egiz.eaaf.core.api.logging.IMessageSourceLocation; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.Resource; +import org.springframework.core.io.ResourceLoader; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration({ "/spring/test_eaaf_pvp.beans.xml", +"/spring/test_eaaf_core_spring_config.beans.xml", +"/spring/eaaf_utils.beans.xml" }) +@TestPropertySource(locations = { "/config/config_1.props" }) +public class PvpCoreMessageSourceTest { + + @Autowired + private ResourceLoader loader; + @Autowired(required = false) + private List<IMessageSourceLocation> messageSources; + + @Test + public void checkMessageSources() { + Assert.assertNotNull("No messageSource", messageSources); + + for (final IMessageSourceLocation messageSource : messageSources) { + Assert.assertNotNull("No sourcePath", messageSource.getMessageSourceLocation()); + + for (final String el : messageSource.getMessageSourceLocation()) { + final Resource messages = loader.getResource(el + ".properties"); + Assert.assertTrue("Source not exist", messages.exists()); + + } + } + } +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/QaaLevelVerifierTest.java b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/QaaLevelVerifierTest.java new file mode 100644 index 00000000..44cdf111 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/QaaLevelVerifierTest.java @@ -0,0 +1,147 @@ +package at.gv.egiz.eaaf.modules.pvp2.test; + +import java.util.Arrays; +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.BlockJUnit4ClassRunner; + +import at.gv.egiz.eaaf.core.api.data.EaafConstants; +import at.gv.egiz.eaaf.modules.pvp2.exception.QaaNotAllowedException; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.QaaLevelVerifier; + +@RunWith(BlockJUnit4ClassRunner.class) +public class QaaLevelVerifierTest { + + QaaLevelVerifier verifyer = new QaaLevelVerifier(); + + @Test + public void matchingModeUnknown() { + String matchingMode = "notExist"; + List<String> requiredLoAs = Arrays.asList(EaafConstants.EIDAS_LOA_SUBSTANTIAL); + + try { + QaaLevelVerifier.verifyQaaLevel(EaafConstants.EIDAS_LOA_LOW, requiredLoAs, matchingMode); + Assert.fail("LoA should not be allowed"); + + } catch (QaaNotAllowedException e) { + + } + + try { + QaaLevelVerifier.verifyQaaLevel("not_exist", requiredLoAs, matchingMode); + Assert.fail("LoA should not be allowed"); + + } catch (QaaNotAllowedException e) { + + } + + } + + @Test + public void matchingMinimumRequiredLow() throws QaaNotAllowedException { + String matchingMode = EaafConstants.EIDAS_LOA_MATCHING_MINIMUM; + List<String> requiredLoAs = Arrays.asList(EaafConstants.EIDAS_LOA_LOW); + + QaaLevelVerifier.verifyQaaLevel(EaafConstants.EIDAS_LOA_LOW, requiredLoAs, matchingMode); + QaaLevelVerifier.verifyQaaLevel(EaafConstants.EIDAS_LOA_SUBSTANTIAL, requiredLoAs, matchingMode); + QaaLevelVerifier.verifyQaaLevel(EaafConstants.EIDAS_LOA_HIGH, requiredLoAs, matchingMode); + + try { + QaaLevelVerifier.verifyQaaLevel("not_exist", requiredLoAs, matchingMode); + Assert.fail("LoA should not be allowed"); + + } catch (QaaNotAllowedException e) { + + } + + } + + @Test + public void matchingMinimumRequiredSubstantial() throws QaaNotAllowedException { + String matchingMode = EaafConstants.EIDAS_LOA_MATCHING_MINIMUM; + List<String> requiredLoAs = Arrays.asList(EaafConstants.EIDAS_LOA_SUBSTANTIAL); + + try { + QaaLevelVerifier.verifyQaaLevel(EaafConstants.EIDAS_LOA_LOW, requiredLoAs, matchingMode); + Assert.fail("LoA should not be allowed"); + + } catch (QaaNotAllowedException e) { + + } + + QaaLevelVerifier.verifyQaaLevel(EaafConstants.EIDAS_LOA_SUBSTANTIAL, requiredLoAs, matchingMode); + QaaLevelVerifier.verifyQaaLevel(EaafConstants.EIDAS_LOA_HIGH, requiredLoAs, matchingMode); + + try { + QaaLevelVerifier.verifyQaaLevel("not_exist", requiredLoAs, matchingMode); + Assert.fail("LoA should not be allowed"); + + } catch (QaaNotAllowedException e) { + + } + + } + + @Test + public void matchingMinimumRequiredHigh() throws QaaNotAllowedException { + String matchingMode = EaafConstants.EIDAS_LOA_MATCHING_MINIMUM; + List<String> requiredLoAs = Arrays.asList(EaafConstants.EIDAS_LOA_HIGH); + + try { + QaaLevelVerifier.verifyQaaLevel(EaafConstants.EIDAS_LOA_LOW, requiredLoAs, matchingMode); + Assert.fail("LoA should not be allowed"); + + } catch (QaaNotAllowedException e) { + + } + + try { + QaaLevelVerifier.verifyQaaLevel(EaafConstants.EIDAS_LOA_SUBSTANTIAL, requiredLoAs, matchingMode); + Assert.fail("LoA should not be allowed"); + + } catch (QaaNotAllowedException e) { + + } + + QaaLevelVerifier.verifyQaaLevel(EaafConstants.EIDAS_LOA_HIGH, requiredLoAs, matchingMode); + + try { + QaaLevelVerifier.verifyQaaLevel("not_exist", requiredLoAs, matchingMode); + Assert.fail("LoA should not be allowed"); + + } catch (QaaNotAllowedException e) { + + } + + } + + @Test + public void matchingExact1() throws QaaNotAllowedException { + String matchingMode = EaafConstants.EIDAS_LOA_MATCHING_EXACT; + List<String> requiredLoAs = Arrays.asList(EaafConstants.EIDAS_LOA_SUBSTANTIAL, EaafConstants.EIDAS_LOA_LOW); + + try { + QaaLevelVerifier.verifyQaaLevel(EaafConstants.EIDAS_LOA_HIGH, requiredLoAs, matchingMode); + Assert.fail("LoA should not be allowed"); + + } catch (QaaNotAllowedException e) { + + } + + QaaLevelVerifier.verifyQaaLevel(EaafConstants.EIDAS_LOA_LOW, requiredLoAs, matchingMode); + QaaLevelVerifier.verifyQaaLevel(EaafConstants.EIDAS_LOA_SUBSTANTIAL, requiredLoAs, matchingMode); + + try { + QaaLevelVerifier.verifyQaaLevel("not_exist", requiredLoAs, matchingMode); + Assert.fail("LoA should not be allowed"); + + } catch (QaaNotAllowedException e) { + + } + + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/SamlVerificationEngineTest.java b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/SamlVerificationEngineTest.java new file mode 100644 index 00000000..64bfb8f6 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/SamlVerificationEngineTest.java @@ -0,0 +1,474 @@ +package at.gv.egiz.eaaf.modules.pvp2.test; + +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.core.exceptions.EaafProtocolException; +import at.gv.egiz.eaaf.core.exceptions.InvalidProtocolRequestException; +import at.gv.egiz.eaaf.core.impl.data.Pair; +import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2MetadataException; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlAssertionValidationExeption; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlSigningException; +import at.gv.egiz.eaaf.modules.pvp2.impl.message.PvpSProfileRequest; +import at.gv.egiz.eaaf.modules.pvp2.impl.validation.TrustEngineFactory; +import at.gv.egiz.eaaf.modules.pvp2.impl.verification.SamlVerificationEngine; +import at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyCredentialProvider; +import at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyMetadataProvider; + +import org.joda.time.DateTime; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.opensaml.core.xml.io.UnmarshallingException; +import org.opensaml.core.xml.util.XMLObjectSupport; +import org.opensaml.saml.common.xml.SAMLConstants; +import org.opensaml.saml.saml2.core.Assertion; +import org.opensaml.saml.saml2.core.AuthnRequest; +import org.opensaml.saml.saml2.core.EncryptedAssertion; +import org.opensaml.saml.saml2.core.Response; +import org.opensaml.saml.saml2.core.StatusCode; +import org.opensaml.xmlsec.signature.support.SignatureConstants; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.util.Assert; +import org.w3c.dom.Element; + +import net.shibboleth.utilities.java.support.xml.XMLParserException; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration({ "/spring/test_eaaf_pvp.beans.xml", + "/spring/test_eaaf_core_spring_config.beans.xml", + "/spring/eaaf_utils.beans.xml" }) +@TestPropertySource(locations = { "/config/config_1.props" }) +public class SamlVerificationEngineTest extends AbstractSamlVerificationEngine { + + @Autowired + private SamlVerificationEngine verifyEngine; + @Autowired + private DummyCredentialProvider credentialProvider; + + @Autowired DummyMetadataProvider metadataProvider; + @Autowired IConfiguration authConfig; + + @Override + protected String getMetadataClassPathEntityPath() { + return "classpath:/data/pvp_metadata_junit_keystore_classpath_entityId.xml"; + + } + + @Override + protected String getMetadataJunitJKeystore() { + return "classpath:/data/pvp_metadata_junit_keystore.xml"; + } + + @Override + protected String getAuthnRequestWithoutSigPath() { + return "/data/AuthRequest_without_sig_1.xml"; + + } + + @Override + protected String getResponseWithSigPath() { + return "/data/Response_with_sig_1.xml"; + } + + @Override + protected String getResponseWithoutSigPath() { + return "/data/Response_without_sig_1.xml"; + } + + @Test + public void validateSamlRequestWrongSignatureAlg() throws SecurityException, Exception { + + final String authnReqPath = getAuthnRequestWithoutSigPath(); + final String metadataPath = getMetadataJunitJKeystore(); + final String spEntityId = metadataPath; + + metadataProvider.runGarbageCollector(); + + final EaafX509Credential cred = credentialProvider.getMetaDataSigningCredential(); + cred.setSignatureAlgorithmForSigning(SignatureConstants.ALGO_ID_SIGNATURE_NOT_RECOMMENDED_RSA_MD5); + final Pair<AuthnRequest, IPvp2MetadataProvider> inputMsg = + initializeAuthnRequest(spEntityId, metadataPath, authnReqPath, + cred); + + final PvpSProfileRequest msg = new PvpSProfileRequest( + inputMsg.getFirst(), + SAMLConstants.SAML2_POST_BINDING_URI); + msg.setEntityID(spEntityId); + + try { + verifyEngine.verify(msg, + TrustEngineFactory.getSignatureKnownKeysTrustEngine(metadataProvider)); + org.junit.Assert.fail("Wrong SigAlg not detected"); + + } catch (final Exception e) { + Assert.isInstanceOf(EaafProtocolException.class, e, "Wrong exceptionType"); + org.junit.Assert.assertEquals("Wrong errorcode", "internal.pvp.99", ((EaafException) e).getErrorId()); + + } + } + + @Test + public void validateSamlInvalidRequest() throws SecurityException, Exception { + + final String authnReqPath = "/data/AuthRequest_without_sig_missing_id.xml"; + final String metadataPath = getMetadataJunitJKeystore(); + final String spEntityId = metadataPath; + + final Pair<AuthnRequest, IPvp2MetadataProvider> inputMsg = + initializeAuthnRequest(spEntityId, metadataPath, authnReqPath, + credentialProvider.getMetaDataSigningCredential()); + + metadataProvider.addMetadataResolverIntoChain(inputMsg.getSecond()); + + final PvpSProfileRequest msg = new PvpSProfileRequest( + inputMsg.getFirst(), + SAMLConstants.SAML2_POST_BINDING_URI); + msg.setEntityID(spEntityId); + + try { + verifyEngine.verify(msg, + TrustEngineFactory.getSignatureKnownKeysTrustEngine(metadataProvider)); + org.junit.Assert.fail("invalid request not detected"); + + } catch (final Exception e) { + Assert.isInstanceOf(InvalidProtocolRequestException.class, e, "Wrong exceptionType"); + org.junit.Assert.assertEquals("Wrong errorcode", "internal.pvp.03", ((EaafException) e).getErrorId()); + + } + } + + @Test + public void verifyAssertionSucessNotEncrypted() throws SamlSigningException, Pvp2MetadataException, + CredentialsNotAvailableException, XMLParserException, UnmarshallingException, SamlAssertionValidationExeption { + final String authnReqPath = "/data/Response_without_sig_classpath_entityid.xml"; + final String metadataPath = getMetadataJunitJKeystore(); + final String spEntityId = "https://demo.egiz.gv.at/demoportal_demologin/"; + + final Pair<Response, IPvp2MetadataProvider> inputMsg = + initializeResponse(spEntityId, metadataPath, authnReqPath, + credentialProvider.getMetaDataSigningCredential()); + + verifyEngine.validateAssertion(inputMsg.getFirst(), credentialProvider.getMetaDataSigningCredential(), + spEntityId, "jUnit Test", false); + + + } + + @Test + public void verifyAssertionWrongAudiency() throws SamlSigningException, Pvp2MetadataException, + CredentialsNotAvailableException, XMLParserException, UnmarshallingException, SamlAssertionValidationExeption { + final String authnReqPath = "/data/Response_without_sig_classpath_entityid.xml"; + final String metadataPath = getMetadataJunitJKeystore(); + final String spEntityId = "https://demo.egiz.gv.at/"; + + final Pair<Response, IPvp2MetadataProvider> inputMsg = + initializeResponse(spEntityId, metadataPath, authnReqPath, + credentialProvider.getMetaDataSigningCredential()); + try { + verifyEngine.validateAssertion(inputMsg.getFirst(), credentialProvider.getMetaDataSigningCredential(), + spEntityId, "jUnit Test", false); + org.junit.Assert.fail("Wrong Audiency not detected"); + + } catch (final SamlAssertionValidationExeption e) { + org.junit.Assert.assertEquals("Wrong errorcode", "internal.pvp.15", ((EaafException) e).getErrorId()); + + } + } + + @Test + public void verifyAssertionWrongStatusCode() throws SamlSigningException, Pvp2MetadataException, + CredentialsNotAvailableException, XMLParserException, UnmarshallingException, SamlAssertionValidationExeption { + final String authnReqPath = "/data/Response_without_sig_classpath_entityid.xml"; + final String metadataPath = getMetadataJunitJKeystore(); + final String spEntityId = "https://demo.egiz.gv.at/demoportal_demologin/"; + + final Pair<Response, IPvp2MetadataProvider> inputMsg = + initializeResponse(spEntityId, metadataPath, authnReqPath, + credentialProvider.getMetaDataSigningCredential()); + + final Response response = inputMsg.getFirst(); + response.getStatus().getStatusCode().setValue(StatusCode.RESPONDER); + + try { + verifyEngine.validateAssertion(response, credentialProvider.getMetaDataSigningCredential(), + spEntityId, "jUnit Test", false); + org.junit.Assert.fail("Wrong StatusCode not detected"); + + } catch (final SamlAssertionValidationExeption e) { + org.junit.Assert.assertEquals("Wrong errorcode", "internal.pvp.17", ((EaafException) e).getErrorId()); + + } + } + + @Test + public void verifyAssertionWrongIssueInstant() throws SamlSigningException, Pvp2MetadataException, + CredentialsNotAvailableException, XMLParserException, UnmarshallingException, SamlAssertionValidationExeption { + final String authnReqPath = "/data/Response_without_sig_classpath_entityid.xml"; + final String metadataPath = getMetadataJunitJKeystore(); + final String spEntityId = "https://demo.egiz.gv.at/demoportal_demologin/"; + + final Pair<Response, IPvp2MetadataProvider> inputMsg = + initializeResponse(spEntityId, metadataPath, authnReqPath, + credentialProvider.getMetaDataSigningCredential()); + + final Response response = inputMsg.getFirst(); + response.setIssueInstant(DateTime.now().plusMinutes(10)); + + try { + verifyEngine.validateAssertion(response, credentialProvider.getMetaDataSigningCredential(), + spEntityId, "jUnit Test", true); + org.junit.Assert.fail("Wrong date not detected"); + + } catch (final SamlAssertionValidationExeption e) { + org.junit.Assert.assertEquals("Wrong errorcode", "internal.pvp.14", ((EaafException) e).getErrorId()); + + } + } + + @Test + public void verifyAssertionNoContitions() throws SamlSigningException, Pvp2MetadataException, + CredentialsNotAvailableException, XMLParserException, UnmarshallingException, SamlAssertionValidationExeption { + final String authnReqPath = "/data/Response_without_sig_classpath_entityid.xml"; + final String metadataPath = getMetadataJunitJKeystore(); + final String spEntityId = "https://demo.egiz.gv.at/demoportal_demologin/"; + + final Pair<Response, IPvp2MetadataProvider> inputMsg = + initializeResponse(spEntityId, metadataPath, authnReqPath, + credentialProvider.getMetaDataSigningCredential()); + + final Response response = inputMsg.getFirst(); + response.getAssertions().get(0).setConditions(null); + + try { + verifyEngine.validateAssertion(response, credentialProvider.getMetaDataSigningCredential(), + spEntityId, "jUnit Test", true); + org.junit.Assert.fail("Wrong date not detected"); + + } catch (final SamlAssertionValidationExeption e) { + org.junit.Assert.assertEquals("Wrong errorcode", "internal.pvp.15", ((EaafException) e).getErrorId()); + + } + } + + @Test + public void verifyAssertionWrongContitions() throws SamlSigningException, Pvp2MetadataException, + CredentialsNotAvailableException, XMLParserException, UnmarshallingException, SamlAssertionValidationExeption { + final String authnReqPath = "/data/Response_without_sig_classpath_entityid.xml"; + final String metadataPath = getMetadataJunitJKeystore(); + final String spEntityId = "https://demo.egiz.gv.at/demoportal_demologin/"; + + final Pair<Response, IPvp2MetadataProvider> inputMsg = + initializeResponse(spEntityId, metadataPath, authnReqPath, + credentialProvider.getMetaDataSigningCredential()); + + final Response response = inputMsg.getFirst(); + + try { + verifyEngine.validateAssertion(response, credentialProvider.getMetaDataSigningCredential(), + spEntityId, "jUnit Test", true); + org.junit.Assert.fail("Wrong date not detected"); + + } catch (final SamlAssertionValidationExeption e) { + org.junit.Assert.assertEquals("Wrong errorcode", "internal.pvp.15", ((EaafException) e).getErrorId()); + + } + } + + @Test + public void verifyAssertionWrongContitionsAudienceRestrictions() throws SamlSigningException, Pvp2MetadataException, + CredentialsNotAvailableException, XMLParserException, UnmarshallingException, SamlAssertionValidationExeption { + final String authnReqPath = "/data/Response_without_sig_classpath_entityid.xml"; + final String metadataPath = getMetadataJunitJKeystore(); + final String spEntityId = "https://demo.egiz.gv.at/demoportal_demologin/"; + + final Pair<Response, IPvp2MetadataProvider> inputMsg = + initializeResponse(spEntityId, metadataPath, authnReqPath, + credentialProvider.getMetaDataSigningCredential()); + + final Response response = inputMsg.getFirst(); + response.getAssertions().get(0).getConditions().setNotBefore(DateTime.now()); + response.getAssertions().get(0).getConditions().setNotOnOrAfter(DateTime.now().plusMinutes(15)); + response.getAssertions().get(0).getConditions().getAudienceRestrictions().clear(); + + try { + verifyEngine.validateAssertion(response, credentialProvider.getMetaDataSigningCredential(), + spEntityId, "jUnit Test", true); + org.junit.Assert.fail("Wrong date not detected"); + + } catch (final SamlAssertionValidationExeption e) { + org.junit.Assert.assertEquals("Wrong errorcode", "internal.pvp.15", ((EaafException) e).getErrorId()); + + } + } + + @Test + public void verifyAssertionWrongContitionsNotBefore() throws SamlSigningException, Pvp2MetadataException, + CredentialsNotAvailableException, XMLParserException, UnmarshallingException, SamlAssertionValidationExeption { + final String authnReqPath = "/data/Response_without_sig_classpath_entityid.xml"; + final String metadataPath = getMetadataJunitJKeystore(); + final String spEntityId = "https://demo.egiz.gv.at/demoportal_demologin/"; + + final Pair<Response, IPvp2MetadataProvider> inputMsg = + initializeResponse(spEntityId, metadataPath, authnReqPath, + credentialProvider.getMetaDataSigningCredential()); + + final Response response = inputMsg.getFirst(); + response.getAssertions().get(0).getConditions().setNotBefore(DateTime.now().plusMinutes(10)); + response.getAssertions().get(0).getConditions().setNotOnOrAfter(DateTime.now().plusMinutes(15)); + + try { + verifyEngine.validateAssertion(response, credentialProvider.getMetaDataSigningCredential(), + spEntityId, "jUnit Test", true); + org.junit.Assert.fail("Wrong date not detected"); + + } catch (final SamlAssertionValidationExeption e) { + org.junit.Assert.assertEquals("Wrong errorcode", "internal.pvp.15", ((EaafException) e).getErrorId()); + + } + } + + @Test + public void verifyAssertionWrongContitionsNotOnOrAfter() throws SamlSigningException, Pvp2MetadataException, + CredentialsNotAvailableException, XMLParserException, UnmarshallingException, SamlAssertionValidationExeption { + final String authnReqPath = "/data/Response_without_sig_classpath_entityid.xml"; + final String metadataPath = getMetadataJunitJKeystore(); + final String spEntityId = "https://demo.egiz.gv.at/demoportal_demologin/"; + + final Pair<Response, IPvp2MetadataProvider> inputMsg = + initializeResponse(spEntityId, metadataPath, authnReqPath, + credentialProvider.getMetaDataSigningCredential()); + + final Response response = inputMsg.getFirst(); + response.getAssertions().get(0).getConditions().setNotBefore(DateTime.now()); + response.getAssertions().get(0).getConditions().setNotOnOrAfter(DateTime.now().minusMinutes(5)); + + try { + verifyEngine.validateAssertion(response, credentialProvider.getMetaDataSigningCredential(), + spEntityId, "jUnit Test", true); + org.junit.Assert.fail("Wrong date not detected"); + + } catch (final SamlAssertionValidationExeption e) { + org.junit.Assert.assertEquals("Wrong errorcode", "internal.pvp.15", ((EaafException) e).getErrorId()); + + } + } + + @Test + public void verifyAssertionValidContitions() throws SamlSigningException, Pvp2MetadataException, + CredentialsNotAvailableException, XMLParserException, UnmarshallingException, SamlAssertionValidationExeption { + final String authnReqPath = "/data/Response_without_sig_classpath_entityid.xml"; + final String metadataPath = getMetadataJunitJKeystore(); + final String spEntityId = "https://demo.egiz.gv.at/demoportal_demologin/"; + + final Pair<Response, IPvp2MetadataProvider> inputMsg = + initializeResponse(spEntityId, metadataPath, authnReqPath, + credentialProvider.getMetaDataSigningCredential()); + + final Response response = inputMsg.getFirst(); + response.getAssertions().get(0).getConditions().setNotBefore(DateTime.now()); + response.getAssertions().get(0).getConditions().setNotOnOrAfter(DateTime.now().plusMinutes(5)); + + + verifyEngine.validateAssertion(response, credentialProvider.getMetaDataSigningCredential(), + spEntityId, "jUnit Test", true); + + } + + @Test + public void verifyEncAssertionWrongKey() throws SamlSigningException, Pvp2MetadataException, + CredentialsNotAvailableException, XMLParserException, UnmarshallingException, SamlAssertionValidationExeption { + final String authnReqPath = "/data/Asserion_enc_no_key.xml"; + final String metadataPath = getMetadataJunitJKeystore(); + final String spEntityId = "https://eid.a-sit.at/Shibboleth.sso/"; + + final Pair<Response, IPvp2MetadataProvider> inputMsg = + initializeResponse(spEntityId, metadataPath, authnReqPath, + credentialProvider.getMetaDataSigningCredential()); + + try { + verifyEngine.validateAssertion(inputMsg.getFirst(), credentialProvider.getMetaDataSigningCredential(), + spEntityId, "jUnit Test", false); + org.junit.Assert.fail("Wrong date not detected"); + + } catch (final SamlAssertionValidationExeption e) { + org.junit.Assert.assertEquals("Wrong errorcode", "internal.pvp.16", ((EaafException) e).getErrorId()); + + } + } + + @Test + public void verifyEncAssertion() throws Exception { + final String authnReqPath = "/data/Response_without_sig_classpath_entityid.xml"; + final String metadataPath = getMetadataJunitJKeystore(); + final String spEntityId = "https://demo.egiz.gv.at/demoportal_demologin/"; + + final Pair<Response, IPvp2MetadataProvider> inputMsg = + initializeResponse(spEntityId, metadataPath, authnReqPath, + credentialProvider.getMetaDataSigningCredential()); + + final Response response = inputMsg.getFirst(); + response.getAssertions().get(0).getConditions().setNotBefore(DateTime.now()); + response.getAssertions().get(0).getConditions().setNotOnOrAfter(DateTime.now().plusMinutes(5)); + + final Element secAssertionElement = XMLObjectSupport.marshall(response.getAssertions().get(0)); + + secAssertionElement.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:xs", "http://www.w3.org/2001/XMLSchema"); + final Assertion secAssertion = (Assertion) XMLObjectSupport.getUnmarshaller(secAssertionElement) + .unmarshall(secAssertionElement); + + final EncryptedAssertion encAsserton = doEncryption(secAssertion, + credentialProvider.getMetaDataSigningCredential(), + authConfig); + response.getEncryptedAssertions().add(encAsserton); + + + verifyEngine.validateAssertion(response, credentialProvider.getMetaDataSigningCredential(), + spEntityId, "jUnit Test", false); + + org.junit.Assert.assertEquals("Assertions not match", 2, response.getAssertions().size()); + + } + + @Test + public void verifyEncAssertionWrongSchema() throws Exception { + final String authnReqPath = "/data/Response_without_sig_classpath_entityid.xml"; + final String metadataPath = getMetadataJunitJKeystore(); + final String spEntityId = "https://demo.egiz.gv.at/demoportal_demologin/"; + + final Pair<Response, IPvp2MetadataProvider> inputMsg = + initializeResponse(spEntityId, metadataPath, authnReqPath, + credentialProvider.getMetaDataSigningCredential()); + + final Response response = inputMsg.getFirst(); + response.getAssertions().get(0).getConditions().setNotBefore(DateTime.now()); + response.getAssertions().get(0).getConditions().setNotOnOrAfter(DateTime.now().plusMinutes(5)); + + final Element secAssertionElement = XMLObjectSupport.marshall(response.getAssertions().get(0)); + + final Assertion secAssertion = (Assertion) XMLObjectSupport.getUnmarshaller(secAssertionElement) + .unmarshall(secAssertionElement); + + final EncryptedAssertion encAsserton = doEncryption(secAssertion, + credentialProvider.getMetaDataSigningCredential(), + authConfig); + response.getEncryptedAssertions().add(encAsserton); + + try { + verifyEngine.validateAssertion(response, credentialProvider.getMetaDataSigningCredential(), + spEntityId, "jUnit Test", false); + + org.junit.Assert.fail("Wrong XML Schema not detected"); + + } catch (final SamlAssertionValidationExeption e) { + org.junit.Assert.assertEquals("Wrong errorcode", "internal.pvp.15", ((EaafException) e).getErrorId()); + + } + + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/SamlVerificationEngineWithHsmFacadeTest.java b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/SamlVerificationEngineWithHsmFacadeTest.java new file mode 100644 index 00000000..5b06a73f --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/SamlVerificationEngineWithHsmFacadeTest.java @@ -0,0 +1,70 @@ +package at.gv.egiz.eaaf.modules.pvp2.test; + +import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlSigningException; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.opensaml.xmlsec.signature.support.SignatureConstants; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration({ "/spring/test_eaaf_pvp.beans.xml", + "/spring/test_eaaf_core_spring_config.beans.xml", + "/spring/eaaf_utils.beans.xml" }) +@TestPropertySource(locations = { "/config/config_3.props" }) +public class SamlVerificationEngineWithHsmFacadeTest extends AbstractSamlVerificationEngine { + + @Override + protected String getMetadataClassPathEntityPath() { + return "classpath:/data/pvp_metadata_junit_keystore_classpath_entityId.xml"; + + } + + @Override + protected String getMetadataJunitJKeystore() { + return "classpath:/data/pvp_metadata_junit_keystore.xml"; + } + + @Override + protected String getAuthnRequestWithoutSigPath() { + return "/data/AuthRequest_without_sig_1.xml"; + + } + + @Override + protected String getResponseWithSigPath() { + return "/data/Response_with_sig_1.xml"; + } + + @Override + protected String getResponseWithoutSigPath() { + return "/data/Response_without_sig_1.xml"; + } + + @Test + public void validateSamlRequestWrongSignatureAlg() throws SecurityException, Exception { + + final String authnReqPath = getAuthnRequestWithoutSigPath(); + final String metadataPath = getMetadataJunitJKeystore(); + final String spEntityId = metadataPath; + + metadataProvider.runGarbageCollector(); + + final EaafX509Credential cred = credentialProvider.getMetaDataSigningCredential(); + cred.setSignatureAlgorithmForSigning(SignatureConstants.ALGO_ID_SIGNATURE_NOT_RECOMMENDED_RSA_MD5); + try { + initializeAuthnRequest(spEntityId, metadataPath, authnReqPath, + cred); + org.junit.Assert.fail("Wrong SigAlg not detected"); + + } catch (final SamlSigningException e) { + org.junit.Assert.assertEquals("Wrong errorCode", "internal.pvp.96", e.getErrorId()); + + } + } + + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/binding/PostBindingTest.java b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/binding/PostBindingTest.java new file mode 100644 index 00000000..147199a5 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/binding/PostBindingTest.java @@ -0,0 +1,764 @@ +package at.gv.egiz.eaaf.modules.pvp2.test.binding; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.util.Base64; +import java.util.Map; + +import javax.xml.parsers.ParserConfigurationException; + +import at.gv.egiz.eaaf.core.api.IRequest; +import at.gv.egiz.eaaf.core.api.gui.IVelocityGuiBuilderConfiguration; +import at.gv.egiz.eaaf.core.impl.idp.module.gui.DummyGuiBuilderConfigurationFactory; +import at.gv.egiz.eaaf.core.impl.idp.module.test.TestRequestImpl; +import at.gv.egiz.eaaf.core.impl.utils.DomUtils; +import at.gv.egiz.eaaf.core.impl.utils.IHttpClientFactory; +import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential; +import at.gv.egiz.eaaf.modules.pvp2.api.message.InboundMessageInterface; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttribute; +import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttributes; +import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2MetadataException; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlMessageValidationException; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlSigningException; +import at.gv.egiz.eaaf.modules.pvp2.impl.binding.PostBinding; +import at.gv.egiz.eaaf.modules.pvp2.impl.message.InboundMessage; +import at.gv.egiz.eaaf.modules.pvp2.impl.message.PvpSProfileRequest; +import at.gv.egiz.eaaf.modules.pvp2.impl.message.PvpSProfileResponse; +import at.gv.egiz.eaaf.modules.pvp2.impl.metadata.PvpMetadataResolverFactory; +import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafOpenSaml3xInitializer; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils; +import at.gv.egiz.eaaf.modules.pvp2.impl.validation.EaafUriCompare; +import at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyCredentialProvider; +import at.gv.egiz.eaaf.modules.pvp2.test.metadata.MetadataResolverTest; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.RandomStringUtils; +import org.joda.time.DateTime; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.opensaml.core.xml.XMLObject; +import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport; +import org.opensaml.core.xml.io.MarshallingException; +import org.opensaml.core.xml.io.Unmarshaller; +import org.opensaml.core.xml.io.UnmarshallerFactory; +import org.opensaml.core.xml.io.UnmarshallingException; +import org.opensaml.core.xml.schema.XSString; +import org.opensaml.core.xml.util.XMLObjectSupport; +import org.opensaml.messaging.decoder.MessageDecodingException; +import org.opensaml.messaging.encoder.MessageEncodingException; +import org.opensaml.saml.common.SignableSAMLObject; +import org.opensaml.saml.saml2.core.AuthnRequest; +import org.opensaml.saml.saml2.core.Issuer; +import org.opensaml.saml.saml2.core.RequestAbstractType; +import org.opensaml.saml.saml2.core.StatusResponseType; +import org.opensaml.saml.saml2.metadata.SPSSODescriptor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.w3c.dom.Element; +import org.xml.sax.SAXException; + +import net.shibboleth.utilities.java.support.net.URIComparator; +import net.shibboleth.utilities.java.support.xml.SerializeSupport; +import net.shibboleth.utilities.java.support.xml.XMLParserException; +import okhttp3.HttpUrl; +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration({"/spring/test_eaaf_pvp.beans.xml", + "/spring/test_eaaf_core_spring_config.beans.xml", + "/spring/eaaf_utils.beans.xml"}) +@TestPropertySource(locations = {"/config/config_1.props"}) +public class PostBindingTest { + + public static final String HTTP_FORM_RELAYSTATE = "RelayState="; + public static final String HTTP_FORM_SAMLREQ = "SAMLRequest="; + public static final String HTTP_FORM_SAMLRESP = "SAMLResponse="; + + @Autowired private PostBinding bindingImpl; + @Autowired private DummyCredentialProvider credentialProvider; + @Autowired private DummyGuiBuilderConfigurationFactory guiBuilderFactory; + @Autowired private PvpMetadataResolverFactory metadataResolverFactory; + @Autowired private IHttpClientFactory httpClientFactory; + + private static MockWebServer mockWebServer; + private static HttpUrl mockServerUrl; + + protected MockHttpServletRequest httpReq; + protected MockHttpServletResponse httpResp; + protected IRequest pendingReq; + + /** + * JUnit class initializer. + * + * @throws Exception In case of an OpenSAML3 initialization error + */ + @BeforeClass + public static void classInitializer() throws Exception { + EaafOpenSaml3xInitializer.eaafInitialize(); + + mockWebServer = new MockWebServer(); + mockServerUrl = mockWebServer.url("/sp/metadata"); + } + + /** + * Test initializer. + * + */ + @Before + public void initialize() { + httpReq = new MockHttpServletRequest(); + httpResp = new MockHttpServletResponse(); + + pendingReq = new TestRequestImpl(); + + } + + @Test + public void checkCanHandle() { + httpReq.setMethod("POST"); + Assert.assertTrue("Wrong canHandle result", bindingImpl.handleDecode("Post", httpReq)); + Assert.assertFalse("Wrong canHandle result", bindingImpl.handleDecode("Redirect", httpReq)); + + httpReq.setMethod("GET"); + Assert.assertFalse("Wrong canHandle result", bindingImpl.handleDecode("Post", httpReq)); + Assert.assertFalse("Wrong canHandle result", bindingImpl.handleDecode("Redirect", httpReq)); + } + + @Test + public void wrongPostBindingEncoding() throws MessageDecodingException, SecurityException, + IOException, Pvp2MetadataException { + final String serviceUrl = "https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp2/post"; + + final IPvp2MetadataProvider metadataProvider = + metadataResolverFactory.createMetadataProvider( + "classpath:/data/pvp_metadata_wrong_sig.xml", null, "jUnit metadata resolver", null); + + final URIComparator comparator = new EaafUriCompare(serviceUrl); + + final String b64AuthnReq = Base64.getEncoder().encodeToString(IOUtils.toByteArray( + PostBindingTest.class.getResourceAsStream("/data/AuthRequest_without_sig_1.xml"))); + httpReq.setMethod("POST"); + httpReq.addParameter("SAMLRequest", b64AuthnReq); + httpReq.setParameter("SAMLEncoding", RandomStringUtils.randomAlphabetic(5)); + + try { + bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, comparator); + Assert.fail("Missing signature not detected"); + + } catch (final Pvp2Exception e) { + Assert.assertEquals("Wrong errorCode", "internal.pvp.02", e.getErrorId()); + + } + + } + + @Test + public void decodeRequestWrongEndpoint() throws MessageDecodingException, SecurityException, + IOException, Pvp2MetadataException { + final String serviceUrl = "https://wrongEndpoint/pvp2/post"; + + final IPvp2MetadataProvider metadataProvider = + metadataResolverFactory.createMetadataProvider( + "classpath:/data/pvp_metadata_wrong_sig.xml", null, "jUnit metadata resolver", null); + + final URIComparator comparator = new EaafUriCompare(serviceUrl); + + final String b64AuthnReq = Base64.getEncoder().encodeToString(IOUtils.toByteArray( + PostBindingTest.class.getResourceAsStream("/data/AuthRequest_with_sig_1.xml"))); + httpReq.setMethod("POST"); + httpReq.addParameter("SAMLRequest", b64AuthnReq); + + try { + bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, comparator); + Assert.fail("Wrong http end-point not detected"); + + } catch (final Pvp2Exception e) { + Assert.assertEquals("Wrong errorCode", "internal.pvp.11", e.getErrorId()); + Assert.assertNotNull("Parameters null", e.getParams()); + Assert.assertEquals("Wrong numer of parameters", 1, e.getParams().length); + + + } + + } + + @Test + public void decodeRequestMissingSignature() throws MessageDecodingException, SecurityException, + IOException, Pvp2MetadataException { + final String serviceUrl = "https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp2/post"; + + final IPvp2MetadataProvider metadataProvider = + metadataResolverFactory.createMetadataProvider( + "classpath:/data/pvp_metadata_wrong_sig.xml", null, "jUnit metadata resolver", null); + + final URIComparator comparator = new EaafUriCompare(serviceUrl); + + final String b64AuthnReq = Base64.getEncoder().encodeToString(IOUtils.toByteArray( + PostBindingTest.class.getResourceAsStream("/data/AuthRequest_without_sig_1.xml"))); + httpReq.setMethod("POST"); + httpReq.addParameter("SAMLRequest", b64AuthnReq); + + try { + bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, comparator); + Assert.fail("Missing signature not detected"); + + } catch (final Pvp2Exception e) { + Assert.assertEquals("Wrong errorCode", "internal.pvp.02", e.getErrorId()); + + } + + } + + @Test + public void decodeRequestWrongSignature() throws MessageDecodingException, SecurityException, + IOException, Pvp2Exception { + final String serviceUrl = "https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp2/post"; + + final IPvp2MetadataProvider metadataProvider = + metadataResolverFactory.createMetadataProvider( + "classpath:/data/pvp_metadata_wrong_sig.xml", null, "jUnit metadata resolver", null); + + final URIComparator comparator = new EaafUriCompare(serviceUrl); + + final String b64AuthnReq = Base64.getEncoder().encodeToString(IOUtils.toByteArray( + PostBindingTest.class.getResourceAsStream("/data/AuthRequest_with_sig_1.xml"))); + httpReq.setMethod("POST"); + httpReq.addParameter("SAMLRequest", b64AuthnReq); + + try { + bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, comparator); + Assert.fail("Invalid signature not detected"); + + } catch (final Pvp2Exception e) { + org.springframework.util.Assert.isInstanceOf(SamlSigningException.class, e, "Wrong Exception type"); + Assert.assertEquals("Wrong errorCode", "internal.pvp.10", e.getErrorId()); + Assert.assertNotNull("No error params", e.getParams()); + Assert.assertEquals("Wrong param size", 1, e.getParams().length); + + } + + } + + @Test + public void decodeRequestMsgExpired() throws MessageDecodingException, SecurityException, IOException, Pvp2Exception { + final String serviceUrl = "https://eidas-test.bmi.gv.at/ms_connector/pvp/post"; + + final IPvp2MetadataProvider metadataProvider = + metadataResolverFactory.createMetadataProvider( + "classpath:/data/pvp_metadata_moaid_test.xml", null, "jUnit metadata resolver", null); + + final URIComparator comparator = new EaafUriCompare(serviceUrl); + + final String b64AuthnReq = new String(IOUtils.toByteArray( + PostBindingTest.class.getResourceAsStream("/data/AuthRequest_withsig_expired.b64")), "UTF-8"); + httpReq.setMethod("POST"); + httpReq.addParameter("SAMLRequest", b64AuthnReq); + + + try { + bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, comparator); + Assert.fail("Expired msg not detected"); + + } catch (final Pvp2Exception e) { + org.springframework.util.Assert.isInstanceOf(SamlMessageValidationException.class, e, "Wrong Exception type"); + Assert.assertEquals("Wrong errorCode", "internal.pvp.11", e.getErrorId()); + Assert.assertNotNull("No error params", e.getParams()); + Assert.assertEquals("Wrong param size", 1, e.getParams().length); + + } + + } + + @Test + public void decodeRequestSuccessMetadataReloadRequired() throws MessageDecodingException, SecurityException, + IOException, Pvp2Exception, CredentialsNotAvailableException, XMLParserException, UnmarshallingException { + final String serviceUrl = "http://testservice.org"; + + final String b64AuthnReq = generateSaml2AuthnRequest( + credentialProvider.getMetaDataSigningCredential()); + httpReq.setMethod("POST"); + httpReq.addParameter("SAMLRequest", b64AuthnReq); + + mockWebServer.enqueue(new MockResponse().setResponseCode(200) + .setBody(new String(IOUtils.toByteArray( + MetadataResolverTest.class.getResourceAsStream( + "/data/pvp_metadata_wrong_sig.xml")), "UTF-8")) + .setHeader("Content-Type", "text/xml")); + + mockWebServer.enqueue(new MockResponse().setResponseCode(200) + .setBody(new String(IOUtils.toByteArray( + MetadataResolverTest.class.getResourceAsStream( + "/data/pvp_metadata_junit_keystore.xml")), "UTF-8")) + .setHeader("Content-Type", "text/xml")); + + final IPvp2MetadataProvider metadataProvider = + metadataResolverFactory.createMetadataProvider( + mockServerUrl.url().toString(), + null, "jUnit test", httpClientFactory.getHttpClient()); + + final URIComparator comparator = new EaafUriCompare(serviceUrl); + + + final InboundMessageInterface msg = + bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, comparator); + + Assert.assertNotNull("PVP msg is null", msg); + Assert.assertNull("RelayState not null", msg.getRelayState()); + Assert.assertNotNull("AuthnReq is null", msg.getInboundMessage()); + Assert.assertNotNull("EntityId is null", msg.getEntityID()); + Assert.assertEquals("EntityId not match", "https://demo.egiz.gv.at/demoportal_demologin/", msg.getEntityID()); + Assert.assertTrue("Wrong isVerified flag", msg.isVerified()); + + } + + @Test + public void decodeRequestSuccessWithRelayStateRsaSig() throws MessageDecodingException, SecurityException, + IOException, Pvp2Exception, CredentialsNotAvailableException, XMLParserException, UnmarshallingException { + final String serviceUrl = "http://testservice.org"; + final String relayState = RandomStringUtils.randomAlphanumeric(10); + + final String b64AuthnReq = generateSaml2AuthnRequest( + credentialProvider.getMetaDataSigningCredential()); + httpReq.setMethod("POST"); + httpReq.addParameter("SAMLRequest", b64AuthnReq); + httpReq.addParameter("RelayState", relayState); + + final IPvp2MetadataProvider metadataProvider = + metadataResolverFactory.createMetadataProvider( + "classpath:/data/pvp_metadata_junit_keystore.xml", null, "jUnit metadata resolver", null); + + final URIComparator comparator = new EaafUriCompare(serviceUrl); + + final InboundMessageInterface msg = + bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, comparator); + + Assert.assertNotNull("PVP msg is null", msg); + Assert.assertNotNull("RelayState is not null", msg.getRelayState()); + Assert.assertEquals("RelayState not match", relayState, msg.getRelayState()); + Assert.assertNotNull("AuthnReq is null", msg.getInboundMessage()); + Assert.assertNotNull("EntityId is null", msg.getEntityID()); + Assert.assertEquals("EntityId not match", "https://demo.egiz.gv.at/demoportal_demologin/", msg.getEntityID()); + Assert.assertTrue("Wrong isVerified flag", msg.isVerified()); + + } + + @Test + public void decodeRequestSuccessWithRequestAttributes() throws MessageDecodingException, SecurityException, + IOException, Pvp2Exception, CredentialsNotAvailableException, XMLParserException, UnmarshallingException, MarshallingException { + final String serviceUrl = "https://eidas-test.bmi.gv.at/ms_connector/pvp/post"; + final String relayState = RandomStringUtils.randomAlphanumeric(10); + + final RequestAbstractType authnReq = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + PostBindingTest.class.getResourceAsStream("/data/eIDAS_connector_authn.xml")); + authnReq.setIssueInstant(DateTime.now()); + final Issuer issuer = Saml2Utils.createSamlObject(Issuer.class); + issuer.setValue("https://demo.egiz.gv.at/demoportal_demologin/"); + authnReq.setIssuer(issuer); + + final RequestAbstractType signedAuthn = Saml2Utils.signSamlObject(authnReq, credentialProvider.getMessageSigningCredential(), true); + final Element signedElement = XMLObjectSupport.getMarshaller(signedAuthn).marshall(signedAuthn); + final String b64AuthnReq = + Base64.getEncoder().encodeToString(SerializeSupport.nodeToString(signedElement).getBytes("UTF-8")); + httpReq.setMethod("POST"); + httpReq.addParameter("SAMLRequest", b64AuthnReq); + httpReq.addParameter("RelayState", relayState); + + final IPvp2MetadataProvider metadataProvider = + metadataResolverFactory.createMetadataProvider( + "classpath:/data/pvp_metadata_junit_keystore.xml", null, "jUnit metadata resolver", null); + + final URIComparator comparator = new EaafUriCompare(serviceUrl); + + final InboundMessageInterface msg = + bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, comparator); + + Assert.assertNotNull("PVP msg is null", msg); + Assert.assertNotNull("RelayState is not null", msg.getRelayState()); + Assert.assertEquals("RelayState not match", relayState, msg.getRelayState()); + Assert.assertNotNull("AuthnReq is null", msg.getInboundMessage()); + Assert.assertNotNull("EntityId is null", msg.getEntityID()); + Assert.assertEquals("EntityId not match", "https://demo.egiz.gv.at/demoportal_demologin/", msg.getEntityID()); + Assert.assertTrue("Wrong isVerified flag", msg.isVerified()); + + org.springframework.util.Assert.isInstanceOf(PvpSProfileRequest.class, msg, "Inbound message is of wrong type"); + org.springframework.util.Assert.isInstanceOf(AuthnRequest.class, ((PvpSProfileRequest)msg).getSamlRequest(), + "Inbound message is of wrong type"); + + final AuthnRequest parsedAuthnReq = (AuthnRequest)((PvpSProfileRequest)msg).getSamlRequest(); + Assert.assertNotNull("No extension", parsedAuthnReq.getExtensions()); + Assert.assertNotNull("No extension child", parsedAuthnReq.getExtensions().getUnknownXMLObjects()); + Assert.assertEquals("extension child size", 1, parsedAuthnReq.getExtensions().getUnknownXMLObjects().size()); + + final XMLObject reqAttrs = parsedAuthnReq.getExtensions().getUnknownXMLObjects().get(0); + org.springframework.util.Assert.isInstanceOf(EaafRequestedAttributes.class, reqAttrs, "Wrong requested Attributes type"); + final EaafRequestedAttributes eaafReqAttrs = (EaafRequestedAttributes) reqAttrs; + Assert.assertNotNull("Req attr is null", eaafReqAttrs.getAttributes()); + Assert.assertFalse("Req attr is empty", eaafReqAttrs.getAttributes().isEmpty()); + Assert.assertEquals("Req attr size", 1, eaafReqAttrs.getAttributes().size()); + + final EaafRequestedAttribute eaafReqAttr = eaafReqAttrs.getAttributes().get(0); + Assert.assertNotNull("Req Attibute is null", eaafReqAttr); + Assert.assertEquals("Req. Attr. Friendlyname", "EID-SECTOR-FOR-IDENTIFIER", eaafReqAttr.getFriendlyName()); + Assert.assertEquals("Req. Attr. Name", "urn:oid:1.2.40.0.10.2.1.1.261.34", eaafReqAttr.getName()); + + Assert.assertEquals("Req. Attr. Value size", 1, eaafReqAttr.getAttributeValues().size()); + org.springframework.util.Assert.isInstanceOf(XSString.class, eaafReqAttr.getAttributeValues().get(0), + "Wrong requested Attributes Value type"); + Assert.assertEquals("Req. Attr. Value", "urn:publicid:gv.at:cdid+BF", ((XSString)eaafReqAttr.getAttributeValues().get(0)).getValue()); + + } + + @Test + public void decodeRequestSuccessWithoutRelayStateEcdsaSig() throws MessageDecodingException, SecurityException, + IOException, Pvp2Exception, CredentialsNotAvailableException, XMLParserException, UnmarshallingException { + final String serviceUrl = "http://testservice.org"; + + final String b64AuthnReq = generateSaml2AuthnRequest( + credentialProvider.getMessageSigningCredential()); + httpReq.setMethod("POST"); + httpReq.addParameter("SAMLRequest", b64AuthnReq); + + + final IPvp2MetadataProvider metadataProvider = + metadataResolverFactory.createMetadataProvider( + "classpath:/data/pvp_metadata_junit_keystore.xml", null, "jUnit metadata resolver", null); + + final URIComparator comparator = new EaafUriCompare(serviceUrl); + + final InboundMessageInterface msg = + bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, comparator); + + Assert.assertNotNull("PVP msg is null", msg); + Assert.assertNull("RelayState is not null", msg.getRelayState()); + Assert.assertNotNull("AuthnReq is null", msg.getInboundMessage()); + Assert.assertNotNull("EntityId is null", msg.getEntityID()); + Assert.assertEquals("EntityId not match", "https://demo.egiz.gv.at/demoportal_demologin/", msg.getEntityID()); + Assert.assertTrue("Wrong isVerified flag", msg.isVerified()); + + //check if reconstraction from serialized form work well + ((InboundMessage)msg).setSamlMessage(null); + try { + Assert.assertNotNull("AuthnReq is null", msg.getInboundMessage()); + + } catch (final RuntimeException e) { } + + } + + @Test + public void decodeResponseSuccess() throws MessageDecodingException, SecurityException, + IOException, Pvp2Exception, CredentialsNotAvailableException, XMLParserException, UnmarshallingException { + final String serviceUrl = "http://testservice.org"; + + final IPvp2MetadataProvider metadataProvider = + metadataResolverFactory.createMetadataProvider( + "classpath:/data/pvp_metadata_junit_keystore.xml", null, "jUnit metadata resolver", null); + + final URIComparator comparator = new EaafUriCompare(serviceUrl); + + final String b64AuthnReq = generateSaml2Response(credentialProvider.getMetaDataSigningCredential()); + httpReq.setMethod("POST"); + httpReq.addParameter("SAMLRequest", b64AuthnReq); + + final InboundMessageInterface msg = + bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, comparator); + + Assert.assertNotNull("PVP msg is null", msg); + Assert.assertNull("RelayState is not null", msg.getRelayState()); + Assert.assertNotNull("Response is null", msg.getInboundMessage()); + Assert.assertNotNull("EntityId is null", msg.getEntityID()); + Assert.assertEquals("EntityId not match", "https://demo.egiz.gv.at/demoportal_demologin/", msg.getEntityID()); + Assert.assertTrue("Wrong isVerified flag", msg.isVerified()); + + org.springframework.util.Assert.isInstanceOf(PvpSProfileResponse.class, msg, "Inbound message is of wrong type"); + + } + + @Test + public void encodeRequestSuccess() throws MessageDecodingException, SecurityException, + MessageEncodingException, XMLParserException, UnmarshallingException, + CredentialsNotAvailableException, ParserConfigurationException, SAXException, IOException, Pvp2Exception { + //build test data + final String serviceUrl = "http://testservice.org"; + final String relayState = null; + guiBuilderFactory.setVelocityBuilderConfig(createDummyGuiConfig()); + final RequestAbstractType authnReq = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + PostBindingTest.class.getResourceAsStream("/data/AuthRequest_without_sig_1.xml")); + + bindingImpl.encodeRequest(httpReq, httpResp, authnReq, serviceUrl, relayState, + credentialProvider.getMetaDataSigningCredential(), pendingReq); + + //validate + Assert.assertEquals("http StatusCode", 200, httpResp.getStatus()); + Assert.assertNotNull("PVP msg is null", httpResp.getContentLength()); + + Assert.assertEquals("ContentType", "text/html", httpResp.getContentType()); + Assert.assertEquals("Encoding", "UTF-8", httpResp.getCharacterEncoding()); + + final String http = httpResp.getContentAsString(); + Assert.assertNotNull("http body is null", http); + Assert.assertFalse("http body is empty", http.isEmpty()); + + Assert.assertFalse("RelayState parameter", http.contains(HTTP_FORM_RELAYSTATE)); + + Assert.assertTrue("SAMLRequest parameter", http.contains(HTTP_FORM_SAMLREQ)); + final String httpSamlReq = extractParamFromHttpForm(http, HTTP_FORM_SAMLREQ); + checkSamlMessageSigned(httpSamlReq); + + } + + @Test + public void encodeRequestSuccessEcdsa() throws MessageDecodingException, SecurityException, + MessageEncodingException, XMLParserException, UnmarshallingException, + CredentialsNotAvailableException, ParserConfigurationException, SAXException, IOException, Pvp2Exception { + //build test data + final String serviceUrl = "http://testservice.org"; + final String relayState = null; + guiBuilderFactory.setVelocityBuilderConfig(createDummyGuiConfig()); + final RequestAbstractType authnReq = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + PostBindingTest.class.getResourceAsStream("/data/AuthRequest_without_sig_1.xml")); + + bindingImpl.encodeRequest(httpReq, httpResp, authnReq, serviceUrl, relayState, + credentialProvider.getMessageSigningCredential(), pendingReq); + + //validate + Assert.assertEquals("http StatusCode", 200, httpResp.getStatus()); + Assert.assertNotNull("PVP msg is null", httpResp.getContentLength()); + + Assert.assertEquals("ContentType", "text/html", httpResp.getContentType()); + Assert.assertEquals("Encoding", "UTF-8", httpResp.getCharacterEncoding()); + + final String http = httpResp.getContentAsString(); + Assert.assertNotNull("http body is null", http); + Assert.assertFalse("http body is empty", http.isEmpty()); + + Assert.assertFalse("RelayState parameter", http.contains(HTTP_FORM_RELAYSTATE)); + + Assert.assertTrue("SAMLRequest parameter", http.contains(HTTP_FORM_SAMLREQ)); + final String httpSamlReq = extractParamFromHttpForm(http, HTTP_FORM_SAMLREQ); + checkSamlMessageSigned(httpSamlReq); + + } + + @Test + public void encodeRequestSuccessWithRelayState() throws MessageDecodingException, SecurityException, + MessageEncodingException, XMLParserException, UnmarshallingException, + CredentialsNotAvailableException, ParserConfigurationException, SAXException, IOException, Pvp2Exception { + + //build test data + final String serviceUrl = "http://testservice.org"; + final String relayState = RandomStringUtils.randomAlphabetic(10); + guiBuilderFactory.setVelocityBuilderConfig(createDummyGuiConfig()); + final RequestAbstractType authnReq = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + PostBindingTest.class.getResourceAsStream("/data/AuthRequest_without_sig_1.xml")); + + bindingImpl.encodeRequest(httpReq, httpResp, authnReq, serviceUrl, relayState, + credentialProvider.getMetaDataSigningCredential(), pendingReq); + + + //validate + Assert.assertEquals("http StatusCode", 200, httpResp.getStatus()); + Assert.assertNotNull("PVP msg is null", httpResp.getContentLength()); + + Assert.assertEquals("ContentType", "text/html", httpResp.getContentType()); + Assert.assertEquals("Encoding", "UTF-8", httpResp.getCharacterEncoding()); + + final String http = httpResp.getContentAsString(); + Assert.assertNotNull("http body is null", http); + Assert.assertFalse("http body is empty", http.isEmpty()); + + Assert.assertTrue("RelayState parameter", http.contains(HTTP_FORM_RELAYSTATE)); + final String httpRelayState = extractParamFromHttpForm(http, HTTP_FORM_RELAYSTATE); + Assert.assertEquals("Wrong RelayState", relayState, httpRelayState); + + Assert.assertTrue("SAMLRequest parameter", http.contains(HTTP_FORM_SAMLREQ)); + final String httpSamlReq = extractParamFromHttpForm(http, HTTP_FORM_SAMLREQ); + checkSamlMessageSigned(httpSamlReq); + + } + + @Test + public void encodeResponseSuccessWithRelayState() throws MessageDecodingException, SecurityException, + MessageEncodingException, XMLParserException, UnmarshallingException, + CredentialsNotAvailableException, ParserConfigurationException, SAXException, IOException, Pvp2Exception { + + //build test data + final String serviceUrl = "http://testservice.org"; + final String relayState = RandomStringUtils.randomAlphabetic(10); + guiBuilderFactory.setVelocityBuilderConfig(createDummyGuiConfig()); + final StatusResponseType authnReq = (StatusResponseType) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + PostBindingTest.class.getResourceAsStream("/data/Response_without_sig_1.xml")); + + bindingImpl.encodeResponse(httpReq, httpResp, authnReq, serviceUrl, relayState, + credentialProvider.getMetaDataSigningCredential(), pendingReq); + + + //validate + Assert.assertEquals("http StatusCode", 200, httpResp.getStatus()); + Assert.assertNotNull("PVP msg is null", httpResp.getContentLength()); + + Assert.assertEquals("ContentType", "text/html", httpResp.getContentType()); + Assert.assertEquals("Encoding", "UTF-8", httpResp.getCharacterEncoding()); + + final String http = httpResp.getContentAsString(); + Assert.assertNotNull("http body is null", http); + Assert.assertFalse("http body is empty", http.isEmpty()); + + Assert.assertTrue("RelayState parameter", http.contains(HTTP_FORM_RELAYSTATE)); + final String httpRelayState = extractParamFromHttpForm(http, HTTP_FORM_RELAYSTATE); + Assert.assertEquals("Wrong RelayState", relayState, httpRelayState); + + Assert.assertTrue("SAMLRequest parameter", http.contains(HTTP_FORM_SAMLRESP)); + final String httpSamlReq = extractParamFromHttpForm(http, HTTP_FORM_SAMLRESP); + checkSamlMessageSigned(httpSamlReq); + + } + + @Test + public void encodeResponseSuccess() throws MessageDecodingException, SecurityException, + MessageEncodingException, XMLParserException, UnmarshallingException, + CredentialsNotAvailableException, ParserConfigurationException, SAXException, IOException, Pvp2Exception { + + //build test data + final String serviceUrl = "http://testservice.org"; + final String relayState = null; + guiBuilderFactory.setVelocityBuilderConfig(createDummyGuiConfig()); + final StatusResponseType authnReq = (StatusResponseType) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + PostBindingTest.class.getResourceAsStream("/data/Response_without_sig_1.xml")); + + bindingImpl.encodeResponse(httpReq, httpResp, authnReq, serviceUrl, relayState, + credentialProvider.getMetaDataSigningCredential(), pendingReq); + + + //validate + Assert.assertEquals("http StatusCode", 200, httpResp.getStatus()); + Assert.assertNotNull("PVP msg is null", httpResp.getContentLength()); + + Assert.assertEquals("ContentType", "text/html", httpResp.getContentType()); + Assert.assertEquals("Encoding", "UTF-8", httpResp.getCharacterEncoding()); + + final String http = httpResp.getContentAsString(); + Assert.assertNotNull("http body is null", http); + Assert.assertFalse("http body is empty", http.isEmpty()); + + Assert.assertFalse("RelayState parameter", http.contains(HTTP_FORM_RELAYSTATE)); + + Assert.assertTrue("SAMLRequest parameter", http.contains(HTTP_FORM_SAMLRESP)); + final String httpSamlReq = extractParamFromHttpForm(http, HTTP_FORM_SAMLRESP); + checkSamlMessageSigned(httpSamlReq); + + } + + private IVelocityGuiBuilderConfiguration createDummyGuiConfig() { + return new IVelocityGuiBuilderConfiguration() { + + @Override + public Map<String, Object> getViewParameters() { + return null; + } + + @Override + public String getViewName() { + return "SAML2 Post-Binding"; + } + + @Override + public String getDefaultContentType() { + return null; + } + + @Override + public InputStream getTemplate(String viewName) { + return PostBindingTest.class.getResourceAsStream("/data/pvp_postbinding_template.html"); + } + + @Override + public String getClasspathTemplateDir() { + return null; + + } + }; + } + + private void checkSamlMessageSigned(String b64Msg) throws ParserConfigurationException, + SAXException, IOException, UnmarshallingException { + final Element httpSamlReqElment = DomUtils.parseXmlNonValidating( + new ByteArrayInputStream(Base64.getDecoder().decode(b64Msg))); + + final UnmarshallerFactory unmarshallerFactory = XMLObjectProviderRegistrySupport.getUnmarshallerFactory(); + final Unmarshaller unmarshaller = unmarshallerFactory.getUnmarshaller(httpSamlReqElment); + final SignableSAMLObject msg = (SignableSAMLObject) unmarshaller.unmarshall(httpSamlReqElment); + Assert.assertTrue("SAML msg not signed", msg.isSigned()); + + } + + private String extractParamFromHttpForm(String http, String httpFormRelaystate) { + final int startIndex = http.indexOf(httpFormRelaystate) + httpFormRelaystate.length(); + final int endIndex = http.indexOf("\"", startIndex); + return http.substring(startIndex, endIndex); + + } + + private String generateSaml2AuthnRequest(EaafX509Credential credentials) + throws XMLParserException, UnmarshallingException, Pvp2Exception, CredentialsNotAvailableException, + UnsupportedEncodingException { + final MockHttpServletRequest intHttpReq = new MockHttpServletRequest(); + final MockHttpServletResponse intHttpResp = new MockHttpServletResponse(); + guiBuilderFactory.setVelocityBuilderConfig(createDummyGuiConfig()); + final RequestAbstractType authnReq = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + PostBindingTest.class.getResourceAsStream("/data/AuthRequest_without_sig_1.xml")); + authnReq.setIssueInstant(DateTime.now()); + + bindingImpl.encodeRequest(intHttpReq, intHttpResp, authnReq, "http://testservice.org", null, + credentials, pendingReq); + + Assert.assertEquals("http StatusCode", 200, intHttpResp.getStatus()); + final String http = intHttpResp.getContentAsString(); + Assert.assertNotNull("http body is null", http); + Assert.assertTrue("SAMLRequest parameter", http.contains(HTTP_FORM_SAMLREQ)); + return extractParamFromHttpForm(http, HTTP_FORM_SAMLREQ); + + } + + private String generateSaml2Response(EaafX509Credential credentials) + throws XMLParserException, UnmarshallingException, Pvp2Exception, CredentialsNotAvailableException, + UnsupportedEncodingException { + final MockHttpServletRequest intHttpReq = new MockHttpServletRequest(); + final MockHttpServletResponse intHttpResp = new MockHttpServletResponse(); + guiBuilderFactory.setVelocityBuilderConfig(createDummyGuiConfig()); + final StatusResponseType response = (StatusResponseType) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + PostBindingTest.class.getResourceAsStream("/data/Response_without_sig_1.xml")); + response.setIssueInstant(DateTime.now()); + + bindingImpl.encodeResponse(intHttpReq, intHttpResp, response, "http://testservice.org", null, + credentials, pendingReq); + + Assert.assertEquals("http StatusCode", 200, intHttpResp.getStatus()); + final String http = intHttpResp.getContentAsString(); + Assert.assertNotNull("http body is null", http); + Assert.assertTrue("SAMLRequest parameter", http.contains(HTTP_FORM_SAMLRESP)); + return extractParamFromHttpForm(http, HTTP_FORM_SAMLRESP); + + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/binding/RedirectBindingTest.java b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/binding/RedirectBindingTest.java new file mode 100644 index 00000000..37e4acd1 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/binding/RedirectBindingTest.java @@ -0,0 +1,854 @@ +package at.gv.egiz.eaaf.modules.pvp2.test.binding; + +import java.io.IOException; +import java.net.URLDecoder; + +import javax.xml.parsers.ParserConfigurationException; + +import at.gv.egiz.eaaf.core.api.IRequest; +import at.gv.egiz.eaaf.core.impl.idp.module.test.TestRequestImpl; +import at.gv.egiz.eaaf.core.impl.utils.IHttpClientFactory; +import at.gv.egiz.eaaf.modules.pvp2.PvpConstants; +import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential; +import at.gv.egiz.eaaf.modules.pvp2.api.message.InboundMessageInterface; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2MetadataException; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlMessageValidationException; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlSigningException; +import at.gv.egiz.eaaf.modules.pvp2.impl.binding.RedirectBinding; +import at.gv.egiz.eaaf.modules.pvp2.impl.metadata.PvpMetadataResolverFactory; +import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafOpenSaml3xInitializer; +import at.gv.egiz.eaaf.modules.pvp2.impl.validation.EaafUriCompare; +import at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyCredentialProvider; +import at.gv.egiz.eaaf.modules.pvp2.test.metadata.MetadataResolverTest; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.RandomStringUtils; +import org.joda.time.DateTime; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport; +import org.opensaml.core.xml.io.UnmarshallingException; +import org.opensaml.core.xml.util.XMLObjectSupport; +import org.opensaml.messaging.decoder.MessageDecodingException; +import org.opensaml.messaging.encoder.MessageEncodingException; +import org.opensaml.saml.saml2.core.RequestAbstractType; +import org.opensaml.saml.saml2.core.StatusResponseType; +import org.opensaml.saml.saml2.metadata.SPSSODescriptor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.xml.sax.SAXException; + +import net.shibboleth.utilities.java.support.net.URIComparator; +import net.shibboleth.utilities.java.support.net.URISupport; +import net.shibboleth.utilities.java.support.xml.XMLParserException; +import okhttp3.HttpUrl; +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration({ "/spring/test_eaaf_pvp.beans.xml", + "/spring/test_eaaf_core_spring_config.beans.xml", + "/spring/eaaf_utils.beans.xml" }) +@TestPropertySource(locations = { "/config/config_1.props" }) +public class RedirectBindingTest { + + public static final String HTTP_FORM_RELAYSTATE = "RelayState"; + public static final String HTTP_FORM_RELAYSTATE_PARAM = HTTP_FORM_RELAYSTATE + "="; + + public static final String HTTP_FORM_SAMLREQ = "SAMLRequest"; + public static final String HTTP_FORM_SAMLREQ_PARAM = HTTP_FORM_SAMLREQ + "="; + public static final String HTTP_FORM_SAMLRESP = "SAMLResponse"; + public static final String HTTP_FORM_SAMLRESP_PARM = HTTP_FORM_SAMLRESP + "="; + + public static final String HTTP_REDIRECT_SIGALG = "SigAlg"; + public static final String HTTP_REDIRECT_SIGALG_PARAM = HTTP_REDIRECT_SIGALG + "="; + public static final String HTTP_REDIRECT_SIGNATURE = "Signature"; + public static final String HTTP_REDIRECT_SIGNATURE_PARAM = HTTP_REDIRECT_SIGNATURE + "="; + + @Autowired + private RedirectBinding bindingImpl; + @Autowired + private DummyCredentialProvider credentialProvider; + @Autowired + private PvpMetadataResolverFactory metadataResolverFactory; + @Autowired private IHttpClientFactory httpClientFactory; + + private static MockWebServer mockWebServer; + private static HttpUrl mockServerUrl; + + protected MockHttpServletRequest httpReq; + protected MockHttpServletResponse httpResp; + protected IRequest pendingReq; + + /** + * JUnit class initializer. + * + * @throws Exception In case of an OpenSAML3 initialization error + */ + @BeforeClass + public static void classInitializer() throws Exception { + EaafOpenSaml3xInitializer.eaafInitialize(); + + mockWebServer = new MockWebServer(); + mockServerUrl = mockWebServer.url("/sp/metadata"); + } + + /** + * Test initializer. + * + */ + @Before + public void initialize() { + httpReq = new MockHttpServletRequest(); + httpResp = new MockHttpServletResponse(); + + pendingReq = new TestRequestImpl(); + + } + + @Test + public void checkCanHandle() { + httpReq.setMethod("POST"); + Assert.assertFalse("Wrong canHandle result", bindingImpl.handleDecode("Post", httpReq)); + Assert.assertFalse("Wrong canHandle result", bindingImpl.handleDecode("Redirect", httpReq)); + + httpReq.setMethod("GET"); + Assert.assertFalse("Wrong canHandle result", bindingImpl.handleDecode("Post", httpReq)); + Assert.assertTrue("Wrong canHandle result", bindingImpl.handleDecode("Redirect", httpReq)); + } + + @Test + public void wrongHttpRequestMethod() throws MessageDecodingException, + SecurityException, IOException, Pvp2MetadataException { + final String serviceUrl = "http://testservice.org"; + + final IPvp2MetadataProvider metadataProvider = + metadataResolverFactory.createMetadataProvider( + "classpath:/data/pvp_metadata_wrong_sig.xml", null, "jUnit metadata resolver", null); + + final URIComparator comparator = new EaafUriCompare(serviceUrl); + + httpReq.setMethod("POST"); + httpReq.setRequestURI("http://testservice.org"); + httpReq.setQueryString("SAMLRequest=nVRNb9swDD13wP6DoXvkr%2FRjQuzCSFAgQDd0TbfDLoVi0642Wcok2kn766c4duABWw%" + + "2B%2BSdQj%2BfhIanF7qKXXgrFCq4SENCAeqFwXQlUJ%2BfZ0N7sht%2BnC8lpGO5Y1%2BKIe4XcDFj3nqCw7vSSkMYppboVli" + + "tdgGeZsk32%2BZxEN2M5o1LmWxMusBYMu1VIr29RgNmBakcNaFXBw6R0C0Yhtg3BCOBp%2FQxy%2FlcsuFMeO8Qvijvk%2BOps" + + "9Aak2FfHWq4Q8c4BtySHO4eomLCEuipyXURjzeVQGYRE7mLWNC22RK0xIFITzWRDPgsun4IrFn1gQ0evryx%2FE%2Bz4o5Oohv" + + "R6sczZjId7XgQ%2FVE%2B9Om5rj%2B%2FCjRRSzsoMyUCjwlaTHgq2ruIBaU6jEG61ayrG777RBLp%2BPR6krofyFP2Y68N402" + + "5%2BQ4xTi6ccPFxd9mC8Ot15NI9T7umiDpSd1nrUT4kFLkb96mZR6vzTAERKCpoEpCu6OPbTohCRThtc%2FU%2Bs3AIpuH9ygI" + + "hwm7cNYzXGspXSKP0I5qUP9Ruz3e2pRm1%2B00i2Fxne77ecCxRuor1l2Dy1Ifz6o%2F6%2Fso%2B78p%2Bb0%2FDz%2BGdI%2" + + "F&SigAlg=http%3A%2F%2Fwww.w3.org%2F2001%2F04%2Fxmldsig-more%23rsa-sha256&Signature=DOVMqh17xn4wl%2" + + "Byvifm4McMsBjKDVf1eqph9ss362ZEbp2nkAIXUzkNWv72I96iNK3r%2BYbAxY9dwZ8Z7jKzCGiJ9Qm34YSfPvzXWl3EVrdI86" + + "9U%2BH6HGIMqVew3cVdr4q3Qv9ZBIhdRxbrDu%2F%2BnMjdf8mzbgcQnfjSQiQIYWxOIXZFyxKsyrxJtIam4hoNwUT7mMN6Rjg" + + "zvyeS3mARsTJdcI0Vn4ItiprhLgIkD18V9WIdeSZR0gfRaFj8PKdmXCD%2FIa0cKgjhVKoiIZisV4vcthBOeDIqBORL2Ad3Xhc" + + "NRQ3%2BcpAf65zHGMBAv1aRy7Bmv0%2B%2BOvCavufykqI2EHtg%3D%3D"); + + httpReq.setParameter(HTTP_FORM_SAMLREQ, URLDecoder.decode(URISupport.getRawQueryStringParameter( + httpReq.getQueryString(), HTTP_FORM_SAMLREQ).substring(HTTP_FORM_SAMLREQ_PARAM.length()), "UTF-8")); + httpReq.setParameter(HTTP_REDIRECT_SIGALG, URLDecoder.decode(URISupport.getRawQueryStringParameter( + httpReq.getQueryString(), HTTP_REDIRECT_SIGALG).substring(HTTP_REDIRECT_SIGALG_PARAM.length()), + "UTF-8")); + + try { + bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, + comparator); + Assert.fail("Missing signature not detected"); + + } catch (final Pvp2Exception e) { + Assert.assertEquals("Wrong errorCode", "internal.pvp.95", e.getErrorId()); + + } + } + + @Test + public void wrongRedirectBindingType() throws MessageDecodingException, + SecurityException, IOException, Pvp2MetadataException { + final String serviceUrl = "http://testservice.org"; + + final IPvp2MetadataProvider metadataProvider = + metadataResolverFactory.createMetadataProvider( + "classpath:/data/pvp_metadata_wrong_sig.xml", null, "jUnit metadata resolver", null); + + final URIComparator comparator = new EaafUriCompare(serviceUrl); + + httpReq.setMethod("POST"); + httpReq.setRequestURI("http://testservice.org"); + httpReq.setQueryString("SAMLRequest=nVRNb9swDD13wP6DoXvkr%2FRjQuzCSFAgQDd0TbfDLoVi0642Wcok2kn766c4duABWw%" + + "2B%2BSdQj%2BfhIanF7qKXXgrFCq4SENCAeqFwXQlUJ%2BfZ0N7sht%2BnC8lpGO5Y1%2BKIe4XcDFj3nqCw7vSSkMYppboVli" + + "tdgGeZsk32%2BZxEN2M5o1LmWxMusBYMu1VIr29RgNmBakcNaFXBw6R0C0Yhtg3BCOBp%2FQxy%2FlcsuFMeO8Qvijvk%2BOps" + + "9Aak2FfHWq4Q8c4BtySHO4eomLCEuipyXURjzeVQGYRE7mLWNC22RK0xIFITzWRDPgsun4IrFn1gQ0evryx%2FE%2Bz4o5Oohv" + + "R6sczZjId7XgQ%2FVE%2B9Om5rj%2B%2FCjRRSzsoMyUCjwlaTHgq2ruIBaU6jEG61ayrG777RBLp%2BPR6krofyFP2Y68N402" + + "5%2BQ4xTi6ccPFxd9mC8Ot15NI9T7umiDpSd1nrUT4kFLkb96mZR6vzTAERKCpoEpCu6OPbTohCRThtc%2FU%2Bs3AIpuH9ygI" + + "hwm7cNYzXGspXSKP0I5qUP9Ruz3e2pRm1%2B00i2Fxne77ecCxRuor1l2Dy1Ifz6o%2F6%2Fso%2B78p%2Bb0%2FDz%2BGdI%2" + + "F&SigAlg=http%3A%2F%2Fwww.w3.org%2F2001%2F04%2Fxmldsig-more%23rsa-sha256&Signature=DOVMqh17xn4wl%2" + + "Byvifm4McMsBjKDVf1eqph9ss362ZEbp2nkAIXUzkNWv72I96iNK3r%2BYbAxY9dwZ8Z7jKzCGiJ9Qm34YSfPvzXWl3EVrdI86" + + "9U%2BH6HGIMqVew3cVdr4q3Qv9ZBIhdRxbrDu%2F%2BnMjdf8mzbgcQnfjSQiQIYWxOIXZFyxKsyrxJtIam4hoNwUT7mMN6Rjg" + + "zvyeS3mARsTJdcI0Vn4ItiprhLgIkD18V9WIdeSZR0gfRaFj8PKdmXCD%2FIa0cKgjhVKoiIZisV4vcthBOeDIqBORL2Ad3Xhc" + + "NRQ3%2BcpAf65zHGMBAv1aRy7Bmv0%2B%2BOvCavufykqI2EHtg%3D%3D"); + + httpReq.setParameter(HTTP_FORM_SAMLREQ, URLDecoder.decode(URISupport.getRawQueryStringParameter( + httpReq.getQueryString(), HTTP_FORM_SAMLREQ).substring(HTTP_FORM_SAMLREQ_PARAM.length()), "UTF-8")); + httpReq.setParameter(HTTP_REDIRECT_SIGALG, URLDecoder.decode(URISupport.getRawQueryStringParameter( + httpReq.getQueryString(), HTTP_REDIRECT_SIGALG).substring(HTTP_REDIRECT_SIGALG_PARAM.length()), + "UTF-8")); + httpReq.setParameter("SAMLEncoding", RandomStringUtils.randomAlphabetic(5)); + + try { + bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, + comparator); + Assert.fail("Missing signature not detected"); + + } catch (final Pvp2Exception e) { + Assert.assertEquals("Wrong errorCode", "internal.pvp.95", e.getErrorId()); + + } + } + + @Test + public void decodeRequestNoSignature() throws MessageDecodingException, + SecurityException, IOException, Pvp2MetadataException { + final String serviceUrl = "http://testservice.org"; + + final IPvp2MetadataProvider metadataProvider = + metadataResolverFactory.createMetadataProvider( + "classpath:/data/pvp_metadata_wrong_sig.xml", null, "jUnit metadata resolver", null); + + final URIComparator comparator = new EaafUriCompare(serviceUrl); + + httpReq.setMethod("GET"); + httpReq.setRequestURI("http://testservice.org"); + httpReq.setQueryString("SAMLRequest=nVRNb9swDD13wP6DoXvkr%2FRjQuzCSFAgQDd0TbfDLoVi0642Wcok2kn766c4duABWw%" + + "2B%2BSdQj%2BfhIanF7qKXXgrFCq4SENCAeqFwXQlUJ%2BfZ0N7sht%2BnC8lpGO5Y1%2BKIe4XcDFj3nqCw7vSSkMYppboVli" + + "tdgGeZsk32%2BZxEN2M5o1LmWxMusBYMu1VIr29RgNmBakcNaFXBw6R0C0Yhtg3BCOBp%2FQxy%2FlcsuFMeO8Qvijvk%2BOps" + + "9Aak2FfHWq4Q8c4BtySHO4eomLCEuipyXURjzeVQGYRE7mLWNC22RK0xIFITzWRDPgsun4IrFn1gQ0evryx%2FE%2Bz4o5Oohv" + + "R6sczZjId7XgQ%2FVE%2B9Om5rj%2B%2FCjRRSzsoMyUCjwlaTHgq2ruIBaU6jEG61ayrG777RBLp%2BPR6krofyFP2Y68N402" + + "5%2BQ4xTi6ccPFxd9mC8Ot15NI9T7umiDpSd1nrUT4kFLkb96mZR6vzTAERKCpoEpCu6OPbTohCRThtc%2FU%2Bs3AIpuH9ygI" + + "hwm7cNYzXGspXSKP0I5qUP9Ruz3e2pRm1%2B00i2Fxne77ecCxRuor1l2Dy1Ifz6o%2F6%2Fso%2B78p%2Bb0%2FDz%2BGdI%2" + + "F&SigAlg=http%3A%2F%2Fwww.w3.org%2F2001%2F04%2Fxmldsig-more%23rsa-sha256&Signature=DOVMqh17xn4wl%2" + + "Byvifm4McMsBjKDVf1eqph9ss362ZEbp2nkAIXUzkNWv72I96iNK3r%2BYbAxY9dwZ8Z7jKzCGiJ9Qm34YSfPvzXWl3EVrdI86" + + "9U%2BH6HGIMqVew3cVdr4q3Qv9ZBIhdRxbrDu%2F%2BnMjdf8mzbgcQnfjSQiQIYWxOIXZFyxKsyrxJtIam4hoNwUT7mMN6Rjg" + + "zvyeS3mARsTJdcI0Vn4ItiprhLgIkD18V9WIdeSZR0gfRaFj8PKdmXCD%2FIa0cKgjhVKoiIZisV4vcthBOeDIqBORL2Ad3Xhc" + + "NRQ3%2BcpAf65zHGMBAv1aRy7Bmv0%2B%2BOvCavufykqI2EHtg%3D%3D"); + + httpReq.setParameter(HTTP_FORM_SAMLREQ, URLDecoder.decode(URISupport.getRawQueryStringParameter( + httpReq.getQueryString(), HTTP_FORM_SAMLREQ).substring(HTTP_FORM_SAMLREQ_PARAM.length()), "UTF-8")); + httpReq.setParameter(HTTP_REDIRECT_SIGALG, URLDecoder.decode(URISupport.getRawQueryStringParameter( + httpReq.getQueryString(), HTTP_REDIRECT_SIGALG).substring(HTTP_REDIRECT_SIGALG_PARAM.length()), + "UTF-8")); + + try { + bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, + comparator); + Assert.fail("Missing signature not detected"); + + } catch (final Pvp2Exception e) { + Assert.assertEquals("Wrong errorCode", "internal.pvp.02", e.getErrorId()); + + } + } + + @Test + public void decodeRequestWrongEndpoint() throws MessageDecodingException, + SecurityException, IOException, Pvp2Exception { + final String serviceUrl = "http://wrongEndPoint.org"; + + final IPvp2MetadataProvider metadataProvider = + metadataResolverFactory.createMetadataProvider( + "classpath:/data/pvp_metadata_wrong_sig.xml", null, "jUnit metadata resolver", null); + + final URIComparator comparator = new EaafUriCompare(serviceUrl); + + httpReq.setMethod("GET"); + httpReq.setRequestURI("http://testservice.org"); + httpReq.setQueryString("SAMLRequest=nVRNb9swDD13wP6DoXvkr%2FRjQuzCSFAgQDd0TbfDLoVi0642Wcok2kn766c4duABWw%" + + "2B%2BSdQj%2BfhIanF7qKXXgrFCq4SENCAeqFwXQlUJ%2BfZ0N7sht%2BnC8lpGO5Y1%2BKIe4XcDFj3nqCw7vSSkMYppboVli" + + "tdgGeZsk32%2BZxEN2M5o1LmWxMusBYMu1VIr29RgNmBakcNaFXBw6R0C0Yhtg3BCOBp%2FQxy%2FlcsuFMeO8Qvijvk%2BOps" + + "9Aak2FfHWq4Q8c4BtySHO4eomLCEuipyXURjzeVQGYRE7mLWNC22RK0xIFITzWRDPgsun4IrFn1gQ0evryx%2FE%2Bz4o5Oohv" + + "R6sczZjId7XgQ%2FVE%2B9Om5rj%2B%2FCjRRSzsoMyUCjwlaTHgq2ruIBaU6jEG61ayrG777RBLp%2BPR6krofyFP2Y68N402" + + "5%2BQ4xTi6ccPFxd9mC8Ot15NI9T7umiDpSd1nrUT4kFLkb96mZR6vzTAERKCpoEpCu6OPbTohCRThtc%2FU%2Bs3AIpuH9ygI" + + "hwm7cNYzXGspXSKP0I5qUP9Ruz3e2pRm1%2B00i2Fxne77ecCxRuor1l2Dy1Ifz6o%2F6%2Fso%2B78p%2Bb0%2FDz%2BGdI%2" + + "F&SigAlg=http%3A%2F%2Fwww.w3.org%2F2001%2F04%2Fxmldsig-more%23rsa-sha256&Signature=DOVMqh17xn4wl%2" + + "Byvifm4McMsBjKDVf1eqph9ss362ZEbp2nkAIXUzkNWv72I96iNK3r%2BYbAxY9dwZ8Z7jKzCGiJ9Qm34YSfPvzXWl3EVrdI86" + + "9U%2BH6HGIMqVew3cVdr4q3Qv9ZBIhdRxbrDu%2F%2BnMjdf8mzbgcQnfjSQiQIYWxOIXZFyxKsyrxJtIam4hoNwUT7mMN6Rjg" + + "zvyeS3mARsTJdcI0Vn4ItiprhLgIkD18V9WIdeSZR0gfRaFj8PKdmXCD%2FIa0cKgjhVKoiIZisV4vcthBOeDIqBORL2Ad3Xhc" + + "NRQ3%2BcpAf65zHGMBAv1aRy7Bmv0%2B%2BOvCavufykqI2EHtg%3D%3D"); + + httpReq.setParameter(HTTP_FORM_SAMLREQ, URLDecoder.decode(URISupport.getRawQueryStringParameter( + httpReq.getQueryString(), HTTP_FORM_SAMLREQ).substring(HTTP_FORM_SAMLREQ_PARAM.length()), "UTF-8")); + httpReq.setParameter(HTTP_REDIRECT_SIGALG, URLDecoder.decode(URISupport.getRawQueryStringParameter( + httpReq.getQueryString(), HTTP_REDIRECT_SIGALG).substring(HTTP_REDIRECT_SIGALG_PARAM.length()), + "UTF-8")); + httpReq.setParameter(HTTP_REDIRECT_SIGNATURE, URLDecoder.decode(URISupport.getRawQueryStringParameter( + httpReq.getQueryString(), HTTP_REDIRECT_SIGNATURE).substring(HTTP_REDIRECT_SIGNATURE_PARAM.length()), + "UTF-8")); + + try { + bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, + comparator); + Assert.fail("Wrong signature not detected"); + + } catch (final Pvp2Exception e) { + Assert.assertEquals("Wrong errorCode", "internal.pvp.10", e.getErrorId()); + Assert.assertNotNull("Parameters null", e.getParams()); + Assert.assertEquals("Wrong numer of parameters", 1, e.getParams().length); + + } + + } + + @Test + public void decodeRequestWrongSignature() throws MessageDecodingException, + SecurityException, IOException, Pvp2Exception { + final String serviceUrl = "http://testservice.org"; + + final IPvp2MetadataProvider metadataProvider = + metadataResolverFactory.createMetadataProvider( + "classpath:/data/pvp_metadata_wrong_sig.xml", null, "jUnit metadata resolver", null); + + final URIComparator comparator = new EaafUriCompare(serviceUrl); + + httpReq.setMethod("GET"); + httpReq.setRequestURI("http://testservice.org"); + httpReq.setQueryString("SAMLRequest=nVRNb9swDD13wP6DoXvkr%2FRjQuzCSFAgQDd0TbfDLoVi0642Wcok2kn766c4duABWw%" + + "2B%2BSdQj%2BfhIanF7qKXXgrFCq4SENCAeqFwXQlUJ%2BfZ0N7sht%2BnC8lpGO5Y1%2BKIe4XcDFj3nqCw7vSSkMYppboVli" + + "tdgGeZsk32%2BZxEN2M5o1LmWxMusBYMu1VIr29RgNmBakcNaFXBw6R0C0Yhtg3BCOBp%2FQxy%2FlcsuFMeO8Qvijvk%2BOps" + + "9Aak2FfHWq4Q8c4BtySHO4eomLCEuipyXURjzeVQGYRE7mLWNC22RK0xIFITzWRDPgsun4IrFn1gQ0evryx%2FE%2Bz4o5Oohv" + + "R6sczZjId7XgQ%2FVE%2B9Om5rj%2B%2FCjRRSzsoMyUCjwlaTHgq2ruIBaU6jEG61ayrG777RBLp%2BPR6krofyFP2Y68N402" + + "5%2BQ4xTi6ccPFxd9mC8Ot15NI9T7umiDpSd1nrUT4kFLkb96mZR6vzTAERKCpoEpCu6OPbTohCRThtc%2FU%2Bs3AIpuH9ygI" + + "hwm7cNYzXGspXSKP0I5qUP9Ruz3e2pRm1%2B00i2Fxne77ecCxRuor1l2Dy1Ifz6o%2F6%2Fso%2B78p%2Bb0%2FDz%2BGdI%2" + + "F&SigAlg=http%3A%2F%2Fwww.w3.org%2F2001%2F04%2Fxmldsig-more%23rsa-sha256&Signature=DOVMqh17xn4wl%2" + + "Byvifm4McMsBjKDVf1eqph9ss362ZEbp2nkAIXUzkNWv72I96iNK3r%2BYbAxY9dwZ8Z7jKzCGiJ9Qm34YSfPvzXWl3EVrdI86" + + "9U%2BH6HGIMqVew3cVdr4q3Qv9ZBIhdRxbrDu%2F%2BnMjdf8mzbgcQnfjSQiQIYWxOIXZFyxKsyrxJtIam4hoNwUT7mMN6Rjg" + + "zvyeS3mARsTJdcI0Vn4ItiprhLgIkD18V9WIdeSZR0gfRaFj8PKdmXCD%2FIa0cKgjhVKoiIZisV4vcthBOeDIqBORL2Ad3Xhc" + + "NRQ3%2BcpAf65zHGMBAv1aRy7Bmv0%2B%2BOvCavufykqI2EHtg%3D%3D"); + + httpReq.setParameter(HTTP_FORM_SAMLREQ, URLDecoder.decode(URISupport.getRawQueryStringParameter( + httpReq.getQueryString(), HTTP_FORM_SAMLREQ).substring(HTTP_FORM_SAMLREQ_PARAM.length()), "UTF-8")); + httpReq.setParameter(HTTP_REDIRECT_SIGALG, URLDecoder.decode(URISupport.getRawQueryStringParameter( + httpReq.getQueryString(), HTTP_REDIRECT_SIGALG).substring(HTTP_REDIRECT_SIGALG_PARAM.length()), + "UTF-8")); + httpReq.setParameter(HTTP_REDIRECT_SIGNATURE, URLDecoder.decode(URISupport.getRawQueryStringParameter( + httpReq.getQueryString(), HTTP_REDIRECT_SIGNATURE).substring(HTTP_REDIRECT_SIGNATURE_PARAM.length()), + "UTF-8")); + + try { + bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, + comparator); + Assert.fail("Wrong signature not detected"); + + } catch (final Pvp2Exception e) { + org.springframework.util.Assert.isInstanceOf(SamlSigningException.class, e, "Wrong Exception type"); + Assert.assertEquals("Wrong errorCode", "internal.pvp.10", e.getErrorId()); + Assert.assertNotNull("No error params", e.getParams()); + Assert.assertEquals("Wrong param size", 1, e.getParams().length); + + } + + } + + @Test + public void decodeRequestExpired() throws MessageDecodingException, + SecurityException, IOException, Pvp2Exception, CredentialsNotAvailableException, + XMLParserException, UnmarshallingException { + final String serviceUrl = "http://testservice.org"; + + final IPvp2MetadataProvider metadataProvider = + metadataResolverFactory.createMetadataProvider( + "classpath:/data/pvp_metadata_junit_keystore.xml", null, "jUnit metadata resolver", null); + + final URIComparator comparator = new EaafUriCompare(serviceUrl); + + httpReq.setMethod("GET"); + httpReq.setRequestURI("http://testservice.org"); + httpReq.setQueryString("SAMLRequest=nVRNb9swDD13wP6DoXvkj2RFJsQujAQFAnTD1nQ97FIoNu1qkyVPop20v36KYwcusPVgQ" + + "AeLeiQfH0mvbo6V9FowVmgVk5AGxAOV6VyoMiY%2FHm5nS3KTrCyvZFSztMFndQ9%2FGrDoOUdl2fklJo1RTHMrLFO8AsswY7v" + + "0yx2LaMBqo1FnWhIvtRYMulRrrWxTgdmBaUUGW5XD0aV3CEQj9g3CGeFovIU4fhuXXSiOHeNnxJr5PjqbPQOpNiXxtpuYPHGAf" + + "cFhnsH1MixgnucZL6JwzhdREYT53MGsbVxoi1xhTKIgCmZBNAsWD8Fn5s6na7qMwp%2FEexwUcvWQXg%2FWOZuxEO%2FrwIfqi" + + "XerTcXxffjJIvJZ0UEZKBT4QpJTwdZVnEOlKZTilZYt5djda22Qy6fTp9SlUP7KHzMdeO%2Ba%2FS%2FIcArx5OOHq6s%2BzFe" + + "H226mEep9XbTB0pO6zNoZ8U1Lkb14qZT6sDbAEWKCpoEpCtanHlp0QpIpw%2BtfqPUbAHm3D25QEY6T9mGs5jjWWjrF76GY1KF" + + "%2BIw6HA7WozW9a6pZC47vd9jOB4hXU9zS9gxakvxjU%2F1f2UXf%2BU3NyeR7%2FGZK%2F&SigAlg=http%3A%2F%2Fwww.w3" + + ".org%2F2001%2F04%2Fxmldsig-more%23rsa-sha256&Signature=JogFpk2oimCnBCgE7eZx%2B6yoJu2ZCgus5vM1opkTk" + + "OLM9qgNMUJJJbIeA3j2TR%2BWx3pUApnV7ed9CuTBF94b3ELkFdaZAetfLzY8gnPLCBmcYIYkwg3bK7ZQWEBJpjNoU%2BaBHXV" + + "OgptLUt0qRWavm%2BiPOUXRWpb0PtgvApTieRk32gBfZbuPOltWjrRCKaa2ulKBjB34LqYdAaIWaVix2sGvg128p6lC7bQ%2Fz" + + "wmz6j8S5Vn8snvlg48MlBldTWKSZrUERx3MwTyaB17A617XmX2QKo8fGCQ6O7FF4umFyWGAlujI%2FwqafTfPlaNX2usHynHS6" + + "XkH5HWCDSAe3%2BVR1w%3D%3D "); + + httpReq.setParameter(HTTP_FORM_SAMLREQ, URLDecoder.decode(URISupport.getRawQueryStringParameter( + httpReq.getQueryString(), HTTP_FORM_SAMLREQ).substring(HTTP_FORM_SAMLREQ_PARAM.length()), "UTF-8")); + httpReq.setParameter(HTTP_REDIRECT_SIGALG, URLDecoder.decode(URISupport.getRawQueryStringParameter( + httpReq.getQueryString(), HTTP_REDIRECT_SIGALG).substring(HTTP_REDIRECT_SIGALG_PARAM.length()), + "UTF-8")); + httpReq.setParameter(HTTP_REDIRECT_SIGNATURE, URLDecoder.decode(URISupport.getRawQueryStringParameter( + httpReq.getQueryString(), HTTP_REDIRECT_SIGNATURE).substring(HTTP_REDIRECT_SIGNATURE_PARAM.length()), + "UTF-8")); + + try { + bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, + comparator); + Assert.fail("Expired message not detected"); + + } catch (final Pvp2Exception e) { + org.springframework.util.Assert.isInstanceOf(SamlMessageValidationException.class, e, + "Wrong Exception type"); + Assert.assertEquals("Wrong errorCode", "internal.pvp.11", e.getErrorId()); + Assert.assertNotNull("No error params", e.getParams()); + Assert.assertEquals("Wrong param size", 1, e.getParams().length); + + } + + } + + @Test + public void decodeRequestSuccess() throws MessageDecodingException, + SecurityException, IOException, Pvp2Exception, CredentialsNotAvailableException, + XMLParserException, UnmarshallingException { + final String serviceUrl = "http://testservice.org"; + + final IPvp2MetadataProvider metadataProvider = + metadataResolverFactory.createMetadataProvider( + "classpath:/data/pvp_metadata_junit_keystore.xml", null, "jUnit metadata resolver", null); + + final URIComparator comparator = new EaafUriCompare(serviceUrl); + + httpReq.setMethod("GET"); + httpReq.setRequestURI("http://testservice.org"); + httpReq.setQueryString(generateAuthnRequest(credentialProvider.getMetaDataSigningCredential())); + + httpReq.setParameter(HTTP_FORM_SAMLREQ, URLDecoder.decode(URISupport.getRawQueryStringParameter( + httpReq.getQueryString(), HTTP_FORM_SAMLREQ).substring(HTTP_FORM_SAMLREQ_PARAM.length()), "UTF-8")); + httpReq.setParameter(HTTP_REDIRECT_SIGALG, URLDecoder.decode(URISupport.getRawQueryStringParameter( + httpReq.getQueryString(), HTTP_REDIRECT_SIGALG).substring(HTTP_REDIRECT_SIGALG_PARAM.length()), + "UTF-8")); + httpReq.setParameter(HTTP_REDIRECT_SIGNATURE, URLDecoder.decode(URISupport.getRawQueryStringParameter( + httpReq.getQueryString(), HTTP_REDIRECT_SIGNATURE).substring(HTTP_REDIRECT_SIGNATURE_PARAM.length()), + "UTF-8")); + + final InboundMessageInterface msg = + bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, + comparator); + + Assert.assertNotNull("PVP msg is null", msg); + Assert.assertNull("RelayState is not null", msg.getRelayState()); + Assert.assertNotNull("AuthnReq is null", msg.getInboundMessage()); + Assert.assertNotNull("EntityId is null", msg.getEntityID()); + Assert.assertEquals("EntityId not match", "https://demo.egiz.gv.at/demoportal_demologin/", msg + .getEntityID()); + Assert.assertTrue("Wrong isVerified flag", msg.isVerified()); + + } + + @Test + public void decodeResponseSuccess() throws MessageDecodingException, SecurityException, IOException, + Pvp2Exception, CredentialsNotAvailableException, XMLParserException, UnmarshallingException { + final String serviceUrl = "http://testservice.org"; + + final IPvp2MetadataProvider metadataProvider = + metadataResolverFactory.createMetadataProvider( + "classpath:/data/pvp_metadata_junit_keystore.xml", null, "jUnit metadata resolver", null); + + final URIComparator comparator = new EaafUriCompare(serviceUrl); + + httpReq.setMethod("GET"); + httpReq.setRequestURI("http://testservice.org"); + httpReq.setQueryString(generateResponse(credentialProvider.getMetaDataSigningCredential())); + + httpReq.setParameter(HTTP_FORM_SAMLRESP, URLDecoder.decode(URISupport.getRawQueryStringParameter( + httpReq.getQueryString(), HTTP_FORM_SAMLRESP).substring(HTTP_FORM_SAMLRESP_PARM.length()), "UTF-8")); + httpReq.setParameter(HTTP_REDIRECT_SIGALG, URLDecoder.decode(URISupport.getRawQueryStringParameter( + httpReq.getQueryString(), HTTP_REDIRECT_SIGALG).substring(HTTP_REDIRECT_SIGALG_PARAM.length()), + "UTF-8")); + httpReq.setParameter(HTTP_REDIRECT_SIGNATURE, URLDecoder.decode(URISupport.getRawQueryStringParameter( + httpReq.getQueryString(), HTTP_REDIRECT_SIGNATURE).substring(HTTP_REDIRECT_SIGNATURE_PARAM.length()), + "UTF-8")); + + final InboundMessageInterface msg = + bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, + comparator); + + Assert.assertNotNull("PVP msg is null", msg); + Assert.assertNull("RelayState is not null", msg.getRelayState()); + Assert.assertNotNull("Response is null", msg.getInboundMessage()); + Assert.assertNotNull("EntityId is null", msg.getEntityID()); + Assert.assertEquals("EntityId not match", "https://demo.egiz.gv.at/demoportal_demologin/", msg + .getEntityID()); + Assert.assertTrue("Wrong isVerified flag", msg.isVerified()); + + } + + @Test + public void decodeResponseSuccessWithRelayStateAndMetadataReload() throws MessageDecodingException, + SecurityException, IOException, Pvp2Exception, CredentialsNotAvailableException, + XMLParserException, UnmarshallingException { + final String serviceUrl = "http://testservice.org"; + final String relayState = RandomStringUtils.randomAlphanumeric(10); + + mockWebServer.enqueue(new MockResponse().setResponseCode(200) + .setBody(new String(IOUtils.toByteArray( + MetadataResolverTest.class.getResourceAsStream( + "/data/pvp_metadata_wrong_sig.xml")), "UTF-8")) + .setHeader("Content-Type", "text/xml")); + + mockWebServer.enqueue(new MockResponse().setResponseCode(200) + .setBody(new String(IOUtils.toByteArray( + MetadataResolverTest.class.getResourceAsStream( + "/data/pvp_metadata_junit_keystore.xml")), "UTF-8")) + .setHeader("Content-Type", "text/xml")); + + final IPvp2MetadataProvider metadataProvider = + metadataResolverFactory.createMetadataProvider( + mockServerUrl.url().toString(), + null, "jUnit test", httpClientFactory.getHttpClient()); + + + httpReq.setMethod("GET"); + httpReq.setRequestURI("http://testservice.org"); + httpReq.setParameter(HTTP_FORM_RELAYSTATE, relayState); + httpReq.setQueryString(generateResponse(credentialProvider.getMetaDataSigningCredential())); + + httpReq.setParameter(HTTP_FORM_SAMLRESP, URLDecoder.decode(URISupport.getRawQueryStringParameter( + httpReq.getQueryString(), HTTP_FORM_SAMLRESP).substring(HTTP_FORM_SAMLRESP_PARM.length()), "UTF-8")); + httpReq.setParameter(HTTP_REDIRECT_SIGALG, URLDecoder.decode(URISupport.getRawQueryStringParameter( + httpReq.getQueryString(), HTTP_REDIRECT_SIGALG).substring(HTTP_REDIRECT_SIGALG_PARAM.length()), + "UTF-8")); + httpReq.setParameter(HTTP_REDIRECT_SIGNATURE, URLDecoder.decode(URISupport.getRawQueryStringParameter( + httpReq.getQueryString(), HTTP_REDIRECT_SIGNATURE).substring(HTTP_REDIRECT_SIGNATURE_PARAM.length()), + "UTF-8")); + + final URIComparator comparator = new EaafUriCompare(serviceUrl); + + final InboundMessageInterface msg = + bindingImpl.decode(httpReq, httpResp, metadataProvider, SPSSODescriptor.DEFAULT_ELEMENT_NAME, + comparator); + + Assert.assertNotNull("PVP msg is null", msg); + Assert.assertNotNull("RelayState is null", msg.getRelayState()); + Assert.assertEquals("RelayState not match", relayState, msg.getRelayState()); + Assert.assertNotNull("Response is null", msg.getInboundMessage()); + Assert.assertNotNull("EntityId is null", msg.getEntityID()); + Assert.assertEquals("EntityId not match", "https://demo.egiz.gv.at/demoportal_demologin/", msg + .getEntityID()); + Assert.assertTrue("Wrong isVerified flag", msg.isVerified()); + + } + + @Test + public void encodeRequestSuccess() throws MessageDecodingException, SecurityException, + MessageEncodingException, XMLParserException, UnmarshallingException, + CredentialsNotAvailableException, ParserConfigurationException, SAXException, IOException, + Pvp2Exception { + // build test data + final String serviceUrl = "http://testservice.org"; + final String relayState = null; + final RequestAbstractType authnReq = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + RedirectBindingTest.class.getResourceAsStream("/data/AuthRequest_without_sig_1.xml")); + + bindingImpl.encodeRequest(httpReq, httpResp, authnReq, serviceUrl, relayState, + credentialProvider.getMetaDataSigningCredential(), pendingReq); + + // validate + Assert.assertEquals("http StatusCode", 302, httpResp.getStatus()); + Assert.assertEquals("PVP msg is null", 0, httpResp.getContentLength()); + + Assert.assertNull("ContentType", httpResp.getContentType()); + Assert.assertEquals("Encoding", "UTF-8", httpResp.getCharacterEncoding()); + + final String locationHeader = httpResp.getHeader("Location"); + Assert.assertNotNull("Location header is null", locationHeader); + Assert.assertFalse("Location header is empty", locationHeader.isEmpty()); + + Assert.assertTrue("Wrong redirect URL", + locationHeader.startsWith(serviceUrl + "?" + HTTP_FORM_SAMLREQ_PARAM)); + + final String respSamlMsg = checkMessagePart(locationHeader, HTTP_FORM_SAMLREQ_PARAM, true); + Assert.assertNotNull("Saml msg is null", respSamlMsg); + Assert.assertFalse("Saml msg is empty", respSamlMsg.isEmpty()); + + final String sigAlg = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGALG_PARAM, true); + Assert.assertNotNull("SigAlg is null", sigAlg); + Assert.assertFalse("SigAlg is empty", sigAlg.isEmpty()); + Assert.assertEquals("SigAlg not match", PvpConstants.DEFAULT_SIGNING_METHODE_RSA, + URLDecoder.decode(sigAlg, "UTF-8")); + + final String samlSig = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGNATURE_PARAM, true); + Assert.assertNotNull("Saml signature null", samlSig); + Assert.assertFalse("Saml signature is empty", samlSig.isEmpty()); + + final String respRelayState = checkMessagePart(locationHeader, HTTP_FORM_RELAYSTATE_PARAM, false); + Assert.assertNull("RelayState parameter", respRelayState); + + } + + @Test + public void encodeRequestSuccessEcdsa() throws MessageDecodingException, SecurityException, + MessageEncodingException, XMLParserException, UnmarshallingException, + CredentialsNotAvailableException, ParserConfigurationException, SAXException, IOException, + Pvp2Exception { + // build test data + final String serviceUrl = "http://testservice.org"; + final String relayState = null; + final RequestAbstractType authnReq = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + RedirectBindingTest.class.getResourceAsStream("/data/AuthRequest_without_sig_1.xml")); + + bindingImpl.encodeRequest(httpReq, httpResp, authnReq, serviceUrl, relayState, + credentialProvider.getMessageSigningCredential(), pendingReq); + + // validate + // validate + Assert.assertEquals("http StatusCode", 302, httpResp.getStatus()); + Assert.assertEquals("PVP msg is null", 0, httpResp.getContentLength()); + + Assert.assertNull("ContentType", httpResp.getContentType()); + Assert.assertEquals("Encoding", "UTF-8", httpResp.getCharacterEncoding()); + + final String locationHeader = httpResp.getHeader("Location"); + Assert.assertNotNull("Location header is null", locationHeader); + Assert.assertFalse("Location header is empty", locationHeader.isEmpty()); + + Assert.assertTrue("Wrong redirect URL", + locationHeader.startsWith(serviceUrl + "?" + HTTP_FORM_SAMLREQ_PARAM)); + + final String respSamlMsg = checkMessagePart(locationHeader, HTTP_FORM_SAMLREQ_PARAM, true); + Assert.assertNotNull("Saml msg is null", respSamlMsg); + Assert.assertFalse("Saml msg is empty", respSamlMsg.isEmpty()); + + final String sigAlg = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGALG_PARAM, true); + Assert.assertNotNull("SigAlg is null", sigAlg); + Assert.assertFalse("SigAlg is empty", sigAlg.isEmpty()); + Assert.assertEquals("SigAlg not match", PvpConstants.DEFAULT_SIGNING_METHODE_EC, + URLDecoder.decode(sigAlg, "UTF-8")); + + final String samlSig = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGNATURE_PARAM, true); + Assert.assertNotNull("Saml signature null", samlSig); + Assert.assertFalse("Saml signature is empty", samlSig.isEmpty()); + + final String respRelayState = checkMessagePart(locationHeader, HTTP_FORM_RELAYSTATE_PARAM, false); + Assert.assertNull("RelayState parameter", respRelayState); + + } + + @Test + public void encodeRequestSuccessWithRelayState() throws MessageDecodingException, SecurityException, + MessageEncodingException, XMLParserException, UnmarshallingException, + CredentialsNotAvailableException, ParserConfigurationException, SAXException, IOException, + Pvp2Exception { + + // build test data + final String serviceUrl = "http://testservice.org"; + final String relayState = RandomStringUtils.randomAlphabetic(10); + final RequestAbstractType authnReq = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + RedirectBindingTest.class.getResourceAsStream("/data/AuthRequest_without_sig_1.xml")); + + bindingImpl.encodeRequest(httpReq, httpResp, authnReq, serviceUrl, relayState, + credentialProvider.getMetaDataSigningCredential(), pendingReq); + + // validate + Assert.assertEquals("http StatusCode", 302, httpResp.getStatus()); + Assert.assertEquals("PVP msg is null", 0, httpResp.getContentLength()); + + Assert.assertNull("ContentType", httpResp.getContentType()); + Assert.assertEquals("Encoding", "UTF-8", httpResp.getCharacterEncoding()); + + final String locationHeader = httpResp.getHeader("Location"); + Assert.assertNotNull("Location header is null", locationHeader); + Assert.assertFalse("Location header is empty", locationHeader.isEmpty()); + + Assert.assertTrue("Wrong redirect URL", + locationHeader.startsWith(serviceUrl + "?" + HTTP_FORM_SAMLREQ_PARAM)); + + final String respSamlMsg = checkMessagePart(locationHeader, HTTP_FORM_SAMLREQ_PARAM, true); + Assert.assertNotNull("Saml msg is null", respSamlMsg); + Assert.assertFalse("Saml msg is empty", respSamlMsg.isEmpty()); + + final String sigAlg = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGALG_PARAM, true); + Assert.assertNotNull("SigAlg is null", sigAlg); + Assert.assertFalse("SigAlg is empty", sigAlg.isEmpty()); + Assert.assertEquals("SigAlg not match", PvpConstants.DEFAULT_SIGNING_METHODE_RSA, + URLDecoder.decode(sigAlg, "UTF-8")); + + final String samlSig = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGNATURE_PARAM, true); + Assert.assertNotNull("Saml signature null", samlSig); + Assert.assertFalse("Saml signature is empty", samlSig.isEmpty()); + + final String respRelayState = checkMessagePart(locationHeader, HTTP_FORM_RELAYSTATE_PARAM, false); + Assert.assertNotNull("RelayState parameter", respRelayState); + Assert.assertEquals("RelayState not match", relayState, + URLDecoder.decode(respRelayState, "UTF-8")); + + } + + @Test + public void encodeResponseSuccessWithRelayState() throws MessageDecodingException, SecurityException, + MessageEncodingException, XMLParserException, UnmarshallingException, + CredentialsNotAvailableException, ParserConfigurationException, SAXException, IOException, + Pvp2Exception { + + // build test data + final String serviceUrl = "http://testservice.org"; + final String relayState = RandomStringUtils.randomAlphabetic(10); + final StatusResponseType authnReq = (StatusResponseType) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + RedirectBindingTest.class.getResourceAsStream("/data/Response_without_sig_1.xml")); + + bindingImpl.encodeResponse(httpReq, httpResp, authnReq, serviceUrl, relayState, + credentialProvider.getMetaDataSigningCredential(), pendingReq); + + // validate + Assert.assertEquals("http StatusCode", 302, httpResp.getStatus()); + Assert.assertEquals("PVP msg is null", 0, httpResp.getContentLength()); + + Assert.assertNull("ContentType", httpResp.getContentType()); + Assert.assertEquals("Encoding", "UTF-8", httpResp.getCharacterEncoding()); + + final String locationHeader = httpResp.getHeader("Location"); + Assert.assertNotNull("Location header is null", locationHeader); + Assert.assertFalse("Location header is empty", locationHeader.isEmpty()); + + Assert.assertTrue("Wrong redirect URL", + locationHeader.startsWith(serviceUrl + "?" + HTTP_FORM_SAMLRESP_PARM)); + + final String respSamlMsg = checkMessagePart(locationHeader, HTTP_FORM_SAMLRESP_PARM, true); + Assert.assertNotNull("Saml msg is null", respSamlMsg); + Assert.assertFalse("Saml msg is empty", respSamlMsg.isEmpty()); + + final String sigAlg = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGALG_PARAM, true); + Assert.assertNotNull("SigAlg is null", sigAlg); + Assert.assertFalse("SigAlg is empty", sigAlg.isEmpty()); + Assert.assertEquals("SigAlg not match", PvpConstants.DEFAULT_SIGNING_METHODE_RSA, + URLDecoder.decode(sigAlg, "UTF-8")); + + final String samlSig = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGNATURE_PARAM, true); + Assert.assertNotNull("Saml signature null", samlSig); + Assert.assertFalse("Saml signature is empty", samlSig.isEmpty()); + + final String respRelayState = checkMessagePart(locationHeader, HTTP_FORM_RELAYSTATE_PARAM, false); + Assert.assertNotNull("RelayState parameter", respRelayState); + Assert.assertEquals("RelayState not match", relayState, + URLDecoder.decode(respRelayState, "UTF-8")); + + } + + @Test + public void encodeResponseSuccess() throws MessageDecodingException, SecurityException, + MessageEncodingException, XMLParserException, UnmarshallingException, + CredentialsNotAvailableException, ParserConfigurationException, SAXException, IOException, + Pvp2Exception { + + // build test data + final String serviceUrl = "http://testservice.org"; + final String relayState = null; + final StatusResponseType authnReq = (StatusResponseType) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + RedirectBindingTest.class.getResourceAsStream("/data/Response_without_sig_1.xml")); + + bindingImpl.encodeResponse(httpReq, httpResp, authnReq, serviceUrl, relayState, + credentialProvider.getMetaDataSigningCredential(), pendingReq); + + // validate + Assert.assertEquals("http StatusCode", 302, httpResp.getStatus()); + Assert.assertEquals("PVP msg is null", 0, httpResp.getContentLength()); + + Assert.assertNull("ContentType", httpResp.getContentType()); + Assert.assertEquals("Encoding", "UTF-8", httpResp.getCharacterEncoding()); + + final String locationHeader = httpResp.getHeader("Location"); + Assert.assertNotNull("Location header is null", locationHeader); + Assert.assertFalse("Location header is empty", locationHeader.isEmpty()); + + Assert.assertTrue("Wrong redirect URL", + locationHeader.startsWith(serviceUrl + "?" + HTTP_FORM_SAMLRESP_PARM)); + + final String respSamlMsg = checkMessagePart(locationHeader, HTTP_FORM_SAMLRESP_PARM, true); + Assert.assertNotNull("Saml msg is null", respSamlMsg); + Assert.assertFalse("Saml msg is empty", respSamlMsg.isEmpty()); + + final String sigAlg = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGALG_PARAM, true); + Assert.assertNotNull("SigAlg is null", sigAlg); + Assert.assertFalse("SigAlg is empty", sigAlg.isEmpty()); + Assert.assertEquals("SigAlg not match", PvpConstants.DEFAULT_SIGNING_METHODE_RSA, + URLDecoder.decode(sigAlg, "UTF-8")); + + final String samlSig = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGNATURE_PARAM, true); + Assert.assertNotNull("Saml signature null", samlSig); + Assert.assertFalse("Saml signature is empty", samlSig.isEmpty()); + + final String respRelayState = checkMessagePart(locationHeader, HTTP_FORM_RELAYSTATE_PARAM, false); + Assert.assertNull("RelayState parameter", respRelayState); + + } + + private String checkMessagePart(String locationHeader, String httpFormSamlreq, boolean isRequired) { + final int startIndex = locationHeader.indexOf(httpFormSamlreq); + int endIndex = locationHeader.indexOf("&", startIndex); + + if (isRequired && startIndex == -1) { + Assert.fail("Element: " + httpFormSamlreq + " NOT found"); + + } else if (startIndex == -1) { + return null; + + } + + if (endIndex == -1) { + endIndex = locationHeader.length(); + + } + + return locationHeader.substring(startIndex + httpFormSamlreq.length(), endIndex); + + } + + private String generateAuthnRequest(EaafX509Credential credential) throws Pvp2Exception, + XMLParserException, UnmarshallingException { + final MockHttpServletRequest intHttpReq = new MockHttpServletRequest(); + final MockHttpServletResponse intHttpResp = new MockHttpServletResponse(); + + final RequestAbstractType authnReq = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + RedirectBindingTest.class.getResourceAsStream("/data/AuthRequest_without_sig_1.xml")); + authnReq.setIssueInstant(DateTime.now()); + + bindingImpl.encodeRequest(intHttpReq, intHttpResp, authnReq, "http://testservice.org", null, + credential, pendingReq); + + Assert.assertEquals("http StatusCode", 302, intHttpResp.getStatus()); + final String locationHeader = intHttpResp.getHeader("Location"); + Assert.assertNotNull("Location header is null", locationHeader); + return locationHeader.split("\\?")[1]; + + } + + private String generateResponse(EaafX509Credential credential) throws Pvp2Exception, + XMLParserException, UnmarshallingException { + new MockHttpServletRequest(); + final MockHttpServletRequest intHttpReq = new MockHttpServletRequest(); + final MockHttpServletResponse intHttpResp = new MockHttpServletResponse(); + + final StatusResponseType authnReq = (StatusResponseType) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + RedirectBindingTest.class.getResourceAsStream("/data/Response_without_sig_1.xml")); + authnReq.setIssueInstant(DateTime.now()); + + bindingImpl.encodeResponse(intHttpReq, intHttpResp, authnReq, "http://testservice.org", null, + credential, pendingReq); + + Assert.assertEquals("http StatusCode", 302, intHttpResp.getStatus()); + final String locationHeader = intHttpResp.getHeader("Location"); + Assert.assertNotNull("Location header is null", locationHeader); + return locationHeader.split("\\?")[1]; + + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/binding/SoapBindingTest.java b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/binding/SoapBindingTest.java new file mode 100644 index 00000000..f3a7e01d --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/binding/SoapBindingTest.java @@ -0,0 +1,216 @@ +package at.gv.egiz.eaaf.modules.pvp2.test.binding; + +import java.io.ByteArrayOutputStream; +import java.io.UnsupportedEncodingException; + +import at.gv.egiz.eaaf.core.api.IRequest; +import at.gv.egiz.eaaf.core.impl.idp.module.test.TestRequestImpl; +import at.gv.egiz.eaaf.modules.pvp2.api.message.InboundMessageInterface; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; +import at.gv.egiz.eaaf.modules.pvp2.impl.binding.SoapBinding; +import at.gv.egiz.eaaf.modules.pvp2.impl.metadata.PvpMetadataResolverFactory; +import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafOpenSaml3xInitializer; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils; +import at.gv.egiz.eaaf.modules.pvp2.impl.validation.EaafUriCompare; +import at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyCredentialProvider; + +import org.joda.time.DateTime; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport; +import org.opensaml.core.xml.io.Marshaller; +import org.opensaml.core.xml.io.MarshallingException; +import org.opensaml.core.xml.io.UnmarshallingException; +import org.opensaml.core.xml.util.XMLObjectSupport; +import org.opensaml.saml.saml2.core.RequestAbstractType; +import org.opensaml.saml.saml2.core.StatusResponseType; +import org.opensaml.saml.saml2.metadata.SPSSODescriptor; +import org.opensaml.soap.soap11.Envelope; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import net.shibboleth.utilities.java.support.logic.Constraint; +import net.shibboleth.utilities.java.support.net.URIComparator; +import net.shibboleth.utilities.java.support.xml.SerializeSupport; +import net.shibboleth.utilities.java.support.xml.XMLParserException; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration({"/spring/test_eaaf_pvp.beans.xml", + "/spring/test_eaaf_core_spring_config.beans.xml", + "/spring/eaaf_utils.beans.xml"}) +@TestPropertySource(locations = {"/config/config_1.props"}) +public class SoapBindingTest { + + @Autowired private SoapBinding bindingImpl; + @Autowired private PvpMetadataResolverFactory metadataResolverFactory; + @Autowired private DummyCredentialProvider credentialProvider; + + protected MockHttpServletRequest httpReq; + protected MockHttpServletResponse httpResp; + protected IRequest pendingReq; + + /** + * JUnit class initializer. + * + * @throws Exception In case of an OpenSAML3 initialization error + */ + @BeforeClass + public static void classInitializer() throws Exception { + EaafOpenSaml3xInitializer.eaafInitialize(); + + } + + /** + * Test initializer. + * + */ + @Before + public void initialize() { + httpReq = new MockHttpServletRequest(); + httpResp = new MockHttpServletResponse(); + + pendingReq = new TestRequestImpl(); + + } + + @Test + public void withoutSig() throws Pvp2Exception, MarshallingException, XMLParserException, UnmarshallingException { + final String serviceUrl = "https://localhost/pvp2/post"; + final IPvp2MetadataProvider metadataProvider = + metadataResolverFactory.createMetadataProvider( + "classpath:/data/pvp_metadata_junit_keystore.xml", null, "jUnit metadata resolver", null); + final URIComparator comparator = new EaafUriCompare(serviceUrl); + + final RequestAbstractType payload = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + PostBindingTest.class.getResourceAsStream("/data/AuthRequest_without_sig_1.xml")); + payload.setIssueInstant(DateTime.now()); + final Envelope enveloped = Saml2Utils.buildSoap11Envelope(payload); + final Marshaller marshaller = Constraint.isNotNull( + XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(enveloped), + "SOAP Envelope marshaller not available"); + final ByteArrayOutputStream arrayOut = new ByteArrayOutputStream(); + SerializeSupport.writeNode(marshaller.marshall(enveloped), arrayOut); + httpReq.setMethod("POST"); + httpReq.setContentType("text/xml"); + httpReq.setContent(arrayOut.toByteArray()); + + + try { + bindingImpl.decode(httpReq, httpResp, metadataProvider, + SPSSODescriptor.DEFAULT_ELEMENT_NAME, comparator); + Assert.fail("Missing signature not detected"); + + } catch (final Pvp2Exception e) { + Assert.assertEquals("Wrong errorCode", "internal.pvp.02", e.getErrorId()); + + } + } + + @Test + public void wrongSignature() throws Pvp2Exception, MarshallingException, XMLParserException, UnmarshallingException { + final String serviceUrl = "https://localhost/pvp2/post"; + final IPvp2MetadataProvider metadataProvider = + metadataResolverFactory.createMetadataProvider( + "classpath:/data/pvp_metadata_junit_keystore.xml", null, "jUnit metadata resolver", null); + final URIComparator comparator = new EaafUriCompare(serviceUrl); + + final RequestAbstractType payload = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + PostBindingTest.class.getResourceAsStream("/data/AuthRequest_with_sig_1.xml")); + payload.setIssueInstant(DateTime.now()); + final Envelope enveloped = Saml2Utils.buildSoap11Envelope(payload); + final Marshaller marshaller = Constraint.isNotNull( + XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(enveloped), + "SOAP Envelope marshaller not available"); + final ByteArrayOutputStream arrayOut = new ByteArrayOutputStream(); + SerializeSupport.writeNode(marshaller.marshall(enveloped), arrayOut); + httpReq.setMethod("POST"); + httpReq.setContentType("text/xml"); + httpReq.setContent(arrayOut.toByteArray()); + + + try { + bindingImpl.decode(httpReq, httpResp, metadataProvider, + SPSSODescriptor.DEFAULT_ELEMENT_NAME, comparator); + Assert.fail("Missing signature not detected"); + + } catch (final Pvp2Exception e) { + Assert.assertEquals("Wrong errorCode", "internal.pvp.10", e.getErrorId()); + + } + } + + @Test + public void validSignature() throws Pvp2Exception, MarshallingException, XMLParserException, + UnmarshallingException, CredentialsNotAvailableException { + final String serviceUrl = "https://localhost/pvp2/post"; + final IPvp2MetadataProvider metadataProvider = + metadataResolverFactory.createMetadataProvider( + "classpath:/data/pvp_metadata_junit_keystore.xml", null, "jUnit metadata resolver", null); + final URIComparator comparator = new EaafUriCompare(serviceUrl); + + final RequestAbstractType payload = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + PostBindingTest.class.getResourceAsStream("/data/AuthRequest_with_sig_1.xml")); + payload.setIssueInstant(DateTime.now()); + final RequestAbstractType signedPayload = Saml2Utils.signSamlObject( + payload, credentialProvider.getMetaDataSigningCredential(), true); + + final Envelope enveloped = Saml2Utils.buildSoap11Envelope(signedPayload); + final Marshaller marshaller = Constraint.isNotNull( + XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(enveloped), + "SOAP Envelope marshaller not available"); + final ByteArrayOutputStream arrayOut = new ByteArrayOutputStream(); + SerializeSupport.writeNode(marshaller.marshall(enveloped), arrayOut); + httpReq.setMethod("POST"); + httpReq.setContentType("text/xml"); + httpReq.setContent(arrayOut.toByteArray()); + + + final InboundMessageInterface msg = + bindingImpl.decode(httpReq, httpResp, metadataProvider, + SPSSODescriptor.DEFAULT_ELEMENT_NAME, comparator); + + Assert.assertNotNull("Inbound msg is null", msg); + Assert.assertNotNull("AuthnReq is null", msg.getInboundMessage()); + Assert.assertNotNull("EntityId is null", msg.getEntityID()); + Assert.assertEquals("EntityId not match", "https://demo.egiz.gv.at/demoportal_demologin/", msg.getEntityID()); + Assert.assertTrue("Wrong isVerified flag", msg.isVerified()); + + } + + @Test + public void encodeResponse() throws XMLParserException, UnmarshallingException, + Pvp2Exception, CredentialsNotAvailableException, UnsupportedEncodingException { + final String serviceUrl = "http://testservice.org"; + + final StatusResponseType response = (StatusResponseType) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + PostBindingTest.class.getResourceAsStream("/data/Response_without_sig_1.xml")); + + bindingImpl.encodeResponse(httpReq, httpResp, response, serviceUrl, null, + credentialProvider.getMetaDataSigningCredential(), pendingReq); + + Assert.assertEquals("http StatusCode", 200, httpResp.getStatus()); + Assert.assertNotNull("PVP msg is null", httpResp.getContentLength()); + + Assert.assertEquals("ContentType", "text/xml", httpResp.getContentType()); + Assert.assertEquals("Encoding", "UTF-8", httpResp.getCharacterEncoding()); + + final String http = httpResp.getContentAsString(); + Assert.assertNotNull("http body is null", http); + Assert.assertFalse("http body is empty", http.isEmpty()); + + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/dummy/DummyCredentialProvider.java b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/dummy/DummyCredentialProvider.java new file mode 100644 index 00000000..7418e1b3 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/dummy/DummyCredentialProvider.java @@ -0,0 +1,93 @@ +package at.gv.egiz.eaaf.modules.pvp2.test.dummy; + +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException; +import at.gv.egiz.eaaf.core.impl.credential.KeyStoreConfiguration; +import at.gv.egiz.eaaf.core.impl.credential.KeyStoreConfiguration.KeyStoreType; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.AbstractCredentialProvider; + +import org.springframework.beans.factory.annotation.Autowired; + +public class DummyCredentialProvider extends AbstractCredentialProvider { + + @Autowired IConfiguration basicConfig; + + public static final String KEYSTORE_TYPE = "keystore.type"; + public static final String KEYSTORE_PATH = "keystore.path"; + public static final String KEYSTORE_PASSWORD = "keystore.pass"; + public static final String KEYSTORE_NAME = "keystore.name"; + + + public static final String KEY_METADATA_ALIAS = "key.metadata.alias"; + public static final String KEY_METADATA_PASSWORD = "key.metadata.pass"; + + public static final String KEY_SIGNING_ALIAS = "key.sig.alias"; + public static final String KEY_SIGNING_PASSWORD = "key.sig.pass"; + + public static final String KEY_ENCRYPTION_ALIAS = "key.enc.alias"; + public static final String KEY_ENCRYPTION_PASSWORD = "key.enc.pass"; + + private static final String KEYSTORENAME = "jUnit test credential provider"; + + @Override + public KeyStoreConfiguration getBasicKeyStoreConfig() throws EaafConfigurationException { + final KeyStoreConfiguration keyStoreConfig = new KeyStoreConfiguration(); + keyStoreConfig.setFriendlyName(KEYSTORENAME); + keyStoreConfig.setKeyStoreType(getKeyStoreType()); + + keyStoreConfig.setKeyStoreName( + basicConfig.getBasicConfiguration(KEYSTORE_NAME)); + + keyStoreConfig.setSoftKeyStoreFilePath(getKeyStoreFilePath()); + keyStoreConfig.setSoftKeyStorePassword(getKeyStorePassword()); + + return keyStoreConfig; + } + + public String getKeyStoreType() { + return basicConfig.getBasicConfiguration(KEYSTORE_TYPE, KeyStoreType.JKS.getKeyStoreType()); + + } + + public String getKeyStoreFilePath() { + final String path = basicConfig.getBasicConfiguration(KEYSTORE_PATH); + return path; + + } + + public String getKeyStorePassword() { + return basicConfig.getBasicConfiguration(KEYSTORE_PASSWORD); + } + + @Override + public String getMetadataKeyAlias() { + return basicConfig.getBasicConfiguration(KEY_METADATA_ALIAS); + } + + @Override + public String getMetadataKeyPassword() { + return basicConfig.getBasicConfiguration(KEY_METADATA_PASSWORD); + } + + @Override + public String getSignatureKeyAlias() { + return basicConfig.getBasicConfiguration(KEY_SIGNING_ALIAS); + } + + @Override + public String getSignatureKeyPassword() { + return basicConfig.getBasicConfiguration(KEY_SIGNING_PASSWORD); + } + + @Override + public String getEncryptionKeyAlias() { + return basicConfig.getBasicConfiguration(KEY_ENCRYPTION_ALIAS); + } + + @Override + public String getEncryptionKeyPassword() { + return basicConfig.getBasicConfiguration(KEY_ENCRYPTION_PASSWORD); + } + + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/dummy/DummyMetadataProvider.java b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/dummy/DummyMetadataProvider.java new file mode 100644 index 00000000..64ebe00c --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/dummy/DummyMetadataProvider.java @@ -0,0 +1,80 @@ +package at.gv.egiz.eaaf.modules.pvp2.test.dummy; + +import java.io.IOException; +import java.security.cert.CertificateException; +import java.util.ArrayList; +import java.util.List; + +import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException; +import at.gv.egiz.eaaf.core.impl.utils.IHttpClientFactory; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2MetadataException; +import at.gv.egiz.eaaf.modules.pvp2.impl.metadata.AbstractChainingMetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.impl.metadata.PvpMetadataResolverFactory; + +import org.opensaml.saml.metadata.resolver.MetadataResolver; +import org.opensaml.saml.metadata.resolver.filter.MetadataFilter; +import org.opensaml.saml.metadata.resolver.filter.MetadataFilterChain; +import org.springframework.beans.factory.annotation.Autowired; + +public class DummyMetadataProvider extends AbstractChainingMetadataProvider { + + private final List<String> configuredMetadataUrls = new ArrayList<>(); + private String metadataProviderName; + + @Autowired PvpMetadataResolverFactory resolverFactory; + @Autowired IHttpClientFactory httpClientFactory; + private final MetadataFilterChain metadataFilters = new MetadataFilterChain(); + + @Override + protected String getMetadataUrl(String entityId) throws EaafConfigurationException { + return entityId; + + } + + @Override + protected MetadataResolver createNewMetadataProvider(String entityId) throws EaafConfigurationException, + IOException, CertificateException { + try { + return resolverFactory.createMetadataProvider(entityId, metadataFilters, entityId, null, + httpClientFactory.getHttpClient()); + + } catch (final Pvp2MetadataException e) { + throw new EaafConfigurationException("internal.pvp.04", new Object[] {entityId}, e); + + } + + } + + @Override + protected List<String> getAllMetadataUrlsFromConfiguration() throws EaafConfigurationException { + return configuredMetadataUrls; + + } + + @Override + protected String getMetadataProviderId() { + return metadataProviderName; + + } + + public void addMetadataUrls(List<String> metadataUrls) { + configuredMetadataUrls.addAll(metadataUrls); + + } + + public void clearMetadataUrls() { + configuredMetadataUrls.clear(); + + } + + public void setMetadataProviderName(String name) { + metadataProviderName = name; + + } + + public void setMetadataFilters(List<MetadataFilter> filtersToUse) { + metadataFilters.setFilters(filtersToUse); + + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/metadata/ChainingMetadataTest.java b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/metadata/ChainingMetadataTest.java new file mode 100644 index 00000000..6abe52dc --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/metadata/ChainingMetadataTest.java @@ -0,0 +1,167 @@ +package at.gv.egiz.eaaf.modules.pvp2.test.metadata; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.util.Arrays; + +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.core.impl.utils.FileUtils; +import at.gv.egiz.eaaf.core.impl.utils.IHttpClientFactory; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2MetadataException; +import at.gv.egiz.eaaf.modules.pvp2.impl.metadata.PvpMetadataResolverFactory; +import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafOpenSaml3xInitializer; +import at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyMetadataProvider; + +import org.apache.commons.io.IOUtils; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.opensaml.core.criterion.EntityIdCriterion; +import org.opensaml.saml.criterion.EntityRoleCriterion; +import org.opensaml.saml.saml2.metadata.EntityDescriptor; +import org.opensaml.saml.saml2.metadata.SPSSODescriptor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import net.shibboleth.utilities.java.support.resolver.CriteriaSet; +import net.shibboleth.utilities.java.support.resolver.ResolverException; +import okhttp3.HttpUrl; +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer; + + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration({ "/spring/test_eaaf_pvp.beans.xml", + "/spring/test_eaaf_core_spring_config.beans.xml", + "/spring/eaaf_utils.beans.xml" }) +@TestPropertySource(locations = { "/config/config_1.props" }) +public class ChainingMetadataTest { + + private static MockWebServer mockWebServer; + private static HttpUrl mockServerUrl; + + @Autowired DummyMetadataProvider metadataProvider; + @Autowired PvpMetadataResolverFactory factory; + @Autowired IConfiguration authConfig; + @Autowired IHttpClientFactory httpFactory; + + + /** + * JUnit class initializer. + * + * @throws Exception In case of an OpenSAML3 initialization error + */ + @BeforeClass + public static void classInitializer() throws Exception { + EaafOpenSaml3xInitializer.eaafInitialize(); + + mockWebServer = new MockWebServer(); + mockServerUrl = mockWebServer.url("/sp/metadata"); + } + + @Test + public void runGarbageCollector() throws ResolverException, Pvp2MetadataException, + UnsupportedEncodingException, IOException { + + mockWebServer.enqueue(new MockResponse().setResponseCode(200) + .setBody(new String(IOUtils.toByteArray( + MetadataResolverTest.class.getResourceAsStream( + "/data/pvp_metadata_moaid_test.xml")), "UTF-8")) + .setHeader("Content-Type", "text/xml")); + + final EntityDescriptor entityDesc = + metadataProvider.getEntityDescriptor("classpath:/data/pvp_metadata_junit_keystore_classpath_entityId.xml"); + Assert.assertNotNull("EntityDesc is null", entityDesc); + + final IPvp2MetadataProvider provider2 = factory.createMetadataProvider( + "classpath:/data/pvp_metadata_junit_keystore.xml", null, "jUnit", null); + metadataProvider.addMetadataResolverIntoChain(provider2); + + final IPvp2MetadataProvider provider3 = factory.createMetadataProvider( + "classpath:/data/pvp_metadata_valid_with_entityCategory_egov.xml", null, "jUnit", null); + metadataProvider.addMetadataResolverIntoChain(provider3); + + final IPvp2MetadataProvider provider4 = factory.createMetadataProvider( + mockServerUrl.url().toString(), null, "jUnit", httpFactory.getHttpClient()); + metadataProvider.addMetadataResolverIntoChain(provider4); + + + + + metadataProvider.addMetadataUrls(Arrays.asList( + FileUtils.makeAbsoluteUrl("classpath:/data/pvp_metadata_junit_keystore.xml", + authConfig.getConfigurationRootDirectory()), mockServerUrl.url().toString())); + + metadataProvider.runGarbageCollector(); + + final EntityDescriptor entityDesc4 = + metadataProvider.getEntityDescriptor("classpath:/data/pvp_metadata_junit_keystore_classpath_entityId.xml"); + Assert.assertNotNull("EntityDesc is null", entityDesc4); + + + metadataProvider.clearMetadataUrls(); + metadataProvider.runGarbageCollector(); + + final CriteriaSet criteria = new CriteriaSet(); + criteria.add(new EntityIdCriterion("classpath:/data/pvp_metadata_junit_keystore_classpath_entityId.xml")); + final EntityDescriptor entityDesc5 = metadataProvider.resolveSingle(criteria); + Assert.assertNotNull("EntityDesc is null", entityDesc5); + + + final CriteriaSet criteria6 = new CriteriaSet(); + criteria6.add(new EntityIdCriterion("classpath:/data/classpath:/data/pvp_metadata_junit_keystore.xml")); + final EntityDescriptor entityDesc6 = metadataProvider.resolveSingle(criteria6); + Assert.assertNull("EntityDesc not null", entityDesc6); + + metadataProvider.refreshMetadataProvider("classpath:/data/pvp_metadata_junit_keystore_classpath_entityId.xml"); + + metadataProvider.clear(); + + metadataProvider.refreshMetadataProvider("classpath:/data/pvp_metadata_junit_keystore_classpath_entityId.xml"); + + metadataProvider.clear("classpath:/data/pvp_metadata_junit_keystore_classpath_entityId.xml"); + + Assert.assertFalse("Wrong refresh flag", metadataProvider.wasLastRefreshSuccess()); + + metadataProvider.getMetadataFilter(); + + metadataProvider.fullyDestroy(); + + metadataProvider.refreshMetadataProvider("classpath:/data/pvp_metadata_junit_keystore_classpath_entityId.xml"); + + final CriteriaSet criteria7 = new CriteriaSet(); + criteria7.add(new EntityIdCriterion("classpath:/data/pvp_metadata_junit_keystore_classpath_entityId.xml")); + final Iterable<EntityDescriptor> entityDesc7 = metadataProvider.resolve(criteria7); + Assert.assertNotNull("EntityDesc is null", entityDesc7); + Assert.assertTrue("is Empty", entityDesc7.iterator().hasNext()); + + final CriteriaSet criteria8 = new CriteriaSet(); + criteria8.add(new EntityIdCriterion("classpath:/data/classpath:/data/pvp_metadata_junit_keystore.xml")); + final Iterable<EntityDescriptor> entityDesc8 = metadataProvider.resolve(criteria8); + Assert.assertNotNull("EntityDesc not null", entityDesc8); + Assert.assertFalse("is not Empty", entityDesc8.iterator().hasNext()); + + metadataProvider.refresh(); + + metadataProvider.getLastRefresh(); + + metadataProvider.getLastSuccessfulRefresh(); + + metadataProvider.getLastUpdate(); + + metadataProvider.refreshMetadataProvider("classpath:/data/pvp_metadata_junit_keystore_classpath_entityId.xml"); + + + final CriteriaSet criteria9 = new CriteriaSet(); + criteria9.add(new EntityRoleCriterion(SPSSODescriptor.DEFAULT_ELEMENT_NAME)); + final Iterable<EntityDescriptor> entityDesc9 = metadataProvider.resolve(criteria9); + Assert.assertNotNull("EntityDesc not null", entityDesc9); + + } + + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/metadata/MetadataBuilderTest.java b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/metadata/MetadataBuilderTest.java new file mode 100644 index 00000000..0f8817a0 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/metadata/MetadataBuilderTest.java @@ -0,0 +1,301 @@ +package at.gv.egiz.eaaf.modules.pvp2.test.metadata; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactoryConfigurationError; + +import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvpMetadataBuilderConfiguration; +import at.gv.egiz.eaaf.modules.pvp2.api.utils.IPvp2CredentialProvider; +import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException; +import at.gv.egiz.eaaf.modules.pvp2.impl.builder.PvpMetadataBuilder; +import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafOpenSaml3xInitializer; +import at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyCredentialProvider; + +import org.apache.commons.lang3.RandomStringUtils; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport; +import org.opensaml.core.xml.io.MarshallingException; +import org.opensaml.core.xml.io.UnmarshallingException; +import org.opensaml.core.xml.util.XMLObjectSupport; +import org.opensaml.saml.common.xml.SAMLConstants; +import org.opensaml.saml.saml2.core.Attribute; +import org.opensaml.saml.saml2.core.NameIDType; +import org.opensaml.saml.saml2.metadata.ContactPerson; +import org.opensaml.saml.saml2.metadata.EntityDescriptor; +import org.opensaml.saml.saml2.metadata.Organization; +import org.opensaml.saml.saml2.metadata.RequestedAttribute; +import org.opensaml.saml.security.impl.SAMLSignatureProfileValidator; +import org.opensaml.security.SecurityException; +import org.opensaml.security.credential.Credential; +import org.opensaml.security.x509.BasicX509Credential; +import org.opensaml.xmlsec.signature.support.SignatureException; +import org.opensaml.xmlsec.signature.support.SignatureValidator; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import net.shibboleth.utilities.java.support.xml.XMLParserException; + + + + + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration({ "/spring/test_eaaf_pvp.beans.xml", + "/spring/test_eaaf_core_spring_config.beans.xml", + "/spring/eaaf_utils.beans.xml" }) +@TestPropertySource(locations = { "/config/config_1.props" }) +public class MetadataBuilderTest { + + @Autowired private PvpMetadataBuilder metadataBuilder; + @Autowired private DummyCredentialProvider credentialProvider; + + private static CertificateFactory fact; + + /** + * JUnit class initializer. + * + * @throws Exception In case of an OpenSAML3 initialization error + */ + @BeforeClass + public static void classInitializer() throws Exception { + EaafOpenSaml3xInitializer.eaafInitialize(); + + fact = CertificateFactory.getInstance("X.509"); + } + + @Test + public void buildIdpMetadata() throws CredentialsNotAvailableException, EaafException, + SecurityException, TransformerFactoryConfigurationError, MarshallingException, + TransformerException, ParserConfigurationException, IOException, SignatureException, + XMLParserException, UnmarshallingException, CertificateException { + + final IPvpMetadataBuilderConfiguration config = idpMetadataConfig(credentialProvider, false, true); + + //generate metadata + final String metadata = metadataBuilder.buildPvpMetadata(config); + + //validate + final EntityDescriptor entity = validateMetadata(metadata); + Assert.assertNotNull("IDPSSODescr. is null", entity.getIDPSSODescriptor(SAMLConstants.SAML20P_NS)); + Assert.assertNull("IDPSSODescr. is null", entity.getSPSSODescriptor(SAMLConstants.SAML20P_NS)); + + } + + @Test + public void buildSpMetadata() throws CredentialsNotAvailableException, EaafException, + SecurityException, TransformerFactoryConfigurationError, MarshallingException, + TransformerException, ParserConfigurationException, IOException, SignatureException, + XMLParserException, UnmarshallingException, CertificateException { + + final IPvpMetadataBuilderConfiguration config = idpMetadataConfig(credentialProvider, true, false); + + //generate metadata + final String metadata = metadataBuilder.buildPvpMetadata(config); + + //validate + final EntityDescriptor entity = validateMetadata(metadata); + Assert.assertNull("IDPSSODescr. is null", entity.getIDPSSODescriptor(SAMLConstants.SAML20P_NS)); + Assert.assertNotNull("IDPSSODescr. is null", entity.getSPSSODescriptor(SAMLConstants.SAML20P_NS)); + + } + + @Test + public void buildSpAndIdpMetadata() throws CredentialsNotAvailableException, EaafException, + SecurityException, TransformerFactoryConfigurationError, MarshallingException, + TransformerException, ParserConfigurationException, IOException, SignatureException, + XMLParserException, UnmarshallingException, CertificateException { + + final IPvpMetadataBuilderConfiguration config = idpMetadataConfig(credentialProvider, true, true); + + //generate metadata + final String metadata = metadataBuilder.buildPvpMetadata(config); + + //validate + final EntityDescriptor entity = validateMetadata(metadata); + Assert.assertNotNull("IDPSSODescr. is null", entity.getIDPSSODescriptor(SAMLConstants.SAML20P_NS)); + Assert.assertNotNull("IDPSSODescr. is null", entity.getSPSSODescriptor(SAMLConstants.SAML20P_NS)); + + } + + private EntityDescriptor validateMetadata(String metadata) throws UnsupportedEncodingException, + XMLParserException, UnmarshallingException, SignatureException, CertificateException { + Assert.assertNotNull("Metadata is null", metadata); + Assert.assertFalse("Metadata is empty", metadata.isEmpty()); + + final EntityDescriptor entity = (EntityDescriptor) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + new ByteArrayInputStream(metadata.getBytes("UTF-8"))); + + Assert.assertNotNull("Unmarshalling failed", entity); + Assert.assertNotNull("EntityId is null", entity.getEntityID()); + + Assert.assertNotNull("Signature is null", entity.getSignature()); + final SAMLSignatureProfileValidator sigValidator = new SAMLSignatureProfileValidator(); + sigValidator.validate(entity.getSignature()); + + final Credential cred = new BasicX509Credential((X509Certificate) fact.generateCertificate( + MetadataResolverTest.class.getResourceAsStream("/data/junit_metadata_sig_cert.crt"))); + SignatureValidator.validate(entity.getSignature(), cred); + + return entity; + } + + public static IPvpMetadataBuilderConfiguration idpMetadataConfig(IPvp2CredentialProvider credentialProvider, boolean buildSpInfos, boolean buildIdpInfos) { + return new IPvpMetadataBuilderConfiguration() { + + @Override + public boolean wantAuthnRequestSigned() { + return true; + } + + @Override + public boolean wantAssertionSigned() { + return true; + } + + @Override + public String getSpSloSoapBindingUrl() { + return RandomStringUtils.randomAlphabetic(10); + + } + + @Override + public String getSpSloRedirectBindingUrl() { + return RandomStringUtils.randomAlphabetic(10); + + } + + @Override + public String getSpSloPostBindingUrl() { + return RandomStringUtils.randomAlphabetic(10); + } + + @Override + public Collection<RequestedAttribute> getSpRequiredAttributes() { + return null; + } + + @Override + public String getSpNameForLogging() { + return RandomStringUtils.randomAlphabetic(10); + } + + @Override + public String getSpAssertionConsumerServiceRedirectBindingUrl() { + return RandomStringUtils.randomAlphabetic(10); + } + + @Override + public String getSpAssertionConsumerServicePostBindingUrl() { + return RandomStringUtils.randomAlphabetic(10); + } + + @Override + public List<String> getSpAllowedNameIdTypes() { + return Arrays.asList(NameIDType.PERSISTENT); + } + + @Override + public Credential getRequestorResponseSigningCredentials() throws CredentialsNotAvailableException { + return credentialProvider.getMessageSigningCredential(); + } + + @Override + public Organization getOrgansiationInformation() { + return null; + } + + @Override + public int getMetadataValidUntil() { + return 10; + } + + @Override + public EaafX509Credential getMetadataSigningCredentials() throws CredentialsNotAvailableException { + return credentialProvider.getMetaDataSigningCredential(); + } + + @Override + public String getIdpWebSsoRedirectBindingUrl() { + return RandomStringUtils.randomAlphabetic(10); + } + + @Override + public String getIdpWebSsoPostBindingUrl() { + return RandomStringUtils.randomAlphabetic(10); + } + + @Override + public String getIdpSloRedirectBindingUrl() { + return RandomStringUtils.randomAlphabetic(10); + } + + @Override + public String getIdpSloPostBindingUrl() { + return RandomStringUtils.randomAlphabetic(10); + } + + @Override + public List<String> getIdpPossibleNameIdTypes() { + return Arrays.asList(NameIDType.PERSISTENT); + } + + @Override + public List<Attribute> getIdpPossibleAttributes() { + return null; + } + + @Override + public String getEntityID() { + return RandomStringUtils.randomAlphabetic(10); + } + + @Override + public String getEntityFriendlyName() { + return RandomStringUtils.randomAlphabetic(10); + } + + @Override + public Credential getEncryptionCredentials() throws CredentialsNotAvailableException { + return credentialProvider.getMessageSigningCredential(); + } + + @Override + public List<ContactPerson> getContactPersonInformation() { + return null; + } + + @Override + public boolean buildSpSsoDescriptor() { + return buildSpInfos; + } + + @Override + public boolean buildIdpSsoDescriptor() { + return buildIdpInfos; + } + + @Override + public boolean buildEntitiesDescriptorAsRootElement() { + return false; + } + }; + } +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/metadata/MetadataResolverTest.java b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/metadata/MetadataResolverTest.java new file mode 100644 index 00000000..accdd8b0 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/java/at/gv/egiz/eaaf/modules/pvp2/test/metadata/MetadataResolverTest.java @@ -0,0 +1,742 @@ +package at.gv.egiz.eaaf.modules.pvp2.test.metadata; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.List; + +import javax.xml.transform.TransformerException; + +import at.gv.egiz.eaaf.core.impl.utils.IHttpClientFactory; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2InternalErrorException; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2MetadataException; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlSigningException; +import at.gv.egiz.eaaf.modules.pvp2.impl.metadata.PvpMetadataResolverFactory; +import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafOpenSaml3xInitializer; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils; +import at.gv.egiz.eaaf.modules.pvp2.impl.validation.TrustEngineFactory; +import at.gv.egiz.eaaf.modules.pvp2.impl.validation.metadata.PvpEntityCategoryFilter; +import at.gv.egiz.eaaf.modules.pvp2.impl.validation.metadata.SchemaValidationFilter; +import at.gv.egiz.eaaf.modules.pvp2.impl.validation.metadata.SimpleMetadataSignatureVerificationFilter; +import at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyCredentialProvider; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.RandomStringUtils; +import org.joda.time.DateTime; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.opensaml.core.config.ConfigurationService; +import org.opensaml.core.criterion.EntityIdCriterion; +import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport; +import org.opensaml.core.xml.io.MarshallingException; +import org.opensaml.core.xml.io.UnmarshallingException; +import org.opensaml.core.xml.util.XMLObjectSupport; +import org.opensaml.saml.common.xml.SAMLConstants; +import org.opensaml.saml.criterion.EntityRoleCriterion; +import org.opensaml.saml.metadata.resolver.filter.MetadataFilter; +import org.opensaml.saml.metadata.resolver.filter.MetadataFilterChain; +import org.opensaml.saml.metadata.resolver.filter.impl.RequiredValidUntilFilter; +import org.opensaml.saml.metadata.resolver.impl.PredicateRoleDescriptorResolver; +import org.opensaml.saml.saml2.metadata.EntityDescriptor; +import org.opensaml.saml.saml2.metadata.RequestedAttribute; +import org.opensaml.saml.saml2.metadata.SPSSODescriptor; +import org.opensaml.saml.security.impl.MetadataCredentialResolver; +import org.opensaml.security.credential.Credential; +import org.opensaml.security.credential.UsageType; +import org.opensaml.security.criteria.UsageCriterion; +import org.opensaml.security.x509.BasicX509Credential; +import org.opensaml.xmlsec.SignatureValidationConfiguration; +import org.opensaml.xmlsec.SignatureValidationParameters; +import org.opensaml.xmlsec.keyinfo.KeyInfoCredentialResolver; +import org.opensaml.xmlsec.keyinfo.impl.BasicProviderKeyInfoCredentialResolver; +import org.opensaml.xmlsec.keyinfo.impl.KeyInfoProvider; +import org.opensaml.xmlsec.keyinfo.impl.provider.DSAKeyValueProvider; +import org.opensaml.xmlsec.keyinfo.impl.provider.InlineX509DataProvider; +import org.opensaml.xmlsec.keyinfo.impl.provider.RSAKeyValueProvider; +import org.opensaml.xmlsec.signature.support.SignatureValidationParametersCriterion; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.w3c.dom.Element; + +import net.shibboleth.utilities.java.support.component.ComponentInitializationException; +import net.shibboleth.utilities.java.support.resolver.CriteriaSet; +import net.shibboleth.utilities.java.support.resolver.ResolverException; +import net.shibboleth.utilities.java.support.xml.SerializeSupport; +import net.shibboleth.utilities.java.support.xml.XMLParserException; +import okhttp3.HttpUrl; +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration({ "/spring/test_eaaf_pvp.beans.xml", + "/spring/test_eaaf_core_spring_config.beans.xml", + "/spring/eaaf_utils.beans.xml" }) +@TestPropertySource(locations = { "/config/config_1.props" }) +public class MetadataResolverTest { + + private static MockWebServer mockWebServer; + private static HttpUrl mockServerUrl; + + @Autowired + private PvpMetadataResolverFactory metadataResolverFactory; + @Autowired + private IHttpClientFactory httpClientFactory; + @Autowired private DummyCredentialProvider credentialProvider; + + /** + * JUnit class initializer. + * + * @throws Exception In case of an OpenSAML3 initialization error + */ + @BeforeClass + public static void classInitializer() throws Exception { + EaafOpenSaml3xInitializer.eaafInitialize(); + mockWebServer = new MockWebServer(); + mockServerUrl = mockWebServer.url("/sp/metadata"); + + } + + /** + * Single test initializer. + * + */ + @Before + public void testInitializer() { + + } + + @Test + public void wrongSchema() { + final List<MetadataFilter> filterList = new ArrayList<>(); + filterList.add(new SchemaValidationFilter(true)); + + final MetadataFilterChain filterChain = new MetadataFilterChain(); + filterChain.setFilters(filterList); + + try { + metadataResolverFactory.createMetadataProvider( + "classpath:/data/pvp_metadata_wrong_schema.xml", + filterChain, "jUnit test", null); + Assert.fail("Wrong XML Schema not detected"); + + } catch (final Pvp2MetadataException e) { + Assert.assertEquals("Wrong ErrorCode", "internal.pvp.08", e.getErrorId()); + Assert.assertNotNull("params null", e.getParams()); + Assert.assertEquals("Params size", 2, e.getParams().length); + Assert.assertEquals("Param[0] wrong", + "classpath:/data/pvp_metadata_wrong_schema.xml", e.getParams()[0]); + + } + + } + + @Test + public void simpleClasspathMetadataWithoutSigValidation() + throws Pvp2MetadataException, ComponentInitializationException, ResolverException, + Pvp2InternalErrorException { + final List<MetadataFilter> filterList = new ArrayList<>(); + filterList.add(new SchemaValidationFilter(true)); + + final MetadataFilterChain filterChain = new MetadataFilterChain(); + filterChain.setFilters(filterList); + + final IPvp2MetadataProvider mdResolver = metadataResolverFactory.createMetadataProvider( + "classpath:/data/pvp_metadata_wrong_sig.xml", + filterChain, "jUnit test", null); + + final EntityDescriptor entityIdNotExists = mdResolver.getEntityDescriptor( + "https://demo.egiz.gv.at/notExtist/"); + Assert.assertNull("No EntityDescripter", entityIdNotExists); + + final EntityDescriptor entityId = mdResolver.getEntityDescriptor( + "https://demo.egiz.gv.at/demoportal_demologin/"); + Assert.assertNotNull("No EntityDescripter", entityId); + + Assert.assertNotNull("Metadata provider is null", mdResolver); + final MetadataCredentialResolver resolver = createKeyInfoResolver(mdResolver); + + final CriteriaSet criteriaSet = new CriteriaSet(); + criteriaSet.add(new EntityIdCriterion("https://demo.egiz.gv.at/demoportal_demologin/")); + criteriaSet.add(new EntityRoleCriterion(SPSSODescriptor.DEFAULT_ELEMENT_NAME)); + criteriaSet.add(new UsageCriterion(UsageType.SIGNING)); + final SignatureValidationParameters sigValCrit = new SignatureValidationParameters(); + sigValCrit.setBlacklistedAlgorithms( + ConfigurationService.get(SignatureValidationConfiguration.class) + .getBlacklistedAlgorithms()); + sigValCrit.setSignatureTrustEngine( + TrustEngineFactory.getSignatureKnownKeysTrustEngine(mdResolver)); + criteriaSet.add(new SignatureValidationParametersCriterion(sigValCrit)); + + final Iterable<Credential> keyInfos = resolver.resolve(criteriaSet); + Assert.assertNotNull("KeyInfos null", keyInfos); + + } + + @Test + public void noCredentials() { + final String metadataUrl = "classpath:/data/pvp_metadata_moaid_test.xml"; + + final List<BasicX509Credential> credentials = new ArrayList<>(); + + final List<MetadataFilter> filterList = new ArrayList<>(); + filterList.add(new SchemaValidationFilter(true)); + + filterList.add(new SimpleMetadataSignatureVerificationFilter( + credentials, + metadataUrl)); + + final MetadataFilterChain filterChain = new MetadataFilterChain(); + filterChain.setFilters(filterList); + + try { + metadataResolverFactory.createMetadataProvider( + metadataUrl, + filterChain, "jUnit test", null); + Assert.fail("Untrusted signature not detected"); + + } catch (final Pvp2MetadataException e) { + Assert.assertEquals("Wrong errorCode", "internal.pvp.07", e.getErrorId()); + + } + + } + + @Test + public void wrongCredentials() throws CertificateException { + final String metadataUrl = "classpath:/data/pvp_metadata_moaid_test.xml"; + + final List<BasicX509Credential> credentials = new ArrayList<>(); + final CertificateFactory fact = CertificateFactory.getInstance("X.509"); + final BasicX509Credential credential = new BasicX509Credential((X509Certificate) fact.generateCertificate( + MetadataResolverTest.class.getResourceAsStream("/data/assertion_sig_cert.crt"))); + credentials.add(credential); + + final List<MetadataFilter> filterList = new ArrayList<>(); + filterList.add(new SchemaValidationFilter(true)); + + filterList.add(new SimpleMetadataSignatureVerificationFilter( + credentials, + metadataUrl)); + + final MetadataFilterChain filterChain = new MetadataFilterChain(); + filterChain.setFilters(filterList); + + try { + metadataResolverFactory.createMetadataProvider( + metadataUrl, + filterChain, "jUnit test", null); + Assert.fail("Untrusted signature not detected"); + + } catch (final Pvp2MetadataException e) { + Assert.assertEquals("Wrong errorCode", "internal.pvp.07", e.getErrorId()); + + } + + } + + @Test + public void validCredentialsInvalidSig() throws CertificateException, Pvp2MetadataException, + ResolverException { + final String metadataUrl = "classpath:/data/pvp_metadata_moaid_test.xml"; + + final List<BasicX509Credential> credentials = new ArrayList<>(); + final CertificateFactory fact = CertificateFactory.getInstance("X.509"); + credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate( + MetadataResolverTest.class.getResourceAsStream("/data/assertion_sig_cert.crt")))); + credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate( + MetadataResolverTest.class.getResourceAsStream("/data/metadata_sig_cert.crt")))); + + final List<MetadataFilter> filterList = new ArrayList<>(); + filterList.add(new SchemaValidationFilter(true)); + + filterList.add(new SimpleMetadataSignatureVerificationFilter( + credentials, + metadataUrl)); + + final MetadataFilterChain filterChain = new MetadataFilterChain(); + filterChain.setFilters(filterList); + try { + metadataResolverFactory.createMetadataProvider( + metadataUrl, + filterChain, "jUnit test", null); + Assert.fail("Untrusted signature not detected"); + + } catch (final Pvp2MetadataException e) { + Assert.assertEquals("Wrong errorCode", "internal.pvp.07", e.getErrorId()); + + } + + } + + @Test + public void metadataSignatureValidCredentials() throws CertificateException, Pvp2MetadataException, + ResolverException, XMLParserException, UnmarshallingException, SamlSigningException, + CredentialsNotAvailableException, MarshallingException, TransformerException, IOException { + + mockWebServer.shutdown(); + mockWebServer = new MockWebServer(); + mockServerUrl = mockWebServer.url("/sp/metadata"); + + final EntityDescriptor metadata = (EntityDescriptor) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + MetadataResolverTest.class.getResourceAsStream("/data/pvp_metadata_moaid_test.xml")); + metadata.setValidUntil(DateTime.now().plusDays(1)); + metadata.setSignature(null); + metadata.setEntityID(RandomStringUtils.randomAlphabetic(10)); + final EntityDescriptor signedMatadata = + Saml2Utils.signSamlObject(metadata, credentialProvider.getMetaDataSigningCredential(), true); + final Element metadataElement = XMLObjectSupport.marshall(signedMatadata); + mockWebServer.enqueue(new MockResponse().setResponseCode(200) + .setBody(SerializeSupport.nodeToString(metadataElement)) + .setHeader("Content-Type", "text/html;charset=utf-8")); + + final List<BasicX509Credential> credentials = new ArrayList<>(); + final CertificateFactory fact = CertificateFactory.getInstance("X.509"); + credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate( + MetadataResolverTest.class.getResourceAsStream("/data/metadata_sig_cert.crt")))); + credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate( + MetadataResolverTest.class.getResourceAsStream("/data/assertion_sig_cert.crt")))); + credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate( + MetadataResolverTest.class.getResourceAsStream("/data/junit_metadata_sig_cert.crt")))); + + final List<MetadataFilter> filterList = new ArrayList<>(); + filterList.add(new SchemaValidationFilter(true)); + filterList.add(new SimpleMetadataSignatureVerificationFilter( + credentials, + mockServerUrl.url().toString())); + filterList.add(new PvpEntityCategoryFilter(true)); + + final MetadataFilterChain filterChain = new MetadataFilterChain(); + filterChain.setFilters(filterList); + + final IPvp2MetadataProvider mdResolver = metadataResolverFactory.createMetadataProvider( + mockServerUrl.url().toString(), + filterChain, "jUnit test", httpClientFactory.getHttpClient()); + + final EntityDescriptor entityIdNotExists = mdResolver.getEntityDescriptor( + metadata.getEntityID()); + Assert.assertNotNull("No EntityDescripter", entityIdNotExists); + + } + + @Test + public void metadataSignatureValidCredentialsSecond() throws CertificateException, Pvp2MetadataException, + ResolverException, XMLParserException, UnmarshallingException, SamlSigningException, + CredentialsNotAvailableException, MarshallingException, TransformerException, IOException { + + final EntityDescriptor metadata = (EntityDescriptor) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + MetadataResolverTest.class.getResourceAsStream("/data/pvp_metadata_valid_with_entityCategory.xml")); + metadata.setValidUntil(DateTime.now().plusDays(1)); + metadata.setSignature(null); + metadata.setEntityID(RandomStringUtils.randomAlphabetic(10)); + final EntityDescriptor signedMatadata = + Saml2Utils.signSamlObject(metadata, credentialProvider.getMetaDataSigningCredential(), true); + final Element metadataElement = XMLObjectSupport.marshall(signedMatadata); + mockWebServer.enqueue(new MockResponse().setResponseCode(200) + .setBody(SerializeSupport.nodeToString(metadataElement)) + .setHeader("Content-Type", "text/html;charset=utf-8")); + + final List<BasicX509Credential> credentials = new ArrayList<>(); + final CertificateFactory fact = CertificateFactory.getInstance("X.509"); + credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate( + MetadataResolverTest.class.getResourceAsStream("/data/metadata_sig_cert.crt")))); + credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate( + MetadataResolverTest.class.getResourceAsStream("/data/assertion_sig_cert.crt")))); + credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate( + MetadataResolverTest.class.getResourceAsStream("/data/junit_metadata_sig_cert.crt")))); + + final List<MetadataFilter> filterList = new ArrayList<>(); + filterList.add(new SchemaValidationFilter(true)); + filterList.add(new SimpleMetadataSignatureVerificationFilter( + credentials, + mockServerUrl.url().toString())); + filterList.add(new PvpEntityCategoryFilter(true)); + + final MetadataFilterChain filterChain = new MetadataFilterChain(); + filterChain.setFilters(filterList); + + final IPvp2MetadataProvider mdResolver = metadataResolverFactory.createMetadataProvider( + mockServerUrl.url().toString(), + filterChain, "jUnit test", httpClientFactory.getHttpClient()); + + + + final EntityDescriptor descr = mdResolver.getEntityDescriptor(metadata.getEntityID()); + Assert.assertNotNull("No EntityDescripter", descr); + + final List<RequestedAttribute> reqAttr = descr.getSPSSODescriptor(SAMLConstants.SAML20P_NS) + .getAttributeConsumingServices().get(0).getRequestAttributes(); + Assert.assertNotNull("Req. attributes are null", reqAttr); + Assert.assertEquals("# of req. attributes", 20, reqAttr.size()); + + } + + @Test + public void metadataSignatureValidCredentialsThird() throws CertificateException, Pvp2MetadataException, + ResolverException, XMLParserException, UnmarshallingException, SamlSigningException, + CredentialsNotAvailableException, MarshallingException, TransformerException, IOException { + + final EntityDescriptor metadata = (EntityDescriptor) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + MetadataResolverTest.class.getResourceAsStream("/data/pvp_metadata_valid_with_entityCategory_egov.xml")); + metadata.setValidUntil(DateTime.now().plusDays(1)); + metadata.setSignature(null); + metadata.setEntityID(RandomStringUtils.randomAlphabetic(10)); + final EntityDescriptor signedMatadata = + Saml2Utils.signSamlObject(metadata, credentialProvider.getMetaDataSigningCredential(), true); + final Element metadataElement = XMLObjectSupport.marshall(signedMatadata); + mockWebServer.enqueue(new MockResponse().setResponseCode(200) + .setBody(SerializeSupport.nodeToString(metadataElement)) + .setHeader("Content-Type", "text/html;charset=utf-8")); + + final List<BasicX509Credential> credentials = new ArrayList<>(); + final CertificateFactory fact = CertificateFactory.getInstance("X.509"); + credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate( + MetadataResolverTest.class.getResourceAsStream("/data/metadata_sig_cert.crt")))); + credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate( + MetadataResolverTest.class.getResourceAsStream("/data/assertion_sig_cert.crt")))); + credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate( + MetadataResolverTest.class.getResourceAsStream("/data/junit_metadata_sig_cert.crt")))); + + final List<MetadataFilter> filterList = new ArrayList<>(); + filterList.add(new SchemaValidationFilter(true)); + filterList.add(new SimpleMetadataSignatureVerificationFilter( + credentials, + mockServerUrl.url().toString())); + filterList.add(new PvpEntityCategoryFilter(true)); + + final MetadataFilterChain filterChain = new MetadataFilterChain(); + filterChain.setFilters(filterList); + + final IPvp2MetadataProvider mdResolver = metadataResolverFactory.createMetadataProvider( + mockServerUrl.url().toString(), + filterChain, "jUnit test", httpClientFactory.getHttpClient()); + + + + final EntityDescriptor descr = mdResolver.getEntityDescriptor(metadata.getEntityID()); + Assert.assertNotNull("No EntityDescripter", descr); + + final List<RequestedAttribute> reqAttr = descr.getSPSSODescriptor(SAMLConstants.SAML20P_NS) + .getAttributeConsumingServices().get(0).getRequestAttributes(); + Assert.assertNotNull("Req. attributes are null", reqAttr); + Assert.assertEquals("# of req. attributes", 9, reqAttr.size()); + + } + + @Test + public void metadataExpired() throws CertificateException, Pvp2MetadataException, + ResolverException, XMLParserException, UnmarshallingException, SamlSigningException, + CredentialsNotAvailableException, MarshallingException, TransformerException, IOException { + + final EntityDescriptor metadata = (EntityDescriptor) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + MetadataResolverTest.class.getResourceAsStream("/data/pvp_metadata_valid.xml")); + metadata.setValidUntil(DateTime.now().minusDays(2)); + metadata.setSignature(null); + Saml2Utils.signSamlObject(metadata, credentialProvider.getMetaDataSigningCredential(), true); + final Element metadataElement = XMLObjectSupport.marshall(metadata); + + mockWebServer.enqueue(new MockResponse().setResponseCode(200) + .setBody(SerializeSupport.nodeToString(metadataElement)) + .setHeader("Content-Type", "text/html;charset=utf-8")); + + final List<BasicX509Credential> credentials = new ArrayList<>(); + final CertificateFactory fact = CertificateFactory.getInstance("X.509"); + credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate( + MetadataResolverTest.class.getResourceAsStream("/data/metadata_sig_cert.crt")))); + credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate( + MetadataResolverTest.class.getResourceAsStream("/data/assertion_sig_cert.crt")))); + credentials.add(new BasicX509Credential((X509Certificate) fact.generateCertificate( + MetadataResolverTest.class.getResourceAsStream("/data/junit_metadata_sig_cert.crt")))); + + final List<MetadataFilter> filterList = new ArrayList<>(); + filterList.add(new SchemaValidationFilter(true)); + filterList.add(new SimpleMetadataSignatureVerificationFilter( + credentials, + mockServerUrl.url().toString())); + filterList.add(new RequiredValidUntilFilter()); + filterList.add(new PvpEntityCategoryFilter(false)); + + + final MetadataFilterChain filterChain = new MetadataFilterChain(); + filterChain.setFilters(filterList); + + try { + metadataResolverFactory.createMetadataProvider( + mockServerUrl.url().toString(), + filterChain, "jUnit test", httpClientFactory.getHttpClient()); + Assert.fail("Expired metadata not detected"); + + } catch (final Pvp2MetadataException e) { + Assert.assertEquals("Wrong errorCode", "internal.pvp.09", e.getErrorId()); + + } + + + } + + @Test + public void simpleClasspathMetadataWithoutSigValidationMoaidTwoSigKeys() + throws Pvp2MetadataException, ComponentInitializationException, ResolverException, + Pvp2InternalErrorException { + final List<MetadataFilter> filterList = new ArrayList<>(); + filterList.add(new SchemaValidationFilter(true)); + + final MetadataFilterChain filterChain = new MetadataFilterChain(); + filterChain.setFilters(filterList); + + final String entityIdToResolve = "https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/metadata"; + + final IPvp2MetadataProvider mdResolver = metadataResolverFactory.createMetadataProvider( + "classpath:/data/pvp_metadata_moaid_test.xml", + filterChain, "jUnit test", null); + + final EntityDescriptor entityIdNotExists = mdResolver.getEntityDescriptor( + "https://demo.egiz.gv.at/notExtist/"); + Assert.assertNull("No EntityDescripter", entityIdNotExists); + + final EntityDescriptor entityId = mdResolver.getEntityDescriptor(entityIdToResolve); + Assert.assertNotNull("No EntityDescripter", entityId); + + Assert.assertNotNull("Metadata provider is null", mdResolver); + final MetadataCredentialResolver resolver = createKeyInfoResolver(mdResolver); + + final CriteriaSet sigCriteriaSet = new CriteriaSet(); + sigCriteriaSet.add(new EntityIdCriterion(entityIdToResolve)); + sigCriteriaSet.add(new EntityRoleCriterion(SPSSODescriptor.DEFAULT_ELEMENT_NAME)); + sigCriteriaSet.add(new UsageCriterion(UsageType.SIGNING)); + final SignatureValidationParameters sigValCrit = new SignatureValidationParameters(); + sigValCrit.setBlacklistedAlgorithms( + ConfigurationService.get(SignatureValidationConfiguration.class) + .getBlacklistedAlgorithms()); + sigValCrit.setSignatureTrustEngine( + TrustEngineFactory.getSignatureKnownKeysTrustEngine(mdResolver)); + sigCriteriaSet.add(new SignatureValidationParametersCriterion(sigValCrit)); + + final Iterable<Credential> singingKeyInfos = resolver.resolve(sigCriteriaSet); + Assert.assertNotNull("Signing KeyInfos null", singingKeyInfos); + Assert.assertTrue("First Credential resolved", singingKeyInfos.iterator().hasNext()); + Assert.assertTrue("Second Credential resolved", singingKeyInfos.iterator().hasNext()); + + final CriteriaSet encCriteriaSet = new CriteriaSet(); + encCriteriaSet.add(new EntityIdCriterion(entityIdToResolve)); + encCriteriaSet.add(new EntityRoleCriterion(SPSSODescriptor.DEFAULT_ELEMENT_NAME)); + encCriteriaSet.add(new UsageCriterion(UsageType.ENCRYPTION)); + final Iterable<Credential> encKeyInfos = resolver.resolve(encCriteriaSet); + Assert.assertNotNull("Encryption KeyInfos null", encKeyInfos); + Assert.assertTrue("No Credential resolved", encKeyInfos.iterator().hasNext()); + + } + + @Test + public void httpMetadataLoading() throws UnsupportedEncodingException, + IOException, ResolverException, Pvp2MetadataException { + + mockWebServer.enqueue(new MockResponse().setResponseCode(200) + .setBody(new String(IOUtils.toByteArray( + MetadataResolverTest.class.getResourceAsStream( + "/data/pvp_metadata_moaid_test.xml")), "UTF-8")) + .setHeader("Content-Type", "text/xml")); + + final List<MetadataFilter> filterList = new ArrayList<>(); + filterList.add(new SchemaValidationFilter(true)); + + final MetadataFilterChain filterChain = new MetadataFilterChain(); + filterChain.setFilters(filterList); + + final String entityIdToResolve = "https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/metadata"; + + final IPvp2MetadataProvider mdResolver = metadataResolverFactory.createMetadataProvider( + mockServerUrl.url().toString(), + filterChain, "jUnit test", httpClientFactory.getHttpClient()); + + final EntityDescriptor entityIdNotExists = mdResolver.getEntityDescriptor( + "https://demo.egiz.gv.at/notExtist/"); + Assert.assertNull("No EntityDescripter", entityIdNotExists); + + final EntityDescriptor entityId = mdResolver.getEntityDescriptor(entityIdToResolve); + Assert.assertNotNull("No EntityDescripter", entityId); + + } + + @Test + public void httpMetadataLoadingRefeshFailed() throws UnsupportedEncodingException, + IOException, ResolverException, Pvp2MetadataException { + + mockWebServer.enqueue(new MockResponse().setResponseCode(200) + .setBody(new String(IOUtils.toByteArray( + MetadataResolverTest.class.getResourceAsStream( + "/data/pvp_metadata_moaid_test.xml")), "UTF-8")) + .setHeader("Content-Type", "text/xml")); + + final List<MetadataFilter> filterList = new ArrayList<>(); + filterList.add(new SchemaValidationFilter(true)); + + final MetadataFilterChain filterChain = new MetadataFilterChain(); + filterChain.setFilters(filterList); + + final String entityIdToResolve = "https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/metadata"; + + final IPvp2MetadataProvider mdResolver = metadataResolverFactory.createMetadataProvider( + mockServerUrl.url().toString(), + filterChain, "jUnit test", httpClientFactory.getHttpClient()); + + final EntityDescriptor entityIdNotExists = mdResolver.getEntityDescriptor( + "https://demo.egiz.gv.at/notExtist/"); + Assert.assertNull("No EntityDescripter", entityIdNotExists); + + final EntityDescriptor entityId = mdResolver.getEntityDescriptor(entityIdToResolve); + Assert.assertNotNull("No EntityDescripter", entityId); + + final DateTime lastRefreshSucess = mdResolver.getLastSuccessfulRefresh(); + + try { + mdResolver.refresh(); + Assert.fail("Refesh possible without available metadata"); + + } catch (final ResolverException e) { + Assert.assertFalse("Wrong Refesh success flag", mdResolver.wasLastRefreshSuccess()); + Assert.assertEquals("Wrong refresh success date", lastRefreshSucess, mdResolver + .getLastSuccessfulRefresh()); + + } + + } + + @Test + public void httpMetadataLoadingWithRefeshSuccess() throws UnsupportedEncodingException, + IOException, ResolverException, Pvp2MetadataException { + + mockWebServer.enqueue(new MockResponse().setResponseCode(200) + .setBody(new String(IOUtils.toByteArray( + MetadataResolverTest.class.getResourceAsStream( + "/data/pvp_metadata_moaid_test.xml")), "UTF-8")) + .setHeader("Content-Type", "text/xml")); + + mockWebServer.enqueue(new MockResponse().setResponseCode(200) + .setBody(new String(IOUtils.toByteArray( + MetadataResolverTest.class.getResourceAsStream( + "/data/pvp_metadata_moaid_test.xml")), "UTF-8")) + .setHeader("Content-Type", "text/xml")); + + final List<MetadataFilter> filterList = new ArrayList<>(); + filterList.add(new SchemaValidationFilter(true)); + + final MetadataFilterChain filterChain = new MetadataFilterChain(); + filterChain.setFilters(filterList); + + final String entityIdToResolve = "https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/metadata"; + + final IPvp2MetadataProvider mdResolver = metadataResolverFactory.createMetadataProvider( + mockServerUrl.url().toString(), + filterChain, "jUnit test", httpClientFactory.getHttpClient()); + + final EntityDescriptor entityIdNotExists = mdResolver.getEntityDescriptor( + "https://demo.egiz.gv.at/notExtist/"); + Assert.assertNull("No EntityDescripter", entityIdNotExists); + + final EntityDescriptor entityId = mdResolver.getEntityDescriptor(entityIdToResolve); + Assert.assertNotNull("No EntityDescripter", entityId); + + // refresh metadata + mdResolver.refresh(); + + Assert.assertTrue("Refresh not sucessful", mdResolver.wasLastRefreshSuccess()); + + } + + @Test + public void httpMetadataLoadingWithoutHttpClient() throws UnsupportedEncodingException, + IOException, ResolverException, Pvp2MetadataException { + + mockWebServer.enqueue(new MockResponse().setResponseCode(200) + .setBody(new String(IOUtils.toByteArray( + MetadataResolverTest.class.getResourceAsStream( + "/data/pvp_metadata_moaid_test.xml")), "UTF-8")) + .setHeader("Content-Type", "text/xml")); + + final List<MetadataFilter> filterList = new ArrayList<>(); + filterList.add(new SchemaValidationFilter(true)); + + final MetadataFilterChain filterChain = new MetadataFilterChain(); + filterChain.setFilters(filterList); + + try { + metadataResolverFactory.createMetadataProvider( + mockServerUrl.url().toString(), + filterChain, "jUnit test", null); + Assert.fail("No httpclient not detected"); + + } catch (final Pvp2MetadataException e) { + Assert.assertEquals("Wrong errorCode", "internal.pvp.09", e.getErrorId()); + Assert.assertNotNull("No error params", e.getParams()); + Assert.assertEquals("Wrong params size", 2, e.getParams().length); + + } + } + + @Test + public void httpMetadataLoadingWrongUrl() throws UnsupportedEncodingException, + IOException, ResolverException, Pvp2MetadataException { + + mockWebServer.enqueue(new MockResponse().setResponseCode(200) + .setBody(new String(IOUtils.toByteArray( + MetadataResolverTest.class.getResourceAsStream( + "/data/pvp_metadata_moaid_test.xml")), "UTF-8")) + .setHeader("Content-Type", "text/xml")); + + final List<MetadataFilter> filterList = new ArrayList<>(); + filterList.add(new SchemaValidationFilter(true)); + + final MetadataFilterChain filterChain = new MetadataFilterChain(); + filterChain.setFilters(filterList); + + try { + metadataResolverFactory.createMetadataProvider( + "http://127.0.0.1/notexist", + filterChain, "jUnit test", httpClientFactory.getHttpClient()); + Assert.fail("No httpclient not detected"); + + } catch (final Pvp2MetadataException e) { + Assert.assertEquals("Wrong errorCode", "internal.pvp.09", e.getErrorId()); + Assert.assertNotNull("No error params", e.getParams()); + Assert.assertEquals("Wrong params size", 2, e.getParams().length); + + } + + } + + private MetadataCredentialResolver createKeyInfoResolver(IPvp2MetadataProvider mdResolver) + throws ComponentInitializationException { + final List<KeyInfoProvider> keyInfoProvider = new ArrayList<>(); + keyInfoProvider.add(new DSAKeyValueProvider()); + keyInfoProvider.add(new RSAKeyValueProvider()); + keyInfoProvider.add(new InlineX509DataProvider()); + final KeyInfoCredentialResolver keyInfoCredentialResolver = new BasicProviderKeyInfoCredentialResolver( + keyInfoProvider); + + final PredicateRoleDescriptorResolver roleDescriptorResolver = new PredicateRoleDescriptorResolver( + mdResolver); + roleDescriptorResolver.setRequireValidMetadata(true); + roleDescriptorResolver.initialize(); + + final MetadataCredentialResolver resolver = new MetadataCredentialResolver(); + resolver.setRoleDescriptorResolver(roleDescriptorResolver); + resolver.setKeyInfoCredentialResolver(keyInfoCredentialResolver); + resolver.initialize(); + + return resolver; + } +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/config/config_1.props b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/config/config_1.props new file mode 100644 index 00000000..6177b738 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/config/config_1.props @@ -0,0 +1,19 @@ +security.hsmfacade.host=eid.a-sit.at +security.hsmfacade.port=9050 +security.hsmfacade.trustedsslcert=src/test/resources/data/hsm_facade_trust_root.crt +security.hsmfacade.username=authhandler-junit +security.hsmfacade.password=supersecret123 +security.hsmfacade.hsmname=software + +keystore.path=classpath:/data/junit.jks +keystore.pass=password +key.metadata.alias=meta +key.metadata.pass=password +key.sig.alias=sig +key.sig.pass=password +key.enc.alias= +key.enc.pass= + +client.http.connection.timeout.socket=2 +client.http.connection.timeout.connection=2 +client.http.connection.timeout.request=2
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/config/config_2.props b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/config/config_2.props new file mode 100644 index 00000000..60cecebb --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/config/config_2.props @@ -0,0 +1,12 @@ +keystore.path=classpath:/data/junit.jks +keystore.pass=password +key.metadata.alias=shibboleth-sign +key.metadata.pass=password +key.sig.alias=shibboleth-sign +key.sig.pass=password +key.enc.alias= +key.enc.pass= + +client.http.connection.timeout.socket=2 +client.http.connection.timeout.connection=2 +client.http.connection.timeout.request=2
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/config/config_3.props b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/config/config_3.props new file mode 100644 index 00000000..abc8f591 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/config/config_3.props @@ -0,0 +1,18 @@ +security.hsmfacade.host=eid.a-sit.at +security.hsmfacade.port=9050 +security.hsmfacade.trustedsslcert=src/test/resources/data/hsm_facade_trust_root.crt +security.hsmfacade.username=authhandler-junit +security.hsmfacade.password=supersecret123 +security.hsmfacade.hsmname=software + +keystore.type=hsmfacade +keystore.name=authhandler +key.metadata.alias=authhandler-sign +key.sig.alias=authhandler-sign +key.sig.pass=password +key.enc.alias= +key.enc.pass= + +client.http.connection.timeout.socket=2 +client.http.connection.timeout.connection=2 +client.http.connection.timeout.request=2
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/Asserion_enc_no_key.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/Asserion_enc_no_key.xml new file mode 100644 index 00000000..a1428347 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/Asserion_enc_no_key.xml @@ -0,0 +1,81 @@ +<?xml version="1.0" encoding="UTF-8"?> +<saml2p:Response Destination="https://eid.a-sit.at/Shibboleth.sso/SAML2/POST" ID="_d4c5806eb9d7aec2a37541184023d38d" InResponseTo="_f9db5e7b5ddfd119edc3f9b63b086071" IssueInstant="2020-02-05T13:06:55.691Z" Version="2.0" xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol"> + <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">https://eid.a-sit.at/idp/shibboleth</saml2:Issuer> + <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> + <ds:SignedInfo> + <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> + <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha512"/> + <ds:Reference URI="#_d4c5806eb9d7aec2a37541184023d38d"> + <ds:Transforms> + <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> + <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> + </ds:Transforms> + <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha512"/> + <ds:DigestValue>InYZAEShnT3qk+4LlRpjt+nxCQAnerLIMQpoMzT8/SQ8E8vG36c06b4pjnjUa91p4ehdn1NSV52+9GlbXCBp8Q==</ds:DigestValue> + </ds:Reference> + </ds:SignedInfo> + <ds:SignatureValue>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE=</ds:SignatureValue> + <ds:KeyInfo> + <ds:X509Data> + <ds:X509Certificate>MIIDBzCCAq2gAwIBAgIINiXH097lKl4wCgYIKoZIzj0EAwIwGjEYMBYGA1UEAwwPTG9jYWxQa2lT +ZXJ2aWNlMB4XDTIwMDIwNTEyMjQyOVoXDTIwMDUwNTExMjQyOVowLjEZMBcGA1UEAwwQN2xXOUps +S2FYRW93eDJFYzERMA8GA1UECgwIc29mdHdhcmUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK +AoICAQDCOl3IYslq+HV1/FlSJxCdzKJ439pM98U+UfJ+bMEI6k/heFS/MNCsDDiWbIpeD2G8mDss +N1dl5xKvhgBaibYoKCjNS/sToOzhUVNfIdy/S9fc74nrXsaHB1sAf33L/2srpE2dTy/KQKAqtZ7M +eSC3GRnIyqb6KWBDSNItQ0o/6EGn+enFSkTiZM/WUWfMhe46vCVF2QWV6NvRv64xMJtYsC3dHiGs +xYgG9uZitcs0dfsY/DH4xr/vd3g5uioTDs5PElFrvzx4lbpsWMRy5OmfCRvt0R+VXP53+9o6xvNg +TbkV9rh54xwzf6geqMxT7S9na7/YzCq4hg9V4FkYCZfvXXazcxJeUNTChhvKBBXozia+FnDM67/s +QlTW2ZhGzTWv/Zs1a1xA65qahJuDeHVKo6fagAGlYNNFXNDbzPdpydtbj+5vF8dnpMp9fC9nPeQD +8BF3DOA4vraNET4XraX/vaWkvaKVCtoWYnX510TbMqtwLmksq2KiIe4mEcuEINhQ/3ERwH0mwn+/ +LKVVBRdN0gucMTSlglFe0ctuyDb8sId5kGxxucwjFBjqsRSCXpHEjlydFE0fPF6slTGl0+GCJdpJ +StDuaQ38a35U+N7x9IucakNGBXfZcwWp4dx4t8cokxLN5bpPpLo3PVfMBQ0dnH9MSzm5nVhJL5fJ +Q1asrQIDAQABMAoGCCqGSM49BAMCA0gAMEUCIQD04k68PMq+VuwfIbIWJkg3weQUASVKxKDjHnfH +/YsrPQIgVkmT8vTKC6YrfaAiMlFXsQGX9iDJBbnqNB3+9GUY7Z0=</ds:X509Certificate> + </ds:X509Data> + </ds:KeyInfo> + </ds:Signature> + <saml2p:Status> + <saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/> + </saml2p:Status> + <saml2:EncryptedAssertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion"> + <xenc:EncryptedData Id="_8bfb44aaaec124f25496619c3c59daa9" Type="http://www.w3.org/2001/04/xmlenc#Element" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"> + <xenc:EncryptionMethod Algorithm="http://www.w3.org/2009/xmlenc11#aes128-gcm" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"/> + <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> + <xenc:EncryptedKey Id="_9af666773660a6b50b4da5879a0ed6a5" Recipient="https://eid.a-sit.at/shibboleth" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"> + <xenc:EncryptionMethod Algorithm="http://www.w3.org/2009/xmlenc11#rsa-oaep" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"> + <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"/> + <xenc11:MGF Algorithm="http://www.w3.org/2009/xmlenc11#mgf1sha1" xmlns:xenc11="http://www.w3.org/2009/xmlenc11#"/> + </xenc:EncryptionMethod> + <ds:KeyInfo> + <ds:X509Data> + <ds:X509Certificate>MIID6zCCAlOgAwIBAgIJAPoNcjesqrTTMA0GCSqGSIb3DQEBCwUAMBcxFTATBgNVBAMTDGVpZC5h +LXNpdC5hdDAeFw0yMDAyMDUwODQ3MjlaFw0zMDAyMDIwODQ3MjlaMBcxFTATBgNVBAMTDGVpZC5h +LXNpdC5hdDCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBALxWBbZxOq06T+jUsJdpl8B2 +r6EYlY8MoNGsFDGyc/KuEALitFboBkgH0ztNS4YLGGdaTi3WPX3NZGr5zBx8bsxVvEW67mTkLSlw +3/FWhO8oMUuBQlR21piecVZBLj91NHstkcTSD5Cbq4uBRpPKBha7b5DrCD1BvLBYto5BCsLYeNp4 +UFgBFaLP+nUpS5fOaA6IGPRPDVKkL9wxob4Md75FuuE58MdiwaByzGjNtsmYM8uTy8wnFpXvYDwj +g3z3Pe3jrpoUglSdrFweTnXCCrkuqzjWtt5CHYW47NgrcV7hRARHFlzzBgYW2kmLnMNdhJHOldkN +DKaqn0oV2gCaemxvWKVbSYcZ27kyYFqPWaou/o4ufvQT9P8LeFKayL10b7chEU4UbJYTjh4Pi4On +VhOtOrguNJDd/qbcKrlHRb+DpDVHmZi5w9HDpg3l3SlGTzuib0nWZ64IG4Y8a1c2tpFRoiYv/aXu +7JHPMRNp/LoA1qwoF19jUzV8TWZbrrPkIwIDAQABozowODAXBgNVHREEEDAOggxlaWQuYS1zaXQu +YXQwHQYDVR0OBBYEFLP5q5ESOCfShH5tQmk6gN+PgSNSMA0GCSqGSIb3DQEBCwUAA4IBgQBHHhCl +un9DsVkT+LSEkKwyRI90wppWRpzEg2HFhbc+G53jF/qPX2WlvAASDULzPH+uBrqdbiAUlXk1JBYc +Ux0u6xV0mGSHdgq0eSzlLI/exjJTtsIOT8zeSTwjvhlNiXlJGSanoOUVNysIXM4Nv+NUB/MbYcVT +xDXzYGl45qhNhCcLSD4pQmVRAuhElH/ZwNXtUjaN2x48alZTq/+hdGK+YpNqeHS8+LcqkX9Mctth +xkF6piecW9QYzzmDlq+sOaezdhRcUS4tABaOmBFysO2GdMUtaDnBGeFiMLdRRijAEwBFYSO425pW +9Sj9ce32RgsopRF1Sz1SbbH4COrf5LdQwzS7qEUdDXQIOP7HbO9NrXkyN3W/lp5c/uVBe5fQt8Ke +v7jKaanqQozChmu6/iO7Y8DHj2/4o3QHfw4qjraJoGOSbqHDq4wBr8c403nnuGQzW0BWA04Cm0J1 +UAq08IPUdLQdsRtHOb+IVig/3S2PekIIl/U73OJChRg9566vwNo=</ds:X509Certificate> + </ds:X509Data> + </ds:KeyInfo> + <xenc:CipherData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"> + <xenc:CipherValue>ex7yi4ATGyUZmH9deZW5zwG8DGE/38pIR4hMJKQpOhxWMkwIgDmQ9AxB9qjYb7Rg7sVm6Tzeyy7cYkKvC3v5yLkCJ4JMfBSn2jmovAUW9o6m0S/IVSyzWUknIzVO5ZRK91M0TINmlo7kKeD9mtW2LNgo2Ai5mfCThjPGbkJFelHJjDCnu2IGu+3g1uif8kx5m3NAVg7vT8SrpdQSCZrsuhw7IM5OEKxtutAeLDdu8W88bkLDeaM+Oe7jKRfa25q5ZEpFWfDKnju0qIybjzGifS/nZDT0CRftFsusZ8QMoytvQ2Brget6ymH723sAjngDE+JZ6Za9U4FJH/8P2n7Fs91i1QCPMbuib0oLvgW4TR4rZebrWtDlYDe5MlDwdGtJX3iWu2Rt/gK5HKztFFeo0+6O2kvdZsqmnmXLV14RK+e3upoY+crcSofyqU61ouwnyYLTOqoR5xMUDl4QSCfbkoUngVKxDQr4c5eulnhQqs3WIBM83BVpqSPFnfrdJP3q</xenc:CipherValue> + </xenc:CipherData> + </xenc:EncryptedKey> + </ds:KeyInfo> + <xenc:CipherData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"> + <xenc:CipherValue>tr9Nhnr8opMNTj5+fWTSfnPhuVm2g3VxF9UPLbub0yrXgEOpIFvR6vf/c2r0g4o1f1ddPmndPPOjqYTln4OT04PT/WLS3lrfoPj4fu+KS3WGfZjL8JmgL/6hkhUHll1tzx4PiBvMVP4MCrH4ieKfHWQDDxVexPznJ3yLbGiplh/jOcot8zgDIEu87x9vQoEM71pDjz2/vBje2DgZN1Bf2K8lRERLWl1dC06EPqH99eUXBVo94LdMqsOEECBJmzfOvivd5JsoQ7x5eZ3cfYmPwtQkQjg8FDLxFpLcXAmadZQrYK9dVIKLRZtI7QxEKV+rd/dHvIvyqRT+YMCobkvSC8xdneVlr0PgXL2oY3yFaGbL4a1paIpDxkEe1sCbz4ucY/SRoKd6zqmBFXIS1wZSkUcrvuIzuGBho7Bn0GPc167kaplLshW/CoklNLQJEFnjWu2VPGLj8IZjApYVkRgv/LZZRLJ8I4zfAI6wblqPQPsLm1adiBtBsI2CygkOkL5T5PPHmjJxFWoczIiNGfxwOUpMSGrQE2GVjsAc3r76FwJW40PjcgEsDeAsZaX0ct7LfJolhZSMI/h9cu2VtDgxq/eeGZzXVvTIG68oKUjLnKlCXCcwE+KdHjLnVF8N0gwWYau59Ln8DODP6l1kvmb7O034uI3eiTumqgJT27uAJ9KQol1LsmHZZoeiDJY4nMV7MAHfIMSHetzPiOSF2xilkwi0te7cWfJRDhWtymIilMTDkJTTqN9EHK5GbZ3JzPVsyw+PbI36PudiS3KOsb6qdb42fcWfOFeeOLOEsb1pxk/aHk8sG14i01MTGGJRhPZcBmrxJmLy5TNZ8Xp/kiA1w4cTwoDk8aQcUeMg350rEGbhW6/9Jm5BPC+z0GhnzWo0DnzLuJCu1zSmO2s+bUwBnGH/ZFxbf4DWCmYrq+T32hfrTFUncZOenlLkPgM7vJK/o4ND/d76z00ud6BoPPa67q4ZxAMgo2T2+HGjrL6JsbivcjOazByKSq9aCOYy9LpaWD20k8c3voqzt+GUJadc7bEeEn7fBI0Y7J4hRfFQiSanXn/fHbUPUZMlctDgkJrQFeRI0Jrkrlp8k8RErMdAdYQI8j5cMphKTXAF/gpc0dFI6HPgVQk7ioEYIUh/44OssVLKjYoQAZnZN1ndgVHHl8jogB3KQ+mVJoBlnckyWneO9bNcnekfWI6F4UHdzzjiPeujobglkzc5eOnw2fL8ELqHW4gzKFfrukQgOCgmEHIJV8TBzGRLmIN3kLvPvA7Q3oneb6J2+FPwT1wZupKoqwmKDiUtu+O99JGsjW6J5C9MdVT5DE0NShM4FU/XvmPAQIOO31Rg1HIdNH9fodCtyA8YT76Xjpi73nt7SjkJyKX/jdHMhFzHTblYpDV98ZoRq8I/AU71KbV1w7u5ThNfPHYBsWVm28KtpzfvxV0yFV5HtTHwLiXmu9P0D2o1K6aB6XC6hlgeB1VtujJBya7zaF45xLGVfYDj4HALqxqDDv0T+qIlgoRe1/c8LbVdYzZU8Yseqe1QC6NQA7277xBheF8LqHTXBaOeIOVgkKHHTb64AZ2eqrnKGnWV3VT1k3GszboZz4TNKg3izu7R54+UmF6psLhVW1mUaHvjVviZiXlu215XlOVop7P3Q6WBR1i8p4PvLSy5IiEwCRIPzXSjVPkFHujwcaqHZ0VgD+p9lfHHh4LARcZM9+tvD67FNt4Uq9W+l3mocN2suGEJfWElm9Z1TdPKzqQUJwZPEnL1JZKykAic5CmTqo7uqGHzIL0SzIrsnkbPclFFgHjXWJOgMfnya58pUh3RX7QQ1+ZH6/C0qeILzXjAJXNKfHEgro99GFGN5kxQShDqJljWKDjbJ9M8ioDqt/4KvMwkferpaNro4/06k8/qhKmFh/I/cNd9SfIaYEU95Ej121nFBD20qOXCUKCQ3rP1z33ezZ2Lld+RSr+fkJ/8IlarVCitENmR6fn7cVCmwEYcK7kfZSCZ0FFgb9gf/LpPE4jlZ3voyNquvXIrlG47WC6IwHOieY4PalONmhKHkYzhngnAyvuHQ/vUJ5PxF/9Ks7KQA+UVFaP/fiuNED8UZ/iziBmEolw2/A==</xenc:CipherValue> + </xenc:CipherData> + </xenc:EncryptedData> + </saml2:EncryptedAssertion> +</saml2p:Response> diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/AuthRequest_with_sig_1.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/AuthRequest_with_sig_1.xml new file mode 100644 index 00000000..f9de11c4 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/AuthRequest_with_sig_1.xml @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="UTF-8"?> +<saml2p:AuthnRequest xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" AssertionConsumerServiceIndex="1" AttributeConsumingServiceIndex="0" Destination="https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp2/post" ID="_aeebfae3ce681fe3ddcaf213a42f01d3" IssueInstant="2014-03-05T06:39:02.775Z" Version="2.0"> + <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://demo.egiz.gv.at/demoportal_demologin/</saml2:Issuer> + <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> + <ds:SignedInfo> + <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> + <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/> + <ds:Reference URI="#_aeebfae3ce681fe3ddcaf213a42f01d3"> + <ds:Transforms> + <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> + <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> + </ds:Transforms> + <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> + <ds:DigestValue>sBVJQf9b+QIxRfH8YuTbF6hBrf4=</ds:DigestValue> + </ds:Reference> + </ds:SignedInfo> + <ds:SignatureValue>JK68H5XqmD2OEA8O/UCZFenVj0TrvauPhaKJt73pbHbi//hO1hBcRQbV2Qg3gQ11EcJ9Q+TM3TCe9nT6tdU/z7ry3qdZvlOfrkMF13fY4HOIuvB9AcySdxq2yKA3V5O9sLhf5S9qCyx9lMnTARC7wkVs4j2Pv00R6P/iROOHD5ryGF2J0FdtMp9VqhvQJ9yRGM2lTduF98MqxWA2EMk6AMo7qij0Bvha1B2OyFSU9HM3fyfRQpXDeiLnKHcjLpzu5TDNkKrP75c7vv85DDr7s2I0p74nAOVLMuLau5tEQ91Crk9QoqoqqEecKWcNJDXTO9MahCQw77hUDL1WOEMFFg==</ds:SignatureValue> + <ds:KeyInfo> + <ds:KeyValue> + <ds:RSAKeyValue> + <ds:Modulus>nEPzKMh3TovnfBnTyv+TMYFsGep8Uil7iNbfVyfLoBfqRdeGDOk4es2qWkgB6az+kM/9Js2H06m4 +pjEY7/RIjd0lMWqgi8eqdjilMmbFQykkYYQhlZbvi8KqoBcCKzj5N3GY4qh8A5qN4y85Q3sZj23T +iiIY1rphE+ZTOHCm6CKeRso9jj409YHP1xAXfPvtIYx2TA1uuagxOmL75OC/hr7gcUm0tmuKiSeq ++TO4VZw2Q7K7YESZ1WkiBoG2i4cHdcBFKnVrGNtyxl6UkjWxXRJSU9aNLs5QxsE6iFwCvFoIO+IU +cVWxfFHqOGbRtAcRUb4fk+KFHE2o1DLmfwZaUQ==</ds:Modulus> + <ds:Exponent>AQAB</ds:Exponent> + </ds:RSAKeyValue> + </ds:KeyValue> + </ds:KeyInfo> + </ds:Signature> + <saml2:Subject xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion"> + <saml2:NameID>https://demo.egiz.gv.at/demoportal_demologin/</saml2:NameID> + </saml2:Subject> + <saml2p:NameIDPolicy AllowCreate="true" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"/> + <saml2p:RequestedAuthnContext> + <saml2:AuthnContextClassRef xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">http://www.stork.gov.eu/1.0/citizenQAALevel/4</saml2:AuthnContextClassRef> + </saml2p:RequestedAuthnContext> +</saml2p:AuthnRequest> diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/AuthRequest_without_sig_1.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/AuthRequest_without_sig_1.xml new file mode 100644 index 00000000..ef35ea92 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/AuthRequest_without_sig_1.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8"?> +<saml2p:AuthnRequest xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" AssertionConsumerServiceIndex="1" AttributeConsumingServiceIndex="0" Destination="https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp2/post" ID="_aeebfae3ce681fe3ddcaf213a42f01d3" IssueInstant="2014-03-05T06:39:02.775Z" Version="2.0"> + <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://demo.egiz.gv.at/demoportal_demologin/</saml2:Issuer> + <saml2:Subject xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion"> + <saml2:NameID>https://demo.egiz.gv.at/demoportal_demologin/</saml2:NameID> + </saml2:Subject> + <saml2p:NameIDPolicy AllowCreate="true" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"/> + <saml2p:RequestedAuthnContext> + <saml2:AuthnContextClassRef xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">http://www.stork.gov.eu/1.0/citizenQAALevel/4</saml2:AuthnContextClassRef> + </saml2p:RequestedAuthnContext> +</saml2p:AuthnRequest> diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/AuthRequest_without_sig_missing_id.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/AuthRequest_without_sig_missing_id.xml new file mode 100644 index 00000000..e028d8d1 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/AuthRequest_without_sig_missing_id.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8"?> +<saml2p:AuthnRequest xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" AssertionConsumerServiceIndex="1" AttributeConsumingServiceIndex="0" Destination="https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp2/post" IssueInstant="2014-03-05T06:39:02.775Z" Version="2.0"> + <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://demo.egiz.gv.at/demoportal_demologin/</saml2:Issuer> + <saml2:Subject xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion"> + <saml2:NameID>https://demo.egiz.gv.at/demoportal_demologin/</saml2:NameID> + </saml2:Subject> + <saml2p:NameIDPolicy AllowCreate="true" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"/> + <saml2p:RequestedAuthnContext> + <saml2:AuthnContextClassRef xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">http://www.stork.gov.eu/1.0/citizenQAALevel/4</saml2:AuthnContextClassRef> + </saml2p:RequestedAuthnContext> +</saml2p:AuthnRequest> diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/AuthRequest_withsig_expired.b64 b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/AuthRequest_withsig_expired.b64 new file mode 100644 index 00000000..f02ce2ea --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/AuthRequest_withsig_expired.b64 @@ -0,0 +1 @@ +PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c2FtbDJwOkF1dGhuUmVxdWVzdCB4bWxuczpzYW1sMnA9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpwcm90b2NvbCIgQXNzZXJ0aW9uQ29uc3VtZXJTZXJ2aWNlSW5kZXg9IjAiIERlc3RpbmF0aW9uPSJodHRwczovL2VpZGFzLXRlc3QuYm1pLmd2LmF0L21zX2Nvbm5lY3Rvci9wdnAvcG9zdCIgSUQ9Il9lZDJjZDQ0NjNiODJkYzYwOTI0MzM5YjEwZWIyNzQ4OCIgSXNQYXNzaXZlPSJmYWxzZSIgSXNzdWVJbnN0YW50PSIyMDIwLTAyLTA0VDA2OjQ4OjU4LjA3NFoiIFByb3ZpZGVyTmFtZT0iT3BlbklEIENvbm5lY3QgRGVtbyIgVmVyc2lvbj0iMi4wIiB4bWxuczp4cz0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEiPjxzYW1sMjpJc3N1ZXIgeG1sbnM6c2FtbDI9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphc3NlcnRpb24iIEZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOm5hbWVpZC1mb3JtYXQ6ZW50aXR5Ij5odHRwczovL2RlbW8uZWdpei5ndi5hdC9kZW1vcG9ydGFsX21vYWlkLTIuMC9zcC9laWRhcy9tZXRhZGF0YTwvc2FtbDI6SXNzdWVyPjxkczpTaWduYXR1cmUgeG1sbnM6ZHM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyMiPjxkczpTaWduZWRJbmZvPjxkczpDYW5vbmljYWxpemF0aW9uTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8xMC94bWwtZXhjLWMxNG4jIi8+PGRzOlNpZ25hdHVyZU1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMDQveG1sZHNpZy1tb3JlI3JzYS1zaGEyNTYiLz48ZHM6UmVmZXJlbmNlIFVSST0iI19lZDJjZDQ0NjNiODJkYzYwOTI0MzM5YjEwZWIyNzQ4OCI+PGRzOlRyYW5zZm9ybXM+PGRzOlRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyNlbnZlbG9wZWQtc2lnbmF0dXJlIi8+PGRzOlRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMTAveG1sLWV4Yy1jMTRuIyI+PGVjOkluY2x1c2l2ZU5hbWVzcGFjZXMgeG1sbnM6ZWM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMTAveG1sLWV4Yy1jMTRuIyIgUHJlZml4TGlzdD0ieHMiLz48L2RzOlRyYW5zZm9ybT48L2RzOlRyYW5zZm9ybXM+PGRzOkRpZ2VzdE1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMDQveG1sZW5jI3NoYTI1NiIvPjxkczpEaWdlc3RWYWx1ZT5aSEZ0UVpYeXBTbFhrK3ZYdGZlSDVMWEdNcTE2MUpmUHdFUHBPVFhUSzlRPTwvZHM6RGlnZXN0VmFsdWU+PC9kczpSZWZlcmVuY2U+PC9kczpTaWduZWRJbmZvPjxkczpTaWduYXR1cmVWYWx1ZT5CSFFHeXpMZE5rb2dGZmt5T0FxVnBTRXh1NXhRaWxvVUs5L01GejBTM01LZnRkaDVtTXVaT0tBSUU1SUMrKzlPS25UbUlncUVNdWJVKzAvTEVobTUwUk1oZGtxYUFFWG02Y2xKYmlaOHBvT0pPd09sWlhQVWtub0J4NkZxRi9MNThqTFV6ZlluNEh0OUtCOGVQV2djU2FVR3lpMHB4OEdzMzNJUDd3eGF2bnhGYUMvSERpZkN0UytaZzJ5QVpJR2lnQksxcXIrUTMweWIrNWZEQmprU3pWMWJGb2NKdHY2cDJhSXlUMTNnb2x6N0FuK3JSWVloVnd5WENBY25CdHJjQTREbmNpWVVnTVNLQTRTR1hLNExyZ1RTdjFXUHJEdlJmWkVLMk9xL2JEMHE0MWF1T1d4VVkzK2x2T2pJYUI3YnRobURiSVJPbmhaWW1rMDlPSFZJMVE9PTwvZHM6U2lnbmF0dXJlVmFsdWU+PGRzOktleUluZm8+PGRzOlg1MDlEYXRhPjxkczpYNTA5Q2VydGlmaWNhdGU+TUlJREt6Q0NBaE1DQkZyeEtPNHdEUVlKS29aSWh2Y05BUUVMQlFBd1dqRUxNQWtHQTFVRUJoTUNRVlF4RFRBTEJnTlZCQW9NQkVWSApTVm94R0RBV0JnTlZCQXNNRDJSbGJXOHVaV2RwZWk1bmRpNWhkREVpTUNBR0ExVUVBd3daVFU5QkxVbEVJRWxFVUNBb1ZHVnpkQzFXClpYSnphVzl1S1RBZUZ3MHhPREExTURnd05ETTBOVFJhRncweU1UQXhNekV3TkRNME5UUmFNRm94Q3pBSkJnTlZCQVlUQWtGVU1RMHcKQ3dZRFZRUUtEQVJGUjBsYU1SZ3dGZ1lEVlFRTERBOWtaVzF2TG1WbmFYb3VaM1l1WVhReElqQWdCZ05WQkFNTUdVMVBRUzFKUkNCSgpSRkFnS0ZSbGMzUXRWbVZ5YzJsdmJpa3dnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDYUZucW9hWW9xClVwdGVuZW1DNkZpVkRnNUYyaEVqcGppeDgrb3c2LzZRaFVsMmNQT1MwdXdaSGFJdndUL1JWYko5Q1BkaWw2KzExcWFDUGZaK0ZvWSsKTStrZTdUUmQyUlMxRHFGYmUxS0MwaW1FbndlbXlMUXJZZTVQbTdETmNhWS9rSFRUcStrMGVlR2JZSDBVL0lvcHlpMFZ1TjVPV2w0RgpWZzQ1cGY3a25oWGthaW1JdGRqbkNYbktjWU05MW1tbHRDZjZURGdVcno3VVM3UG1ndmlubmhmQmdkSVRBVDRHUnI0ZWhsaVQrL2p0CjFPekhFeVdSSGFuQkdJcFhOZVpOcXhnbnBuR3RhRGg0Slp1WVI4cWZIK0dSSzZkdFcyemllajZyR0lpVUVsR1ZDa1hzb2hneE1OenEKbldlRDlKVDgreXlwMVhabHlRZitJeGhoRVNRTEFnTUJBQUV3RFFZSktvWklodmNOQVFFTEJRQURnZ0VCQUlGZWpBRlFlcGFFbC9rQwpWTHZpZE1SK01YcTVMQ0dIdGhVaUk2ZURUUVorSDdsWmRIbGo1NDdYd0VkWDE1YjZNZDNoN2VTSjRod2xmVjRnby8wRmFvTFB6dlZxCml0d3RZWTVodHl3QjNCNlpWMzRFeWk2QzU5R2wzNFhyVjhDV3hINEtLd0xzVkFqQXkrL3AvWGgwcTJwelNCa2VPQ2h6Qk1Ca2pteWMKMlVlNE1FS2RMOWd1enA2K1ljL0hML3BoSEFLWWFwa1Z5Rnd2c2RxV09neVJ6eEFISU5rbzhFeEltTU1CM3hCNWE1MmtmcUxjdWk1TwpmekVoandMRkphR0JNbUZDbUZHR09Vd3RJdmwvNlpRMkxMek9FOStnaVZLOVdzSWdIMTFQdStlalBGQWJYZjhjZjRvV2hiQWZUa2l5CjRqcFhycDc3SlhGUlNEV2RkYjB5ZVBjPTwvZHM6WDUwOUNlcnRpZmljYXRlPjwvZHM6WDUwOURhdGE+PC9kczpLZXlJbmZvPjwvZHM6U2lnbmF0dXJlPjxzYW1sMnA6RXh0ZW5zaW9ucz48ZWlkOlJlcXVlc3RlZEF0dHJpYnV0ZXMgeG1sbnM6ZWlkPSJodHRwOi8vZWlkLmd2LmF0L2VJRC9hdHRyaWJ1dGVzL3NhbWwtZXh0ZW5zaW9ucyI+PGVpZDpSZXF1ZXN0ZWRBdHRyaWJ1dGUgRnJpZW5kbHlOYW1lPSJFSUQtU0VDVE9SLUZPUi1JREVOVElGSUVSIiBOYW1lPSJ1cm46b2lkOjEuMi40MC4wLjEwLjIuMS4xLjI2MS4zNCIgTmFtZUZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmF0dHJuYW1lLWZvcm1hdDp1cmkiIGlzUmVxdWlyZWQ9InRydWUiPjxlaWQ6QXR0cmlidXRlVmFsdWUgeG1sbnM6eHNpPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYS1pbnN0YW5jZSIgeHNpOnR5cGU9InhzOnN0cmluZyI+dXJuOnB1YmxpY2lkOmd2LmF0OmNkaWQrQkY8L2VpZDpBdHRyaWJ1dGVWYWx1ZT48L2VpZDpSZXF1ZXN0ZWRBdHRyaWJ1dGU+PC9laWQ6UmVxdWVzdGVkQXR0cmlidXRlcz48L3NhbWwycDpFeHRlbnNpb25zPjxzYW1sMnA6TmFtZUlEUG9saWN5IEFsbG93Q3JlYXRlPSJ0cnVlIiBGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpuYW1laWQtZm9ybWF0OnBlcnNpc3RlbnQiLz48c2FtbDJwOlJlcXVlc3RlZEF1dGhuQ29udGV4dCBDb21wYXJpc29uPSJtaW5pbXVtIj48c2FtbDI6QXV0aG5Db250ZXh0Q2xhc3NSZWYgeG1sbnM6c2FtbDI9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphc3NlcnRpb24iPmh0dHA6Ly9laWRhcy5ldXJvcGEuZXUvTG9BL2xvdzwvc2FtbDI6QXV0aG5Db250ZXh0Q2xhc3NSZWY+PC9zYW1sMnA6UmVxdWVzdGVkQXV0aG5Db250ZXh0PjxzYW1sMnA6U2NvcGluZz48c2FtbDJwOlJlcXVlc3RlcklEPmh0dHBzOi8vZGVtby5lZ2l6Lmd2LmF0L2RlbW9wb3J0YWwtb3BlbklEX2RlbW88L3NhbWwycDpSZXF1ZXN0ZXJJRD48L3NhbWwycDpTY29waW5nPjwvc2FtbDJwOkF1dGhuUmVxdWVzdD4
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/Response_with_sig_1.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/Response_with_sig_1.xml new file mode 100644 index 00000000..2654f2e8 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/Response_with_sig_1.xml @@ -0,0 +1,81 @@ +<?xml version="1.0" encoding="UTF-8"?> +<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" Destination="https://demo.egiz.gv.at/demoportal_demologin/securearea.action" InResponseTo="_aeebfae3ce681fe3ddcaf213a42f01d3" IssueInstant="2014-03-05T06:39:51.017Z" Version="2.0" xmlns:xs="http://www.w3.org/2001/XMLSchema"> + <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp/metadata</saml2:Issuer> + <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> + <ds:SignedInfo> + <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> + <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/> + <ds:Reference URI=""> + <ds:Transforms> + <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> + <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"> + <ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="xs"/> + </ds:Transform> + </ds:Transforms> + <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/> + <ds:DigestValue>fCE31ZeXZybQLOuNQBePLjFrCtKdvCmeyJ1tUW/ghtA=</ds:DigestValue> + </ds:Reference> + </ds:SignedInfo> + <ds:SignatureValue>vUFR3YPk5wiBJnrLh6Er7V46FNDMuB5Jcu73Rw7tipgr+bnV0reRNcZ5TGT+VMjNhtKJMcqgjrQWJ6tACe1r0mzhpRSVQkw7yFkTvIhQHX1a08yqJ4yy3qiN13ctDo4VgP9qHUim7b797oOKNhRXFk+2GJA5hRcpRliUjhBlzTYrxpkY5NcYDRhDPlvMx+l11oa1iDGuAylN+ty4h3P4fIoIgL9Tz1m3l65LqkV5RBc6avSeHw9OASMigPsjd5b0IBvhvJ611xLgzC1BOtJshiw1k/p8alv8TaUmYZ/kJbRN1tuTBL129edbS0Rz0faT0tniF42QHteJ214brK3rCg==</ds:SignatureValue> + <ds:KeyInfo> + <ds:KeyValue> + <ds:RSAKeyValue> + <ds:Modulus>xRE83dJy1dj+KVBp5Syo91fjGeG1MmJDSuTZ5MwdDzvIZrbK3YPh0jbJz4lOSrw9urRacavZX4m2 +XAKfSRxaowP3GqTh3Ew4WJE7yXEnWiic7bUz8uMIr020bsvqHCvY48+oPARbz/cEOf5NgMBWqo9E +nibdIyU5+AmfFzDaMwNocJEANoXrjLTpduCHvT0Qt/wH+7rVdgjX1djMrBhyMWs7GQyIBRfuf58m +8kdcoiMSm9AWA4d4GzXch+bi1QRzj+Ib80DeWdcXP3Hc6pcyp/+L+hya2jZ9NMS8yup6xuoAeh7w +6JNpfE9QnO3/CPrDZTtmjPK2OIRkhgn4Yi+iBQ==</ds:Modulus> + <ds:Exponent>AQAB</ds:Exponent> + </ds:RSAKeyValue> + </ds:KeyValue> + </ds:KeyInfo> + </ds:Signature> + <saml2p:Status> + <saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/> + </saml2p:Status> + <saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" ID="_602c3236bffaf71ac3ac88674e76ff9f" IssueInstant="2014-03-05T06:39:51.017Z" Version="2.0"> + <saml2:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp/metadata</saml2:Issuer> + <saml2:Subject> + <saml2:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent" NameQualifier="urn:publicid:gv.at:cdid+BF">QVGm48cqcM4UcyhDTNGYmVdrIoY=</saml2:NameID> + <saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"> + <saml2:SubjectConfirmationData InResponseTo="_aeebfae3ce681fe3ddcaf213a42f01d3" NotOnOrAfter="2014-03-05T06:44:51.017Z" Recipient="https://demo.egiz.gv.at/demoportal_demologin/securearea.action"/> + </saml2:SubjectConfirmation> + </saml2:Subject> + <saml2:Conditions NotBefore="2014-03-05T06:39:51.017Z" NotOnOrAfter="2014-03-05T06:44:51.017Z"> + <saml2:AudienceRestriction> + <saml2:Audience>https://demo.egiz.gv.at/demoportal_demologin/</saml2:Audience> + </saml2:AudienceRestriction> + </saml2:Conditions> + <saml2:AuthnStatement AuthnInstant="2014-03-05T06:39:51.017Z" SessionIndex="_c0c683509a8ff6ac372a9cf9c5c5a406"> + <saml2:AuthnContext> + <saml2:AuthnContextClassRef>http://www.stork.gov.eu/1.0/citizenQAALevel/4</saml2:AuthnContextClassRef> + </saml2:AuthnContext> + </saml2:AuthnStatement> + <saml2:AttributeStatement> + <saml2:Attribute FriendlyName="PVP-VERSION" Name="urn:oid:1.2.40.0.10.2.1.1.261.10" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">2.1</saml2:AttributeValue> + </saml2:Attribute> + <saml2:Attribute FriendlyName="PRINCIPAL-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.20" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Mustermann</saml2:AttributeValue> + </saml2:Attribute> + <saml2:Attribute FriendlyName="GIVEN-NAME" Name="urn:oid:2.5.4.42" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Max</saml2:AttributeValue> + </saml2:Attribute> + <saml2:Attribute FriendlyName="BIRTHDATE" Name="urn:oid:1.2.40.0.10.2.1.1.55" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">1940-01-01</saml2:AttributeValue> + </saml2:Attribute> + <saml2:Attribute FriendlyName="BPK" Name="urn:oid:1.2.40.0.10.2.1.1.149" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">BF:QVGm48cqcM4UcyhDTNGYmVdrIoY=</saml2:AttributeValue> + </saml2:Attribute> + <saml2:Attribute FriendlyName="EID-CITIZEN-QAA-LEVEL" Name="urn:oid:1.2.40.0.10.2.1.1.261.94" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:integer">4</saml2:AttributeValue> + </saml2:Attribute> + <saml2:Attribute FriendlyName="EID-ISSUING-NATION" Name="urn:oid:1.2.40.0.10.2.1.1.261.32" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">AT</saml2:AttributeValue> + </saml2:Attribute> + <saml2:Attribute FriendlyName="EID-SECTOR-FOR-IDENTIFIER" Name="urn:oid:1.2.40.0.10.2.1.1.261.34" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">urn:publicid:gv.at:cdid+BF</saml2:AttributeValue> + </saml2:Attribute> + </saml2:AttributeStatement> + </saml2:Assertion> +</saml2p:Response> diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/Response_without_sig_1.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/Response_without_sig_1.xml new file mode 100644 index 00000000..e6530cca --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/Response_without_sig_1.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="UTF-8"?> +<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" ID="_4c1c39ee0969b320bf0cae37816f7d5b" Destination="https://demo.egiz.gv.at/demoportal_demologin/securearea.action" InResponseTo="_aeebfae3ce681fe3ddcaf213a42f01d3" IssueInstant="2014-03-05T06:39:51.017Z" Version="2.0" xmlns:xs="http://www.w3.org/2001/XMLSchema"> + <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://demo.egiz.gv.at/demoportal_demologin/</saml2:Issuer> + <saml2p:Status> + <saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/> + </saml2p:Status> + <saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" ID="_602c3236bffaf71ac3ac88674e76ff9f" IssueInstant="2014-03-05T06:39:51.017Z" Version="2.0"> + <saml2:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp/metadata</saml2:Issuer> + <saml2:Subject> + <saml2:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent" NameQualifier="urn:publicid:gv.at:cdid+BF">QVGm48cqcM4UcyhDTNGYmVdrIoY=</saml2:NameID> + <saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"> + <saml2:SubjectConfirmationData InResponseTo="_aeebfae3ce681fe3ddcaf213a42f01d3" NotOnOrAfter="2014-03-05T06:44:51.017Z" Recipient="https://demo.egiz.gv.at/demoportal_demologin/securearea.action"/> + </saml2:SubjectConfirmation> + </saml2:Subject> + <saml2:Conditions NotBefore="2014-03-05T06:39:51.017Z" NotOnOrAfter="2014-03-05T06:44:51.017Z"> + <saml2:AudienceRestriction> + <saml2:Audience>https://demo.egiz.gv.at/demoportal_demologin/</saml2:Audience> + </saml2:AudienceRestriction> + </saml2:Conditions> + <saml2:AuthnStatement AuthnInstant="2014-03-05T06:39:51.017Z" SessionIndex="_c0c683509a8ff6ac372a9cf9c5c5a406"> + <saml2:AuthnContext> + <saml2:AuthnContextClassRef>http://www.stork.gov.eu/1.0/citizenQAALevel/4</saml2:AuthnContextClassRef> + </saml2:AuthnContext> + </saml2:AuthnStatement> + <saml2:AttributeStatement> + <saml2:Attribute FriendlyName="PVP-VERSION" Name="urn:oid:1.2.40.0.10.2.1.1.261.10" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">2.1</saml2:AttributeValue> + </saml2:Attribute> + <saml2:Attribute FriendlyName="PRINCIPAL-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.20" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Mustermann</saml2:AttributeValue> + </saml2:Attribute> + <saml2:Attribute FriendlyName="GIVEN-NAME" Name="urn:oid:2.5.4.42" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Max</saml2:AttributeValue> + </saml2:Attribute> + <saml2:Attribute FriendlyName="BIRTHDATE" Name="urn:oid:1.2.40.0.10.2.1.1.55" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">1940-01-01</saml2:AttributeValue> + </saml2:Attribute> + <saml2:Attribute FriendlyName="BPK" Name="urn:oid:1.2.40.0.10.2.1.1.149" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">BF:QVGm48cqcM4UcyhDTNGYmVdrIoY=</saml2:AttributeValue> + </saml2:Attribute> + <saml2:Attribute FriendlyName="EID-CITIZEN-QAA-LEVEL" Name="urn:oid:1.2.40.0.10.2.1.1.261.94" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:integer">4</saml2:AttributeValue> + </saml2:Attribute> + <saml2:Attribute FriendlyName="EID-ISSUING-NATION" Name="urn:oid:1.2.40.0.10.2.1.1.261.32" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">AT</saml2:AttributeValue> + </saml2:Attribute> + <saml2:Attribute FriendlyName="EID-SECTOR-FOR-IDENTIFIER" Name="urn:oid:1.2.40.0.10.2.1.1.261.34" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">urn:publicid:gv.at:cdid+BF</saml2:AttributeValue> + </saml2:Attribute> + </saml2:AttributeStatement> + </saml2:Assertion> +</saml2p:Response> diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/Response_without_sig_classpath_entityid.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/Response_without_sig_classpath_entityid.xml new file mode 100644 index 00000000..2683742e --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/Response_without_sig_classpath_entityid.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="UTF-8"?> +<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" Destination="https://demo.egiz.gv.at/demoportal_demologin/securearea.action" InResponseTo="_aeebfae3ce681fe3ddcaf213a42f01d3" IssueInstant="2014-03-05T06:39:51.017Z" Version="2.0" xmlns:xs="http://www.w3.org/2001/XMLSchema"> + <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://demo.egiz.gv.at/demoportal_demologin/</saml2:Issuer> + <saml2p:Status> + <saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/> + </saml2p:Status> + <saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" ID="_602c3236bffaf71ac3ac88674e76ff9f" IssueInstant="2014-03-05T06:39:51.017Z" Version="2.0"> + <saml2:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp/metadata</saml2:Issuer> + <saml2:Subject> + <saml2:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent" NameQualifier="urn:publicid:gv.at:cdid+BF">QVGm48cqcM4UcyhDTNGYmVdrIoY=</saml2:NameID> + <saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"> + <saml2:SubjectConfirmationData InResponseTo="_aeebfae3ce681fe3ddcaf213a42f01d3" NotOnOrAfter="2014-03-05T06:44:51.017Z" Recipient="https://demo.egiz.gv.at/demoportal_demologin/securearea.action"/> + </saml2:SubjectConfirmation> + </saml2:Subject> + <saml2:Conditions NotBefore="2014-03-05T06:39:51.017Z" NotOnOrAfter="2014-03-05T06:44:51.017Z"> + <saml2:AudienceRestriction> + <saml2:Audience>https://demo.egiz.gv.at/demoportal_demologin/</saml2:Audience> + </saml2:AudienceRestriction> + </saml2:Conditions> + <saml2:AuthnStatement AuthnInstant="2014-03-05T06:39:51.017Z" SessionIndex="_c0c683509a8ff6ac372a9cf9c5c5a406"> + <saml2:AuthnContext> + <saml2:AuthnContextClassRef>http://www.stork.gov.eu/1.0/citizenQAALevel/4</saml2:AuthnContextClassRef> + </saml2:AuthnContext> + </saml2:AuthnStatement> + <saml2:AttributeStatement> + <saml2:Attribute FriendlyName="PVP-VERSION" Name="urn:oid:1.2.40.0.10.2.1.1.261.10" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">2.1</saml2:AttributeValue> + </saml2:Attribute> + <saml2:Attribute FriendlyName="PRINCIPAL-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.20" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Mustermann</saml2:AttributeValue> + </saml2:Attribute> + <saml2:Attribute FriendlyName="GIVEN-NAME" Name="urn:oid:2.5.4.42" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Max</saml2:AttributeValue> + </saml2:Attribute> + <saml2:Attribute FriendlyName="BIRTHDATE" Name="urn:oid:1.2.40.0.10.2.1.1.55" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">1940-01-01</saml2:AttributeValue> + </saml2:Attribute> + <saml2:Attribute FriendlyName="BPK" Name="urn:oid:1.2.40.0.10.2.1.1.149" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">BF:QVGm48cqcM4UcyhDTNGYmVdrIoY=</saml2:AttributeValue> + </saml2:Attribute> + <saml2:Attribute FriendlyName="EID-CITIZEN-QAA-LEVEL" Name="urn:oid:1.2.40.0.10.2.1.1.261.94" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:integer">4</saml2:AttributeValue> + </saml2:Attribute> + <saml2:Attribute FriendlyName="EID-ISSUING-NATION" Name="urn:oid:1.2.40.0.10.2.1.1.261.32" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">AT</saml2:AttributeValue> + </saml2:Attribute> + <saml2:Attribute FriendlyName="EID-SECTOR-FOR-IDENTIFIER" Name="urn:oid:1.2.40.0.10.2.1.1.261.34" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">urn:publicid:gv.at:cdid+BF</saml2:AttributeValue> + </saml2:Attribute> + </saml2:AttributeStatement> + </saml2:Assertion> +</saml2p:Response> diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/assertion_sig_cert.crt b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/assertion_sig_cert.crt new file mode 100644 index 00000000..b53c558d --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/assertion_sig_cert.crt @@ -0,0 +1,10 @@ +-----BEGIN CERTIFICATE----- +MIIBbTCCARKgAwIBAgIEXjF+qTAKBggqhkjOPQQDAjA+MQswCQYDVQQGEwJBVDEN +MAsGA1UEBwwERUdJWjEOMAwGA1UECgwFalVuaXQxEDAOBgNVBAMMB3NpZ25pbmcw +HhcNMjAwMTI5MTI0NjMzWhcNMjcwMTI4MTI0NjMzWjA+MQswCQYDVQQGEwJBVDEN +MAsGA1UEBwwERUdJWjEOMAwGA1UECgwFalVuaXQxEDAOBgNVBAMMB3NpZ25pbmcw +WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASRt7gZRrr4rSEE7Q922oKQJF+mlkwC +LZnv8ZzHtH54s4VdyQFIBjQF1PPf9PTn+5tid8QJehZPndcoeD7J8fPJMAoGCCqG +SM49BAMCA0kAMEYCIQDFUO0owvqMVRO2FmD+vb8mqJBpWCE6Cl5pEHaygTa5LwIh +ANsmjI2azWiTSFjb7Ou5fnCfbeiJUP0s66m8qS4rYl9L +-----END CERTIFICATE----- diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/eIDAS_connector_authn.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/eIDAS_connector_authn.xml new file mode 100644 index 00000000..8ca219a7 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/eIDAS_connector_authn.xml @@ -0,0 +1,54 @@ +<?xml version="1.0" encoding="UTF-8"?> +<saml2p:AuthnRequest xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:xs="http://www.w3.org/2001/XMLSchema" AssertionConsumerServiceIndex="0" Destination="https://eidas-test.bmi.gv.at/ms_connector/pvp/post" ID="_d9748baa2c1d4cdaa436b2191307fc0e" IsPassive="false" IssueInstant="2020-02-06T15:18:56.002Z" ProviderName="OpenID Connect Demo" Version="2.0"> + <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/metadata</saml2:Issuer> + <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> + <ds:SignedInfo> + <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> + <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/> + <ds:Reference URI="#_d9748baa2c1d4cdaa436b2191307fc0e"> + <ds:Transforms> + <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> + <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"> + <ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="xs"/> + </ds:Transform> + </ds:Transforms> + <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/> + <ds:DigestValue>LxI6QpEx3gT26uxEJi9xZBSVeZIEPUiFYn48Kn8484E=</ds:DigestValue> + </ds:Reference> + </ds:SignedInfo> + <ds:SignatureValue>Id1Zxcrp5RgQw63/NnsYItW82JIWbBhyhL2l/vvcDNN6ccMo5NMY8qcPfmUuOmzi4JdbolAlR3wvoOu4CTXSl8w6Gz67Bbv4qP2kn+Mn6y2Eo40DMM2eEPq529yu9Aa4vU7uLVCHVUGw6vjvlnBeLw4Axwi2v1uxmGIEORb2XKeoy1DjWI9EdhJf7bufL+fEW3AdzZ5GRAUtZ3zh569G9BNnigzUg+j5Rn7An99QR1+2OrxTCFazH7m+Z8ouFXD9LEFtuJJzSEsRGIrU9/9RVYE6gYlb3qA3At2pY5sso2TEUqY2uknBCybz5PoSChAt+SgMp63nWoc9XRk4j/Lkww==</ds:SignatureValue> + <ds:KeyInfo> + <ds:X509Data> + <ds:X509Certificate>MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH +SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W +ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w +CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ +RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq +UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+ +M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F +Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt +1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq +nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC +VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq +itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc +2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O +fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy +4jpXrp77JXFRSDWddb0yePc=</ds:X509Certificate> + </ds:X509Data> + </ds:KeyInfo> + </ds:Signature> + <saml2p:Extensions> + <eid:RequestedAttributes xmlns:eid="http://eid.gv.at/eID/attributes/saml-extensions"> + <eid:RequestedAttribute FriendlyName="EID-SECTOR-FOR-IDENTIFIER" Name="urn:oid:1.2.40.0.10.2.1.1.261.34" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"> + <eid:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">urn:publicid:gv.at:cdid+BF</eid:AttributeValue> + </eid:RequestedAttribute> + </eid:RequestedAttributes> + </saml2p:Extensions> + <saml2p:NameIDPolicy AllowCreate="true" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"/> + <saml2p:RequestedAuthnContext Comparison="minimum"> + <saml2:AuthnContextClassRef xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">http://eidas.europa.eu/LoA/low</saml2:AuthnContextClassRef> + </saml2p:RequestedAuthnContext> + <saml2p:Scoping> + <saml2p:RequesterID>https://demo.egiz.gv.at/demoportal-openID_demo</saml2p:RequesterID> + </saml2p:Scoping> +</saml2p:AuthnRequest>
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/hsm_facade_trust_root.crt b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/hsm_facade_trust_root.crt new file mode 100644 index 00000000..01be3821 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/hsm_facade_trust_root.crt @@ -0,0 +1,10 @@ +-----BEGIN CERTIFICATE----- +MIIBdDCCARqgAwIBAgIEXkz1yjAKBggqhkjOPQQDAjARMQ8wDQYDVQQDDAZlY3Jv +b3QwHhcNMjAwMjE5MDg0NjAyWhcNMjEwMjE4MDg0NjAyWjARMQ8wDQYDVQQDDAZl +Y3Jvb3QwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAS8yvpVIWbPj4E7Lr87hwQR +T9DZf9WY5LMV7gF6NKpnJ5JkEql/s7fqBVbrh8aSNo6gmfmSk4VYGhPJ+DCMzzQj +o2AwXjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFOXafzYpIOlu6BgNU+Ee +JWuJobgWMB0GA1UdDgQWBBTl2n82KSDpbugYDVPhHiVriaG4FjALBgNVHQ8EBAMC +AQYwCgYIKoZIzj0EAwIDSAAwRQIgRt/51PKL/bATuLCdib95Ika+h845Jo0G+Sbn +bzNwJAcCIQCVD1cxEBuUkKaiaLbTiNVsEjvQb6ti0TFbbQUH66jCGA== +-----END CERTIFICATE----- diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/junit.jks b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/junit.jks Binary files differnew file mode 100644 index 00000000..59e6ad13 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/junit.jks diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/junit_metadata_sig_cert.crt b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/junit_metadata_sig_cert.crt new file mode 100644 index 00000000..b544c194 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/junit_metadata_sig_cert.crt @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIIC+jCCAeKgAwIBAgIEXjF+fTANBgkqhkiG9w0BAQsFADA/MQswCQYDVQQGEwJB +VDENMAsGA1UEBwwERUdJWjEOMAwGA1UECgwFalVuaXQxETAPBgNVBAMMCE1ldGFk +YXRhMB4XDTIwMDEyOTEyNDU0OVoXDTI2MDEyODEyNDU0OVowPzELMAkGA1UEBhMC +QVQxDTALBgNVBAcMBEVHSVoxDjAMBgNVBAoMBWpVbml0MREwDwYDVQQDDAhNZXRh +ZGF0YTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK230G3dxNbNlSYA +O5Kx/Js0aBAgxMt7q9m+dA35fK/dOvF/GjrqjWsMCnax+no9gLnq6x0gXiJclz6H +rp/YDOfLrJjMpNL/r0FWT947vbnEj7eT8TdY5d6Yi8AZulZmjiCI5nbZh2zwrP4+ +WqRroLoPhXQj8mDyp26M4xHBBUhLMRc2HV4S+XH4uNZ/vTmb8vBg31XGHCY33gl7 +/KA54JNGxJdN8Dxv6yHYsm91ZfVrX39W0iYLUNhUCkolwuQmjDVfrExM8BTLIONb +f+erJoCm3A9ghZyDYRQ/e69/UEUqDa6XOzykr88INkQscEiAXCDS+EBPMpKo+t3l +PIA9r7kCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAh/2mg4S03bdZy1OVtEAudBT9 +YZb9OF34hxPtNbkB/V04wSIg1d4TBr5KDhV7CdiUOxPZzHpS8LUCgfGX306FB6NX +zh/b67uTOPaE72AB4VIT/Np0fsM7k5WhG9k9NoprIGiqCz2lXcfpZiT+LtSO1vWS +YI87wR9KOSWjcw/5i5qZIAJuwvLCQj5JtUsmrhHK75222J3TJf4dS/gfN4xfY2rW +9vcXtH6//8WdWp/zx9V7Z1ZsDb8TDKtBCEGuFDgVeU5ScKtVq8qRoUKD3Ve76cZi +purO3KrRrVAuZP2EfLkZdHEHqe8GPigNnZ5kTn8V2VJ3iRAQ73hpJRR98tFd0A== +-----END CERTIFICATE----- diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/junit_without_trustcerts.jks b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/junit_without_trustcerts.jks Binary files differnew file mode 100644 index 00000000..b5262cb8 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/junit_without_trustcerts.jks diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/junit_without_trustcerts.p12 b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/junit_without_trustcerts.p12 Binary files differnew file mode 100644 index 00000000..c3fe2681 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/junit_without_trustcerts.p12 diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/metadata_sig_cert.crt b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/metadata_sig_cert.crt new file mode 100644 index 00000000..61aa137b --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/metadata_sig_cert.crt @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH +SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W +ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w +CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ +RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq +UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+ +M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F +Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt +1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq +nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC +VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq +itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc +2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O +fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy +4jpXrp77JXFRSDWddb0yePc= +-----END CERTIFICATE-----
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_junit_keystore.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_junit_keystore.xml new file mode 100644 index 00000000..7fdbef90 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_junit_keystore.xml @@ -0,0 +1,126 @@ +<?xml version="1.0" encoding="UTF-8"?> +<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" ID="_2e23ca9b2ba4dc9eef15187830d07ff0" entityID="https://demo.egiz.gv.at/demoportal_demologin/" validUntil="2045-02-05T06:41:42.966Z"> + <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> + <ds:SignedInfo> + <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> + <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/> + <ds:Reference URI="#_2e23ca9b2ba4dc9eef15187830d07ff0"> + <ds:Transforms> + <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> + <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> + </ds:Transforms> + <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/> + <ds:DigestValue>Jy/c0ZvVJSfWzSoAcxDx/o+T5W61vvNJNqTFz2o+ILc=</ds:DigestValue> + </ds:Reference> + </ds:SignedInfo> + <ds:SignatureValue>chMxIdwrPvr78j3oTtgS7udbydy9kye1bbeQ4jm2GeFKUfxvJqY+vt9MjVnWFeR4c16gd80BjZJ6xxD5i5Ifci3YtxeKSxq0ttH/xZYEhJZkD/0NrGUhSvNV9zuLAz3uGk/LJ+2JxRq7dbnW4n9MtGuYhea8OW9/Pr1xI1KyskQS76NZDsGjjfnFWbFXahLoQZULU4Ke3SfZVqLATTn0J34RZnjNH3QieY3LhRzOVu/I5yeZtnLgUS6dg0Gab9DA/pdNFaC632iaE5QCXJmhgpqkjbkayO9e8N93YGFjbszhU1Kws5OUGjXjfCZwezLeOUZoKEfo5c+4+zEaTrEQjg==</ds:SignatureValue> + <ds:KeyInfo> + <ds:X509Data> + <ds:X509Certificate>MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH +SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W +ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w +CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ +RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq +UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+ +M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F +Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt +1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq +nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC +VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq +itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc +2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O +fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy +4jpXrp77JXFRSDWddb0yePc=</ds:X509Certificate> + </ds:X509Data> + </ds:KeyInfo> + </ds:Signature> + <md:SPSSODescriptor AuthnRequestsSigned="true" WantAssertionsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"> + <md:KeyDescriptor use="signing"> + <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> + <ds:X509Data> + <ds:X509Certificate>MIIC+jCCAeKgAwIBAgIEXjF+fTANBgkqhkiG9w0BAQsFADA/MQswCQYDVQQGEwJB +VDENMAsGA1UEBwwERUdJWjEOMAwGA1UECgwFalVuaXQxETAPBgNVBAMMCE1ldGFk +YXRhMB4XDTIwMDEyOTEyNDU0OVoXDTI2MDEyODEyNDU0OVowPzELMAkGA1UEBhMC +QVQxDTALBgNVBAcMBEVHSVoxDjAMBgNVBAoMBWpVbml0MREwDwYDVQQDDAhNZXRh +ZGF0YTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK230G3dxNbNlSYA +O5Kx/Js0aBAgxMt7q9m+dA35fK/dOvF/GjrqjWsMCnax+no9gLnq6x0gXiJclz6H +rp/YDOfLrJjMpNL/r0FWT947vbnEj7eT8TdY5d6Yi8AZulZmjiCI5nbZh2zwrP4+ +WqRroLoPhXQj8mDyp26M4xHBBUhLMRc2HV4S+XH4uNZ/vTmb8vBg31XGHCY33gl7 +/KA54JNGxJdN8Dxv6yHYsm91ZfVrX39W0iYLUNhUCkolwuQmjDVfrExM8BTLIONb +f+erJoCm3A9ghZyDYRQ/e69/UEUqDa6XOzykr88INkQscEiAXCDS+EBPMpKo+t3l +PIA9r7kCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAh/2mg4S03bdZy1OVtEAudBT9 +YZb9OF34hxPtNbkB/V04wSIg1d4TBr5KDhV7CdiUOxPZzHpS8LUCgfGX306FB6NX +zh/b67uTOPaE72AB4VIT/Np0fsM7k5WhG9k9NoprIGiqCz2lXcfpZiT+LtSO1vWS +YI87wR9KOSWjcw/5i5qZIAJuwvLCQj5JtUsmrhHK75222J3TJf4dS/gfN4xfY2rW +9vcXtH6//8WdWp/zx9V7Z1ZsDb8TDKtBCEGuFDgVeU5ScKtVq8qRoUKD3Ve76cZi +purO3KrRrVAuZP2EfLkZdHEHqe8GPigNnZ5kTn8V2VJ3iRAQ73hpJRR98tFd0A==</ds:X509Certificate> + </ds:X509Data> + <ds:X509Data> + <ds:X509Certificate>MIIBbTCCARKgAwIBAgIEXjF+qTAKBggqhkjOPQQDAjA+MQswCQYDVQQGEwJBVDEN +MAsGA1UEBwwERUdJWjEOMAwGA1UECgwFalVuaXQxEDAOBgNVBAMMB3NpZ25pbmcw +HhcNMjAwMTI5MTI0NjMzWhcNMjcwMTI4MTI0NjMzWjA+MQswCQYDVQQGEwJBVDEN +MAsGA1UEBwwERUdJWjEOMAwGA1UECgwFalVuaXQxEDAOBgNVBAMMB3NpZ25pbmcw +WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASRt7gZRrr4rSEE7Q922oKQJF+mlkwC +LZnv8ZzHtH54s4VdyQFIBjQF1PPf9PTn+5tid8QJehZPndcoeD7J8fPJMAoGCCqG +SM49BAMCA0kAMEYCIQDFUO0owvqMVRO2FmD+vb8mqJBpWCE6Cl5pEHaygTa5LwIh +ANsmjI2azWiTSFjb7Ou5fnCfbeiJUP0s66m8qS4rYl9L + </ds:X509Certificate> + </ds:X509Data> + </ds:KeyInfo> + </md:KeyDescriptor> + <md:KeyDescriptor use="encryption"> + <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> + <ds:X509Data> + <ds:X509Certificate>MIIC+jCCAeKgAwIBAgIEXjF+fTANBgkqhkiG9w0BAQsFADA/MQswCQYDVQQGEwJB +VDENMAsGA1UEBwwERUdJWjEOMAwGA1UECgwFalVuaXQxETAPBgNVBAMMCE1ldGFk +YXRhMB4XDTIwMDEyOTEyNDU0OVoXDTI2MDEyODEyNDU0OVowPzELMAkGA1UEBhMC +QVQxDTALBgNVBAcMBEVHSVoxDjAMBgNVBAoMBWpVbml0MREwDwYDVQQDDAhNZXRh +ZGF0YTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK230G3dxNbNlSYA +O5Kx/Js0aBAgxMt7q9m+dA35fK/dOvF/GjrqjWsMCnax+no9gLnq6x0gXiJclz6H +rp/YDOfLrJjMpNL/r0FWT947vbnEj7eT8TdY5d6Yi8AZulZmjiCI5nbZh2zwrP4+ +WqRroLoPhXQj8mDyp26M4xHBBUhLMRc2HV4S+XH4uNZ/vTmb8vBg31XGHCY33gl7 +/KA54JNGxJdN8Dxv6yHYsm91ZfVrX39W0iYLUNhUCkolwuQmjDVfrExM8BTLIONb +f+erJoCm3A9ghZyDYRQ/e69/UEUqDa6XOzykr88INkQscEiAXCDS+EBPMpKo+t3l +PIA9r7kCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAh/2mg4S03bdZy1OVtEAudBT9 +YZb9OF34hxPtNbkB/V04wSIg1d4TBr5KDhV7CdiUOxPZzHpS8LUCgfGX306FB6NX +zh/b67uTOPaE72AB4VIT/Np0fsM7k5WhG9k9NoprIGiqCz2lXcfpZiT+LtSO1vWS +YI87wR9KOSWjcw/5i5qZIAJuwvLCQj5JtUsmrhHK75222J3TJf4dS/gfN4xfY2rW +9vcXtH6//8WdWp/zx9V7Z1ZsDb8TDKtBCEGuFDgVeU5ScKtVq8qRoUKD3Ve76cZi +purO3KrRrVAuZP2EfLkZdHEHqe8GPigNnZ5kTn8V2VJ3iRAQ73hpJRR98tFd0A==</ds:X509Certificate> + </ds:X509Data> + </ds:KeyInfo> + </md:KeyDescriptor> + <md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat> + <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/post" index="0" isDefault="true"/> + <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/redirect" index="1"/> + <md:AttributeConsumingService index="0" isDefault="true"> + <md:ServiceName xml:lang="en">Default Service</md:ServiceName> + <md:RequestedAttribute FriendlyName="BPK" Name="urn:oid:1.2.40.0.10.2.1.1.149" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="PRINCIPAL-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.20" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="BIRTHDATE" Name="urn:oid:1.2.40.0.10.2.1.1.55" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="PVP-VERSION" Name="urn:oid:1.2.40.0.10.2.1.1.261.10" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="EID-ISSUING-NATION" Name="urn:oid:1.2.40.0.10.2.1.1.261.32" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-SOURCE-PIN-TYPE" Name="urn:oid:1.2.40.0.10.2.1.1.261.76" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-FULL-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.84" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="MANDATE-TYPE" Name="urn:oid:1.2.40.0.10.2.1.1.261.68" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-SOURCE-PIN" Name="urn:oid:1.2.40.0.10.2.1.1.261.100" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="GIVEN-NAME" Name="urn:oid:2.5.4.42" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="EID-SECTOR-FOR-IDENTIFIER" Name="urn:oid:1.2.40.0.10.2.1.1.261.34" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="MANDATE-TYPE-OID" Name="urn:oid:1.2.40.0.10.2.1.1.261.106" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="EID-IDENTITY-LINK" Name="urn:oid:1.2.40.0.10.2.1.1.261.38" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="EID-CITIZEN-QAA-EIDAS-LEVEL" Name="urn:oid:1.2.40.0.10.2.1.1.261.108" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + </md:AttributeConsumingService> + </md:SPSSODescriptor> + <md:Organization> + <md:OrganizationName xml:lang="de">EGIZ</md:OrganizationName> + <md:OrganizationDisplayName xml:lang="de">E-Government Innovationszentrum</md:OrganizationDisplayName> + <md:OrganizationURL xml:lang="de">http://www.egiz.gv.at</md:OrganizationURL> + </md:Organization> + <md:ContactPerson contactType="technical"> + <md:Company>E-Government Innovationszentrum</md:Company> + <md:GivenName>Lenz</md:GivenName> + <md:SurName>Thomas</md:SurName> + <md:EmailAddress>thomas.lenz@egiz.gv.at</md:EmailAddress> + <md:TelephoneNumber>+43 316 873 5525</md:TelephoneNumber> + </md:ContactPerson> +</md:EntityDescriptor> diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_junit_keystore_classpath_entityId.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_junit_keystore_classpath_entityId.xml new file mode 100644 index 00000000..7ccd5484 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_junit_keystore_classpath_entityId.xml @@ -0,0 +1,242 @@ +<?xml version="1.0" encoding="UTF-8"?> +<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" ID="_2e23ca9b2ba4dc9eef15187830d07ff0" entityID="classpath:/data/pvp_metadata_junit_keystore_classpath_entityId.xml" validUntil="2045-02-05T06:41:42.966Z"> + <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> + <ds:SignedInfo> + <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> + <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/> + <ds:Reference URI="#_2e23ca9b2ba4dc9eef15187830d07ff0"> + <ds:Transforms> + <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> + <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> + </ds:Transforms> + <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/> + <ds:DigestValue>Jy/c0ZvVJSfWzSoAcxDx/o+T5W61vvNJNqTFz2o+ILc=</ds:DigestValue> + </ds:Reference> + </ds:SignedInfo> + <ds:SignatureValue>chMxIdwrPvr78j3oTtgS7udbydy9kye1bbeQ4jm2GeFKUfxvJqY+vt9MjVnWFeR4c16gd80BjZJ6xxD5i5Ifci3YtxeKSxq0ttH/xZYEhJZkD/0NrGUhSvNV9zuLAz3uGk/LJ+2JxRq7dbnW4n9MtGuYhea8OW9/Pr1xI1KyskQS76NZDsGjjfnFWbFXahLoQZULU4Ke3SfZVqLATTn0J34RZnjNH3QieY3LhRzOVu/I5yeZtnLgUS6dg0Gab9DA/pdNFaC632iaE5QCXJmhgpqkjbkayO9e8N93YGFjbszhU1Kws5OUGjXjfCZwezLeOUZoKEfo5c+4+zEaTrEQjg==</ds:SignatureValue> + <ds:KeyInfo> + <ds:X509Data> + <ds:X509Certificate>MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH +SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W +ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w +CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ +RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq +UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+ +M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F +Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt +1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq +nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC +VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq +itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc +2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O +fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy +4jpXrp77JXFRSDWddb0yePc=</ds:X509Certificate> + </ds:X509Data> + </ds:KeyInfo> + </ds:Signature> + <md:IDPSSODescriptor WantAuthnRequestsSigned="true" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"> + <md:KeyDescriptor use="signing"> + <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> + <ds:X509Data> + <ds:X509Certificate>MIIC+jCCAeKgAwIBAgIEXjF+fTANBgkqhkiG9w0BAQsFADA/MQswCQYDVQQGEwJB +VDENMAsGA1UEBwwERUdJWjEOMAwGA1UECgwFalVuaXQxETAPBgNVBAMMCE1ldGFk +YXRhMB4XDTIwMDEyOTEyNDU0OVoXDTI2MDEyODEyNDU0OVowPzELMAkGA1UEBhMC +QVQxDTALBgNVBAcMBEVHSVoxDjAMBgNVBAoMBWpVbml0MREwDwYDVQQDDAhNZXRh +ZGF0YTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK230G3dxNbNlSYA +O5Kx/Js0aBAgxMt7q9m+dA35fK/dOvF/GjrqjWsMCnax+no9gLnq6x0gXiJclz6H +rp/YDOfLrJjMpNL/r0FWT947vbnEj7eT8TdY5d6Yi8AZulZmjiCI5nbZh2zwrP4+ +WqRroLoPhXQj8mDyp26M4xHBBUhLMRc2HV4S+XH4uNZ/vTmb8vBg31XGHCY33gl7 +/KA54JNGxJdN8Dxv6yHYsm91ZfVrX39W0iYLUNhUCkolwuQmjDVfrExM8BTLIONb +f+erJoCm3A9ghZyDYRQ/e69/UEUqDa6XOzykr88INkQscEiAXCDS+EBPMpKo+t3l +PIA9r7kCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAh/2mg4S03bdZy1OVtEAudBT9 +YZb9OF34hxPtNbkB/V04wSIg1d4TBr5KDhV7CdiUOxPZzHpS8LUCgfGX306FB6NX +zh/b67uTOPaE72AB4VIT/Np0fsM7k5WhG9k9NoprIGiqCz2lXcfpZiT+LtSO1vWS +YI87wR9KOSWjcw/5i5qZIAJuwvLCQj5JtUsmrhHK75222J3TJf4dS/gfN4xfY2rW +9vcXtH6//8WdWp/zx9V7Z1ZsDb8TDKtBCEGuFDgVeU5ScKtVq8qRoUKD3Ve76cZi +purO3KrRrVAuZP2EfLkZdHEHqe8GPigNnZ5kTn8V2VJ3iRAQ73hpJRR98tFd0A==</ds:X509Certificate> + </ds:X509Data> + <ds:X509Data> + <ds:X509Certificate>MIIBbTCCARKgAwIBAgIEXjF+qTAKBggqhkjOPQQDAjA+MQswCQYDVQQGEwJBVDEN +MAsGA1UEBwwERUdJWjEOMAwGA1UECgwFalVuaXQxEDAOBgNVBAMMB3NpZ25pbmcw +HhcNMjAwMTI5MTI0NjMzWhcNMjcwMTI4MTI0NjMzWjA+MQswCQYDVQQGEwJBVDEN +MAsGA1UEBwwERUdJWjEOMAwGA1UECgwFalVuaXQxEDAOBgNVBAMMB3NpZ25pbmcw +WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASRt7gZRrr4rSEE7Q922oKQJF+mlkwC +LZnv8ZzHtH54s4VdyQFIBjQF1PPf9PTn+5tid8QJehZPndcoeD7J8fPJMAoGCCqG +SM49BAMCA0kAMEYCIQDFUO0owvqMVRO2FmD+vb8mqJBpWCE6Cl5pEHaygTa5LwIh +ANsmjI2azWiTSFjb7Ou5fnCfbeiJUP0s66m8qS4rYl9L + </ds:X509Certificate> + </ds:X509Data> + <ds:X509Data> + <ds:X509Certificate>MIIDFDCCArqgAwIBAgIIFy4Oe7D+zq8wCgYIKoZIzj0EAwIwIzEhMB8GA1UEAwwY +S2V5c3RvcmVCYWNrZWRQa2lTZXJ2aWNlMB4XDTIwMDIxOTE0MDMxNVoXDTIwMDUx +OTEzMDMxNVowMjEdMBsGA1UEAwwUaW50LWF1dGhoYW5kbGVyLXNpZ24xETAPBgNV +BAoMCHNvZnR3YXJlMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtE1v +1J54suM3VR17mTO5OKrCBeDP6a2dQswhMmUNO6i1l4eXNbtBvMj7k0mnc4yLLZxQ +P0cosjT1kNkOvSNCQcSI+869EOdU4QDCreGLss9a84ZNf/X3ioq/2PYTLOJSMkDQ +qLMHUVawwPYw+ZyUHaY7G0AwX5Gj1gMadfWVMDPAo5OT9WntpqG1850yO0aUMBaF +GSE9RrWVmL1+d2qHqh/pAwq6DQEtbKCl18t1zQfLZvumnQfF930KB2IkLaq6wRTW +IRdwte20PfVmEloAOdegXqUX59rkq6+5CaXfIsN+4Vkb12n2ArZwI/EFjgRdtGYj +CmuySDorynSHrCO934/LHjZtdJPFbg5/4CTXpI1aInum4uqDuq6xoL+ns4hk8kkD +9H9Pj5MYyjUc51+450ylOwLmGkqNDJBh3ecnH76NIoKviR3KlBaj0bSlnoV5Kl8H +bfnXQD98BH+YLeULrD3XWVjirOWPdfdNKcInpuXrdTZ/GvyGL5T/63mtEWiWysfP +Gw4+9AlWNXpyLviaHfxTpC6T76qYHKHd4eltRLubrgL8gHZrJwHio98kKfVMS3Oy +qHAEWBSWv+LveARn0RF4jlcPIL3gclrU9jxF4k5Btvdax3+if1MWVAZ9ML5263ug +Qr11Pkbko09VqppyM484/o+mJihTWyucKdVONw8CAwEAATAKBggqhkjOPQQDAgNI +ADBFAiBJSZqfI1kmJGy8/tRut7h2YbZWNeUA+gmFX+wJxu9ePwIhALgjht8La4AZ +/r3t33clJW8tGRMiA8cBbxm3Ox0y7DyP</ds:X509Certificate> + </ds:X509Data> + </ds:KeyInfo> + </md:KeyDescriptor> + <md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp2/post"/> + <md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp2/redirect"/> + <md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat> + <md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</md:NameIDFormat> + <md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</md:NameIDFormat> + <md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp2/post"/> + <md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp2/redirect"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" FriendlyName="MANDATOR-NATURAL-PERSON-BIRTHDATE" Name="urn:oid:1.2.40.0.10.2.1.1.261.82" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" FriendlyName="BPK" Name="urn:oid:1.2.40.0.10.2.1.1.149" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" FriendlyName="MANDATOR-NATURAL-PERSON-FAMILY-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.80" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" FriendlyName="EID-CCS-URL" Name="urn:oid:1.2.40.0.10.2.1.1.261.64" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" FriendlyName="MANDATE-PROF-REP-OID" Name="urn:oid:1.2.40.0.10.2.1.1.261.86" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" FriendlyName="BIRTHDATE" Name="urn:oid:1.2.40.0.10.2.1.1.55" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" FriendlyName="PRINCIPAL-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.20" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" FriendlyName="EID-AUTH-BLOCK" Name="urn:oid:1.2.40.0.10.2.1.1.261.62" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" FriendlyName="MANDATOR-LEGAL-PERSON-FULL-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.84" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" FriendlyName="MANDATE-TYPE" Name="urn:oid:1.2.40.0.10.2.1.1.261.68" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" FriendlyName="EID-SIGNER-CERTIFICATE" Name="urn:oid:1.2.40.0.10.2.1.1.261.66" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" FriendlyName="ENC-BPK-LIST" Name="urn:oid:1.2.40.0.10.2.1.1.261.22" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" FriendlyName="MANDATE-PROF-REP-DESCRIPTION" Name="urn:oid:1.2.40.0.10.2.1.1.261.88" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" FriendlyName="BPK-LIST" Name="urn:oid:1.2.40.0.10.2.1.1.261.28" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" FriendlyName="MANDATE-REFERENCE-VALUE" Name="urn:oid:1.2.40.0.10.2.1.1.261.90" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" FriendlyName="EID-CITIZEN-QAA-LEVEL" Name="urn:oid:1.2.40.0.10.2.1.1.261.94" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" FriendlyName="MANDATOR-NATURAL-PERSON-ENC-BPK-LIST" Name="urn:oid:1.2.40.0.10.2.1.1.261.72" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" FriendlyName="MANDATE-FULL-MANDATE" Name="urn:oid:1.2.40.0.10.2.1.1.261.92" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" FriendlyName="MANDATOR-NATURAL-PERSON-SOURCE-PIN" Name="urn:oid:1.2.40.0.10.2.1.1.261.70" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" FriendlyName="MANDATOR-LEGAL-PERSON-SOURCE-PIN-TYPE" Name="urn:oid:1.2.40.0.10.2.1.1.261.76" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" FriendlyName="MANDATOR-NATURAL-PERSON-BPK" Name="urn:oid:1.2.40.0.10.2.1.1.261.98" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" FriendlyName="EID-ISSUING-NATION" Name="urn:oid:1.2.40.0.10.2.1.1.261.32" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" FriendlyName="PVP-VERSION" Name="urn:oid:1.2.40.0.10.2.1.1.261.10" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" FriendlyName="MANDATOR-NATURAL-PERSON-BPK-LIST" Name="urn:oid:1.2.40.0.10.2.1.1.261.73" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" FriendlyName="EID-STORK-TOKEN" Name="urn:oid:1.2.40.0.10.2.1.1.261.96" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" FriendlyName="MANDATOR-LEGAL-PERSON-SOURCE-PIN" Name="urn:oid:1.2.40.0.10.2.1.1.261.100" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" FriendlyName="EID-SOURCE-PIN" Name="urn:oid:1.2.40.0.10.2.1.1.261.36" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" FriendlyName="MANDATOR-NATURAL-PERSON-SOURCE-PIN-TYPE" Name="urn:oid:1.2.40.0.10.2.1.1.261.102" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" FriendlyName="GIVEN-NAME" Name="urn:oid:2.5.4.42" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" FriendlyName="MANDATOR-NATURAL-PERSON-GIVEN-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.78" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" FriendlyName="EID-SECTOR-FOR-IDENTIFIER" Name="urn:oid:1.2.40.0.10.2.1.1.261.34" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" FriendlyName="EID-SOURCE-PIN-TYPE" Name="urn:oid:1.2.40.0.10.2.1.1.261.104" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" FriendlyName="EID-E-ID-TOKEN" Name="urn:oid:1.2.40.0.10.2.1.1.261.39" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" FriendlyName="MANDATE-TYPE-OID" Name="urn:oid:1.2.40.0.10.2.1.1.261.106" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" FriendlyName="EID-IDENTITY-LINK" Name="urn:oid:1.2.40.0.10.2.1.1.261.38" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" FriendlyName="EID-CITIZEN-QAA-EIDAS-LEVEL" Name="urn:oid:1.2.40.0.10.2.1.1.261.108" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"/> + <saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" FriendlyName="EID-IDENTITY-STATUS-LEVEL" Name="urn:oid:1.2.40.0.10.2.1.1.261.109" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"/> + </md:IDPSSODescriptor> + <md:SPSSODescriptor AuthnRequestsSigned="true" WantAssertionsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"> + <md:KeyDescriptor use="signing"> + <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> + <ds:X509Data> + <ds:X509Certificate>MIIC+jCCAeKgAwIBAgIEXjF+fTANBgkqhkiG9w0BAQsFADA/MQswCQYDVQQGEwJB +VDENMAsGA1UEBwwERUdJWjEOMAwGA1UECgwFalVuaXQxETAPBgNVBAMMCE1ldGFk +YXRhMB4XDTIwMDEyOTEyNDU0OVoXDTI2MDEyODEyNDU0OVowPzELMAkGA1UEBhMC +QVQxDTALBgNVBAcMBEVHSVoxDjAMBgNVBAoMBWpVbml0MREwDwYDVQQDDAhNZXRh +ZGF0YTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK230G3dxNbNlSYA +O5Kx/Js0aBAgxMt7q9m+dA35fK/dOvF/GjrqjWsMCnax+no9gLnq6x0gXiJclz6H +rp/YDOfLrJjMpNL/r0FWT947vbnEj7eT8TdY5d6Yi8AZulZmjiCI5nbZh2zwrP4+ +WqRroLoPhXQj8mDyp26M4xHBBUhLMRc2HV4S+XH4uNZ/vTmb8vBg31XGHCY33gl7 +/KA54JNGxJdN8Dxv6yHYsm91ZfVrX39W0iYLUNhUCkolwuQmjDVfrExM8BTLIONb +f+erJoCm3A9ghZyDYRQ/e69/UEUqDa6XOzykr88INkQscEiAXCDS+EBPMpKo+t3l +PIA9r7kCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAh/2mg4S03bdZy1OVtEAudBT9 +YZb9OF34hxPtNbkB/V04wSIg1d4TBr5KDhV7CdiUOxPZzHpS8LUCgfGX306FB6NX +zh/b67uTOPaE72AB4VIT/Np0fsM7k5WhG9k9NoprIGiqCz2lXcfpZiT+LtSO1vWS +YI87wR9KOSWjcw/5i5qZIAJuwvLCQj5JtUsmrhHK75222J3TJf4dS/gfN4xfY2rW +9vcXtH6//8WdWp/zx9V7Z1ZsDb8TDKtBCEGuFDgVeU5ScKtVq8qRoUKD3Ve76cZi +purO3KrRrVAuZP2EfLkZdHEHqe8GPigNnZ5kTn8V2VJ3iRAQ73hpJRR98tFd0A==</ds:X509Certificate> + </ds:X509Data> + <ds:X509Data> + <ds:X509Certificate>MIIBbTCCARKgAwIBAgIEXjF+qTAKBggqhkjOPQQDAjA+MQswCQYDVQQGEwJBVDEN +MAsGA1UEBwwERUdJWjEOMAwGA1UECgwFalVuaXQxEDAOBgNVBAMMB3NpZ25pbmcw +HhcNMjAwMTI5MTI0NjMzWhcNMjcwMTI4MTI0NjMzWjA+MQswCQYDVQQGEwJBVDEN +MAsGA1UEBwwERUdJWjEOMAwGA1UECgwFalVuaXQxEDAOBgNVBAMMB3NpZ25pbmcw +WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASRt7gZRrr4rSEE7Q922oKQJF+mlkwC +LZnv8ZzHtH54s4VdyQFIBjQF1PPf9PTn+5tid8QJehZPndcoeD7J8fPJMAoGCCqG +SM49BAMCA0kAMEYCIQDFUO0owvqMVRO2FmD+vb8mqJBpWCE6Cl5pEHaygTa5LwIh +ANsmjI2azWiTSFjb7Ou5fnCfbeiJUP0s66m8qS4rYl9L + </ds:X509Certificate> + </ds:X509Data> + <ds:X509Data> + <ds:X509Certificate>MIIDFDCCArqgAwIBAgIIFy4Oe7D+zq8wCgYIKoZIzj0EAwIwIzEhMB8GA1UEAwwY +S2V5c3RvcmVCYWNrZWRQa2lTZXJ2aWNlMB4XDTIwMDIxOTE0MDMxNVoXDTIwMDUx +OTEzMDMxNVowMjEdMBsGA1UEAwwUaW50LWF1dGhoYW5kbGVyLXNpZ24xETAPBgNV +BAoMCHNvZnR3YXJlMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtE1v +1J54suM3VR17mTO5OKrCBeDP6a2dQswhMmUNO6i1l4eXNbtBvMj7k0mnc4yLLZxQ +P0cosjT1kNkOvSNCQcSI+869EOdU4QDCreGLss9a84ZNf/X3ioq/2PYTLOJSMkDQ +qLMHUVawwPYw+ZyUHaY7G0AwX5Gj1gMadfWVMDPAo5OT9WntpqG1850yO0aUMBaF +GSE9RrWVmL1+d2qHqh/pAwq6DQEtbKCl18t1zQfLZvumnQfF930KB2IkLaq6wRTW +IRdwte20PfVmEloAOdegXqUX59rkq6+5CaXfIsN+4Vkb12n2ArZwI/EFjgRdtGYj +CmuySDorynSHrCO934/LHjZtdJPFbg5/4CTXpI1aInum4uqDuq6xoL+ns4hk8kkD +9H9Pj5MYyjUc51+450ylOwLmGkqNDJBh3ecnH76NIoKviR3KlBaj0bSlnoV5Kl8H +bfnXQD98BH+YLeULrD3XWVjirOWPdfdNKcInpuXrdTZ/GvyGL5T/63mtEWiWysfP +Gw4+9AlWNXpyLviaHfxTpC6T76qYHKHd4eltRLubrgL8gHZrJwHio98kKfVMS3Oy +qHAEWBSWv+LveARn0RF4jlcPIL3gclrU9jxF4k5Btvdax3+if1MWVAZ9ML5263ug +Qr11Pkbko09VqppyM484/o+mJihTWyucKdVONw8CAwEAATAKBggqhkjOPQQDAgNI +ADBFAiBJSZqfI1kmJGy8/tRut7h2YbZWNeUA+gmFX+wJxu9ePwIhALgjht8La4AZ +/r3t33clJW8tGRMiA8cBbxm3Ox0y7DyP</ds:X509Certificate> + </ds:X509Data> + </ds:KeyInfo> + </md:KeyDescriptor> + <md:KeyDescriptor use="encryption"> + <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> + <ds:X509Data> + <ds:X509Certificate>MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH +SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W +ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w +CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ +RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq +UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+ +M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F +Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt +1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq +nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC +VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq +itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc +2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O +fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy +4jpXrp77JXFRSDWddb0yePc=</ds:X509Certificate> + </ds:X509Data> + </ds:KeyInfo> + </md:KeyDescriptor> + <md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat> + <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/post" index="0" isDefault="true"/> + <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/redirect" index="1"/> + <md:AttributeConsumingService index="0" isDefault="true"> + <md:ServiceName xml:lang="en">Default Service</md:ServiceName> + <md:RequestedAttribute FriendlyName="BPK" Name="urn:oid:1.2.40.0.10.2.1.1.149" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="PRINCIPAL-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.20" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="BIRTHDATE" Name="urn:oid:1.2.40.0.10.2.1.1.55" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="PVP-VERSION" Name="urn:oid:1.2.40.0.10.2.1.1.261.10" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="EID-ISSUING-NATION" Name="urn:oid:1.2.40.0.10.2.1.1.261.32" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-SOURCE-PIN-TYPE" Name="urn:oid:1.2.40.0.10.2.1.1.261.76" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-FULL-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.84" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="MANDATE-TYPE" Name="urn:oid:1.2.40.0.10.2.1.1.261.68" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-SOURCE-PIN" Name="urn:oid:1.2.40.0.10.2.1.1.261.100" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="GIVEN-NAME" Name="urn:oid:2.5.4.42" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="EID-SECTOR-FOR-IDENTIFIER" Name="urn:oid:1.2.40.0.10.2.1.1.261.34" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="MANDATE-TYPE-OID" Name="urn:oid:1.2.40.0.10.2.1.1.261.106" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="EID-IDENTITY-LINK" Name="urn:oid:1.2.40.0.10.2.1.1.261.38" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="EID-CITIZEN-QAA-EIDAS-LEVEL" Name="urn:oid:1.2.40.0.10.2.1.1.261.108" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + </md:AttributeConsumingService> + </md:SPSSODescriptor> + <md:Organization> + <md:OrganizationName xml:lang="de">EGIZ</md:OrganizationName> + <md:OrganizationDisplayName xml:lang="de">E-Government Innovationszentrum</md:OrganizationDisplayName> + <md:OrganizationURL xml:lang="de">http://www.egiz.gv.at</md:OrganizationURL> + </md:Organization> + <md:ContactPerson contactType="technical"> + <md:Company>E-Government Innovationszentrum</md:Company> + <md:GivenName>Lenz</md:GivenName> + <md:SurName>Thomas</md:SurName> + <md:EmailAddress>thomas.lenz@egiz.gv.at</md:EmailAddress> + <md:TelephoneNumber>+43 316 873 5525</md:TelephoneNumber> + </md:ContactPerson> +</md:EntityDescriptor> diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_moaid_test.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_moaid_test.xml new file mode 100644 index 00000000..ddc6e4ad --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_moaid_test.xml @@ -0,0 +1,135 @@ +<?xml version="1.0" encoding="UTF-8"?> +<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" ID="_2e23ca9b2ba4dc9eef15187830d07ff0" entityID="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/metadata" validUntil="2040-02-05T06:41:42.966Z"> + <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> + <ds:SignedInfo> + <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> + <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/> + <ds:Reference URI="#_2e23ca9b2ba4dc9eef15187830d07ff0"> + <ds:Transforms> + <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> + <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> + </ds:Transforms> + <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/> + <ds:DigestValue>Jy/c0ZvVJSfWzSoAcxDx/o+T5W61vvNJNqTFz2o+ILc=</ds:DigestValue> + </ds:Reference> + </ds:SignedInfo> + <ds:SignatureValue>chMxIdwrPvr78j3oTtgS7udbydy9kye1bbeQ4jm2GeFKUfxvJqY+vt9MjVnWFeR4c16gd80BjZJ6xxD5i5Ifci3YtxeKSxq0ttH/xZYEhJZkD/0NrGUhSvNV9zuLAz3uGk/LJ+2JxRq7dbnW4n9MtGuYhea8OW9/Pr1xI1KyskQS76NZDsGjjfnFWbFXahLoQZULU4Ke3SfZVqLATTn0J34RZnjNH3QieY3LhRzOVu/I5yeZtnLgUS6dg0Gab9DA/pdNFaC632iaE5QCXJmhgpqkjbkayO9e8N93YGFjbszhU1Kws5OUGjXjfCZwezLeOUZoKEfo5c+4+zEaTrEQjg==</ds:SignatureValue> + <ds:KeyInfo> + <ds:X509Data> + <ds:X509Certificate>MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH +SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W +ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w +CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ +RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq +UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+ +M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F +Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt +1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq +nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC +VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq +itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc +2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O +fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy +4jpXrp77JXFRSDWddb0yePc=</ds:X509Certificate> + </ds:X509Data> + </ds:KeyInfo> + </ds:Signature> + <md:SPSSODescriptor AuthnRequestsSigned="true" WantAssertionsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"> + <md:KeyDescriptor use="signing"> + <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> + <ds:X509Data> + <ds:X509Certificate>MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH +SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W +ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w +CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ +RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq +UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+ +M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F +Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt +1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq +nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC +VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq +itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc +2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O +fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy +4jpXrp77JXFRSDWddb0yePc=</ds:X509Certificate> + </ds:X509Data> + <ds:X509Data> + <ds:X509Certificate>MIIEFTCCAv2gAwIBAgIJAI/HXXgQpJtFMA0GCSqGSIb3DQEBCwUAMGQxCzAJBgNVBAYTAkFUMRMw + EQYDVQQIEwpTb21lLVN0YXRlMQ0wCwYDVQQHEwRHcmF6MQ0wCwYDVQQKEwRFR0laMSIwIAYDVQQD + ExlNT0EtSUQgSURQIChUZXN0LVZlcnNpb24pMB4XDTE0MDEyMTA4NDAxOFoXDTE1MDEyMTA4NDAx + OFowZDELMAkGA1UEBhMCQVQxEzARBgNVBAgTClNvbWUtU3RhdGUxDTALBgNVBAcTBEdyYXoxDTAL + BgNVBAoTBEVHSVoxIjAgBgNVBAMTGU1PQS1JRCBJRFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqG + SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDFETzd0nLV2P4pUGnlLKj3V+MZ4bUyYkNK5NnkzB0PO8hm + tsrdg+HSNsnPiU5KvD26tFpxq9lfibZcAp9JHFqjA/capOHcTDhYkTvJcSdaKJzttTPy4wivTbRu + y+ocK9jjz6g8BFvP9wQ5/k2AwFaqj0SeJt0jJTn4CZ8XMNozA2hwkQA2heuMtOl24Ie9PRC3/Af7 + utV2CNfV2MysGHIxazsZDIgFF+5/nybyR1yiIxKb0BYDh3gbNdyH5uLVBHOP4hvzQN5Z1xc/cdzq + lzKn/4v6HJraNn00xLzK6nrG6gB6HvDok2l8T1Cc7f8I+sNlO2aM8rY4hGSGCfhiL6IFAgMBAAGj + gckwgcYwHQYDVR0OBBYEFKG3LzuPtAGCXUPTw3fo9dtsS9wWMIGWBgNVHSMEgY4wgYuAFKG3LzuP + tAGCXUPTw3fo9dtsS9wWoWikZjBkMQswCQYDVQQGEwJBVDETMBEGA1UECBMKU29tZS1TdGF0ZTEN + MAsGA1UEBxMER3JhejENMAsGA1UEChMERUdJWjEiMCAGA1UEAxMZTU9BLUlEIElEUCAoVGVzdC1W + ZXJzaW9uKYIJAI/HXXgQpJtFMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAME3wzEi + UAcF2pCDtMMJzX4IDhSkWNuvWtSMMy8Vgtcc2t570teIKh+qNKQWZyX3QFVE6ovDABg3ZUhn780l + G4/t6aMOUEeGg4udl7l0QRBRbdd+9oc0Aw5dQqku02AQ6wQd695PLj+F0GeA7cdef90aLPu6Rwa5 + z5BiKpReJZoul3NpjQXz7A1IslZOlIhEDcFUlBSn/+QfLOeNDKurvPT0OzUGSGfrv0AoniNHc/fz + lfyRmgFbzAVHedU5cIxcE0yHtEKFjFSVwtGng9rTJpoOoY4pvGvAHlw6GEgO+HwFukPDtnvY8vi/ + cfmNJhb06H+6mmHz929Bk4HuHoQj8X8= + </ds:X509Certificate> + </ds:X509Data> + </ds:KeyInfo> + </md:KeyDescriptor> + <md:KeyDescriptor use="encryption"> + <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> + <ds:X509Data> + <ds:X509Certificate>MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH +SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W +ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w +CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ +RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq +UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+ +M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F +Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt +1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq +nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC +VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq +itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc +2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O +fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy +4jpXrp77JXFRSDWddb0yePc=</ds:X509Certificate> + </ds:X509Data> + </ds:KeyInfo> + </md:KeyDescriptor> + <md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat> + <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/post" index="0" isDefault="true"/> + <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/redirect" index="1"/> + <md:AttributeConsumingService index="0" isDefault="true"> + <md:ServiceName xml:lang="en">Default Service</md:ServiceName> + <md:RequestedAttribute FriendlyName="BPK" Name="urn:oid:1.2.40.0.10.2.1.1.149" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="PRINCIPAL-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.20" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="BIRTHDATE" Name="urn:oid:1.2.40.0.10.2.1.1.55" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="PVP-VERSION" Name="urn:oid:1.2.40.0.10.2.1.1.261.10" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="EID-ISSUING-NATION" Name="urn:oid:1.2.40.0.10.2.1.1.261.32" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-SOURCE-PIN-TYPE" Name="urn:oid:1.2.40.0.10.2.1.1.261.76" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-FULL-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.84" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="MANDATE-TYPE" Name="urn:oid:1.2.40.0.10.2.1.1.261.68" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-SOURCE-PIN" Name="urn:oid:1.2.40.0.10.2.1.1.261.100" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="GIVEN-NAME" Name="urn:oid:2.5.4.42" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="EID-SECTOR-FOR-IDENTIFIER" Name="urn:oid:1.2.40.0.10.2.1.1.261.34" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="MANDATE-TYPE-OID" Name="urn:oid:1.2.40.0.10.2.1.1.261.106" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="EID-IDENTITY-LINK" Name="urn:oid:1.2.40.0.10.2.1.1.261.38" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="EID-CITIZEN-QAA-EIDAS-LEVEL" Name="urn:oid:1.2.40.0.10.2.1.1.261.108" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + </md:AttributeConsumingService> + </md:SPSSODescriptor> + <md:Organization> + <md:OrganizationName xml:lang="de">EGIZ</md:OrganizationName> + <md:OrganizationDisplayName xml:lang="de">E-Government Innovationszentrum</md:OrganizationDisplayName> + <md:OrganizationURL xml:lang="de">http://www.egiz.gv.at</md:OrganizationURL> + </md:Organization> + <md:ContactPerson contactType="technical"> + <md:Company>E-Government Innovationszentrum</md:Company> + <md:GivenName>Lenz</md:GivenName> + <md:SurName>Thomas</md:SurName> + <md:EmailAddress>thomas.lenz@egiz.gv.at</md:EmailAddress> + <md:TelephoneNumber>+43 316 873 5525</md:TelephoneNumber> + </md:ContactPerson> +</md:EntityDescriptor> diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_valid.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_valid.xml new file mode 100644 index 00000000..d5855d43 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_valid.xml @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="UTF-8"?><md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" ID="_ee52efc823faa4334d93d1a787fb2c24" entityID="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eid/metadata" validUntil="2020-02-05T10:58:10.849Z"><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:SignedInfo><ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/><ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/><ds:Reference URI="#_ee52efc823faa4334d93d1a787fb2c24"><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/><ds:DigestValue>O4rfKjKlNT+p4hNR5NtYkrnu/AATuSGxsKxn3C4+VhA=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>G8jkWHT0baEviEcd4Xd/+u/WMyVK1H/Jdy2y1YE1nv+61zrm3rEgzuW70kGGdpxGt3enWznYem9jwkckXVu21QWZa9XDICu1MIrnpWs37Iz2ph3uHqvfYLS3awEs4GzinB6sLNM+2xEgmv/hXjSFIeOsCAIxdAsA7Btbq6iIx0xIknVZHlp3pWBzXAFvsizWx7QFldaMhzsfZ1HgSd7EdqFoMEjhEr6FHsppj2NjKjqNVg4AGHFp+GkzxXcXHTcojwigIx4qFli4B6EdqGPvC1oX1fBy09iYxeA0maI/qwLsWLfShrtNE3eFi7aQblTkTaK1cFO8q5P8u61yKtv3wg==</ds:SignatureValue><ds:KeyInfo><ds:X509Data><ds:X509Certificate>MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH +SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W +ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w +CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ +RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq +UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+ +M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F +Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt +1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq +nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC +VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq +itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc +2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O +fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy +4jpXrp77JXFRSDWddb0yePc=</ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature><md:SPSSODescriptor AuthnRequestsSigned="true" WantAssertionsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"><md:KeyDescriptor use="signing"><ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:X509Data><ds:X509Certificate>MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH +SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W +ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w +CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ +RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq +UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+ +M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F +Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt +1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq +nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC +VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq +itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc +2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O +fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy +4jpXrp77JXFRSDWddb0yePc=</ds:X509Certificate></ds:X509Data></ds:KeyInfo></md:KeyDescriptor><md:KeyDescriptor use="encryption"><ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:X509Data><ds:X509Certificate>MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH +SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W +ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w +CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ +RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq +UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+ +M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F +Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt +1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq +nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC +VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq +itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc +2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O +fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy +4jpXrp77JXFRSDWddb0yePc=</ds:X509Certificate></ds:X509Data></ds:KeyInfo></md:KeyDescriptor><md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat><md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eid/post" index="0" isDefault="true"/><md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eid/redirect" index="1"/><md:AttributeConsumingService index="0" isDefault="true"><md:ServiceName xml:lang="en">Default Service</md:ServiceName><md:RequestedAttribute FriendlyName="MANDATOR-NATURAL-PERSON-BIRTHDATE" Name="urn:oid:1.2.40.0.10.2.1.1.261.82" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="BPK" Name="urn:oid:1.2.40.0.10.2.1.1.149" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="MANDATOR-NATURAL-PERSON-FAMILY-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.80" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="PRINCIPAL-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.20" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="BIRTHDATE" Name="urn:oid:1.2.40.0.10.2.1.1.55" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="EID-CCS-URL" Name="urn:oid:1.2.40.0.10.2.1.1.261.64" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="MANDATE-PROF-REP-OID" Name="urn:oid:1.2.40.0.10.2.1.1.261.86" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-FULL-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.84" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="MANDATE-TYPE" Name="urn:oid:1.2.40.0.10.2.1.1.261.68" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="ENC-BPK-LIST" Name="urn:oid:1.2.40.0.10.2.1.1.261.22" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="EID-SIGNER-CERTIFICATE" Name="urn:oid:1.2.40.0.10.2.1.1.261.66" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="MANDATE-PROF-REP-DESCRIPTION" Name="urn:oid:1.2.40.0.10.2.1.1.261.88" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="BPK-LIST" Name="urn:oid:1.2.40.0.10.2.1.1.261.28" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="MANDATE-REFERENCE-VALUE" Name="urn:oid:1.2.40.0.10.2.1.1.261.90" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="MANDATOR-NATURAL-PERSON-ENC-BPK-LIST" Name="urn:oid:1.2.40.0.10.2.1.1.261.72" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="PVP-VERSION" Name="urn:oid:1.2.40.0.10.2.1.1.261.10" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="EID-ISSUING-NATION" Name="urn:oid:1.2.40.0.10.2.1.1.261.32" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-SOURCE-PIN-TYPE" Name="urn:oid:1.2.40.0.10.2.1.1.261.76" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="MANDATOR-NATURAL-PERSON-BPK" Name="urn:oid:1.2.40.0.10.2.1.1.261.98" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="MANDATOR-NATURAL-PERSON-BPK-LIST" Name="urn:oid:1.2.40.0.10.2.1.1.261.73" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-SOURCE-PIN" Name="urn:oid:1.2.40.0.10.2.1.1.261.100" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="GIVEN-NAME" Name="urn:oid:2.5.4.42" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="EID-SECTOR-FOR-IDENTIFIER" Name="urn:oid:1.2.40.0.10.2.1.1.261.34" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="MANDATOR-NATURAL-PERSON-GIVEN-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.78" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="EID-E-ID-TOKEN" Name="urn:oid:1.2.40.0.10.2.1.1.261.39" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="MANDATE-TYPE-OID" Name="urn:oid:1.2.40.0.10.2.1.1.261.106" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="EID-CITIZEN-QAA-EIDAS-LEVEL" Name="urn:oid:1.2.40.0.10.2.1.1.261.108" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/><md:RequestedAttribute FriendlyName="EID-IDENTITY-STATUS-LEVEL" Name="urn:oid:1.2.40.0.10.2.1.1.261.109" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/></md:AttributeConsumingService></md:SPSSODescriptor><md:Organization><md:OrganizationName xml:lang="de">EGIZ</md:OrganizationName><md:OrganizationDisplayName xml:lang="de">E-Government Innovationszentrum</md:OrganizationDisplayName><md:OrganizationURL xml:lang="de">http://www.egiz.gv.at</md:OrganizationURL></md:Organization><md:ContactPerson contactType="technical"><md:Company>E-Government Innovationszentrum</md:Company><md:GivenName>Lenz</md:GivenName><md:SurName>Thomas</md:SurName><md:EmailAddress>thomas.lenz@egiz.gv.at</md:EmailAddress><md:TelephoneNumber>+43 316 873 5525</md:TelephoneNumber></md:ContactPerson></md:EntityDescriptor>
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_valid_with_entityCategory.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_valid_with_entityCategory.xml new file mode 100644 index 00000000..54ad2b03 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_valid_with_entityCategory.xml @@ -0,0 +1,107 @@ +<?xml version="1.0" encoding="UTF-8"?> +<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" ID="_ee52efc823faa4334d93d1a787fb2c24" entityID="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eid/metadata" validUntil="2020-02-05T10:58:10.849Z"> + <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> + <ds:SignedInfo> + <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> + <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/> + <ds:Reference URI="#_ee52efc823faa4334d93d1a787fb2c24"> + <ds:Transforms> + <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> + <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> + </ds:Transforms> + <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/> + <ds:DigestValue>O4rfKjKlNT+p4hNR5NtYkrnu/AATuSGxsKxn3C4+VhA=</ds:DigestValue> + </ds:Reference> + </ds:SignedInfo> + <ds:SignatureValue>G8jkWHT0baEviEcd4Xd/+u/WMyVK1H/Jdy2y1YE1nv+61zrm3rEgzuW70kGGdpxGt3enWznYem9jwkckXVu21QWZa9XDICu1MIrnpWs37Iz2ph3uHqvfYLS3awEs4GzinB6sLNM+2xEgmv/hXjSFIeOsCAIxdAsA7Btbq6iIx0xIknVZHlp3pWBzXAFvsizWx7QFldaMhzsfZ1HgSd7EdqFoMEjhEr6FHsppj2NjKjqNVg4AGHFp+GkzxXcXHTcojwigIx4qFli4B6EdqGPvC1oX1fBy09iYxeA0maI/qwLsWLfShrtNE3eFi7aQblTkTaK1cFO8q5P8u61yKtv3wg==</ds:SignatureValue> + <ds:KeyInfo> + <ds:X509Data> + <ds:X509Certificate>MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH +SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W +ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w +CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ +RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq +UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+ +M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F +Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt +1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq +nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC +VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq +itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc +2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O +fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy +4jpXrp77JXFRSDWddb0yePc=</ds:X509Certificate> + </ds:X509Data> + </ds:KeyInfo> + </ds:Signature> + <md:Extensions> + <mdattr:EntityAttributes xmlns:mdattr="urn:oasis:names:tc:SAML:metadata:attribute"> + <saml2:Attribute xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Name="http://macedir.org/entity-category" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">http://www.ref.gv.at/ns/names/agiz/pvp/citizentoken</saml2:AttributeValue> + </saml2:Attribute> + </mdattr:EntityAttributes> + </md:Extensions> + <md:SPSSODescriptor AuthnRequestsSigned="true" WantAssertionsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"> + <md:KeyDescriptor use="signing"> + <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> + <ds:X509Data> + <ds:X509Certificate>MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH +SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W +ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w +CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ +RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq +UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+ +M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F +Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt +1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq +nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC +VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq +itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc +2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O +fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy +4jpXrp77JXFRSDWddb0yePc=</ds:X509Certificate> + </ds:X509Data> + </ds:KeyInfo> + </md:KeyDescriptor> + <md:KeyDescriptor use="encryption"> + <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> + <ds:X509Data> + <ds:X509Certificate>MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH +SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W +ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w +CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ +RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq +UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+ +M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F +Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt +1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq +nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC +VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq +itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc +2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O +fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy +4jpXrp77JXFRSDWddb0yePc=</ds:X509Certificate> + </ds:X509Data> + </ds:KeyInfo> + </md:KeyDescriptor> + <md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat> + <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eid/post" index="0" isDefault="true"/> + <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eid/redirect" index="1"/> + <md:AttributeConsumingService index="0" isDefault="true"> + <md:ServiceName xml:lang="en">Default Service</md:ServiceName> + <md:RequestedAttribute FriendlyName="MANDATOR-NATURAL-PERSON-BIRTHDATE" Name="urn:oid:1.2.40.0.10.2.1.1.261.82" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + </md:AttributeConsumingService> + </md:SPSSODescriptor> + <md:Organization> + <md:OrganizationName xml:lang="de">EGIZ</md:OrganizationName> + <md:OrganizationDisplayName xml:lang="de">E-Government Innovationszentrum</md:OrganizationDisplayName> + <md:OrganizationURL xml:lang="de">http://www.egiz.gv.at</md:OrganizationURL> + </md:Organization> + <md:ContactPerson contactType="technical"> + <md:Company>E-Government Innovationszentrum</md:Company> + <md:GivenName>Lenz</md:GivenName> + <md:SurName>Thomas</md:SurName> + <md:EmailAddress>thomas.lenz@egiz.gv.at</md:EmailAddress> + <md:TelephoneNumber>+43 316 873 5525</md:TelephoneNumber> + </md:ContactPerson> +</md:EntityDescriptor> diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_valid_with_entityCategory_egov.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_valid_with_entityCategory_egov.xml new file mode 100644 index 00000000..5129c494 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_valid_with_entityCategory_egov.xml @@ -0,0 +1,107 @@ +<?xml version="1.0" encoding="UTF-8"?> +<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" ID="_ee52efc823faa4334d93d1a787fb2c24" entityID="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eid/metadata" validUntil="2045-02-05T10:58:10.849Z"> + <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> + <ds:SignedInfo> + <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> + <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/> + <ds:Reference URI="#_ee52efc823faa4334d93d1a787fb2c24"> + <ds:Transforms> + <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> + <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> + </ds:Transforms> + <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/> + <ds:DigestValue>O4rfKjKlNT+p4hNR5NtYkrnu/AATuSGxsKxn3C4+VhA=</ds:DigestValue> + </ds:Reference> + </ds:SignedInfo> + <ds:SignatureValue>G8jkWHT0baEviEcd4Xd/+u/WMyVK1H/Jdy2y1YE1nv+61zrm3rEgzuW70kGGdpxGt3enWznYem9jwkckXVu21QWZa9XDICu1MIrnpWs37Iz2ph3uHqvfYLS3awEs4GzinB6sLNM+2xEgmv/hXjSFIeOsCAIxdAsA7Btbq6iIx0xIknVZHlp3pWBzXAFvsizWx7QFldaMhzsfZ1HgSd7EdqFoMEjhEr6FHsppj2NjKjqNVg4AGHFp+GkzxXcXHTcojwigIx4qFli4B6EdqGPvC1oX1fBy09iYxeA0maI/qwLsWLfShrtNE3eFi7aQblTkTaK1cFO8q5P8u61yKtv3wg==</ds:SignatureValue> + <ds:KeyInfo> + <ds:X509Data> + <ds:X509Certificate>MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH +SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W +ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w +CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ +RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq +UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+ +M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F +Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt +1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq +nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC +VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq +itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc +2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O +fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy +4jpXrp77JXFRSDWddb0yePc=</ds:X509Certificate> + </ds:X509Data> + </ds:KeyInfo> + </ds:Signature> + <md:Extensions> + <mdattr:EntityAttributes xmlns:mdattr="urn:oasis:names:tc:SAML:metadata:attribute"> + <saml2:Attribute xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Name="http://macedir.org/entity-category" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">http://www.ref.gv.at/ns/names/agiz/pvp/egovtoken</saml2:AttributeValue> + </saml2:Attribute> + </mdattr:EntityAttributes> + </md:Extensions> + <md:SPSSODescriptor AuthnRequestsSigned="true" WantAssertionsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"> + <md:KeyDescriptor use="signing"> + <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> + <ds:X509Data> + <ds:X509Certificate>MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH +SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W +ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w +CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ +RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq +UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+ +M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F +Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt +1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq +nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC +VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq +itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc +2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O +fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy +4jpXrp77JXFRSDWddb0yePc=</ds:X509Certificate> + </ds:X509Data> + </ds:KeyInfo> + </md:KeyDescriptor> + <md:KeyDescriptor use="encryption"> + <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> + <ds:X509Data> + <ds:X509Certificate>MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH +SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W +ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w +CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ +RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq +UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+ +M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F +Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt +1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq +nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC +VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq +itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc +2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O +fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy +4jpXrp77JXFRSDWddb0yePc=</ds:X509Certificate> + </ds:X509Data> + </ds:KeyInfo> + </md:KeyDescriptor> + <md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat> + <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eid/post" index="0" isDefault="true"/> + <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eid/redirect" index="1"/> + <md:AttributeConsumingService index="0" isDefault="true"> + <md:ServiceName xml:lang="en">Default Service</md:ServiceName> + <md:RequestedAttribute FriendlyName="MANDATOR-NATURAL-PERSON-BIRTHDATE" Name="urn:oid:1.2.40.0.10.2.1.1.261.82" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + </md:AttributeConsumingService> + </md:SPSSODescriptor> + <md:Organization> + <md:OrganizationName xml:lang="de">EGIZ</md:OrganizationName> + <md:OrganizationDisplayName xml:lang="de">E-Government Innovationszentrum</md:OrganizationDisplayName> + <md:OrganizationURL xml:lang="de">http://www.egiz.gv.at</md:OrganizationURL> + </md:Organization> + <md:ContactPerson contactType="technical"> + <md:Company>E-Government Innovationszentrum</md:Company> + <md:GivenName>Lenz</md:GivenName> + <md:SurName>Thomas</md:SurName> + <md:EmailAddress>thomas.lenz@egiz.gv.at</md:EmailAddress> + <md:TelephoneNumber>+43 316 873 5525</md:TelephoneNumber> + </md:ContactPerson> +</md:EntityDescriptor> diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_wrong_schema.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_wrong_schema.xml new file mode 100644 index 00000000..5fc61717 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_wrong_schema.xml @@ -0,0 +1,122 @@ +<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" entityID="https://demo.egiz.gv.at/demoportal_demologin/" validUntil="2059-07-27T11:23:29.736Z"> + <ds:Signature> + <ds:SignedInfo> + <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> + <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/> + <ds:Reference URI="#_c0303e3081ac29bb8329cade76279069"> + <ds:Transforms> + <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> + <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> + </ds:Transforms> + <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/> + <ds:DigestValue>IjxuoZphYVmZdZ5HfoVDr35r2b1V840+SMeC89IO/SQ=</ds:DigestValue> + </ds:Reference> + </ds:SignedInfo> + <ds:SignatureValue>JILQKKPvsK7onsMweJauAcGEniFGJ5bXEOvfYhxAYCB+dXL6pH87USD1v9UqycllBDqQE/Rp2tPtqo11CjdcKs0KkceQCZjzmDlVPqMZrgh0FerTSysF0fcPKoKeAtqqk+WSu7Xk9lU+PCxGArGA+vBLTRRbAOuZpE7ORrS7AF2m5uaO1YOKfO0GN+LoxTiygI2aeqKsKMlPkboh4ZuEjv1ht9xUHeQtAf/MHtaXZDvaRQPXALf0oCRnDWpiiqvKdARJq5NXrrbrdow/M1FpoddtE0Mu65AsorIdXoPSXJnLhw/zDfHv82PQo0pW7ujc0yJY+5VzfURMZOyKmrfCmg==</ds:SignatureValue> + <ds:KeyInfo> + <ds:X509Data> + <ds:X509Certificate>MIIEFTCCAv2gAwIBAgIJAI/HXXgQpJtFMA0GCSqGSIb3DQEBCwUAMGQxCzAJBgNVBAYTAkFUMRMw +EQYDVQQIEwpTb21lLVN0YXRlMQ0wCwYDVQQHEwRHcmF6MQ0wCwYDVQQKEwRFR0laMSIwIAYDVQQD +ExlNT0EtSUQgSURQIChUZXN0LVZlcnNpb24pMB4XDTE0MDEyMTA4NDAxOFoXDTE1MDEyMTA4NDAx +OFowZDELMAkGA1UEBhMCQVQxEzARBgNVBAgTClNvbWUtU3RhdGUxDTALBgNVBAcTBEdyYXoxDTAL +BgNVBAoTBEVHSVoxIjAgBgNVBAMTGU1PQS1JRCBJRFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDFETzd0nLV2P4pUGnlLKj3V+MZ4bUyYkNK5NnkzB0PO8hm +tsrdg+HSNsnPiU5KvD26tFpxq9lfibZcAp9JHFqjA/capOHcTDhYkTvJcSdaKJzttTPy4wivTbRu +y+ocK9jjz6g8BFvP9wQ5/k2AwFaqj0SeJt0jJTn4CZ8XMNozA2hwkQA2heuMtOl24Ie9PRC3/Af7 +utV2CNfV2MysGHIxazsZDIgFF+5/nybyR1yiIxKb0BYDh3gbNdyH5uLVBHOP4hvzQN5Z1xc/cdzq +lzKn/4v6HJraNn00xLzK6nrG6gB6HvDok2l8T1Cc7f8I+sNlO2aM8rY4hGSGCfhiL6IFAgMBAAGj +gckwgcYwHQYDVR0OBBYEFKG3LzuPtAGCXUPTw3fo9dtsS9wWMIGWBgNVHSMEgY4wgYuAFKG3LzuP +tAGCXUPTw3fo9dtsS9wWoWikZjBkMQswCQYDVQQGEwJBVDETMBEGA1UECBMKU29tZS1TdGF0ZTEN +MAsGA1UEBxMER3JhejENMAsGA1UEChMERUdJWjEiMCAGA1UEAxMZTU9BLUlEIElEUCAoVGVzdC1W +ZXJzaW9uKYIJAI/HXXgQpJtFMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAME3wzEi +UAcF2pCDtMMJzX4IDhSkWNuvWtSMMy8Vgtcc2t570teIKh+qNKQWZyX3QFVE6ovDABg3ZUhn780l +G4/t6aMOUEeGg4udl7l0QRBRbdd+9oc0Aw5dQqku02AQ6wQd695PLj+F0GeA7cdef90aLPu6Rwa5 +z5BiKpReJZoul3NpjQXz7A1IslZOlIhEDcFUlBSn/+QfLOeNDKurvPT0OzUGSGfrv0AoniNHc/fz +lfyRmgFbzAVHedU5cIxcE0yHtEKFjFSVwtGng9rTJpoOoY4pvGvAHlw6GEgO+HwFukPDtnvY8vi/ +cfmNJhb06H+6mmHz929Bk4HuHoQj8X8=</ds:X509Certificate> + </ds:X509Data> + </ds:KeyInfo> + </ds:Signature> + <md:SPSSODescriptor AuthnRequestsSigned="true" WantAssertionsSigned="true" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"> + <md:KeyDescriptor use="signing"> + <ds:KeyInfo> + <ds:KeyValue> + <ds:RSAKeyValue> + <ds:Modulus>nEPzKMh3TovnfBnTyv+TMYFsGep8Uil7iNbfVyfLoBfqRdeGDOk4es2qWkgB6az+kM/9Js2H06m4 +pjEY7/RIjd0lMWqgi8eqdjilMmbFQykkYYQhlZbvi8KqoBcCKzj5N3GY4qh8A5qN4y85Q3sZj23T +iiIY1rphE+ZTOHCm6CKeRso9jj409YHP1xAXfPvtIYx2TA1uuagxOmL75OC/hr7gcUm0tmuKiSeq ++TO4VZw2Q7K7YESZ1WkiBoG2i4cHdcBFKnVrGNtyxl6UkjWxXRJSU9aNLs5QxsE6iFwCvFoIO+IU +cVWxfFHqOGbRtAcRUb4fk+KFHE2o1DLmfwZaUQ==</ds:Modulus> + <ds:Exponent>AQAB</ds:Exponent> + </ds:RSAKeyValue> + </ds:KeyValue> + </ds:KeyInfo> + <ds:KeyInfo> + <ds:X509Data> + <ds:X509Certificate>MIIEFTCCAv2gAwIBAgIJAI/HXXgQpJtFMA0GCSqGSIb3DQEBCwUAMGQxCzAJBgNVBAYTAkFUMRMw +EQYDVQQIEwpTb21lLVN0YXRlMQ0wCwYDVQQHEwRHcmF6MQ0wCwYDVQQKEwRFR0laMSIwIAYDVQQD +ExlNT0EtSUQgSURQIChUZXN0LVZlcnNpb24pMB4XDTE0MDEyMTA4NDAxOFoXDTE1MDEyMTA4NDAx +OFowZDELMAkGA1UEBhMCQVQxEzARBgNVBAgTClNvbWUtU3RhdGUxDTALBgNVBAcTBEdyYXoxDTAL +BgNVBAoTBEVHSVoxIjAgBgNVBAMTGU1PQS1JRCBJRFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDFETzd0nLV2P4pUGnlLKj3V+MZ4bUyYkNK5NnkzB0PO8hm +tsrdg+HSNsnPiU5KvD26tFpxq9lfibZcAp9JHFqjA/capOHcTDhYkTvJcSdaKJzttTPy4wivTbRu +y+ocK9jjz6g8BFvP9wQ5/k2AwFaqj0SeJt0jJTn4CZ8XMNozA2hwkQA2heuMtOl24Ie9PRC3/Af7 +utV2CNfV2MysGHIxazsZDIgFF+5/nybyR1yiIxKb0BYDh3gbNdyH5uLVBHOP4hvzQN5Z1xc/cdzq +lzKn/4v6HJraNn00xLzK6nrG6gB6HvDok2l8T1Cc7f8I+sNlO2aM8rY4hGSGCfhiL6IFAgMBAAGj +gckwgcYwHQYDVR0OBBYEFKG3LzuPtAGCXUPTw3fo9dtsS9wWMIGWBgNVHSMEgY4wgYuAFKG3LzuP +tAGCXUPTw3fo9dtsS9wWoWikZjBkMQswCQYDVQQGEwJBVDETMBEGA1UECBMKU29tZS1TdGF0ZTEN +MAsGA1UEBxMER3JhejENMAsGA1UEChMERUdJWjEiMCAGA1UEAxMZTU9BLUlEIElEUCAoVGVzdC1W +ZXJzaW9uKYIJAI/HXXgQpJtFMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAME3wzEi +UAcF2pCDtMMJzX4IDhSkWNuvWtSMMy8Vgtcc2t570teIKh+qNKQWZyX3QFVE6ovDABg3ZUhn780l +G4/t6aMOUEeGg4udl7l0QRBRbdd+9oc0Aw5dQqku02AQ6wQd695PLj+F0GeA7cdef90aLPu6Rwa5 +z5BiKpReJZoul3NpjQXz7A1IslZOlIhEDcFUlBSn/+QfLOeNDKurvPT0OzUGSGfrv0AoniNHc/fz +lfyRmgFbzAVHedU5cIxcE0yHtEKFjFSVwtGng9rTJpoOoY4pvGvAHlw6GEgO+HwFukPDtnvY8vi/ +cfmNJhb06H+6mmHz929Bk4HuHoQj8X8=</ds:X509Certificate> + </ds:X509Data> + </ds:KeyInfo> + </md:KeyDescriptor> + <md:KeyDescriptor use="encryption"> + <ds:KeyInfo> + <ds:X509Data> + <ds:X509Certificate>MIIEFTCCAv2gAwIBAgIJAI/HXXgQpJtFMA0GCSqGSIb3DQEBCwUAMGQxCzAJBgNVBAYTAkFUMRMw +EQYDVQQIEwpTb21lLVN0YXRlMQ0wCwYDVQQHEwRHcmF6MQ0wCwYDVQQKEwRFR0laMSIwIAYDVQQD +ExlNT0EtSUQgSURQIChUZXN0LVZlcnNpb24pMB4XDTE0MDEyMTA4NDAxOFoXDTE1MDEyMTA4NDAx +OFowZDELMAkGA1UEBhMCQVQxEzARBgNVBAgTClNvbWUtU3RhdGUxDTALBgNVBAcTBEdyYXoxDTAL +BgNVBAoTBEVHSVoxIjAgBgNVBAMTGU1PQS1JRCBJRFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDFETzd0nLV2P4pUGnlLKj3V+MZ4bUyYkNK5NnkzB0PO8hm +tsrdg+HSNsnPiU5KvD26tFpxq9lfibZcAp9JHFqjA/capOHcTDhYkTvJcSdaKJzttTPy4wivTbRu +y+ocK9jjz6g8BFvP9wQ5/k2AwFaqj0SeJt0jJTn4CZ8XMNozA2hwkQA2heuMtOl24Ie9PRC3/Af7 +utV2CNfV2MysGHIxazsZDIgFF+5/nybyR1yiIxKb0BYDh3gbNdyH5uLVBHOP4hvzQN5Z1xc/cdzq +lzKn/4v6HJraNn00xLzK6nrG6gB6HvDok2l8T1Cc7f8I+sNlO2aM8rY4hGSGCfhiL6IFAgMBAAGj +gckwgcYwHQYDVR0OBBYEFKG3LzuPtAGCXUPTw3fo9dtsS9wWMIGWBgNVHSMEgY4wgYuAFKG3LzuP +tAGCXUPTw3fo9dtsS9wWoWikZjBkMQswCQYDVQQGEwJBVDETMBEGA1UECBMKU29tZS1TdGF0ZTEN +MAsGA1UEBxMER3JhejENMAsGA1UEChMERUdJWjEiMCAGA1UEAxMZTU9BLUlEIElEUCAoVGVzdC1W +ZXJzaW9uKYIJAI/HXXgQpJtFMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAME3wzEi +UAcF2pCDtMMJzX4IDhSkWNuvWtSMMy8Vgtcc2t570teIKh+qNKQWZyX3QFVE6ovDABg3ZUhn780l +G4/t6aMOUEeGg4udl7l0QRBRbdd+9oc0Aw5dQqku02AQ6wQd695PLj+F0GeA7cdef90aLPu6Rwa5 +z5BiKpReJZoul3NpjQXz7A1IslZOlIhEDcFUlBSn/+QfLOeNDKurvPT0OzUGSGfrv0AoniNHc/fz +lfyRmgFbzAVHedU5cIxcE0yHtEKFjFSVwtGng9rTJpoOoY4pvGvAHlw6GEgO+HwFukPDtnvY8vi/ +cfmNJhb06H+6mmHz929Bk4HuHoQj8X8=</ds:X509Certificate> + </ds:X509Data> + </ds:KeyInfo> + </md:KeyDescriptor> + <md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://demo.egiz.gv.at/demoportal_demologin/pvp2/sp/redirect"/> + <md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat> + <md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</md:NameIDFormat> + <md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</md:NameIDFormat> + <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://demo.egiz.gv.at/demoportal_demologin/pvp2/sp/post" index="0" isDefault="true"/> + <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://demo.egiz.gv.at/demoportal_demologin/pvp2/sp/redirect" index="1"/> + </md:SPSSODescriptor> + <md:Organization> + <md:OrganizationName xml:lang="de">EGIZ</md:OrganizationName> + <md:OrganizationDisplayName xml:lang="de">E-Government Innovationszentrum</md:OrganizationDisplayName> + <md:OrganizationURL xml:lang="de">http://www.egiz.gv.at</md:OrganizationURL> + </md:Organization> + <md:ContactPerson contactType="technical"> + <md:Company>E-Government Innovationszentrum</md:Company> + <md:GivenName>Lenz</md:GivenName> + <md:SurName>Thomas</md:SurName> + <md:EmailAddress>thomas.lenz@egiz.gv.at</md:EmailAddress> + <md:TelephoneNumber>+43 316 873 5525</md:TelephoneNumber> + </md:ContactPerson> +</md:EntityDescriptor> diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_wrong_sig.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_wrong_sig.xml new file mode 100644 index 00000000..510c84f8 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_metadata_wrong_sig.xml @@ -0,0 +1,162 @@ +<?xml version="1.0" encoding="UTF-8"?> +<md:EntityDescriptor + xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" + xmlns:ds="http://www.w3.org/2000/09/xmldsig#" + entityID="https://demo.egiz.gv.at/demoportal_demologin/" + validUntil="2059-07-27T11:23:29.736Z"> + <ds:Signature> + <ds:SignedInfo> + <ds:CanonicalizationMethod + Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /> + <ds:SignatureMethod + Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" /> + <ds:Reference + URI="#_c0303e3081ac29bb8329cade76279069"> + <ds:Transforms> + <ds:Transform + Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /> + <ds:Transform + Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /> + </ds:Transforms> + <ds:DigestMethod + Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" /> + <ds:DigestValue>IjxuoZphYVmZdZ5HfoVDr35r2b1V840+SMeC89IO/SQ= + </ds:DigestValue> + </ds:Reference> + </ds:SignedInfo> + <ds:SignatureValue>JILQKKPvsK7onsMweJauAcGEniFGJ5bXEOvfYhxAYCB+dXL6pH87USD1v9UqycllBDqQE/Rp2tPtqo11CjdcKs0KkceQCZjzmDlVPqMZrgh0FerTSysF0fcPKoKeAtqqk+WSu7Xk9lU+PCxGArGA+vBLTRRbAOuZpE7ORrS7AF2m5uaO1YOKfO0GN+LoxTiygI2aeqKsKMlPkboh4ZuEjv1ht9xUHeQtAf/MHtaXZDvaRQPXALf0oCRnDWpiiqvKdARJq5NXrrbrdow/M1FpoddtE0Mu65AsorIdXoPSXJnLhw/zDfHv82PQo0pW7ujc0yJY+5VzfURMZOyKmrfCmg== + </ds:SignatureValue> + <ds:KeyInfo> + <ds:X509Data> + <ds:X509Certificate>MIIEFTCCAv2gAwIBAgIJAI/HXXgQpJtFMA0GCSqGSIb3DQEBCwUAMGQxCzAJBgNVBAYTAkFUMRMw + EQYDVQQIEwpTb21lLVN0YXRlMQ0wCwYDVQQHEwRHcmF6MQ0wCwYDVQQKEwRFR0laMSIwIAYDVQQD + ExlNT0EtSUQgSURQIChUZXN0LVZlcnNpb24pMB4XDTE0MDEyMTA4NDAxOFoXDTE1MDEyMTA4NDAx + OFowZDELMAkGA1UEBhMCQVQxEzARBgNVBAgTClNvbWUtU3RhdGUxDTALBgNVBAcTBEdyYXoxDTAL + BgNVBAoTBEVHSVoxIjAgBgNVBAMTGU1PQS1JRCBJRFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqG + SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDFETzd0nLV2P4pUGnlLKj3V+MZ4bUyYkNK5NnkzB0PO8hm + tsrdg+HSNsnPiU5KvD26tFpxq9lfibZcAp9JHFqjA/capOHcTDhYkTvJcSdaKJzttTPy4wivTbRu + y+ocK9jjz6g8BFvP9wQ5/k2AwFaqj0SeJt0jJTn4CZ8XMNozA2hwkQA2heuMtOl24Ie9PRC3/Af7 + utV2CNfV2MysGHIxazsZDIgFF+5/nybyR1yiIxKb0BYDh3gbNdyH5uLVBHOP4hvzQN5Z1xc/cdzq + lzKn/4v6HJraNn00xLzK6nrG6gB6HvDok2l8T1Cc7f8I+sNlO2aM8rY4hGSGCfhiL6IFAgMBAAGj + gckwgcYwHQYDVR0OBBYEFKG3LzuPtAGCXUPTw3fo9dtsS9wWMIGWBgNVHSMEgY4wgYuAFKG3LzuP + tAGCXUPTw3fo9dtsS9wWoWikZjBkMQswCQYDVQQGEwJBVDETMBEGA1UECBMKU29tZS1TdGF0ZTEN + MAsGA1UEBxMER3JhejENMAsGA1UEChMERUdJWjEiMCAGA1UEAxMZTU9BLUlEIElEUCAoVGVzdC1W + ZXJzaW9uKYIJAI/HXXgQpJtFMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAME3wzEi + UAcF2pCDtMMJzX4IDhSkWNuvWtSMMy8Vgtcc2t570teIKh+qNKQWZyX3QFVE6ovDABg3ZUhn780l + G4/t6aMOUEeGg4udl7l0QRBRbdd+9oc0Aw5dQqku02AQ6wQd695PLj+F0GeA7cdef90aLPu6Rwa5 + z5BiKpReJZoul3NpjQXz7A1IslZOlIhEDcFUlBSn/+QfLOeNDKurvPT0OzUGSGfrv0AoniNHc/fz + lfyRmgFbzAVHedU5cIxcE0yHtEKFjFSVwtGng9rTJpoOoY4pvGvAHlw6GEgO+HwFukPDtnvY8vi/ + cfmNJhb06H+6mmHz929Bk4HuHoQj8X8= + </ds:X509Certificate> + </ds:X509Data> + </ds:KeyInfo> + </ds:Signature> + <md:SPSSODescriptor AuthnRequestsSigned="true" + WantAssertionsSigned="true" + protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"> + <md:KeyDescriptor use="signing"> + <ds:KeyInfo> + <ds:KeyValue> + <ds:RSAKeyValue> + <ds:Modulus>nEPzKMh3TovnfBnTyv+TMYFsGep8Uil7iNbfVyfLoBfqRdeGDOk4es2qWkgB6az+kM/9Js2H06m4 + pjEY7/RIjd0lMWqgi8eqdjilMmbFQykkYYQhlZbvi8KqoBcCKzj5N3GY4qh8A5qN4y85Q3sZj23T + iiIY1rphE+ZTOHCm6CKeRso9jj409YHP1xAXfPvtIYx2TA1uuagxOmL75OC/hr7gcUm0tmuKiSeq + +TO4VZw2Q7K7YESZ1WkiBoG2i4cHdcBFKnVrGNtyxl6UkjWxXRJSU9aNLs5QxsE6iFwCvFoIO+IU + cVWxfFHqOGbRtAcRUb4fk+KFHE2o1DLmfwZaUQ== + </ds:Modulus> + <ds:Exponent>AQAB</ds:Exponent> + </ds:RSAKeyValue> + </ds:KeyValue> + <ds:KeyValue> + <ds:RSAKeyValue> + <ds:Modulus>xA7SEU+e0yQH5rm9kbCDN9o3aPIo7HbP7tX6WOocLZAtNfyxSZDU16ksL6W + jubafOqNEpcwR3RdFsT7bCqnXPBe5ELh5u4VEy19MzxkXRgrMvavzyBpVRgBUwUlV + 5foK5hhmbktQhyNdy/6LpQRhDUDsTvK+g9Ucj47es9AQJ3U= + </ds:Modulus> + <ds:Exponent>AQAB</ds:Exponent> + </ds:RSAKeyValue> + </ds:KeyValue> + <!-- ds:X509Data> + <ds:X509Certificate>MIIEFTCCAv2gAwIBAgIJAI/HXXgQpJtFMA0GCSqGSIb3DQEBCwUAMGQxCzAJBgNVBAYTAkFUMRMw + EQYDVQQIEwpTb21lLVN0YXRlMQ0wCwYDVQQHEwRHcmF6MQ0wCwYDVQQKEwRFR0laMSIwIAYDVQQD + ExlNT0EtSUQgSURQIChUZXN0LVZlcnNpb24pMB4XDTE0MDEyMTA4NDAxOFoXDTE1MDEyMTA4NDAx + OFowZDELMAkGA1UEBhMCQVQxEzARBgNVBAgTClNvbWUtU3RhdGUxDTALBgNVBAcTBEdyYXoxDTAL + BgNVBAoTBEVHSVoxIjAgBgNVBAMTGU1PQS1JRCBJRFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqG + SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDFETzd0nLV2P4pUGnlLKj3V+MZ4bUyYkNK5NnkzB0PO8hm + tsrdg+HSNsnPiU5KvD26tFpxq9lfibZcAp9JHFqjA/capOHcTDhYkTvJcSdaKJzttTPy4wivTbRu + y+ocK9jjz6g8BFvP9wQ5/k2AwFaqj0SeJt0jJTn4CZ8XMNozA2hwkQA2heuMtOl24Ie9PRC3/Af7 + utV2CNfV2MysGHIxazsZDIgFF+5/nybyR1yiIxKb0BYDh3gbNdyH5uLVBHOP4hvzQN5Z1xc/cdzq + lzKn/4v6HJraNn00xLzK6nrG6gB6HvDok2l8T1Cc7f8I+sNlO2aM8rY4hGSGCfhiL6IFAgMBAAGj + gckwgcYwHQYDVR0OBBYEFKG3LzuPtAGCXUPTw3fo9dtsS9wWMIGWBgNVHSMEgY4wgYuAFKG3LzuP + tAGCXUPTw3fo9dtsS9wWoWikZjBkMQswCQYDVQQGEwJBVDETMBEGA1UECBMKU29tZS1TdGF0ZTEN + MAsGA1UEBxMER3JhejENMAsGA1UEChMERUdJWjEiMCAGA1UEAxMZTU9BLUlEIElEUCAoVGVzdC1W + ZXJzaW9uKYIJAI/HXXgQpJtFMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAME3wzEi + UAcF2pCDtMMJzX4IDhSkWNuvWtSMMy8Vgtcc2t570teIKh+qNKQWZyX3QFVE6ovDABg3ZUhn780l + G4/t6aMOUEeGg4udl7l0QRBRbdd+9oc0Aw5dQqku02AQ6wQd695PLj+F0GeA7cdef90aLPu6Rwa5 + z5BiKpReJZoul3NpjQXz7A1IslZOlIhEDcFUlBSn/+QfLOeNDKurvPT0OzUGSGfrv0AoniNHc/fz + lfyRmgFbzAVHedU5cIxcE0yHtEKFjFSVwtGng9rTJpoOoY4pvGvAHlw6GEgO+HwFukPDtnvY8vi/ + cfmNJhb06H+6mmHz929Bk4HuHoQj8X8= + </ds:X509Certificate> + </ds:X509Data--> + </ds:KeyInfo> + </md:KeyDescriptor> + <md:KeyDescriptor use="encryption"> + <ds:KeyInfo> + <ds:X509Data> + <ds:X509Certificate>MIIEFTCCAv2gAwIBAgIJAI/HXXgQpJtFMA0GCSqGSIb3DQEBCwUAMGQxCzAJBgNVBAYTAkFUMRMw + EQYDVQQIEwpTb21lLVN0YXRlMQ0wCwYDVQQHEwRHcmF6MQ0wCwYDVQQKEwRFR0laMSIwIAYDVQQD + ExlNT0EtSUQgSURQIChUZXN0LVZlcnNpb24pMB4XDTE0MDEyMTA4NDAxOFoXDTE1MDEyMTA4NDAx + OFowZDELMAkGA1UEBhMCQVQxEzARBgNVBAgTClNvbWUtU3RhdGUxDTALBgNVBAcTBEdyYXoxDTAL + BgNVBAoTBEVHSVoxIjAgBgNVBAMTGU1PQS1JRCBJRFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqG + SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDFETzd0nLV2P4pUGnlLKj3V+MZ4bUyYkNK5NnkzB0PO8hm + tsrdg+HSNsnPiU5KvD26tFpxq9lfibZcAp9JHFqjA/capOHcTDhYkTvJcSdaKJzttTPy4wivTbRu + y+ocK9jjz6g8BFvP9wQ5/k2AwFaqj0SeJt0jJTn4CZ8XMNozA2hwkQA2heuMtOl24Ie9PRC3/Af7 + utV2CNfV2MysGHIxazsZDIgFF+5/nybyR1yiIxKb0BYDh3gbNdyH5uLVBHOP4hvzQN5Z1xc/cdzq + lzKn/4v6HJraNn00xLzK6nrG6gB6HvDok2l8T1Cc7f8I+sNlO2aM8rY4hGSGCfhiL6IFAgMBAAGj + gckwgcYwHQYDVR0OBBYEFKG3LzuPtAGCXUPTw3fo9dtsS9wWMIGWBgNVHSMEgY4wgYuAFKG3LzuP + tAGCXUPTw3fo9dtsS9wWoWikZjBkMQswCQYDVQQGEwJBVDETMBEGA1UECBMKU29tZS1TdGF0ZTEN + MAsGA1UEBxMER3JhejENMAsGA1UEChMERUdJWjEiMCAGA1UEAxMZTU9BLUlEIElEUCAoVGVzdC1W + ZXJzaW9uKYIJAI/HXXgQpJtFMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAME3wzEi + UAcF2pCDtMMJzX4IDhSkWNuvWtSMMy8Vgtcc2t570teIKh+qNKQWZyX3QFVE6ovDABg3ZUhn780l + G4/t6aMOUEeGg4udl7l0QRBRbdd+9oc0Aw5dQqku02AQ6wQd695PLj+F0GeA7cdef90aLPu6Rwa5 + z5BiKpReJZoul3NpjQXz7A1IslZOlIhEDcFUlBSn/+QfLOeNDKurvPT0OzUGSGfrv0AoniNHc/fz + lfyRmgFbzAVHedU5cIxcE0yHtEKFjFSVwtGng9rTJpoOoY4pvGvAHlw6GEgO+HwFukPDtnvY8vi/ + cfmNJhb06H+6mmHz929Bk4HuHoQj8X8= + </ds:X509Certificate> + </ds:X509Data> + </ds:KeyInfo> + </md:KeyDescriptor> + <md:SingleLogoutService + Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" + Location="https://demo.egiz.gv.at/demoportal_demologin/pvp2/sp/redirect" /> + <md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent + </md:NameIDFormat> + <md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient + </md:NameIDFormat> + <md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified + </md:NameIDFormat> + <md:AssertionConsumerService + Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" + Location="https://demo.egiz.gv.at/demoportal_demologin/pvp2/sp/post" + index="0" isDefault="true" /> + <md:AssertionConsumerService + Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" + Location="https://demo.egiz.gv.at/demoportal_demologin/pvp2/sp/redirect" + index="1" /> + </md:SPSSODescriptor> + <md:Organization> + <md:OrganizationName xml:lang="de">EGIZ + </md:OrganizationName> + <md:OrganizationDisplayName xml:lang="de">E-Government + Innovationszentrum</md:OrganizationDisplayName> + <md:OrganizationURL xml:lang="de">http://www.egiz.gv.at + </md:OrganizationURL> + </md:Organization> + <md:ContactPerson contactType="technical"> + <md:Company>E-Government Innovationszentrum</md:Company> + <md:GivenName>Lenz</md:GivenName> + <md:SurName>Thomas</md:SurName> + <md:EmailAddress>thomas.lenz@egiz.gv.at</md:EmailAddress> + <md:TelephoneNumber>+43 316 873 5525</md:TelephoneNumber> + </md:ContactPerson> +</md:EntityDescriptor> diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_postbinding_template.html b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_postbinding_template.html new file mode 100644 index 00000000..a0d31907 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/pvp_postbinding_template.html @@ -0,0 +1,3 @@ +#if($RelayState)RelayState=${RelayState}"}#end +#if($SAMLRequest)SAMLRequest=${SAMLRequest}"}#end +#if($SAMLResponse)SAMLResponse=${SAMLResponse}"}#end
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/SpringTest-context_lazy.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/SpringTest-context_lazy.xml new file mode 100644 index 00000000..59bb2e43 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/SpringTest-context_lazy.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:context="http://www.springframework.org/schema/context" + xmlns:tx="http://www.springframework.org/schema/tx" + xmlns:aop="http://www.springframework.org/schema/aop" + xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd + http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd" > + + <context:annotation-config /> + + <bean id="dummyCredentialProvider" + class="at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyCredentialProvider" + lazy-init="true"/> + + <bean id="eaafKeyStoreFactory" + class="at.gv.egiz.eaaf.core.impl.credential.EaafKeyStoreFactory" /> + +</beans> diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_core.beans.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_core.beans.xml new file mode 100644 index 00000000..0c421356 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_core.beans.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:context="http://www.springframework.org/schema/context" + xmlns:tx="http://www.springframework.org/schema/tx" + xmlns:aop="http://www.springframework.org/schema/aop" + xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd + http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> + + <!-- import resource="classpath:/spring/eaaf_utils.beans.xml" /--> + + <bean id="dummyVelocityGuiBuilder" + class="at.gv.egiz.eaaf.core.impl.idp.module.gui.DummyVelocityGuiFormBuilder" /> + + <bean id="dummyGuiBuilderConfigFactory" + class="at.gv.egiz.eaaf.core.impl.idp.module.gui.DummyGuiBuilderConfigurationFactory" /> + +</beans>
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_core_map_config.beans.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_core_map_config.beans.xml new file mode 100644 index 00000000..c1660a70 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_core_map_config.beans.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:context="http://www.springframework.org/schema/context" + xmlns:tx="http://www.springframework.org/schema/tx" + xmlns:aop="http://www.springframework.org/schema/aop" + xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd + http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> + + <bean id="dummyAuthConfigMap" + class="at.gv.egiz.eaaf.core.impl.idp.module.test.DummyAuthConfigMap"> + <constructor-arg value="/config/config_1.props" /> + </bean> + +</beans>
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_core_spring_config.beans.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_core_spring_config.beans.xml new file mode 100644 index 00000000..5319236b --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_core_spring_config.beans.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:context="http://www.springframework.org/schema/context" + xmlns:tx="http://www.springframework.org/schema/tx" + xmlns:aop="http://www.springframework.org/schema/aop" + xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd + http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> + + <bean id="dummyAuthConfig" + class="at.gv.egiz.eaaf.core.impl.idp.module.test.DummyAuthConfig" /> + + + <bean id="eaafKeyStoreFactory" + class="at.gv.egiz.eaaf.core.impl.credential.EaafKeyStoreFactory" /> + +</beans>
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_pvp.beans.xml b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_pvp.beans.xml new file mode 100644 index 00000000..e7cc42ed --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_pvp.beans.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:context="http://www.springframework.org/schema/context" + xmlns:tx="http://www.springframework.org/schema/tx" + xmlns:aop="http://www.springframework.org/schema/aop" + xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd + http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> + + <import resource="test_eaaf_core.beans.xml"/> + <import resource="classpath:/eaaf_pvp.beans.xml"/> + + <bean id="dummyCredentialProvider" + class="at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyCredentialProvider" /> + + <bean id="dummyChainingMetadataResolver" + class="at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyMetadataProvider"/> + + <bean id="samlVerificationEngine" + class="at.gv.egiz.eaaf.modules.pvp2.impl.verification.SamlVerificationEngine"/> + +</beans>
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_pvp2_idp/pom.xml b/eaaf_modules/eaaf_module_pvp2_idp/pom.xml index 69028266..ffda330d 100644 --- a/eaaf_modules/eaaf_module_pvp2_idp/pom.xml +++ b/eaaf_modules/eaaf_module_pvp2_idp/pom.xml @@ -5,10 +5,10 @@ <parent> <groupId>at.gv.egiz.eaaf</groupId> <artifactId>eaaf_modules</artifactId> - <version>1.0.13.2</version> + <version>1.1.0</version> </parent> <artifactId>eaaf_module_pvp2_idp</artifactId> - <name>eaaf_module_pvp2_core</name> + <name>eaaf_module_pvp2_idp</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> @@ -32,6 +32,29 @@ <artifactId>junit</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-test</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>at.gv.egiz.eaaf</groupId> + <artifactId>eaaf_core_utils</artifactId> + <scope>test</scope> + <type>test-jar</type> + </dependency> + <dependency> + <groupId>at.gv.egiz.eaaf</groupId> + <artifactId>eaaf-core</artifactId> + <scope>test</scope> + <type>test-jar</type> + </dependency> + <dependency> + <groupId>at.gv.egiz.eaaf</groupId> + <artifactId>eaaf_module_pvp2_core</artifactId> + <scope>test</scope> + <type>test-jar</type> + </dependency> </dependencies> <build> @@ -49,21 +72,20 @@ </plugin> <!-- enable co-existence of testng and junit --> - <plugin> - <artifactId>maven-surefire-plugin</artifactId> - <version>${surefire.version}</version> - <configuration> - <threadCount>1</threadCount> - <argLine>--add-modules java.xml.bind</argLine> - </configuration> - <dependencies> - <dependency> - <groupId>org.apache.maven.surefire</groupId> - <artifactId>surefire-junit47</artifactId> - <version>${surefire.version}</version> - </dependency> - </dependencies> - </plugin> + <plugin> + <artifactId>maven-surefire-plugin</artifactId> + <version>${surefire.version}</version> + <configuration> + <threadCount>1</threadCount> + </configuration> + <dependencies> + <dependency> + <groupId>org.apache.maven.surefire</groupId> + <artifactId>surefire-junit47</artifactId> + <version>${surefire.version}</version> + </dependency> + </dependencies> + </plugin> </plugins> </build> diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/PVP2SProfileIDPSpringResourceProvider.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/PVP2SProfileIDPSpringResourceProvider.java deleted file mode 100644 index d50c5ee4..00000000 --- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/PVP2SProfileIDPSpringResourceProvider.java +++ /dev/null @@ -1,54 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.idp; - -import org.springframework.core.io.ClassPathResource; -import org.springframework.core.io.Resource; - -import at.gv.egiz.components.spring.api.SpringResourceProvider; - -public class PVP2SProfileIDPSpringResourceProvider implements SpringResourceProvider { - - @Override - public String getName() { - return "EAAF PVP2 S-Profile IDP SpringResourceProvider"; - } - - @Override - public String[] getPackagesToScan() { - // TODO Auto-generated method stub - return null; - } - - @Override - public Resource[] getResourcesToLoad() { - ClassPathResource sl20AuthConfig = new ClassPathResource("/eaaf_pvp_idp.beans.xml", PVP2SProfileIDPSpringResourceProvider.class); - - return new Resource[] {sl20AuthConfig}; - } - -} diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/Pvp2SProfileIdpSpringResourceProvider.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/Pvp2SProfileIdpSpringResourceProvider.java new file mode 100644 index 00000000..7e572d70 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/Pvp2SProfileIdpSpringResourceProvider.java @@ -0,0 +1,48 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.idp; + +import at.gv.egiz.components.spring.api.SpringResourceProvider; + +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; + +public class Pvp2SProfileIdpSpringResourceProvider implements SpringResourceProvider { + + @Override + public String getName() { + return "EAAF PVP2 S-Profile IDP SpringResourceProvider"; + } + + @Override + public String[] getPackagesToScan() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Resource[] getResourcesToLoad() { + final ClassPathResource sl20AuthConfig = new ClassPathResource("/eaaf_pvp_idp.beans.xml", + Pvp2SProfileIdpSpringResourceProvider.class); + + return new Resource[] { sl20AuthConfig }; + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/api/builder/ISubjectNameIdGenerator.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/api/builder/ISubjectNameIdGenerator.java index 90662f48..fd04e38f 100644 --- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/api/builder/ISubjectNameIdGenerator.java +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/api/builder/ISubjectNameIdGenerator.java @@ -1,45 +1,39 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 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: + * Licensed under the EUPL, Version 1.2 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: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * 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. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * 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.egiz.eaaf.modules.pvp2.idp.api.builder; import at.gv.egiz.eaaf.core.api.idp.IAuthData; -import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration; +import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration; import at.gv.egiz.eaaf.core.impl.data.Pair; -import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; public interface ISubjectNameIdGenerator { - /** - * Generates a SAML2 subjectNameId from authentication data - * - * @param authData Authentication data for the current pending request - * @param spConfig Service provider configuration - * @return Pair of subjectNameId and NameIdFormat - * @throws PVP2Exception - */ - public Pair<String, String> generateSubjectNameId(IAuthData authData, ISPConfiguration spConfig) throws PVP2Exception; + /** + * Generates a SAML2 subjectNameId from authentication data. + * + * @param authData Authentication data for the current pending request + * @param spConfig Service provider configuration + * @return Pair of subjectNameId and NameIdFormat + * @throws Pvp2Exception In case of an error + */ + Pair<String, String> generateSubjectNameId(IAuthData authData, ISpConfiguration spConfig) + throws Pvp2Exception; } diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/InvalidAssertionConsumerServiceException.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/InvalidAssertionConsumerServiceException.java index 42424726..a7e05664 100644 --- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/InvalidAssertionConsumerServiceException.java +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/InvalidAssertionConsumerServiceException.java @@ -1,54 +1,46 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 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: + * Licensed under the EUPL, Version 1.2 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: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * 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. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * 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.egiz.eaaf.modules.pvp2.idp.exception; -import org.opensaml.saml2.core.StatusCode; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; + +import org.opensaml.saml.saml2.core.StatusCode; -import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception; +public class InvalidAssertionConsumerServiceException extends Pvp2Exception { -public class InvalidAssertionConsumerServiceException extends PVP2Exception { + private static final long serialVersionUID = 7861790149343943091L; - public InvalidAssertionConsumerServiceException(int idx) { - super("pvp2.28", new Object[]{idx}); - this.statusCodeValue = StatusCode.REQUESTER_URI; - } + public InvalidAssertionConsumerServiceException(final int idx) { + super("pvp2.28", new Object[] { idx }); + this.statusCodeValue = StatusCode.REQUESTER; + } - /** - * - */ - public InvalidAssertionConsumerServiceException(String wrongURL) { - super("pvp2.23", new Object[]{wrongURL}); - this.statusCodeValue = StatusCode.REQUESTER_URI; - - } + /** + * Invalid assertion consumer-service URL. + * + * @param wrongUrl invalid URL + */ + public InvalidAssertionConsumerServiceException(final String wrongUrl) { + super("pvp2.23", new Object[] { wrongUrl }); + this.statusCodeValue = StatusCode.REQUESTER; - /** - * - */ - private static final long serialVersionUID = 7861790149343943091L; + } } diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/InvalidAssertionEncryptionException.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/InvalidAssertionEncryptionException.java index 55c94df1..89179ff6 100644 --- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/InvalidAssertionEncryptionException.java +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/InvalidAssertionEncryptionException.java @@ -1,42 +1,35 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 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: + * Licensed under the EUPL, Version 1.2 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: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * 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. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * 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.egiz.eaaf.modules.pvp2.idp.exception; -import org.opensaml.saml2.core.StatusCode; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; -import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception; +import org.opensaml.saml.saml2.core.StatusCode; -public class InvalidAssertionEncryptionException extends PVP2Exception { +public class InvalidAssertionEncryptionException extends Pvp2Exception { - private static final long serialVersionUID = 6513388841485355549L; + private static final long serialVersionUID = 6513388841485355549L; - public InvalidAssertionEncryptionException() { - super("pvp2.16", new Object[]{}); - this.statusCodeValue = StatusCode.RESPONDER_URI; - } + public InvalidAssertionEncryptionException() { + super("pvp2.16", new Object[] {}); + this.statusCodeValue = StatusCode.RESPONDER; + } } diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/RequestDeniedException.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/RequestDeniedException.java index 6109c78d..cf4ac8d1 100644 --- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/RequestDeniedException.java +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/RequestDeniedException.java @@ -1,45 +1,35 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 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: + * Licensed under the EUPL, Version 1.2 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: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * 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. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * 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.egiz.eaaf.modules.pvp2.idp.exception; -import org.opensaml.saml2.core.StatusCode; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; -import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception; +import org.opensaml.saml.saml2.core.StatusCode; -public class RequestDeniedException extends PVP2Exception { +public class RequestDeniedException extends Pvp2Exception { - public RequestDeniedException() { - super("pvp2.14", null); - this.statusCodeValue = StatusCode.REQUEST_DENIED_URI; - } + private static final long serialVersionUID = 4415896615794730553L; - /** - * - */ - private static final long serialVersionUID = 4415896615794730553L; + public RequestDeniedException() { + super("pvp2.14", null); + this.statusCodeValue = StatusCode.REQUEST_DENIED; + } } diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/ResponderErrorException.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/ResponderErrorException.java index 7f565c00..e6cdf8f1 100644 --- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/ResponderErrorException.java +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/ResponderErrorException.java @@ -1,50 +1,40 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 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: + * Licensed under the EUPL, Version 1.2 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: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * 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. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * 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.egiz.eaaf.modules.pvp2.idp.exception; -import org.opensaml.saml2.core.StatusCode; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; + +import org.opensaml.saml.saml2.core.StatusCode; -import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception; +public class ResponderErrorException extends Pvp2Exception { -public class ResponderErrorException extends PVP2Exception { + private static final long serialVersionUID = -425416760138285446L; - /** - * - */ - private static final long serialVersionUID = -425416760138285446L; + public ResponderErrorException(final String messageId, final Object[] parameters, + final Throwable wrapped) { + super(messageId, parameters, wrapped); + this.statusCodeValue = StatusCode.RESPONDER; + } - public ResponderErrorException(String messageId, Object[] parameters, - Throwable wrapped) { - super(messageId, parameters, wrapped); - this.statusCodeValue = StatusCode.RESPONDER_URI; - } - - public ResponderErrorException(String messageId, Object[] parameters) { - super(messageId, parameters); - this.statusCodeValue = StatusCode.RESPONDER_URI; - } + public ResponderErrorException(final String messageId, final Object[] parameters) { + super(messageId, parameters); + this.statusCodeValue = StatusCode.RESPONDER; + } } diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/SAMLRequestNotSignedException.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/SAMLRequestNotSignedException.java deleted file mode 100644 index a0fad363..00000000 --- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/SAMLRequestNotSignedException.java +++ /dev/null @@ -1,50 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.idp.exception; - -import org.opensaml.saml2.core.StatusCode; - -import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception; - -public class SAMLRequestNotSignedException extends PVP2Exception { - - public SAMLRequestNotSignedException() { - super("pvp2.07", null); - this.statusCodeValue = StatusCode.REQUESTER_URI; - } - - public SAMLRequestNotSignedException(Throwable e) { - super("pvp2.07", null, e); - this.statusCodeValue = StatusCode.REQUESTER_URI; - } - - /** - * - */ - private static final long serialVersionUID = 1L; - -} diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/SAMLRequestNotSupported.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/SAMLRequestNotSupported.java deleted file mode 100644 index e59ebe0a..00000000 --- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/SAMLRequestNotSupported.java +++ /dev/null @@ -1,46 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.idp.exception; - -import org.opensaml.saml2.core.StatusCode; - -import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception; - - -public class SAMLRequestNotSupported extends PVP2Exception { - - public SAMLRequestNotSupported() { - super("pvp2.09", null); - this.statusCodeValue = StatusCode.REQUEST_UNSUPPORTED_URI; - } - - /** - * - */ - private static final long serialVersionUID = 1244883178458802767L; - -} diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/SamlRequestNotSignedException.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/SamlRequestNotSignedException.java new file mode 100644 index 00000000..add2103b --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/SamlRequestNotSignedException.java @@ -0,0 +1,40 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.idp.exception; + +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; + +import org.opensaml.saml.saml2.core.StatusCode; + +public class SamlRequestNotSignedException extends Pvp2Exception { + + private static final long serialVersionUID = 1L; + + public SamlRequestNotSignedException() { + super("pvp2.07", null); + this.statusCodeValue = StatusCode.REQUESTER; + } + + public SamlRequestNotSignedException(final Throwable e) { + super("pvp2.07", null, e); + this.statusCodeValue = StatusCode.REQUESTER; + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/SamlRequestNotSupported.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/SamlRequestNotSupported.java new file mode 100644 index 00000000..d672f457 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/SamlRequestNotSupported.java @@ -0,0 +1,35 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.idp.exception; + +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; + +import org.opensaml.saml.saml2.core.StatusCode; + +public class SamlRequestNotSupported extends Pvp2Exception { + + private static final long serialVersionUID = 1244883178458802767L; + + public SamlRequestNotSupported() { + super("pvp2.09", null); + this.statusCodeValue = StatusCode.REQUEST_UNSUPPORTED; + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/UnprovideableAttributeException.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/UnprovideableAttributeException.java index 0dfda55f..3a56b414 100644 --- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/UnprovideableAttributeException.java +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/exception/UnprovideableAttributeException.java @@ -1,43 +1,34 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 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: + * Licensed under the EUPL, Version 1.2 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: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * 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. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * 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.egiz.eaaf.modules.pvp2.idp.exception; -import org.opensaml.saml2.core.StatusCode; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; + +import org.opensaml.saml.saml2.core.StatusCode; -import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception; +public class UnprovideableAttributeException extends Pvp2Exception { -public class UnprovideableAttributeException extends PVP2Exception { - /** - * - */ - private static final long serialVersionUID = 3972197758163647157L; + private static final long serialVersionUID = 3972197758163647157L; - public UnprovideableAttributeException(String attributeName) { - super("pvp2.10", new Object[] {attributeName}); - this.statusCodeValue = StatusCode.UNKNOWN_ATTR_PROFILE_URI; - } + public UnprovideableAttributeException(final String attributeName) { + super("pvp2.10", new Object[] { attributeName }); + this.statusCodeValue = StatusCode.UNKNOWN_ATTR_PROFILE; + } } diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/AbstractPvp2XProtocol.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/AbstractPvp2XProtocol.java new file mode 100644 index 00000000..597d3c22 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/AbstractPvp2XProtocol.java @@ -0,0 +1,549 @@ +/******************************************************************************* + * Copyright 2017 Graz University of Technology + * EAAF-Core Components has been developed in a cooperation between EGIZ, + * A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.idp.impl; + +import java.util.List; + +import javax.annotation.PostConstruct; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang.StringEscapeUtils; +import org.apache.commons.lang3.StringUtils; +import org.joda.time.DateTime; +import org.opensaml.common.xml.SAMLConstants; +import org.opensaml.saml2.core.AuthnRequest; +import org.opensaml.saml2.core.Issuer; +import org.opensaml.saml2.core.NameID; +import org.opensaml.saml2.core.Response; +import org.opensaml.saml2.core.Status; +import org.opensaml.saml2.core.StatusCode; +import org.opensaml.saml2.core.StatusMessage; +import org.opensaml.saml2.metadata.AssertionConsumerService; +import org.opensaml.saml2.metadata.EntityDescriptor; +import org.opensaml.saml2.metadata.SPSSODescriptor; +import org.opensaml.ws.security.SecurityPolicyException; +import org.opensaml.xml.security.x509.X509Credential; +import org.opensaml.xml.signature.SignableXMLObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; + +import at.gv.egiz.components.eventlog.api.EventConstants; +import at.gv.egiz.eaaf.core.api.IRequest; +import at.gv.egiz.eaaf.core.api.data.EAAFConstants; +import at.gv.egiz.eaaf.core.api.idp.IModulInfo; +import at.gv.egiz.eaaf.core.api.logging.IRevisionLogger; +import at.gv.egiz.eaaf.core.exceptions.AuthnRequestValidatorException; +import at.gv.egiz.eaaf.core.exceptions.EAAFException; +import at.gv.egiz.eaaf.core.exceptions.InvalidProtocolRequestException; +import at.gv.egiz.eaaf.core.exceptions.NoPassivAuthenticationException; +import at.gv.egiz.eaaf.core.exceptions.SLOException; +import at.gv.egiz.eaaf.core.impl.idp.controller.AbstractController; +import at.gv.egiz.eaaf.modules.pvp2.PVPEventConstants; +import at.gv.egiz.eaaf.modules.pvp2.api.IPVP2BasicConfiguration; +import at.gv.egiz.eaaf.modules.pvp2.api.binding.IEncoder; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPVPMetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.api.validation.IAuthnRequestPostProcessor; +import at.gv.egiz.eaaf.modules.pvp2.exception.InvalidPVPRequestException; +import at.gv.egiz.eaaf.modules.pvp2.exception.NameIDFormatNotSupportedException; +import at.gv.egiz.eaaf.modules.pvp2.exception.NoMetadataInformationException; +import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception; +import at.gv.egiz.eaaf.modules.pvp2.idp.exception.InvalidAssertionConsumerServiceException; +import at.gv.egiz.eaaf.modules.pvp2.impl.binding.PostBinding; +import at.gv.egiz.eaaf.modules.pvp2.impl.binding.RedirectBinding; +import at.gv.egiz.eaaf.modules.pvp2.impl.binding.SoapBinding; +import at.gv.egiz.eaaf.modules.pvp2.impl.message.InboundMessage; +import at.gv.egiz.eaaf.modules.pvp2.impl.message.PVPSProfileRequest; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.AbstractCredentialProvider; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.SAML2Utils; +import at.gv.egiz.eaaf.modules.pvp2.impl.validation.EAAFURICompare; +import at.gv.egiz.eaaf.modules.pvp2.impl.validation.TrustEngineFactory; +import at.gv.egiz.eaaf.modules.pvp2.impl.verification.SAMLVerificationEngine; + +public abstract class AbstractPVP2XProtocol extends AbstractController implements IModulInfo { + private static final Logger log = LoggerFactory.getLogger(AbstractPVP2XProtocol.class); + + @Autowired(required=true) protected IPVP2BasicConfiguration pvpBasicConfiguration; + @Autowired(required=true) protected IPVPMetadataProvider metadataProvider; + @Autowired(required=true) protected SAMLVerificationEngine samlVerificationEngine; + @Autowired(required=false) protected List<IAuthnRequestPostProcessor> authRequestPostProcessors; + + private AbstractCredentialProvider pvpIDPCredentials; + + + + /** + * Sets a specific credential provider for PVP S-Profile IDP component. + * @param pvpIDPCredentials credential provider + */ + public void setPvpIDPCredentials(AbstractCredentialProvider pvpIDPCredentials) { + this.pvpIDPCredentials = pvpIDPCredentials; + + } + + public boolean generateErrorMessage(Throwable e, + HttpServletRequest request, HttpServletResponse response, + IRequest protocolRequest) throws Throwable { + + if(protocolRequest == null) { + throw e; + } + + if(!(protocolRequest instanceof PVPSProfilePendingRequest) ) { + throw e; + } + PVPSProfilePendingRequest pvpRequest = (PVPSProfilePendingRequest)protocolRequest; + + Response samlResponse = + SAML2Utils.createSAMLObject(Response.class); + Status status = SAML2Utils.createSAMLObject(Status.class); + StatusCode statusCode = SAML2Utils.createSAMLObject(StatusCode.class); + StatusMessage statusMessage = SAML2Utils.createSAMLObject(StatusMessage.class); + + String moaError = null; + + if(e instanceof NoPassivAuthenticationException) { + statusCode.setValue(StatusCode.NO_PASSIVE_URI); + statusMessage.setMessage(StringEscapeUtils.escapeXml(e.getLocalizedMessage())); + + } else if (e instanceof NameIDFormatNotSupportedException) { + statusCode.setValue(StatusCode.INVALID_NAMEID_POLICY_URI); + statusMessage.setMessage(StringEscapeUtils.escapeXml(e.getLocalizedMessage())); + + } else if (e instanceof SLOException) { + //SLOExecpetions only occurs if session information is lost + return false; + + } else if(e instanceof PVP2Exception) { + PVP2Exception ex = (PVP2Exception) e; + statusCode.setValue(ex.getStatusCodeValue()); + String statusMessageValue = ex.getStatusMessageValue(); + if(statusMessageValue != null) { + statusMessage.setMessage(StringEscapeUtils.escapeXml(statusMessageValue)); + } + moaError = statusMessager.mapInternalErrorToExternalError(ex.getErrorId()); + + } else { + statusCode.setValue(StatusCode.RESPONDER_URI); + statusMessage.setMessage(StringEscapeUtils.escapeXml(e.getLocalizedMessage())); + moaError = statusMessager.getResponseErrorCode(e); + } + + + if (StringUtils.isNotEmpty(moaError)) { + StatusCode moaStatusCode = SAML2Utils.createSAMLObject(StatusCode.class); + moaStatusCode.setValue(moaError); + statusCode.setStatusCode(moaStatusCode); + } + + status.setStatusCode(statusCode); + if(statusMessage.getMessage() != null) { + status.setStatusMessage(statusMessage); + } + samlResponse.setStatus(status); + String remoteSessionID = SAML2Utils.getSecureIdentifier(); + samlResponse.setID(remoteSessionID); + + samlResponse.setIssueInstant(new DateTime()); + Issuer nissuer = SAML2Utils.createSAMLObject(Issuer.class); + nissuer.setValue(pvpBasicConfiguration.getIDPEntityId(pvpRequest.getAuthURL())); + nissuer.setFormat(NameID.ENTITY); + samlResponse.setIssuer(nissuer); + + IEncoder encoder = null; + + if(pvpRequest.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI)) { + encoder = applicationContext.getBean("PVPRedirectBinding", RedirectBinding.class); + + } else if(pvpRequest.getBinding().equals(SAMLConstants.SAML2_POST_BINDING_URI)) { + encoder = applicationContext.getBean("PVPPOSTBinding", PostBinding.class); + + } else if (pvpRequest.getBinding().equals(SAMLConstants.SAML2_SOAP11_BINDING_URI)) { + encoder = applicationContext.getBean("PVPSOAPBinding", SoapBinding.class); + } + + if(encoder == null) { + // default to redirect binding + encoder = new RedirectBinding(); + } + + String relayState = null; + if (pvpRequest.getRequest() != null) + relayState = pvpRequest.getRequest().getRelayState(); + + X509Credential signCred = pvpIDPCredentials.getIDPAssertionSigningCredential(); + + encoder.encodeRespone(request, response, samlResponse, pvpRequest.getConsumerURL(), + relayState, signCred, protocolRequest); + return true; + } + + public boolean validate(HttpServletRequest request, + HttpServletResponse response, IRequest pending) { + + return true; + } + + protected void pvpMetadataRequest(HttpServletRequest req, HttpServletResponse resp) throws EAAFException { + //create pendingRequest object + PVPSProfilePendingRequest pendingReq = applicationContext.getBean(PVPSProfilePendingRequest.class); + pendingReq.initialize(req, authConfig); + pendingReq.setModule(getName()); + + revisionsLogger.logEvent( + pendingReq.getUniqueSessionIdentifier(), + pendingReq.getUniqueTransactionIdentifier(), + EventConstants.TRANSACTION_IP, + req.getRemoteAddr()); + + MetadataAction metadataAction = applicationContext.getBean(MetadataAction.class); + metadataAction.processRequest(pendingReq, + req, resp, null); + + } + + protected void PVPIDPPostRequest(HttpServletRequest req, HttpServletResponse resp) throws EAAFException { + PVPSProfilePendingRequest pendingReq = null; + + try { + //create pendingRequest object + pendingReq = applicationContext.getBean(PVPSProfilePendingRequest.class); + pendingReq.initialize(req, authConfig); + pendingReq.setModule(getName()); + + revisionsLogger.logEvent(EventConstants.SESSION_CREATED, pendingReq.getUniqueSessionIdentifier()); + revisionsLogger.logEvent(EventConstants.TRANSACTION_CREATED, pendingReq.getUniqueTransactionIdentifier()); + revisionsLogger.logEvent( + pendingReq.getUniqueSessionIdentifier(), + pendingReq.getUniqueTransactionIdentifier(), + EventConstants.TRANSACTION_IP, + req.getRemoteAddr()); + + //get POST-Binding decoder implementation + InboundMessage msg = (InboundMessage) new PostBinding().decode( + req, resp, metadataProvider, false, + new EAAFURICompare(pvpBasicConfiguration.getIDPSSOPostService(pendingReq.getAuthURL()))); + pendingReq.setRequest(msg); + + //preProcess Message + preProcess(req, resp, pendingReq); + + } catch (SecurityPolicyException e) { + String samlRequest = req.getParameter("SAMLRequest"); + log.warn("Receive INVALID protocol request: " + samlRequest, e); + + //write revision log entries + if (pendingReq != null) + revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR, pendingReq.getUniqueTransactionIdentifier()); + + throw new InvalidProtocolRequestException("pvp2.21", new Object[] {}); + + } catch (SecurityException e) { + String samlRequest = req.getParameter("SAMLRequest"); + log.warn("Receive INVALID protocol request: " + samlRequest, e); + + //write revision log entries + if (pendingReq != null) + revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR, pendingReq.getUniqueTransactionIdentifier()); + + throw new InvalidProtocolRequestException("pvp2.22", new Object[] {e.getMessage()}); + + } catch (EAAFException e) { + + //write revision log entries + if (pendingReq != null) + revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR, pendingReq.getUniqueTransactionIdentifier()); + + throw e; + + } catch (Throwable e) { + String samlRequest = req.getParameter("SAMLRequest"); + log.warn("Receive INVALID protocol request: " + samlRequest, e); + + //write revision log entries + if (pendingReq != null) + revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR, pendingReq.getUniqueTransactionIdentifier()); + + throw new EAAFException("pvp2.24", new Object[] {e.getMessage()}, e); + } + } + + protected void PVPIDPRedirecttRequest(HttpServletRequest req, HttpServletResponse resp) throws EAAFException { + PVPSProfilePendingRequest pendingReq = null; + try { + //create pendingRequest object + pendingReq = applicationContext.getBean(PVPSProfilePendingRequest.class); + pendingReq.initialize(req, authConfig); + pendingReq.setModule(getName()); + + revisionsLogger.logEvent(EventConstants.SESSION_CREATED, pendingReq.getUniqueSessionIdentifier()); + revisionsLogger.logEvent(EventConstants.TRANSACTION_CREATED, pendingReq.getUniqueTransactionIdentifier()); + revisionsLogger.logEvent( + pendingReq.getUniqueSessionIdentifier(), + pendingReq.getUniqueTransactionIdentifier(), + EventConstants.TRANSACTION_IP, + req.getRemoteAddr()); + + //get POST-Binding decoder implementation + InboundMessage msg = (InboundMessage) new RedirectBinding().decode( + req, resp, metadataProvider, false, + new EAAFURICompare(pvpBasicConfiguration.getIDPSSORedirectService(pendingReq.getAuthURL()))); + pendingReq.setRequest(msg); + + //preProcess Message + preProcess(req, resp, pendingReq); + + } catch (SecurityPolicyException e) { + String samlRequest = req.getParameter("SAMLRequest"); + log.warn("Receive INVALID protocol request: " + samlRequest, e); + + //write revision log entries + if (pendingReq != null) + revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR, pendingReq.getUniqueTransactionIdentifier()); + + throw new InvalidProtocolRequestException("pvp2.21", new Object[] {}); + + } catch (SecurityException e) { + String samlRequest = req.getParameter("SAMLRequest"); + log.warn("Receive INVALID protocol request: " + samlRequest, e); + + //write revision log entries + if (pendingReq != null) + revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR, pendingReq.getUniqueTransactionIdentifier()); + + throw new InvalidProtocolRequestException("pvp2.22", new Object[] {e.getMessage()}); + + } catch (EAAFException e) { + String samlRequest = req.getParameter("SAMLRequest"); + log.info("Receive INVALID protocol request: " + samlRequest); + + //write revision log entries + if (pendingReq != null) + revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR, pendingReq.getUniqueTransactionIdentifier()); + + throw e; + + } catch (Throwable e) { + String samlRequest = req.getParameter("SAMLRequest"); + log.warn("Receive INVALID protocol request: " + samlRequest, e); + + //write revision log entries + if (pendingReq != null) + revisionsLogger.logEvent(pendingReq, EventConstants.TRANSACTION_ERROR, pendingReq.getUniqueTransactionIdentifier()); + + throw new EAAFException("pvp2.24", new Object[] {e.getMessage()}, e); + } + } + + + + /** + * + * + * @param request + * @param response + * @param msg + * @return true if preprocess can handle this request type, otherwise false + * @throws Throwable + */ + abstract protected boolean childPreProcess(HttpServletRequest request, + HttpServletResponse response, PVPSProfilePendingRequest pendingReq) throws Throwable; + + protected void preProcess(HttpServletRequest request, + HttpServletResponse response, PVPSProfilePendingRequest pendingReq) throws Throwable { + + InboundMessage msg = pendingReq.getRequest(); + + if (StringUtils.isEmpty(msg.getEntityID())) { + throw new InvalidProtocolRequestException("pvp2.20", new Object[] {}); + + } + + if(!msg.isVerified()) { + samlVerificationEngine.verify(msg, + TrustEngineFactory.getSignatureKnownKeysTrustEngine(metadataProvider)); + msg.setVerified(true); + + } + + revisionsLogger.logEvent(pendingReq, IRevisionLogger.AUTHPROTOCOL_TYPE, getAuthProtocolIdentifier()); + + if (msg instanceof PVPSProfileRequest && + ((PVPSProfileRequest)msg).getSamlRequest() instanceof AuthnRequest) + preProcessAuthRequest(request, response, pendingReq); + + else if (childPreProcess(request, response, pendingReq)) + log.debug("Find protocol handler in child implementation"); + + else { + log.error("Receive unsupported PVP21 message of type: " + ((PVPSProfileRequest)msg).getSamlRequest().getClass().getName()); + throw new InvalidPVPRequestException("pvp2.09", + new Object[] {((PVPSProfileRequest)msg).getSamlRequest().getClass().getName()}); + } + + + + //switch to session authentication + protAuthService.performAuthentication(request, response, pendingReq); + } + + + /** + * PreProcess Authn request + * @param request + * @param response + * @param pendingReq + * @throws Throwable + */ + private void preProcessAuthRequest(HttpServletRequest request, + HttpServletResponse response, PVPSProfilePendingRequest pendingReq) throws Throwable { + + PVPSProfileRequest moaRequest = ((PVPSProfileRequest)pendingReq.getRequest()); + SignableXMLObject samlReq = moaRequest.getSamlRequest(); + + if(!(samlReq instanceof AuthnRequest)) { + throw new InvalidPVPRequestException("Unsupported request", new Object[] {}); + } + + EntityDescriptor metadata = moaRequest.getEntityMetadata(metadataProvider); + if(metadata == null) { + throw new NoMetadataInformationException(); + } + SPSSODescriptor spSSODescriptor = metadata.getSPSSODescriptor(SAMLConstants.SAML20P_NS); + + AuthnRequest authnRequest = (AuthnRequest)samlReq; + + if (authnRequest.getIssueInstant() == null) { + log.warn("Unsupported request: No IssueInstant Attribute found."); + throw new AuthnRequestValidatorException("pvp2.22", + new Object[] {"Unsupported request: No IssueInstant Attribute found"}, + pendingReq); + + } + + if (authnRequest.getIssueInstant().minusMinutes(EAAFConstants.ALLOWED_TIME_JITTER).isAfterNow()) { + log.warn("Unsupported request: No IssueInstant DateTime is not valid anymore."); + throw new AuthnRequestValidatorException("pvp2.22", + new Object[] {"Unsupported request: No IssueInstant DateTime is not valid anymore."}, + pendingReq); + + } + + //parse AssertionConsumerService + AssertionConsumerService consumerService = null; + if (StringUtils.isNotEmpty(authnRequest.getAssertionConsumerServiceURL()) && + StringUtils.isNotEmpty(authnRequest.getProtocolBinding())) { + //use AssertionConsumerServiceURL from request + + //check requested AssertionConsumingService URL against metadata + List<AssertionConsumerService> metadataAssertionServiceList = spSSODescriptor.getAssertionConsumerServices(); + for (AssertionConsumerService service : metadataAssertionServiceList) { + if (authnRequest.getProtocolBinding().equals(service.getBinding()) + && authnRequest.getAssertionConsumerServiceURL().equals(service.getLocation())) { + consumerService = SAML2Utils.createSAMLObject(AssertionConsumerService.class); + consumerService.setBinding(authnRequest.getProtocolBinding()); + consumerService.setLocation(authnRequest.getAssertionConsumerServiceURL()); + log.debug("Requested AssertionConsumerServiceURL is valid."); + } + } + + if (consumerService == null) { + throw new InvalidAssertionConsumerServiceException(authnRequest.getAssertionConsumerServiceURL()); + + } + + + } else { + //use AssertionConsumerServiceIndex and select consumerService from metadata + Integer aIdx = authnRequest.getAssertionConsumerServiceIndex(); + int assertionidx = 0; + + if(aIdx != null) { + assertionidx = aIdx.intValue(); + + } else { + assertionidx = SAML2Utils.getDefaultAssertionConsumerServiceIndex(spSSODescriptor); + + } + consumerService = spSSODescriptor.getAssertionConsumerServices().get(assertionidx); + + if (consumerService == null) { + throw new InvalidAssertionConsumerServiceException(aIdx); + + } + } + + + //validate AuthnRequest + AuthnRequest authReq = (AuthnRequest) samlReq; + String oaURL = moaRequest.getEntityMetadata(metadataProvider).getEntityID(); + log.info("Dispatch PVP2 AuthnRequest: OAURL=" + oaURL + " Binding=" + consumerService.getBinding()); + + pendingReq.setSPEntityId(StringEscapeUtils.escapeHtml(oaURL)); + pendingReq.setOnlineApplicationConfiguration(authConfig.getServiceProviderConfiguration(pendingReq.getSPEntityId())); + pendingReq.setBinding(consumerService.getBinding()); + pendingReq.setRequest(moaRequest); + pendingReq.setConsumerURL(consumerService.getLocation()); + + //parse AuthRequest + pendingReq.setPassiv(authReq.isPassive()); + pendingReq.setForce(authReq.isForceAuthn()); + + //AuthnRequest needs authentication + pendingReq.setNeedAuthentication(true); + + //set protocol action, which should be executed after authentication + pendingReq.setAction(AuthenticationAction.class.getName()); + + // do post-processing if required + log.trace("Starting extended AuthnRequest validation and processing ... "); + if (authRequestPostProcessors != null) { + for (final IAuthnRequestPostProcessor processor : authRequestPostProcessors) { + log.trace("Post-process AuthnRequest with module: {}", processor.getClass().getSimpleName()); + processor.process(request, pendingReq, authReq, spSSODescriptor); + + } + } + + log.debug("Extended AuthnRequest validation and processing finished"); + + //write revisionslog entry + revisionsLogger.logEvent(pendingReq, PVPEventConstants.AUTHPROTOCOL_PVP_REQUEST_AUTHREQUEST, authReq.getID()); + + } + + @PostConstruct + private void verifyInitialization() { + if (pvpIDPCredentials == null) { + log.error("No SAML2 credentialProvider injected!"); + throw new RuntimeException("No SAML2 credentialProvider injected!"); + + } + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/AuthenticationAction.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/AuthenticationAction.java index cbbed659..f9d7767f 100644 --- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/AuthenticationAction.java +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/AuthenticationAction.java @@ -1,29 +1,22 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 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: + * Licensed under the EUPL, Version 1.2 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: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * 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. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * 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.egiz.eaaf.modules.pvp2.idp.impl; import javax.annotation.PostConstruct; @@ -31,14 +24,12 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.joda.time.DateTime; -import org.opensaml.common.xml.SAMLConstants; -import org.opensaml.saml2.core.Assertion; -import org.opensaml.saml2.core.AuthnRequest; -import org.opensaml.saml2.core.Response; -import org.opensaml.saml2.metadata.AssertionConsumerService; -import org.opensaml.saml2.metadata.EntityDescriptor; -import org.opensaml.ws.message.encoder.MessageEncodingException; -import org.opensaml.xml.security.SecurityException; +import org.opensaml.saml.common.xml.SAMLConstants; +import org.opensaml.saml.saml2.core.Assertion; +import org.opensaml.saml.saml2.core.AuthnRequest; +import org.opensaml.saml.saml2.core.Response; +import org.opensaml.saml.saml2.metadata.AssertionConsumerService; +import org.opensaml.saml.saml2.metadata.EntityDescriptor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -49,137 +40,139 @@ import at.gv.egiz.eaaf.core.api.IRequest; import at.gv.egiz.eaaf.core.api.idp.IAction; import at.gv.egiz.eaaf.core.api.idp.IAuthData; import at.gv.egiz.eaaf.core.api.idp.IConfiguration; -import at.gv.egiz.eaaf.core.api.idp.slo.SLOInformationInterface; +import at.gv.egiz.eaaf.core.api.idp.slo.SloInformationInterface; import at.gv.egiz.eaaf.core.api.logging.IRevisionLogger; -import at.gv.egiz.eaaf.core.exceptions.EAAFException; -import at.gv.egiz.eaaf.core.impl.data.SLOInformationImpl; -import at.gv.egiz.eaaf.modules.pvp2.api.IPVP2BasicConfiguration; +import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.core.impl.data.SloInformationImpl; +import at.gv.egiz.eaaf.modules.pvp2.api.IPvp2BasicConfiguration; import at.gv.egiz.eaaf.modules.pvp2.api.binding.IEncoder; -import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPVPMetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.api.utils.IPvp2CredentialProvider; import at.gv.egiz.eaaf.modules.pvp2.exception.BindingNotSupportedException; import at.gv.egiz.eaaf.modules.pvp2.idp.exception.ResponderErrorException; import at.gv.egiz.eaaf.modules.pvp2.idp.impl.builder.AuthResponseBuilder; -import at.gv.egiz.eaaf.modules.pvp2.idp.impl.builder.PVP2AssertionBuilder; +import at.gv.egiz.eaaf.modules.pvp2.idp.impl.builder.Pvp2AssertionBuilder; import at.gv.egiz.eaaf.modules.pvp2.impl.binding.PostBinding; import at.gv.egiz.eaaf.modules.pvp2.impl.binding.RedirectBinding; -import at.gv.egiz.eaaf.modules.pvp2.impl.message.PVPSProfileRequest; -import at.gv.egiz.eaaf.modules.pvp2.impl.utils.AbstractCredentialProvider; -import at.gv.egiz.eaaf.modules.pvp2.impl.utils.SAML2Utils; +import at.gv.egiz.eaaf.modules.pvp2.impl.message.PvpSProfileRequest; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils; @Service("PVPAuthenticationRequestAction") public class AuthenticationAction implements IAction { - private static final Logger log = LoggerFactory.getLogger(AuthenticationAction.class); - - private static final String CONFIG_PROPERTY_PVP2_ENABLE_ENCRYPTION = "protocols.pvp2.assertion.encryption.active"; - - @Autowired(required=true) private IPVPMetadataProvider metadataProvider; - @Autowired(required=true) ApplicationContext springContext; - @Autowired(required=true) IConfiguration authConfig; - @Autowired(required=true) PVP2AssertionBuilder assertionBuilder; - @Autowired(required=true) IPVP2BasicConfiguration pvpBasicConfiguration; - @Autowired(required=true) IRevisionLogger revisionsLogger; - - private AbstractCredentialProvider pvpIDPCredentials; - - /** - * Sets a specific credential provider for PVP S-Profile IDP component. - * @param pvpIDPCredentials credential provider - */ - public void setPvpIDPCredentials(AbstractCredentialProvider pvpIDPCredentials) { - this.pvpIDPCredentials = pvpIDPCredentials; - - } - - @Override - public SLOInformationInterface processRequest(IRequest req, HttpServletRequest httpReq, - HttpServletResponse httpResp, IAuthData authData) throws ResponderErrorException { - final PVPSProfilePendingRequest pvpRequest = (PVPSProfilePendingRequest) req; - try { - //get basic information - final PVPSProfileRequest moaRequest = (PVPSProfileRequest) pvpRequest.getRequest(); - final AuthnRequest authnRequest = (AuthnRequest) moaRequest.getSamlRequest(); - final EntityDescriptor peerEntity = moaRequest.getEntityMetadata(metadataProvider); - - final AssertionConsumerService consumerService = - SAML2Utils.createSAMLObject(AssertionConsumerService.class); - consumerService.setBinding(pvpRequest.getBinding()); - consumerService.setLocation(pvpRequest.getConsumerURL()); - - final DateTime date = new DateTime(); - final SLOInformationImpl sloInformation = new SLOInformationImpl(); - final String issuerEntityID = pvpBasicConfiguration.getIDPEntityId(pvpRequest.getAuthURL()); - - //build Assertion - final Assertion assertion = assertionBuilder.buildAssertion(issuerEntityID, pvpRequest, authnRequest, authData, - peerEntity, date, consumerService, sloInformation); - - final Response authResponse = AuthResponseBuilder.buildResponse( - metadataProvider, issuerEntityID, authnRequest, - date, assertion, authConfig.getBasicConfigurationBoolean( - CONFIG_PROPERTY_PVP2_ENABLE_ENCRYPTION, true)); - - IEncoder binding = null; - - if (consumerService.getBinding().equals( - SAMLConstants.SAML2_REDIRECT_BINDING_URI)) { - binding = springContext.getBean("PVPRedirectBinding", RedirectBinding.class); - - } else if (consumerService.getBinding().equals( - SAMLConstants.SAML2_POST_BINDING_URI)) { - binding = springContext.getBean("PVPPOSTBinding", PostBinding.class); - - } - - if (binding == null) { - throw new BindingNotSupportedException(consumerService.getBinding()); - } - - binding.encodeRespone(httpReq, httpResp, authResponse, - consumerService.getLocation(), moaRequest.getRelayState(), - pvpIDPCredentials.getIDPAssertionSigningCredential(), req); - - revisionsLogger.logEvent(req, 3105, authResponse.getID()); - - //set protocol type - sloInformation.setProtocolType(req.requestedModule()); - sloInformation.setSpEntityID(req.getServiceProviderConfiguration().getUniqueIdentifier()); - return sloInformation; - - } catch (MessageEncodingException | SecurityException e) { - log.warn("Message Encoding exception", e); - throw new ResponderErrorException("pvp2.01", null, e); - - } catch (final EAAFException e) { - log.info("Response generation error: Msg: ", e.getMessage()); - throw new ResponderErrorException(e.getErrorId(), e.getParams(), e); - - } catch (final Exception e) { - log.warn("Response generation error", e); - throw new ResponderErrorException("pvp2.01", null, e); - - } - - } - - @Override - public boolean needAuthentication(IRequest req, HttpServletRequest httpReq, - HttpServletResponse httpResp) { - return true; - } - - @Override - public String getDefaultActionName() { - return "PVPAuthenticationRequestAction"; - - } - - @PostConstruct - private void verifyInitialization() { - if (pvpIDPCredentials == null) { - log.error("No SAML2 credentialProvider injected!"); - throw new RuntimeException("No SAML2 credentialProvider injected!"); - - } - } + private static final Logger log = LoggerFactory.getLogger(AuthenticationAction.class); + + @Autowired(required = true) + private IPvp2MetadataProvider metadataProvider; + @Autowired(required = true) + ApplicationContext springContext; + @Autowired(required = true) + IConfiguration authConfig; + @Autowired(required = true) + Pvp2AssertionBuilder assertionBuilder; + @Autowired(required = true) + IPvp2BasicConfiguration pvpBasicConfiguration; + @Autowired(required = true) + IRevisionLogger revisionsLogger; + + private IPvp2CredentialProvider pvpIdpCredentials; + + /** + * Sets a specific credential provider for PVP S-Profile IDP component. + * + * @param pvpIdpCredentials credential provider + */ + public void setPvpIdpCredentials(final IPvp2CredentialProvider pvpIdpCredentials) { + this.pvpIdpCredentials = pvpIdpCredentials; + + } + + @Override + public SloInformationInterface processRequest(final IRequest req, + final HttpServletRequest httpReq, final HttpServletResponse httpResp, + final IAuthData authData) throws ResponderErrorException { + final PvpSProfilePendingRequest pvpRequest = (PvpSProfilePendingRequest) req; + try { + // get basic information + final PvpSProfileRequest moaRequest = (PvpSProfileRequest) pvpRequest.getRequest(); + final AuthnRequest authnRequest = (AuthnRequest) moaRequest.getSamlRequest(); + final EntityDescriptor peerEntity = moaRequest.getEntityMetadata(metadataProvider); + + final AssertionConsumerService consumerService = + Saml2Utils.createSamlObject(AssertionConsumerService.class); + consumerService.setBinding(pvpRequest.getBinding()); + consumerService.setLocation(pvpRequest.getConsumerUrl()); + + final DateTime date = new DateTime(); + final SloInformationImpl sloInformation = new SloInformationImpl(); + final String issuerEntityID = pvpBasicConfiguration.getIdpEntityId(pvpRequest.getAuthUrl()); + + // build Assertion + final Assertion assertion = assertionBuilder.buildAssertion(issuerEntityID, pvpRequest, + authnRequest, authData, peerEntity, date, consumerService, sloInformation); + + final Response authResponse = AuthResponseBuilder.buildResponse(metadataProvider, + issuerEntityID, authnRequest, date, assertion, + authConfig); + + IEncoder binding = null; + + if (consumerService.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI)) { + binding = springContext.getBean("PvpRedirectBinding", RedirectBinding.class); + + } else if (consumerService.getBinding().equals(SAMLConstants.SAML2_POST_BINDING_URI)) { + binding = springContext.getBean("PvpPostBinding", PostBinding.class); + + } + + if (binding == null) { + throw new BindingNotSupportedException(consumerService.getBinding()); + } + + binding.encodeResponse(httpReq, httpResp, authResponse, consumerService.getLocation(), + moaRequest.getRelayState(), pvpIdpCredentials.getMessageSigningCredential(), req); + + revisionsLogger.logEvent(req, 3105, authResponse.getID()); + + // set protocol type + sloInformation.setProtocolType(req.requestedModule()); + sloInformation.setSpEntityID(req.getServiceProviderConfiguration().getUniqueIdentifier()); + return sloInformation; + + } catch (final SecurityException e) { + log.warn("Message Encoding exception", e); + throw new ResponderErrorException("pvp2.01", null, e); + + } catch (final EaafException e) { + log.info("Response generation error: Msg: ", e.getMessage()); + throw new ResponderErrorException(e.getErrorId(), e.getParams(), e); + + } catch (final Exception e) { + log.warn("Response generation error", e); + throw new ResponderErrorException("pvp2.01", null, e); + + } + + } + + @Override + public boolean needAuthentication(final IRequest req, final HttpServletRequest httpReq, + final HttpServletResponse httpResp) { + return true; + } + + @Override + public String getDefaultActionName() { + return "PVPAuthenticationRequestAction"; + + } + + @PostConstruct + private void verifyInitialization() { + if (pvpIdpCredentials == null) { + log.error("No SAML2 credentialProvider injected!"); + throw new RuntimeException("No SAML2 credentialProvider injected!"); + + } + } } diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/MetadataAction.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/MetadataAction.java index 6b957522..0b344ba3 100644 --- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/MetadataAction.java +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/MetadataAction.java @@ -1,123 +1,120 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 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: + * Licensed under the EUPL, Version 1.2 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: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * 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. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * 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.egiz.eaaf.modules.pvp2.idp.impl; import javax.annotation.PostConstruct; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import at.gv.egiz.eaaf.core.api.IRequest; +import at.gv.egiz.eaaf.core.api.idp.IAction; +import at.gv.egiz.eaaf.core.api.idp.IAuthData; +import at.gv.egiz.eaaf.core.api.idp.slo.SloInformationInterface; +import at.gv.egiz.eaaf.core.api.logging.IRevisionLogger; +import at.gv.egiz.eaaf.modules.pvp2.PvpEventConstants; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvpMetadataBuilderConfiguration; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvpMetadataConfigurationFactory; +import at.gv.egiz.eaaf.modules.pvp2.api.utils.IPvp2CredentialProvider; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2MetadataException; +import at.gv.egiz.eaaf.modules.pvp2.impl.builder.PvpMetadataBuilder; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.stereotype.Service; -import at.gv.egiz.eaaf.core.api.IRequest; -import at.gv.egiz.eaaf.core.api.idp.IAction; -import at.gv.egiz.eaaf.core.api.idp.IAuthData; -import at.gv.egiz.eaaf.core.api.idp.slo.SLOInformationInterface; -import at.gv.egiz.eaaf.core.api.logging.IRevisionLogger; -import at.gv.egiz.eaaf.modules.pvp2.PVPEventConstants; -import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPVPMetadataBuilderConfiguration; -import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPVPMetadataConfigurationFactory; -import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2MetadataException; -import at.gv.egiz.eaaf.modules.pvp2.impl.builder.PVPMetadataBuilder; -import at.gv.egiz.eaaf.modules.pvp2.impl.utils.AbstractCredentialProvider; - @Service("pvpMetadataService") public class MetadataAction implements IAction { - private static final Logger log = LoggerFactory.getLogger(MetadataAction.class); - - @Autowired private IRevisionLogger revisionsLogger; - @Autowired private PVPMetadataBuilder metadatabuilder; - @Autowired private IPVPMetadataConfigurationFactory configFactory; - - private AbstractCredentialProvider pvpIDPCredentials; - - /** - * Sets a specific credential provider for PVP S-Profile IDP component. - * @param pvpIDPCredentials credential provider - */ - public void setPvpIDPCredentials(AbstractCredentialProvider pvpIDPCredentials) { - this.pvpIDPCredentials = pvpIDPCredentials; - - } - - public SLOInformationInterface processRequest(IRequest req, HttpServletRequest httpReq, - HttpServletResponse httpResp, IAuthData authData) throws PVP2MetadataException { - try { - revisionsLogger.logEvent(req, PVPEventConstants.AUTHPROTOCOL_PVP_METADATA); - - //build metadata - IPVPMetadataBuilderConfiguration metadataConfig = - configFactory.generateMetadataBuilderConfiguration( - req.getAuthURLWithOutSlash(), - pvpIDPCredentials); - - ; - - String metadataXML = metadatabuilder.buildPVPMetadata(metadataConfig); - log.debug("METADATA: " + metadataXML); - - byte[] content = metadataXML.getBytes("UTF-8"); - httpResp.setStatus(HttpServletResponse.SC_OK); - httpResp.setContentLength(content.length); - httpResp.setContentType(MediaType.APPLICATION_XML_VALUE); - httpResp.getOutputStream().write(content); - return null; - - } catch (Exception e) { - log.error("Failed to generate metadata", e); - throw new PVP2MetadataException("pvp2.27", null); - } - } - - public boolean needAuthentication(IRequest req, HttpServletRequest httpReq, - HttpServletResponse httpResp) { - return false; - } - - /* (non-Javadoc) - * @see at.gv.egovernment.moa.id.moduls.IAction#getDefaultActionName() - */ - @Override - public String getDefaultActionName() { - return "IDP - PVP Metadata action"; - } - - @PostConstruct - private void verifyInitialization() { - if (pvpIDPCredentials == null) { - log.error("No SAML2 credentialProvider injected!"); - throw new RuntimeException("No SAML2 credentialProvider injected!"); - - } - } - + private static final Logger log = LoggerFactory.getLogger(MetadataAction.class); + + @Autowired + private IRevisionLogger revisionsLogger; + @Autowired + private PvpMetadataBuilder metadatabuilder; + @Autowired + private IPvpMetadataConfigurationFactory configFactory; + + private IPvp2CredentialProvider pvpIdpCredentials; + + /** + * Sets a specific credential provider for PVP S-Profile IDP component. + * + * @param pvpIdpCredentials credential provider + */ + public void setPvpIdpCredentials(final IPvp2CredentialProvider pvpIdpCredentials) { + this.pvpIdpCredentials = pvpIdpCredentials; + + } + + @Override + public SloInformationInterface processRequest(final IRequest req, + final HttpServletRequest httpReq, final HttpServletResponse httpResp, + final IAuthData authData) throws Pvp2MetadataException { + try { + revisionsLogger.logEvent(req, PvpEventConstants.AUTHPROTOCOL_PVP_METADATA); + + // build metadata + final IPvpMetadataBuilderConfiguration metadataConfig = configFactory + .generateMetadataBuilderConfiguration(req.getAuthUrlWithOutSlash(), pvpIdpCredentials); + + final String metadataXml = metadatabuilder.buildPvpMetadata(metadataConfig); + log.trace("METADATA: " + metadataXml); + + final byte[] content = metadataXml.getBytes("UTF-8"); + httpResp.setStatus(HttpServletResponse.SC_OK); + httpResp.setContentLength(content.length); + httpResp.setContentType(MediaType.APPLICATION_XML_VALUE); + httpResp.getOutputStream().write(content); + return null; + + } catch (final Exception e) { + log.error("Failed to generate metadata", e); + throw new Pvp2MetadataException("pvp2.27", null); + } + } + + @Override + public boolean needAuthentication(final IRequest req, final HttpServletRequest httpReq, + final HttpServletResponse httpResp) { + return false; + } + + /* + * (non-Javadoc) + * + * @see at.gv.egovernment.moa.id.moduls.IAction#getDefaultActionName() + */ + @Override + public String getDefaultActionName() { + return "IDP - PVP Metadata action"; + } + + @PostConstruct + private void verifyInitialization() { + if (pvpIdpCredentials == null) { + log.error("No SAML2 credentialProvider injected!"); + throw new RuntimeException("No SAML2 credentialProvider injected!"); + + } + } } diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/PVPSProfilePendingRequest.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/PVPSProfilePendingRequest.java deleted file mode 100644 index 7f086ff6..00000000 --- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/PVPSProfilePendingRequest.java +++ /dev/null @@ -1,69 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.idp.impl; - -import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; - -import at.gv.egiz.eaaf.core.impl.idp.controller.protocols.RequestImpl; -import at.gv.egiz.eaaf.modules.pvp2.impl.message.InboundMessage; - -@Component("PVPSProfilePendingRequest") -@Scope(value = BeanDefinition.SCOPE_PROTOTYPE) -public class PVPSProfilePendingRequest extends RequestImpl { - private static final long serialVersionUID = 4889919265919638188L; - - InboundMessage request; - String binding; - String consumerURL; - - public InboundMessage getRequest() { - return request; - } - - public void setRequest(InboundMessage request) { - this.request = request; - } - - public String getBinding() { - return binding; - } - - public void setBinding(String binding) { - this.binding = binding; - } - - public String getConsumerURL() { - return consumerURL; - } - - public void setConsumerURL(String consumerURL) { - this.consumerURL = consumerURL; - - } -} diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/PvpSProfilePendingRequest.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/PvpSProfilePendingRequest.java new file mode 100644 index 00000000..26e04881 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/PvpSProfilePendingRequest.java @@ -0,0 +1,62 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.idp.impl; + +import at.gv.egiz.eaaf.core.impl.idp.controller.protocols.RequestImpl; +import at.gv.egiz.eaaf.modules.pvp2.impl.message.InboundMessage; + +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +@Component("PVPSProfilePendingRequest") +@Scope(value = BeanDefinition.SCOPE_PROTOTYPE) +public class PvpSProfilePendingRequest extends RequestImpl { + private static final long serialVersionUID = 4889919265919638188L; + + InboundMessage request; + String binding; + String consumerUrl; + + public InboundMessage getRequest() { + return request; + } + + public void setRequest(final InboundMessage request) { + this.request = request; + } + + public String getBinding() { + return binding; + } + + public void setBinding(final String binding) { + this.binding = binding; + } + + public String getConsumerUrl() { + return consumerUrl; + } + + public void setConsumerUrl(final String consumerUrl) { + this.consumerUrl = consumerUrl; + + } +} diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/builder/AuthResponseBuilder.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/builder/AuthResponseBuilder.java index 07423c19..482a2a09 100644 --- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/builder/AuthResponseBuilder.java +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/builder/AuthResponseBuilder.java @@ -1,153 +1,215 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 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: + * Licensed under the EUPL, Version 1.2 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: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * 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. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * 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.egiz.eaaf.modules.pvp2.idp.impl.builder; import java.util.ArrayList; import java.util.List; +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.modules.pvp2.PvpConstants; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlSigningException; +import at.gv.egiz.eaaf.modules.pvp2.idp.exception.InvalidAssertionEncryptionException; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils; + import org.joda.time.DateTime; -import org.opensaml.Configuration; -import org.opensaml.common.xml.SAMLConstants; -import org.opensaml.saml2.core.Assertion; -import org.opensaml.saml2.core.EncryptedAssertion; -import org.opensaml.saml2.core.Issuer; -import org.opensaml.saml2.core.NameID; -import org.opensaml.saml2.core.RequestAbstractType; -import org.opensaml.saml2.core.Response; -import org.opensaml.saml2.encryption.Encrypter; -import org.opensaml.saml2.encryption.Encrypter.KeyPlacement; -import org.opensaml.saml2.metadata.SPSSODescriptor; -import org.opensaml.saml2.metadata.provider.MetadataProvider; -import org.opensaml.security.MetadataCredentialResolver; -import org.opensaml.security.MetadataCriteria; -import org.opensaml.xml.encryption.EncryptionException; -import org.opensaml.xml.encryption.EncryptionParameters; -import org.opensaml.xml.encryption.KeyEncryptionParameters; -import org.opensaml.xml.security.CriteriaSet; -import org.opensaml.xml.security.SecurityException; -import org.opensaml.xml.security.credential.UsageType; -import org.opensaml.xml.security.criteria.EntityIDCriteria; -import org.opensaml.xml.security.criteria.UsageCriteria; -import org.opensaml.xml.security.keyinfo.KeyInfoGeneratorFactory; -import org.opensaml.xml.security.x509.X509Credential; +import org.opensaml.core.criterion.EntityIdCriterion; +import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport; +import org.opensaml.core.xml.io.MarshallingException; +import org.opensaml.core.xml.io.UnmarshallingException; +import org.opensaml.core.xml.util.XMLObjectSupport; +import org.opensaml.saml.common.xml.SAMLConstants; +import org.opensaml.saml.criterion.EntityRoleCriterion; +import org.opensaml.saml.criterion.ProtocolCriterion; +import org.opensaml.saml.metadata.resolver.impl.PredicateRoleDescriptorResolver; +import org.opensaml.saml.saml2.core.Assertion; +import org.opensaml.saml.saml2.core.EncryptedAssertion; +import org.opensaml.saml.saml2.core.Issuer; +import org.opensaml.saml.saml2.core.NameIDType; +import org.opensaml.saml.saml2.core.RequestAbstractType; +import org.opensaml.saml.saml2.core.Response; +import org.opensaml.saml.saml2.encryption.Encrypter; +import org.opensaml.saml.saml2.encryption.Encrypter.KeyPlacement; +import org.opensaml.saml.saml2.metadata.SPSSODescriptor; +import org.opensaml.saml.security.impl.MetadataCredentialResolver; +import org.opensaml.security.credential.UsageType; +import org.opensaml.security.criteria.UsageCriterion; +import org.opensaml.security.x509.X509Credential; +import org.opensaml.xmlsec.SecurityConfigurationSupport; +import org.opensaml.xmlsec.encryption.support.DataEncryptionParameters; +import org.opensaml.xmlsec.encryption.support.EncryptionException; +import org.opensaml.xmlsec.encryption.support.KeyEncryptionParameters; +import org.opensaml.xmlsec.keyinfo.KeyInfoCredentialResolver; +import org.opensaml.xmlsec.keyinfo.KeyInfoGeneratorFactory; +import org.opensaml.xmlsec.keyinfo.impl.BasicProviderKeyInfoCredentialResolver; +import org.opensaml.xmlsec.keyinfo.impl.KeyInfoProvider; +import org.opensaml.xmlsec.keyinfo.impl.provider.DSAKeyValueProvider; +import org.opensaml.xmlsec.keyinfo.impl.provider.InlineX509DataProvider; +import org.opensaml.xmlsec.keyinfo.impl.provider.RSAKeyValueProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.w3c.dom.Element; -import at.gv.egiz.eaaf.modules.pvp2.PVPConstants; -import at.gv.egiz.eaaf.modules.pvp2.idp.exception.InvalidAssertionEncryptionException; -import at.gv.egiz.eaaf.modules.pvp2.impl.utils.SAML2Utils; +import net.shibboleth.utilities.java.support.component.ComponentInitializationException; +import net.shibboleth.utilities.java.support.resolver.CriteriaSet; +import net.shibboleth.utilities.java.support.resolver.ResolverException; /** + * Authentication response builder. + * * @author tlenz * */ public class AuthResponseBuilder { - private static final Logger log = LoggerFactory.getLogger(AuthResponseBuilder.class); - - public static Response buildResponse(MetadataProvider metadataProvider, String issuerEntityID, RequestAbstractType req, DateTime date, Assertion assertion, boolean enableEncryption) throws InvalidAssertionEncryptionException { - Response authResponse = SAML2Utils.createSAMLObject(Response.class); - - Issuer nissuer = SAML2Utils.createSAMLObject(Issuer.class); - - nissuer.setValue(issuerEntityID); - nissuer.setFormat(NameID.ENTITY); - authResponse.setIssuer(nissuer); - authResponse.setInResponseTo(req.getID()); - - //set responseID - String remoteSessionID = SAML2Utils.getSecureIdentifier(); - authResponse.setID(remoteSessionID); - - - //SAML2 response required IssueInstant - authResponse.setIssueInstant(date); - - authResponse.setStatus(SAML2Utils.getSuccessStatus()); - - //check, if metadata includes an encryption key - MetadataCredentialResolver mdCredResolver = - new MetadataCredentialResolver(metadataProvider); - - CriteriaSet criteriaSet = new CriteriaSet(); - criteriaSet.add( new EntityIDCriteria(req.getIssuer().getValue()) ); - criteriaSet.add( new MetadataCriteria(SPSSODescriptor.DEFAULT_ELEMENT_NAME, SAMLConstants.SAML20P_NS) ); - criteriaSet.add( new UsageCriteria(UsageType.ENCRYPTION) ); - - X509Credential encryptionCredentials = null; - try { - encryptionCredentials = (X509Credential) mdCredResolver.resolveSingle(criteriaSet); - - } catch (SecurityException e2) { - log.warn("Can not extract the Assertion Encryption-Key from metadata", e2); - throw new InvalidAssertionEncryptionException(); - - } - - if (encryptionCredentials != null && enableEncryption) { - //encrypt SAML2 assertion - - try { - - EncryptionParameters dataEncParams = new EncryptionParameters(); - dataEncParams.setAlgorithm(PVPConstants.DEFAULT_SYM_ENCRYPTION_METHODE); - - List<KeyEncryptionParameters> keyEncParamList = new ArrayList<KeyEncryptionParameters>(); - KeyEncryptionParameters keyEncParam = new KeyEncryptionParameters(); - - keyEncParam.setEncryptionCredential(encryptionCredentials); - keyEncParam.setAlgorithm(PVPConstants.DEFAULT_ASYM_ENCRYPTION_METHODE); - KeyInfoGeneratorFactory kigf = Configuration.getGlobalSecurityConfiguration() - .getKeyInfoGeneratorManager().getDefaultManager() - .getFactory(encryptionCredentials); - keyEncParam.setKeyInfoGenerator(kigf.newInstance()); - keyEncParamList.add(keyEncParam); - - Encrypter samlEncrypter = new Encrypter(dataEncParams, keyEncParamList); - //samlEncrypter.setKeyPlacement(KeyPlacement.INLINE); - samlEncrypter.setKeyPlacement(KeyPlacement.PEER); - - EncryptedAssertion encryptAssertion = null; - - encryptAssertion = samlEncrypter.encrypt(assertion); - - authResponse.getEncryptedAssertions().add(encryptAssertion); - - } catch (EncryptionException e1) { - log.warn("Can not encrypt the PVP2 assertion", e1); - throw new InvalidAssertionEncryptionException(); - - } - - } else { - authResponse.getAssertions().add(assertion); - - } - - return authResponse; - } + private static final Logger log = LoggerFactory.getLogger(AuthResponseBuilder.class); + + /** + * Build PVP2 S-Profile authentication response. + * + * @param metadataProvider Service-Provider metadata + * @param issuerEntityID IDP entityId + * @param req current pending request + * @param date Timestamp + * @param assertion PVP2 S-Profil Assertion + * @param authConfig {@link IConfiguration} + * @return PVP2 S-Profile authentication response + * @throws InvalidAssertionEncryptionException In case of an error + */ + public static Response buildResponse(final IPvp2MetadataProvider metadataProvider, + final String issuerEntityID, final RequestAbstractType req, final DateTime date, + final Assertion assertion, IConfiguration authConfig) + throws InvalidAssertionEncryptionException { + final Response authResponse = Saml2Utils.createSamlObject(Response.class); + + final Issuer nissuer = Saml2Utils.createSamlObject(Issuer.class); + + nissuer.setValue(issuerEntityID); + nissuer.setFormat(NameIDType.ENTITY); + authResponse.setIssuer(nissuer); + authResponse.setInResponseTo(req.getID()); + + // set responseID + final String remoteSessionID = Saml2Utils.getSecureIdentifier(); + authResponse.setID(remoteSessionID); + + // SAML2 response required IssueInstant + authResponse.setIssueInstant(date); + + authResponse.setStatus(Saml2Utils.getSuccessStatus()); + + // check, if metadata includes an encryption key + final X509Credential encryptionCredentials = resolveEncryptionCredential(req, metadataProvider); + + if (encryptionCredentials != null + && authConfig.getBasicConfigurationBoolean( + PvpConstants.CONFIG_PROPERTY_PVP2_ENABLE_ENCRYPTION, true)) { + authResponse.getEncryptedAssertions().add( + doEncryption(assertion, encryptionCredentials, authConfig)); + + } else { + authResponse.getAssertions().add(assertion); + + } + + return authResponse; + } + + private static EncryptedAssertion doEncryption(Assertion assertion, + X509Credential encryptionCredentials, IConfiguration authConfig) + throws InvalidAssertionEncryptionException { + try { + final String keyEncAlg = Saml2Utils.getKeyOperationAlgorithmFromCredential( + encryptionCredentials, + authConfig.getBasicConfiguration( + PvpConstants.CONFIG_PROP_SEC_ENCRYPTION_KEY_RSA_ALG, + PvpConstants.DEFAULT_ASYM_ENCRYPTION_METHODE_RSA), + authConfig.getBasicConfiguration( + PvpConstants.CONFIG_PROP_SEC_ENCRYPTION_KEY_EC_ALG, + PvpConstants.DEFAULT_ASYM_ENCRYPTION_METHODE_EC)); + + final DataEncryptionParameters dataEncParams = new DataEncryptionParameters(); + dataEncParams.setAlgorithm(authConfig.getBasicConfiguration( + PvpConstants.CONFIG_PROP_SEC_ENCRYPTION_DATA, PvpConstants.DEFAULT_SYM_ENCRYPTION_METHODE)); + + final List<KeyEncryptionParameters> keyEncParamList = new ArrayList<>(); + final KeyEncryptionParameters keyEncParam = new KeyEncryptionParameters(); + keyEncParam.setEncryptionCredential(encryptionCredentials); + keyEncParam.setAlgorithm(keyEncAlg); + + final KeyInfoGeneratorFactory kigf = + SecurityConfigurationSupport.getGlobalEncryptionConfiguration() + .getKeyTransportKeyInfoGeneratorManager().getDefaultManager().getFactory(encryptionCredentials); + keyEncParam.setKeyInfoGenerator(kigf.newInstance()); + keyEncParamList.add(keyEncParam); + + final Encrypter samlEncrypter = new Encrypter(dataEncParams, keyEncParamList); + samlEncrypter.setKeyPlacement(KeyPlacement.PEER); + + final Element assertionElement = XMLObjectProviderRegistrySupport.getMarshallerFactory() + .getMarshaller(assertion).marshall(assertion); + assertionElement.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:xs", "http://www.w3.org/2001/XMLSchema"); + + return samlEncrypter.encrypt((Assertion) + XMLObjectSupport.getUnmarshaller(assertionElement).unmarshall(assertionElement)); + + } catch (final EncryptionException | SamlSigningException | MarshallingException | UnmarshallingException e1) { + log.warn("Can not encrypt the PVP2 assertion", e1); + throw new InvalidAssertionEncryptionException(); + + } + + } + + private static X509Credential resolveEncryptionCredential(RequestAbstractType req, + IPvp2MetadataProvider metadataProvider) throws InvalidAssertionEncryptionException { + try { + final List<KeyInfoProvider> keyInfoProvider = new ArrayList<>(); + keyInfoProvider.add(new DSAKeyValueProvider()); + keyInfoProvider.add(new RSAKeyValueProvider()); + keyInfoProvider.add(new InlineX509DataProvider()); + final KeyInfoCredentialResolver keyInfoCredentialResolver = new BasicProviderKeyInfoCredentialResolver( + keyInfoProvider); + + final PredicateRoleDescriptorResolver roleDescriptorResolver = new PredicateRoleDescriptorResolver( + metadataProvider); + roleDescriptorResolver.setRequireValidMetadata(true); + roleDescriptorResolver.initialize(); + + final MetadataCredentialResolver mdCredResolver = new MetadataCredentialResolver(); + mdCredResolver.setRoleDescriptorResolver(roleDescriptorResolver); + mdCredResolver.setKeyInfoCredentialResolver(keyInfoCredentialResolver); + mdCredResolver.initialize(); + + final CriteriaSet criteriaSet = new CriteriaSet(); + criteriaSet.add(new EntityIdCriterion(req.getIssuer().getValue())); + criteriaSet.add(new ProtocolCriterion(SAMLConstants.SAML20P_NS)); + criteriaSet.add(new EntityRoleCriterion(SPSSODescriptor.DEFAULT_ELEMENT_NAME)); + criteriaSet.add(new UsageCriterion(UsageType.ENCRYPTION)); + + return (X509Credential) mdCredResolver.resolveSingle(criteriaSet); + + } catch (final SecurityException | ComponentInitializationException | ResolverException e2) { + log.warn("Can not extract the Assertion Encryption-Key from metadata", e2); + throw new InvalidAssertionEncryptionException(); + + } + } } diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/builder/PVP2AssertionBuilder.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/builder/PVP2AssertionBuilder.java deleted file mode 100644 index 2ccc2c9e..00000000 --- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/builder/PVP2AssertionBuilder.java +++ /dev/null @@ -1,459 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.idp.impl.builder; - -import java.security.MessageDigest; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import org.apache.commons.lang3.StringUtils; -import org.joda.time.DateTime; -import org.opensaml.common.xml.SAMLConstants; -import org.opensaml.saml2.core.Assertion; -import org.opensaml.saml2.core.Attribute; -import org.opensaml.saml2.core.AttributeQuery; -import org.opensaml.saml2.core.AttributeStatement; -import org.opensaml.saml2.core.Audience; -import org.opensaml.saml2.core.AudienceRestriction; -import org.opensaml.saml2.core.AuthnContext; -import org.opensaml.saml2.core.AuthnContextClassRef; -import org.opensaml.saml2.core.AuthnRequest; -import org.opensaml.saml2.core.AuthnStatement; -import org.opensaml.saml2.core.Conditions; -import org.opensaml.saml2.core.Issuer; -import org.opensaml.saml2.core.NameID; -import org.opensaml.saml2.core.RequestedAuthnContext; -import org.opensaml.saml2.core.Subject; -import org.opensaml.saml2.core.SubjectConfirmation; -import org.opensaml.saml2.core.SubjectConfirmationData; -import org.opensaml.saml2.core.impl.AuthnRequestImpl; -import org.opensaml.saml2.metadata.AssertionConsumerService; -import org.opensaml.saml2.metadata.AttributeConsumingService; -import org.opensaml.saml2.metadata.EntityDescriptor; -import org.opensaml.saml2.metadata.NameIDFormat; -import org.opensaml.saml2.metadata.RequestedAttribute; -import org.opensaml.saml2.metadata.SPSSODescriptor; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.springframework.util.Base64Utils; - -import at.gv.egiz.eaaf.core.api.data.EAAFConstants; -import at.gv.egiz.eaaf.core.api.data.ILoALevelMapper; -import at.gv.egiz.eaaf.core.api.idp.IAuthData; -import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration; -import at.gv.egiz.eaaf.core.api.idp.slo.SLOInformationInterface; -import at.gv.egiz.eaaf.core.exceptions.UnavailableAttributeException; -import at.gv.egiz.eaaf.core.impl.data.Pair; -import at.gv.egiz.eaaf.core.impl.idp.controller.protocols.RequestImpl; -import at.gv.egiz.eaaf.core.impl.utils.Random; -import at.gv.egiz.eaaf.modules.pvp2.PVPConstants; -import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception; -import at.gv.egiz.eaaf.modules.pvp2.exception.QAANotSupportedException; -import at.gv.egiz.eaaf.modules.pvp2.idp.api.builder.ISubjectNameIdGenerator; -import at.gv.egiz.eaaf.modules.pvp2.idp.exception.ResponderErrorException; -import at.gv.egiz.eaaf.modules.pvp2.idp.exception.UnprovideableAttributeException; -import at.gv.egiz.eaaf.modules.pvp2.idp.impl.PVPSProfilePendingRequest; -import at.gv.egiz.eaaf.modules.pvp2.impl.builder.PVPAttributeBuilder; -import at.gv.egiz.eaaf.modules.pvp2.impl.utils.QAALevelVerifier; -import at.gv.egiz.eaaf.modules.pvp2.impl.utils.SAML2Utils; - -@Service("PVP2AssertionBuilder") -public class PVP2AssertionBuilder implements PVPConstants { - - private static final Logger log = LoggerFactory.getLogger(PVP2AssertionBuilder.class); - @Autowired private ILoALevelMapper loaLevelMapper; - @Autowired private ISubjectNameIdGenerator subjectNameIdGenerator; - - - /** - * Build a PVP assertion as response for a SAML2 AttributeQuery request - * - * @param issuerEntityID EnitiyID, which should be used for this IDP response - * @param attrQuery AttributeQuery request from Service-Provider - * @param attrList List of PVP response attributes - * @param now Current time - * @param validTo ValidTo time of the assertion - * @param qaaLevel QAA level of the authentication - * @param sessionIndex SAML2 SessionIndex, which should be included * - * @return PVP 2.1 Assertion - * @throws PVP2Exception - */ - public Assertion buildAssertion(String issuerEntityID, AttributeQuery attrQuery, - List<Attribute> attrList, DateTime now, DateTime validTo, String qaaLevel, String sessionIndex) throws PVP2Exception { - - AuthnContextClassRef authnContextClassRef = SAML2Utils.createSAMLObject(AuthnContextClassRef.class); - authnContextClassRef.setAuthnContextClassRef(qaaLevel); - - NameID subjectNameID = SAML2Utils.createSAMLObject(NameID.class); - subjectNameID.setFormat(attrQuery.getSubject().getNameID().getFormat()); - subjectNameID.setValue(attrQuery.getSubject().getNameID().getValue()); - - SubjectConfirmationData subjectConfirmationData = null; - - return buildGenericAssertion(issuerEntityID, attrQuery.getIssuer().getValue(), now, - authnContextClassRef, attrList, subjectNameID, subjectConfirmationData, sessionIndex, - validTo); - } - - - /** - * Build a PVP 2.1 assertion as response of a SAML2 AuthnRequest - * - * @param issuerEntityID EnitiyID, which should be used for this IDP response - * @param pendingReq Current processed pendingRequest DAO - * @param authnRequest Current processed PVP AuthnRequest - * @param authData AuthenticationData of the user, which is already authenticated - * @param peerEntity SAML2 EntityDescriptor of the service-provider, which receives the response - * @param date TimeStamp - * @param assertionConsumerService SAML2 endpoint of the service-provider, which should be used - * @param sloInformation Single LogOut information DAO - * @return - * @throws PVP2Exception - */ - public Assertion buildAssertion(String issuerEntityID, PVPSProfilePendingRequest pendingReq, AuthnRequest authnRequest, - IAuthData authData, EntityDescriptor peerEntity, DateTime date, - AssertionConsumerService assertionConsumerService, SLOInformationInterface sloInformation) - throws PVP2Exception { - - ISPConfiguration oaParam = pendingReq.getServiceProviderConfiguration(); - AuthnContextClassRef authnContextClassRef = SAML2Utils.createSAMLObject(AuthnContextClassRef.class); - - //check if authn. request contains LoA - RequestedAuthnContext reqAuthnContext = authnRequest.getRequestedAuthnContext(); - if (reqAuthnContext == null) { - authnContextClassRef.setAuthnContextClassRef(authData.getEIDASQAALevel()); - - } else { - //authn. request requests LoA levels. To LoA validation - List<AuthnContextClassRef> reqAuthnContextClassRefIt = reqAuthnContext.getAuthnContextClassRefs(); - - //get matching mode from authn. request - String loaMatchingMode = EAAFConstants.EIDAS_LOA_MATCHING_MINIMUM; - if (reqAuthnContext.getComparison() != null && - StringUtils.isNotEmpty(reqAuthnContext.getComparison().toString())) - loaMatchingMode = reqAuthnContext.getComparison().toString(); - - //get requested LoAs - if (reqAuthnContextClassRefIt.size() == 0) { - QAALevelVerifier.verifyQAALevel(authData.getEIDASQAALevel(), - oaParam.getRequiredLoA(), loaMatchingMode); - authnContextClassRef.setAuthnContextClassRef(authData.getEIDASQAALevel()); - - } else { - List<String> eIDASLoaFromRequest = new ArrayList<String>(); - for (AuthnContextClassRef authnClassRef : reqAuthnContextClassRefIt) { - String qaa_uri = authnClassRef.getAuthnContextClassRef(); - - if (!qaa_uri.trim().startsWith(EAAFConstants.EIDAS_LOA_PREFIX)) { - if (loaLevelMapper != null) { - log.debug("Find no eIDAS LoA in AuthnReq. Start mapping process ... " ); - eIDASLoaFromRequest.add(loaLevelMapper.mapToeIDASLoA(qaa_uri.trim())); - - } else - log.debug("AuthnRequest contains no eIDAS LoA. NO LoA mapper FOUND, ignore " - + "'" + qaa_uri.trim() + "'"); - } else - eIDASLoaFromRequest.add(qaa_uri.trim()); - - } - - //stop process if no supported LoA scheme is requested - if (eIDASLoaFromRequest.isEmpty()) { - log.info("Authn. request contains no supported LoA level. Stop authentication process ... "); - throw new QAANotSupportedException("No supported LoA in Authn. request"); - - } - - //verifiy LoAs from request to authentication LoA - QAALevelVerifier.verifyQAALevel(authData.getEIDASQAALevel(), eIDASLoaFromRequest , loaMatchingMode); - authnContextClassRef.setAuthnContextClassRef(authData.getEIDASQAALevel()); - - } - } - - - //load SPSS decriptor from service-provider metadata - SPSSODescriptor spSSODescriptor = peerEntity.getSPSSODescriptor(SAMLConstants.SAML20P_NS); - - //add Attributes to Assertion - List<Attribute> attrList = new ArrayList<Attribute>(); - if (spSSODescriptor.getAttributeConsumingServices() != null && - spSSODescriptor.getAttributeConsumingServices().size() > 0) { - - Integer aIdx = authnRequest.getAttributeConsumingServiceIndex(); - int idx = 0; - - AttributeConsumingService attributeConsumingService = null; - if (aIdx != null) { - idx = aIdx.intValue(); - attributeConsumingService = spSSODescriptor - .getAttributeConsumingServices().get(idx); - - } else { - List<AttributeConsumingService> attrConsumingServiceList = spSSODescriptor.getAttributeConsumingServices(); - for (AttributeConsumingService el : attrConsumingServiceList) { - if (el.isDefault()) - attributeConsumingService = el; - } - } - - /* - * TODO: maybe use first AttributeConsumingService if no is selected - * in request or on service is marked as default - * - */ - if (attributeConsumingService == null ) { - List<AttributeConsumingService> attrConsumingServiceList = spSSODescriptor.getAttributeConsumingServices(); - if (attrConsumingServiceList != null && !attrConsumingServiceList.isEmpty()) - attributeConsumingService = attrConsumingServiceList.get(0); - - } - - - if (attributeConsumingService != null) { - Iterator<RequestedAttribute> it = attributeConsumingService - .getRequestAttributes().iterator(); - while (it.hasNext()) { - RequestedAttribute reqAttribut = it.next(); - try { - Attribute attr = PVPAttributeBuilder.buildAttribute( - reqAttribut.getName(), oaParam, authData); - if (attr == null) { - if (reqAttribut.isRequired()) { - throw new UnprovideableAttributeException( - reqAttribut.getName()); - } - } else { - attrList.add(attr); - } - - } catch (UnavailableAttributeException e) { - log.info( - "Attribute generation for " - + reqAttribut.getFriendlyName() + " not possible."); - if (reqAttribut.isRequired()) { - throw new UnprovideableAttributeException( - reqAttribut.getName()); - } - - - } catch (PVP2Exception e) { - log.info( - "Attribute generation failed! for " - + reqAttribut.getFriendlyName()); - if (reqAttribut.isRequired()) { - throw new UnprovideableAttributeException( - reqAttribut.getName()); - } - - } catch (Exception e) { - log.warn( - "General Attribute generation failed! for " - + reqAttribut.getFriendlyName(), e); - if (reqAttribut.isRequired()) { - throw new UnprovideableAttributeException( - reqAttribut.getName()); - } - - } - } - } - } - - //generate subjectNameId - NameID subjectNameID = SAML2Utils.createSAMLObject(NameID.class); - Pair<String, String> subjectNameIdPair = subjectNameIdGenerator.generateSubjectNameId(authData, oaParam); - subjectNameID.setValue(subjectNameIdPair.getFirst()); - subjectNameID.setNameQualifier(subjectNameIdPair.getSecond()); - - //get NameIDFormat from request - String nameIDFormat = NameID.TRANSIENT; - AuthnRequest authnReq = (AuthnRequestImpl) authnRequest; - if (authnReq.getNameIDPolicy() != null && - StringUtils.isNotEmpty(authnReq.getNameIDPolicy().getFormat())) { - nameIDFormat = authnReq.getNameIDPolicy().getFormat(); - - } else { - //get NameIDFormat from metadata - List<NameIDFormat> metadataNameIDFormats = spSSODescriptor.getNameIDFormats(); - - if (metadataNameIDFormats != null) { - - for (NameIDFormat el : metadataNameIDFormats) { - if (NameID.PERSISTENT.equals(el.getFormat())) { - nameIDFormat = NameID.PERSISTENT; - break; - - } else if (NameID.TRANSIENT.equals(el.getFormat()) || - NameID.UNSPECIFIED.equals(el.getFormat())) - break; - - } - } - } - - if (NameID.TRANSIENT.equals(nameIDFormat) || NameID.UNSPECIFIED.equals(nameIDFormat)) { - String random = Random.nextHexRandom32(); - String nameID = subjectNameID.getValue(); - - try { - MessageDigest md = MessageDigest.getInstance("SHA-1"); - byte[] hash = md.digest((nameID + random).getBytes("ISO-8859-1")); - subjectNameID.setValue(Base64Utils.encodeToString(hash)); - subjectNameID.setNameQualifier(null); - subjectNameID.setFormat(NameID.TRANSIENT); - - } catch (Exception e) { - log.warn("PVP2 subjectNameID error", e); - throw new ResponderErrorException("internal.03", null, e); - - } - - } else - subjectNameID.setFormat(nameIDFormat); - - - String sessionIndex = null; - - //if request is a reauthentication and NameIDFormat match reuse old session information - if (StringUtils.isNotEmpty(authData.getNameID()) && - StringUtils.isNotEmpty(authData.getNameIDFormat()) && - nameIDFormat.equals(authData.getNameIDFormat())) { - subjectNameID.setValue(authData.getNameID()); - sessionIndex = authData.getSessionIndex(); - - } - - // - if (StringUtils.isEmpty(sessionIndex)) - sessionIndex = SAML2Utils.getSecureIdentifier(); - - SubjectConfirmationData subjectConfirmationData = SAML2Utils - .createSAMLObject(SubjectConfirmationData.class); - subjectConfirmationData.setInResponseTo(authnRequest.getID()); - subjectConfirmationData.setNotOnOrAfter(new DateTime(authData.getSsoSessionValidTo().getTime())); - - //set 'recipient' attribute in subjectConformationData - subjectConfirmationData.setRecipient(assertionConsumerService.getLocation()); - - //set IP address of the user machine as 'Address' attribute in subjectConformationData - String usersIPAddress = pendingReq.getRawData( - RequestImpl.DATAID_REQUESTER_IP_ADDRESS, String.class); - if (StringUtils.isNotEmpty(usersIPAddress)) - subjectConfirmationData.setAddress(usersIPAddress); - - //set SLO information - sloInformation.setUserNameIdentifier(subjectNameID.getValue()); - sloInformation.setNameIDFormat(subjectNameID.getFormat()); - sloInformation.setSessionIndex(sessionIndex); - - return buildGenericAssertion(issuerEntityID, peerEntity.getEntityID(), date, authnContextClassRef, attrList, subjectNameID, subjectConfirmationData, sessionIndex, subjectConfirmationData.getNotOnOrAfter()); - } - - /** - * - * @param issuer IDP EntityID - * @param entityID Service Provider EntityID - * @param date - * @param authnContextClassRef - * @param attrList - * @param subjectNameID - * @param subjectConfirmationData - * @param sessionIndex - * @param isValidTo - * @return - * @throws ConfigurationException - */ - - public Assertion buildGenericAssertion(String issuer, String entityID, DateTime date, - AuthnContextClassRef authnContextClassRef, List<Attribute> attrList, - NameID subjectNameID, SubjectConfirmationData subjectConfirmationData, - String sessionIndex, DateTime isValidTo) throws ResponderErrorException { - Assertion assertion = SAML2Utils.createSAMLObject(Assertion.class); - - AuthnContext authnContext = SAML2Utils - .createSAMLObject(AuthnContext.class); - authnContext.setAuthnContextClassRef(authnContextClassRef); - - AuthnStatement authnStatement = SAML2Utils - .createSAMLObject(AuthnStatement.class); - - authnStatement.setAuthnInstant(date); - authnStatement.setSessionIndex(sessionIndex); - authnStatement.setAuthnContext(authnContext); - - assertion.getAuthnStatements().add(authnStatement); - - AttributeStatement attributeStatement = SAML2Utils - .createSAMLObject(AttributeStatement.class); - attributeStatement.getAttributes().addAll(attrList); - if (attributeStatement.getAttributes().size() > 0) { - assertion.getAttributeStatements().add(attributeStatement); - } - - Subject subject = SAML2Utils.createSAMLObject(Subject.class); - subject.setNameID(subjectNameID); - - SubjectConfirmation subjectConfirmation = SAML2Utils - .createSAMLObject(SubjectConfirmation.class); - subjectConfirmation.setMethod(SubjectConfirmation.METHOD_BEARER); - subjectConfirmation.setSubjectConfirmationData(subjectConfirmationData); - - subject.getSubjectConfirmations().add(subjectConfirmation); - - Conditions conditions = SAML2Utils.createSAMLObject(Conditions.class); - AudienceRestriction audienceRestriction = SAML2Utils - .createSAMLObject(AudienceRestriction.class); - Audience audience = SAML2Utils.createSAMLObject(Audience.class); - - audience.setAudienceURI(entityID); - audienceRestriction.getAudiences().add(audience); - conditions.setNotBefore(date); - conditions.setNotOnOrAfter(isValidTo); - - conditions.getAudienceRestrictions().add(audienceRestriction); - - assertion.setConditions(conditions); - - Issuer issuerObj = SAML2Utils.createSAMLObject(Issuer.class); - - if (issuer.endsWith("/")) - issuer = issuer.substring(0, issuer.length()-1); - issuerObj.setValue(issuer); - issuerObj.setFormat(NameID.ENTITY); - - assertion.setIssuer(issuerObj); - assertion.setSubject(subject); - assertion.setID(SAML2Utils.getSecureIdentifier()); - assertion.setIssueInstant(date); - - return assertion; - } -} diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/builder/Pvp2AssertionBuilder.java b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/builder/Pvp2AssertionBuilder.java new file mode 100644 index 00000000..b7b18f0f --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/idp/impl/builder/Pvp2AssertionBuilder.java @@ -0,0 +1,469 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.idp.impl.builder; + +import java.security.MessageDigest; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import javax.naming.ConfigurationException; + +import at.gv.egiz.eaaf.core.api.data.EaafConstants; +import at.gv.egiz.eaaf.core.api.data.ILoALevelMapper; +import at.gv.egiz.eaaf.core.api.idp.IAuthData; +import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration; +import at.gv.egiz.eaaf.core.api.idp.slo.SloInformationInterface; +import at.gv.egiz.eaaf.core.exceptions.UnavailableAttributeException; +import at.gv.egiz.eaaf.core.impl.data.Pair; +import at.gv.egiz.eaaf.core.impl.idp.controller.protocols.RequestImpl; +import at.gv.egiz.eaaf.core.impl.utils.Random; +import at.gv.egiz.eaaf.modules.pvp2.PvpConstants; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; +import at.gv.egiz.eaaf.modules.pvp2.exception.QaaNotSupportedException; +import at.gv.egiz.eaaf.modules.pvp2.idp.api.builder.ISubjectNameIdGenerator; +import at.gv.egiz.eaaf.modules.pvp2.idp.exception.ResponderErrorException; +import at.gv.egiz.eaaf.modules.pvp2.idp.exception.UnprovideableAttributeException; +import at.gv.egiz.eaaf.modules.pvp2.idp.impl.PvpSProfilePendingRequest; +import at.gv.egiz.eaaf.modules.pvp2.impl.builder.PvpAttributeBuilder; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.QaaLevelVerifier; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils; + +import org.apache.commons.lang3.StringUtils; +import org.joda.time.DateTime; +import org.opensaml.saml.common.xml.SAMLConstants; +import org.opensaml.saml.saml2.core.Assertion; +import org.opensaml.saml.saml2.core.Attribute; +import org.opensaml.saml.saml2.core.AttributeQuery; +import org.opensaml.saml.saml2.core.AttributeStatement; +import org.opensaml.saml.saml2.core.Audience; +import org.opensaml.saml.saml2.core.AudienceRestriction; +import org.opensaml.saml.saml2.core.AuthnContext; +import org.opensaml.saml.saml2.core.AuthnContextClassRef; +import org.opensaml.saml.saml2.core.AuthnRequest; +import org.opensaml.saml.saml2.core.AuthnStatement; +import org.opensaml.saml.saml2.core.Conditions; +import org.opensaml.saml.saml2.core.Issuer; +import org.opensaml.saml.saml2.core.NameID; +import org.opensaml.saml.saml2.core.NameIDType; +import org.opensaml.saml.saml2.core.RequestedAuthnContext; +import org.opensaml.saml.saml2.core.Subject; +import org.opensaml.saml.saml2.core.SubjectConfirmation; +import org.opensaml.saml.saml2.core.SubjectConfirmationData; +import org.opensaml.saml.saml2.metadata.AssertionConsumerService; +import org.opensaml.saml.saml2.metadata.AttributeConsumingService; +import org.opensaml.saml.saml2.metadata.EntityDescriptor; +import org.opensaml.saml.saml2.metadata.NameIDFormat; +import org.opensaml.saml.saml2.metadata.RequestedAttribute; +import org.opensaml.saml.saml2.metadata.SPSSODescriptor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.Base64Utils; + +@Service("PVP2AssertionBuilder") +public class Pvp2AssertionBuilder implements PvpConstants { + + private static final Logger log = LoggerFactory.getLogger(Pvp2AssertionBuilder.class); + @Autowired + private ILoALevelMapper loaLevelMapper; + @Autowired + private ISubjectNameIdGenerator subjectNameIdGenerator; + + /** + * Build a PVP assertion as response for a SAML2 AttributeQuery request. + * + * @param issuerEntityID EnitiyID, which should be used for this IDP response + * @param attrQuery AttributeQuery request from Service-Provider + * @param attrList List of PVP response attributes + * @param now Current time + * @param validTo ValidTo time of the assertion + * @param qaaLevel QAA level of the authentication + * @param sessionIndex SAML2 SessionIndex, which should be included * + * @return PVP 2.1 Assertion + * @throws Pvp2Exception In case of an error + */ + public Assertion buildAssertion(final String issuerEntityID, final AttributeQuery attrQuery, + final List<Attribute> attrList, final DateTime now, final DateTime validTo, + final String qaaLevel, final String sessionIndex) throws Pvp2Exception { + + final AuthnContextClassRef authnContextClassRef = + Saml2Utils.createSamlObject(AuthnContextClassRef.class); + authnContextClassRef.setAuthnContextClassRef(qaaLevel); + + final NameID subjectNameID = Saml2Utils.createSamlObject(NameID.class); + subjectNameID.setFormat(attrQuery.getSubject().getNameID().getFormat()); + subjectNameID.setValue(attrQuery.getSubject().getNameID().getValue()); + + final SubjectConfirmationData subjectConfirmationData = null; + + return buildGenericAssertion(issuerEntityID, attrQuery.getIssuer().getValue(), now, + authnContextClassRef, attrList, subjectNameID, subjectConfirmationData, sessionIndex, + validTo); + } + + /** + * Build a PVP 2.1 assertion as response of a SAML2 AuthnRequest. + * + * @param issuerEntityID EnitiyID, which should be used for this IDP + * response + * @param pendingReq Current processed pendingRequest DAO + * @param authnRequest Current processed PVP AuthnRequest + * @param authData AuthenticationData of the user, which is + * already authenticated + * @param peerEntity SAML2 EntityDescriptor of the + * service-provider, which receives the response + * @param date TimeStamp + * @param assertionConsumerService SAML2 endpoint of the service-provider, which + * should be used + * @param sloInformation Single LogOut information DAO + * @return PVP2 S-Profil Assertion + * @throws Pvp2Exception In case of an error + */ + public Assertion buildAssertion(final String issuerEntityID, + final PvpSProfilePendingRequest pendingReq, final AuthnRequest authnRequest, + final IAuthData authData, final EntityDescriptor peerEntity, final DateTime date, + final AssertionConsumerService assertionConsumerService, + final SloInformationInterface sloInformation) throws Pvp2Exception { + + final ISpConfiguration oaParam = pendingReq.getServiceProviderConfiguration(); + final AuthnContextClassRef authnContextClassRef = + Saml2Utils.createSamlObject(AuthnContextClassRef.class); + + // check if authn. request contains LoA + final RequestedAuthnContext reqAuthnContext = authnRequest.getRequestedAuthnContext(); + if (reqAuthnContext == null) { + authnContextClassRef.setAuthnContextClassRef(authData.getEidasQaaLevel()); + + } else { + // authn. request requests LoA levels. To LoA validation + final List<AuthnContextClassRef> reqAuthnContextClassRefIt = + reqAuthnContext.getAuthnContextClassRefs(); + + // get matching mode from authn. request + String loaMatchingMode = EaafConstants.EIDAS_LOA_MATCHING_MINIMUM; + if (reqAuthnContext.getComparison() != null + && StringUtils.isNotEmpty(reqAuthnContext.getComparison().toString())) { + loaMatchingMode = reqAuthnContext.getComparison().toString(); + } + + // get requested LoAs + if (reqAuthnContextClassRefIt.size() == 0) { + QaaLevelVerifier.verifyQaaLevel(authData.getEidasQaaLevel(), oaParam.getRequiredLoA(), + loaMatchingMode); + authnContextClassRef.setAuthnContextClassRef(authData.getEidasQaaLevel()); + + } else { + final List<String> eidasLoaFromRequest = new ArrayList<>(); + for (final AuthnContextClassRef authnClassRef : reqAuthnContextClassRefIt) { + final String qaa_uri = authnClassRef.getAuthnContextClassRef(); + + if (!qaa_uri.trim().startsWith(EaafConstants.EIDAS_LOA_PREFIX)) { + if (loaLevelMapper != null) { + log.debug("Find no eIDAS LoA in AuthnReq. Start mapping process ... "); + eidasLoaFromRequest.add(loaLevelMapper.mapToEidasLoa(qaa_uri.trim())); + + } else { + log.debug("AuthnRequest contains no eIDAS LoA. NO LoA mapper FOUND, ignore " + "'" + + qaa_uri.trim() + "'"); + } + } else { + eidasLoaFromRequest.add(qaa_uri.trim()); + } + + } + + // stop process if no supported LoA scheme is requested + if (eidasLoaFromRequest.isEmpty()) { + log.info( + "Authn. request contains no supported LoA level. Stop authentication process ... "); + throw new QaaNotSupportedException("No supported LoA in Authn. request"); + + } + + // verifiy LoAs from request to authentication LoA + QaaLevelVerifier.verifyQaaLevel(authData.getEidasQaaLevel(), eidasLoaFromRequest, + loaMatchingMode); + authnContextClassRef.setAuthnContextClassRef(authData.getEidasQaaLevel()); + + } + } + + // load SPSS decriptor from service-provider metadata + final SPSSODescriptor spSsoDescriptor = peerEntity.getSPSSODescriptor(SAMLConstants.SAML20P_NS); + + // add Attributes to Assertion + final List<Attribute> attrList = new ArrayList<>(); + if (spSsoDescriptor.getAttributeConsumingServices() != null + && spSsoDescriptor.getAttributeConsumingServices().size() > 0) { + + final Integer aIdx = authnRequest.getAttributeConsumingServiceIndex(); + int idx = 0; + + AttributeConsumingService attributeConsumingService = null; + if (aIdx != null) { + idx = aIdx; + attributeConsumingService = spSsoDescriptor.getAttributeConsumingServices().get(idx); + + } else { + final List<AttributeConsumingService> attrConsumingServiceList = + spSsoDescriptor.getAttributeConsumingServices(); + for (final AttributeConsumingService el : attrConsumingServiceList) { + if (el.isDefault()) { + attributeConsumingService = el; + } + } + } + + /* + * TODO: maybe use first AttributeConsumingService if no is selected in request + * or on service is marked as default + * + */ + if (attributeConsumingService == null) { + final List<AttributeConsumingService> attrConsumingServiceList = + spSsoDescriptor.getAttributeConsumingServices(); + if (attrConsumingServiceList != null && !attrConsumingServiceList.isEmpty()) { + attributeConsumingService = attrConsumingServiceList.get(0); + } + + } + + if (attributeConsumingService != null) { + final Iterator<RequestedAttribute> it = + attributeConsumingService.getRequestAttributes().iterator(); + while (it.hasNext()) { + final RequestedAttribute reqAttribut = it.next(); + try { + final Attribute attr = + PvpAttributeBuilder.buildAttribute(reqAttribut.getName(), oaParam, authData); + if (attr == null) { + if (reqAttribut.isRequired()) { + throw new UnprovideableAttributeException(reqAttribut.getName()); + } + } else { + attrList.add(attr); + } + + } catch (final UnavailableAttributeException e) { + log.info( + "Attribute generation for " + reqAttribut.getFriendlyName() + " not possible."); + if (reqAttribut.isRequired()) { + throw new UnprovideableAttributeException(reqAttribut.getName()); + } + + } catch (final Pvp2Exception e) { + log.info("Attribute generation failed! for " + reqAttribut.getFriendlyName()); + if (reqAttribut.isRequired()) { + throw new UnprovideableAttributeException(reqAttribut.getName()); + } + + } catch (final Exception e) { + log.warn("General Attribute generation failed! for " + reqAttribut.getFriendlyName(), + e); + if (reqAttribut.isRequired()) { + throw new UnprovideableAttributeException(reqAttribut.getName()); + } + + } + } + } + } + + // generate subjectNameId + final NameID subjectNameID = Saml2Utils.createSamlObject(NameID.class); + final Pair<String, String> subjectNameIdPair = + subjectNameIdGenerator.generateSubjectNameId(authData, oaParam); + subjectNameID.setValue(subjectNameIdPair.getFirst()); + subjectNameID.setNameQualifier(subjectNameIdPair.getSecond()); + + // get NameIDFormat from request + String nameIdFormat = NameIDType.TRANSIENT; + final AuthnRequest authnReq = authnRequest; + if (authnReq.getNameIDPolicy() != null + && StringUtils.isNotEmpty(authnReq.getNameIDPolicy().getFormat())) { + nameIdFormat = authnReq.getNameIDPolicy().getFormat(); + + } else { + // get NameIDFormat from metadata + final List<NameIDFormat> metadataNameIdFormats = spSsoDescriptor.getNameIDFormats(); + + if (metadataNameIdFormats != null) { + + for (final NameIDFormat el : metadataNameIdFormats) { + if (NameIDType.PERSISTENT.equals(el.getFormat())) { + nameIdFormat = NameIDType.PERSISTENT; + break; + + } else if (NameIDType.TRANSIENT.equals(el.getFormat()) + || NameIDType.UNSPECIFIED.equals(el.getFormat())) { + break; + } + + } + } + } + + if (NameIDType.TRANSIENT.equals(nameIdFormat) || NameIDType.UNSPECIFIED.equals(nameIdFormat)) { + final String random = Random.nextHexRandom32(); + final String nameID = subjectNameID.getValue(); + + try { + final MessageDigest md = MessageDigest.getInstance("SHA-1"); + final byte[] hash = md.digest((nameID + random).getBytes("ISO-8859-1")); + subjectNameID.setValue(Base64Utils.encodeToString(hash)); + subjectNameID.setNameQualifier(null); + subjectNameID.setFormat(NameIDType.TRANSIENT); + + } catch (final Exception e) { + log.warn("PVP2 subjectNameID error", e); + throw new ResponderErrorException("internal.03", null, e); + + } + + } else { + subjectNameID.setFormat(nameIdFormat); + } + + String sessionIndex = null; + + // if request is a reauthentication and NameIDFormat match reuse old session + // information + if (StringUtils.isNotEmpty(authData.getNameID()) + && StringUtils.isNotEmpty(authData.getNameIdFormat()) + && nameIdFormat.equals(authData.getNameIdFormat())) { + subjectNameID.setValue(authData.getNameID()); + sessionIndex = authData.getSessionIndex(); + + } + + // + if (StringUtils.isEmpty(sessionIndex)) { + sessionIndex = Saml2Utils.getSecureIdentifier(); + } + + final SubjectConfirmationData subjectConfirmationData = + Saml2Utils.createSamlObject(SubjectConfirmationData.class); + subjectConfirmationData.setInResponseTo(authnRequest.getID()); + subjectConfirmationData + .setNotOnOrAfter(new DateTime(authData.getSsoSessionValidTo().getTime())); + + // set 'recipient' attribute in subjectConformationData + subjectConfirmationData.setRecipient(assertionConsumerService.getLocation()); + + // set IP address of the user machine as 'Address' attribute in + // subjectConformationData + final String usersIpAddress = + pendingReq.getRawData(RequestImpl.DATAID_REQUESTER_IP_ADDRESS, String.class); + if (StringUtils.isNotEmpty(usersIpAddress)) { + subjectConfirmationData.setAddress(usersIpAddress); + } + + // set SLO information + sloInformation.setUserNameIdentifier(subjectNameID.getValue()); + sloInformation.setNameIdFormat(subjectNameID.getFormat()); + sloInformation.setSessionIndex(sessionIndex); + + return buildGenericAssertion(issuerEntityID, peerEntity.getEntityID(), date, + authnContextClassRef, attrList, subjectNameID, subjectConfirmationData, sessionIndex, + subjectConfirmationData.getNotOnOrAfter()); + } + + /** + * Build generic part of PVP S-Profile Assertion. + * + * @param issuer IDP EntityID + * @param entityID Service Provider EntityID + * @param date Timestamp + * @param authnContextClassRef SAML2 AuthnContextClassReference + * @param attrList List of attributes + * @param subjectNameID SubjectNameId + * @param subjectConfirmationData SubjectConfirmationInformation + * @param sessionIndex SessionIndex + * @param isValidTo ValidTo Timestamp + * @return PVP S-Profile Assertion + * @throws ConfigurationException In case on an error + */ + + public Assertion buildGenericAssertion(String issuer, final String entityID, final DateTime date, + final AuthnContextClassRef authnContextClassRef, final List<Attribute> attrList, + final NameID subjectNameID, final SubjectConfirmationData subjectConfirmationData, + final String sessionIndex, final DateTime isValidTo) throws ResponderErrorException { + final Assertion assertion = Saml2Utils.createSamlObject(Assertion.class); + + final AuthnContext authnContext = Saml2Utils.createSamlObject(AuthnContext.class); + authnContext.setAuthnContextClassRef(authnContextClassRef); + + final AuthnStatement authnStatement = Saml2Utils.createSamlObject(AuthnStatement.class); + + authnStatement.setAuthnInstant(date); + authnStatement.setSessionIndex(sessionIndex); + authnStatement.setAuthnContext(authnContext); + + assertion.getAuthnStatements().add(authnStatement); + + final AttributeStatement attributeStatement = + Saml2Utils.createSamlObject(AttributeStatement.class); + attributeStatement.getAttributes().addAll(attrList); + if (attributeStatement.getAttributes().size() > 0) { + assertion.getAttributeStatements().add(attributeStatement); + } + + final Subject subject = Saml2Utils.createSamlObject(Subject.class); + subject.setNameID(subjectNameID); + + final SubjectConfirmation subjectConfirmation = + Saml2Utils.createSamlObject(SubjectConfirmation.class); + subjectConfirmation.setMethod(SubjectConfirmation.METHOD_BEARER); + subjectConfirmation.setSubjectConfirmationData(subjectConfirmationData); + + subject.getSubjectConfirmations().add(subjectConfirmation); + + final Conditions conditions = Saml2Utils.createSamlObject(Conditions.class); + final AudienceRestriction audienceRestriction = + Saml2Utils.createSamlObject(AudienceRestriction.class); + final Audience audience = Saml2Utils.createSamlObject(Audience.class); + + audience.setAudienceURI(entityID); + audienceRestriction.getAudiences().add(audience); + conditions.setNotBefore(date); + conditions.setNotOnOrAfter(isValidTo); + + conditions.getAudienceRestrictions().add(audienceRestriction); + + assertion.setConditions(conditions); + + final Issuer issuerObj = Saml2Utils.createSamlObject(Issuer.class); + + if (issuer.endsWith("/")) { + issuer = issuer.substring(0, issuer.length() - 1); + } + issuerObj.setValue(issuer); + issuerObj.setFormat(NameIDType.ENTITY); + + assertion.setIssuer(issuerObj); + assertion.setSubject(subject); + assertion.setID(Saml2Utils.getSecureIdentifier()); + assertion.setIssueInstant(date); + + return assertion; + } +} diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider b/eaaf_modules/eaaf_module_pvp2_idp/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider index cda12a62..c3c68e20 100644 --- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider @@ -1 +1 @@ -at.gv.egiz.eaaf.modules.pvp2.idp.PVP2SProfileIDPSpringResourceProvider
\ No newline at end of file +at.gv.egiz.eaaf.modules.pvp2.idp.Pvp2SProfileIdpSpringResourceProvider
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/main/resources/eaaf_pvp_idp.beans.xml b/eaaf_modules/eaaf_module_pvp2_idp/src/main/resources/eaaf_pvp_idp.beans.xml index b01a09ff..d29b5aba 100644 --- a/eaaf_modules/eaaf_module_pvp2_idp/src/main/resources/eaaf_pvp_idp.beans.xml +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/main/resources/eaaf_pvp_idp.beans.xml @@ -1,22 +1,19 @@ <?xml version="1.0" encoding="UTF-8"?> -<!-- - --> - <beans xmlns="http://www.springframework.org/schema/beans" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xmlns:context="http://www.springframework.org/schema/context" - xmlns:tx="http://www.springframework.org/schema/tx" - xmlns:aop="http://www.springframework.org/schema/aop" - xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd - http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd - http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd - http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> - - <bean id="PVP2AssertionBuilder" - class="at.gv.egiz.eaaf.modules.pvp2.idp.impl.builder.PVP2AssertionBuilder" /> - - <bean id="PVPSProfilePendingRequest" - class="at.gv.egiz.eaaf.modules.pvp2.idp.impl.PVPSProfilePendingRequest" - scope="prototype"/> - + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:context="http://www.springframework.org/schema/context" + xmlns:tx="http://www.springframework.org/schema/tx" + xmlns:aop="http://www.springframework.org/schema/aop" + xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd + http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> + + <bean id="PVP2AssertionBuilder" + class="at.gv.egiz.eaaf.modules.pvp2.idp.impl.builder.Pvp2AssertionBuilder" /> + + <bean id="PVPSProfilePendingRequest" + class="at.gv.egiz.eaaf.modules.pvp2.idp.impl.PvpSProfilePendingRequest" + scope="prototype" /> + </beans>
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/AuthenticationActionTest.java b/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/AuthenticationActionTest.java new file mode 100644 index 00000000..a88fa869 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/AuthenticationActionTest.java @@ -0,0 +1,226 @@ +package at.gv.egiz.eaaf.modules.pvp2.idp.test; + +import java.util.Date; + +import org.apache.commons.lang3.RandomStringUtils; +import org.apache.commons.lang3.time.DateFormatUtils; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import at.gv.egiz.eaaf.core.api.data.EaafConstants; +import at.gv.egiz.eaaf.core.api.idp.IAuthData; +import at.gv.egiz.eaaf.core.api.idp.auth.data.IIdentityLink; +import at.gv.egiz.eaaf.core.impl.idp.module.test.DummyAuthConfig; +import at.gv.egiz.eaaf.modules.pvp2.idp.exception.ResponderErrorException; +import at.gv.egiz.eaaf.modules.pvp2.idp.impl.AuthenticationAction; +import at.gv.egiz.eaaf.modules.pvp2.idp.impl.PvpSProfilePendingRequest; +import at.gv.egiz.eaaf.modules.pvp2.impl.metadata.PvpMetadataResolverFactory; +import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafOpenSaml3xInitializer; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration({"/spring/test_eaaf_pvp.beans.xml"}) +@TestPropertySource( + locations = {"/config/config_1.props"}) +public class AuthenticationActionTest { + + @Autowired private DummyAuthConfig authConfig; + @Autowired private PvpMetadataResolverFactory metadataResolverFactory; + @Autowired private AuthenticationAction action; + + protected MockHttpServletRequest httpReq; + protected MockHttpServletResponse httpResp; + private PvpSProfilePendingRequest pendingReq; + /** + * JUnit class initializer. + * + * @throws Exception In case of an OpenSAML3 initialization error + */ + @BeforeClass + public static void classInitializer() throws Exception { + EaafOpenSaml3xInitializer.eaafInitialize(); + + } + + /** + * Test initializer. + * + */ + @Before + public void initialize() { + httpReq = new MockHttpServletRequest(); + httpResp = new MockHttpServletResponse(); + + pendingReq = new PvpSProfilePendingRequest(); + + } + + @Test + public void checkNeedAuthFlag() { + Assert.assertTrue("Wrong 'needAuth' flag", action.needAuthentication(pendingReq, httpReq, httpResp)); + + } + + @Test + public void noAuthnRequestInPendingRequest() { + + IAuthData authData = generateAuthData(); + + try { + action.processRequest(pendingReq, httpReq, httpResp, authData); + Assert.fail("No SAML requst not detected"); + + } catch (ResponderErrorException e) { + Assert.assertEquals("Wrong errorCode", "pvp2.01", e.getErrorId()); + } + + } + + private IAuthData generateAuthData() { + return new IAuthData() { + + @Override + public boolean isSsoSession() { + return false; + } + + @Override + public boolean isForeigner() { + return false; + } + + @Override + public boolean isBaseIdTransferRestrication() { + return true; + } + + @Override + public Date getSsoSessionValidTo() { + return null; + + } + + @Override + public String getSessionIndex() { + return null; + + } + + @Override + public String getNameIdFormat() { + return null; + + } + + @Override + public String getNameID() { + return null; + + } + + @Override + public IIdentityLink getIdentityLink() { + return null; + + } + + @Override + public String getIdentificationValue() { + return null; + + } + + @Override + public String getIdentificationType() { + return null; + + } + + @Override + public String getGivenName() { + return RandomStringUtils.randomAlphabetic(10); + + } + + @Override + public <T> T getGenericData(String key, Class<T> clazz) { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getFormatedDateOfBirth() { + return DateFormatUtils.format(getDateOfBirth(), "yyyy-MM-dd"); + } + + @Override + public String getFamilyName() { + return RandomStringUtils.randomAlphabetic(10); + + } + + @Override + public String getEncryptedSourceIdType() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getEncryptedSourceId() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getEidasQaaLevel() { + return EaafConstants.EIDAS_LOA_LOW; + } + + @Override + public Date getDateOfBirth() { + return new Date(); + + } + + @Override + public String getCiticenCountryCode() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getBpkType() { + return EaafConstants.URN_PREFIX_CDID + RandomStringUtils.randomAlphabetic(2); + } + + @Override + public String getBpk() { + return RandomStringUtils.randomAlphabetic(10); + } + + @Override + public String getAuthenticationIssuer() { + return RandomStringUtils.randomAlphabetic(10); + } + + @Override + public String getAuthenticationIssueInstantString() { + return DateFormatUtils.ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.format(getAuthenticationIssueInstant()); + } + + @Override + public Date getAuthenticationIssueInstant() { + return new Date(); + } + }; + + } +} diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/AuthnResponseBuilderTest.java b/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/AuthnResponseBuilderTest.java new file mode 100644 index 00000000..b2e528c4 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/AuthnResponseBuilderTest.java @@ -0,0 +1,156 @@ +package at.gv.egiz.eaaf.modules.pvp2.idp.test; + +import java.io.IOException; + +import javax.xml.transform.TransformerException; + +import at.gv.egiz.eaaf.core.impl.idp.module.test.DummyAuthConfig; +import at.gv.egiz.eaaf.core.impl.utils.DomUtils; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2MetadataException; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlAssertionValidationExeption; +import at.gv.egiz.eaaf.modules.pvp2.idp.exception.InvalidAssertionEncryptionException; +import at.gv.egiz.eaaf.modules.pvp2.idp.impl.builder.AuthResponseBuilder; +import at.gv.egiz.eaaf.modules.pvp2.impl.metadata.PvpMetadataResolverFactory; +import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafOpenSaml3xInitializer; +import at.gv.egiz.eaaf.modules.pvp2.impl.verification.SamlVerificationEngine; +import at.gv.egiz.eaaf.modules.pvp2.test.binding.PostBindingTest; +import at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyCredentialProvider; + +import org.apache.commons.lang3.RandomStringUtils; +import org.joda.time.DateTime; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport; +import org.opensaml.core.xml.io.MarshallingException; +import org.opensaml.core.xml.io.UnmarshallingException; +import org.opensaml.core.xml.util.XMLObjectSupport; +import org.opensaml.saml.saml2.core.Assertion; +import org.opensaml.saml.saml2.core.RequestAbstractType; +import org.opensaml.saml.saml2.core.Response; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.w3c.dom.Element; + +import net.shibboleth.utilities.java.support.xml.XMLParserException; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration({"/spring/test_eaaf_pvp.beans.xml"}) +@TestPropertySource( + locations = {"/config/config_1.props"}) +public class AuthnResponseBuilderTest { + + @Autowired private DummyAuthConfig authConfig; + @Autowired private PvpMetadataResolverFactory metadataResolverFactory; + @Autowired private SamlVerificationEngine verifyEngine; + @Autowired private DummyCredentialProvider credentialProvider; + + /** + * JUnit class initializer. + * + * @throws Exception In case of an OpenSAML3 initialization error + */ + @BeforeClass + public static void classInitializer() throws Exception { + EaafOpenSaml3xInitializer.eaafInitialize(); + + } + + @Test + public void encryptedAssertion() throws InvalidAssertionEncryptionException, Pvp2MetadataException, + XMLParserException, UnmarshallingException, MarshallingException, TransformerException, IOException { + final String issuerEntityID = RandomStringUtils.randomAlphabetic(15); + + final IPvp2MetadataProvider metadataProvider = + metadataResolverFactory.createMetadataProvider( + "classpath:/data/pvp_metadata_junit_keystore.xml", null, "jUnit metadata resolver", null); + + final RequestAbstractType authnReq = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + PostBindingTest.class.getResourceAsStream("/data/AuthRequest_without_sig_1.xml")); + authnReq.setID("_" + RandomStringUtils.randomAlphanumeric(10)); + + final Assertion assertion = (Assertion) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + PostBindingTest.class.getResourceAsStream("/data/Assertion_1.xml")); + + //build response + final DateTime now = DateTime.now(); + final Response response = AuthResponseBuilder.buildResponse( + metadataProvider, issuerEntityID, authnReq, + now, assertion, authConfig); + + + //validate + Assert.assertNotNull("SAML2 response is null", response); + Assert.assertTrue("Assertion not null", response.getAssertions().isEmpty()); + Assert.assertNotNull("Enc. assertion is null", response.getEncryptedAssertions()); + Assert.assertFalse("Enc. assertion is empty", response.getEncryptedAssertions().isEmpty()); + Assert.assertEquals("# enc. assertions wrong", 1, response.getEncryptedAssertions().size()); + + Assert.assertEquals("InResponseTo", authnReq.getID(), response.getInResponseTo()); + Assert.assertEquals("Issuer EntityId", issuerEntityID, response.getIssuer().getValue()); + Assert.assertNotNull("ResponseId is null", response.getID()); + Assert.assertFalse("ResponseId is emptry", response.getID().isEmpty()); + + final Element responseElement = XMLObjectSupport.getMarshaller(response).marshall(response); + final String xmlResp = DomUtils.serializeNode(responseElement); + Assert.assertNotNull("XML response is null", xmlResp); + Assert.assertFalse("XML response is empty", xmlResp.isEmpty()); + + } + + @Test + public void encryptedAssertionWithDecryption() throws InvalidAssertionEncryptionException, Pvp2MetadataException, + XMLParserException, UnmarshallingException, MarshallingException, TransformerException, IOException, + SamlAssertionValidationExeption, CredentialsNotAvailableException { + final String issuerEntityID = RandomStringUtils.randomAlphabetic(15); + + final IPvp2MetadataProvider metadataProvider = + metadataResolverFactory.createMetadataProvider( + "classpath:/data/pvp_metadata_junit_keystore.xml", null, "jUnit metadata resolver", null); + + final RequestAbstractType authnReq = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + PostBindingTest.class.getResourceAsStream("/data/AuthRequest_without_sig_1.xml")); + authnReq.setID("_" + RandomStringUtils.randomAlphanumeric(10)); + + final Assertion assertion = (Assertion) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + PostBindingTest.class.getResourceAsStream("/data/Assertion_1.xml")); + + //build response + final DateTime now = DateTime.now(); + final Response response = AuthResponseBuilder.buildResponse( + metadataProvider, issuerEntityID, authnReq, + now, assertion, authConfig); + + + //validate + Assert.assertNotNull("SAML2 response is null", response); + Assert.assertTrue("Assertion not null", response.getAssertions().isEmpty()); + Assert.assertNotNull("Enc. assertion is null", response.getEncryptedAssertions()); + Assert.assertFalse("Enc. assertion is empty", response.getEncryptedAssertions().isEmpty()); + Assert.assertEquals("# enc. assertions wrong", 1, response.getEncryptedAssertions().size()); + + Assert.assertEquals("InResponseTo", authnReq.getID(), response.getInResponseTo()); + Assert.assertEquals("Issuer EntityId", issuerEntityID, response.getIssuer().getValue()); + Assert.assertNotNull("ResponseId is null", response.getID()); + Assert.assertFalse("ResponseId is emptry", response.getID().isEmpty()); + + final Element responseElement = XMLObjectSupport.getMarshaller(response).marshall(response); + final String xmlResp = DomUtils.serializeNode(responseElement); + Assert.assertNotNull("XML response is null", xmlResp); + Assert.assertFalse("XML response is empty", xmlResp.isEmpty()); + + verifyEngine.validateAssertion(response, credentialProvider.getMetaDataSigningCredential(), + "https://demo.egiz.gv.at/demoportal_demologin/", "jUnitTest", false); + + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/MetadataActionTest.java b/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/MetadataActionTest.java new file mode 100644 index 00000000..8436a43d --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/MetadataActionTest.java @@ -0,0 +1,67 @@ +package at.gv.egiz.eaaf.modules.pvp2.idp.test; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import at.gv.egiz.eaaf.core.impl.idp.module.test.DummyAuthConfig; +import at.gv.egiz.eaaf.core.impl.idp.module.test.TestRequestImpl; +import at.gv.egiz.eaaf.modules.pvp2.idp.impl.MetadataAction; +import at.gv.egiz.eaaf.modules.pvp2.impl.metadata.PvpMetadataResolverFactory; +import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafOpenSaml3xInitializer; +import at.gv.egiz.eaaf.modules.pvp2.impl.verification.SamlVerificationEngine; +import at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyCredentialProvider; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration({"/spring/test_eaaf_pvp.beans.xml"}) +@TestPropertySource( + locations = {"/config/config_1.props"}) +public class MetadataActionTest { + + @Autowired private DummyAuthConfig authConfig; + @Autowired private PvpMetadataResolverFactory metadataResolverFactory; + @Autowired private SamlVerificationEngine verifyEngine; + @Autowired private DummyCredentialProvider credentialProvider; + @Autowired private MetadataAction action; + + protected MockHttpServletRequest httpReq; + protected MockHttpServletResponse httpResp; + private TestRequestImpl pendingReq; + /** + * JUnit class initializer. + * + * @throws Exception In case of an OpenSAML3 initialization error + */ + @BeforeClass + public static void classInitializer() throws Exception { + EaafOpenSaml3xInitializer.eaafInitialize(); + + } + + /** + * Test initializer. + * + */ + @Before + public void initialize() { + httpReq = new MockHttpServletRequest(); + httpResp = new MockHttpServletResponse(); + + pendingReq = new TestRequestImpl(); + + } + + @Test + public void checkNeedAuthFlag() { + Assert.assertFalse("Wrong 'needAuth' flag", action.needAuthentication(pendingReq, httpReq, httpResp)); + + } +} diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/Pvp2SProfileIdpSpringResourceProviderTest.java b/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/Pvp2SProfileIdpSpringResourceProviderTest.java new file mode 100644 index 00000000..f9aafea9 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/Pvp2SProfileIdpSpringResourceProviderTest.java @@ -0,0 +1,56 @@ +package at.gv.egiz.eaaf.modules.pvp2.idp.test; + +import java.io.IOException; +import java.io.InputStream; + +import org.apache.commons.io.IOUtils; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.BlockJUnit4ClassRunner; +import org.springframework.core.io.Resource; + +import at.gv.egiz.eaaf.core.test.TestConstants; +import at.gv.egiz.eaaf.modules.pvp2.idp.Pvp2SProfileIdpSpringResourceProvider; + + + +@RunWith(BlockJUnit4ClassRunner.class) +public class Pvp2SProfileIdpSpringResourceProviderTest { + + @Test + public void testSpringConfig() { + final Pvp2SProfileIdpSpringResourceProvider test = + new Pvp2SProfileIdpSpringResourceProvider(); + for (final Resource el : test.getResourcesToLoad()) { + try { + IOUtils.toByteArray(el.getInputStream()); + + } catch (final IOException e) { + Assert.fail("Ressouce: " + el.getFilename() + " not found"); + } + + } + + Assert.assertNotNull("no Name", test.getName()); + Assert.assertNull("Find package definitions", test.getPackagesToScan()); + + } + + @Test + public void testSpILoaderConfig() { + final InputStream el = this.getClass().getResourceAsStream(TestConstants.TEST_SPI_LOADER_PATH); + try { + final String spiFile = IOUtils.toString(el, "UTF-8"); + + Assert.assertEquals("Wrong classpath in SPI file", + Pvp2SProfileIdpSpringResourceProvider.class.getName(), spiFile); + + + } catch (final IOException e) { + Assert.fail("Ressouce: " + TestConstants.TEST_SPI_LOADER_PATH + " not found"); + + } + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/dummy/DummyLoALevelMapper.java b/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/dummy/DummyLoALevelMapper.java new file mode 100644 index 00000000..004df86d --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/dummy/DummyLoALevelMapper.java @@ -0,0 +1,25 @@ +package at.gv.egiz.eaaf.modules.pvp2.idp.test.dummy; + +import at.gv.egiz.eaaf.core.api.data.ILoALevelMapper; + +public class DummyLoALevelMapper implements ILoALevelMapper { + + @Override + public String mapToEidasLoa(String qaa) { + // TODO Auto-generated method stub + return null; + } + + @Override + public String mapToSecClass(String qaa) { + // TODO Auto-generated method stub + return null; + } + + @Override + public String mapEidasQaaToStorkQaa(String eidasqaaLevel) { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/dummy/DummyPvpConfiguration.java b/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/dummy/DummyPvpConfiguration.java new file mode 100644 index 00000000..c5fc0f13 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/dummy/DummyPvpConfiguration.java @@ -0,0 +1,52 @@ +package at.gv.egiz.eaaf.modules.pvp2.idp.test.dummy; + +import java.util.List; + +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.modules.pvp2.api.IPvp2BasicConfiguration; + +import org.opensaml.saml.saml2.metadata.ContactPerson; +import org.opensaml.saml.saml2.metadata.Organization; +import org.springframework.beans.factory.annotation.Autowired; + +public class DummyPvpConfiguration implements IPvp2BasicConfiguration { + + @Autowired private IConfiguration basicConfig; + + @Override + public String getIdpEntityId(String authUrl) throws EaafException { + return authUrl + "/idp"; + } + + @Override + public String getIdpSsoPostService(String authUrl) throws EaafException { + return authUrl + "/sso/post"; + } + + @Override + public String getIdpSsoRedirectService(String authUrl) throws EaafException { + return authUrl + "/sso/redirect"; + } + + @Override + public String getIdpSsoSoapService(String authUrl) throws EaafException { + return authUrl + "/sso/soap"; + } + + @Override + public List<ContactPerson> getIdpContacts() throws EaafException { + return null; + } + + @Override + public Organization getIdpOrganisation() throws EaafException { + return null; + } + + @Override + public IConfiguration getBasicConfiguration() { + return basicConfig; + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/dummy/DummyPvpMetadataConfigFactory.java b/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/dummy/DummyPvpMetadataConfigFactory.java new file mode 100644 index 00000000..3f24480b --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/dummy/DummyPvpMetadataConfigFactory.java @@ -0,0 +1,16 @@ +package at.gv.egiz.eaaf.modules.pvp2.idp.test.dummy; + +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvpMetadataBuilderConfiguration; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvpMetadataConfigurationFactory; +import at.gv.egiz.eaaf.modules.pvp2.api.utils.IPvp2CredentialProvider; +import at.gv.egiz.eaaf.modules.pvp2.test.metadata.MetadataBuilderTest; + +public class DummyPvpMetadataConfigFactory implements IPvpMetadataConfigurationFactory { + + @Override + public IPvpMetadataBuilderConfiguration generateMetadataBuilderConfiguration(String authUrl, + IPvp2CredentialProvider pvpIdpCredentials) { + return MetadataBuilderTest.idpMetadataConfig(pvpIdpCredentials, false, true); + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/dummy/DummySubjectNameGenerator.java b/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/dummy/DummySubjectNameGenerator.java new file mode 100644 index 00000000..3eaa4c09 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/idp/test/dummy/DummySubjectNameGenerator.java @@ -0,0 +1,18 @@ +package at.gv.egiz.eaaf.modules.pvp2.idp.test.dummy; + +import at.gv.egiz.eaaf.core.api.idp.IAuthData; +import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration; +import at.gv.egiz.eaaf.core.impl.data.Pair; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; +import at.gv.egiz.eaaf.modules.pvp2.idp.api.builder.ISubjectNameIdGenerator; + +public class DummySubjectNameGenerator implements ISubjectNameIdGenerator { + + @Override + public Pair<String, String> generateSubjectNameId(IAuthData authData, ISpConfiguration spConfig) + throws Pvp2Exception { + return Pair.newInstance(authData.getBpk(), authData.getBpkType()); + + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/config/config_1.props b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/config/config_1.props new file mode 100644 index 00000000..164b8807 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/config/config_1.props @@ -0,0 +1,12 @@ +keystore.path=classpath:/data/junit.jks +keystore.pass=password +key.metadata.alias=meta +key.metadata.pass=password +key.sig.alias=sig +key.sig.pass=password +key.enc.alias= +key.enc.pass= + +client.http.connection.timeout.socket=2 +client.http.connection.timeout.connection=2 +client.http.connection.timeout.request=2
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/config/config_2.props b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/config/config_2.props new file mode 100644 index 00000000..60cecebb --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/config/config_2.props @@ -0,0 +1,12 @@ +keystore.path=classpath:/data/junit.jks +keystore.pass=password +key.metadata.alias=shibboleth-sign +key.metadata.pass=password +key.sig.alias=shibboleth-sign +key.sig.pass=password +key.enc.alias= +key.enc.pass= + +client.http.connection.timeout.socket=2 +client.http.connection.timeout.connection=2 +client.http.connection.timeout.request=2
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/data/Assertion_1.xml b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/data/Assertion_1.xml new file mode 100644 index 00000000..7c45b5fa --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/data/Assertion_1.xml @@ -0,0 +1,46 @@ +<?xml version="1.0" encoding="UTF-8"?> + <saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" ID="_602c3236bffaf71ac3ac88674e76ff9f" IssueInstant="2014-03-05T06:39:51.017Z" Version="2.0"> + <saml2:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp/metadata</saml2:Issuer> + <saml2:Subject> + <saml2:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent" NameQualifier="urn:publicid:gv.at:cdid+BF">QVGm48cqcM4UcyhDTNGYmVdrIoY=</saml2:NameID> + <saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"> + <saml2:SubjectConfirmationData InResponseTo="_aeebfae3ce681fe3ddcaf213a42f01d3" NotOnOrAfter="2014-03-05T06:44:51.017Z" Recipient="https://demo.egiz.gv.at/demoportal_demologin/securearea.action"/> + </saml2:SubjectConfirmation> + </saml2:Subject> + <saml2:Conditions NotBefore="2014-03-05T06:39:51.017Z" NotOnOrAfter="2014-03-05T06:44:51.017Z"> + <saml2:AudienceRestriction> + <saml2:Audience>https://demo.egiz.gv.at/demoportal_demologin/</saml2:Audience> + </saml2:AudienceRestriction> + </saml2:Conditions> + <saml2:AuthnStatement AuthnInstant="2014-03-05T06:39:51.017Z" SessionIndex="_c0c683509a8ff6ac372a9cf9c5c5a406"> + <saml2:AuthnContext> + <saml2:AuthnContextClassRef>http://www.stork.gov.eu/1.0/citizenQAALevel/4</saml2:AuthnContextClassRef> + </saml2:AuthnContext> + </saml2:AuthnStatement> + <saml2:AttributeStatement> + <saml2:Attribute FriendlyName="PVP-VERSION" Name="urn:oid:1.2.40.0.10.2.1.1.261.10" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">2.1</saml2:AttributeValue> + </saml2:Attribute> + <saml2:Attribute FriendlyName="PRINCIPAL-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.20" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Mustermann</saml2:AttributeValue> + </saml2:Attribute> + <saml2:Attribute FriendlyName="GIVEN-NAME" Name="urn:oid:2.5.4.42" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Max</saml2:AttributeValue> + </saml2:Attribute> + <saml2:Attribute FriendlyName="BIRTHDATE" Name="urn:oid:1.2.40.0.10.2.1.1.55" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">1940-01-01</saml2:AttributeValue> + </saml2:Attribute> + <saml2:Attribute FriendlyName="BPK" Name="urn:oid:1.2.40.0.10.2.1.1.149" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">BF:QVGm48cqcM4UcyhDTNGYmVdrIoY=</saml2:AttributeValue> + </saml2:Attribute> + <saml2:Attribute FriendlyName="EID-CITIZEN-QAA-LEVEL" Name="urn:oid:1.2.40.0.10.2.1.1.261.94" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:integer">4</saml2:AttributeValue> + </saml2:Attribute> + <saml2:Attribute FriendlyName="EID-ISSUING-NATION" Name="urn:oid:1.2.40.0.10.2.1.1.261.32" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">AT</saml2:AttributeValue> + </saml2:Attribute> + <saml2:Attribute FriendlyName="EID-SECTOR-FOR-IDENTIFIER" Name="urn:oid:1.2.40.0.10.2.1.1.261.34" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">urn:publicid:gv.at:cdid+BF</saml2:AttributeValue> + </saml2:Attribute> + </saml2:AttributeStatement> + </saml2:Assertion> diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/data/AuthRequest_without_sig_1.xml b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/data/AuthRequest_without_sig_1.xml new file mode 100644 index 00000000..ef35ea92 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/data/AuthRequest_without_sig_1.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8"?> +<saml2p:AuthnRequest xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" AssertionConsumerServiceIndex="1" AttributeConsumingServiceIndex="0" Destination="https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp2/post" ID="_aeebfae3ce681fe3ddcaf213a42f01d3" IssueInstant="2014-03-05T06:39:02.775Z" Version="2.0"> + <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://demo.egiz.gv.at/demoportal_demologin/</saml2:Issuer> + <saml2:Subject xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion"> + <saml2:NameID>https://demo.egiz.gv.at/demoportal_demologin/</saml2:NameID> + </saml2:Subject> + <saml2p:NameIDPolicy AllowCreate="true" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"/> + <saml2p:RequestedAuthnContext> + <saml2:AuthnContextClassRef xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">http://www.stork.gov.eu/1.0/citizenQAALevel/4</saml2:AuthnContextClassRef> + </saml2p:RequestedAuthnContext> +</saml2p:AuthnRequest> diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/data/junit.jks b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/data/junit.jks Binary files differnew file mode 100644 index 00000000..b5262cb8 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/data/junit.jks diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/data/pvp_metadata_junit_keystore.xml b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/data/pvp_metadata_junit_keystore.xml new file mode 100644 index 00000000..7fdbef90 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/data/pvp_metadata_junit_keystore.xml @@ -0,0 +1,126 @@ +<?xml version="1.0" encoding="UTF-8"?> +<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" ID="_2e23ca9b2ba4dc9eef15187830d07ff0" entityID="https://demo.egiz.gv.at/demoportal_demologin/" validUntil="2045-02-05T06:41:42.966Z"> + <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> + <ds:SignedInfo> + <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> + <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/> + <ds:Reference URI="#_2e23ca9b2ba4dc9eef15187830d07ff0"> + <ds:Transforms> + <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> + <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> + </ds:Transforms> + <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/> + <ds:DigestValue>Jy/c0ZvVJSfWzSoAcxDx/o+T5W61vvNJNqTFz2o+ILc=</ds:DigestValue> + </ds:Reference> + </ds:SignedInfo> + <ds:SignatureValue>chMxIdwrPvr78j3oTtgS7udbydy9kye1bbeQ4jm2GeFKUfxvJqY+vt9MjVnWFeR4c16gd80BjZJ6xxD5i5Ifci3YtxeKSxq0ttH/xZYEhJZkD/0NrGUhSvNV9zuLAz3uGk/LJ+2JxRq7dbnW4n9MtGuYhea8OW9/Pr1xI1KyskQS76NZDsGjjfnFWbFXahLoQZULU4Ke3SfZVqLATTn0J34RZnjNH3QieY3LhRzOVu/I5yeZtnLgUS6dg0Gab9DA/pdNFaC632iaE5QCXJmhgpqkjbkayO9e8N93YGFjbszhU1Kws5OUGjXjfCZwezLeOUZoKEfo5c+4+zEaTrEQjg==</ds:SignatureValue> + <ds:KeyInfo> + <ds:X509Data> + <ds:X509Certificate>MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH +SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W +ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w +CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ +RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq +UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+ +M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F +Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt +1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq +nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC +VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq +itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc +2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O +fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy +4jpXrp77JXFRSDWddb0yePc=</ds:X509Certificate> + </ds:X509Data> + </ds:KeyInfo> + </ds:Signature> + <md:SPSSODescriptor AuthnRequestsSigned="true" WantAssertionsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"> + <md:KeyDescriptor use="signing"> + <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> + <ds:X509Data> + <ds:X509Certificate>MIIC+jCCAeKgAwIBAgIEXjF+fTANBgkqhkiG9w0BAQsFADA/MQswCQYDVQQGEwJB +VDENMAsGA1UEBwwERUdJWjEOMAwGA1UECgwFalVuaXQxETAPBgNVBAMMCE1ldGFk +YXRhMB4XDTIwMDEyOTEyNDU0OVoXDTI2MDEyODEyNDU0OVowPzELMAkGA1UEBhMC +QVQxDTALBgNVBAcMBEVHSVoxDjAMBgNVBAoMBWpVbml0MREwDwYDVQQDDAhNZXRh +ZGF0YTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK230G3dxNbNlSYA +O5Kx/Js0aBAgxMt7q9m+dA35fK/dOvF/GjrqjWsMCnax+no9gLnq6x0gXiJclz6H +rp/YDOfLrJjMpNL/r0FWT947vbnEj7eT8TdY5d6Yi8AZulZmjiCI5nbZh2zwrP4+ +WqRroLoPhXQj8mDyp26M4xHBBUhLMRc2HV4S+XH4uNZ/vTmb8vBg31XGHCY33gl7 +/KA54JNGxJdN8Dxv6yHYsm91ZfVrX39W0iYLUNhUCkolwuQmjDVfrExM8BTLIONb +f+erJoCm3A9ghZyDYRQ/e69/UEUqDa6XOzykr88INkQscEiAXCDS+EBPMpKo+t3l +PIA9r7kCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAh/2mg4S03bdZy1OVtEAudBT9 +YZb9OF34hxPtNbkB/V04wSIg1d4TBr5KDhV7CdiUOxPZzHpS8LUCgfGX306FB6NX +zh/b67uTOPaE72AB4VIT/Np0fsM7k5WhG9k9NoprIGiqCz2lXcfpZiT+LtSO1vWS +YI87wR9KOSWjcw/5i5qZIAJuwvLCQj5JtUsmrhHK75222J3TJf4dS/gfN4xfY2rW +9vcXtH6//8WdWp/zx9V7Z1ZsDb8TDKtBCEGuFDgVeU5ScKtVq8qRoUKD3Ve76cZi +purO3KrRrVAuZP2EfLkZdHEHqe8GPigNnZ5kTn8V2VJ3iRAQ73hpJRR98tFd0A==</ds:X509Certificate> + </ds:X509Data> + <ds:X509Data> + <ds:X509Certificate>MIIBbTCCARKgAwIBAgIEXjF+qTAKBggqhkjOPQQDAjA+MQswCQYDVQQGEwJBVDEN +MAsGA1UEBwwERUdJWjEOMAwGA1UECgwFalVuaXQxEDAOBgNVBAMMB3NpZ25pbmcw +HhcNMjAwMTI5MTI0NjMzWhcNMjcwMTI4MTI0NjMzWjA+MQswCQYDVQQGEwJBVDEN +MAsGA1UEBwwERUdJWjEOMAwGA1UECgwFalVuaXQxEDAOBgNVBAMMB3NpZ25pbmcw +WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASRt7gZRrr4rSEE7Q922oKQJF+mlkwC +LZnv8ZzHtH54s4VdyQFIBjQF1PPf9PTn+5tid8QJehZPndcoeD7J8fPJMAoGCCqG +SM49BAMCA0kAMEYCIQDFUO0owvqMVRO2FmD+vb8mqJBpWCE6Cl5pEHaygTa5LwIh +ANsmjI2azWiTSFjb7Ou5fnCfbeiJUP0s66m8qS4rYl9L + </ds:X509Certificate> + </ds:X509Data> + </ds:KeyInfo> + </md:KeyDescriptor> + <md:KeyDescriptor use="encryption"> + <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> + <ds:X509Data> + <ds:X509Certificate>MIIC+jCCAeKgAwIBAgIEXjF+fTANBgkqhkiG9w0BAQsFADA/MQswCQYDVQQGEwJB +VDENMAsGA1UEBwwERUdJWjEOMAwGA1UECgwFalVuaXQxETAPBgNVBAMMCE1ldGFk +YXRhMB4XDTIwMDEyOTEyNDU0OVoXDTI2MDEyODEyNDU0OVowPzELMAkGA1UEBhMC +QVQxDTALBgNVBAcMBEVHSVoxDjAMBgNVBAoMBWpVbml0MREwDwYDVQQDDAhNZXRh +ZGF0YTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK230G3dxNbNlSYA +O5Kx/Js0aBAgxMt7q9m+dA35fK/dOvF/GjrqjWsMCnax+no9gLnq6x0gXiJclz6H +rp/YDOfLrJjMpNL/r0FWT947vbnEj7eT8TdY5d6Yi8AZulZmjiCI5nbZh2zwrP4+ +WqRroLoPhXQj8mDyp26M4xHBBUhLMRc2HV4S+XH4uNZ/vTmb8vBg31XGHCY33gl7 +/KA54JNGxJdN8Dxv6yHYsm91ZfVrX39W0iYLUNhUCkolwuQmjDVfrExM8BTLIONb +f+erJoCm3A9ghZyDYRQ/e69/UEUqDa6XOzykr88INkQscEiAXCDS+EBPMpKo+t3l +PIA9r7kCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAh/2mg4S03bdZy1OVtEAudBT9 +YZb9OF34hxPtNbkB/V04wSIg1d4TBr5KDhV7CdiUOxPZzHpS8LUCgfGX306FB6NX +zh/b67uTOPaE72AB4VIT/Np0fsM7k5WhG9k9NoprIGiqCz2lXcfpZiT+LtSO1vWS +YI87wR9KOSWjcw/5i5qZIAJuwvLCQj5JtUsmrhHK75222J3TJf4dS/gfN4xfY2rW +9vcXtH6//8WdWp/zx9V7Z1ZsDb8TDKtBCEGuFDgVeU5ScKtVq8qRoUKD3Ve76cZi +purO3KrRrVAuZP2EfLkZdHEHqe8GPigNnZ5kTn8V2VJ3iRAQ73hpJRR98tFd0A==</ds:X509Certificate> + </ds:X509Data> + </ds:KeyInfo> + </md:KeyDescriptor> + <md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat> + <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/post" index="0" isDefault="true"/> + <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/redirect" index="1"/> + <md:AttributeConsumingService index="0" isDefault="true"> + <md:ServiceName xml:lang="en">Default Service</md:ServiceName> + <md:RequestedAttribute FriendlyName="BPK" Name="urn:oid:1.2.40.0.10.2.1.1.149" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="PRINCIPAL-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.20" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="BIRTHDATE" Name="urn:oid:1.2.40.0.10.2.1.1.55" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="PVP-VERSION" Name="urn:oid:1.2.40.0.10.2.1.1.261.10" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="EID-ISSUING-NATION" Name="urn:oid:1.2.40.0.10.2.1.1.261.32" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-SOURCE-PIN-TYPE" Name="urn:oid:1.2.40.0.10.2.1.1.261.76" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-FULL-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.84" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="MANDATE-TYPE" Name="urn:oid:1.2.40.0.10.2.1.1.261.68" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-SOURCE-PIN" Name="urn:oid:1.2.40.0.10.2.1.1.261.100" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="GIVEN-NAME" Name="urn:oid:2.5.4.42" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="EID-SECTOR-FOR-IDENTIFIER" Name="urn:oid:1.2.40.0.10.2.1.1.261.34" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="MANDATE-TYPE-OID" Name="urn:oid:1.2.40.0.10.2.1.1.261.106" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="EID-IDENTITY-LINK" Name="urn:oid:1.2.40.0.10.2.1.1.261.38" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="EID-CITIZEN-QAA-EIDAS-LEVEL" Name="urn:oid:1.2.40.0.10.2.1.1.261.108" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + </md:AttributeConsumingService> + </md:SPSSODescriptor> + <md:Organization> + <md:OrganizationName xml:lang="de">EGIZ</md:OrganizationName> + <md:OrganizationDisplayName xml:lang="de">E-Government Innovationszentrum</md:OrganizationDisplayName> + <md:OrganizationURL xml:lang="de">http://www.egiz.gv.at</md:OrganizationURL> + </md:Organization> + <md:ContactPerson contactType="technical"> + <md:Company>E-Government Innovationszentrum</md:Company> + <md:GivenName>Lenz</md:GivenName> + <md:SurName>Thomas</md:SurName> + <md:EmailAddress>thomas.lenz@egiz.gv.at</md:EmailAddress> + <md:TelephoneNumber>+43 316 873 5525</md:TelephoneNumber> + </md:ContactPerson> +</md:EntityDescriptor> diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/spring/test_eaaf_core.beans.xml b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/spring/test_eaaf_core.beans.xml new file mode 100644 index 00000000..99552053 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/spring/test_eaaf_core.beans.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:context="http://www.springframework.org/schema/context" + xmlns:tx="http://www.springframework.org/schema/tx" + xmlns:aop="http://www.springframework.org/schema/aop" + xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd + http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> + + <bean id="dummyAuthConfig" + class="at.gv.egiz.eaaf.core.impl.idp.module.test.DummyAuthConfig" /> + + <bean id="dummyVelocityGuiBuilder" + class="at.gv.egiz.eaaf.core.impl.idp.module.gui.DummyVelocityGuiFormBuilder" /> + + <bean id="dummyGuiBuilderConfigFactory" + class="at.gv.egiz.eaaf.core.impl.idp.module.gui.DummyGuiBuilderConfigurationFactory" /> + + <bean id="httpClientFactory" + class="at.gv.egiz.eaaf.core.impl.utils.HttpClientFactory" /> + + <bean id="dummyRevisionLogger" + class="at.gv.egiz.eaaf.core.impl.logging.DummyRevisionsLogger" /> + + <bean id="eaafKeyStoreFactory" + class="at.gv.egiz.eaaf.core.impl.credential.EaafKeyStoreFactory" /> + +</beans>
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/spring/test_eaaf_pvp.beans.xml b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/spring/test_eaaf_pvp.beans.xml new file mode 100644 index 00000000..2bddd629 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_idp/src/test/resources/spring/test_eaaf_pvp.beans.xml @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:context="http://www.springframework.org/schema/context" + xmlns:tx="http://www.springframework.org/schema/tx" + xmlns:aop="http://www.springframework.org/schema/aop" + xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd + http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> + + <import resource="test_eaaf_core.beans.xml"/> + <import resource="classpath:/eaaf_pvp.beans.xml"/> + <import resource="classpath:/eaaf_pvp_idp.beans.xml"/> + + <bean id="dummyCredentialProvider" + class="at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyCredentialProvider" /> + + <bean id="dummyChainingMetadataResolver" + class="at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyMetadataProvider" /> + + <bean id="samlVerificationEngine" + class="at.gv.egiz.eaaf.modules.pvp2.impl.verification.SamlVerificationEngine" /> + + <bean id="dummyLoALevelMapper" + class="at.gv.egiz.eaaf.modules.pvp2.idp.test.dummy.DummyLoALevelMapper" /> + + <bean id="dummySubjectNameIdGenerator" + class="at.gv.egiz.eaaf.modules.pvp2.idp.test.dummy.DummySubjectNameGenerator" /> + + <bean id="dummyPvpBasicConfig" + class="at.gv.egiz.eaaf.modules.pvp2.idp.test.dummy.DummyPvpConfiguration" /> + + <bean id="dummyMetadataConfigFactor" + class="at.gv.egiz.eaaf.modules.pvp2.idp.test.dummy.DummyPvpMetadataConfigFactory" /> + + <bean id="PVPAuthenticationRequestAction" + class="at.gv.egiz.eaaf.modules.pvp2.idp.impl.AuthenticationAction"> + <property name="pvpIdpCredentials" ref="dummyCredentialProvider" /> + </bean> + + <bean id="pvpMetadataService" + class="at.gv.egiz.eaaf.modules.pvp2.idp.impl.MetadataAction" > + <property name="pvpIdpCredentials" ref="dummyCredentialProvider" /> + </bean> + +</beans>
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_pvp2_sp/pom.xml b/eaaf_modules/eaaf_module_pvp2_sp/pom.xml index d2157a45..69eb26ab 100644 --- a/eaaf_modules/eaaf_module_pvp2_sp/pom.xml +++ b/eaaf_modules/eaaf_module_pvp2_sp/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>at.gv.egiz.eaaf</groupId> <artifactId>eaaf_modules</artifactId> - <version>1.0.13.2</version> + <version>1.1.0</version> </parent> <artifactId>eaaf_module_pvp2_sp</artifactId> <name>eaaf_module_pvp2_sp</name> @@ -32,11 +32,23 @@ <scope>provided</scope> </dependency> + <!-- Only for testing --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-test</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>at.gv.egiz.eaaf</groupId> + <artifactId>eaaf_core_utils</artifactId> + <scope>test</scope> + <type>test-jar</type> + </dependency> </dependencies> <build> @@ -54,21 +66,20 @@ </plugin> <!-- enable co-existence of testng and junit --> - <plugin> - <artifactId>maven-surefire-plugin</artifactId> - <version>${surefire.version}</version> - <configuration> - <threadCount>1</threadCount> - <argLine>--add-modules java.xml.bind</argLine> - </configuration> - <dependencies> - <dependency> - <groupId>org.apache.maven.surefire</groupId> - <artifactId>surefire-junit47</artifactId> - <version>${surefire.version}</version> - </dependency> - </dependencies> - </plugin> + <plugin> + <artifactId>maven-surefire-plugin</artifactId> + <version>${surefire.version}</version> + <configuration> + <threadCount>1</threadCount> + </configuration> + <dependencies> + <dependency> + <groupId>org.apache.maven.surefire</groupId> + <artifactId>surefire-junit47</artifactId> + <version>${surefire.version}</version> + </dependency> + </dependencies> + </plugin> </plugins> </build> diff --git a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/Pvp2SProfileSpSpringResourceProvider.java b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/Pvp2SProfileSpSpringResourceProvider.java new file mode 100644 index 00000000..7535e013 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/Pvp2SProfileSpSpringResourceProvider.java @@ -0,0 +1,48 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.sp; + +import at.gv.egiz.components.spring.api.SpringResourceProvider; + +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; + +public class Pvp2SProfileSpSpringResourceProvider implements SpringResourceProvider { + + @Override + public String getName() { + return "EAAF PVP2 S-Profile Service-Provider SpringResourceProvider"; + } + + @Override + public String[] getPackagesToScan() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Resource[] getResourcesToLoad() { + final ClassPathResource sl20AuthConfig = + new ClassPathResource("/eaaf_pvp_sp.beans.xml", Pvp2SProfileSpSpringResourceProvider.class); + + return new Resource[] { sl20AuthConfig }; + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/api/IPVPAuthnRequestBuilderConfiguruation.java b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/api/IPVPAuthnRequestBuilderConfiguruation.java deleted file mode 100644 index b8a8e796..00000000 --- a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/api/IPVPAuthnRequestBuilderConfiguruation.java +++ /dev/null @@ -1,195 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.sp.api; - -import java.util.List; - -import org.opensaml.saml2.core.AuthnContextComparisonTypeEnumeration; -import org.opensaml.saml2.metadata.EntityDescriptor; -import org.opensaml.xml.security.credential.Credential; -import org.w3c.dom.Element; - -import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EAAFRequestedAttribute; - -/** - * @author tlenz - * - */ -public interface IPVPAuthnRequestBuilderConfiguruation { - - /** - * Defines a unique name for this PVP Service-provider, which is used for logging - * - * @return - */ - public String getSPNameForLogging(); - - /** - * If true, the SAML2 isPassive flag is set in the AuthnRequest - * - * @return - */ - public Boolean isPassivRequest(); - - /** - * Define the ID of the AssertionConsumerService, - * which defines the required attributes in service-provider metadata. - * - * @return - */ - public Integer getAssertionConsumerServiceId(); - - /** - * Define the SAML2 EntityID of the service provider. - * - * @return - */ - public String getSPEntityID(); - - /** - * Define the SAML2 NameIDPolicy - * - * @return Service-Provider EntityID, but never null - */ - public String getNameIDPolicyFormat(); - - /** - * Define the AuthnContextClassRefernece of this request - * - * Example: - * http://www.ref.gv.at/ns/names/agiz/pvp/secclass/0-3 - * http://www.stork.gov.eu/1.0/citizenQAALevel/4 - * - * - * @return - */ - public String getAuthnContextClassRef(); - - /** - * Define the AuthnContextComparison model, which should be used - * - * @return - */ - public AuthnContextComparisonTypeEnumeration getAuthnContextComparison(); - - - /** - * Define the credential, which should be used to sign the AuthnRequest - * - * @return - */ - public Credential getAuthnRequestSigningCredential(); - - - /** - * Define the SAML2 EntityDescriptor of the IDP, which should receive the AuthnRequest - * - * @return Credential, but never null. - */ - public EntityDescriptor getIDPEntityDescriptor(); - - /** - * Set the SAML2 NameIDPolicy allow-creation flag - * - * @return EntityDescriptor, but never null. - */ - public boolean getNameIDPolicyAllowCreation(); - - - /** - * Set the requested SubjectNameID - * - * @return SubjectNameID, or null if no SubjectNameID should be used - */ - public String getSubjectNameID(); - - /** - * Define the qualifier of the <code>SubjectNameID</code> - * <br><br> - * Like: 'urn:publicid:gv.at:cdid+BF' - * - * @return qualifier, or null if no qualifier should be set - */ - public String getSubjectNameIDQualifier(); - - /** - * Define the format of the subjectNameID, which is included in authn-request - * - * - * @return nameIDFormat, of SAML2 'transient' if nothing is defined - */ - public String getSubjectNameIDFormat(); - - /** - * Define a SP specific SAML2 requestID - * - * @return requestID, or null if the requestID should be generated automatically - */ - public String getRequestID(); - - /** - * Defines the 'method' attribute in 'SubjectConformation' element - * - * @return method, or null if no method should set - */ - public String getSubjectConformationMethode(); - - /** - * Define the information, which should be added as 'subjectConformationDate' - * in 'SubjectConformation' element - * - * @return subjectConformation information or null if no subjectConformation should be set - */ - public Element getSubjectConformationDate(); - - - /** - * Get the EntityId of the SP in case of a SAML2 proxy use-case - * - * @return - */ - public String getScopeRequesterId(); - - - /** - * Get a FriendlyName for the SP that sends the request - * - * @return - */ - public String getProviderName(); - - - /** - * Get a Set of SAML2 attributes that are requested by using SAML2 requested attributes - * <br> - * <b>Info:</b> Attributes are requested by using eIDAS SAML2 extension for requested attributes - * - * @return - */ - public List<EAAFRequestedAttribute> getRequestedAttributes(); - -} diff --git a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/api/IPvpAuthnRequestBuilderConfiguruation.java b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/api/IPvpAuthnRequestBuilderConfiguruation.java new file mode 100644 index 00000000..597507f3 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/api/IPvpAuthnRequestBuilderConfiguruation.java @@ -0,0 +1,188 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.sp.api; + +import java.util.List; + +import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential; +import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttribute; + +import org.opensaml.saml.saml2.core.AuthnContextComparisonTypeEnumeration; +import org.opensaml.saml.saml2.metadata.EntityDescriptor; +import org.w3c.dom.Element; + +/** + * Configuration of a PVP2 S-Profile authentication-request builder. + * + * @author tlenz + * + */ +public interface IPvpAuthnRequestBuilderConfiguruation { + + /** + * Defines a unique name for this PVP Service-provider, which is used for + * logging. + * + * @return + */ + String getSpNameForLogging(); + + /** + * If true, the SAML2 isPassive flag is set in the AuthnRequest. + * + * @return + */ + Boolean isPassivRequest(); + + /** + * Define the ID of the AssertionConsumerService, which defines the required + * attributes in service-provider metadata. + * + * @return + */ + Integer getAssertionConsumerServiceId(); + + /** + * Define the SAML2 EntityID of the service provider. + * + * @return + */ + String getSpEntityID(); + + /** + * Define the SAML2 NameIDPolicy. + * + * @return Service-Provider EntityID, but never null + */ + String getNameIdPolicyFormat(); + + /** + * Define the AuthnContextClassRefernece of this request. + * + * <p> + * Example: http://www.ref.gv.at/ns/names/agiz/pvp/secclass/0-3 + * http://www.stork.gov.eu/1.0/citizenQAALevel/4 + * </p> + * + * @return + */ + String getAuthnContextClassRef(); + + /** + * Define the AuthnContextComparison model, which should be used. + * + * @return + */ + AuthnContextComparisonTypeEnumeration getAuthnContextComparison(); + + /** + * Define the credential, which should be used to sign the AuthnRequest. + * + * @return + */ + EaafX509Credential getAuthnRequestSigningCredential(); + + /** + * Define the SAML2 EntityDescriptor of the IDP, which should receive the + * AuthnRequest. + * + * @return Credential, but never null. + */ + EntityDescriptor getIdpEntityDescriptor(); + + /** + * Set the SAML2 NameIDPolicy allow-creation flag. + * + * @return EntityDescriptor, but never null. + */ + boolean getNameIdPolicyAllowCreation(); + + /** + * Set the requested SubjectNameID. + * + * @return SubjectNameID, or null if no SubjectNameID should be used + */ + String getSubjectNameID(); + + /** + * Define the qualifier of the <code>SubjectNameID</code> <br> + * <br> + * Like: 'urn:publicid:gv.at:cdid+BF' + * + * @return qualifier, or null if no qualifier should be set + */ + String getSubjectNameIdQualifier(); + + /** + * Define the format of the subjectNameID, which is included in authn-request. + * + * + * @return nameIDFormat, of SAML2 'transient' if nothing is defined + */ + String getSubjectNameIdFormat(); + + /** + * Define a SP specific SAML2 requestID. + * + * @return requestID, or null if the requestID should be generated automatically + */ + String getRequestID(); + + /** + * Defines the 'method' attribute in 'SubjectConformation' element. + * + * @return method, or null if no method should set + */ + String getSubjectConformationMethode(); + + /** + * Define the information, which should be added as 'subjectConformationDate' in + * 'SubjectConformation' element. + * + * @return subjectConformation information or null if no subjectConformation + * should be set + */ + Element getSubjectConformationDate(); + + /** + * Get the EntityId of the SP in case of a SAML2 proxy use-case. + * + * @return + */ + String getScopeRequesterId(); + + /** + * Get a FriendlyName for the SP that sends the request. + * + * @return + */ + String getProviderName(); + + /** + * Get a Set of SAML2 attributes that are requested by using SAML2 requested + * attributes. <br> + * <b>Info:</b> Attributes are requested by using eIDAS SAML2 extension for + * requested attributes + * + * @return + */ + List<EaafRequestedAttribute> getRequestedAttributes(); + +} diff --git a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AssertionAttributeExtractorExeption.java b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AssertionAttributeExtractorExeption.java index 3afcc65d..4411d9c6 100644 --- a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AssertionAttributeExtractorExeption.java +++ b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AssertionAttributeExtractorExeption.java @@ -1,56 +1,40 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 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: + * Licensed under the EUPL, Version 1.2 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: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * 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. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * 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.egiz.eaaf.modules.pvp2.sp.exception; -import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; -/** - * @author tlenz - * - */ -public class AssertionAttributeExtractorExeption extends PVP2Exception { - - /** - * - */ - private static final long serialVersionUID = -6459000942830951492L; - - public AssertionAttributeExtractorExeption(String attributeName) { - super("Parse PVP2.1 assertion FAILED: Attribute " + attributeName - + " can not extract.", null); - } - - public AssertionAttributeExtractorExeption(String messageId, - Object[] parameters) { - super(messageId, parameters); - } - - public AssertionAttributeExtractorExeption() { - super("Parse PVP2.1 assertion FAILED. Interfederation not possible", null); - } +public class AssertionAttributeExtractorExeption extends Pvp2Exception { + + private static final long serialVersionUID = -6459000942830951492L; + + public AssertionAttributeExtractorExeption(final String attributeName) { + super("Parse PVP2.1 assertion FAILED: Attribute " + attributeName + " can not extract.", null); + } + + public AssertionAttributeExtractorExeption(final String messageId, final Object[] parameters) { + super(messageId, parameters); + } + + public AssertionAttributeExtractorExeption() { + super("Parse PVP2.1 assertion FAILED. Interfederation not possible", null); + } } diff --git a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AssertionValidationExeption.java b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AssertionValidationExeption.java index 5766aab0..03fae599 100644 --- a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AssertionValidationExeption.java +++ b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AssertionValidationExeption.java @@ -1,53 +1,37 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 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: + * Licensed under the EUPL, Version 1.2 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: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * 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. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * 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.egiz.eaaf.modules.pvp2.sp.exception; -import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; -/** - * @author tlenz - * - */ -public class AssertionValidationExeption extends PVP2Exception { +public class AssertionValidationExeption extends Pvp2Exception { - private static final long serialVersionUID = -3987805399122286259L; + private static final long serialVersionUID = -3987805399122286259L; - public AssertionValidationExeption(String messageId, Object[] parameters) { - super(messageId, parameters); - } + public AssertionValidationExeption(final String messageId, final Object[] parameters) { + super(messageId, parameters); + } - /** - * @param string - * @param object - * @param e - */ - public AssertionValidationExeption(String string, Object[] parameters, - Throwable e) { - super(string, parameters, e); - } + public AssertionValidationExeption(final String string, final Object[] parameters, + final Throwable e) { + super(string, parameters, e); + } } diff --git a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AuthnRequestBuildException.java b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AuthnRequestBuildException.java index 9fdffaf4..251ba759 100644 --- a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AuthnRequestBuildException.java +++ b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AuthnRequestBuildException.java @@ -1,53 +1,35 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 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: + * Licensed under the EUPL, Version 1.2 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: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * 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. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * 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.egiz.eaaf.modules.pvp2.sp.exception; -import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; -/** - * @author tlenz - * - */ -public class AuthnRequestBuildException extends PVP2Exception { +public class AuthnRequestBuildException extends Pvp2Exception { - /** - * - */ - private static final long serialVersionUID = -1375451065455859354L; + private static final long serialVersionUID = -1375451065455859354L; - /** - * @param messageId - * @param parameters - */ - public AuthnRequestBuildException(String messageId, Object[] parameters) { - super(messageId, parameters); - } + public AuthnRequestBuildException(final String messageId, final Object[] parameters) { + super(messageId, parameters); + } - public AuthnRequestBuildException(String messageId, Object[] parameters, Throwable e) { - super(messageId, parameters, e); - } + public AuthnRequestBuildException(final String messageId, final Object[] parameters, final Throwable e) { + super(messageId, parameters, e); + } } diff --git a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AuthnResponseValidationException.java b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AuthnResponseValidationException.java index 9d2ec046..44fbf40f 100644 --- a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AuthnResponseValidationException.java +++ b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/exception/AuthnResponseValidationException.java @@ -1,54 +1,37 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 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: + * Licensed under the EUPL, Version 1.2 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: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * 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. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * 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.egiz.eaaf.modules.pvp2.sp.exception; -import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; -/** - * @author tlenz - * - */ -public class AuthnResponseValidationException extends PVP2Exception { +public class AuthnResponseValidationException extends Pvp2Exception { + + private static final long serialVersionUID = 8023812861029406575L; - /** - * - */ - private static final long serialVersionUID = 8023812861029406575L; + public AuthnResponseValidationException(final String messageId, final Object[] parameters) { + super(messageId, parameters); + } - /** - * @param messageId - * @param parameters - */ - public AuthnResponseValidationException(String messageId, Object[] parameters) { - super(messageId, parameters); - } - - public AuthnResponseValidationException(String messageId, Object[] parameters, Throwable e) { - super(messageId, parameters, e); - } + public AuthnResponseValidationException(final String messageId, final Object[] parameters, + final Throwable e) { + super(messageId, parameters, e); + } } diff --git a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/PVPAuthnRequestBuilder.java b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/PVPAuthnRequestBuilder.java deleted file mode 100644 index e8cdd1f7..00000000 --- a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/PVPAuthnRequestBuilder.java +++ /dev/null @@ -1,259 +0,0 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 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: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * 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.egiz.eaaf.modules.pvp2.sp.impl; - -import java.security.NoSuchAlgorithmException; -import java.util.List; - -import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.lang3.StringUtils; -import org.joda.time.DateTime; -import org.opensaml.common.impl.SecureRandomIdentifierGenerator; -import org.opensaml.common.xml.SAMLConstants; -import org.opensaml.saml2.common.Extensions; -import org.opensaml.saml2.core.AuthnContextClassRef; -import org.opensaml.saml2.core.AuthnContextComparisonTypeEnumeration; -import org.opensaml.saml2.core.AuthnRequest; -import org.opensaml.saml2.core.Issuer; -import org.opensaml.saml2.core.NameID; -import org.opensaml.saml2.core.NameIDPolicy; -import org.opensaml.saml2.core.NameIDType; -import org.opensaml.saml2.core.RequestedAuthnContext; -import org.opensaml.saml2.core.RequesterID; -import org.opensaml.saml2.core.Scoping; -import org.opensaml.saml2.core.Subject; -import org.opensaml.saml2.core.SubjectConfirmation; -import org.opensaml.saml2.core.SubjectConfirmationData; -import org.opensaml.saml2.metadata.EntityDescriptor; -import org.opensaml.saml2.metadata.SingleSignOnService; -import org.opensaml.ws.message.encoder.MessageEncodingException; -import org.opensaml.xml.security.SecurityException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationContext; -import org.springframework.stereotype.Service; - -import at.gv.egiz.eaaf.core.api.IRequest; -import at.gv.egiz.eaaf.modules.pvp2.api.binding.IEncoder; -import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EAAFRequestedAttribute; -import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EAAFRequestedAttributes; -import at.gv.egiz.eaaf.modules.pvp2.exception.PVP2Exception; -import at.gv.egiz.eaaf.modules.pvp2.impl.binding.PostBinding; -import at.gv.egiz.eaaf.modules.pvp2.impl.binding.RedirectBinding; -import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EAAFRequestExtensionBuilder; -import at.gv.egiz.eaaf.modules.pvp2.impl.utils.SAML2Utils; -import at.gv.egiz.eaaf.modules.pvp2.sp.api.IPVPAuthnRequestBuilderConfiguruation; -import at.gv.egiz.eaaf.modules.pvp2.sp.exception.AuthnRequestBuildException; - -/** - * @author tlenz - * - */ -@Service("pvpAuthnRequestBuilder") -public class PVPAuthnRequestBuilder { - private static final Logger log = LoggerFactory.getLogger(PVPAuthnRequestBuilder.class); - - - @Autowired(required=true) ApplicationContext springContext; - - - /** - * Build a PVP2.x specific authentication request - * - * @param pendingReq Currently processed pendingRequest - * @param config AuthnRequest builder configuration, never null - * @param idpEntity SAML2 EntityDescriptor of the IDP, which receive this AuthnRequest, never null - * @param httpResp - * @throws NoSuchAlgorithmException - * @throws SecurityException - * @throws PVP2Exception - * @throws MessageEncodingException - */ - public void buildAuthnRequest(IRequest pendingReq, IPVPAuthnRequestBuilderConfiguruation config, - HttpServletResponse httpResp) throws NoSuchAlgorithmException, MessageEncodingException, PVP2Exception, SecurityException { - //get IDP Entity element from config - EntityDescriptor idpEntity = config.getIDPEntityDescriptor(); - - AuthnRequest authReq = SAML2Utils - .createSAMLObject(AuthnRequest.class); - - //select SingleSignOn Service endpoint from IDP metadata - SingleSignOnService endpoint = null; - for (SingleSignOnService sss : - idpEntity.getIDPSSODescriptor(SAMLConstants.SAML20P_NS).getSingleSignOnServices()) { - - // use POST binding as default if it exists - if (sss.getBinding().equals(SAMLConstants.SAML2_POST_BINDING_URI)) { - endpoint = sss; - - } else if ( sss.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI) - && endpoint == null ) - endpoint = sss; - - } - - if (endpoint == null) { - log.warn("Building AuthnRequest FAILED: > Requested IDP " + idpEntity.getEntityID() - + " does not support POST or Redirect Binding."); - throw new AuthnRequestBuildException("sp.pvp2.00", new Object[]{config.getSPNameForLogging(), idpEntity.getEntityID()}); - - } else - authReq.setDestination(endpoint.getLocation()); - - - //set basic AuthnRequest information - String reqID = config.getRequestID(); - if (StringUtils.isNotEmpty(reqID)) - authReq.setID(reqID); - - else { - SecureRandomIdentifierGenerator gen = new SecureRandomIdentifierGenerator(); - authReq.setID(gen.generateIdentifier()); - - } - - authReq.setIssueInstant(new DateTime()); - - //set isPassive flag - if (config.isPassivRequest() == null) - authReq.setIsPassive(false); - else - authReq.setIsPassive(config.isPassivRequest()); - - //set EntityID of the service provider - Issuer issuer = SAML2Utils.createSAMLObject(Issuer.class); - issuer.setFormat(NameIDType.ENTITY); - issuer.setValue(config.getSPEntityID()); - authReq.setIssuer(issuer); - - //set AssertionConsumerService ID - if (config.getAssertionConsumerServiceId() != null) - authReq.setAssertionConsumerServiceIndex(config.getAssertionConsumerServiceId()); - - //set NameIDPolicy - if (config.getNameIDPolicyFormat() != null) { - NameIDPolicy policy = SAML2Utils.createSAMLObject(NameIDPolicy.class); - policy.setAllowCreate(config.getNameIDPolicyAllowCreation()); - policy.setFormat(config.getNameIDPolicyFormat()); - authReq.setNameIDPolicy(policy); - } - - //set requested QAA level - if (config.getAuthnContextClassRef() != null) { - RequestedAuthnContext reqAuthContext = SAML2Utils.createSAMLObject(RequestedAuthnContext.class); - AuthnContextClassRef authnClassRef = SAML2Utils.createSAMLObject(AuthnContextClassRef.class); - - authnClassRef.setAuthnContextClassRef(config.getAuthnContextClassRef()); - - if (config.getAuthnContextComparison() == null) - reqAuthContext.setComparison(AuthnContextComparisonTypeEnumeration.MINIMUM); - else - reqAuthContext.setComparison(config.getAuthnContextComparison()); - - reqAuthContext.getAuthnContextClassRefs().add(authnClassRef); - authReq.setRequestedAuthnContext(reqAuthContext); - } - - //set request Subject element - if (StringUtils.isNotEmpty(config.getSubjectNameID())) { - Subject reqSubject = SAML2Utils.createSAMLObject(Subject.class); - NameID subjectNameID = SAML2Utils.createSAMLObject(NameID.class); - - subjectNameID.setValue(config.getSubjectNameID()); - if (StringUtils.isNotEmpty(config.getSubjectNameIDQualifier())) - subjectNameID.setNameQualifier(config.getSubjectNameIDQualifier()); - - if (StringUtils.isNotEmpty(config.getSubjectNameIDFormat())) - subjectNameID.setFormat(config.getSubjectNameIDFormat()); - else - subjectNameID.setFormat(NameID.TRANSIENT); - - reqSubject.setNameID(subjectNameID); - - if (config.getSubjectConformationDate() != null) { - SubjectConfirmation subjectConformation = SAML2Utils.createSAMLObject(SubjectConfirmation.class); - SubjectConfirmationData subjectConformDate = SAML2Utils.createSAMLObject(SubjectConfirmationData.class); - subjectConformation.setSubjectConfirmationData(subjectConformDate); - reqSubject.getSubjectConfirmations().add(subjectConformation ); - - if (config.getSubjectConformationMethode() != null) - subjectConformation.setMethod(config.getSubjectConformationMethode()); - - subjectConformDate.setDOM(config.getSubjectConformationDate()); - - } - - authReq.setSubject(reqSubject ); - - } - - - //set ProviderName - if (StringUtils.isNotEmpty(config.getProviderName())) - authReq.setProviderName(config.getProviderName()); - - //set RequesterId in case of proxy mode - if (StringUtils.isNotEmpty(config.getScopeRequesterId())) { - Scoping scope = SAML2Utils.createSAMLObject(Scoping.class); - RequesterID requesterId = SAML2Utils.createSAMLObject(RequesterID.class); - requesterId.setRequesterID(config.getScopeRequesterId()); - scope.getRequesterIDs().add(requesterId ); - authReq.setScoping(scope ); - - } - - //add optional requested attributes - if (config.getRequestedAttributes() != null) { - List<EAAFRequestedAttribute> reqAttr = config.getRequestedAttributes(); - Extensions extenstions = new EAAFRequestExtensionBuilder().buildObject(); - EAAFRequestedAttributes reqAttributs = SAML2Utils.createSAMLObject(EAAFRequestedAttributes.class); - reqAttributs.getAttributes().addAll(reqAttr); - extenstions.getUnknownXMLObjects().add(reqAttributs); - authReq.setExtensions(extenstions ); - - } - - //select message encoder - IEncoder binding = null; - if (endpoint.getBinding().equals( - SAMLConstants.SAML2_REDIRECT_BINDING_URI)) { - binding = springContext.getBean("PVPRedirectBinding", RedirectBinding.class); - - } else if (endpoint.getBinding().equals( - SAMLConstants.SAML2_POST_BINDING_URI)) { - binding = springContext.getBean("PVPPOSTBinding", PostBinding.class); - - } - - //encode message - binding.encodeRequest(null, httpResp, authReq, - endpoint.getLocation(), pendingReq.getPendingRequestId(), config.getAuthnRequestSigningCredential(), pendingReq); - } - -} diff --git a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/PvpAuthnRequestBuilder.java b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/PvpAuthnRequestBuilder.java new file mode 100644 index 00000000..752386a0 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/PvpAuthnRequestBuilder.java @@ -0,0 +1,265 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 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: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * 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.egiz.eaaf.modules.pvp2.sp.impl; + +import java.security.NoSuchAlgorithmException; +import java.util.List; + +import javax.servlet.http.HttpServletResponse; + +import at.gv.egiz.eaaf.core.api.IRequest; +import at.gv.egiz.eaaf.modules.pvp2.api.binding.IEncoder; +import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttribute; +import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttributes; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; +import at.gv.egiz.eaaf.modules.pvp2.impl.binding.PostBinding; +import at.gv.egiz.eaaf.modules.pvp2.impl.binding.RedirectBinding; +import at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr.EaafRequestExtensionBuilder; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils; +import at.gv.egiz.eaaf.modules.pvp2.sp.api.IPvpAuthnRequestBuilderConfiguruation; +import at.gv.egiz.eaaf.modules.pvp2.sp.exception.AuthnRequestBuildException; + +import org.apache.commons.lang3.StringUtils; +import org.joda.time.DateTime; +import org.opensaml.messaging.encoder.MessageEncodingException; +import org.opensaml.saml.common.xml.SAMLConstants; +import org.opensaml.saml.saml2.core.AuthnContextClassRef; +import org.opensaml.saml.saml2.core.AuthnContextComparisonTypeEnumeration; +import org.opensaml.saml.saml2.core.AuthnRequest; +import org.opensaml.saml.saml2.core.Extensions; +import org.opensaml.saml.saml2.core.Issuer; +import org.opensaml.saml.saml2.core.NameID; +import org.opensaml.saml.saml2.core.NameIDPolicy; +import org.opensaml.saml.saml2.core.NameIDType; +import org.opensaml.saml.saml2.core.RequestedAuthnContext; +import org.opensaml.saml.saml2.core.RequesterID; +import org.opensaml.saml.saml2.core.Scoping; +import org.opensaml.saml.saml2.core.Subject; +import org.opensaml.saml.saml2.core.SubjectConfirmation; +import org.opensaml.saml.saml2.core.SubjectConfirmationData; +import org.opensaml.saml.saml2.metadata.EntityDescriptor; +import org.opensaml.saml.saml2.metadata.SingleSignOnService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; + +import net.shibboleth.utilities.java.support.security.SecureRandomIdentifierGenerationStrategy; + +/** + * PVP2 S-Profil Authentication-Request builder-implementation. + * + * @author tlenz + * + */ +public class PvpAuthnRequestBuilder { + private static final Logger log = LoggerFactory.getLogger(PvpAuthnRequestBuilder.class); + + @Autowired(required = true) + ApplicationContext springContext; + + /** + * Build a PVP2.x specific authentication request + * + * @param pendingReq Currently processed pendingRequest + * @param config AuthnRequest builder configuration, never null + * @param httpResp http response object + * @throws NoSuchAlgorithmException In case of error + * @throws SecurityException In case of error + * @throws Pvp2Exception In case of error + * @throws MessageEncodingException In case of error + */ + public void buildAuthnRequest(final IRequest pendingReq, + final IPvpAuthnRequestBuilderConfiguruation config, final HttpServletResponse httpResp) + throws NoSuchAlgorithmException, MessageEncodingException, Pvp2Exception, SecurityException { + // get IDP Entity element from config + final EntityDescriptor idpEntity = config.getIdpEntityDescriptor(); + + final AuthnRequest authReq = Saml2Utils.createSamlObject(AuthnRequest.class); + + // select SingleSignOn Service endpoint from IDP metadata + SingleSignOnService endpoint = null; + for (final SingleSignOnService sss : idpEntity.getIDPSSODescriptor(SAMLConstants.SAML20P_NS) + .getSingleSignOnServices()) { + + // use POST binding as default if it exists + if (sss.getBinding().equals(SAMLConstants.SAML2_POST_BINDING_URI)) { + endpoint = sss; + + } else if (sss.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI) + && endpoint == null) { + endpoint = sss; + } + + } + + if (endpoint == null) { + log.warn("Building AuthnRequest FAILED: > Requested IDP " + idpEntity.getEntityID() + + " does not support POST or Redirect Binding."); + throw new AuthnRequestBuildException("sp.pvp2.00", + new Object[] { config.getSpNameForLogging(), idpEntity.getEntityID() }); + + } else { + authReq.setDestination(endpoint.getLocation()); + } + + // set basic AuthnRequest information + final String reqID = config.getRequestID(); + if (StringUtils.isNotEmpty(reqID)) { + authReq.setID(reqID); + } else { + final SecureRandomIdentifierGenerationStrategy gen = new SecureRandomIdentifierGenerationStrategy(); + authReq.setID(gen.generateIdentifier()); + + } + + authReq.setIssueInstant(new DateTime()); + + // set isPassive flag + if (config.isPassivRequest() == null) { + authReq.setIsPassive(false); + } else { + authReq.setIsPassive(config.isPassivRequest()); + } + + // set EntityID of the service provider + final Issuer issuer = Saml2Utils.createSamlObject(Issuer.class); + issuer.setFormat(NameIDType.ENTITY); + issuer.setValue(config.getSpEntityID()); + authReq.setIssuer(issuer); + + // set AssertionConsumerService ID + if (config.getAssertionConsumerServiceId() != null) { + authReq.setAssertionConsumerServiceIndex(config.getAssertionConsumerServiceId()); + } + + // set NameIDPolicy + if (config.getNameIdPolicyFormat() != null) { + final NameIDPolicy policy = Saml2Utils.createSamlObject(NameIDPolicy.class); + policy.setAllowCreate(config.getNameIdPolicyAllowCreation()); + policy.setFormat(config.getNameIdPolicyFormat()); + authReq.setNameIDPolicy(policy); + } + + // set requested QAA level + if (config.getAuthnContextClassRef() != null) { + final RequestedAuthnContext reqAuthContext = + Saml2Utils.createSamlObject(RequestedAuthnContext.class); + final AuthnContextClassRef authnClassRef = + Saml2Utils.createSamlObject(AuthnContextClassRef.class); + + authnClassRef.setAuthnContextClassRef(config.getAuthnContextClassRef()); + + if (config.getAuthnContextComparison() == null) { + reqAuthContext.setComparison(AuthnContextComparisonTypeEnumeration.MINIMUM); + } else { + reqAuthContext.setComparison(config.getAuthnContextComparison()); + } + + reqAuthContext.getAuthnContextClassRefs().add(authnClassRef); + authReq.setRequestedAuthnContext(reqAuthContext); + } + + // set request Subject element + if (StringUtils.isNotEmpty(config.getSubjectNameID())) { + final Subject reqSubject = Saml2Utils.createSamlObject(Subject.class); + final NameID subjectNameID = Saml2Utils.createSamlObject(NameID.class); + + subjectNameID.setValue(config.getSubjectNameID()); + if (StringUtils.isNotEmpty(config.getSubjectNameIdQualifier())) { + subjectNameID.setNameQualifier(config.getSubjectNameIdQualifier()); + } + + if (StringUtils.isNotEmpty(config.getSubjectNameIdFormat())) { + subjectNameID.setFormat(config.getSubjectNameIdFormat()); + } else { + subjectNameID.setFormat(NameIDType.TRANSIENT); + } + + reqSubject.setNameID(subjectNameID); + + if (config.getSubjectConformationDate() != null) { + final SubjectConfirmation subjectConformation = + Saml2Utils.createSamlObject(SubjectConfirmation.class); + final SubjectConfirmationData subjectConformDate = + Saml2Utils.createSamlObject(SubjectConfirmationData.class); + subjectConformation.setSubjectConfirmationData(subjectConformDate); + reqSubject.getSubjectConfirmations().add(subjectConformation); + + if (config.getSubjectConformationMethode() != null) { + subjectConformation.setMethod(config.getSubjectConformationMethode()); + } + + subjectConformDate.setDOM(config.getSubjectConformationDate()); + + } + + authReq.setSubject(reqSubject); + + } + + // set ProviderName + if (StringUtils.isNotEmpty(config.getProviderName())) { + authReq.setProviderName(config.getProviderName()); + } + + // set RequesterId in case of proxy mode + if (StringUtils.isNotEmpty(config.getScopeRequesterId())) { + final Scoping scope = Saml2Utils.createSamlObject(Scoping.class); + final RequesterID requesterId = Saml2Utils.createSamlObject(RequesterID.class); + requesterId.setRequesterID(config.getScopeRequesterId()); + scope.getRequesterIDs().add(requesterId); + authReq.setScoping(scope); + + } + + // add optional requested attributes + if (config.getRequestedAttributes() != null) { + final List<EaafRequestedAttribute> reqAttr = config.getRequestedAttributes(); + final Extensions extenstions = new EaafRequestExtensionBuilder().buildObject(); + final EaafRequestedAttributes reqAttributs = + Saml2Utils.createSamlObject(EaafRequestedAttributes.class); + reqAttributs.getAttributes().addAll(reqAttr); + extenstions.getUnknownXMLObjects().add(reqAttributs); + authReq.setExtensions(extenstions); + + } + + // select message encoder + IEncoder binding = null; + if (endpoint.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI)) { + binding = springContext.getBean("PvpRedirectBinding", RedirectBinding.class); + + } else if (endpoint.getBinding().equals(SAMLConstants.SAML2_POST_BINDING_URI)) { + binding = springContext.getBean("PvpPostBinding", PostBinding.class); + + } else { + log.warn("Binding: {} is not supported", endpoint.getBinding()); + throw new AuthnRequestBuildException("sp.pvp2.00", + new Object[] { config.getSpNameForLogging(), idpEntity.getEntityID() }); + + } + + // encode message + binding.encodeRequest(null, httpResp, authReq, endpoint.getLocation(), + pendingReq.getPendingRequestId(), config.getAuthnRequestSigningCredential(), pendingReq); + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/logging/PvpSpModuleMessageSource.java b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/logging/PvpSpModuleMessageSource.java new file mode 100644 index 00000000..7fbd2daf --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/logging/PvpSpModuleMessageSource.java @@ -0,0 +1,16 @@ +package at.gv.egiz.eaaf.modules.pvp2.sp.impl.logging; + +import java.util.Arrays; +import java.util.List; + +import at.gv.egiz.eaaf.core.api.logging.IMessageSourceLocation; + +public class PvpSpModuleMessageSource implements IMessageSourceLocation { + + @Override + public List<String> getMessageSourceLocation() { + return Arrays.asList("classpath:messages/pvp_sp_messages"); + + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/utils/AssertionAttributeExtractor.java b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/utils/AssertionAttributeExtractor.java index 22f1cb06..b12a5913 100644 --- a/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/utils/AssertionAttributeExtractor.java +++ b/eaaf_modules/eaaf_module_pvp2_sp/src/main/java/at/gv/egiz/eaaf/modules/pvp2/sp/impl/utils/AssertionAttributeExtractor.java @@ -1,29 +1,22 @@ -/******************************************************************************* - * Copyright 2017 Graz University of Technology - * EAAF-Core Components has been developed in a cooperation between EGIZ, - * A-SIT Plus, A-SIT, and Graz University of Technology. +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. * - * Licensed under the EUPL, Version 1.2 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: + * Licensed under the EUPL, Version 1.2 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: * https://joinup.ec.europa.eu/news/understanding-eupl-v12 * - * 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. - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ -/******************************************************************************* - *******************************************************************************/ + * 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.egiz.eaaf.modules.pvp2.sp.impl.utils; import java.util.ArrayList; @@ -35,308 +28,346 @@ import java.util.List; import java.util.Map; import java.util.Set; +import at.gv.egiz.eaaf.core.api.data.ExtendedPvpAttributeDefinitions; +import at.gv.egiz.eaaf.modules.pvp2.PvpConstants; +import at.gv.egiz.eaaf.modules.pvp2.sp.exception.AssertionAttributeExtractorExeption; + import org.apache.commons.lang3.StringUtils; -import org.opensaml.saml2.core.Assertion; -import org.opensaml.saml2.core.Attribute; -import org.opensaml.saml2.core.AttributeStatement; -import org.opensaml.saml2.core.AuthnContextClassRef; -import org.opensaml.saml2.core.AuthnStatement; -import org.opensaml.saml2.core.Response; -import org.opensaml.saml2.core.StatusResponseType; -import org.opensaml.saml2.core.Subject; -import org.opensaml.xml.XMLObject; +import org.opensaml.core.xml.XMLObject; +import org.opensaml.saml.saml2.core.Assertion; +import org.opensaml.saml.saml2.core.Attribute; +import org.opensaml.saml.saml2.core.AttributeStatement; +import org.opensaml.saml.saml2.core.AuthnContextClassRef; +import org.opensaml.saml.saml2.core.AuthnStatement; +import org.opensaml.saml.saml2.core.Response; +import org.opensaml.saml.saml2.core.StatusResponseType; +import org.opensaml.saml.saml2.core.Subject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import at.gv.egiz.eaaf.modules.pvp2.PVPConstants; -import at.gv.egiz.eaaf.modules.pvp2.sp.exception.AssertionAttributeExtractorExeption; - public class AssertionAttributeExtractor { - - private static final Logger log = LoggerFactory.getLogger(AssertionAttributeExtractor.class); - - private Assertion assertion = null; - private Map<String, List<String>> attributs = new HashMap<String, List<String>>(); - //private PersonalAttributeList storkAttributes = new PersonalAttributeList(); - - private final List<String> minimalMDSAttributeNamesList = Arrays.asList( - PVPConstants.PRINCIPAL_NAME_NAME, - PVPConstants.GIVEN_NAME_NAME, - PVPConstants.BIRTHDATE_NAME, - PVPConstants.BPK_NAME); - - private final List<String> minimalIDLAttributeNamesList = Arrays.asList( - PVPConstants.EID_IDENTITY_LINK_NAME, - PVPConstants.EID_SOURCE_PIN_NAME, - PVPConstants.EID_SOURCE_PIN_TYPE_NAME); - - /** - * Parse the SAML2 Response element and extracts included information - * <br><br> - * <b>INFO:</b> Actually, only the first SAML2 Assertion of the SAML2 Response is used! - * - * @param samlResponse SAML2 Response - * @throws AssertionAttributeExtractorExeption - */ - public AssertionAttributeExtractor(StatusResponseType samlResponse) throws AssertionAttributeExtractorExeption { - if (samlResponse != null && samlResponse instanceof Response) { - List<Assertion> assertions = ((Response) samlResponse).getAssertions(); - if (assertions.size() == 0) - throw new AssertionAttributeExtractorExeption("Assertion"); - - else if (assertions.size() > 1) - log.warn("Found more then ONE PVP2.1 assertions. Only the First is used."); - - assertion = assertions.get(0); - internalInitialize(); - - } else - throw new AssertionAttributeExtractorExeption(); - } - - /** - * Parse the SAML2 Assertion element and extracts included information - * <br><br> - * - * @param assertion SAML2 Assertion - * @throws AssertionAttributeExtractorExeption - */ - public AssertionAttributeExtractor(Assertion assertion) throws AssertionAttributeExtractorExeption { - this.assertion = assertion; - internalInitialize(); - - } - - /** - * Get all SAML2 attributes from first SAML2 AttributeStatement element - * - * @return List of SAML2 Attributes - */ - public List<Attribute> getAllResponseAttributesFromFirstAttributeStatement() { - return assertion.getAttributeStatements().get(0).getAttributes(); - - } - - /** - * Get all SAML2 attributes of specific SAML2 AttributeStatement element - * - * @param attrStatementID List ID of the AttributeStatement element - * @return List of SAML2 Attributes - */ - public List<Attribute> getAllResponseAttributes(int attrStatementID) { - return assertion.getAttributeStatements().get(attrStatementID).getAttributes(); - - } - - /** - * check attributes from assertion with minimal required attribute list - * @return - */ - public boolean containsAllRequiredAttributes() { - return containsAllRequiredAttributes(minimalMDSAttributeNamesList) - || containsAllRequiredAttributes(minimalIDLAttributeNamesList); - - } - - /** - * check attributes from assertion with attributeNameList - * bPK or enc_bPK are always needed - * - * @param List of attributes which are required - * - * @return - */ - public boolean containsAllRequiredAttributes(Collection<String> attributeNameList) { - - //first check if a bPK or an encrypted bPK is available - boolean flag = true; - for (String attr : attributeNameList) { - if (!attributs.containsKey(attr)) { - flag = false; - log.debug("Assertion contains no Attribute " + attr); - - } - - } - - if (flag) - return flag; - - else { - log.debug("Assertion contains no all minimum attributes from: " + attributeNameList.toString()); - return false; - - } - } - - public boolean containsAttribute(String attributeName) { - return attributs.containsKey(attributeName); - - } - - public String getSingleAttributeValue(String attributeName) { - if (attributs.containsKey(attributeName) && attributs.get(attributeName).size() > 0) - return attributs.get(attributeName).get(0); - else - return null; - - } - - public List<String> getAttributeValues(String attributeName) { - return attributs.get(attributeName); - - } - - /** - * Return all include PVP attribute names - * - * @return - */ - public Set<String> getAllIncludeAttributeNames() { - return attributs.keySet(); - - } - -// public PersonalAttributeList getSTORKAttributes() { -// return storkAttributes; -// } - - - public String getNameID() throws AssertionAttributeExtractorExeption { - if (assertion.getSubject() != null) { - Subject subject = assertion.getSubject(); - - if (subject.getNameID() != null) { - if (StringUtils.isNotEmpty(subject.getNameID().getValue())) - return subject.getNameID().getValue(); - - else - log.error("SAML2 NameID Element is empty."); - } - } - - throw new AssertionAttributeExtractorExeption("nameID"); - } - - /** - * Get the Id attribute from SAML2 assertion - * - * @return - */ - public String getAssertionID() { - return assertion.getID(); - - } - - public String getSessionIndex() throws AssertionAttributeExtractorExeption { - AuthnStatement authn = getAuthnStatement(); - - if (StringUtils.isNotEmpty(authn.getSessionIndex())) - return authn.getSessionIndex(); - - else - throw new AssertionAttributeExtractorExeption("SessionIndex"); - } - - /** - * @return - * @throws AssertionAttributeExtractorExeption - */ - public String getQAALevel() throws AssertionAttributeExtractorExeption { - AuthnStatement authn = getAuthnStatement(); - if (authn.getAuthnContext() != null && authn.getAuthnContext().getAuthnContextClassRef() != null) { - AuthnContextClassRef qaaClass = authn.getAuthnContext().getAuthnContextClassRef(); - - if (StringUtils.isNotEmpty(qaaClass.getAuthnContextClassRef())) - return qaaClass.getAuthnContextClassRef(); - - else - throw new AssertionAttributeExtractorExeption("AuthnContextClassRef (QAALevel)"); - } - - throw new AssertionAttributeExtractorExeption("AuthnContextClassRef"); - } - - public Assertion getFullAssertion() { - return assertion; - } - - - /** - * Get the Assertion validTo period - * - * Primarily, the 'SessionNotOnOrAfter' attribute in the SAML2 'AuthnStatment' element is used. - * If this is empty, this method returns value of SAML 'Conditions' element. - * - * @return Date, until this SAML2 assertion is valid - */ - public Date getAssertionNotOnOrAfter() { - if (getFullAssertion().getAuthnStatements() != null - && getFullAssertion().getAuthnStatements().size() > 0) { - for (AuthnStatement el : getFullAssertion().getAuthnStatements()) { - if (el.getSessionNotOnOrAfter() != null) - return (el.getSessionNotOnOrAfter().toDate()); - } - - } - - return getFullAssertion().getConditions().getNotOnOrAfter().toDate(); - - } - - /** - * Get the Assertion validFrom period - * - * This method returns value of SAML 'Conditions' element. - * - * @return Date, after this SAML2 assertion is valid, otherwise null - */ - public Date getAssertionNotBefore() { - try { - return getFullAssertion().getConditions().getNotBefore().toDate(); - - } catch (NullPointerException e) { - return null; - - } - - } - - private AuthnStatement getAuthnStatement() throws AssertionAttributeExtractorExeption { - List<AuthnStatement> authnList = assertion.getAuthnStatements(); - if (authnList.size() == 0) - throw new AssertionAttributeExtractorExeption("AuthnStatement"); - - else if (authnList.size() > 1) - log.warn("Found more then ONE AuthnStatements in PVP2.1 assertions. Only the First is used."); - - return authnList.get(0); - } - - private void internalInitialize() { - if (assertion.getAttributeStatements() != null && - assertion.getAttributeStatements().size() > 0) { - AttributeStatement attrStat = assertion.getAttributeStatements().get(0); - for (Attribute attr : attrStat.getAttributes()) { - if (attr.getName().startsWith(PVPConstants.STORK_ATTRIBUTE_PREFIX)) { - List<String> storkAttrValues = new ArrayList<String>(); - for (XMLObject el : attr.getAttributeValues()) - storkAttrValues.add(el.getDOM().getTextContent()); - -// PersonalAttribute storkAttr = new PersonalAttribute(attr.getName(), -// false, storkAttrValues , "Available"); -// storkAttributes.put(attr.getName(), storkAttr ); - - } else { - List<String> attrList = new ArrayList<String>(); - for (XMLObject el : attr.getAttributeValues()) - attrList.add(el.getDOM().getTextContent()); - - attributs.put(attr.getName(), attrList); - - } - } - } - } + + private static final Logger log = LoggerFactory.getLogger(AssertionAttributeExtractor.class); + + private Assertion assertion = null; + private final Map<String, List<String>> attributs = new HashMap<>(); + // private PersonalAttributeList storkAttributes = new PersonalAttributeList(); + + @Deprecated + private final List<String> minimalMdsAttributeNamesList = + Arrays.asList(PvpConstants.PRINCIPAL_NAME_NAME, PvpConstants.GIVEN_NAME_NAME, + PvpConstants.BIRTHDATE_NAME, PvpConstants.BPK_NAME); + + @Deprecated + private final List<String> minimalIdlAttributeNamesList = + Arrays.asList(PvpConstants.EID_IDENTITY_LINK_NAME, PvpConstants.EID_SOURCE_PIN_NAME, + PvpConstants.EID_SOURCE_PIN_TYPE_NAME); + + private final List<String> minimalEidAttributeNamesList = + Arrays.asList(ExtendedPvpAttributeDefinitions.EID_EIDBIND_NAME); + + /** + * Parse the SAML2 Response element and extracts included information. <br> + * <br> + * <b>INFO:</b> Actually, only the first SAML2 Assertion of the SAML2 Response + * is used! + * + * @param samlResponse SAML2 Response + * @throws AssertionAttributeExtractorExeption In case of an error + */ + public AssertionAttributeExtractor(final StatusResponseType samlResponse) + throws AssertionAttributeExtractorExeption { + if (samlResponse != null && samlResponse instanceof Response) { + final List<Assertion> assertions = ((Response) samlResponse).getAssertions(); + if (assertions.size() == 0) { + throw new AssertionAttributeExtractorExeption("Assertion"); + } else if (assertions.size() > 1) { + log.warn("Found more then ONE PVP2.1 assertions. Only the First is used."); + } + + assertion = assertions.get(0); + internalInitialize(); + + } else { + throw new AssertionAttributeExtractorExeption(); + } + } + + /** + * Parse the SAML2 Assertion element and extracts included information. <br> + * <br> + * + * @param assertion SAML2 Assertion + * @throws AssertionAttributeExtractorExeption In case of an error + */ + public AssertionAttributeExtractor(final Assertion assertion) + throws AssertionAttributeExtractorExeption { + this.assertion = assertion; + internalInitialize(); + + } + + /** + * Get all SAML2 attributes from first SAML2 AttributeStatement element. + * + * @return List of SAML2 Attributes + */ + public List<Attribute> getAllResponseAttributesFromFirstAttributeStatement() { + return assertion.getAttributeStatements().get(0).getAttributes(); + + } + + /** + * Get all SAML2 attributes of specific SAML2 AttributeStatement element. + * + * @param attrStatementID List ID of the AttributeStatement element + * @return List of SAML2 Attributes + */ + public List<Attribute> getAllResponseAttributes(final int attrStatementID) { + return assertion.getAttributeStatements().get(attrStatementID).getAttributes(); + + } + + /** + * check attributes from assertion with minimal required attribute list. + * + * @return + */ + public boolean containsAllRequiredAttributes() { + return containsAllRequiredAttributes(minimalEidAttributeNamesList) + || containsAllRequiredAttributes(minimalIdlAttributeNamesList) + || containsAllRequiredAttributes(minimalMdsAttributeNamesList); + + } + + /** + * check attributes from assertion with attributeNameList bPK or enc_bPK are + * always needed. + * + * @param attributeNameList List of attributes which are required + * + * @return + */ + public boolean containsAllRequiredAttributes(final Collection<String> attributeNameList) { + + // first check if a bPK or an encrypted bPK is available + boolean flag = true; + for (final String attr : attributeNameList) { + if (!attributs.containsKey(attr)) { + flag = false; + log.debug("Assertion contains no Attribute " + attr); + + } + + } + + if (flag) { + return flag; + } else { + log.debug( + "Assertion contains no all minimum attributes from: " + attributeNameList.toString()); + return false; + + } + } + + public boolean containsAttribute(final String attributeName) { + return attributs.containsKey(attributeName); + + } + + /** + * Get single attribute with name. + * + * @param attributeName attribute Name + * @return Attribute value + */ + public String getSingleAttributeValue(final String attributeName) { + if (attributs.containsKey(attributeName) && attributs.get(attributeName).size() > 0) { + return attributs.get(attributeName).get(0); + } else { + return null; + } + + } + + public List<String> getAttributeValues(final String attributeName) { + return attributs.get(attributeName); + + } + + /** + * Return all include PVP attribute names. + * + * @return + */ + public Set<String> getAllIncludeAttributeNames() { + return attributs.keySet(); + + } + + /** + * Get User's nameId. + * + * @return nameId + * @throws AssertionAttributeExtractorExeption In case of an error + */ + public String getNameID() throws AssertionAttributeExtractorExeption { + if (assertion.getSubject() != null) { + final Subject subject = assertion.getSubject(); + + if (subject.getNameID() != null) { + if (StringUtils.isNotEmpty(subject.getNameID().getValue())) { + return subject.getNameID().getValue(); + } else { + log.error("SAML2 NameID Element is empty."); + } + } + } + + throw new AssertionAttributeExtractorExeption("nameID"); + } + + /** + * Get the Id attribute from SAML2 assertion. + * + * @return + */ + public String getAssertionID() { + return assertion.getID(); + + } + + /** + * Get SessionIndex from assertion. + * + * @return sessionIndex + * @throws AssertionAttributeExtractorExeption In case of an error + */ + public String getSessionIndex() throws AssertionAttributeExtractorExeption { + final AuthnStatement authn = getAuthnStatement(); + + if (StringUtils.isNotEmpty(authn.getSessionIndex())) { + return authn.getSessionIndex(); + } else { + throw new AssertionAttributeExtractorExeption("SessionIndex"); + } + } + + /** + * Get LoA from Assertion. + * + * @return LoA + * @throws AssertionAttributeExtractorExeption In case of an error + */ + public String getQaaLevel() throws AssertionAttributeExtractorExeption { + final AuthnStatement authn = getAuthnStatement(); + if (authn.getAuthnContext() != null + && authn.getAuthnContext().getAuthnContextClassRef() != null) { + final AuthnContextClassRef qaaClass = authn.getAuthnContext().getAuthnContextClassRef(); + + if (StringUtils.isNotEmpty(qaaClass.getAuthnContextClassRef())) { + return qaaClass.getAuthnContextClassRef(); + } else { + throw new AssertionAttributeExtractorExeption("AuthnContextClassRef (QAALevel)"); + } + } + + throw new AssertionAttributeExtractorExeption("AuthnContextClassRef"); + } + + public Assertion getFullAssertion() { + return assertion; + } + + /** + * Get the Assertion validTo period. + * + * <p> + * Primarily, the 'SessionNotOnOrAfter' attribute in the SAML2 'AuthnStatment' + * element is used. If this is empty, this method returns value of SAML + * 'Conditions' element. + * </p> + * + * @return Date, until this SAML2 assertion is valid + */ + public Date getAssertionNotOnOrAfter() { + if (getFullAssertion().getAuthnStatements() != null + && getFullAssertion().getAuthnStatements().size() > 0) { + for (final AuthnStatement el : getFullAssertion().getAuthnStatements()) { + if (el.getSessionNotOnOrAfter() != null) { + return el.getSessionNotOnOrAfter().toDate(); + } + } + + } + + return getFullAssertion().getConditions().getNotOnOrAfter().toDate(); + + } + + /** + * Get the Assertion issuing date. + * + * <p> + * This method returns value of SAML 'Conditions' element. + * </p> + * + * @return Date, when the SAML2 assertion was issued, otherwise null + */ + public Date getAssertionIssuingDate() { + try { + return getFullAssertion().getIssueInstant().toDate(); + + } catch (final NullPointerException e) { + return null; + + } + } + + /** + * Get the Assertion validFrom period. + * + * <p> + * This method returns value of SAML 'Conditions' element. + * </p> + * + * @return Date, after this SAML2 assertion is valid, otherwise null + */ + public Date getAssertionNotBefore() { + try { + return getFullAssertion().getConditions().getNotBefore().toDate(); + + } catch (final NullPointerException e) { + return null; + + } + } + + private AuthnStatement getAuthnStatement() throws AssertionAttributeExtractorExeption { + final List<AuthnStatement> authnList = assertion.getAuthnStatements(); + if (authnList.size() == 0) { + throw new AssertionAttributeExtractorExeption("AuthnStatement"); + } else if (authnList.size() > 1) { + log.warn("Found more then ONE AuthnStatements in PVP2.1 assertions. Only the First is used."); + } + + return authnList.get(0); + } + + private void internalInitialize() { + if (assertion.getAttributeStatements() != null + && assertion.getAttributeStatements().size() > 0) { + final AttributeStatement attrStat = assertion.getAttributeStatements().get(0); + for (final Attribute attr : attrStat.getAttributes()) { + final List<String> attrList = new ArrayList<>(); + for (final XMLObject el : attr.getAttributeValues()) { + attrList.add(el.getDOM().getTextContent()); + attributs.put(attr.getName(), attrList); + + } + } + } + } } diff --git a/eaaf_modules/eaaf_module_pvp2_sp/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider b/eaaf_modules/eaaf_module_pvp2_sp/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider new file mode 100644 index 00000000..9a6cb2d2 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_sp/src/main/resources/META-INF/services/at.gv.egiz.components.spring.api.SpringResourceProvider @@ -0,0 +1 @@ +at.gv.egiz.eaaf.modules.pvp2.sp.Pvp2SProfileSpSpringResourceProvider
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_pvp2_sp/src/main/resources/eaaf_pvp_sp.beans.xml b/eaaf_modules/eaaf_module_pvp2_sp/src/main/resources/eaaf_pvp_sp.beans.xml new file mode 100644 index 00000000..439ad005 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_sp/src/main/resources/eaaf_pvp_sp.beans.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:context="http://www.springframework.org/schema/context" + xmlns:tx="http://www.springframework.org/schema/tx" + xmlns:aop="http://www.springframework.org/schema/aop" + xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd + http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> + + <bean id="pvpSpLogMessageSource" + class="at.gv.egiz.eaaf.modules.pvp2.sp.impl.logging.PvpSpModuleMessageSource" /> + + <bean id="pvpAuthnRequestBuilder" + class="at.gv.egiz.eaaf.modules.pvp2.sp.impl.PvpAuthnRequestBuilder" /> + +</beans>
\ No newline at end of file diff --git a/eaaf_modules/eaaf_module_pvp2_sp/src/main/resources/messages/pvp_sp_messages.properties b/eaaf_modules/eaaf_module_pvp2_sp/src/main/resources/messages/pvp_sp_messages.properties new file mode 100644 index 00000000..682c3f18 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_sp/src/main/resources/messages/pvp_sp_messages.properties @@ -0,0 +1,17 @@ +sp.pvp2.00=Can not build PVP AuthnRequest for {0} {1}. No valid SingleSignOnService endpoint found. +sp.pvp2.01=Can not build PVP AuthnRequest for {0}. IDP is not allowed for federated authentication. +sp.pvp2.02=Can not build PVP AuthnRequest for {0}. IDP has no (valid) metadata. +sp.pvp2.03=Receive PVP Response from {0} with unsupported Binding. +sp.pvp2.04=Receive invalid PVP Response from {0}. No PVP metadata found. +sp.pvp2.05=Receive invalid PVP Response from {0} {1}. StatusCode:{2} Msg:{3}. +sp.pvp2.06=Receive invalid PVP Response from {0}. Assertion does not contain all required attributes. +sp.pvp2.07=Receive invalid PVP Response from {0}. Attribute {1} is not valid. +sp.pvp2.08=Receive invalid PVP Response from {0}. Response issuer {1} is not valid or allowed. +sp.pvp2.09=Receive invalid PVP Response from {0} {1}. StatusCodes:{2} {3} Msg:{4} +sp.pvp2.10=Receive invalid PVP Response from {0}. No valid assertion included. +sp.pvp2.11=Receive invalid PVP Response from {0}. Assertion decryption FAILED. +sp.pvp2.12=Receive invalid PVP Response from {0}. Msg:{1} +sp.pvp2.13=Can not build PVP AuthnRequest for {0}. Internal processing error. + + + diff --git a/eaaf_modules/eaaf_module_pvp2_sp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/sp/test/Pvp2SProfileSpSpringResourceProviderTest.java b/eaaf_modules/eaaf_module_pvp2_sp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/sp/test/Pvp2SProfileSpSpringResourceProviderTest.java new file mode 100644 index 00000000..4a132c3f --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_sp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/sp/test/Pvp2SProfileSpSpringResourceProviderTest.java @@ -0,0 +1,57 @@ +package at.gv.egiz.eaaf.modules.pvp2.sp.test; + +import java.io.IOException; +import java.io.InputStream; + +import at.gv.egiz.eaaf.core.test.TestConstants; +import at.gv.egiz.eaaf.modules.pvp2.Pvp2SProfileCoreSpringResourceProvider; +import at.gv.egiz.eaaf.modules.pvp2.sp.Pvp2SProfileSpSpringResourceProvider; + +import org.apache.commons.io.IOUtils; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.BlockJUnit4ClassRunner; +import org.springframework.core.io.Resource; + + + +@RunWith(BlockJUnit4ClassRunner.class) +public class Pvp2SProfileSpSpringResourceProviderTest { + + @Test + public void testSpringConfig() { + final Pvp2SProfileCoreSpringResourceProvider test = + new Pvp2SProfileCoreSpringResourceProvider(); + for (final Resource el : test.getResourcesToLoad()) { + try { + IOUtils.toByteArray(el.getInputStream()); + + } catch (final IOException e) { + Assert.fail("Ressouce: " + el.getFilename() + " not found"); + } + + } + + Assert.assertNotNull("no Name", test.getName()); + Assert.assertNull("Find package definitions", test.getPackagesToScan()); + + } + + @Test + public void testSpILoaderConfig() { + final InputStream el = this.getClass().getResourceAsStream(TestConstants.TEST_SPI_LOADER_PATH); + try { + final String spiFile = IOUtils.toString(el, "UTF-8"); + + Assert.assertEquals("Wrong classpath in SPI file", + Pvp2SProfileSpSpringResourceProvider.class.getName(), spiFile); + + + } catch (final IOException e) { + Assert.fail("Ressouce: " + TestConstants.TEST_SPI_LOADER_PATH + " not found"); + + } + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_sp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/sp/test/PvpSpMessageSourceTest.java b/eaaf_modules/eaaf_module_pvp2_sp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/sp/test/PvpSpMessageSourceTest.java new file mode 100644 index 00000000..90bb084a --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_sp/src/test/java/at/gv/egiz/eaaf/modules/pvp2/sp/test/PvpSpMessageSourceTest.java @@ -0,0 +1,39 @@ +package at.gv.egiz.eaaf.modules.pvp2.sp.test; + +import java.util.List; + +import at.gv.egiz.eaaf.core.api.logging.IMessageSourceLocation; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.Resource; +import org.springframework.core.io.ResourceLoader; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration({ "/eaaf_pvp_sp.beans.xml"}) +public class PvpSpMessageSourceTest { + + @Autowired + private ResourceLoader loader; + @Autowired(required = false) + private List<IMessageSourceLocation> messageSources; + + @Test + public void checkMessageSources() { + Assert.assertNotNull("No messageSource", messageSources); + + for (final IMessageSourceLocation messageSource : messageSources) { + Assert.assertNotNull("No sourcePath", messageSource.getMessageSourceLocation()); + + for (final String el : messageSource.getMessageSourceLocation()) { + final Resource messages = loader.getResource(el + ".properties"); + Assert.assertTrue("Source not exist", messages.exists()); + + } + } + } +} diff --git a/eaaf_modules/pom.xml b/eaaf_modules/pom.xml index b1b5bf91..228a41cf 100644 --- a/eaaf_modules/pom.xml +++ b/eaaf_modules/pom.xml @@ -4,7 +4,7 @@ <parent> <groupId>at.gv.egiz</groupId> <artifactId>eaaf</artifactId> - <version>1.0.13.2</version> + <version>1.1.0</version> </parent> <groupId>at.gv.egiz.eaaf</groupId> |