All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.wss4j.dom.WSSecurityEngine Maven / Gradle / Ivy

The newest version!
/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF 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.apache.wss4j.dom;

import java.util.ArrayList;
import java.util.List;

import javax.security.auth.callback.CallbackHandler;
import javax.xml.namespace.QName;

import org.apache.wss4j.common.bsp.BSPRule;
import org.apache.wss4j.common.crypto.Crypto;
import org.apache.wss4j.common.derivedKey.ConversationConstants;
import org.apache.wss4j.common.ext.WSSecurityException;
import org.apache.wss4j.dom.handler.RequestData;
import org.apache.wss4j.dom.message.CallbackLookup;
import org.apache.wss4j.dom.processor.Processor;
import org.apache.wss4j.dom.saml.DOMSAMLUtil;
import org.apache.wss4j.dom.util.WSSecurityUtil;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

/**
 * WS-Security Engine.
 */
public class WSSecurityEngine {
    private static final org.slf4j.Logger LOG = 
        org.slf4j.LoggerFactory.getLogger(WSSecurityEngine.class);

    /**
     * wsse:BinarySecurityToken as defined by WS Security specification
     */
    public static final QName BINARY_TOKEN = 
        new QName(WSConstants.WSSE_NS, WSConstants.BINARY_TOKEN_LN);
    /**
     * wsse:UsernameToken as defined by WS Security specification
     */
    public static final QName USERNAME_TOKEN = 
        new QName(WSConstants.WSSE_NS, WSConstants.USERNAME_TOKEN_LN);
    /**
     * wsu:Timestamp as defined by OASIS WS Security specification,
     */
    public static final QName TIMESTAMP = 
        new QName(WSConstants.WSU_NS, WSConstants.TIMESTAMP_TOKEN_LN);
    /**
     * wsse11:signatureConfirmation as defined by OASIS WS Security specification,
     */
    public static final QName SIGNATURE_CONFIRMATION = 
        new QName(WSConstants.WSSE11_NS, WSConstants.SIGNATURE_CONFIRMATION_LN);
    /**
     * ds:Signature as defined by XML Signature specification,
     * enhanced by WS Security specification
     */
    public static final QName SIGNATURE = 
        new QName(WSConstants.SIG_NS, WSConstants.SIG_LN);
    /**
     * xenc:EncryptedKey as defined by XML Encryption specification,
     * enhanced by WS Security specification
     */
    public static final QName ENCRYPTED_KEY = 
        new QName(WSConstants.ENC_NS, WSConstants.ENC_KEY_LN);
    /**
     * xenc:EncryptedData as defined by XML Encryption specification,
     * enhanced by WS Security specification
     */
    public static final QName ENCRYPTED_DATA = 
        new QName(WSConstants.ENC_NS, WSConstants.ENC_DATA_LN);
    /**
     * xenc:ReferenceList as defined by XML Encryption specification,
     */
    public static final QName REFERENCE_LIST = 
        new QName(WSConstants.ENC_NS, WSConstants.REF_LIST_LN);
    /**
     * saml:Assertion as defined by SAML v1.1 specification
     */
    public static final QName SAML_TOKEN = 
        new QName(WSConstants.SAML_NS, WSConstants.ASSERTION_LN);
    
    /**
     * saml:Assertion as defined by SAML v2.0 specification
     */
    public static final QName SAML2_TOKEN = 
        new QName(WSConstants.SAML2_NS, WSConstants.ASSERTION_LN);
    
    /**
     * saml:EncryptedAssertion as defined by SAML v2.0 specification
     */
    public static final QName ENCRYPTED_ASSERTION = 
        new QName(WSConstants.SAML2_NS, WSConstants.ENCRYPED_ASSERTION_LN);

    /**
     * wsc:DerivedKeyToken as defined by WS-SecureConversation specification
     */
    public static final QName DERIVED_KEY_TOKEN_05_02 = 
        new QName(ConversationConstants.WSC_NS_05_02, ConversationConstants.DERIVED_KEY_TOKEN_LN);

    /**
     * wsc:SecurityContextToken as defined by WS-SecureConversation specification
     */
    public static final QName SECURITY_CONTEXT_TOKEN_05_02 = 
        new QName(ConversationConstants.WSC_NS_05_02, ConversationConstants.SECURITY_CONTEXT_TOKEN_LN);

    /**
     * wsc:DerivedKeyToken as defined by WS-SecureConversation specification in WS-SX
     */
    public static final QName DERIVED_KEY_TOKEN_05_12 = 
        new QName(ConversationConstants.WSC_NS_05_12, ConversationConstants.DERIVED_KEY_TOKEN_LN);

    /**
     * wsc:SecurityContextToken as defined by WS-SecureConversation specification in 
     * WS-SX
     */
    public static final QName SECURITY_CONTEXT_TOKEN_05_12 = 
        new QName(ConversationConstants.WSC_NS_05_12, ConversationConstants.SECURITY_CONTEXT_TOKEN_LN);
    
    /**
     * The WSSConfig instance used by this SecurityEngine to
     * find Processors for processing security headers
     */
    private WSSConfig wssConfig;
    private boolean doDebug;
    private CallbackLookup callbackLookup;
    
    /**
     * @return      the WSSConfig object set on this instance
     */
    public final WSSConfig
    getWssConfig() {
        if (wssConfig == null) {
            wssConfig = WSSConfig.getNewInstance();
        }
        return wssConfig;
    }
    
    /**
     * @param cfg   the WSSConfig instance for this WSSecurityEngine to use
     *
     * @return      the WSSConfig instance previously set on this 
     *              WSSecurityEngine instance
     */
    public final WSSConfig
    setWssConfig(WSSConfig cfg) {
        WSSConfig ret = wssConfig;
        wssConfig = cfg;
        return ret;
    }
    
    /**
     * Set the CallbackLookup object to use to locate elements
     * @param callbackLookup the CallbackLookup object to use to locate elements
     */
    public void setCallbackLookup(CallbackLookup callbackLookup) {
        this.callbackLookup = callbackLookup;
    }
    
    /**
     * Get the CallbackLookup object to use to locate elements
     * @return the CallbackLookup object to use to locate elements
     */
    public CallbackLookup getCallbackLookup() {
        return callbackLookup;
    }
    
    /**
     * Process the security header given the soap envelope as W3C document.
     * 

* This is the main entry point to verify or decrypt a SOAP envelope. * First check if a wsse:Security is available with the * defined actor. * * @param doc the SOAP envelope as {@link Document} * @param actor the engine works on behalf of this actor. Refer * to the SOAP specification about actor or role * * @param cb a callback hander to the caller to resolve passwords during * encryption and UsernameToken handling * @param crypto the object that implements the access to the keystore and the * handling of certificates. * @return a result list * @throws WSSecurityException * @see WSSecurityEngine#processSecurityHeader(Element securityHeader, CallbackHandler cb, * Crypto sigVerCrypto, Crypto decCrypto) */ public List processSecurityHeader( Document doc, String actor, CallbackHandler cb, Crypto crypto ) throws WSSecurityException { return processSecurityHeader(doc, actor, cb, crypto, crypto); } /** * Process the security header given the soap envelope as W3C document. *

* This is the main entry point to verify or decrypt a SOAP envelope. * First check if a wsse:Security is available with the * defined actor. * * @param doc the SOAP envelope as {@link Document} * @param actor the engine works on behalf of this actor. Refer * to the SOAP specification about actor or role * * @param cb a callback hander to the caller to resolve passwords during * encryption and UsernameToken handling * @param sigVerCrypto the object that implements the access to the keystore and the * handling of certificates for Signature verification * @param decCrypto the object that implements the access to the keystore and the * handling of certificates for Decryption * @return a result list * @throws WSSecurityException * @see WSSecurityEngine#processSecurityHeader( * Element securityHeader, CallbackHandler cb, Crypto sigVerCrypto, Crypto decCrypto) */ public List processSecurityHeader( Document doc, String actor, CallbackHandler cb, Crypto sigVerCrypto, Crypto decCrypto ) throws WSSecurityException { doDebug = LOG.isDebugEnabled(); if (doDebug) { LOG.debug("enter processSecurityHeader()"); } if (actor == null) { actor = ""; } List wsResult = null; Element elem = WSSecurityUtil.getSecurityHeader(doc, actor); if (elem != null) { if (doDebug) { LOG.debug("Processing WS-Security header for '" + actor + "' actor."); } wsResult = processSecurityHeader(elem, cb, sigVerCrypto, decCrypto); } return wsResult; } /** * Process the security header given the wsse:Security DOM * Element. * * This function loops over all direct child elements of the * wsse:Security header. If it finds a known element, it * transfers control to the appropriate handling function. The method * processes the known child elements in the same order as they appear in * the wsse:Security element. This is in accordance to the WS * Security specification.

* * Currently the functions can handle the following child elements: * *

    *
  • {@link #SIGNATURE ds:Signature}
  • *
  • {@link #ENCRYPTED_KEY xenc:EncryptedKey}
  • *
  • {@link #REFERENCE_LIST xenc:ReferenceList}
  • *
  • {@link #USERNAME_TOKEN wsse:UsernameToken}
  • *
  • {@link #TIMESTAMP wsu:Timestamp}
  • *
* * Note that additional child elements can be processed if appropriate * Processors have been registered with the WSSCondig instance set * on this class. * * @param securityHeader the wsse:Security header element * @param cb a callback hander to the caller to resolve passwords during * encryption and UsernameToken handling * @param sigVerCrypto the object that implements the access to the keystore and the * handling of certificates used for Signature verification * @param decCrypto the object that implements the access to the keystore and the * handling of certificates used for Decryption * @return a List of {@link WSSecurityEngineResult}. Each element in the * the List represents the result of a security action. The elements * are ordered according to the sequence of the security actions in the * wsse:Signature header. The List may be empty if no security processing * was performed. * @throws WSSecurityException */ public List processSecurityHeader( Element securityHeader, CallbackHandler cb, Crypto sigVerCrypto, Crypto decCrypto ) throws WSSecurityException { RequestData data = new RequestData(); data.setWssConfig(getWssConfig()); data.setDecCrypto(decCrypto); data.setSigVerCrypto(sigVerCrypto); data.setCallbackHandler(cb); return processSecurityHeader(securityHeader, data); } /** * Process the security header given the soap envelope as W3C document. *

* This is the main entry point to verify or decrypt a SOAP envelope. * First check if a wsse:Security is available with the * defined actor. * * @param doc the SOAP envelope as {@link Document} * @param actor the engine works on behalf of this actor. Refer * to the SOAP specification about actor or role * * @param requestData the RequestData associated with the request. It should * be able to provide the callback handler, cryptos, etc... * as needed by the processing * @return a result list * @throws WSSecurityException */ public List processSecurityHeader( Document doc, String actor, RequestData requestData ) throws WSSecurityException { if (actor == null) { actor = ""; } List wsResult = null; Element elem = WSSecurityUtil.getSecurityHeader(doc, actor); if (elem != null) { if (doDebug) { LOG.debug("Processing WS-Security header for '" + actor + "' actor."); } wsResult = processSecurityHeader(elem, requestData); } return wsResult; } /** * Process the security header given the wsse:Security DOM * Element. * * This function loops over all direct child elements of the * wsse:Security header. If it finds a known element, it * transfers control to the appropriate handling function. The method * processes the known child elements in the same order as they appear in * the wsse:Security element. This is in accordance to the WS * Security specification.

* * Currently the functions can handle the following child elements: * *

    *
  • {@link #SIGNATURE ds:Signature}
  • *
  • {@link #ENCRYPTED_KEY xenc:EncryptedKey}
  • *
  • {@link #REFERENCE_LIST xenc:ReferenceList}
  • *
  • {@link #USERNAME_TOKEN wsse:UsernameToken}
  • *
  • {@link #TIMESTAMP wsu:Timestamp}
  • *
* * Note that additional child elements can be processed if appropriate * Processors have been registered with the WSSCondig instance set * on this class. * * @param securityHeader the wsse:Security header element * @param requestData the RequestData associated with the request. It should * be able to provide the callback handler, cryptos, etc... * as needed by the processing * @return a List of {@link WSSecurityEngineResult}. Each element in the * the List represents the result of a security action. The elements * are ordered according to the sequence of the security actions in the * wsse:Signature header. The List may be empty if no security processing * was performed. * @throws WSSecurityException */ public List processSecurityHeader( Element securityHeader, RequestData requestData ) throws WSSecurityException { List returnResults = new ArrayList(); if (securityHeader == null) { return returnResults; } if (requestData.getWssConfig() == null) { requestData.setWssConfig(getWssConfig()); } // // Gather some info about the document to process and store // it for retrieval. Store the implementation of signature crypto // (no need for encryption --- yet) // WSDocInfo wsDocInfo = new WSDocInfo(securityHeader.getOwnerDocument()); wsDocInfo.setCallbackLookup(callbackLookup); wsDocInfo.setCrypto(requestData.getSigVerCrypto()); wsDocInfo.setSecurityHeader(securityHeader); final WSSConfig cfg = getWssConfig(); Node node = securityHeader.getFirstChild(); boolean foundTimestamp = false; while (node != null) { Node nextSibling = node.getNextSibling(); if (Node.ELEMENT_NODE == node.getNodeType()) { QName el = new QName(node.getNamespaceURI(), node.getLocalName()); // Check for multiple timestamps if (foundTimestamp && el.equals(TIMESTAMP)) { requestData.getBSPEnforcer().handleBSPRule(BSPRule.R3227); } else if (el.equals(TIMESTAMP)) { foundTimestamp = true; } // // Call the processor for this token. After the processor returns, // store it for later retrieval. The token processor may store some // information about the processed token // Processor p = cfg.getProcessor(el); if (p != null) { List results = p.handleToken((Element) node, requestData, wsDocInfo); if (!results.isEmpty()) { returnResults.addAll(0, results); } } else { if (doDebug) { LOG.debug( "Unknown Element: " + node.getLocalName() + " " + node.getNamespaceURI() ); } } } // // If the next sibling is null and the stored next sibling is not null, then we have // encountered an EncryptedData element which was decrypted, and so the next sibling // of the current node is null. In that case, go on to the previously stored next // sibling // if (node.getNextSibling() == null && nextSibling != null && nextSibling.getParentNode() != null) { node = nextSibling; } else { node = node.getNextSibling(); } } // Validate SAML Subject Confirmation requirements if (wssConfig.isValidateSamlSubjectConfirmation()) { Element bodyElement = WSSecurityUtil.findBodyElement(securityHeader.getOwnerDocument()); DOMSAMLUtil.validateSAMLResults(returnResults, requestData.getTlsCerts(), bodyElement); } return returnResults; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy