diff options
author | Thomas Lenz <thomas.lenz@egiz.gv.at> | 2020-01-31 20:41:54 +0100 |
---|---|---|
committer | Thomas Lenz <thomas.lenz@egiz.gv.at> | 2020-01-31 20:41:54 +0100 |
commit | d41afe91ee59daf6b5f5037cecac52900fe2ccb2 (patch) | |
tree | 3a19e1818d276d701574758ce6166b2f3a7e2030 /eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding | |
parent | 0cf9926282ba4aa46bad3f4e8020cec72683492f (diff) | |
download | EAAF-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')
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 |