blob: 4b8548fefb9b9d34e82e7ba33d63879d7cd0f80a [file] [log] [blame]
/*
* Copyright 2004,2005 The Apache Software Foundation.
*
* Licensed 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.rampart.handler;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMException;
import org.apache.axiom.soap.SOAPEnvelope;
import org.apache.axiom.soap.SOAPHeader;
import org.apache.axiom.soap.SOAPHeaderBlock;
import org.apache.axis2.AxisFault;
import org.apache.axis2.Constants;
import org.apache.axis2.addressing.AddressingConstants;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.context.OperationContext;
import org.apache.axis2.wsdl.WSDLConstants;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.rampart.RampartConstants;
import org.apache.rampart.util.Axis2Util;
import org.apache.rampart.util.HandlerParameterDecoder;
import org.apache.ws.security.SOAPConstants;
import org.apache.ws.security.WSConstants;
import org.apache.ws.security.WSSecurityEngineResult;
import org.apache.ws.security.WSSecurityException;
import org.apache.ws.security.handler.RequestData;
import org.apache.ws.security.handler.WSHandlerConstants;
import org.apache.ws.security.handler.WSHandlerResult;
import org.apache.ws.security.message.token.Timestamp;
import org.apache.ws.security.util.WSSecurityUtil;
import org.w3c.dom.Document;
import javax.security.auth.callback.CallbackHandler;
import javax.xml.namespace.QName;
import java.security.cert.X509Certificate;
import java.util.Iterator;
import java.util.Vector;
/**
* @deprecated
*/
public class WSDoAllReceiver extends WSDoAllHandler {
private static final Log log = LogFactory.getLog(WSDoAllReceiver.class);
private static Log mlog = LogFactory.getLog(RampartConstants.MESSAGE_LOG);
public WSDoAllReceiver() {
super();
inHandler = true;
}
public void processMessage(MessageContext msgContext) throws AxisFault {
if(mlog.isDebugEnabled()){
mlog.debug("*********************** WSDoAllReceiver recieved \n"+msgContext.getEnvelope());
}
boolean doDebug = log.isDebugEnabled();
if (doDebug) {
log.debug("WSDoAllReceiver: enter invoke() ");
}
String useDoomValue = (String) getProperty(msgContext,
WSSHandlerConstants.USE_DOOM);
boolean useDoom = useDoomValue != null
&& Constants.VALUE_TRUE.equalsIgnoreCase(useDoomValue);
RequestData reqData = new RequestData();
try {
this.processBasic(msgContext, useDoom, reqData);
} catch (AxisFault axisFault) {
setAddressingInformationOnFault(msgContext);
throw axisFault;
} catch (Exception e) {
setAddressingInformationOnFault(msgContext);
throw new AxisFault(e.getMessage(), e);
} finally {
if (reqData != null) {
reqData.clear();
reqData = null;
}
if (doDebug) {
log.debug("WSDoAllReceiver: exit invoke()");
}
}
}
private void processBasic(MessageContext msgContext, boolean useDoom, RequestData reqData)
throws Exception {
// populate the properties
try {
HandlerParameterDecoder.processParameters(msgContext, true);
} catch (Exception e) {
throw new AxisFault("Configuration error", e);
}
reqData = new RequestData();
reqData.setMsgContext(msgContext);
if (((getOption(WSSHandlerConstants.INFLOW_SECURITY)) == null) &&
((getProperty(msgContext, WSSHandlerConstants.INFLOW_SECURITY)) == null)) {
if (msgContext.isServerSide() &&
((getOption(WSSHandlerConstants.INFLOW_SECURITY_SERVER)) == null) &&
((getProperty(msgContext, WSSHandlerConstants.INFLOW_SECURITY_SERVER)) == null)) {
return;
} else if (((getOption(WSSHandlerConstants.INFLOW_SECURITY_CLIENT)) == null) &&
((getProperty(msgContext, WSSHandlerConstants.INFLOW_SECURITY_CLIENT)) == null)) {
return;
}
}
Vector actions = new Vector();
String action = null;
if ((action = (String) getOption(WSSHandlerConstants.ACTION_ITEMS)) == null) {
action = (String) getProperty(msgContext,
WSSHandlerConstants.ACTION_ITEMS);
}
if (action == null) {
throw new AxisFault("WSDoAllReceiver: No action items defined");
}
int doAction = WSSecurityUtil.decodeAction(action, actions);
if (doAction == WSConstants.NO_SECURITY) {
return;
}
String actor = (String) getOption(WSHandlerConstants.ACTOR);
Document doc = null;
try {
doc = Axis2Util.getDocumentFromSOAPEnvelope(msgContext
.getEnvelope(), useDoom);
} catch (WSSecurityException wssEx) {
throw new AxisFault(
"WSDoAllReceiver: Error in converting to Document", wssEx);
}
// Do not process faults
SOAPConstants soapConstants = WSSecurityUtil.getSOAPConstants(doc
.getDocumentElement());
if (WSSecurityUtil.findElement(doc.getDocumentElement(), "Fault",
soapConstants.getEnvelopeURI()) != null) {
return;
}
/*
* To check a UsernameToken or to decrypt an encrypted message we need a
* password.
*/
CallbackHandler cbHandler = null;
if ((doAction & (WSConstants.ENCR | WSConstants.UT)) != 0) {
cbHandler = getPasswordCB(reqData);
}
// Copy the WSHandlerConstants.SEND_SIGV over to the new message
// context - if it exists, if signatureConfirmation in the response msg
String sigConfEnabled = null;
if ((sigConfEnabled = (String) getOption(WSHandlerConstants.ENABLE_SIGNATURE_CONFIRMATION)) == null) {
sigConfEnabled = (String) getProperty(msgContext,
WSHandlerConstants.ENABLE_SIGNATURE_CONFIRMATION);
}
// To handle sign confirmation of a sync response
// TODO Async response
if (!msgContext.isServerSide()
&& !"false".equalsIgnoreCase(sigConfEnabled)) {
OperationContext opCtx = msgContext.getOperationContext();
MessageContext outMsgCtx = opCtx
.getMessageContext(WSDLConstants.MESSAGE_LABEL_OUT_VALUE);
if (outMsgCtx != null) {
msgContext.setProperty(WSHandlerConstants.SEND_SIGV, outMsgCtx
.getProperty(WSHandlerConstants.SEND_SIGV));
} else {
throw new WSSecurityException(
"Cannot obtain request message context");
}
}
/*
* Get and check the Signature specific parameters first because they
* may be used for encryption too.
*/
doReceiverAction(doAction, reqData);
Vector wsResult = null;
try {
wsResult = secEngine.processSecurityHeader(doc, actor, cbHandler,
reqData.getSigCrypto(), reqData.getDecCrypto());
} catch (WSSecurityException ex) {
throw new AxisFault("WSDoAllReceiver: security processing failed",
ex);
}
if (wsResult == null) { // no security header found
if (doAction == WSConstants.NO_SECURITY) {
return;
} else {
throw new AxisFault(
"WSDoAllReceiver: Incoming message does not contain required Security header");
}
}
if (reqData.getWssConfig().isEnableSignatureConfirmation()
&& !msgContext.isServerSide()) {
checkSignatureConfirmation(reqData, wsResult);
}
/**
* Set the new SOAPEnvelope
*/
msgContext.setEnvelope(Axis2Util.getSOAPEnvelopeFromDOMDocument(doc, useDoom));
/*
* After setting the new current message, probably modified because of
* decryption, we need to locate the security header. That is, we force
* Axis (with getSOAPEnvelope()) to parse the string, build the new
* header. Then we examine, look up the security header and set the
* header as processed.
*
* Please note: find all header elements that contain the same actor
* that was given to processSecurityHeader(). Then check if there is a
* security header with this actor.
*/
SOAPHeader header = null;
try {
header = msgContext.getEnvelope().getHeader();
} catch (OMException ex) {
throw new AxisFault(
"WSDoAllReceiver: cannot get SOAP header after security processing",
ex);
}
Iterator headers = header.examineHeaderBlocks(actor);
SOAPHeaderBlock headerBlock = null;
while (headers.hasNext()) { // Find the wsse header
SOAPHeaderBlock hb = (SOAPHeaderBlock) headers.next();
if (hb.getLocalName().equals(WSConstants.WSSE_LN)
&& hb.getNamespace().getNamespaceURI().equals(WSConstants.WSSE_NS)) {
headerBlock = hb;
break;
}
}
headerBlock.setProcessed();
/*
* Now we can check the certificate used to sign the message. In the
* following implementation the certificate is only trusted if either it
* itself or the certificate of the issuer is installed in the keystore.
*
* Note: the method verifyTrust(X509Certificate) allows custom
* implementations with other validation algorithms for subclasses.
*/
// Extract the signature action result from the action vector
WSSecurityEngineResult actionResult = WSSecurityUtil.fetchActionResult(
wsResult, WSConstants.SIGN);
if (actionResult != null) {
X509Certificate returnCert = actionResult.getCertificate();
if (returnCert != null) {
if (!verifyTrust(returnCert, reqData)) {
throw new AxisFault(
"WSDoAllReceiver: The certificate used for the signature is not trusted");
}
}
}
/*
* Perform further checks on the timestamp that was transmitted in the
* header. In the following implementation the timestamp is valid if it
* was created after (now-ttl), where ttl is set on server side, not by
* the client.
*
* Note: the method verifyTimestamp(Timestamp) allows custom
* implementations with other validation algorithms for subclasses.
*/
// Extract the timestamp action result from the action vector
actionResult = WSSecurityUtil.fetchActionResult(wsResult,
WSConstants.TS);
if (actionResult != null) {
Timestamp timestamp = actionResult.getTimestamp();
if (timestamp != null) {
String ttl = null;
if ((ttl = (String) getOption(WSHandlerConstants.TTL_TIMESTAMP)) == null) {
ttl = (String) getProperty(msgContext,
WSHandlerConstants.TTL_TIMESTAMP);
}
int ttl_i = 0;
if (ttl != null) {
try {
ttl_i = Integer.parseInt(ttl);
} catch (NumberFormatException e) {
ttl_i = reqData.getTimeToLive();
}
}
if (ttl_i <= 0) {
ttl_i = reqData.getTimeToLive();
}
if (!verifyTimestamp(timestamp, ttl_i)) {
throw new AxisFault(
"WSDoAllReceiver: The timestamp could not be validated");
}
}
}
/*
* now check the security actions: do they match, in right order?
*/
if (!checkReceiverResults(wsResult, actions)) {
throw new AxisFault(
"WSDoAllReceiver: security processing failed (actions mismatch)");
}
/*
* All ok up to this point. Now construct and setup the security result
* structure. The service may fetch this and check it. Also the
* DoAllSender will use this in certain situations such as:
* USE_REQ_SIG_CERT to encrypt
*/
Vector results = null;
if ((results = (Vector) getProperty(msgContext,
WSHandlerConstants.RECV_RESULTS)) == null) {
results = new Vector();
msgContext.setProperty(WSHandlerConstants.RECV_RESULTS, results);
}
WSHandlerResult rResult = new WSHandlerResult(actor, wsResult);
results.add(0, rResult);
}
private void setAddressingInformationOnFault(MessageContext msgContext) {
SOAPEnvelope env = msgContext.getEnvelope();
SOAPHeader header = env.getHeader();
if (header != null) {
OMElement msgIdElem = header.getFirstChildWithName(new QName(
AddressingConstants.Final.WSA_NAMESPACE,
AddressingConstants.WSA_MESSAGE_ID));
if (msgIdElem == null) {
msgIdElem = header.getFirstChildWithName(new QName(
AddressingConstants.Submission.WSA_NAMESPACE,
AddressingConstants.WSA_MESSAGE_ID));
}
if (msgIdElem != null && msgIdElem.getText() != null) {
msgContext.getOptions().setMessageId(msgIdElem.getText());
}
}
}
}