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

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

There is a newer version: 3.0.4
Show 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.engine;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

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.ext.WSSecurityException;
import org.apache.wss4j.dom.WSConstants;
import org.apache.wss4j.dom.WSDocInfo;
import org.apache.wss4j.dom.callback.CallbackLookup;
import org.apache.wss4j.dom.callback.DOMCallbackLookup;
import org.apache.wss4j.dom.handler.RequestData;
import org.apache.wss4j.dom.handler.WSHandlerResult;
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);

    /**
     * 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 WSHandlerResult Object containing the results of processing the security header * @throws WSSecurityException * @see WSSecurityEngine#processSecurityHeader(Element securityHeader, CallbackHandler cb, * Crypto sigVerCrypto, Crypto decCrypto) */ public WSHandlerResult 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 WSHandlerResult Object containing the results of processing the security header * @throws WSSecurityException * @see WSSecurityEngine#processSecurityHeader( * Element securityHeader, CallbackHandler cb, Crypto sigVerCrypto, Crypto decCrypto) */ public WSHandlerResult processSecurityHeader( Document doc, String actor, CallbackHandler cb, Crypto sigVerCrypto, Crypto decCrypto ) throws WSSecurityException { LOG.debug("enter processSecurityHeader()"); if (actor == null) { actor = ""; } WSHandlerResult wsResult = null; Element elem = WSSecurityUtil.getSecurityHeader(doc, actor); if (elem != null) { LOG.debug("Processing WS-Security header for '{}' actor.", actor); wsResult = processSecurityHeader(elem, actor, 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 WSHandlerResult Object containing the results of processing the security header * @throws WSSecurityException */ public WSHandlerResult processSecurityHeader( Element securityHeader, String actor, CallbackHandler cb, Crypto sigVerCrypto, Crypto decCrypto ) throws WSSecurityException { RequestData data = new RequestData(); data.setActor(actor); 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 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 WSHandlerResult Object containing the results of processing the security header * @throws WSSecurityException */ public WSHandlerResult processSecurityHeader( Document doc, RequestData requestData ) throws WSSecurityException { if (requestData.getActor() == null) { requestData.setActor(""); } String actor = requestData.getActor(); WSHandlerResult 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 WSHandlerResult Object containing the results of processing the security header * @throws WSSecurityException */ public WSHandlerResult processSecurityHeader( Element securityHeader, RequestData requestData ) throws WSSecurityException { if (securityHeader == null) { List results = Collections.emptyList(); Map> actionResults = Collections.emptyMap(); return new WSHandlerResult(null, results, actionResults); } 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()); CallbackLookup callbackLookupToUse = callbackLookup; if (callbackLookupToUse == null) { callbackLookupToUse = new DOMCallbackLookup(securityHeader.getOwnerDocument()); } wsDocInfo.setCallbackLookup(callbackLookupToUse); wsDocInfo.setCrypto(requestData.getSigVerCrypto()); wsDocInfo.setSecurityHeader(securityHeader); requestData.setWsDocInfo(wsDocInfo); final WSSConfig cfg = getWssConfig(); Node node = securityHeader.getFirstChild(); List returnResults = new LinkedList<>(); 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(WSConstants.TIMESTAMP)) { requestData.getBSPEnforcer().handleBSPRule(BSPRule.R3227); } else if (el.equals(WSConstants.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); 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(); } } WSHandlerResult handlerResult = new WSHandlerResult(requestData.getActor(), returnResults, wsDocInfo.getActionResults()); // Validate SAML Subject Confirmation requirements if (requestData.isValidateSamlSubjectConfirmation()) { Element bodyElement = callbackLookupToUse.getSOAPBody(); DOMSAMLUtil.validateSAMLResults(handlerResult, requestData.getTlsCerts(), bodyElement); } wsDocInfo.clear(); return handlerResult; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy