summaryrefslogtreecommitdiff
path: root/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding
diff options
context:
space:
mode:
authorThomas Lenz <thomas.lenz@egiz.gv.at>2020-01-31 20:41:54 +0100
committerThomas Lenz <thomas.lenz@egiz.gv.at>2020-01-31 20:41:54 +0100
commitd41afe91ee59daf6b5f5037cecac52900fe2ccb2 (patch)
tree3a19e1818d276d701574758ce6166b2f3a7e2030 /eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding
parent0cf9926282ba4aa46bad3f4e8020cec72683492f (diff)
downloadEAAF-Components-d41afe91ee59daf6b5f5037cecac52900fe2ccb2.tar.gz
EAAF-Components-d41afe91ee59daf6b5f5037cecac52900fe2ccb2.tar.bz2
EAAF-Components-d41afe91ee59daf6b5f5037cecac52900fe2ccb2.zip
a lot of more OpenSAML3 refactoring staff
This version is also NOT stable!
Diffstat (limited to 'eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding')
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/AbstractBinding.java108
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/PostBinding.java220
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/RedirectBinding.java376
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/SoapBinding.java203
4 files changed, 569 insertions, 338 deletions
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