From d41afe91ee59daf6b5f5037cecac52900fe2ccb2 Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Fri, 31 Jan 2020 20:41:54 +0100 Subject: a lot of more OpenSAML3 refactoring staff This version is also NOT stable! --- .../modules/pvp2/impl/binding/PostBinding.java | 220 ++++++++++----------- 1 file changed, 109 insertions(+), 111 deletions(-) (limited to 'eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/PostBinding.java') 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 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 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 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 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 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 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 -- cgit v1.2.3