diff options
Diffstat (limited to 'eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification')
6 files changed, 156 insertions, 117 deletions
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/AbstractRequestSignedSecurityPolicyRule.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/AbstractRequestSignedSecurityPolicyRule.java index 6d78b775..380e735c 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/AbstractRequestSignedSecurityPolicyRule.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/AbstractRequestSignedSecurityPolicyRule.java @@ -24,28 +24,27 @@ import javax.xml.transform.dom.DOMSource; import javax.xml.validation.Schema; import javax.xml.validation.Validator; +import at.gv.egiz.eaaf.modules.pvp2.exception.SchemaValidationException; + import org.apache.commons.lang3.StringUtils; -import org.opensaml.common.SignableSAMLObject; -import org.opensaml.common.xml.SAMLConstants; -import org.opensaml.common.xml.SAMLSchemaBuilder; +import org.opensaml.core.criterion.EntityIdCriterion; +import org.opensaml.saml.common.SignableSAMLObject; +import org.opensaml.saml.common.xml.SAMLConstants; +import org.opensaml.saml.common.xml.SAMLSchemaBuilder; +import org.opensaml.saml.common.xml.SAMLSchemaBuilder.SAML1Version; +import org.opensaml.saml.security.impl.SAMLSignatureProfileValidator; import org.opensaml.security.MetadataCriteria; -import org.opensaml.security.SAMLSignatureProfileValidator; -import org.opensaml.ws.message.MessageContext; +import org.opensaml.security.credential.UsageType; +import org.opensaml.security.criteria.UsageCriterion; import org.opensaml.ws.security.SecurityPolicyException; import org.opensaml.ws.security.SecurityPolicyRule; -import org.opensaml.xml.XMLObject; -import org.opensaml.xml.security.CriteriaSet; -import org.opensaml.xml.security.credential.UsageType; -import org.opensaml.xml.security.criteria.EntityIDCriteria; -import org.opensaml.xml.security.criteria.UsageCriteria; -import org.opensaml.xml.signature.SignatureTrustEngine; -import org.opensaml.xml.validation.ValidationException; +import org.opensaml.xmlsec.signature.support.SignatureTrustEngine; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Element; import org.xml.sax.SAXException; -import at.gv.egiz.eaaf.modules.pvp2.exception.SchemaValidationException; +import net.shibboleth.utilities.java.support.resolver.CriteriaSet; /** * Signature Policy for SAML2 redirect-binding. @@ -58,6 +57,8 @@ public abstract class AbstractRequestSignedSecurityPolicyRule implements Securit private static final Logger log = LoggerFactory.getLogger(AbstractRequestSignedSecurityPolicyRule.class); + private static SAMLSchemaBuilder schemaBuilder = new SAMLSchemaBuilder(SAML1Version.SAML_11); + private SignatureTrustEngine trustEngine = null; private QName peerEntityRole = null; @@ -136,9 +137,9 @@ public abstract class AbstractRequestSignedSecurityPolicyRule implements Securit } final CriteriaSet criteriaSet = new CriteriaSet(); - criteriaSet.add(new EntityIDCriteria(context.getInboundMessageIssuer())); + criteriaSet.add(new EntityIdCriterion(context.getInboundMessageIssuer())); criteriaSet.add(new MetadataCriteria(peerEntityRole, SAMLConstants.SAML20P_NS)); - criteriaSet.add(new UsageCriteria(UsageType.SIGNING)); + criteriaSet.add(new UsageCriterion(UsageType.SIGNING)); try { if (!trustEngine.validate(samlObj.getSignature(), criteriaSet)) { @@ -164,7 +165,7 @@ public abstract class AbstractRequestSignedSecurityPolicyRule implements Securit String err = null; try { - final Schema test = SAMLSchemaBuilder.getSAML11Schema(); + final Schema test = schemaBuilder.getSAMLSchema(); final Validator val = test.newValidator(); val.validate(new DOMSource(source)); log.debug("Schema validation check done OK"); 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 new file mode 100644 index 00000000..2672bef2 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/EaafMessageContextInitializationHandler.java @@ -0,0 +1,23 @@ +package at.gv.egiz.eaaf.modules.pvp2.impl.verification; + +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 lombok.extern.slf4j.Slf4j; + +@Slf4j +public class EaafMessageContextInitializationHandler extends AbstractMessageHandler<SAMLObject> { + + @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()); + + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PvpAuthRequestSignedRole.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PvpAuthRequestSignedRole.java deleted file mode 100644 index 42d7d6a1..00000000 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PvpAuthRequestSignedRole.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a - * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European - * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in - * compliance with the Licence. You may obtain a copy of the Licence at: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * Unless required by applicable law or agreed to in writing, software distributed under the Licence - * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the Licence for the specific language governing permissions and limitations under - * the Licence. - * - * This product combines work with different licenses. See the "NOTICE" text file for details on the - * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative - * works that you distribute must include a readable copy of the "NOTICE" text file. -*/ - -package at.gv.egiz.eaaf.modules.pvp2.impl.verification; - -import java.util.List; - -import org.opensaml.common.binding.SAMLMessageContext; -import org.opensaml.saml2.binding.security.SAML2AuthnRequestsSignedRule; -import org.opensaml.ws.transport.http.HTTPInTransport; -import org.opensaml.xml.util.DatatypeHelper; - -public class PvpAuthRequestSignedRole extends SAML2AuthnRequestsSignedRule { - - @Override - protected boolean isMessageSigned(final SAMLMessageContext messageContext) { - // This handles HTTP-Redirect and HTTP-POST-SimpleSign bindings. - final HTTPInTransport inTransport = - (HTTPInTransport) messageContext.getInboundMessageTransport(); - - // Check signature parameter exists only once and is not empty - final List<String> sigParam = inTransport.getParameterValues("Signature"); - final boolean isValidSigned = sigParam.size() == 1 && !DatatypeHelper.isEmpty(sigParam.get(0)); - - // Check signature-algorithm parameter exists only once and is not empty - final List<String> sigAlgParam = inTransport.getParameterValues("SigAlg"); - final boolean isValidSigAlgExists = - sigAlgParam.size() == 1 && !DatatypeHelper.isEmpty(sigAlgParam.get(0)); - - // Check signature-content parameter exists only once and is not empty - final List<String> samlReqParam = inTransport.getParameterValues("SAMLRequest"); - final List<String> samlRespParam = inTransport.getParameterValues("SAMLResponse"); - final boolean isValidContent = - (samlReqParam.size() == 1 && !DatatypeHelper.isEmpty(samlReqParam.get(0)) - || samlRespParam.size() == 1 && !DatatypeHelper.isEmpty(samlRespParam.get(0))) - && !(samlReqParam.size() == 1 && samlRespParam.size() == 1); - - return isValidSigned && isValidSigAlgExists && isValidContent; - - } -} 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 new file mode 100644 index 00000000..e43d0423 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PvpSamlMessageHandlerChain.java @@ -0,0 +1,71 @@ +package at.gv.egiz.eaaf.modules.pvp2.impl.verification; + +import java.util.ArrayList; +import java.util.List; + +import org.opensaml.messaging.context.MessageContext; +import org.opensaml.messaging.handler.MessageHandler; +import org.opensaml.messaging.handler.MessageHandlerChain; +import org.opensaml.messaging.handler.MessageHandlerException; +import org.opensaml.saml.common.SAMLObject; + +import lombok.extern.slf4j.Slf4j; +import net.shibboleth.utilities.java.support.component.ComponentInitializationException; + +@Slf4j +public class PvpSamlMessageHandlerChain implements MessageHandlerChain<SAMLObject> { + private final List<MessageHandler<SAMLObject>> handlers = new ArrayList<>(); + private boolean isInitialized = false; + + @Override + public void invoke(MessageContext<SAMLObject> messageContext) throws MessageHandlerException { + if (!isInitialized) { + throw new RuntimeException("Component: " + + PvpSamlMessageHandlerChain.class.getName() + " not initialized"); + + } + for (final MessageHandler<SAMLObject> handler : getHandlers()) { + log.trace("Initializing SAML message handler: {}", handler.getClass().getName()); + handler.invoke(messageContext); + + } + + } + + @Override + public boolean isInitialized() { + return isInitialized; + + } + + @Override + public void initialize() throws ComponentInitializationException { + if (!isInitialized) { + for (final MessageHandler<SAMLObject> handler : getHandlers()) { + log.trace("Initializing SAML message handler: {}", handler.getClass().getName()); + handler.initialize(); + + } + + isInitialized = true; + } + + } + + @Override + public List<MessageHandler<SAMLObject>> getHandlers() { + return handlers; + + } + + public void addHandler(MessageHandler<SAMLObject> handler) { + handlers.add(handler); + + } + + public void addHandlers(List<MessageHandler<SAMLObject>> handlerList) { + handlers.addAll(handlerList); + + } + +} diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PvpSignedRequestPolicyRule.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PvpSignedRequestPolicyRule.java index c7a43b0b..9c02221c 100644 --- a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PvpSignedRequestPolicyRule.java +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/verification/PvpSignedRequestPolicyRule.java @@ -21,13 +21,12 @@ package at.gv.egiz.eaaf.modules.pvp2.impl.verification; import javax.xml.namespace.QName; -import org.opensaml.common.SignableSAMLObject; -import org.opensaml.saml2.metadata.provider.MetadataProvider; -import org.opensaml.xml.XMLObject; -import org.opensaml.xml.signature.SignatureTrustEngine; - import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IRefreshableMetadataProvider; +import org.opensaml.saml.common.SignableSAMLObject; +import org.opensaml.saml2.metadata.provider.MetadataProvider; +import org.opensaml.xmlsec.signature.support.SignatureTrustEngine; + public class PvpSignedRequestPolicyRule extends AbstractRequestSignedSecurityPolicyRule { private IRefreshableMetadataProvider metadataProvider = null; 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 df91ce53..658dfe16 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 @@ -24,43 +24,44 @@ import javax.xml.transform.dom.DOMSource; import javax.xml.validation.Schema; import javax.xml.validation.Validator; -import org.apache.commons.lang3.StringUtils; -import org.opensaml.common.xml.SAMLConstants; -import org.opensaml.common.xml.SAMLSchemaBuilder; -import org.opensaml.saml2.core.RequestAbstractType; -import org.opensaml.saml2.core.StatusResponseType; -import org.opensaml.saml2.metadata.IDPSSODescriptor; -import org.opensaml.saml2.metadata.SPSSODescriptor; -import org.opensaml.security.MetadataCriteria; -import org.opensaml.security.SAMLSignatureProfileValidator; -import org.opensaml.xml.security.CriteriaSet; -import org.opensaml.xml.security.credential.UsageType; -import org.opensaml.xml.security.criteria.EntityIDCriteria; -import org.opensaml.xml.security.criteria.UsageCriteria; -import org.opensaml.xml.signature.SignatureTrustEngine; -import org.opensaml.xml.validation.ValidationException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.w3c.dom.Element; -import org.xml.sax.SAXException; - import at.gv.egiz.eaaf.core.exceptions.EaafProtocolException; import at.gv.egiz.eaaf.core.exceptions.InvalidProtocolRequestException; -import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvpMetadataProvider; +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.SchemaValidationException; 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; -@Service("SAMLVerificationEngine") +import org.apache.commons.lang3.StringUtils; +import org.opensaml.core.criterion.EntityIdCriterion; +import org.opensaml.saml.common.xml.SAMLConstants; +import org.opensaml.saml.common.xml.SAMLSchemaBuilder; +import org.opensaml.saml.common.xml.SAMLSchemaBuilder.SAML1Version; +import org.opensaml.saml.criterion.EntityRoleCriterion; +import org.opensaml.saml.criterion.ProtocolCriterion; +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.security.impl.SAMLSignatureProfileValidator; +import org.opensaml.security.credential.UsageType; +import org.opensaml.security.criteria.UsageCriterion; +import org.opensaml.xmlsec.signature.support.SignatureException; +import org.opensaml.xmlsec.signature.support.SignatureTrustEngine; +import org.springframework.beans.factory.annotation.Autowired; +import org.w3c.dom.Element; +import org.xml.sax.SAXException; + +import lombok.extern.slf4j.Slf4j; +import net.shibboleth.utilities.java.support.resolver.CriteriaSet; + +@Slf4j public class SamlVerificationEngine { - private static final Logger log = LoggerFactory.getLogger(SamlVerificationEngine.class); + private static SAMLSchemaBuilder schemaBuilder = new SAMLSchemaBuilder(SAML1Version.SAML_11); @Autowired(required = true) - IPvpMetadataProvider metadataProvider; + IPvp2MetadataProvider metadataProvider; /** * Verify signature of a signed SAML2 object. @@ -72,7 +73,7 @@ public class SamlVerificationEngine { * @throws Exception In case of a general error */ public void verify(final InboundMessage msg, final SignatureTrustEngine sigTrustEngine) - throws org.opensaml.xml.security.SecurityException, Exception { + throws SecurityException, Exception { try { if (msg instanceof PvpSProfileRequest && ((PvpSProfileRequest) msg).getSamlRequest() instanceof RequestAbstractType) { @@ -135,7 +136,7 @@ public class SamlVerificationEngine { profileValidator.validate(samlObj.getSignature()); performSchemaValidation(samlObj.getDOM()); - } catch (final ValidationException e) { + } catch (final SignatureException e) { log.warn("Signature is not conform to SAML signature profile", e); throw new InvalidProtocolRequestException("pvp2.21", new Object[] {}); @@ -145,15 +146,16 @@ public class SamlVerificationEngine { } final CriteriaSet criteriaSet = new CriteriaSet(); - criteriaSet.add(new EntityIDCriteria(samlObj.getIssuer().getValue())); - criteriaSet.add(new MetadataCriteria(defaultElementName, SAMLConstants.SAML20P_NS)); - criteriaSet.add(new UsageCriteria(UsageType.SIGNING)); + criteriaSet.add(new EntityIdCriterion(samlObj.getIssuer().getValue())); + criteriaSet.add(new ProtocolCriterion(SAMLConstants.SAML20P_NS)); + criteriaSet.add(new EntityRoleCriterion(defaultElementName)); + criteriaSet.add(new UsageCriterion(UsageType.SIGNING)); try { if (!sigTrustEngine.validate(samlObj.getSignature(), criteriaSet)) { throw new InvalidProtocolRequestException("pvp2.21", new Object[] {}); } - } catch (final org.opensaml.xml.security.SecurityException e) { + } catch (final org.opensaml.security.SecurityException e) { log.warn("PVP2x message signature validation FAILED.", e); throw new InvalidProtocolRequestException("pvp2.21", new Object[] {}); } @@ -166,7 +168,7 @@ public class SamlVerificationEngine { profileValidator.validate(samlObj.getSignature()); performSchemaValidation(samlObj.getDOM()); - } catch (final ValidationException e) { + } catch (final SignatureException e) { log.warn("Signature is not conform to SAML signature profile", e); throw new InvalidProtocolRequestException("pvp2.21", new Object[] {}); @@ -176,16 +178,16 @@ public class SamlVerificationEngine { } final CriteriaSet criteriaSet = new CriteriaSet(); - criteriaSet.add(new EntityIDCriteria(samlObj.getIssuer().getValue())); - criteriaSet - .add(new MetadataCriteria(SPSSODescriptor.DEFAULT_ELEMENT_NAME, SAMLConstants.SAML20P_NS)); - criteriaSet.add(new UsageCriteria(UsageType.SIGNING)); + criteriaSet.add(new EntityIdCriterion(samlObj.getIssuer().getValue())); + criteriaSet.add(new ProtocolCriterion(SAMLConstants.SAML20P_NS)); + criteriaSet.add(new EntityRoleCriterion(SPSSODescriptor.DEFAULT_ELEMENT_NAME)); + criteriaSet.add(new UsageCriterion(UsageType.SIGNING)); try { if (!sigTrustEngine.validate(samlObj.getSignature(), criteriaSet)) { throw new InvalidProtocolRequestException("pvp2.21", new Object[] {}); } - } catch (final org.opensaml.xml.security.SecurityException e) { + } catch (final org.opensaml.security.SecurityException e) { log.warn("PVP2x message signature validation FAILED.", e); throw new InvalidProtocolRequestException("pvp2.21", new Object[] {}); } @@ -195,7 +197,7 @@ public class SamlVerificationEngine { String err = null; try { - final Schema test = SAMLSchemaBuilder.getSAML11Schema(); + final Schema test = schemaBuilder.getSAMLSchema(); final Validator val = test.newValidator(); val.validate(new DOMSource(source)); log.debug("Schema validation check done OK"); |