blob: ba35ade4c77a99697ada0af5f19f17bd17cb16d7 [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.soap.SOAPEnvelope;
import org.apache.axiom.soap.SOAPFactory;
import org.apache.axiom.soap.SOAPHeader;
import org.apache.axis2.AxisFault;
import org.apache.axis2.Constants;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.context.OperationContext;
import org.apache.axis2.description.Parameter;
import org.apache.rampart.RampartException;
import org.apache.rampart.conversation.ConversationConfiguration;
import org.apache.rampart.conversation.STSRequester;
import org.apache.rampart.conversation.Util;
import org.apache.rampart.util.Axis2Util;
import org.apache.rampart.util.HandlerParameterDecoder;
import org.apache.rampart.util.MessageOptimizer;
import org.apache.rahas.Token;
import org.apache.rahas.TrustException;
import org.apache.rahas.TrustUtil;
import org.apache.axis2.wsdl.WSDLConstants;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ws.security.WSConstants;
import org.apache.ws.security.WSSecurityException;
import org.apache.ws.security.components.crypto.Crypto;
import org.apache.ws.security.handler.RequestData;
import org.apache.ws.security.handler.WSHandlerConstants;
import org.apache.ws.security.message.WSSecDKEncrypt;
import org.apache.ws.security.message.WSSecEncryptedKey;
import org.apache.ws.security.message.WSSecHeader;
import org.apache.ws.security.message.token.SecurityContextToken;
import org.apache.ws.security.util.WSSecurityUtil;
import org.apache.ws.security.util.XmlSchemaDateFormat;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import java.security.cert.X509Certificate;
import java.text.DateFormat;
import java.util.Date;
import java.util.Vector;
/**
* @deprecated
*/
public class WSDoAllSender extends WSDoAllHandler {
private static final Log log = LogFactory.getLog(WSDoAllSender.class);
public WSDoAllSender() {
super();
inHandler = false;
}
public void processMessage(MessageContext msgContext) throws AxisFault {
String useDoomValue = (String) getProperty(msgContext,
WSSHandlerConstants.USE_DOOM);
boolean useDoom = useDoomValue != null
&& Constants.VALUE_TRUE.equalsIgnoreCase(useDoomValue);
RequestData reqData = new RequestData();
try {
Parameter param = ConversationConfiguration.getParameter(msgContext);
if(param == null || WSSHandlerConstants.RST_ACTON_SCT.equals(msgContext.getWSAAction()) ||
WSSHandlerConstants.RSTR_ACTON_SCT.equals(msgContext.getWSAAction()) ||
WSSHandlerConstants.RSTR_ACTON_ISSUE.equals(msgContext.getWSAAction())) {
//If the msgs are msgs to an STS then use basic WS-Sec
processBasic(msgContext, useDoom, reqData);
} else {
processSecConv(msgContext);
}
} catch (Exception e) {
throw new AxisFault(e.getMessage(), e);
}
finally {
if(reqData != null) {
reqData.clear();
reqData = null;
}
}
}
/**
* Use WS-SecureConversation to secure the messages
* @param msgContext
* @throws Exception
*/
private void processSecConv(MessageContext msgContext) throws Exception {
//Parse the Conversation configuration
ConversationConfiguration config = ConversationConfiguration.load(msgContext, true);
if(config != null)
msgContext.setEnvelope((SOAPEnvelope) config.getDocument()
.getDocumentElement());
if(!config.getMsgCtx().isServerSide()) {
if(config.getContextIdentifier() == null && !config.getMsgCtx().isServerSide()) {
String sts = config.getStsEPRAddress();
if(sts != null) {
//Use a security token service
Axis2Util.useDOOM(false);
STSRequester.issueRequest(config);
Axis2Util.useDOOM(true);
} else {
//Create an an SCT, include it in an RSTR
// and add the RSTR to the header
this.createRSTR(config);
}
}
}
this.constructMessage(config);
}
/**
* This will carryout the WS-Security related operations.
*
* @param msgContext
* @param useDoom
* @throws WSSecurityException
* @throws AxisFault
*/
private void processBasic(MessageContext msgContext, boolean useDoom,
RequestData reqData) throws WSSecurityException, AxisFault {
boolean doDebug = log.isDebugEnabled();
try {
HandlerParameterDecoder.processParameters(msgContext,false);
} catch (Exception e) {
throw new AxisFault("Configureation error", e);
}
if (doDebug) {
log.debug("WSDoAllSender: enter invoke()");
}
/*
* Copy the RECV_RESULTS over to the current message context
* - IF available
*/
OperationContext opCtx = msgContext.getOperationContext();
MessageContext inMsgCtx;
if(opCtx != null &&
(inMsgCtx = opCtx.getMessageContext(WSDLConstants.MESSAGE_LABEL_IN_VALUE)) != null) {
msgContext.setProperty(WSHandlerConstants.RECV_RESULTS,
inMsgCtx.getProperty(WSHandlerConstants.RECV_RESULTS));
}
reqData.setNoSerialization(false);
reqData.setMsgContext(msgContext);
if (((getOption(WSSHandlerConstants.OUTFLOW_SECURITY)) == null) &&
((getProperty(msgContext, WSSHandlerConstants.OUTFLOW_SECURITY)) == null)) {
if (msgContext.isServerSide() &&
((getOption(WSSHandlerConstants.OUTFLOW_SECURITY_SERVER)) == null) &&
((getProperty(msgContext, WSSHandlerConstants.OUTFLOW_SECURITY_SERVER)) == null)) {
return;
} else if (((getOption(WSSHandlerConstants.OUTFLOW_SECURITY_CLIENT)) == null) &&
((getProperty(msgContext, WSSHandlerConstants.OUTFLOW_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;
}
/*
* For every action we need a username, so get this now. The
* username defined in the deployment descriptor takes precedence.
*/
reqData.setUsername((String) getOption(WSHandlerConstants.USER));
if (reqData.getUsername() == null || reqData.getUsername().length() == 0) {
String username = (String) getProperty(reqData.getMsgContext(), WSHandlerConstants.USER);
if (username != null) {
reqData.setUsername(username);
}
}
/*
* Now we perform some set-up for UsernameToken and Signature
* functions. No need to do it for encryption only. Check if
* username is available and then get a passowrd.
*/
if ((doAction & (WSConstants.SIGN | WSConstants.UT | WSConstants.UT_SIGN)) != 0) {
/*
* We need a username - if none throw an AxisFault. For
* encryption there is a specific parameter to get a username.
*/
if (reqData.getUsername() == null
|| reqData.getUsername().length() == 0) {
throw new AxisFault(
"WSDoAllSender: Empty username for specified action");
}
}
/*
* Now get the SOAPEvelope from the message context and convert it
* into a Document
*
* Now we can perform our security operations on this request.
*/
Document doc = null;
/*
* If the message context property conatins a document then this is
* a chained handler.
*/
if ((doc = (Document) ((MessageContext)reqData.getMsgContext())
.getProperty(WSHandlerConstants.SND_SECURITY)) == null) {
try {
doc = Axis2Util.getDocumentFromSOAPEnvelope(msgContext.getEnvelope(), useDoom);
} catch (WSSecurityException wssEx) {
throw new AxisFault("WSDoAllReceiver: Error in converting to Document", wssEx);
}
}
doSenderAction(doAction, doc, reqData, actions, !msgContext.isServerSide());
/*
* If noSerialization is false, this handler shall be the last (or
* only) one in a handler chain. If noSerialization is true, just
* set the processed Document in the transfer property. The next
* Axis WSS4J handler takes it and performs additional security
* processing steps.
*
*/
if (reqData.isNoSerialization()) {
((MessageContext)reqData.getMsgContext()).setProperty(WSHandlerConstants.SND_SECURITY,
doc);
} else {
if(useDoom) {
msgContext.setEnvelope((SOAPEnvelope)doc.getDocumentElement());
} else {
msgContext.setEnvelope(Axis2Util.getSOAPEnvelopeFromDOMDocument(doc, useDoom));
}
((MessageContext)reqData.getMsgContext()).setProperty(WSHandlerConstants.SND_SECURITY, null);
}
/**
* If the optimizeParts parts are set then optimize them
*/
String optimizeParts;
if((optimizeParts = (String) getOption(WSSHandlerConstants.OPTIMIZE_PARTS)) == null) {
optimizeParts = (String)
getProperty(reqData.getMsgContext(), WSSHandlerConstants.OPTIMIZE_PARTS);
}
if(optimizeParts != null) {
// Optimize the Envelope
MessageOptimizer.optimize(msgContext.getEnvelope(),optimizeParts);
}
//Enable handler repetition
Integer repeat;
int repeatCount;
if ((repeat = (Integer)getOption(WSSHandlerConstants.SENDER_REPEAT_COUNT)) == null) {
repeat = (Integer)
getProperty(reqData.getMsgContext(), WSSHandlerConstants.SENDER_REPEAT_COUNT);
}
repeatCount = repeat.intValue();
//Get the current repetition from message context
int repetition = this.getCurrentRepetition(msgContext);
if(repeatCount > 0 && repetition < repeatCount) {
reqData.clear();
reqData = null;
// Increment the repetition to indicate the next repetition
// of the same handler
repetition++;
msgContext.setProperty(WSSHandlerConstants.CURRENT_REPETITON,
new Integer(repetition));
this.invoke(msgContext);
}
if (doDebug) {
log.debug("WSDoAllSender: exit invoke()");
}
}
/**
* Create the self created <code>wsc:SecurityContextToken</code> and
* add it to a <code>wst:RequestSecurityTokenResponse</code>.
*
* This is called in the case where the security context establishment
* is done by one of the parties with out the use of an STS
* and the creted SCT is sent across to the other party in an unsolicited
* <code>wst:RequestSecurityTokenResponse</code>
*
* @param config
* @throws Exception
*/
private void createRSTR(ConversationConfiguration config) throws Exception {
WSSecEncryptedKey encrKeyBuilder = new WSSecEncryptedKey();
Crypto crypto = org.apache.rampart.conversation.Util.getCryptoInstace(config);
String encryptionUser = config.getEncryptionUser();
if(encryptionUser == null) {
throw new RampartException("missingEncryptionUser");
}
X509Certificate cert = crypto.getCertificates(encryptionUser)[0];
encrKeyBuilder.setKeyIdentifierType(WSConstants.THUMBPRINT_IDENTIFIER);
try {
encrKeyBuilder.setUseThisCert(cert);
encrKeyBuilder.prepare(config.getDocument(), crypto);
} catch (WSSecurityException e) {
throw new TrustException(
"errorInBuildingTheEncryptedKeyForPrincipal",
new String[] { cert.getSubjectDN().getName()}, e);
}
SecurityContextToken sct = new SecurityContextToken(config.getDocument());
Util.resgisterContext(sct.getIdentifier(), config);
//Creation and expiration times
Date creationTime = new Date();
Date expirationTime = new Date();
expirationTime.setTime(creationTime.getTime() + 300000);
Token token = new Token(sct.getIdentifier(), (OMElement)sct.getElement(), creationTime, expirationTime);
token.setSecret(encrKeyBuilder.getEphemeralKey());
config.getTokenStore().add(token);
SOAPEnvelope env = config.getMsgCtx().getEnvelope();
SOAPHeader header = env.getHeader();
if(header == null) {
header = ((SOAPFactory)env.getOMFactory()).createSOAPHeader(env);
}
OMElement rstrElem = TrustUtil.createRequestSecurityTokenResponseElement(config.getWstVersion(), header);
OMElement rstElem = TrustUtil.createRequestedSecurityTokenElement(config.getWstVersion(), rstrElem);
// Use GMT time in milliseconds
DateFormat zulu = new XmlSchemaDateFormat();
// Add the Lifetime element
TrustUtil.createLifetimeElement(config.getWstVersion(), rstrElem, zulu
.format(creationTime), zulu.format(expirationTime));
rstElem.addChild((OMElement)sct.getElement());
TrustUtil.createRequestedAttachedRef(config.getWstVersion(), rstrElem,
"#" + sct.getID(), WSSHandlerConstants.TOK_TYPE_SCT);
TrustUtil
.createRequestedUnattachedRef(config.getWstVersion(), rstrElem,
sct.getIdentifier(), WSSHandlerConstants.TOK_TYPE_SCT);
Element encryptedKeyElem = encrKeyBuilder.getEncryptedKeyElement();
Element bstElem = encrKeyBuilder.getBinarySecurityTokenElement();
OMElement reqProofTok = TrustUtil.createRequestedProofTokenElement(
config.getWstVersion(), rstrElem);
if(bstElem != null) {
reqProofTok.addChild((OMElement)bstElem);
}
reqProofTok.addChild((OMElement)encryptedKeyElem);
}
private void constructMessage(ConversationConfiguration config) throws Exception {
Document doc = config.getDocument();
WSSecHeader secHeader = new WSSecHeader();
secHeader.insertSecurityHeader(doc);
Token tempToken = config.getTokenStore().getToken(
config.getContextIdentifier());
byte[] tempSecret = tempToken.getSecret();
SecurityContextToken sct = new SecurityContextToken((Element) doc
.importNode((Element) tempToken.getToken(), true));
// Derived key encryption
WSSecDKEncrypt encrBuilder = new WSSecDKEncrypt();
encrBuilder.setSymmetricEncAlgorithm(WSConstants.AES_128);
OMElement attachedReference = tempToken.getAttachedReference();
if(attachedReference != null) {
encrBuilder.setExternalKey(tempSecret, (Element) doc.importNode(
(Element) attachedReference, true));
} else {
String tokenId = sct.getID();
encrBuilder.setExternalKey(tempSecret, tokenId);
}
encrBuilder.build(doc, secHeader);
WSSecurityUtil.prependChildElement(doc, secHeader.getSecurityHeader(),
sct.getElement(), false);
}
}