diff options
Diffstat (limited to 'eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/AbstractBinding.java')
-rw-r--r-- | eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/binding/AbstractBinding.java | 219 |
1 files changed, 219 insertions, 0 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..3543d85a --- /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,219 @@ +package at.gv.egiz.eaaf.modules.pvp2.impl.binding; + +import javax.xml.namespace.QName; + +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.message.InboundMessageInterface; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2Exception; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2InternalErrorException; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlBindingException; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlMessageValidationException; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlSigningException; +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.utils.Saml2Utils; +import at.gv.egiz.eaaf.modules.pvp2.impl.validation.TrustEngineFactory; +import at.gv.egiz.eaaf.modules.pvp2.impl.verification.PvpSamlMessageHandlerChain; + +import org.opensaml.core.config.ConfigurationService; +import org.opensaml.messaging.context.BaseContext; +import org.opensaml.messaging.context.MessageContext; +import org.opensaml.messaging.decoder.MessageDecodingException; +import org.opensaml.messaging.decoder.servlet.HttpServletRequestMessageDecoder; +import org.opensaml.messaging.handler.MessageHandlerException; +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.core.RequestAbstractType; +import org.opensaml.saml.saml2.core.StatusResponseType; +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; + +import com.google.common.base.Optional; +import com.google.common.base.Predicates; +import com.google.common.base.Throwables; +import com.google.common.collect.FluentIterable; +import lombok.extern.slf4j.Slf4j; +import net.shibboleth.utilities.java.support.component.ComponentInitializationException; + +/** + * Abstract Binding implements common code for SAML2 binding implementations. + * + * @author tlenz + * + */ +@Slf4j +public abstract class AbstractBinding { + + @Autowired + protected IConfiguration basicConfig; + + public abstract String getSaml2BindingName(); + + protected MessageContext<SAMLObject> internalMessageDecode( + HttpServletRequestMessageDecoder<SAMLObject> decoder, + String binding) throws Pvp2Exception { + try { + decoder.initialize(); + decoder.decode(); + + } catch (final ComponentInitializationException e) { + log.warn("Internal initialization error. Reason: {}", e.getMessage()); + throw new Pvp2InternalErrorException(e); + + } catch (final MessageDecodingException e) { + final Optional<Throwable> pvpException = FluentIterable.from( + Throwables.getCausalChain(e)).filter( + Predicates.instanceOf(Pvp2Exception.class)).first(); + + if (pvpException.isPresent()) { + throw (Pvp2Exception) pvpException.get(); + + } else { + throw new SamlBindingException("internal.pvp.95", + new Object[] { binding, "decoding", e.getMessage() }, + e); + + } + + } + + return decoder.getMessageContext(); + + } + + protected MessageContext<SAMLObject> buildBasicMessageContext( + SAMLMessageEncoder encoder, SignableSAMLObject response) { + final MessageContext<SAMLObject> messageContext = new MessageContext<>(); + 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, true)); + + 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, QName peerEntityRole) throws Pvp2InternalErrorException { + final SAMLPeerEntityContext peerEntityContext = new SAMLPeerEntityContext(); + peerEntityContext.setRole(peerEntityRole); + messageContext.addSubcontext(peerEntityContext); + 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)); + + } + + protected void performMessageValidation(PvpSamlMessageHandlerChain messageValidatorChain, + MessageContext<SAMLObject> messageContext) throws Pvp2Exception { + try { + messageValidatorChain.initialize(); + messageValidatorChain.invoke(messageContext); + + } catch (final ComponentInitializationException e) { + log.warn("Internal initialization error. Reason: {}", e.getMessage()); + throw new Pvp2InternalErrorException(e); + + } catch (final MessageHandlerException e) { + log.info("SAML message validation error. Reason: {}", e.getMessage()); + final Optional<Throwable> pvpException = FluentIterable.from( + Throwables.getCausalChain(e)).filter( + Predicates.instanceOf(Pvp2Exception.class)).first(); + + if (pvpException.isPresent()) { + throw (Pvp2Exception) pvpException.get(); + + } else { + throw new SamlMessageValidationException("internal.pvp.11", + new Object[] { e.getMessage() }, e); + + } + } + } + + protected InboundMessageInterface performMessageDecodePostProcessing( + MessageContext<SAMLObject> messageContext, boolean isVerified) { + 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(isVerified); + msg.setRelayState(SAMLBindingSupport.getRelayState(messageContext)); + + return msg; + } +} |