Package org.opensaml.common.binding.security

Source Code of org.opensaml.common.binding.security.SAMLProtocolMessageXMLSignatureSecurityPolicyRule

/*
* Licensed to the University Corporation for Advanced Internet Development,
* Inc. (UCAID) under one or more contributor license agreements.  See the
* NOTICE file distributed with this work for additional information regarding
* copyright ownership. The UCAID licenses this file to You under the Apache
* License, Version 2.0 (the "License"); you may not use this file except in
* compliance with the License.  You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.opensaml.common.binding.security;

import org.opensaml.common.SAMLObject;
import org.opensaml.common.SignableSAMLObject;
import org.opensaml.common.binding.SAMLMessageContext;
import org.opensaml.security.SAMLSignatureProfileValidator;
import org.opensaml.ws.message.MessageContext;
import org.opensaml.ws.security.SecurityPolicyException;
import org.opensaml.xml.security.trust.TrustEngine;
import org.opensaml.xml.signature.Signature;
import org.opensaml.xml.validation.ValidationException;
import org.opensaml.xml.validation.Validator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* SAML security policy rule which validates the signature (if present) on the {@link SAMLObject} which represents the
* SAML protocol message being processed.
*
* <p>
* If the message is not an instance of {@link SignableSAMLObject}, then no processing is performed. If signature
* validation is successful, and the SAML message context issuer was not previously authenticated, then the context's
* issuer authentication state will be set to <code>true</code>.
* </p>
*
* <p>
* If an optional {@link Validator} for {@link Signature} objects is supplied, this validator will be used to validate
* the XML Signature element prior to the actual cryptographic validation of the signature. This might for example be
* used to enforce certain signature profile requirements or to detect signatures upon which it would be unsafe to
* attempt cryptographic processing. When using the single argument constructuor form, the validator will default to
* {@link SAMLSignatureProfileValidator}.
* </p>
*/
public class SAMLProtocolMessageXMLSignatureSecurityPolicyRule extends BaseSAMLXMLSignatureSecurityPolicyRule {

    /** Logger. */
    private final Logger log = LoggerFactory.getLogger(SAMLProtocolMessageXMLSignatureSecurityPolicyRule.class);

    /** Validator for XML Signature instances. */
    private Validator<Signature> sigValidator;

    /**
     * Constructor.
     *
     * Signature pre-validator defaults to {@link SAMLSignatureProfileValidator}.
     *
     * @param engine Trust engine used to verify the signature
     */
    public SAMLProtocolMessageXMLSignatureSecurityPolicyRule(TrustEngine<Signature> engine) {
        super(engine);
        sigValidator = new SAMLSignatureProfileValidator();
    }

    /**
     * Constructor.
     *
     * @param engine Trust engine used to verify the signature
     * @param signatureValidator optional pre-validator used to validate Signature elements prior to the actual
     *            cryptographic validation operation
     */
    public SAMLProtocolMessageXMLSignatureSecurityPolicyRule(TrustEngine<Signature> engine,
            Validator<Signature> signatureValidator) {
        super(engine);
        sigValidator = signatureValidator;
    }

    /** {@inheritDoc} */
    public void evaluate(MessageContext messageContext) throws SecurityPolicyException {
        if (!(messageContext instanceof SAMLMessageContext)) {
            log.debug("Invalid message context type, this policy rule only supports SAMLMessageContext");
            return;
        }

        SAMLMessageContext samlMsgCtx = (SAMLMessageContext) messageContext;

        SAMLObject samlMsg = samlMsgCtx.getInboundSAMLMessage();
        if (!(samlMsg instanceof SignableSAMLObject)) {
            log.debug("Extracted SAML message was not a SignableSAMLObject, can not process signature");
            return;
        }
        SignableSAMLObject signableObject = (SignableSAMLObject) samlMsg;
        if (!signableObject.isSigned()) {
            log.info("SAML protocol message was not signed, skipping XML signature processing");
            return;
        }
        Signature signature = signableObject.getSignature();

        performPreValidation(signature);

        doEvaluate(signature, signableObject, samlMsgCtx);
    }

    /**
     * Perform cryptographic validation and trust evaluation on the Signature token using the configured Signature trust
     * engine.
     *
     * @param signature the signature which is being evaluated
     * @param signableObject the signable object which contained the signature
     * @param samlMsgCtx the SAML message context being processed
     * @throws SecurityPolicyException thrown if the signature fails validation
     */
    protected void doEvaluate(Signature signature, SignableSAMLObject signableObject, SAMLMessageContext samlMsgCtx)
            throws SecurityPolicyException {

        String contextIssuer = samlMsgCtx.getInboundMessageIssuer();
        if (contextIssuer != null) {
            String msgType = signableObject.getElementQName().toString();
            log.debug("Attempting to verify signature on signed SAML protocol message using context issuer message type: {}",
                            msgType);

            if (evaluate(signature, contextIssuer, samlMsgCtx)) {
                log.info("Validation of protocol message signature succeeded, message type: {}", msgType);
                if (!samlMsgCtx.isInboundSAMLMessageAuthenticated()) {
                    log.debug("Authentication via protocol message signature succeeded for context issuer entity ID {}",
                            contextIssuer);
                    samlMsgCtx.setInboundSAMLMessageAuthenticated(true);
                }
            } else {
                log.debug("Validation of protocol message signature failed for context issuer '" + contextIssuer
                        + "', message type: " + msgType);
                throw new SecurityPolicyException("Validation of protocol message signature failed");
            }
        } else {
            log.debug("Context issuer unavailable, can not attempt SAML protocol message signature validation");
            throw new SecurityPolicyException("Context issuer unavailable, can not validate signature");
        }
    }

    /**
     * Get the validator used to perform pre-validation on Signature tokens.
     *
     * @return the configured Signature validator, or null
     */
    protected Validator<Signature> getSignaturePrevalidator() {
        return sigValidator;
    }

    /**
     * Perform pre-validation on the Signature token.
     *
     * @param signature the signature to evaluate
     * @throws SecurityPolicyException thrown if the signature element fails pre-validation
     */
    protected void performPreValidation(Signature signature) throws SecurityPolicyException {
        if (getSignaturePrevalidator() != null) {
            try {
                getSignaturePrevalidator().validate(signature);
            } catch (ValidationException e) {
                log.debug("Protocol message signature failed signature pre-validation", e);
                throw new SecurityPolicyException("Protocol message signature failed signature pre-validation", e);
            }
        }
    }
}
TOP

Related Classes of org.opensaml.common.binding.security.SAMLProtocolMessageXMLSignatureSecurityPolicyRule

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.