org.apache.ws.security.WSSecurityEngine Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of wss4j Show documentation
Show all versions of wss4j Show documentation
The Apache WSS4J project provides a Java implementation of the primary security standards
for Web Services, namely the OASIS Web Services Security (WS-Security) specifications
from the OASIS Web Services Security TC.
/**
* 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.ws.security;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ws.security.components.crypto.Crypto;
import org.apache.ws.security.conversation.ConversationConstants;
import org.apache.ws.security.message.token.UsernameToken;
import org.apache.ws.security.processor.Processor;
import org.apache.ws.security.util.WSSecurityUtil;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.security.auth.callback.CallbackHandler;
import javax.xml.namespace.QName;
import java.util.Vector;
/**
* WS-Security Engine.
*
*
* @author Davanum Srinivas ([email protected]).
* @author Werner Dittmann ([email protected]).
*/
public class WSSecurityEngine {
public static final String VALUE_TYPE = "ValueType";
private static Log log = LogFactory.getLog(WSSecurityEngine.class.getName());
private static Log tlog =
LogFactory.getLog("org.apache.ws.security.TIME");
private static WSSecurityEngine engine = null;
/**
* The WSSConfig instance used by this SecurityEngine to
* find Processors for processing security headers
*/
private WSSConfig wssConfig = null;
private boolean doDebug = false;
/**
* wsse:BinarySecurityToken
as defined by WS Security specification
*/
public static final QName binaryToken =
new QName(WSConstants.WSSE_NS, WSConstants.BINARY_TOKEN_LN);
/**
* wsse:UsernameToken
as defined by WS Security specification
*/
public static final QName usernameToken =
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 signatureConfirmation =
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 specification
*/
public static final QName SAML_TOKEN =
new QName(WSConstants.SAML_NS, WSConstants.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);
public WSSecurityEngine() {
}
/**
* Get a singleton instance of security engine.
*
*
* @return ws-security engine.
*/
public synchronized static WSSecurityEngine getInstance() {
if (engine == null) {
engine = new WSSecurityEngine();
}
return engine;
}
/**
* @return the WSSConfig object set on this instance, or
* the statically defined one, if the instance-level
* config object is null.
*/
public final WSSConfig
getWssConfig() {
return (wssConfig == null) ? WSSConfig.getDefaultWSConfig() : 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;
}
/**
* 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 {@link UsernameToken} handling
* @param crypto the object that implements the access to the keystore and the
* handling of certificates.
* @return a result vector
* @throws WSSecurityException
* @see WSSecurityEngine#processSecurityHeader(Element securityHeader, CallbackHandler cb,
* Crypto sigCrypto, Crypto decCrypto)
*/
public Vector 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 {@link UsernameToken} handling
* @param sigCrypto the object that implements the access to the keystore and the
* handling of certificates for Signature
* @param decCrypto the object that implements the access to the keystore and the
* handling of certificates for Decryption
* @return a result vector
* @throws WSSecurityException
* @see WSSecurityEngine#processSecurityHeader(
* Element securityHeader, CallbackHandler cb, Crypto sigCrypto, Crypto decCrypto)
*/
public Vector processSecurityHeader(Document doc,
String actor,
CallbackHandler cb,
Crypto sigCrypto,
Crypto decCrypto)
throws WSSecurityException {
doDebug = log.isDebugEnabled();
if (doDebug) {
log.debug("enter processSecurityHeader()");
}
if (actor == null) {
actor = "";
}
Vector wsResult = null;
SOAPConstants sc = WSSecurityUtil.getSOAPConstants(doc.getDocumentElement());
Element elem = WSSecurityUtil.getSecurityHeader(doc, actor, sc);
if (elem != null) {
if (doDebug) {
log.debug("Processing WS-Security header for '" + actor + "' actor.");
}
wsResult = processSecurityHeader(elem, cb, sigCrypto, 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 #usernameToken
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 {@link UsernameToken}handling
* @param sigCrypto the object that implements the access to the keystore and the
* handling of certificates used for Signature
* @param decCrypto the object that implements the access to the keystore and the
* handling of certificates used for Decryption
* @return a Vector of {@link WSSecurityEngineResult}. Each element in the
* the Vector 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 Vector maybe empty if no security processing
* was performed.
* @throws WSSecurityException
*/
protected Vector processSecurityHeader(Element securityHeader,
CallbackHandler cb,
Crypto sigCrypto,
Crypto decCrypto) throws WSSecurityException {
long t0 = 0, t1 = 0, t2 = 0;
if (tlog.isDebugEnabled()) {
t0 = System.currentTimeMillis();
}
/*
* 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.setCrypto(sigCrypto);
NodeList list = securityHeader.getChildNodes();
int len = list.getLength();
Node elem;
if (tlog.isDebugEnabled()) {
t1 = System.currentTimeMillis();
}
Vector returnResults = new Vector();
for (int i = 0; i < len; i++) {
elem = list.item(i);
if (elem.getNodeType() != Node.ELEMENT_NODE) {
continue;
}
QName el = new QName(elem.getNamespaceURI(), elem.getLocalName());
final WSSConfig cfg = getWssConfig();
Processor p = cfg.getProcessor(el);
/*
* 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
*/
if (p != null) {
p.handleToken((Element) elem, sigCrypto, decCrypto, cb, wsDocInfo, returnResults, cfg);
wsDocInfo.setProcessor(p);
} else {
/*
* Add check for a BinarySecurityToken, add info to WSDocInfo. If BST is
* found before a Signature token this would speed up (at least a little
* bit) the processing of STR Transform.
*/
if (doDebug) {
log.debug(
"Unknown Element: " + elem.getLocalName() + " " + elem.getNamespaceURI()
);
}
}
}
if (tlog.isDebugEnabled()) {
t2 = System.currentTimeMillis();
tlog.debug(
"processHeader: total " + (t2 - t0) + ", prepare " + (t1 - t0)
+ ", handle " + (t2 - t1)
);
}
return returnResults;
}
}