From e7610325ee2f1d1f4e97e1e7a9b212e692836b5a Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Tue, 4 Feb 2020 17:37:34 +0100 Subject: first stable version that uses OpenSAML 3.x --- .../modules/pvp2/impl/binding/RedirectBinding.java | 234 +++++---------------- 1 file changed, 47 insertions(+), 187 deletions(-) (limited to 'eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/RedirectBinding.java') 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 5f74053d..f62f8a11 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/RedirectBinding.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/RedirectBinding.java @@ -21,6 +21,7 @@ package at.gv.egiz.eaaf.modules.pvp2.impl.binding; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import javax.xml.namespace.QName; import at.gv.egiz.eaaf.core.api.IRequest; import at.gv.egiz.eaaf.modules.pvp2.PvpConstants; @@ -32,15 +33,11 @@ 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.EaafHttpRedirectDeflateDecoder; +import at.gv.egiz.eaaf.modules.pvp2.impl.verification.EaafSaml2HttpRedirectDeflateSignatureSecurityHandler; import at.gv.egiz.eaaf.modules.pvp2.impl.verification.PvpSamlMessageHandlerChain; import org.opensaml.messaging.context.MessageContext; -import org.opensaml.messaging.decoder.MessageDecodingException; -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; @@ -48,13 +45,11 @@ import org.opensaml.saml.common.binding.security.impl.MessageLifetimeSecurityHan import org.opensaml.saml.common.messaging.context.SAMLBindingContext; import org.opensaml.saml.common.xml.SAMLConstants; import org.opensaml.saml.saml2.binding.encoding.impl.HTTPRedirectDeflateEncoder; -import org.opensaml.saml.saml2.binding.security.impl.SAML2HTTPRedirectDeflateSignatureSecurityHandler; import org.opensaml.saml.saml2.core.RequestAbstractType; import org.opensaml.saml.saml2.core.StatusResponseType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import net.shibboleth.utilities.java.support.component.ComponentInitializationException; import net.shibboleth.utilities.java.support.net.URIComparator; public class RedirectBinding extends AbstractBinding implements IDecoder, IEncoder { @@ -137,26 +132,11 @@ public class RedirectBinding extends AbstractBinding implements IDecoder, IEncod @Override public InboundMessageInterface decode(final HttpServletRequest req, final HttpServletResponse resp, final IPvp2MetadataProvider metadataProvider, - final boolean isSpEndPoint, final URIComparator comparator) + QName peerEntityRole, final URIComparator comparator) throws Pvp2Exception { - // TODO: implement one flat decoder to get SAML2 request/response parametes as - // same as in SAML2HTTPRedirectDeflateSignatureSecurityHandler - final EaafHttpRedirectDeflateDecoder decode = new EaafHttpRedirectDeflateDecoder(); - decode.setHttpServletRequest(req); - - // decode request - try { - decode.initialize(); - decode.decode(); - - } catch (MessageDecodingException | ComponentInitializationException e) { - throw new SamlBindingException("internal.pvp.95", - new Object[] { PvpConstants.REDIRECT, "decoding", e.getMessage() }, - e); - } - - final MessageContext messageContext = decode.getMessageContext(); + final EaafHttpRedirectDeflateDecoder decode = new EaafHttpRedirectDeflateDecoder(req); + final MessageContext messageContext = internalMessageDecode(decode, PvpConstants.REDIRECT); final SAMLBindingContext bindingContext = messageContext.getSubcontext(SAMLBindingContext.class, true); if (!bindingContext.hasBindingSignature()) { @@ -165,171 +145,18 @@ public class RedirectBinding extends AbstractBinding implements IDecoder, IEncod } - //inject informations into message context that are required for further processing - injectInboundMessageContexts(messageContext, metadataProvider); + // inject informations into message context that are required for further + // processing + injectInboundMessageContexts(messageContext, metadataProvider, peerEntityRole); + final PvpSamlMessageHandlerChain messageValidatorChain = + buildMessageValidationChain(req, 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); + log.trace("Message validation (Signature, ...) on binding-level starts ... "); + performMessageValidation(messageValidatorChain, messageContext); + log.trace("Message validation successful"); + return performMessageDecodePostProcessing(messageContext, true); - try { - messageValidatorChain.initialize(); - messageValidatorChain.invoke(messageContext); - - } 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.getMessage() instanceof RequestAbstractType) { - final RequestAbstractType inboundMessage = - (RequestAbstractType) messageContext.getMessage(); - msg = new PvpSProfileRequest(inboundMessage, getSaml2BindingName()); - msg.setEntityID(inboundMessage.getIssuer().getValue()); - - } else if (messageContext.getMessage() instanceof StatusResponseType) { - final StatusResponseType inboundMessage = - (StatusResponseType) messageContext.getMessage(); - msg = new PvpSProfileResponse(inboundMessage); - msg.setEntityID(inboundMessage.getIssuer().getValue()); - - } else { - // create empty container if request type is unknown - msg = new InboundMessage(); - - } - - msg.setVerified(false); - msg.setRelayState(SAMLBindingSupport.getRelayState(messageContext)); - - return msg; - -// 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); -// -// } 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 @@ -341,5 +168,38 @@ public class RedirectBinding extends AbstractBinding implements IDecoder, IEncod @Override public String getSaml2BindingName() { return SAMLConstants.SAML2_REDIRECT_BINDING_URI; + + } + + private PvpSamlMessageHandlerChain buildMessageValidationChain(HttpServletRequest req, + IPvp2MetadataProvider metadataProvider) { + final PvpSamlMessageHandlerChain messageValidatorChain = new PvpSamlMessageHandlerChain(); + final EaafSaml2HttpRedirectDeflateSignatureSecurityHandler redirectBindingSignaturHandler = + new EaafSaml2HttpRedirectDeflateSignatureSecurityHandler(metadataProvider); + redirectBindingSignaturHandler.setHttpServletRequest(req); + + messageValidatorChain.addHandler(new CheckMessageVersionHandler()); + messageValidatorChain.addHandler(redirectBindingSignaturHandler); + messageValidatorChain.addHandler(new MessageLifetimeSecurityHandler()); + + /* + * TODO: maybe we add it in a later version Because: - AuthnRequest replay + * should not be a problem on IDP side - Response replay will be not possible, + * because EAAF PVP implements countermeasure based on one-time tokens for each + * request + * + */ + // final MessageReplaySecurityHandler replaySecurityHandler = new + // MessageReplaySecurityHandler(); + // final StorageService replayCacheStorage = null; + // final ReplayCache replayCache = new ReplayCache(); + // replayCache.setId("Message replay cache"); + // replayCache.setStrict(true); + // replayCache.setStorage(replayCacheStorage); + // replaySecurityHandler.setReplayCache(replayCache ); + // messageValidatorChain.addHandler(replaySecurityHandler); + + return messageValidatorChain; + } } -- cgit v1.2.3