diff options
86 files changed, 3573 insertions, 1386 deletions
| diff --git a/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/module/gui/DummyGuiBuilderConfigurationFactory.java b/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/module/gui/DummyGuiBuilderConfigurationFactory.java new file mode 100644 index 00000000..be71a29c --- /dev/null +++ b/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/module/gui/DummyGuiBuilderConfigurationFactory.java @@ -0,0 +1,36 @@ +package at.gv.egiz.eaaf.core.impl.idp.module.gui; + +import java.net.MalformedURLException; +import java.net.URI; + +import at.gv.egiz.eaaf.core.api.IRequest; +import at.gv.egiz.eaaf.core.api.gui.IGuiBuilderConfiguration; +import at.gv.egiz.eaaf.core.api.gui.IGuiBuilderConfigurationFactory; +import at.gv.egiz.eaaf.core.api.gui.IVelocityGuiBuilderConfiguration; + +public class DummyGuiBuilderConfigurationFactory implements IGuiBuilderConfigurationFactory { + +  private IGuiBuilderConfiguration errorGuiConfig; +  private IVelocityGuiBuilderConfiguration velocityBuilderConfig; + +  @Override +  public IGuiBuilderConfiguration getDefaultErrorGui(String authUrl) { +    return errorGuiConfig; +  } + +  @Override +  public IVelocityGuiBuilderConfiguration getSpSpecificSaml2PostConfiguration(IRequest pendingReq, +      String viewName, URI configRootContextDir) throws MalformedURLException { +    return velocityBuilderConfig; +  } + +  public void setErrorGuiConfig(IGuiBuilderConfiguration errorGuiConfig) { +    this.errorGuiConfig = errorGuiConfig; +  } + +  public void setVelocityBuilderConfig(IVelocityGuiBuilderConfiguration velocityBuilderConfig) { +    this.velocityBuilderConfig = velocityBuilderConfig; +  } + + +} diff --git a/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/module/gui/DummyVelocityGuiFormBuilder.java b/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/module/gui/DummyVelocityGuiFormBuilder.java new file mode 100644 index 00000000..e2cdd1ee --- /dev/null +++ b/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/module/gui/DummyVelocityGuiFormBuilder.java @@ -0,0 +1,36 @@ +package at.gv.egiz.eaaf.core.impl.idp.module.gui; + +import java.io.InputStream; + +import at.gv.egiz.eaaf.core.api.gui.IVelocityGuiBuilderConfiguration; +import at.gv.egiz.eaaf.core.exceptions.GuiBuildException; +import at.gv.egiz.eaaf.core.impl.gui.AbstractVelocityGuiFormBuilderImpl; + +public class DummyVelocityGuiFormBuilder extends AbstractVelocityGuiFormBuilderImpl { + +  private InputStream internalTemplate = null; + +  public DummyVelocityGuiFormBuilder() throws GuiBuildException { +    super(); +  } + +  @Override +  protected InputStream getInternalTemplate(IVelocityGuiBuilderConfiguration config) +      throws GuiBuildException { +    return internalTemplate; + +  } + +  /** +   * Set internal template that should be loaded by builder. +   * +   * @param internalTemplate Tempalte +   */ +  public void setInternalTemplate(InputStream internalTemplate) { +    this.internalTemplate = internalTemplate; +  } + + + + +} diff --git a/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/module/test/DummyAuthConfig.java b/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/module/test/DummyAuthConfig.java new file mode 100644 index 00000000..a6f24c6d --- /dev/null +++ b/eaaf_core/src/test/java/at/gv/egiz/eaaf/core/impl/idp/module/test/DummyAuthConfig.java @@ -0,0 +1,72 @@ +package at.gv.egiz.eaaf.core.impl.idp.module.test; + +import java.net.URI; +import java.net.URL; + +import org.apache.commons.lang3.StringUtils; + +import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration; +import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException; +import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.core.impl.idp.conf.AbstractSpringBootConfigurationImpl; + + +public class DummyAuthConfig extends AbstractSpringBootConfigurationImpl { + +  private ISpConfiguration spconfig = null; + +  private String configPropPrefix = StringUtils.EMPTY; + +  public void setSpConfig(final ISpConfiguration spConfig) { +    this.spconfig = spConfig; + +  } + + + +  @Override +  public URI getConfigurationRootDirectory() { +    return new java.io.File(".").toURI(); +  } + +  @Override +  public ISpConfiguration getServiceProviderConfiguration(final String arg0) +      throws EaafConfigurationException { +    return spconfig; +  } + +  @SuppressWarnings("unchecked") +  @Override +  public <T> T getServiceProviderConfiguration(final String arg0, final Class<T> arg1) +      throws EaafConfigurationException { +    return (T) spconfig; + +  } + +  @Override +  public String validateIdpUrl(final URL arg0) throws EaafException { +    return arg0.toString(); +  } + + +  @Override +  protected String getBackupConfigPath() { +    return null; +  } + + +  @Override +  public String getApplicationSpecificKeyPrefix() { +    return configPropPrefix; + +  } + + + +  public void setConfigPropPrefix(final String configPropPrefix) { +    this.configPropPrefix = configPropPrefix; +  } + + + +} diff --git a/eaaf_core_api/src/main/java/at/gv/egiz/eaaf/core/api/logging/IMessageSourceLocation.java b/eaaf_core_api/src/main/java/at/gv/egiz/eaaf/core/api/logging/IMessageSourceLocation.java new file mode 100644 index 00000000..b517568e --- /dev/null +++ b/eaaf_core_api/src/main/java/at/gv/egiz/eaaf/core/api/logging/IMessageSourceLocation.java @@ -0,0 +1,13 @@ +package at.gv.egiz.eaaf.core.api.logging; + +import java.util.List; + +public interface IMessageSourceLocation { + +  /** +   * Get the location of a module specific message source. +   * +   * @return +   */ +  List<String> getMessageSourceLocation(); +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/pom.xml b/eaaf_modules/eaaf_module_pvp2_core/pom.xml index abf2ebe5..62973ac5 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/pom.xml +++ b/eaaf_modules/eaaf_module_pvp2_core/pom.xml @@ -49,10 +49,6 @@      </dependency>      <dependency> -      <groupId>org.owasp.esapi</groupId> -      <artifactId>esapi</artifactId> -    </dependency> -    <dependency>        <groupId>javax.servlet</groupId>        <artifactId>javax.servlet-api</artifactId>        <scope>provided</scope> @@ -64,6 +60,18 @@        <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</artifactId> +      <scope>test</scope> +      <type>test-jar</type> +    </dependency> +        </dependencies>    <build> 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 index 979a61d5..b1ac8e75 100644 --- 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 @@ -28,19 +28,33 @@ 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 DEFAULT_SIGNING_METHODE = +  //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_AES256;    String DEFAULT_ASYM_ENCRYPTION_METHODE =        EncryptionConstants.ALGO_ID_KEYTRANSPORT_RSAOAEP; + +  //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"; @@ -136,4 +150,21 @@ public interface PvpConstants extends PvpAttributeDefinitions {    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/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 57dd63bf..e8da499c 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 @@ -23,18 +23,15 @@ import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletResponse;  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 org.opensaml.messaging.decoder.MessageDecodingException; -import org.opensaml.saml2.metadata.provider.MetadataProvider; -import org.opensaml.security.SecurityException; -  import net.shibboleth.utilities.java.support.net.URIComparator;  public interface IDecoder {    InboundMessageInterface decode(HttpServletRequest req, HttpServletResponse resp, -      MetadataProvider metadataProvider, boolean isSpEndPoint, URIComparator comparator) -      throws MessageDecodingException, SecurityException, Pvp2Exception; +      IPvp2MetadataProvider metadataProvider, boolean isSpEndPoint, URIComparator comparator) +      throws Pvp2Exception;    boolean handleDecode(String action, HttpServletRequest req); 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 01f541a9..691d6574 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 @@ -23,13 +23,12 @@ import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletResponse;  import at.gv.egiz.eaaf.core.api.IRequest; +import at.gv.egiz.eaaf.modules.pvp2.api.credential.EaafX509Credential;  import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; -import org.opensaml.messaging.encoder.MessageEncodingException;  import org.opensaml.saml.saml2.core.RequestAbstractType;  import org.opensaml.saml.saml2.core.StatusResponseType;  import org.opensaml.security.SecurityException; -import org.opensaml.security.credential.Credential;  public interface IEncoder { @@ -44,13 +43,11 @@ public interface IEncoder {     * @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 In case of an error -   * @throws SecurityException        In case of an error -   * @throws Pvp2Exception            In case of an error +   * @throws Pvp2Exception In case of an error     */    void encodeRequest(HttpServletRequest req, HttpServletResponse resp, -      RequestAbstractType request, String targetLocation, String relayState, Credential credentials, -      IRequest pendingReq) throws MessageEncodingException, SecurityException, Pvp2Exception; +      RequestAbstractType request, String targetLocation, String relayState, EaafX509Credential credentials, +      IRequest pendingReq) throws Pvp2Exception;    /**     * Encoder SAML Response. @@ -63,10 +60,9 @@ public interface IEncoder {     * @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 In case of an error     * @throws SecurityException        In case of an error     */ -  void encodeRespone(HttpServletRequest req, HttpServletResponse resp, -      StatusResponseType response, String targetLocation, String relayState, Credential credentials, -      IRequest pendingReq) throws MessageEncodingException, SecurityException, Pvp2Exception; +  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..568b617d --- /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,25 @@ +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); + +} 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/IPvp2MetadataProvider.java index 25b2d250..e2ee0c9d 100644 --- 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/IPvp2MetadataProvider.java @@ -23,42 +23,29 @@ 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; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2MetadataException; -public interface IPvpMetadataProvider extends MetadataProvider { +import org.opensaml.core.xml.XMLObject; +import org.opensaml.saml.metadata.resolver.MetadataResolver; +import org.opensaml.saml.saml2.metadata.EntitiesDescriptor; +import org.opensaml.saml.saml2.metadata.EntityDescriptor; +import org.opensaml.saml.saml2.metadata.RoleDescriptor; -  @Override -  boolean requireValidMetadata(); +public interface IPvp2MetadataProvider extends MetadataResolver { -  @Override -  void setRequireValidMetadata(boolean requireValidMetadata); +  XMLObject getMetadata() throws Pvp2MetadataException; -  @Override -  MetadataFilter getMetadataFilter(); -  @Override -  void setMetadataFilter(MetadataFilter newFilter) throws MetadataProviderException; +  EntitiesDescriptor getEntitiesDescriptor(String entitiesID) throws Pvp2MetadataException; -  @Override -  XMLObject getMetadata() throws MetadataProviderException; -  @Override -  EntitiesDescriptor getEntitiesDescriptor(String entitiesID) throws MetadataProviderException; +  EntityDescriptor getEntityDescriptor(String entityID) throws Pvp2MetadataException; -  @Override -  EntityDescriptor getEntityDescriptor(String entityID) throws MetadataProviderException; -  @Override -  List<RoleDescriptor> getRole(String entityID, QName roleName) throws MetadataProviderException; +  List<RoleDescriptor> getRole(String entityID, QName roleName) throws Pvp2MetadataException; + -  @Override    RoleDescriptor getRole(String entityID, QName roleName, String supportedProtocol) -      throws MetadataProviderException; +      throws Pvp2MetadataException;  } 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/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/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..ae108c35 --- /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,108 @@ +package at.gv.egiz.eaaf.modules.pvp2.impl.binding; + +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.metadata.IPvp2MetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlSigningException; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils; +import at.gv.egiz.eaaf.modules.pvp2.impl.validation.TrustEngineFactory; + +import org.opensaml.core.config.ConfigurationService; +import org.opensaml.messaging.context.BaseContext; +import org.opensaml.messaging.context.MessageContext; +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.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; + +/** + * Abstract Binding implements common code for SAML2 binding implementations. + * + * @author tlenz + * + */ +public abstract class AbstractBinding { + +  @Autowired protected IConfiguration basicConfig; + +  public abstract String getSaml2BindingName(); + +  protected MessageContext<SAMLObject> buildBasicMessageContext( +      SAMLMessageEncoder encoder, SignableSAMLObject response) { +    final MessageContext<SAMLObject> messageContext =  new MessageContext<SAMLObject>(); +    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, false)); + +    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) { +    messageContext.addSubcontext(new SAMLPeerEntityContext()); +    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)); + +  } +} 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 251f6081..6f39392d 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 @@ -27,48 +27,37 @@ 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.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.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.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.EaafHttpPostDecoder;  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; -import org.apache.commons.lang3.StringUtils; -import org.opensaml.common.binding.BasicSAMLMessageContext; +import org.opensaml.messaging.context.MessageContext;  import org.opensaml.messaging.decoder.MessageDecodingException; -import org.opensaml.messaging.encoder.MessageEncodingException;  import org.opensaml.saml.common.SAMLObject; +import org.opensaml.saml.common.binding.SAMLBindingSupport; +import org.opensaml.saml.common.messaging.SAMLMessageSecuritySupport;  import org.opensaml.saml.common.xml.SAMLConstants; -import org.opensaml.saml.saml2.binding.decoding.impl.HTTPPostDecoder; +import org.opensaml.saml.saml2.core.RequestAbstractType;  import org.opensaml.saml.saml2.core.StatusResponseType; -import org.opensaml.saml.saml2.metadata.IDPSSODescriptor; -import org.opensaml.saml.saml2.metadata.SPSSODescriptor; -import org.opensaml.saml.saml2.metadata.SingleSignOnService; -import org.opensaml.saml.saml2.metadata.impl.SingleSignOnServiceBuilder; -import org.opensaml.saml2.metadata.provider.MetadataProvider; -import org.opensaml.security.credential.Credential; -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.slf4j.Logger; -import org.slf4j.LoggerFactory;  import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; +import lombok.extern.slf4j.Slf4j; +import net.shibboleth.utilities.java.support.component.ComponentInitializationException;  import net.shibboleth.utilities.java.support.net.URIComparator; -@Service("PVPPOSTBinding") -public class PostBinding implements IDecoder, IEncoder { -  private static final Logger log = LoggerFactory.getLogger(PostBinding.class); +@Slf4j +public class PostBinding extends AbstractBinding implements IDecoder, IEncoder {    @Autowired(required = true)    IConfiguration authConfig; @@ -78,152 +67,160 @@ public class PostBinding implements IDecoder, IEncoder {    IGuiBuilderConfigurationFactory guiConfigFactory;    @Override -  public void encodeRequest(final HttpServletRequest req, final HttpServletResponse resp, +  public void encodeRequest(final HttpServletRequest httpReq, final HttpServletResponse httpResp,        final RequestAbstractType request, final String targetLocation, final String relayState, -      final Credential credentials, final IRequest pendingReq) -      throws MessageEncodingException, SecurityException { +      final EaafX509Credential credentials, final IRequest pendingReq) +      throws Pvp2Exception {      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()); +      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 OpenSAML2 process parameter into binding context dao -      final HttpServletResponseAdapter responseAdapter = new HttpServletResponseAdapter(resp, true); -      final BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject> context = -          new BasicSAMLMessageContext<>(); -      final SingleSignOnService service = new SingleSignOnServiceBuilder().buildObject(); -      service.setBinding("urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"); -      service.setLocation(targetLocation); +      //set endpoint url +      messageContext.addSubcontext(injectEndpointInfos(request, targetLocation)); -      context.setOutboundSAMLMessageSigningCredential(credentials); -      context.setPeerEntityEndpoint(service); -      context.setOutboundSAMLMessage(request); -      context.setOutboundMessageTransport(responseAdapter); -      context.setRelayState(relayState); -      encoder.encode(context); +      //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 request", e); -      throw new SecurityException(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 encodeRespone(final HttpServletRequest req, final HttpServletResponse resp, +  public void encodeResponse(final HttpServletRequest httpReq, final HttpServletResponse httpResp,        final StatusResponseType response, final String targetLocation, final String relayState, -      final Credential credentials, final IRequest pendingReq) -      throws MessageEncodingException, SecurityException { +      final EaafX509Credential credentials, final IRequest pendingReq) +          throws Pvp2Exception {      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<>(); -      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); +      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 response", e); -      throw new SecurityException(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 MetadataProvider metadataProvider, +      final HttpServletResponse resp, final IPvp2MetadataProvider metadataProvider,        final boolean isSpEndPoint, final URIComparator comparator) -      throws MessageDecodingException, SecurityException { +      throws Pvp2Exception { -    final HTTPPostDecoder decode = new HTTPPostDecoder(); +    //TODO: check, if we should re-implement HTTPPostDecoder to collect the last http parameter!!! +    final EaafHttpPostDecoder decode = new EaafHttpPostDecoder();      decode.setHttpServletRequest(req); -    final BasicSAMLMessageContext<SAMLObject, ?, ?> messageContext = -        new BasicSAMLMessageContext<>(); -    messageContext.setInboundMessageTransport(new HttpServletRequestAdapter(req)); -    // set metadata descriptor type -    if (isSpEndPoint) { -      messageContext.setPeerEntityRole(IDPSSODescriptor.DEFAULT_ELEMENT_NAME); -      decode.setURIComparator(comparator); +    //decode request +    try { +      decode.initialize(); +      decode.decode(); -    } else { -      messageContext.setPeerEntityRole(SPSSODescriptor.DEFAULT_ELEMENT_NAME); -      decode.setURIComparator(comparator); +    } catch (MessageDecodingException | ComponentInitializationException e) { +      throw new SamlBindingException("internal.pvp.95", +          new Object[] {PvpConstants.POST, "decoding", e.getMessage()}, +          e);      } -    messageContext.setMetadataProvider(metadataProvider); +    final MessageContext<SAMLObject> messageContext = decode.getMessageContext(); + +    if (SAMLBindingSupport.isSigningCapableBinding(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); + + +    //TODO: add sig validation!!! -    // 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) { + +    if (messageContext.getMessage() instanceof RequestAbstractType) {        final RequestAbstractType inboundMessage = -          (RequestAbstractType) messageContext.getInboundMessage(); +          (RequestAbstractType) messageContext.getMessage();        msg = new PvpSProfileRequest(inboundMessage, getSaml2BindingName());        msg.setEntityID(inboundMessage.getIssuer().getValue()); -    } else if (messageContext.getInboundMessage() instanceof StatusResponseType) { +    } else if (messageContext.getMessage() instanceof StatusResponseType) {        final StatusResponseType inboundMessage = -          (StatusResponseType) messageContext.getInboundMessage(); +          (StatusResponseType) messageContext.getMessage();        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()); +    msg.setVerified(false); +    msg.setRelayState(SAMLBindingSupport.getRelayState(messageContext));      return msg;    } @@ -231,6 +228,7 @@ public class PostBinding implements IDecoder, IEncoder {    @Override    public boolean handleDecode(final String action, final HttpServletRequest req) {      return req.getMethod().equals("POST") && action.equals(PvpConstants.POST); +    }    @Override 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 559ee3b8..5f74053d 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 @@ -26,211 +26,315 @@ import at.gv.egiz.eaaf.core.api.IRequest;  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.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.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; +import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.EaafHttpRedirectDeflateDecoder; +import at.gv.egiz.eaaf.modules.pvp2.impl.verification.PvpSamlMessageHandlerChain; -import org.apache.commons.lang3.StringUtils; -import org.opensaml.common.binding.BasicSAMLMessageContext; +import org.opensaml.messaging.context.MessageContext;  import org.opensaml.messaging.decoder.MessageDecodingException; -import org.opensaml.messaging.encoder.MessageEncodingException; +import org.opensaml.messaging.handler.MessageHandlerException;  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.decoding.impl.HTTPRedirectDeflateDecoder;  import org.opensaml.saml.saml2.binding.encoding.impl.HTTPRedirectDeflateEncoder; +import org.opensaml.saml.saml2.binding.security.impl.SAML2HTTPRedirectDeflateSignatureSecurityHandler;  import org.opensaml.saml.saml2.core.RequestAbstractType;  import org.opensaml.saml.saml2.core.StatusResponseType; -import org.opensaml.saml.saml2.metadata.IDPSSODescriptor; -import org.opensaml.saml.saml2.metadata.SPSSODescriptor; -import org.opensaml.saml.saml2.metadata.SingleSignOnService; -import org.opensaml.saml.saml2.metadata.impl.SingleSignOnServiceBuilder; -import org.opensaml.saml2.binding.security.SAML2HTTPRedirectDeflateSignatureRule; -import org.opensaml.saml2.metadata.provider.MetadataProvider; -import org.opensaml.security.credential.Credential; -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.slf4j.Logger;  import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Service; +import net.shibboleth.utilities.java.support.component.ComponentInitializationException;  import net.shibboleth.utilities.java.support.net.URIComparator; -import net.shibboleth.utilities.java.support.xml.BasicParserPool; -@Service("PVPRedirectBinding") -public class RedirectBinding implements IDecoder, IEncoder { +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 Credential credentials, final IRequest pendingReq) -      throws MessageEncodingException, SecurityException { - -    // load default PVP security configurations -    EaafDefaultSaml2Bootstrap.initializeDefaultPvpConfiguration(); - -    log.debug("create SAML RedirectBinding response"); - -    final HTTPRedirectDeflateEncoder encoder = new HTTPRedirectDeflateEncoder(); -    final HttpServletResponseAdapter responseAdapter = new HttpServletResponseAdapter(resp, true); -    final BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject> context = -        new BasicSAMLMessageContext<>(); -    final 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); +      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 encodeRespone(final HttpServletRequest req, final HttpServletResponse resp, +  public void encodeResponse(final HttpServletRequest req, final HttpServletResponse resp,        final StatusResponseType response, final String targetLocation, final String relayState, -      final Credential credentials, final IRequest pendingReq) -      throws MessageEncodingException, SecurityException { +      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)); -    // load default PVP security configurations -    EaafDefaultSaml2Bootstrap.initializeDefaultPvpConfiguration(); +      // inject signing context +      messageContext.addSubcontext(injectSigningInfos(credentials)); -    log.debug("create SAML RedirectBinding response"); +      // set relayState of exists +      SAMLBindingSupport.setRelayState(messageContext, relayState); -    final HTTPRedirectDeflateEncoder encoder = new HTTPRedirectDeflateEncoder(); -    final HttpServletResponseAdapter responseAdapter = new HttpServletResponseAdapter(resp, true); -    final BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject> context = -        new BasicSAMLMessageContext<>(); -    final 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); +      // encode message +      encoder.initialize(); +      encoder.encode(); -    encoder.encode(context); +    } 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 MetadataProvider metadataProvider, +      final HttpServletResponse resp, final IPvp2MetadataProvider metadataProvider,        final boolean isSpEndPoint, final URIComparator comparator) -      throws MessageDecodingException, SecurityException { - -    final HTTPRedirectDeflateDecoder decode = new HTTPRedirectDeflateDecoder(new BasicParserPool()); - -    final BasicSAMLMessageContext<SAMLObject, ?, ?> messageContext = -        new BasicSAMLMessageContext<>(); -    messageContext.setInboundMessageTransport(new HttpServletRequestAdapter(req)); +      throws Pvp2Exception { -    // set metadata descriptor type -    if (isSpEndPoint) { -      messageContext.setPeerEntityRole(IDPSSODescriptor.DEFAULT_ELEMENT_NAME); -      decode.setURIComparator(comparator); +    // TODO: implement one flat decoder to get SAML2 request/response parametes as +    // same as in SAML2HTTPRedirectDeflateSignatureSecurityHandler +    final EaafHttpRedirectDeflateDecoder decode = new EaafHttpRedirectDeflateDecoder(); +    decode.setHttpServletRequest(req); -    } else { -      messageContext.setPeerEntityRole(SPSSODescriptor.DEFAULT_ELEMENT_NAME); -      decode.setURIComparator(comparator); -    } +    // decode request +    try { +      decode.initialize(); +      decode.decode(); -    messageContext.setMetadataProvider(metadataProvider); - -    final SAML2HTTPRedirectDeflateSignatureRule signatureRule = -        new SAML2HTTPRedirectDeflateSignatureRule( -            TrustEngineFactory.getSignatureKnownKeysTrustEngine(metadataProvider)); -    final PvpAuthRequestSignedRole signedRole = new PvpAuthRequestSignedRole(); -    final BasicSecurityPolicy policy = new BasicSecurityPolicy(); -    policy.getPolicyRules().add(signedRole); -    policy.getPolicyRules().add(signatureRule); -    final 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); +    } catch (MessageDecodingException | ComponentInitializationException e) { +      throw new SamlBindingException("internal.pvp.95", +          new Object[] { PvpConstants.REDIRECT, "decoding", e.getMessage() }, +          e);      } -    try { -      decode.decode(messageContext); - -      // check signature -      signatureRule.evaluate(messageContext); +    final MessageContext<SAMLObject> messageContext = decode.getMessageContext(); -    } catch (final SecurityException e) { -      if (StringUtils.isEmpty(messageContext.getInboundMessageIssuer())) { -        throw e; +    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); -      } +    } -      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); +    //inject informations into message context that are required for further processing +    injectInboundMessageContexts(messageContext, metadataProvider); + +    log.trace("Signature validation on binding-level starts ... "); +    final PvpSamlMessageHandlerChain messageValidatorChain = new PvpSamlMessageHandlerChain(); +    final SAML2HTTPRedirectDeflateSignatureSecurityHandler redirectBindingSignaturHandler = +        new SAML2HTTPRedirectDeflateSignatureSecurityHandler(); +    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); -          // check signature -          signatureRule.evaluate(messageContext); -        } -        log.trace("Second PVP2X message validation finished"); +    try { +      messageValidatorChain.initialize(); +      messageValidatorChain.invoke(messageContext); -      } else { -        throw e; +    } catch (final ComponentInitializationException e) { +      // TODO Auto-generated catch block +      e.printStackTrace(); -      } +    } catch (final MessageHandlerException e) { +      // TODO Auto-generated catch block +      e.printStackTrace();      }      InboundMessage msg = null; -    if (messageContext.getInboundMessage() instanceof RequestAbstractType) { + +    if (messageContext.getMessage() instanceof RequestAbstractType) {        final RequestAbstractType inboundMessage = -          (RequestAbstractType) messageContext.getInboundMessage(); +          (RequestAbstractType) messageContext.getMessage();        msg = new PvpSProfileRequest(inboundMessage, getSaml2BindingName()); +      msg.setEntityID(inboundMessage.getIssuer().getValue()); -    } else if (messageContext.getInboundMessage() instanceof StatusResponseType) { +    } else if (messageContext.getMessage() instanceof StatusResponseType) {        final StatusResponseType inboundMessage = -          (StatusResponseType) messageContext.getInboundMessage(); +          (StatusResponseType) messageContext.getMessage();        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 { -      log.info( -          "No Metadata found for OA with EntityID " + messageContext.getInboundMessageIssuer());      } -    msg.setVerified(true); -    msg.setRelayState(messageContext.getRelayState()); +    msg.setVerified(false); +    msg.setRelayState(SAMLBindingSupport.getRelayState(messageContext));      return msg; + +//    final BasicSAMLMessageContext<SAMLObject, ?, ?> messageContext = +//        new BasicSAMLMessageContext<>(); +//    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); +// +//    final SAML2HTTPRedirectDeflateSignatureRule signatureRule = +//        new SAML2HTTPRedirectDeflateSignatureRule( +//            TrustEngineFactory.getSignatureKnownKeysTrustEngine(metadataProvider)); +//    final PvpAuthRequestSignedRole signedRole = new PvpAuthRequestSignedRole(); +//    final BasicSecurityPolicy policy = new BasicSecurityPolicy(); +//    policy.getPolicyRules().add(signedRole); +//    policy.getPolicyRules().add(signatureRule); +//    final 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); +//    } +// +//    SAML2AuthnRequestsSignedSecurityHandler +// +//    try { +//      decode.decode(messageContext); +// +//      // check signature +//      signatureRule.evaluate(messageContext); +// +//    } catch (final 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) { +//      final RequestAbstractType inboundMessage = +//          (RequestAbstractType) messageContext.getInboundMessage(); +//      msg = new PvpSProfileRequest(inboundMessage, getSaml2BindingName()); +// +//    } else if (messageContext.getInboundMessage() instanceof StatusResponseType) { +//      final 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;    }    @Override    public boolean handleDecode(final String action, final HttpServletRequest req) { -    return action.equals(PvpConstants.REDIRECT) || action.equals(PvpConstants.SINGLELOGOUT) +    return (action.equals(PvpConstants.REDIRECT) || action.equals(PvpConstants.SINGLELOGOUT))          && req.getMethod().equals("GET");    } 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 04266d37..e0df2d2a 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 @@ -19,8 +19,6 @@  package at.gv.egiz.eaaf.modules.pvp2.impl.binding; -import java.util.List; -  import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletResponse; @@ -28,99 +26,105 @@ import at.gv.egiz.eaaf.core.api.IRequest;  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.IPvp2MetadataProvider;  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; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlBindingException; +import at.gv.egiz.eaaf.modules.pvp2.impl.verification.EaafMessageContextInitializationHandler; +import at.gv.egiz.eaaf.modules.pvp2.impl.verification.PvpSamlMessageHandlerChain; -import org.apache.commons.lang3.StringUtils; -import org.opensaml.common.binding.BasicSAMLMessageContext; +import org.opensaml.messaging.context.MessageContext;  import org.opensaml.messaging.decoder.MessageDecodingException; -import org.opensaml.messaging.encoder.MessageEncodingException;  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.binding.security.impl.SAMLProtocolMessageXMLSignatureSecurityHandler; +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.saml.saml2.metadata.SPSSODescriptor; -import org.opensaml.saml2.metadata.provider.MetadataProvider; -import org.opensaml.security.credential.Credential; -import org.opensaml.soap.soap11.Envelope; -import org.opensaml.ws.transport.http.HttpServletRequestAdapter; -import org.opensaml.ws.transport.http.HttpServletResponseAdapter; -import org.opensaml.xmlsec.signature.SignableXMLObject; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Service; +import lombok.extern.slf4j.Slf4j; +import net.shibboleth.utilities.java.support.component.ComponentInitializationException;  import net.shibboleth.utilities.java.support.net.URIComparator; -import net.shibboleth.utilities.java.support.xml.BasicParserPool; - -@Service("PVPSOAPBinding") -public class SoapBinding implements IDecoder, IEncoder { -  private static final Logger log = LoggerFactory.getLogger(SoapBinding.class); +@Slf4j +public class SoapBinding extends AbstractBinding implements IDecoder, IEncoder {    @Override    public InboundMessageInterface decode(final HttpServletRequest req, -      final HttpServletResponse resp, final MetadataProvider metadataProvider, +      final HttpServletResponse resp, final IPvp2MetadataProvider metadataProvider,        final boolean isSpEndPoint, final URIComparator comparator) -      throws MessageDecodingException, SecurityException, Pvp2Exception { -    final HTTPSOAP11Decoder soapDecoder = new HTTPSOAP11Decoder(new BasicParserPool()); -    final BasicSAMLMessageContext<SAMLObject, ?, ?> messageContext = -        new BasicSAMLMessageContext<>(); -    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); - -    final Envelope inboundMessage = (Envelope) messageContext.getInboundMessage(); - -    if (inboundMessage.getBody() != null) { -      final List<XMLObject> xmlElemList = inboundMessage.getBody().getUnknownXMLObjects(); - -      if (!xmlElemList.isEmpty()) { -        final SignableXMLObject attrReq = (SignableXMLObject) xmlElemList.get(0); -        final PvpSProfileRequest request = new PvpSProfileRequest(attrReq, getSaml2BindingName()); - -        if (messageContext.getPeerEntityMetadata() != null) { -          request.setEntityID(messageContext.getPeerEntityMetadata().getEntityID()); -        } else if (attrReq instanceof RequestAbstractType) { -          final 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 (final Exception e) { -            log.warn("No Metadata found with EntityID " + attributeRequest.getIssuer().getValue()); -          } -        } - -        request.setVerified(false); -        return request; - -      } +      throws Pvp2Exception { + +    try { +      final HTTPSOAP11Decoder soapDecoder = new HTTPSOAP11Decoder(); + +      final PvpSamlMessageHandlerChain messageValidatorChain = new PvpSamlMessageHandlerChain(); +      soapDecoder.setBodyHandler(messageValidatorChain); + +      final SAMLProtocolMessageXMLSignatureSecurityHandler msgSignatureValidationHandler = +          new SAMLProtocolMessageXMLSignatureSecurityHandler(); + +      messageValidatorChain.addHandler(new EaafMessageContextInitializationHandler()); +      messageValidatorChain.addHandler(new CheckMessageVersionHandler()); +      messageValidatorChain.addHandler(new SAMLProtocolAndRoleHandler()); +      messageValidatorChain.addHandler(msgSignatureValidationHandler); +      messageValidatorChain.addHandler(new MessageLifetimeSecurityHandler()); +      messageValidatorChain.addHandler(new SAMLSOAPDecoderBodyHandler()); + +      // decode message +      soapDecoder.initialize(); +      soapDecoder.decode(); + +      final MessageContext<SAMLObject> messageContext = soapDecoder.getMessageContext(); +      messageContext.getMessage(); + +    } catch (MessageDecodingException | ComponentInitializationException e) { +      throw new SamlBindingException("internal.pvp.95", +          new Object[] { PvpConstants.POST, "decoding", e.getMessage() }, +          e);      } +//    final Envelope inboundMessage = (Envelope) messageContext.getMessage(); +// +//    if (inboundMessage.getBody() != null) { +//      final List<XMLObject> xmlElemList = inboundMessage.getBody().getUnknownXMLObjects(); +// +//      if (!xmlElemList.isEmpty()) { +//        final SignableXMLObject attrReq = (SignableXMLObject) xmlElemList.get(0); +//        final PvpSProfileRequest request = new PvpSProfileRequest(attrReq, getSaml2BindingName()); +// +//        if (messageContext.getPeerEntityMetadata() != null) { +//          request.setEntityID(messageContext.getPeerEntityMetadata().getEntityID()); +// +//        } else if (attrReq instanceof RequestAbstractType) { +//          final 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 (final 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);    } @@ -134,30 +138,47 @@ public class SoapBinding implements IDecoder, IEncoder {    @Override    public void encodeRequest(final HttpServletRequest req, final HttpServletResponse resp,        final RequestAbstractType request, final String targetLocation, final String relayState, -      final Credential credentials, final IRequest pendingReq) -      throws MessageEncodingException, SecurityException, Pvp2Exception { +      final EaafX509Credential credentials, final IRequest pendingReq) +      throws Pvp2Exception { +    throw new RuntimeException("Method not supported!!!");    }    @Override -  public void encodeRespone(final HttpServletRequest req, final HttpServletResponse resp, +  public void encodeResponse(final HttpServletRequest req, final HttpServletResponse resp,        final StatusResponseType response, final String targetLocation, final String relayState, -      final Credential credentials, final IRequest pendingReq) -      throws MessageEncodingException, SecurityException, Pvp2Exception { +      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); -    // load default PVP security configurations -    EaafDefaultSaml2Bootstrap.initializeDefaultPvpConfiguration(); +      // inject signing context +      messageContext.addSubcontext(injectSigningInfos(credentials)); -    final HTTPSOAP11Encoder encoder = new HTTPSOAP11Encoder(); -    final HttpServletResponseAdapter responseAdapter = new HttpServletResponseAdapter(resp, true); -    final BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject> context = -        new BasicSAMLMessageContext<>(); -    context.setOutboundSAMLMessageSigningCredential(credentials); -    context.setOutboundSAMLMessage(response); -    context.setOutboundMessageTransport(responseAdapter); +      // set endpoint url +      messageContext.addSubcontext(injectEndpointInfos(response, targetLocation)); -    encoder.encode(context); +      // 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 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 0bfd974e..1667a07d 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 @@ -21,8 +21,8 @@ package at.gv.egiz.eaaf.modules.pvp2.impl.builder;  import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils; -import org.opensaml.core.config.Configuration;  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; @@ -46,7 +46,7 @@ public class CitizenTokenBuilder {     */    public static XMLObject buildAttributeStringValue(final String value) {      final XSStringBuilder stringBuilder = -        (XSStringBuilder) Configuration.getBuilderFactory().getBuilder(XSString.TYPE_NAME); +        (XSStringBuilder) XMLObjectProviderRegistrySupport.getBuilderFactory().getBuilder(XSString.TYPE_NAME);      final XSString stringValue =          stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, XSString.TYPE_NAME);      stringValue.setValue(value); @@ -61,7 +61,7 @@ public class CitizenTokenBuilder {     */    public static XMLObject buildAttributeIntegerValue(final int value) {      final XSIntegerBuilder integerBuilder = -        (XSIntegerBuilder) Configuration.getBuilderFactory().getBuilder(XSInteger.TYPE_NAME); +        (XSIntegerBuilder) XMLObjectProviderRegistrySupport.getBuilderFactory().getBuilder(XSInteger.TYPE_NAME);      final XSInteger integerValue =          integerBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, XSInteger.TYPE_NAME);      integerValue.setValue(value); 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 index 9645c2c8..42f69a57 100644 --- 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 @@ -36,13 +36,13 @@ import javax.xml.transform.stream.StreamResult;  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;  import org.apache.commons.httpclient.auth.CredentialsNotAvailableException;  import org.apache.commons.lang3.StringUtils;  import org.joda.time.DateTime; +import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;  import org.opensaml.core.xml.io.Marshaller;  import org.opensaml.core.xml.io.MarshallingException;  import org.opensaml.saml.common.xml.SAMLConstants; @@ -176,12 +176,11 @@ public class PvpMetadataBuilder {        entitiesDescriptor.getEntityDescriptors().add(entityDescriptor);        // load default PVP security configurations -      EaafDefaultSaml2Bootstrap.initializeDefaultPvpConfiguration();        entitiesDescriptor.setSignature(signature);        // marshall document        final Marshaller out = -          org.opensaml.xml.Configuration.getMarshallerFactory().getMarshaller(entitiesDescriptor); +          XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(entitiesDescriptor);        out.marshall(entitiesDescriptor, document);      } else { @@ -192,7 +191,7 @@ public class PvpMetadataBuilder {        // marshall document        final Marshaller out = -          org.opensaml.xml.Configuration.getMarshallerFactory().getMarshaller(entityDescriptor); +          XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(entityDescriptor);        out.marshall(entityDescriptor, document);      } @@ -335,7 +334,8 @@ public class PvpMetadataBuilder {      attributeService.setIndex(0);      attributeService.setIsDefault(true);      final ServiceName serviceName = Saml2Utils.createSamlObject(ServiceName.class); -    serviceName.setName(new LocalizedString("Default Service", "en")); +    serviceName.setValue("Default Service"); +    serviceName.setXMLLang("en");      attributeService.getNames().add(serviceName);      if (reqSpAttr != null && reqSpAttr.size() > 0) { 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 0499cffa..d37d6724 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 @@ -22,8 +22,8 @@ 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 org.opensaml.core.config.Configuration;  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; @@ -35,7 +35,7 @@ public class SamlAttributeGenerator implements IAttributeGenerator<Attribute> {    private XMLObject buildAttributeStringValue(final String value) {      final XSStringBuilder stringBuilder = -        (XSStringBuilder) Configuration.getBuilderFactory().getBuilder(XSString.TYPE_NAME); +        (XSStringBuilder) XMLObjectProviderRegistrySupport.getBuilderFactory().getBuilder(XSString.TYPE_NAME);      final XSString stringValue =          stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, XSString.TYPE_NAME);      stringValue.setValue(value); @@ -44,7 +44,7 @@ public class SamlAttributeGenerator implements IAttributeGenerator<Attribute> {    private XMLObject buildAttributeIntegerValue(final int value) {      final XSIntegerBuilder integerBuilder = -        (XSIntegerBuilder) Configuration.getBuilderFactory().getBuilder(XSInteger.TYPE_NAME); +        (XSIntegerBuilder) XMLObjectProviderRegistrySupport.getBuilderFactory().getBuilder(XSInteger.TYPE_NAME);      final XSInteger integerValue =          integerBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, XSInteger.TYPE_NAME);      integerValue.setValue(value); 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 index e61f5e6e..726a2960 100644 --- 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 @@ -19,7 +19,7 @@  package at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr; -import org.opensaml.saml2.common.impl.ExtensionsImpl; +import org.opensaml.saml.saml2.core.impl.ExtensionsImpl;  public class EaafExtensionImplementation extends ExtensionsImpl { 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 index 25cbc6ef..c77193fd 100644 --- 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 @@ -19,15 +19,15 @@  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; +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.LOCAL_NAME, +    return buildObject(SAMLConstants.SAML20P_NS, Extensions.DEFAULT_ELEMENT_LOCAL_NAME,          SAMLConstants.SAML20P_PREFIX);    } 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 index 81d8d192..fde79998 100644 --- 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 @@ -19,11 +19,11 @@  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; +import org.opensaml.saml.common.AbstractSAMLObjectBuilder; +  public class EaafRequestedAttributeBuilder      extends AbstractSAMLObjectBuilder<EaafRequestedAttribute> { 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 index 749310f2..4acee141 100644 --- 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 @@ -23,14 +23,16 @@ import java.util.Map.Entry;  import javax.xml.namespace.QName; -import org.opensaml.common.impl.AbstractSAMLObjectMarshaller; -import org.opensaml.xml.XMLObject; -import org.opensaml.xml.io.MarshallingException; -import org.opensaml.xml.util.XMLHelper; +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 at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttribute; +import net.shibboleth.utilities.java.support.xml.AttributeSupport;  public class EaafRequestedAttributeMarshaller extends AbstractSAMLObjectMarshaller {    @Override @@ -60,10 +62,11 @@ public class EaafRequestedAttributeMarshaller extends AbstractSAMLObjectMarshall      Attr attr;      for (final Entry<QName, String> entry : requestedAttr.getUnknownAttributes().entrySet()) { -      attr = XMLHelper.constructAttribute(domElement.getOwnerDocument(), entry.getKey()); + +      attr = AttributeSupport.constructAttribute(domElement.getOwnerDocument(), entry.getKey());        attr.setValue(entry.getValue());        domElement.setAttributeNodeNS(attr); -      if (org.opensaml.xml.Configuration.isIDAttribute(entry.getKey()) +      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 index 35532e77..5313f340 100644 --- 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 @@ -21,15 +21,16 @@ 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; +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, @@ -64,7 +65,7 @@ public class EaafRequestedAttributeUnmarshaller extends AbstractSAMLObjectUnmars        requestedAttr.setIsRequired(attribute.getValue());      } else { -      final QName attribQName = XMLHelper.getNodeQName(attribute); +      final QName attribQName = QNameSupport.getNodeQName(attribute);        if (attribute.isId()) {          requestedAttr.getUnknownAttributes().registerID(attribQName);        } 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 index db08f87f..2d2de292 100644 --- 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 @@ -19,11 +19,11 @@  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; +import org.opensaml.saml.common.AbstractSAMLObjectBuilder; +  public class EaafRequestedAttributesBuilder      extends AbstractSAMLObjectBuilder<EaafRequestedAttributes> { 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 index 8aa70e5a..5d1e0679 100644 --- 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 @@ -19,7 +19,7 @@  package at.gv.egiz.eaaf.modules.pvp2.impl.builder.reqattr; -import org.opensaml.common.impl.AbstractSAMLObjectMarshaller; +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 index f616bbb0..9934c502 100644 --- 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 @@ -19,13 +19,13 @@  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; +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, 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..961f29cb --- /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,17 @@ +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 002db86f..8a741b69 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 @@ -25,18 +25,18 @@ import java.io.Serializable;  import javax.xml.parsers.ParserConfigurationException;  import javax.xml.transform.TransformerException; -import org.opensaml.saml2.metadata.EntityDescriptor; -import org.opensaml.saml2.metadata.provider.MetadataProviderException; +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.IPvp2MetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.exception.NoMetadataInformationException; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2MetadataException; + +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.exception.NoMetadataInformationException; -  public class InboundMessage implements InboundMessageInterface, Serializable {    private static final Logger log = LoggerFactory.getLogger(InboundMessage.class); @@ -56,7 +56,7 @@ public class InboundMessage implements InboundMessageInterface, Serializable {     * @return EntityDescriptor from metadata     * @throws NoMetadataInformationException In case of an error     */ -  public EntityDescriptor getEntityMetadata(final IPvpMetadataProvider metadataProvider) +  public EntityDescriptor getEntityMetadata(final IPvp2MetadataProvider metadataProvider)        throws NoMetadataInformationException {      try {        if (metadataProvider == null) { @@ -65,7 +65,7 @@ public class InboundMessage implements InboundMessageInterface, Serializable {        return metadataProvider.getEntityDescriptor(this.entityID); -    } catch (final MetadataProviderException e) { +    } catch (final Pvp2MetadataException e) {        log.warn("No Metadata for EntitiyID " + entityID);        throw new NoMetadataInformationException();      } 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 index 8a2cce3e..c6068769 100644 --- 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 @@ -19,10 +19,11 @@  package at.gv.egiz.eaaf.modules.pvp2.impl.message; -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.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; @@ -56,7 +57,7 @@ public class PvpSProfileRequest extends InboundMessage {     */    public SignableXMLObject getSamlRequest() {      final UnmarshallerFactory unmarshallerFactory = -        org.opensaml.xml.Configuration.getUnmarshallerFactory(); +        XMLObjectProviderRegistrySupport.getUnmarshallerFactory();      final Unmarshaller unmashaller = unmarshallerFactory.getUnmarshaller(getInboundMessage());      try { 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 index 8d1cbe8c..4ad21fbc 100644 --- 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 @@ -19,10 +19,11 @@  package at.gv.egiz.eaaf.modules.pvp2.impl.message; -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.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; @@ -43,7 +44,7 @@ public class PvpSProfileResponse extends InboundMessage {     */    public StatusResponseType getResponse() {      final UnmarshallerFactory unmarshallerFactory = -        org.opensaml.xml.Configuration.getUnmarshallerFactory(); +        XMLObjectProviderRegistrySupport.getUnmarshallerFactory();      final Unmarshaller unmashaller = unmarshallerFactory.getUnmarshaller(getInboundMessage());      try { 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 4a9bb89a..ec59b1df 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 @@ -21,48 +21,59 @@ 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 java.util.UUID; +import javax.annotation.Nonnull; +import javax.naming.ConfigurationException;  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 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.modules.pvp2.api.metadata.IPvp2MetadataProvider;  import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IRefreshableMetadataProvider; -public abstract class AbstractChainingMetadataProvider extends SimpleMetadataProvider -    implements ObservableMetadataProvider, IGarbageCollectorProcessing, -    IRefreshableMetadataProvider, IDestroyableObject, IPvpMetadataProvider { +import org.apache.commons.lang3.StringUtils; +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.EntitiesDescriptor; +import org.opensaml.saml.saml2.metadata.EntityDescriptor; +import org.opensaml.saml.saml2.metadata.RoleDescriptor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +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; + +public abstract class AbstractChainingMetadataProvider extends SimpleMetadataResolver +    implements IGarbageCollectorProcessing, IRefreshableMetadataProvider, IDestroyableObject, IPvp2MetadataProvider, +    RefreshableMetadataResolver, ClearableMetadataResolver {    private static final Logger log = LoggerFactory.getLogger(AbstractChainingMetadataProvider.class); -  private MetadataProvider internalProvider = null; +  @Nonnull @NonnullElements private final List<MetadataResolver> internalResolvers;    private static Object mutex = new Object();    private Timer timer = null; +  /** +   * Build a chaining metadata resolver that requires valid metadata. +   * +   */    public AbstractChainingMetadataProvider() { -    internalProvider = new ChainingMetadataProvider(); +    internalResolvers = Collections.synchronizedList(Collections.emptyList());    } @@ -102,30 +113,34 @@ public abstract class AbstractChainingMetadataProvider extends SimpleMetadataPro    } + +    @Override -  public synchronized boolean refreshMetadataProvider(final String entityID) { +  public synchronized boolean refreshMetadataProvider(final String entityId) {      try {        // check if metadata provider is already loaded        try { -        if (internalProvider.getEntityDescriptor(entityID) != null) { +        if (resolveEntityDescripor(entityId) != null) {            return true; +          } -      } catch (final MetadataProviderException e) { -        log.debug("Metadata for EntityId: {} is not valid. Starting refresh ... ", entityID); +      } catch (final ResolverException e) { +        log.debug("Metadata for EntityId: {} is not valid. Starting refresh ... ", entityId);        }        // reload metadata provider -      final String metadataUrl = getMetadataUrl(entityID); +      final String metadataUrl = getMetadataUrl(entityId);        if (StringUtils.isNotEmpty(metadataUrl)) { -        final Map<String, HTTPMetadataProvider> actuallyLoadedProviders = -            getAllActuallyLoadedProviders(); +        final Map<String, MetadataResolver> actuallyLoadedResolver = +            getAllActuallyLoadedResolvers();          // check if MetadataProvider is actually loaded -        if (actuallyLoadedProviders.containsKey(metadataUrl)) { -          actuallyLoadedProviders.get(metadataUrl).refresh(); -          log.info("SAML2 metadata for service provider: " + entityID + " is refreshed."); +        final MetadataResolver loadedResover = actuallyLoadedResolver.get(metadataUrl); +        if (loadedResover instanceof RefreshableMetadataResolver) { +          ((RefreshableMetadataResolver)loadedResover).refresh(); +          log.info("SAML2 metadata for service provider: " + entityId + " is refreshed.");            return true;          } else { @@ -134,32 +149,20 @@ public abstract class AbstractChainingMetadataProvider extends SimpleMetadataPro              timer = new Timer(true);            } -          final ChainingMetadataProvider chainProvider = -              (ChainingMetadataProvider) internalProvider; -          chainProvider.addMetadataProvider(createNewMetadataProvider(entityID)); +          internalResolvers.add(createNewMetadataProvider(metadataUrl)); -          emitChangeEvent(); -          log.info("SAML2 metadata for service provider: " + entityID + " is added."); +          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); +            "Can not refresh SAML2 metadata: NO SAML2 metadata URL for SP with Id: " + entityId);        } -    } catch (final MetadataProviderException e) { -      log.warn("Refresh SAML2 metadata for service provider: " + entityID + " FAILED.", e); - -    } catch (final IOException e) { -      log.warn("Refresh SAML2 metadata for service provider: " + entityID + " FAILED.", e); - -    } catch (final EaafConfigurationException e) { -      log.warn("Refresh SAML2 metadata for service provider: " + entityID + " FAILED.", e); - -    } catch (final CertificateException e) { -      log.warn("Refresh SAML2 metadata for service provider: " + entityID + " FAILED.", e); +    } catch (final IOException | ResolverException | EaafConfigurationException | CertificateException e) { +      log.warn("Refresh SAML2 metadata for service provider: " + entityId + " FAILED.", e);      } @@ -172,55 +175,20 @@ public abstract class AbstractChainingMetadataProvider extends SimpleMetadataPro     *     */    public void internalDestroy() { -    if (internalProvider != null && internalProvider instanceof ChainingMetadataProvider) { -      log.info("Destrorying PVP-Authentication MetaDataProvider."); -      final ChainingMetadataProvider chainProvider = (ChainingMetadataProvider) internalProvider; - -      final List<MetadataProvider> providers = chainProvider.getProviders(); -      for (final MetadataProvider provider : providers) { -        if (provider instanceof HTTPMetadataProvider) { -          final HTTPMetadataProvider httpprovider = (HTTPMetadataProvider) provider; -          log.debug("Destroy HTTPMetadataProvider +" + httpprovider.getMetadataURI()); -          httpprovider.destroy(); +      log.info("Destroying chained metadata resolvers ..."); -        } else { -          log.warn("MetadataProvider can not be destroyed."); -        } +      for (final MetadataResolver resolver : internalResolvers) { +        destroyMetadataResolver(resolver);        } -      internalProvider = new ChainingMetadataProvider(); +      internalResolvers.clear();        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(final boolean requireValidMetadata) { -    internalProvider.setRequireValidMetadata(requireValidMetadata); -  }    /*     * (non-Javadoc) @@ -359,18 +327,6 @@ public abstract class AbstractChainingMetadataProvider extends SimpleMetadataPro      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.     * @@ -384,13 +340,13 @@ public abstract class AbstractChainingMetadataProvider extends SimpleMetadataPro     * Creates a new implementation specific SAML2 metadata provider.     *     * @param entityId EntityId -   * @return MetadataProvider +   * @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 MetadataProvider createNewMetadataProvider(String entityId) +  protected abstract MetadataResolver createNewMetadataProvider(String entityId)        throws EaafConfigurationException, IOException, CertificateException;    /** @@ -398,33 +354,25 @@ public abstract class AbstractChainingMetadataProvider extends SimpleMetadataPro     *     * @throws EaafConfigurationException In case of an error     */ +  @Nonnull    protected abstract List<String> getAllMetadataUrlsFromConfiguration()        throws EaafConfigurationException; -  protected void emitChangeEvent() { -    if (getObservers() == null || getObservers().size() == 0) { -      return; -    } - -    final List<Observer> tempObserverList = new ArrayList<>(getObservers()); -    for (final ObservableMetadataProvider.Observer observer : tempObserverList) { -      if (observer != null) { -        observer.onEvent(this); -      } -    } -  } -  private Map<String, HTTPMetadataProvider> getAllActuallyLoadedProviders() { -    final Map<String, HTTPMetadataProvider> loadedproviders = +  private Map<String, MetadataResolver> getAllActuallyLoadedResolvers() { +    final Map<String, MetadataResolver> loadedproviders =          new HashMap<>(); -    final ChainingMetadataProvider chainProvider = (ChainingMetadataProvider) internalProvider;      // make a Map of all actually loaded HTTPMetadataProvider -    final List<MetadataProvider> providers = chainProvider.getProviders(); -    for (final MetadataProvider provider : providers) { -      if (provider instanceof HTTPMetadataProvider) { -        final HTTPMetadataProvider httpprovider = (HTTPMetadataProvider) provider; -        loadedproviders.put(httpprovider.getMetadataURI(), httpprovider); +    for (final MetadataResolver resolver : internalResolvers) { +      if (resolver instanceof IdentifiedComponent) { +        loadedproviders.put(((IdentifiedComponent) resolver).getId(), resolver); + +      } else { +        final String uuid = UUID.randomUUID().toString(); +        loadedproviders.put(uuid, resolver); +        log.debug("MetadatenResolver is not of type: {}. Mark it with id: {}", +            IdentifiedComponent.class.getSimpleName(), uuid);        }      } @@ -433,19 +381,17 @@ public abstract class AbstractChainingMetadataProvider extends SimpleMetadataPro    }    private void addAndRemoveMetadataProvider() throws EaafConfigurationException { -    if (internalProvider != null && internalProvider instanceof ChainingMetadataProvider) { -      log.info("Reload MOAMetaDataProvider."); +      log.info("EAAF chaining metadata resolver starting internal managment task .... ");        /*         * OpenSAML ChainingMetadataProvider can not remove a MetadataProvider         * (UnsupportedOperationException) The ChainingMetadataProvider use internal a         * unmodifiableList to hold all registrated MetadataProviders.         */ -      final Map<String, MetadataProvider> providersinuse = new HashMap<>(); -      final ChainingMetadataProvider chainProvider = (ChainingMetadataProvider) internalProvider; +      final Map<String, MetadataResolver> providersinuse = new HashMap<>();        // get all actually loaded metadata providers -      final Map<String, HTTPMetadataProvider> loadedproviders = getAllActuallyLoadedProviders(); +      final Map<String, MetadataResolver> loadedproviders = getAllActuallyLoadedResolvers();        /*         * TODO: maybe add metadata provider destroy after timeout. But could be a @@ -460,7 +406,6 @@ public abstract class AbstractChainingMetadataProvider extends SimpleMetadataPro        // compare actually loaded Providers with configured SAML2 SPs        final List<String> allMetadataUrls = getAllMetadataUrlsFromConfiguration(); -      if (allMetadataUrls != null) {          final Iterator<String> metadataUrlInterator = allMetadataUrls.iterator();          while (metadataUrlInterator.hasNext()) {            final String metadataurl = metadataUrlInterator.next(); @@ -477,15 +422,15 @@ public abstract class AbstractChainingMetadataProvider extends SimpleMetadataPro            }          } -      } +        // remove all actually loaded MetadataProviders with are not in ConfigurationDB        // any more -      final Collection<HTTPMetadataProvider> notusedproviders = loadedproviders.values(); -      for (final HTTPMetadataProvider provider : notusedproviders) { -        final String metadataurl = provider.getMetadataURI(); -        try { -          provider.destroy(); +      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);            /*             * OpenSAML ChainingMetadataProvider can not remove a MetadataProvider @@ -493,31 +438,43 @@ public abstract class AbstractChainingMetadataProvider extends SimpleMetadataPro             * unmodifiableList to hold all registrated MetadataProviders.             */            // chainProvider.removeMetadataProvider(provider); -          log.info("Remove not used MetadataProvider with MetadataURL " + metadataurl); -        } catch (final Throwable e) { -          log.error("HTTPMetadataProvider with URL " + metadataurl -              + " can not be removed from the list of actually loaded Providers.", e); - -        }        } +  } + +  private EntityDescriptor resolveEntityDescripor(String entityId) throws ResolverException { +    final CriteriaSet criteria = new CriteriaSet(); +    criteria.add(new EntityIdCriterion(entityId)); +    for (final MetadataResolver resolver : internalResolvers) {        try { -        chainProvider.setProviders(new ArrayList<>(providersinuse.values())); -        emitChangeEvent(); +          final EntityDescriptor descriptors = resolver.resolveSingle(criteria); +          if (descriptors != null) { +              return descriptors; +          } -      } catch (final MetadataProviderException e) { -        log.warn( -            "ReInitalize AbstractMetaDataProvider is not possible! Service has to be restarted manualy", -            e); +      } catch (final ResolverException e) { +          continue;        } -    } else { -      log.warn( -          "ReInitalize AbstractMetaDataProvider is not possible! Service has to be restarted manualy");      } +    return null; + +  } + +  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()); + +    }    }  } 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 ebc057df..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/MetadataFilterChain.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.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; - -/** - * Metadata filter-chain implementation. - * - * @author tlenz - * - */ -public class MetadataFilterChain implements MetadataFilter { -  private static final Logger log = LoggerFactory.getLogger(MetadataFilterChain.class); - -  private final List<MetadataFilter> filters = new ArrayList<>(); - -  /** -   * 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 add a metadata filter -   */ -  public void addFilter(final MetadataFilter filter) { -    filters.add(filter); -  } - -  /* -   * (non-Javadoc) -   * -   * @see -   * org.opensaml.saml2.metadata.provider.MetadataFilter#doFilter(org.opensaml.xml -   * .XMLObject) -   */ -  @Override -  public void doFilter(final XMLObject arg0) throws FilterException { -    for (final 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/SimpleMetadataProvider.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/metadata/SimpleMetadataResolver.java index d63950cb..35ad3f97 100644 --- 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/SimpleMetadataResolver.java @@ -25,30 +25,29 @@ 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; +import org.apache.http.client.HttpClient; +import org.opensaml.saml.metadata.resolver.MetadataResolver; +import org.opensaml.saml.metadata.resolver.filter.MetadataFilter; +import org.opensaml.saml.metadata.resolver.impl.FilesystemMetadataResolver; +import org.opensaml.saml.metadata.resolver.impl.HTTPMetadataResolver; +import org.springframework.beans.factory.annotation.Autowired; + +import lombok.extern.slf4j.Slf4j; +import net.shibboleth.utilities.java.support.xml.ParserPool; +  /**   * Simple SAML2 metadata provider.   *   * @author tlenz   *   */ -public abstract class SimpleMetadataProvider implements MetadataProvider { -  private static final Logger log = LoggerFactory.getLogger(SimpleMetadataProvider.class); - +@Slf4j +public abstract class SimpleMetadataResolver implements MetadataResolver {    private static final String URI_PREFIX_HTTP = "http:";    private static final String URI_PREFIX_HTTPS = "https:";    private static final String URI_PREFIX_FILE = "file:"; @@ -56,6 +55,21 @@ public abstract class SimpleMetadataProvider implements MetadataProvider {    @Autowired    protected IConfiguration authConfig; +  @Override +  public final boolean isRequireValidMetadata() { +    return true; + +  } + +  @Override +  public final void setRequireValidMetadata(final boolean requireValidMetadata) { +    log.warn("EAAF {} requires always valid metadata. Setting will be ignored", +        SimpleMetadataResolver.class.getSimpleName()); + +  } + + +    /**     * Create a single SAML2 metadata provider.     * @@ -74,7 +88,7 @@ public abstract class SimpleMetadataProvider implements MetadataProvider {     * @return SAML2 Metadata Provider, or null if the metadata provider can not     *         initialized     */ -  protected MetadataProvider createNewSimpleMetadataProvider(final String metadataLocation, +  protected MetadataResolver createNewSimpleMetadataProvider(final String metadataLocation,        final MetadataFilter filter, final String idForLogging, final Timer timer,        final ParserPool pool, final HttpClient httpClient) {      if (metadataLocation.startsWith(URI_PREFIX_HTTP) @@ -130,24 +144,24 @@ public abstract class SimpleMetadataProvider implements MetadataProvider {     *     * @return SAML2 Metadata Provider     */ -  private MetadataProvider createNewFileSystemMetaDataProvider(final File metadataFile, +  private MetadataResolver createNewFileSystemMetaDataProvider(final File metadataFile,        final MetadataFilter filter, final String idForLogging, final Timer timer,        final ParserPool pool) { -    FilesystemMetadataProvider fileSystemProvider = null; +    FilesystemMetadataResolver fileSystemResolver = 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); +      fileSystemResolver = new FilesystemMetadataResolver(timer, metadataFile); +      fileSystemResolver.setParserPool(pool); +      fileSystemResolver.setRequireValidMetadata(true); +      fileSystemResolver.setMinRefreshDelay(1000 * 60 * 15); // 15 minutes +      fileSystemResolver.setMaxRefreshDelay(1000 * 60 * 60 * 24); // 24 hours -      fileSystemProvider.setMetadataFilter(filter); -      fileSystemProvider.initialize(); +      fileSystemResolver.setMetadataFilter(filter); +      fileSystemResolver.initialize(); +      fileSystemResolver.setId(metadataFile.getAbsolutePath()); -      fileSystemProvider.setRequireValidMetadata(true); +      fileSystemResolver.setRequireValidMetadata(true); -      return fileSystemProvider; +      return fileSystemResolver;      } catch (final Exception e) {        log.warn("Failed to load Metadata file for " + idForLogging + "[ " + "File: " @@ -156,8 +170,9 @@ public abstract class SimpleMetadataProvider implements MetadataProvider {        log.warn("Can not initialize SAML2 metadata provider from filesystem: "            + metadataFile.getAbsolutePath() + " Reason: " + e.getMessage(), e); -      if (fileSystemProvider != null) { -        fileSystemProvider.destroy(); +      if (fileSystemResolver != null) { +        fileSystemResolver.destroy(); +        }      } @@ -178,24 +193,25 @@ public abstract class SimpleMetadataProvider implements MetadataProvider {     *     * @return SAML2 Metadata Provider     */ -  private MetadataProvider createNewHttpMetaDataProvider(final String metadataUrl, +  private MetadataResolver createNewHttpMetaDataProvider(final String metadataUrl,        final MetadataFilter filter, final String idForLogging, final Timer timer,        final ParserPool pool, final HttpClient httpClient) { -    HTTPMetadataProvider httpProvider = null; +    HTTPMetadataResolver httpMetadataResolver = 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 +      httpMetadataResolver = new HTTPMetadataResolver(timer, httpClient, metadataUrl); +      httpMetadataResolver.setParserPool(pool); +      httpMetadataResolver.setRequireValidMetadata(true); +      httpMetadataResolver.setMinRefreshDelay(1000 * 60 * 15); // 15 minutes +      httpMetadataResolver.setMaxRefreshDelay(1000 * 60 * 60 * 24); // 24 hours        // httpProvider.setRefreshDelayFactor(0.1F); -      httpProvider.setMetadataFilter(filter); -      httpProvider.initialize(); +      httpMetadataResolver.setMetadataFilter(filter); +      httpMetadataResolver.setId(metadataUrl); +      httpMetadataResolver.initialize(); -      httpProvider.setRequireValidMetadata(true); +      httpMetadataResolver.setRequireValidMetadata(true); -      return httpProvider; +      return httpMetadataResolver;      } catch (final Throwable e) {        if (e.getCause() != null && e.getCause().getCause() instanceof SSLHandshakeException) { @@ -213,15 +229,11 @@ public abstract class SimpleMetadataProvider implements MetadataProvider {        log.warn("Failed to load Metadata file for " + idForLogging + "[ " + e.getMessage() + " ]",            e); -      if (httpProvider != null) { +      if (httpMetadataResolver != null) {          log.debug("Destroy failed Metadata provider"); -        httpProvider.destroy(); -      } +        httpMetadataResolver.destroy(); -      // if (timer != null) { -      // log.debug("Destroy Timer."); -      // timer.cancel(); -      // } +      }      } 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..dc60019a --- /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,77 @@ +package at.gv.egiz.eaaf.modules.pvp2.impl.opensaml; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import javax.servlet.http.HttpServletRequest; + +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 { + +  @Override +  protected InputStream getBase64DecodedMessage(final HttpServletRequest request) +      throws MessageDecodingException { + +    log.debug("Getting Base64 encoded message from request"); +    String encodedMessage = getLastParameterFromRequest(request, "SAMLRequest"); +    if (Strings.isNullOrEmpty(encodedMessage)) { +      encodedMessage = getLastParameterFromRequest(request, "SAMLResponse"); +    } + + + +    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:\n{}", encodedMessage); +    final byte[] decodedBytes = Base64Support.decode(encodedMessage); +    if (decodedBytes == null) { +      log.info("Unable to Base64 decode SAML message"); +      throw new MessageDecodingException("Unable to Base64 decode SAML message"); +    } + +    log.trace("Decoded SAML message:\n{}", new String(decodedBytes)); +    return new ByteArrayInputStream(decodedBytes); +  } + +  /** +   * 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 +  private 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/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..e9140f26 --- /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,71 @@ +package at.gv.egiz.eaaf.modules.pvp2.impl.opensaml; + +import java.io.InputStream; + +import javax.servlet.http.HttpServletRequest; + +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.net.URISupport; +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 { + +  @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 queryString = getHttpServletRequest().getQueryString(); +    if (!Strings.isNullOrEmpty(URISupport.getRawQueryStringParameter(queryString, "SAMLRequest"))) { +      samlMessageIns = decodeMessage(URISupport.getRawQueryStringParameter(queryString, "SAMLRequest")); +    } else if (!Strings.isNullOrEmpty(URISupport.getRawQueryStringParameter(queryString, "SAMLResponse"))) { +      samlMessageIns = decodeMessage(URISupport.getRawQueryStringParameter(queryString, "SAMLResponse")); +    } 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); +  } + +} 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 index 92d8f4b9..7c433c1c 100644 --- 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 @@ -21,7 +21,19 @@ package at.gv.egiz.eaaf.modules.pvp2.impl.opensaml;  import java.security.KeyStore; -import org.opensaml.xml.security.x509.X509Credential; +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. @@ -29,8 +41,11 @@ import org.opensaml.xml.security.x509.X509Credential;   * @author tlenz   *   */ -public class EaafKeyStoreX509CredentialAdapter -    extends org.opensaml.xml.security.x509.KeyStoreX509CredentialAdapter { +@Slf4j +public class EaafKeyStoreX509CredentialAdapter extends KeyStoreX509CredentialAdapter +    implements EaafX509Credential { + +  private String signatureAlgorithmtToUse;    /**     * Get an OpenSAML2 keystore. @@ -38,10 +53,31 @@ public class EaafKeyStoreX509CredentialAdapter     * @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(final KeyStore store, final String alias, -      final char[] password) { +  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.getSignatureAlgorithm(this, +          PvpConstants.DEFAULT_SIGNING_METHODE_RSA, +          PvpConstants.DEFAULT_SIGNING_METHODE_EC)); + +    } catch (final SamlSigningException e) { +      throw new CredentialsNotAvailableException("internal.pvp.01", new Object[] {keyStoreFriendlyName, alias}, e); + +    } +    }    @Override @@ -49,4 +85,16 @@ public class EaafKeyStoreX509CredentialAdapter      return X509Credential.class;    } +  @Override +  public String getSignatureAlgorithmForSigning() { +    return this.signatureAlgorithmtToUse; + +  } + +  @Override +  public void setSignatureAlgorithmForSigning(String sigAlg) { +    this.signatureAlgorithmtToUse = 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 index 404b4e8e..3650e617 100644 --- 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 @@ -19,6 +19,7 @@  package at.gv.egiz.eaaf.modules.pvp2.impl.opensaml; +  import java.io.BufferedReader;  import java.io.IOException;  import java.io.InputStream; @@ -26,18 +27,21 @@ 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 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. @@ -45,10 +49,9 @@ import at.gv.egiz.eaaf.core.api.gui.IVelocityGuiFormBuilder;   * @author tlenz   *   */ +@Slf4j  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; @@ -57,29 +60,28 @@ public class HttpPostEncoderWithOwnTemplate extends HTTPPostEncoder {     *     * @param guiConfig  GUI configuration     * @param guiBuilder GUI builder implementation -   * @param engine     velocity engine +   * @throws Exception In case of a {@link Velocity} initialization error     */    public HttpPostEncoderWithOwnTemplate(final IVelocityGuiBuilderConfiguration guiConfig, -      final IVelocityGuiFormBuilder guiBuilder, final VelocityEngine engine) { -    super(engine, null); -    this.velocityEngine = engine; +      final IVelocityGuiFormBuilder guiBuilder) throws Exception {      this.guiConfig = guiConfig;      this.guiBuilder = guiBuilder; +    setVelocityEngine(VelocityProvider.getClassPathVelocityEngine()); +    }    /** -   * Base64 and POST encodes the outbound message and writes it to the outbound +   * Base64 and POST encodes the out-bound message and writes it to the out-bound     * 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(final SAMLMessageContext messageContext, final String endpointUrl) +  protected void postEncode(final MessageContext<SAMLObject> messageContext, final String endpointUrl)        throws MessageEncodingException {      log.debug("Invoking Velocity template to create POST body");      InputStream is = null; @@ -91,19 +93,16 @@ public class HttpPostEncoderWithOwnTemplate extends HTTPPostEncoder {        // 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"); +      final HttpServletResponse response = getHttpServletResponse(); -      // evaluate template and write content to response -      final Writer out = new OutputStreamWriter(outTransport.getOutgoingStream(), "UTF-8"); -      velocityEngine.evaluate(context, out, "SAML2_POST_BINDING", +      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(); @@ -123,4 +122,5 @@ public class HttpPostEncoderWithOwnTemplate extends HTTPPostEncoder {      }    } +  } 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 8838daec..bd450518 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 @@ -19,15 +19,13 @@  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.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 org.slf4j.Logger;  import org.slf4j.LoggerFactory; -import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafDefaultSaml2Bootstrap; -  /**   * Create deflate encoded SAML2 redirect-binding informations.   * @@ -40,27 +38,18 @@ public class StringRedirectDeflateEncoder extends HTTPRedirectDeflateEncoder {    private String redirectUrl = null;    @Override -  public void encode(final 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"); -    } - -    // load default PVP security configurations -    EaafDefaultSaml2Bootstrap.initializeDefaultPvpConfiguration(); - -    final SAMLMessageContext samlMsgCtx = (SAMLMessageContext) messageContext; +  protected void doEncode() throws MessageEncodingException { +    final MessageContext<SAMLObject> messageContext = getMessageContext(); +    final SAMLObject outboundMessage = messageContext.getMessage(); -    final String endpointUrl = getEndpointURL(samlMsgCtx).buildURL(); +    final String endpointUrl = getEndpointURL(messageContext).toString(); -    setResponseDestination(samlMsgCtx.getOutboundSAMLMessage(), endpointUrl); +    removeSignature(outboundMessage); -    removeSignature(samlMsgCtx); +    final String encodedMessage = deflateAndBase64Encode(outboundMessage); -    final String encodedMessage = deflateAndBase64Encode(samlMsgCtx.getOutboundSAMLMessage()); +    redirectUrl = buildRedirectURL(messageContext, endpointUrl, encodedMessage); -    redirectUrl = buildRedirectURL(samlMsgCtx, endpointUrl, encodedMessage);    }    /** 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 9625b591..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,88 +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.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; - -/** - * EAAF specific OpenSAML Initializer. - * - * @author tlenz - * - */ -public class EaafDefaultSaml2Bootstrap extends DefaultBootstrap { - -  /** -   * OpenSAML2 bootstrap. -   * -   * @throws ConfigurationException In case of an error -   */ -  public static synchronized void bootstrap() throws ConfigurationException { - -    initializeXMLSecurity(); - -    initializeXMLTooling(); - -    initializeArtifactBuilderFactories(); - -    initializeGlobalSecurityConfiguration(); - -    initializeParserPool(); - -    initializeESAPI(); - -    initializeExtenstions(); - -  } - -  private static void initializeExtenstions() { -    org.opensaml.xml.Configuration.registerObjectProvider( -        EaafRequestedAttribute.DEFAULT_ELEMENT_NAME, new EaafRequestedAttributeBuilder(), -        new EaafRequestedAttributeMarshaller(), new EaafRequestedAttributeUnmarshaller()); - -    org.opensaml.xml.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() { -    org.opensaml.xml.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 index f3e50e4e..97f0f225 100644 --- 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 @@ -19,14 +19,17 @@  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; +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. @@ -38,102 +41,137 @@ public class EaafDefaultSecurityConfigurationBootstrap      extends DefaultSecurityConfigurationBootstrap {    /** -   * Build EAAF security configuration for OpenSAML2. +   * Set EAAF specific encryption configuration to OpenSAML 3.x.     *     * @return     */ -  public static BasicSecurityConfiguration buildDefaultConfig() { -    final BasicSecurityConfiguration config = new BasicSecurityConfiguration(); - -    populateSignatureParams(config); -    populateEncryptionParams(config); -    populateKeyInfoCredentialResolverParams(config); -    populateKeyInfoGeneratorManager(config); -    populateKeyParams(config); +  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;    } -  protected static void populateKeyInfoGeneratorManager(final BasicSecurityConfiguration config) { -    final NamedKeyInfoGeneratorManager namedManager = new NamedKeyInfoGeneratorManager(); -    config.setKeyInfoGeneratorManager(namedManager); - -    namedManager.setUseDefaultManager(true); -    final KeyInfoGeneratorManager defaultManager = namedManager.getDefaultManager(); +  /** +   * Set EAAF specific decryption configuration to OpenSAML 3.x. +   * +   * @return +   */ +  public static BasicDecryptionConfiguration buildEaaftDecryptionConfiguration() { +    final BasicDecryptionConfiguration config = new BasicDecryptionConfiguration(); -    final BasicKeyInfoGeneratorFactory basicFactory = new BasicKeyInfoGeneratorFactory(); -    basicFactory.setEmitPublicKeyValue(true); +    config.setBlacklistedAlgorithms(Collections.singletonList( +        EncryptionConstants.ALGO_ID_KEYTRANSPORT_RSA15)); -    final X509KeyInfoGeneratorFactory x509Factory = new X509KeyInfoGeneratorFactory(); -    x509Factory.setEmitEntityCertificate(true); +    config.setEncryptedKeyResolver(buildBasicEncryptedKeyResolver()); -    defaultManager.registerFactory(basicFactory); -    defaultManager.registerFactory(x509Factory); +    return config;    } -  protected static void populateSignatureParams(final 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); +  /** +   * 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()); -    // use SHA256 instead of SHA1 -    config.setSignatureReferenceDigestMethod(SignatureConstants.ALGO_ID_DIGEST_SHA256); +    return config;    } -  protected static void populateEncryptionParams(final 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"); +  /** +   * 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..42d4d736 --- /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,156 @@ +/* + * 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 +   */ +  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 index e91ee19c..e391bb31 100644 --- 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 @@ -23,14 +23,14 @@ 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; +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 { 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 index eefc166b..9c251233 100644 --- 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 @@ -23,13 +23,13 @@ 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; +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 { 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 c0b015be..336741a0 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 @@ -29,18 +29,21 @@ import java.security.interfaces.RSAPrivateKey;  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.utils.KeyStoreUtils; +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.opensaml.EaafKeyStoreX509CredentialAdapter;  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.opensaml.security.credential.Credential; +import org.opensaml.security.credential.UsageType; +import org.opensaml.xmlsec.signature.Signature; +import org.opensaml.xmlsec.signature.support.SignatureConstants;  import org.slf4j.Logger;  import org.slf4j.LoggerFactory;  import org.springframework.beans.factory.annotation.Autowired; @@ -50,7 +53,10 @@ import org.springframework.core.io.ResourceLoader;  public abstract class AbstractCredentialProvider { -  @Autowired protected ResourceLoader resourceLoader; +  @Autowired +  protected ResourceLoader resourceLoader; +  @Autowired +  protected IConfiguration basicConfig;    private static final Logger log = LoggerFactory.getLogger(AbstractCredentialProvider.class); @@ -127,24 +133,26 @@ public abstract class AbstractCredentialProvider {     * @return Credentials     * @throws CredentialsNotAvailableException In case of a credential error     */ -  public X509Credential getIdpMetaDataSigningCredential() throws CredentialsNotAvailableException { +  public EaafX509Credential getIdpMetaDataSigningCredential() throws CredentialsNotAvailableException {      try {        final EaafKeyStoreX509CredentialAdapter credentials = new EaafKeyStoreX509CredentialAdapter(keyStore, -          getMetadataKeyAlias(), getMetadataKeyPassword().toCharArray()); +          getMetadataKeyAlias(), getMetadataKeyPassword().toCharArray(), getFriendlyName());        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." }); - -      } +      credentials.setSignatureAlgorithmForSigning(Saml2Utils.getSignatureAlgorithm( +          credentials, +          basicConfig.getBasicConfiguration( +              PvpConstants.CONFIG_PROP_SEC_SIGNING_RSA_ALG, +              PvpConstants.DEFAULT_SIGNING_METHODE_RSA), +          basicConfig.getBasicConfiguration( +              PvpConstants.CONFIG_PROP_SEC_SIGNING_RSA_ALG, +              PvpConstants.DEFAULT_SIGNING_METHODE_EC)));        return credentials; -    } catch (final Exception e) { -      log.error("Failed to generate " + getFriendlyName() + " Metadata Signing credentials", e); -      throw new CredentialsNotAvailableException("config.27", new Object[] { e.getMessage() }, e); + +    } catch (final SamlSigningException e) { +      throw new CredentialsNotAvailableException("internal.pvp.01", +          new Object[] { getFriendlyName(), getMetadataKeyAlias() }, e); +      }    } @@ -154,25 +162,27 @@ public abstract class AbstractCredentialProvider {     * @return Credentials     * @throws CredentialsNotAvailableException In case of a credential error     */ -  public X509Credential getIdpAssertionSigningCredential() throws CredentialsNotAvailableException { +  public EaafX509Credential getIdpAssertionSigningCredential() throws CredentialsNotAvailableException {      try {        final EaafKeyStoreX509CredentialAdapter credentials = new EaafKeyStoreX509CredentialAdapter(keyStore, -          getSignatureKeyAlias(), getSignatureKeyPassword().toCharArray()); +          getSignatureKeyAlias(), getSignatureKeyPassword().toCharArray(), getFriendlyName());        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." }); - -      } +      credentials.setSignatureAlgorithmForSigning(Saml2Utils.getSignatureAlgorithm( +          credentials, +          basicConfig.getBasicConfiguration( +              PvpConstants.CONFIG_PROP_SEC_SIGNING_RSA_ALG, +              PvpConstants.DEFAULT_SIGNING_METHODE_RSA), +          basicConfig.getBasicConfiguration( +              PvpConstants.CONFIG_PROP_SEC_SIGNING_RSA_ALG, +              PvpConstants.DEFAULT_SIGNING_METHODE_EC)));        return credentials; +      } catch (final Exception e) { -      log.error("Failed to generate " + getFriendlyName() + " Assertion Signing credentials", e); -      throw new CredentialsNotAvailableException("config.27", new Object[] { e.getMessage() }, e); +      throw new CredentialsNotAvailableException("internal.pvp.01", +          new Object[] { getFriendlyName(), getSignatureKeyAlias() }, e); +      }    } @@ -182,34 +192,18 @@ public abstract class AbstractCredentialProvider {     * @return Credentials     * @throws CredentialsNotAvailableException In case of a credential error     */ -  public X509Credential getIdpAssertionEncryptionCredential() +  public EaafX509Credential getIdpAssertionEncryptionCredential()        throws CredentialsNotAvailableException { -    try { -      // if no encryption key is configured return null -      if (StringUtils.isEmpty(getEncryptionKeyAlias())) { -        return null; -      } - -      final EaafKeyStoreX509CredentialAdapter credentials = new EaafKeyStoreX509CredentialAdapter(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." }); - -      } +    // if no encryption key is configured return null +    if (StringUtils.isEmpty(getEncryptionKeyAlias())) { +      return null; +    } -      return credentials; +    final EaafKeyStoreX509CredentialAdapter credentials = new EaafKeyStoreX509CredentialAdapter(keyStore, +        getEncryptionKeyAlias(), getEncryptionKeyPassword().toCharArray(), getFriendlyName()); +    credentials.setUsageType(UsageType.ENCRYPTION); +    return credentials; -    } catch (final Exception e) { -      log.error("Failed to generate " + getFriendlyName() + " Assertion Encryption credentials", e); -      throw new CredentialsNotAvailableException("config.27", new Object[] { e.getMessage() }, e); -    }    }    /** @@ -218,6 +212,7 @@ public abstract class AbstractCredentialProvider {     * @param credentials Credentials for signing     * @return OpenSAML Signature object     */ +  @Deprecated    public static Signature getIdpSignature(final Credential credentials) {      final PrivateKey privatekey = credentials.getPrivateKey();      final Signature signer = Saml2Utils.createSamlObject(Signature.class); @@ -250,7 +245,7 @@ public abstract class AbstractCredentialProvider {        if (keyStore == null) {          throw new EaafConfigurationException("module.00", -            new Object[] {getFriendlyName(), "KeyStore initialization failed. Maybe wrong password"}); +            new Object[] { getFriendlyName(), "KeyStore initialization failed. Maybe wrong password" });        } 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 index 1a282b55..8b1b041b 100644 --- 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 @@ -20,8 +20,13 @@  package at.gv.egiz.eaaf.modules.pvp2.impl.utils;  import java.io.IOException; +import java.security.PrivateKey; +import java.security.interfaces.ECPrivateKey; +import java.security.interfaces.ECPublicKey; +import java.security.interfaces.RSAPrivateKey;  import java.util.List; +import javax.annotation.Nonnull;  import javax.xml.namespace.QName;  import javax.xml.parsers.DocumentBuilder;  import javax.xml.parsers.DocumentBuilderFactory; @@ -31,35 +36,60 @@ import javax.xml.transform.dom.DOMSource;  import javax.xml.validation.Schema;  import javax.xml.validation.Validator; +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 org.apache.commons.collections4.CollectionUtils;  import org.apache.commons.lang3.StringUtils; -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.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.schema.XSString; +import org.opensaml.core.xml.schema.impl.XSStringBuilder; +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 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);    private static DocumentBuilder builder; +  private static SAMLSchemaBuilder schemaBuilder;    static { +    schemaBuilder = new SAMLSchemaBuilder(SAML1Version.SAML_11); +      final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();      factory.setNamespaceAware(true); @@ -73,16 +103,144 @@ public class Saml2Utils {    }    /** +   * 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 = getSignatureAlgorithm(signingCredential, +          PvpConstants.DEFAULT_SIGNING_METHODE_RSA, +          PvpConstants.DEFAULT_SIGNING_METHODE_EC); + +      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); + +    } + +  } + +  /** +   * Select signature algorithm for a given credential. +   * +   * @param credentials {@link X509Credential} that will be used for signing +   * @param rsaSigAlgorithm RSA based signing algorithm that should be used in case of RSA credential +   * @param ecSigAlgorithm EC based signing algorithm that should be used in case of RSA credential +   * @return either the rsaSigAlgorithm or the ecSigAlgorithm +   * @throws SamlSigningException In case of an unsupported credential +   */ +  public static String getSignatureAlgorithm(X509Credential credentials, +      String rsaSigAlgorithm, String ecSigAlgorithm) throws SamlSigningException { +    final PrivateKey privatekey = credentials.getPrivateKey(); +    if (privatekey instanceof RSAPrivateKey) { +      return rsaSigAlgorithm; + +    } else if (privatekey instanceof ECPrivateKey) { +      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.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(credential); + +    } + +    return keyInfoGenFac.newInstance(); + +  } + + +  /**     * Create a SAML2 object.     * -   * @param       <T> SAML2 object class +   * @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 = -          org.opensaml.xml.Configuration.getBuilderFactory(); +          XMLObjectProviderRegistrySupport.getBuilderFactory();        final QName defaultElementName =            (QName) clazz.getDeclaredField("DEFAULT_ELEMENT_NAME").get(null); @@ -119,7 +277,7 @@ public class Saml2Utils {        throws IOException, MarshallingException, TransformerException {      final Document document = builder.newDocument();      final Marshaller out = -        org.opensaml.xml.Configuration.getMarshallerFactory().getMarshaller(object); +        XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(object);      out.marshall(object, document);      return document;    } @@ -132,7 +290,7 @@ public class Saml2Utils {    public static Status getSuccessStatus() {      final Status status = Saml2Utils.createSamlObject(Status.class);      final StatusCode statusCode = Saml2Utils.createSamlObject(StatusCode.class); -    statusCode.setValue(StatusCode.SUCCESS_URI); +    statusCode.setValue(StatusCode.SUCCESS);      status.setStatusCode(statusCode);      return status;    } @@ -165,7 +323,7 @@ public class Saml2Utils {     * @return     */    public static Envelope buildSoap11Envelope(final XMLObject payload) { -    final XMLObjectBuilderFactory bf = org.opensaml.xml.Configuration.getBuilderFactory(); +    final XMLObjectBuilderFactory bf = XMLObjectProviderRegistrySupport.getBuilderFactory();      final Envelope envelope = (Envelope) bf.getBuilder(Envelope.DEFAULT_ELEMENT_NAME)          .buildObject(Envelope.DEFAULT_ELEMENT_NAME);      final Body body = @@ -211,7 +369,8 @@ public class Saml2Utils {     */    public static void schemeValidation(final XMLObject xmlObject) throws Exception {      try { -      final Schema test = SAMLSchemaBuilder.getSAML11Schema(); + +      final Schema test = schemaBuilder.getSAMLSchema();        final Validator val = test.newValidator();        final DOMSource source = new DOMSource(xmlObject.getDOM());        val.validate(source); @@ -227,11 +386,37 @@ public class Saml2Utils {    private static XMLObject createAttributeValue(final QName attributeValueType,        final String value) { -    final XSStringBuilder stringBuilder = (XSStringBuilder) org.opensaml.xml.Configuration +    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(X509Credential credential) { +    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/validation/EaafUriCompare.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/EaafUriCompare.java index ca37d6e5..9015c40b 100644 --- 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 @@ -19,10 +19,11 @@  package at.gv.egiz.eaaf.modules.pvp2.impl.validation; -import org.opensaml.common.binding.decoding.URIComparator;  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); 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 6497ce06..1591198c 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 @@ -22,41 +22,39 @@ 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 org.opensaml.saml.metadata.resolver.impl.PredicateRoleDescriptorResolver; +import org.opensaml.saml.security.impl.MetadataCredentialResolver; +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;  public class TrustEngineFactory {    /**     * Get OpenSAML2 TrustEngine.     * -   * @param provider Metadata provider +   * @param mdResolver Metadata provider     * @return     */    public static SignatureTrustEngine getSignatureKnownKeysTrustEngine( -      final MetadataProvider provider) { -    MetadataCredentialResolver resolver; - -    resolver = new MetadataCredentialResolver(provider); +      final IPvp2MetadataProvider mdResolver) { +    final MetadataCredentialResolver resolver = new MetadataCredentialResolver(); +    resolver.setRoleDescriptorResolver(new PredicateRoleDescriptorResolver(mdResolver));      final List<KeyInfoProvider> keyInfoProvider = new ArrayList<>();      keyInfoProvider.add(new DSAKeyValueProvider());      keyInfoProvider.add(new RSAKeyValueProvider());      keyInfoProvider.add(new InlineX509DataProvider()); -    final KeyInfoCredentialResolver keyInfoResolver = -        new BasicProviderKeyInfoCredentialResolver(keyInfoProvider); -      final ExplicitKeySignatureTrustEngine engine = -        new ExplicitKeySignatureTrustEngine(resolver, keyInfoResolver); +        new ExplicitKeySignatureTrustEngine(resolver, +            new BasicProviderKeyInfoCredentialResolver(keyInfoProvider));      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 d1eb66a3..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 @@ -23,22 +23,24 @@ 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.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);    @Override -  public void doFilter(final XMLObject metadata) throws SignatureValidationException { +  public XMLObject filter(@Nullable final XMLObject metadata) throws SignatureValidationException {      try {        if (metadata instanceof EntitiesDescriptor) {          final EntitiesDescriptor entitiesDescriptor = (EntitiesDescriptor) metadata; @@ -68,6 +70,9 @@ public abstract class AbstractMetadataSignatureFilter implements MetadataFilter        throw new SignatureValidationException(e);      } + +    return metadata; +    }    /** 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 index 66c3fb9e..efbeb7e5 100644 --- 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 @@ -22,29 +22,28 @@ 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.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. @@ -76,7 +75,7 @@ public class PvpEntityCategoryFilter implements MetadataFilter {     * .XMLObject)     */    @Override -  public void doFilter(final XMLObject metadata) throws FilterException { +  public XMLObject filter(final XMLObject metadata) throws FilterException {      if (isUsed) {        log.trace("Map PVP EntityCategory to single PVP Attributes ... "); @@ -109,8 +108,11 @@ public class PvpEntityCategoryFilter implements MetadataFilter {      } else {        log.trace("Filter to map PVP EntityCategory to single PVP Attributes is deactivated"); +      } +    return metadata; +    }    private void resolveEntityCategoriesToAttributes(final EntityDescriptor metadata) { @@ -190,7 +192,8 @@ public class PvpEntityCategoryFilter implements MetadataFilter {          attributeService.setIndex(0);          attributeService.setIsDefault(true);          final ServiceName serviceName = Saml2Utils.createSamlObject(ServiceName.class); -        serviceName.setName(new LocalizedString("Default Service", "en")); +        serviceName.setValue("Default Service"); +        serviceName.setXMLLang("en");          attributeService.getNames().add(serviceName);          if (attrList != null && !attrList.isEmpty()) { 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 6dcc3234..73a11c49 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 @@ -23,20 +23,23 @@ 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; -  public class SchemaValidationFilter implements MetadataFilter {    private static final Logger log = LoggerFactory.getLogger(SchemaValidationFilter.class);    private boolean isActive = true; +  private static SAMLSchemaBuilder schemaBuilder = new SAMLSchemaBuilder(SAML1Version.SAML_11); +    public SchemaValidationFilter() {    } @@ -53,18 +56,17 @@ public class SchemaValidationFilter implements MetadataFilter {     * .XMLObject)     */    @Override -  public void doFilter(final XMLObject arg0) throws FilterException { +  public XMLObject filter(final XMLObject arg0) throws FilterException {      String errString = null;      if (isActive) {        try { -        final Schema test = SAMLSchemaBuilder.getSAML11Schema(); +        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"); -        return;        } catch (final SAXException e) {          if (log.isDebugEnabled() || log.isTraceEnabled()) { @@ -91,8 +93,10 @@ public class SchemaValidationFilter implements MetadataFilter {      } 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/verification/AbstractRequestSignedSecurityPolicyRule.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/AbstractRequestSignedSecurityPolicyRule.java index 6d78b775..380e735c 100644 --- 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 @@ -24,28 +24,27 @@ import javax.xml.transform.dom.DOMSource;  import javax.xml.validation.Schema;  import javax.xml.validation.Validator; +import at.gv.egiz.eaaf.modules.pvp2.exception.SchemaValidationException; +  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.core.criterion.EntityIdCriterion; +import org.opensaml.saml.common.SignableSAMLObject; +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.security.impl.SAMLSignatureProfileValidator;  import org.opensaml.security.MetadataCriteria; -import org.opensaml.security.SAMLSignatureProfileValidator; -import org.opensaml.ws.message.MessageContext; +import org.opensaml.security.credential.UsageType; +import org.opensaml.security.criteria.UsageCriterion;  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.opensaml.xmlsec.signature.support.SignatureTrustEngine;  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; +import net.shibboleth.utilities.java.support.resolver.CriteriaSet;  /**   * Signature Policy for SAML2 redirect-binding. @@ -58,6 +57,8 @@ public abstract class AbstractRequestSignedSecurityPolicyRule implements Securit    private static final Logger log =        LoggerFactory.getLogger(AbstractRequestSignedSecurityPolicyRule.class); +  private static SAMLSchemaBuilder schemaBuilder = new SAMLSchemaBuilder(SAML1Version.SAML_11); +    private SignatureTrustEngine trustEngine = null;    private QName peerEntityRole = null; @@ -136,9 +137,9 @@ public abstract class AbstractRequestSignedSecurityPolicyRule implements Securit        }        final CriteriaSet criteriaSet = new CriteriaSet(); -      criteriaSet.add(new EntityIDCriteria(context.getInboundMessageIssuer())); +      criteriaSet.add(new EntityIdCriterion(context.getInboundMessageIssuer()));        criteriaSet.add(new MetadataCriteria(peerEntityRole, SAMLConstants.SAML20P_NS)); -      criteriaSet.add(new UsageCriteria(UsageType.SIGNING)); +      criteriaSet.add(new UsageCriterion(UsageType.SIGNING));        try {          if (!trustEngine.validate(samlObj.getSignature(), criteriaSet)) { @@ -164,7 +165,7 @@ public abstract class AbstractRequestSignedSecurityPolicyRule implements Securit      String err = null;      try { -      final Schema test = SAMLSchemaBuilder.getSAML11Schema(); +      final Schema test = schemaBuilder.getSAMLSchema();        final Validator val = test.newValidator();        val.validate(new DOMSource(source));        log.debug("Schema validation check done OK"); 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..2672bef2 --- /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,23 @@ +package at.gv.egiz.eaaf.modules.pvp2.impl.verification; + +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 lombok.extern.slf4j.Slf4j; + +@Slf4j +public class EaafMessageContextInitializationHandler extends AbstractMessageHandler<SAMLObject> { + +  @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()); + +  } + +} 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 42d7d6a1..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PvpAuthRequestSignedRole.java +++ /dev/null @@ -1,57 +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; - -public class PvpAuthRequestSignedRole extends SAML2AuthnRequestsSignedRule { - -  @Override -  protected boolean isMessageSigned(final SAMLMessageContext messageContext) { -    // This handles HTTP-Redirect and HTTP-POST-SimpleSign bindings. -    final HTTPInTransport inTransport = -        (HTTPInTransport) messageContext.getInboundMessageTransport(); - -    // Check signature parameter exists only once and is not empty -    final List<String> sigParam = inTransport.getParameterValues("Signature"); -    final boolean isValidSigned = sigParam.size() == 1 && !DatatypeHelper.isEmpty(sigParam.get(0)); - -    // Check signature-algorithm parameter exists only once and is not empty -    final List<String> sigAlgParam = inTransport.getParameterValues("SigAlg"); -    final boolean isValidSigAlgExists = -        sigAlgParam.size() == 1 && !DatatypeHelper.isEmpty(sigAlgParam.get(0)); - -    // Check signature-content parameter exists only once and is not empty -    final List<String> samlReqParam = inTransport.getParameterValues("SAMLRequest"); -    final List<String> samlRespParam = inTransport.getParameterValues("SAMLResponse"); -    final 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/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..e43d0423 --- /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/PvpSignedRequestPolicyRule.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PvpSignedRequestPolicyRule.java index c7a43b0b..9c02221c 100644 --- 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 @@ -21,13 +21,12 @@ 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; +import org.opensaml.saml.common.SignableSAMLObject; +import org.opensaml.saml2.metadata.provider.MetadataProvider; +import org.opensaml.xmlsec.signature.support.SignatureTrustEngine; +  public class PvpSignedRequestPolicyRule extends AbstractRequestSignedSecurityPolicyRule {    private IRefreshableMetadataProvider metadataProvider = null; diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/SamlVerificationEngine.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/SamlVerificationEngine.java index df91ce53..658dfe16 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/SamlVerificationEngine.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/SamlVerificationEngine.java @@ -24,43 +24,44 @@ 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.EaafProtocolException;  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.IPvp2MetadataProvider;  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") +import org.apache.commons.lang3.StringUtils; +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.RequestAbstractType; +import org.opensaml.saml.saml2.core.StatusResponseType; +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.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.resolver.CriteriaSet; + +@Slf4j  public class SamlVerificationEngine { -  private static final Logger log = LoggerFactory.getLogger(SamlVerificationEngine.class); +  private static SAMLSchemaBuilder schemaBuilder = new SAMLSchemaBuilder(SAML1Version.SAML_11);    @Autowired(required = true) -  IPvpMetadataProvider metadataProvider; +  IPvp2MetadataProvider metadataProvider;    /**     * Verify signature of a signed SAML2 object. @@ -72,7 +73,7 @@ public class SamlVerificationEngine {     * @throws Exception In case of a general error     */    public void verify(final InboundMessage msg, final SignatureTrustEngine sigTrustEngine) -      throws org.opensaml.xml.security.SecurityException, Exception { +      throws SecurityException, Exception {      try {        if (msg instanceof PvpSProfileRequest            && ((PvpSProfileRequest) msg).getSamlRequest() instanceof RequestAbstractType) { @@ -135,7 +136,7 @@ public class SamlVerificationEngine {        profileValidator.validate(samlObj.getSignature());        performSchemaValidation(samlObj.getDOM()); -    } catch (final ValidationException e) { +    } catch (final SignatureException e) {        log.warn("Signature is not conform to SAML signature profile", e);        throw new InvalidProtocolRequestException("pvp2.21", new Object[] {}); @@ -145,15 +146,16 @@ public class SamlVerificationEngine {      }      final 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)); +    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("pvp2.21", new Object[] {});        } -    } catch (final org.opensaml.xml.security.SecurityException e) { +    } catch (final org.opensaml.security.SecurityException e) {        log.warn("PVP2x message signature validation FAILED.", e);        throw new InvalidProtocolRequestException("pvp2.21", new Object[] {});      } @@ -166,7 +168,7 @@ public class SamlVerificationEngine {        profileValidator.validate(samlObj.getSignature());        performSchemaValidation(samlObj.getDOM()); -    } catch (final ValidationException e) { +    } catch (final SignatureException e) {        log.warn("Signature is not conform to SAML signature profile", e);        throw new InvalidProtocolRequestException("pvp2.21", new Object[] {}); @@ -176,16 +178,16 @@ public class SamlVerificationEngine {      }      final 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)); +    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("pvp2.21", new Object[] {});        } -    } catch (final org.opensaml.xml.security.SecurityException e) { +    } catch (final org.opensaml.security.SecurityException e) {        log.warn("PVP2x message signature validation FAILED.", e);        throw new InvalidProtocolRequestException("pvp2.21", new Object[] {});      } @@ -195,7 +197,7 @@ public class SamlVerificationEngine {      String err = null;      try { -      final Schema test = SAMLSchemaBuilder.getSAML11Schema(); +      final Schema test = schemaBuilder.getSAMLSchema();        final Validator val = test.newValidator();        val.validate(new DOMSource(source));        log.debug("Schema validation check done OK"); 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 ee4d3864..2d5dc6ea 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 @@ -10,16 +10,19 @@      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="pvpLogMessageSource" +        class="at.gv.egiz.eaaf.modules.pvp2.impl.logging.PvpModuleMessageSource" /> -  <bean id="PVPRedirectBinding" -    class="at.gv.egiz.eaaf.modules.pvp2.impl.binding.RedirectBinding" /> +  <bean id="PVPMetadataBuilder" +        class="at.gv.egiz.eaaf.modules.pvp2.impl.builder.PvpMetadataBuilder" /> -  <bean id="PVPSOAPBinding" -    class="at.gv.egiz.eaaf.modules.pvp2.impl.binding.SoapBinding" /> +  <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" />  </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..6e647bd0 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/resources/messages/pvp_messages.properties @@ -0,0 +1,12 @@ +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.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/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..6adce26e --- /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,448 @@ +package at.gv.egiz.eaaf.modules.pvp2.test.binding; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +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.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.PostBinding; +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 org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.RandomStringUtils; +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.InitializationException; +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.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.RequestAbstractType; +import org.opensaml.saml.saml2.core.StatusResponseType; +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.component.ComponentInitializationException; +import net.shibboleth.utilities.java.support.net.URIComparator; +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 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; + +  protected MockHttpServletRequest httpReq; +  protected MockHttpServletResponse httpResp; +  protected IRequest pendingReq; + +  @BeforeClass +  public static void classInitializer() throws InitializationException, ComponentInitializationException { +    EaafOpenSaml3xInitializer.eaafInitialize(); + +  } + +  /** +   * 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 decodeRequestSuccess() throws MessageDecodingException, SecurityException, IOException, Pvp2Exception { +    final String serviceUrl = "http://testservice.org"; + +    final IPvp2MetadataProvider metadataProvider = null; + +    final boolean isSpEndPoint = false; +    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); + + +    final InboundMessageInterface msg = +        bindingImpl.decode(httpReq, httpResp, metadataProvider, isSpEndPoint, 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.assertFalse("Wrong isVerified flag", msg.isVerified()); + +  } + +  @Test +  public void decodeRequestSuccessWithRelayState() throws MessageDecodingException, SecurityException, +      IOException, Pvp2Exception { +    final String serviceUrl = "http://testservice.org"; +    final String relayState = RandomStringUtils.randomAlphanumeric(10); + +    final String b64AuthnReq = Base64.getEncoder().encodeToString(IOUtils.toByteArray( +        PostBindingTest.class.getResourceAsStream("/data/AuthRequest_with_sig_1.xml"))); +    httpReq.setMethod("POST"); +    httpReq.addParameter("SAMLRequest", b64AuthnReq); +    httpReq.addParameter("RelayState", relayState); + +    final IPvp2MetadataProvider metadataProvider = null; + +    final boolean isSpEndPoint = false; +    final URIComparator comparator = new EaafUriCompare(serviceUrl); + + +    final InboundMessageInterface msg = +        bindingImpl.decode(httpReq, httpResp, metadataProvider, isSpEndPoint, 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.assertFalse("Wrong isVerified flag", msg.isVerified()); + +  } + +  @Test +  public void decodeResponseSuccess() throws MessageDecodingException, SecurityException, IOException, Pvp2Exception { +    final String serviceUrl = "http://testservice.org"; + +    final IPvp2MetadataProvider metadataProvider = null; + +    final boolean isSpEndPoint = false; +    final URIComparator comparator = new EaafUriCompare(serviceUrl); + +    final String b64AuthnReq = Base64.getEncoder().encodeToString(IOUtils.toByteArray( +        PostBindingTest.class.getResourceAsStream("/data/Response_with_sig_1.xml"))); +    httpReq.setMethod("POST"); +    httpReq.addParameter("SAMLRequest", b64AuthnReq); + + +    final InboundMessageInterface msg = +        bindingImpl.decode(httpReq, httpResp, metadataProvider, isSpEndPoint, 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_moaid-2.0/pvp/metadata", msg.getEntityID()); +    Assert.assertFalse("Wrong isVerified flag", msg.isVerified()); + +  } + +  @Test +  public void decodeResponseSuccessWithRelayState() throws MessageDecodingException, SecurityException, IOException, Pvp2Exception { +    final String serviceUrl = "http://testservice.org"; +    final String relayState = RandomStringUtils.randomAlphanumeric(10); + +    final String b64AuthnReq = Base64.getEncoder().encodeToString(IOUtils.toByteArray( +        PostBindingTest.class.getResourceAsStream("/data/Response_with_sig_1.xml"))); +    httpReq.setMethod("POST"); +    httpReq.addParameter("SAMLRequest", b64AuthnReq); +    httpReq.addParameter("RelayState", relayState); + +    final IPvp2MetadataProvider metadataProvider = null; + +    final boolean isSpEndPoint = false; +    final URIComparator comparator = new EaafUriCompare(serviceUrl); + + +    final InboundMessageInterface msg = +        bindingImpl.decode(httpReq, httpResp, metadataProvider, isSpEndPoint, 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("Response is null", msg.getInboundMessage()); +    Assert.assertNotNull("EntityId is null", msg.getEntityID()); +    Assert.assertEquals("EntityId not match", "https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp/metadata", msg.getEntityID()); +    Assert.assertFalse("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; +    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.getIdpMetaDataSigningCredential(), 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.getIdpAssertionSigningCredential(), 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.getIdpMetaDataSigningCredential(), 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.getIdpMetaDataSigningCredential(), 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.getIdpMetaDataSigningCredential(), 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); + +  } + +} 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..80dfc400 --- /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,490 @@ +package at.gv.egiz.eaaf.modules.pvp2.test.binding; + +import java.io.IOException; +import java.net.URLDecoder; +import java.util.Base64; + +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.modules.pvp2.PvpConstants; +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.RedirectBinding; +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 org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.RandomStringUtils; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.opensaml.core.config.InitializationException; +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.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.component.ComponentInitializationException; +import net.shibboleth.utilities.java.support.net.URIComparator; +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 RedirectBindingTest { + +  public static final String HTTP_FORM_RELAYSTATE = "RelayState="; +  public static final String HTTP_FORM_SAMLREQ = "SAMLRequest="; +  public static final String HTTP_FORM_SAMLRESP = "SAMLResponse="; + +  public static final String HTTP_REDIRECT_SIGALG = "SigAlg="; +  public static final String HTTP_REDIRECT_SIGNATURE = "Signature="; + +  @Autowired private RedirectBinding bindingImpl; +  @Autowired private DummyCredentialProvider credentialProvider; + +  protected MockHttpServletRequest httpReq; +  protected MockHttpServletResponse httpResp; +  protected IRequest pendingReq; + +  @BeforeClass +  public static void classInitializer() throws InitializationException, ComponentInitializationException { +    EaafOpenSaml3xInitializer.eaafInitialize(); + +  } + +  /** +   * 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 decodeRequestSuccess() throws MessageDecodingException, SecurityException, IOException, Pvp2Exception { +    final String serviceUrl = "http://testservice.org"; + +    final IPvp2MetadataProvider metadataProvider = null; + +    final boolean isSpEndPoint = false; +    final URIComparator comparator = new EaafUriCompare(serviceUrl); + +    httpReq.setMethod("GET"); +    httpReq.setRequestURI("http://testservice.org"); +    httpReq.setParameter("SAMLRequest","nVRNb9swDD13wP6DoXvkr/RjQuzCSFAgQDd0TbfDLoVi0642Wcok2kn766c4duABWw++SdQj+fhIanF7qKXXgrFCq4SENCAeqFwXQlUJ+fZ0N7sht+nC8lpGO5Y1+KIe4XcDFj3nqCw7vSSkMYppboVlitdgGeZsk32+ZxEN2M5o1LmWxMusBYMu1VIr29RgNmBakcNaFXBw6R0C0Yhtg3BCOBp/Qxy/lcsuFMeO8Qvijvk+Ops9Aak2FfHWq4Q8c4BtySHO4eomLCEuipyXURjzeVQGYRE7mLWNC22RK0xIFITzWRDPgsun4IrFn1gQ0evryx/E+z4o5OohvR6sczZjId7XgQ/VE+9Om5rj+/CjRRSzsoMyUCjwlaTHgq2ruIBaU6jEG61ayrG777RBLp+PR6krofyFP2Y68N4025+Q4xTi6ccPFxd9mC8Ot15NI9T7umiDpSd1nrUT4kFLkb96mZR6vzTAERKCpoEpCu6OPbTohCRThtc/U+s3AIpuH9ygIhwm7cNYzXGspXSKP0I5qUP9Ruz3e2pRm1+00i2Fxne77ecCxRuor1l2Dy1Ifz6o/6/so+78p+b0/Dz+GdI/"); +    httpReq.setParameter("SigAlg","http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"); +    httpReq.setParameter("Signature","DOVMqh17xn4wl+yvifm4McMsBjKDVf1eqph9ss362ZEbp2nkAIXUzkNWv72I96iNK3r+YbAxY9dwZ8Z7jKzCGiJ9Qm34YSfPvzXWl3EVrdI869U+H6HGIMqVew3cVdr4q3Qv9ZBIhdRxbrDu/+nMjdf8mzbgcQnfjSQiQIYWxOIXZFyxKsyrxJtIam4hoNwUT7mMN6RjgzvyeS3mARsTJdcI0Vn4ItiprhLgIkD18V9WIdeSZR0gfRaFj8PKdmXCD/Ia0cKgjhVKoiIZisV4vcthBOeDIqBORL2Ad3XhcNRQ3+cpAf65zHGMBAv1aRy7Bmv0++OvCavufykqI2EHtg=="); + + + + +    final InboundMessageInterface msg = +        bindingImpl.decode(httpReq, httpResp, metadataProvider, isSpEndPoint, 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.assertFalse("Wrong isVerified flag", msg.isVerified()); + +  } + +  @Ignore +  @Test +  public void decodeRequestSuccessWithRelayState() throws MessageDecodingException, +      SecurityException, IOException, Pvp2Exception { +    final String serviceUrl = "http://testservice.org"; +    final String relayState = RandomStringUtils.randomAlphanumeric(10); + +    final String b64AuthnReq = Base64.getEncoder().encodeToString(IOUtils.toByteArray( +        RedirectBindingTest.class.getResourceAsStream("/data/AuthRequest_with_sig_1.xml"))); +    httpReq.setMethod("POST"); +    httpReq.addParameter("SAMLRequest", b64AuthnReq); +    httpReq.addParameter("RelayState", relayState); + +    final IPvp2MetadataProvider metadataProvider = null; + +    final boolean isSpEndPoint = false; +    final URIComparator comparator = new EaafUriCompare(serviceUrl); + + +    final InboundMessageInterface msg = +        bindingImpl.decode(httpReq, httpResp, metadataProvider, isSpEndPoint, 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.assertFalse("Wrong isVerified flag", msg.isVerified()); + +  } + +  @Ignore +  @Test +  public void decodeResponseSuccess() throws MessageDecodingException, SecurityException, IOException, Pvp2Exception { +    final String serviceUrl = "http://testservice.org"; + +    final IPvp2MetadataProvider metadataProvider = null; + +    final boolean isSpEndPoint = false; +    final URIComparator comparator = new EaafUriCompare(serviceUrl); + +    final String b64AuthnReq = Base64.getEncoder().encodeToString(IOUtils.toByteArray( +        RedirectBindingTest.class.getResourceAsStream("/data/Response_with_sig_1.xml"))); +    httpReq.setMethod("POST"); +    httpReq.addParameter("SAMLRequest", b64AuthnReq); + + +    final InboundMessageInterface msg = +        bindingImpl.decode(httpReq, httpResp, metadataProvider, isSpEndPoint, 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_moaid-2.0/pvp/metadata", msg.getEntityID()); +    Assert.assertFalse("Wrong isVerified flag", msg.isVerified()); + +  } + +  @Ignore +  @Test +  public void decodeResponseSuccessWithRelayState() throws MessageDecodingException, SecurityException, +      IOException, Pvp2Exception { +    final String serviceUrl = "http://testservice.org"; +    final String relayState = RandomStringUtils.randomAlphanumeric(10); + +    final String b64AuthnReq = Base64.getEncoder().encodeToString(IOUtils.toByteArray( +        RedirectBindingTest.class.getResourceAsStream("/data/Response_with_sig_1.xml"))); +    httpReq.setMethod("POST"); +    httpReq.addParameter("SAMLRequest", b64AuthnReq); +    httpReq.addParameter("RelayState", relayState); + +    final IPvp2MetadataProvider metadataProvider = null; + +    final boolean isSpEndPoint = false; +    final URIComparator comparator = new EaafUriCompare(serviceUrl); + + +    final InboundMessageInterface msg = +        bindingImpl.decode(httpReq, httpResp, metadataProvider, isSpEndPoint, 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("Response is null", msg.getInboundMessage()); +    Assert.assertNotNull("EntityId is null", msg.getEntityID()); +    Assert.assertEquals("EntityId not match", "https://demo.egiz.gv.at/demoportal_moaid-2.0/pvp/metadata", msg.getEntityID()); +    Assert.assertFalse("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.getIdpMetaDataSigningCredential(), 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)); + +    final String respSamlMsg = checkMessagePart(locationHeader, HTTP_FORM_SAMLREQ, true); +    Assert.assertNotNull("Saml msg is null", respSamlMsg); +    Assert.assertFalse("Saml msg is empty", respSamlMsg.isEmpty()); + +    final String sigAlg = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGALG, 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, true); +    Assert.assertNotNull("Saml signature null", samlSig); +    Assert.assertFalse("Saml signature is empty", samlSig.isEmpty()); + +    final String respRelayState = checkMessagePart(locationHeader, HTTP_FORM_RELAYSTATE, 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.getIdpAssertionSigningCredential(), 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)); + +    final String respSamlMsg = checkMessagePart(locationHeader, HTTP_FORM_SAMLREQ, true); +    Assert.assertNotNull("Saml msg is null", respSamlMsg); +    Assert.assertFalse("Saml msg is empty", respSamlMsg.isEmpty()); + +    final String sigAlg = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGALG, 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, true); +    Assert.assertNotNull("Saml signature null", samlSig); +    Assert.assertFalse("Saml signature is empty", samlSig.isEmpty()); + +    final String respRelayState = checkMessagePart(locationHeader, HTTP_FORM_RELAYSTATE, 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.getIdpMetaDataSigningCredential(), 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)); + +    final String respSamlMsg = checkMessagePart(locationHeader, HTTP_FORM_SAMLREQ, true); +    Assert.assertNotNull("Saml msg is null", respSamlMsg); +    Assert.assertFalse("Saml msg is empty", respSamlMsg.isEmpty()); + +    final String sigAlg = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGALG, 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, true); +    Assert.assertNotNull("Saml signature null", samlSig); +    Assert.assertFalse("Saml signature is empty", samlSig.isEmpty()); + +    final String respRelayState = checkMessagePart(locationHeader, HTTP_FORM_RELAYSTATE, 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.getIdpMetaDataSigningCredential(), 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)); + +    final String respSamlMsg = checkMessagePart(locationHeader, HTTP_FORM_SAMLRESP, true); +    Assert.assertNotNull("Saml msg is null", respSamlMsg); +    Assert.assertFalse("Saml msg is empty", respSamlMsg.isEmpty()); + +    final String sigAlg = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGALG, 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, true); +    Assert.assertNotNull("Saml signature null", samlSig); +    Assert.assertFalse("Saml signature is empty", samlSig.isEmpty()); + +    final String respRelayState = checkMessagePart(locationHeader, HTTP_FORM_RELAYSTATE, 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.getIdpMetaDataSigningCredential(), 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)); + +    final String respSamlMsg = checkMessagePart(locationHeader, HTTP_FORM_SAMLRESP, true); +    Assert.assertNotNull("Saml msg is null", respSamlMsg); +    Assert.assertFalse("Saml msg is empty", respSamlMsg.isEmpty()); + +    final String sigAlg = checkMessagePart(locationHeader, HTTP_REDIRECT_SIGALG, 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, true); +    Assert.assertNotNull("Saml signature null", samlSig); +    Assert.assertFalse("Saml signature is empty", samlSig.isEmpty()); + +    final String respRelayState = checkMessagePart(locationHeader, HTTP_FORM_RELAYSTATE, 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); + +  } + +} 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..6930790d --- /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,70 @@ +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.EaafException; +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_PATH = "keystore.path"; +  public static final String KEYSTORE_PASSWORD = "keystore.pass"; + +  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"; + +  @Override +  public String getFriendlyName() { +    return "jUnit test credential provider"; +  } + +  @Override +  public String getKeyStoreFilePath() throws EaafException { +    return basicConfig.getBasicConfiguration(KEYSTORE_PATH); +  } + +  @Override +  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/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..74b805ba --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/config/config_1.props @@ -0,0 +1,8 @@ +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=
\ No newline at end of file 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/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..3607cbc4 --- /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" 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> +	<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/junit.jks b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/data/junit.jksBinary files differ new file mode 100644 index 00000000..b5262cb8 --- /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/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/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..de3cfbd1 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_core.beans.xml @@ -0,0 +1,22 @@ +<?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" /> + +</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..f261e893 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/test/resources/spring/test_eaaf_pvp.beans.xml @@ -0,0 +1,29 @@ +<?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"/> + +  <bean id="dummyCredentialProvider" +        class="at.gv.egiz.eaaf.modules.pvp2.test.dummy.DummyCredentialProvider" /> + +  <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" /> + + + +</beans>
\ No newline at end of file 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 6d868558..0003b829 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 @@ -20,7 +20,8 @@  package at.gv.egiz.eaaf.modules.pvp2.idp.exception;  import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; -import org.opensaml.saml2.core.StatusCode; + +import org.opensaml.saml.saml2.core.StatusCode;  public class InvalidAssertionConsumerServiceException extends Pvp2Exception { @@ -28,7 +29,7 @@ public class InvalidAssertionConsumerServiceException extends Pvp2Exception {    public InvalidAssertionConsumerServiceException(final int idx) {      super("pvp2.28", new Object[] {idx}); -    this.statusCodeValue = StatusCode.REQUESTER_URI; +    this.statusCodeValue = StatusCode.REQUESTER;    }    /** @@ -38,7 +39,7 @@ public class InvalidAssertionConsumerServiceException extends Pvp2Exception {     */    public InvalidAssertionConsumerServiceException(final String wrongUrl) {      super("pvp2.23", new Object[] {wrongUrl}); -    this.statusCodeValue = StatusCode.REQUESTER_URI; +    this.statusCodeValue = StatusCode.REQUESTER;    } 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 0d75616a..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 @@ -20,7 +20,8 @@  package at.gv.egiz.eaaf.modules.pvp2.idp.exception;  import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; -import org.opensaml.saml2.core.StatusCode; + +import org.opensaml.saml.saml2.core.StatusCode;  public class InvalidAssertionEncryptionException extends Pvp2Exception { @@ -28,7 +29,7 @@ public class InvalidAssertionEncryptionException extends Pvp2Exception {    public InvalidAssertionEncryptionException() {      super("pvp2.16", new Object[] {}); -    this.statusCodeValue = StatusCode.RESPONDER_URI; +    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 ecceea12..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 @@ -20,7 +20,8 @@  package at.gv.egiz.eaaf.modules.pvp2.idp.exception;  import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; -import org.opensaml.saml2.core.StatusCode; + +import org.opensaml.saml.saml2.core.StatusCode;  public class RequestDeniedException extends Pvp2Exception { @@ -28,7 +29,7 @@ public class RequestDeniedException extends Pvp2Exception {    public RequestDeniedException() {      super("pvp2.14", null); -    this.statusCodeValue = StatusCode.REQUEST_DENIED_URI; +    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 331e11cd..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 @@ -20,7 +20,8 @@  package at.gv.egiz.eaaf.modules.pvp2.idp.exception;  import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; -import org.opensaml.saml2.core.StatusCode; + +import org.opensaml.saml.saml2.core.StatusCode;  public class ResponderErrorException extends Pvp2Exception { @@ -29,11 +30,11 @@ public class ResponderErrorException extends Pvp2Exception {    public ResponderErrorException(final String messageId, final Object[] parameters,        final Throwable wrapped) {      super(messageId, parameters, wrapped); -    this.statusCodeValue = StatusCode.RESPONDER_URI; +    this.statusCodeValue = StatusCode.RESPONDER;    }    public ResponderErrorException(final String messageId, final Object[] parameters) {      super(messageId, parameters); -    this.statusCodeValue = StatusCode.RESPONDER_URI; +    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 index 4650506d..c02e534c 100644 --- 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 @@ -20,7 +20,8 @@  package at.gv.egiz.eaaf.modules.pvp2.idp.exception;  import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; -import org.opensaml.saml2.core.StatusCode; + +import org.opensaml.saml.saml2.core.StatusCode;  public class SamlRequestNotSignedException extends Pvp2Exception { @@ -28,12 +29,12 @@ public class SamlRequestNotSignedException extends Pvp2Exception {    public SamlRequestNotSignedException() {      super("pvp2.07", null); -    this.statusCodeValue = StatusCode.REQUESTER_URI; +    this.statusCodeValue = StatusCode.REQUESTER;    }    public SamlRequestNotSignedException(final Throwable e) {      super("pvp2.07", null, e); -    this.statusCodeValue = StatusCode.REQUESTER_URI; +    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 index 58a493b9..b0dcdb2e 100644 --- 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 @@ -11,7 +11,7 @@   * 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. @@ -19,18 +19,18 @@  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; +  public class SamlRequestNotSupported extends Pvp2Exception {    private static final long serialVersionUID = 1244883178458802767L; -   +    public SamlRequestNotSupported() {      super("pvp2.09", null); -    this.statusCodeValue = StatusCode.REQUEST_UNSUPPORTED_URI; +    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 41252b78..0f84b8fb 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 @@ -20,7 +20,8 @@  package at.gv.egiz.eaaf.modules.pvp2.idp.exception;  import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; -import org.opensaml.saml2.core.StatusCode; + +import org.opensaml.saml.saml2.core.StatusCode;  public class UnprovideableAttributeException extends Pvp2Exception { @@ -28,6 +29,6 @@ public class UnprovideableAttributeException extends Pvp2Exception {    public UnprovideableAttributeException(final String attributeName) {      super("pvp2.10", new Object[] {attributeName}); -    this.statusCodeValue = StatusCode.UNKNOWN_ATTR_PROFILE_URI; +    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 index f8a39b61..f86fd883 100644 --- 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 @@ -39,7 +39,8 @@ 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.credential.EaafX509Credential; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider;  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; @@ -60,20 +61,19 @@ import at.gv.egiz.eaaf.modules.pvp2.impl.verification.SamlVerificationEngine;  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.NameIDType; -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.saml.common.xml.SAMLConstants; +import org.opensaml.saml.saml2.core.AuthnRequest; +import org.opensaml.saml.saml2.core.Issuer; +import org.opensaml.saml.saml2.core.NameIDType; +import org.opensaml.saml.saml2.core.Response; +import org.opensaml.saml.saml2.core.Status; +import org.opensaml.saml.saml2.core.StatusCode; +import org.opensaml.saml.saml2.core.StatusMessage; +import org.opensaml.saml.saml2.metadata.AssertionConsumerService; +import org.opensaml.saml.saml2.metadata.EntityDescriptor; +import org.opensaml.saml.saml2.metadata.SPSSODescriptor;  import org.opensaml.ws.security.SecurityPolicyException; -import org.opensaml.xml.security.x509.X509Credential; -import org.opensaml.xml.signature.SignableXMLObject; +import org.opensaml.xmlsec.signature.SignableXMLObject;  import org.slf4j.Logger;  import org.slf4j.LoggerFactory;  import org.springframework.beans.factory.annotation.Autowired; @@ -84,7 +84,7 @@ public abstract class AbstractPvp2XProtocol extends AbstractController implement    @Autowired(required = true)    protected IPvp2BasicConfiguration pvpBasicConfiguration;    @Autowired(required = true) -  protected IPvpMetadataProvider metadataProvider; +  protected IPvp2MetadataProvider metadataProvider;    @Autowired(required = true)    protected SamlVerificationEngine samlVerificationEngine;    @Autowired(required = false) @@ -125,11 +125,11 @@ public abstract class AbstractPvp2XProtocol extends AbstractController implement      String moaError = null;      if (e instanceof NoPassivAuthenticationException) { -      statusCode.setValue(StatusCode.NO_PASSIVE_URI); +      statusCode.setValue(StatusCode.NO_PASSIVE);        statusMessage.setMessage(StringEscapeUtils.escapeXml(e.getLocalizedMessage()));      } else if (e instanceof NameIdFormatNotSupportedException) { -      statusCode.setValue(StatusCode.INVALID_NAMEID_POLICY_URI); +      statusCode.setValue(StatusCode.INVALID_NAMEID_POLICY);        statusMessage.setMessage(StringEscapeUtils.escapeXml(e.getLocalizedMessage()));      } else if (e instanceof SloException) { @@ -146,7 +146,7 @@ public abstract class AbstractPvp2XProtocol extends AbstractController implement        moaError = statusMessager.mapInternalErrorToExternalError(ex.getErrorId());      } else { -      statusCode.setValue(StatusCode.RESPONDER_URI); +      statusCode.setValue(StatusCode.RESPONDER);        statusMessage.setMessage(StringEscapeUtils.escapeXml(e.getLocalizedMessage()));        moaError = statusMessager.getResponseErrorCode(e);      } @@ -194,9 +194,9 @@ public abstract class AbstractPvp2XProtocol extends AbstractController implement        relayState = pvpRequest.getRequest().getRelayState();      } -    final X509Credential signCred = pvpIdpCredentials.getIdpAssertionSigningCredential(); +    final EaafX509Credential signCred = pvpIdpCredentials.getIdpAssertionSigningCredential(); -    encoder.encodeRespone(request, response, samlResponse, pvpRequest.getConsumerUrl(), relayState, +    encoder.encodeResponse(request, response, samlResponse, pvpRequest.getConsumerUrl(), relayState,          signCred, protocolRequest);      return true;    } 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 d4981cd6..74224dbe 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 @@ -22,6 +22,7 @@ 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; @@ -32,7 +33,7 @@ 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.exception.BindingNotSupportedException;  import at.gv.egiz.eaaf.modules.pvp2.idp.exception.ResponderErrorException;  import at.gv.egiz.eaaf.modules.pvp2.idp.impl.builder.AuthResponseBuilder; @@ -42,15 +43,15 @@ 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 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.messaging.encoder.MessageEncodingException; +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; @@ -65,7 +66,7 @@ public class AuthenticationAction implements IAction {        "protocols.pvp2.assertion.encryption.active";    @Autowired(required = true) -  private IPvpMetadataProvider metadataProvider; +  private IPvp2MetadataProvider metadataProvider;    @Autowired(required = true)    ApplicationContext springContext;    @Autowired(required = true) @@ -131,7 +132,7 @@ public class AuthenticationAction implements IAction {          throw new BindingNotSupportedException(consumerService.getBinding());        } -      binding.encodeRespone(httpReq, httpResp, authResponse, consumerService.getLocation(), +      binding.encodeResponse(httpReq, httpResp, authResponse, consumerService.getLocation(),            moaRequest.getRelayState(), pvpIdpCredentials.getIdpAssertionSigningCredential(), req);        revisionsLogger.logEvent(req, 3105, authResponse.getID()); 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 bf51ac0f..ac551612 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 @@ -21,36 +21,36 @@ package at.gv.egiz.eaaf.modules.pvp2.idp.impl.builder;  import java.util.ArrayList;  import java.util.List; +  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 org.joda.time.DateTime; -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.NameIDType; -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.core.criterion.EntityIdCriterion; +import org.opensaml.saml.common.xml.SAMLConstants; +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.KeyPlacement; +import org.opensaml.saml.saml2.metadata.SPSSODescriptor; +import org.opensaml.saml.security.impl.MetadataCredentialResolver;  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.security.credential.UsageType; +import org.opensaml.security.criteria.UsageCriterion; +import org.opensaml.security.x509.X509Credential; +import org.opensaml.xmlsec.EncryptionParameters; +import org.opensaml.xmlsec.encryption.support.KeyEncryptionParameters; +import org.opensaml.xmlsec.keyinfo.KeyInfoGeneratorFactory;  import org.slf4j.Logger;  import org.slf4j.LoggerFactory; +import net.shibboleth.utilities.java.support.resolver.CriteriaSet; +  /**   * Authentication response builder.   * @@ -101,10 +101,10 @@ public class AuthResponseBuilder {          new MetadataCredentialResolver(metadataProvider);      final CriteriaSet criteriaSet = new CriteriaSet(); -    criteriaSet.add(new EntityIDCriteria(req.getIssuer().getValue())); +    criteriaSet.add(new EntityIdCriterion(req.getIssuer().getValue()));      criteriaSet          .add(new MetadataCriteria(SPSSODescriptor.DEFAULT_ELEMENT_NAME, SAMLConstants.SAML20P_NS)); -    criteriaSet.add(new UsageCriteria(UsageType.ENCRYPTION)); +    criteriaSet.add(new UsageCriterion(UsageType.ENCRYPTION));      X509Credential encryptionCredentials = null;      try { 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 index f57f9db0..922e7efe 100644 --- 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 @@ -23,6 +23,7 @@ import java.security.MessageDigest;  import java.util.ArrayList;  import java.util.Iterator;  import java.util.List; +  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; @@ -42,33 +43,34 @@ 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.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.NameIDType; -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.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.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; 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 index 2e747656..597507f3 100644 --- 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 @@ -21,13 +21,13 @@ 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.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.   * @@ -97,7 +97,7 @@ public interface IPvpAuthnRequestBuilderConfiguruation {     *     * @return     */ -  Credential getAuthnRequestSigningCredential(); +  EaafX509Credential getAuthnRequestSigningCredential();    /**     * Define the SAML2 EntityDescriptor of the IDP, which should receive the 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 index 9b284c88..a81d9119 100644 --- 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 @@ -24,34 +24,6 @@ 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; @@ -64,6 +36,34 @@ 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 org.springframework.stereotype.Service; + +import net.shibboleth.utilities.java.support.security.SecureRandomIdentifierGenerationStrategy; +  /**   * PVP2 S-Profil Authentication-Request builder-implementation.   * @@ -127,7 +127,7 @@ public class PvpAuthnRequestBuilder {      if (StringUtils.isNotEmpty(reqID)) {        authReq.setID(reqID);      } else { -      final SecureRandomIdentifierGenerator gen = new SecureRandomIdentifierGenerator(); +      final SecureRandomIdentifierGenerationStrategy gen = new SecureRandomIdentifierGenerationStrategy();        authReq.setID(gen.generateIdentifier());      } 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 fa2b9312..53d9d9e8 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 @@ -28,22 +28,22 @@ import java.util.List;  import java.util.Map;  import java.util.Set; +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); @@ -47,15 +47,9 @@      <!-- Other third-party libs -->      <org.springframework.version>5.1.5.RELEASE</org.springframework.version>      <org.opensaml.version>3.4.3</org.opensaml.version> - - -    <org.opensaml.xmltooling.version>1.4.6</org.opensaml.xmltooling.version> -    <org.opensaml.openws.version>1.5.6</org.opensaml.openws.version> - -    <org.apache.santuario.xmlsec.version>2.1.3</org.apache.santuario.xmlsec.version> -    <org.bouncycastle.bcprov-jdk15on.version>1.61</org.bouncycastle.bcprov-jdk15on.version> -    <org.owasp.esapi.version>2.1.0.1</org.owasp.esapi.version> -    <surefire.version>2.22.0</surefire.version> +    <org.apache.santuario.xmlsec.version>2.1.4</org.apache.santuario.xmlsec.version> +    <org.bouncycastle.bcprov-jdk15on.version>1.64</org.bouncycastle.bcprov-jdk15on.version> +          <org.slf4j.version>1.7.25</org.slf4j.version>      <commons-codec.version>1.11</commons-codec.version>      <org.apache.commons-lang3.version>3.8.1</org.apache.commons-lang3.version> @@ -79,6 +73,13 @@      <xerces.version>2.11.0</xerces.version>      <xalan.version>2.7.1</xalan.version> +    <!-- jUnit testing --> +    <surefire.version>2.22.1</surefire.version> +    <junit.version>4.12</junit.version> +    <com.squareup.okhttp3.version>4.0.0</com.squareup.okhttp3.version> + +    <!-- Code helper plug-ins --> +    <org.projectlombok.lombok.version>1.18.10</org.projectlombok.lombok.version>      <!-- Code quality checks -->      <jacoco-maven-plugin.version>0.8.5</jacoco-maven-plugin.version> @@ -300,11 +301,6 @@          <version>${iaik.prod.iaik_xsect.version}</version>        </dependency> - - - - -        <dependency>          <groupId>com.google.code.findbugs</groupId>          <artifactId>jsr305</artifactId> @@ -388,11 +384,6 @@        </dependency>        <dependency> -        <groupId>org.owasp.esapi</groupId> -        <artifactId>esapi</artifactId> -        <version>${org.owasp.esapi.version}</version> -      </dependency> -      <dependency>          <groupId>javax.servlet</groupId>          <artifactId>javax.servlet-api</artifactId>          <version>${javax.servlet-api}</version> @@ -457,7 +448,7 @@        <dependency>          <groupId>junit</groupId>          <artifactId>junit</artifactId> -        <version>4.12</version> +        <version>${junit.version}</version>          <scope>test</scope>        </dependency>        <dependency> @@ -466,8 +457,30 @@          <version>${org.springframework.version}</version>          <scope>test</scope>        </dependency> +      <dependency> +        <groupId>com.squareup.okhttp3</groupId> +        <artifactId>mockwebserver</artifactId> +        <version>${com.squareup.okhttp3.version}</version> +        <scope>test</scope> +      </dependency> +      <dependency> +        <groupId>at.gv.egiz.eaaf</groupId> +        <artifactId>eaaf-core</artifactId> +        <version>${egiz.eaaf.version}</version> +        <scope>test</scope> +        <type>test-jar</type> +      </dependency> +          </dependencies>    </dependencyManagement> +  <dependencies> +    <dependency> +      <groupId>org.projectlombok</groupId> +      <artifactId>lombok</artifactId> +      <version>${org.projectlombok.lombok.version}</version> +      <scope>provided</scope> +    </dependency> +  </dependencies>    <build>      <extensions> | 
