diff options
Diffstat (limited to 'eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification')
5 files changed, 228 insertions, 4 deletions
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/EaafMessageContextInitializationHandler.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/EaafMessageContextInitializationHandler.java index 2672bef2..aba0a68b 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/EaafMessageContextInitializationHandler.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/EaafMessageContextInitializationHandler.java @@ -1,23 +1,64 @@ package at.gv.egiz.eaaf.modules.pvp2.impl.verification; +import javax.annotation.Nonnull; + +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2InternalErrorException; +import at.gv.egiz.eaaf.modules.pvp2.impl.validation.TrustEngineFactory; + +import org.opensaml.core.config.ConfigurationService; import org.opensaml.messaging.context.MessageContext; import org.opensaml.messaging.handler.AbstractMessageHandler; import org.opensaml.messaging.handler.MessageHandlerException; import org.opensaml.saml.common.SAMLObject; import org.opensaml.saml.common.messaging.context.SAMLMessageInfoContext; import org.opensaml.saml.common.messaging.context.SAMLPeerEntityContext; +import org.opensaml.xmlsec.SignatureValidationConfiguration; +import org.opensaml.xmlsec.SignatureValidationParameters; +import org.opensaml.xmlsec.context.SecurityParametersContext; +import org.opensaml.xmlsec.signature.support.SignatureTrustEngine; import lombok.extern.slf4j.Slf4j; +import net.shibboleth.utilities.java.support.component.ComponentInitializationException; @Slf4j public class EaafMessageContextInitializationHandler extends AbstractMessageHandler<SAMLObject> { + private final IPvp2MetadataProvider internalMetadataProvider; + private SignatureTrustEngine trustEngine; + + public EaafMessageContextInitializationHandler(@Nonnull IPvp2MetadataProvider metadataProvider) { + internalMetadataProvider = metadataProvider; + } + + @Override + protected void doInitialize() throws ComponentInitializationException { + try { + trustEngine = TrustEngineFactory.getSignatureKnownKeysTrustEngine(internalMetadataProvider); + + } catch (final Pvp2InternalErrorException e) { + throw new ComponentInitializationException("TrustEngine injection FAILED", e); + + } + } + + @Override protected void doInvoke(MessageContext<SAMLObject> messageContext) throws MessageHandlerException { log.trace("Injecting sub-context to SAML2 message ... "); messageContext.addSubcontext(new SAMLPeerEntityContext()); messageContext.addSubcontext(new SAMLMessageInfoContext()); + + 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(trustEngine); } } diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/EaafSaml2HttpRedirectDeflateSignatureSecurityHandler.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/EaafSaml2HttpRedirectDeflateSignatureSecurityHandler.java new file mode 100644 index 00000000..204229ee --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/EaafSaml2HttpRedirectDeflateSignatureSecurityHandler.java @@ -0,0 +1,107 @@ +package at.gv.egiz.eaaf.modules.pvp2.impl.verification; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IRefreshableMetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlSigningException; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.SamlHttpUtils; + +import org.opensaml.messaging.context.MessageContext; +import org.opensaml.messaging.handler.MessageHandlerException; +import org.opensaml.saml.common.messaging.context.SAMLPeerEntityContext; +import org.opensaml.saml.saml2.binding.security.impl.SAML2HTTPRedirectDeflateSignatureSecurityHandler; + +import com.google.common.base.Strings; +import lombok.extern.slf4j.Slf4j; +import net.shibboleth.utilities.java.support.codec.Base64Support; + +/** + * Always extracts the last http parameter with a specific name from request, if + * more than one with the same name exists. + * + * @author tlenz + * + */ +@Slf4j +public class EaafSaml2HttpRedirectDeflateSignatureSecurityHandler extends + SAML2HTTPRedirectDeflateSignatureSecurityHandler { + + public static final String HTTP_REDIRECT_SIGALG = "SigAlg"; + public static final String HTTP_REDIRECT_SIGNATURE = "Signature"; + + private IRefreshableMetadataProvider refreshableMetadataProvider = null; + + /** + * Signature verification handler that reloads SAML2 metadata if signature + * verification fails. + * + * @param metadataProvider Metadata provider implementation. Refreshing is only + * possible, if that provider implements + * {@link IRefreshableMetadataProvider} + */ + public EaafSaml2HttpRedirectDeflateSignatureSecurityHandler( + @Nullable IPvp2MetadataProvider metadataProvider) { + if (metadataProvider != null) { + if (metadataProvider instanceof IRefreshableMetadataProvider) { + refreshableMetadataProvider = (IRefreshableMetadataProvider) metadataProvider; + + } else { + log.trace("Refreshing is not supported by {} metadata-provider", + metadataProvider.getClass().getSimpleName()); + + } + } + } + + @Override + protected void doInvoke(@Nonnull final MessageContext messageContext) throws MessageHandlerException { + try { + super.doInvoke(messageContext); + + } catch (final MessageHandlerException e) { + if (refreshableMetadataProvider != null) { + + log.debug("Starting metadata refresh process ... "); + if (refreshableMetadataProvider.refreshMetadataProvider( + messageContext.getSubcontext(SAMLPeerEntityContext.class).getEntityId())) { + log.trace("Refreshing successful. Restarting message evaluation ... "); + + try { + super.doInvoke(messageContext); + return; + + } catch (final MessageHandlerException e1) { + log.debug("Signature validation fails twice with second error: {}", e.getMessage()); + + } + } + } + + log.info("Signature validation of SAML message failed. Reason: {}", e.getMessage()); + throw new MessageHandlerException( + new SamlSigningException("internal.pvp.10", new Object[] { e.getMessage() }, e)); + } + } + + @Override + @Nullable + protected byte[] getSignature() throws MessageHandlerException { + final String signature = SamlHttpUtils.getLastParameterFromRequest( + getHttpServletRequest(), HTTP_REDIRECT_SIGNATURE); + + if (Strings.isNullOrEmpty(signature)) { + return null; + + } + return Base64Support.decode(signature); + } + + @Override + @Nullable + protected String getSignatureAlgorithm() throws MessageHandlerException { + return SamlHttpUtils.getLastParameterFromRequest(getHttpServletRequest(), HTTP_REDIRECT_SIGALG); + + } +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/EaafSamlProtocolMessageXmlSignatureSecurityHandler.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/EaafSamlProtocolMessageXmlSignatureSecurityHandler.java new file mode 100644 index 00000000..9f6bc864 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/EaafSamlProtocolMessageXmlSignatureSecurityHandler.java @@ -0,0 +1,75 @@ +package at.gv.egiz.eaaf.modules.pvp2.impl.verification; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvp2MetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IRefreshableMetadataProvider; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlSigningException; + +import org.opensaml.messaging.context.MessageContext; +import org.opensaml.messaging.handler.MessageHandlerException; +import org.opensaml.saml.common.binding.security.impl.SAMLProtocolMessageXMLSignatureSecurityHandler; +import org.opensaml.saml.common.messaging.context.SAMLPeerEntityContext; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class EaafSamlProtocolMessageXmlSignatureSecurityHandler extends + SAMLProtocolMessageXMLSignatureSecurityHandler { + + private IRefreshableMetadataProvider refreshableMetadataProvider = null; + + /** + * Signature verification handler that reloads SAML2 metadata if signature + * verification fails. + * + * @param metadataProvider Metadata provider implementation. Refreshing is only + * possible, if that provider implements + * {@link IRefreshableMetadataProvider} + */ + public EaafSamlProtocolMessageXmlSignatureSecurityHandler( + @Nullable IPvp2MetadataProvider metadataProvider) { + if (metadataProvider != null) { + if (metadataProvider instanceof IRefreshableMetadataProvider) { + refreshableMetadataProvider = (IRefreshableMetadataProvider) metadataProvider; + + } else { + log.trace("Refreshing is not supported by {} metadata-provider", + metadataProvider.getClass().getSimpleName()); + + } + } + } + + @Override + public void doInvoke(@Nonnull final MessageContext messageContext) throws MessageHandlerException { + try { + super.doInvoke(messageContext); + + } catch (final MessageHandlerException e) { + if (refreshableMetadataProvider != null) { + + log.debug("Starting metadata refresh process ... "); + if (refreshableMetadataProvider.refreshMetadataProvider( + messageContext.getSubcontext(SAMLPeerEntityContext.class).getEntityId())) { + log.trace("Refreshing successful. Restarting message evaluation ... "); + + try { + super.doInvoke(messageContext); + return; + + } catch (final MessageHandlerException e1) { + log.debug("Signature validation fails twice with second error: {}", e.getMessage()); + + } + } + } + + log.info("Signature validation of SAML message failed. Reason: {}", e.getMessage()); + throw new MessageHandlerException( + new SamlSigningException("internal.pvp.10", new Object[] { e.getMessage() }, e)); + } + + } +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PvpSamlMessageHandlerChain.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PvpSamlMessageHandlerChain.java index e43d0423..a1365023 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PvpSamlMessageHandlerChain.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PvpSamlMessageHandlerChain.java @@ -24,12 +24,12 @@ public class PvpSamlMessageHandlerChain implements MessageHandlerChain<SAMLObjec + PvpSamlMessageHandlerChain.class.getName() + " not initialized"); } + for (final MessageHandler<SAMLObject> handler : getHandlers()) { log.trace("Initializing SAML message handler: {}", handler.getClass().getName()); handler.invoke(messageContext); } - } @Override diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/SamlVerificationEngine.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/SamlVerificationEngine.java index 658dfe16..2e26de7f 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/SamlVerificationEngine.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/SamlVerificationEngine.java @@ -68,9 +68,10 @@ public class SamlVerificationEngine { * * @param msg SAML2 message * @param sigTrustEngine TrustEngine - * @throws org.opensaml.xml.security.SecurityException In case of - * invalid signature - * @throws Exception In case of a general error + * @throws org.opensaml.xml.security.SecurityException In case of invalid + * signature + * @throws Exception In case of a general + * error */ public void verify(final InboundMessage msg, final SignatureTrustEngine sigTrustEngine) throws SecurityException, Exception { |