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); } }