package org.jboss.net.axis.security.handler;
import java.security.KeyStore;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.security.auth.x500.X500Principal;
import javax.security.auth.Subject;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPHeaderElement;
import org.apache.axis.AxisFault;
import org.apache.axis.Message;
import org.apache.axis.MessageContext;
import org.apache.log4j.Logger;
import org.apache.ws.axis.security.WSDoAllConstants;
import org.apache.ws.axis.security.WSDoAllReceiver;
import org.apache.ws.axis.security.WSDoAllReceiverResult;
import org.apache.ws.axis.security.util.AxisUtil;
import org.apache.ws.security.WSConstants;
import org.apache.ws.security.WSSecurityEngineResult;
import org.apache.ws.security.components.crypto.Crypto;
import org.jboss.net.axis.security.JBossCrypto;
import org.jboss.net.axis.security.JBossCryptoFactory;
import org.jboss.net.axis.security.SecurityConstants;
import org.jboss.security.SecurityAssociation;
import org.jboss.security.SecurityDomain;
import org.jboss.security.SimplePrincipal;
public class WSSRequestHandler extends WSDoAllReceiver
{
protected Logger log = Logger.getLogger(this.getClass());
JBossCrypto sigCrypto = null;
SecurityDomain domain = null;
public boolean canHandleBlock(QName arg0)
{
return SecurityConstants.SECURITY_HEADER_QNAME.equals(arg0);
}
public List getUnderstoodHeaders()
{
ArrayList understood = new ArrayList();
understood.add(SecurityConstants.SECURITY_HEADER_QNAME);
return understood;
}
public void invoke(MessageContext mc) throws AxisFault
{
if (log.isDebugEnabled())
log.debug("Enter: invoke(MessageContext)");
String action = (String) getOption(WSDoAllConstants.ACTION);
if (action == null)
action = (String) mc.getProperty(WSDoAllConstants.ACTION);
if (action == null)
throw new AxisFault("WSSRequestHandler: No action defined");
int doAction = AxisUtil.decodeAction(action, new Vector());
try
{
super.invoke(mc);
}
catch (AxisFault e)
{
log.fatal("Failed to handle security header", e);
throw e;
}
Message sm = mc.getCurrentMessage();
SOAPHeader sHeader = null;
try
{
sHeader = sm.getSOAPEnvelope().getHeader();
}
catch (Exception ex)
{
throw new AxisFault("WSRequestHandler: cannot get SOAP header", ex);
}
String actor = (String) getOption(WSDoAllConstants.ACTOR);
Iterator headers = sHeader.examineHeaderElements(actor);
SOAPHeaderElement headerElement = null;
while (headers.hasNext())
{
headerElement = (SOAPHeaderElement) headers.next();
if (headerElement.getLocalName().equals(WSConstants.WSSE_LN)
&& headerElement.getNamespaceURI().equals(WSConstants.WSSE_NS))
{
break;
}
}
if (headerElement != null)
((org.apache.axis.message.SOAPHeaderElementAxisImpl) headerElement).setProcessed(true);
if (((doAction & WSConstants.SIGN) == WSConstants.SIGN) || ((doAction & WSConstants.UT) == WSConstants.UT))
{
if (!"true".equals(getOption("skipAuthentication")))
authenticate(mc, actor);
}
if (log.isDebugEnabled())
{
log.debug("\n\tHeader Element: " + headerElement.getLocalName() + "\n\t\tisProcessed: "
+ ((org.apache.axis.message.SOAPHeaderElementAxisImpl) headerElement).isProcessed() + "\n\t\tmustUnderstand: "
+ ((org.apache.axis.message.SOAPHeaderElementAxisImpl) headerElement).getMustUnderstand());
log.debug("Exit: invoke(MessageContext)");
}
}
protected void authenticate(MessageContext mc, String actor) throws AxisFault
{
if (log.isDebugEnabled())
log.debug("Enter: authenticate(MessageContext)");
String alias = null;
X509Certificate[] certs = null;
SimplePrincipal sp = null;
Vector results = null;
if ((results = (Vector) mc.getProperty(WSDoAllConstants.RECV_RESULTS)) != null)
{
WSDoAllReceiverResult actorResult = null;
for (Iterator i = results.iterator(); i.hasNext();)
{
WSDoAllReceiverResult result = (WSDoAllReceiverResult) i.next();
if (result.getActor() == actor)
{
actorResult = result;
if (log.isDebugEnabled())
log.debug("Found results for actor: " + actor);
break;
}
}
X500Principal sigPrincipal = null;
X509Certificate credential = null;
Vector engineResults = actorResult.getResults();
for (Iterator iter = engineResults.iterator(); iter.hasNext();)
{
WSSecurityEngineResult result = (WSSecurityEngineResult) iter.next();
if (result.getAction() == WSConstants.SIGN)
{
credential = result.getCertificate();
sigPrincipal = credential.getSubjectX500Principal();
}
}
try
{
alias = sigCrypto.getAliasForX500Principal(sigPrincipal);
sp = new SimplePrincipal(alias);
}
catch (Exception e)
{
if (sigPrincipal == null)
log.warn("No Principal was found in the message.");
else
log.warn("Unable to determine alias for the principal: " + sigPrincipal.getName(), e);
}
if (log.isDebugEnabled())
log.debug("attempting to authenticate using " + alias + ":" + credential.getSubjectDN().getName());
Subject subject = new Subject();
if (!domain.isValid(new SimplePrincipal(alias), credential, subject))
{
throw new AxisFault("Server.Unauthenticated", org.apache.axis.utils.Messages.getMessage("cantAuth01", sp
.getName()), null, null);
}
else
{
mc.setProperty(MessageContext.AUTHUSER, subject);
Map signers = (Map) mc.getProperty(SecurityConstants.MC_REQ_SIGNERS);
if (signers == null)
signers = new HashMap(5);
signers.put(actor, alias);
mc.setProperty(SecurityConstants.MC_REQ_SIGNERS, signers);
}
}
if (log.isDebugEnabled())
log.debug("Exit: authenticate(MessageContext)");
}
protected Crypto loadSignatureCrypto() throws AxisFault
{
if (log.isDebugEnabled())
log.debug("Loading the Signature Crypto Class");
if (domain == null)
getSecurityDomain();
KeyStore truststore = domain.getTrustStore();
if (truststore == null)
throw new AxisFault("WSSReceiverHandler: No truststore available.");
String cryptoClass;
if ((cryptoClass = (String) getOption(SecurityConstants.HANDLER_CRYPTO_CLASS)) == null)
cryptoClass = "org.jboss.net.axis.security.JBoss14Crypto";
sigCrypto = JBossCryptoFactory.getInstance(cryptoClass, truststore);
return sigCrypto;
}
protected Crypto loadDecryptionCrypto() throws AxisFault
{
if (log.isDebugEnabled())
log.debug("Loading the Decryption Crypto Class");
if (domain == null)
getSecurityDomain();
KeyStore keystore = domain.getKeyStore();
if (keystore == null)
throw new AxisFault("WSSReceiverHandler: No keystore available.");
String cryptoClass;
if ((cryptoClass = (String) getOption(SecurityConstants.HANDLER_CRYPTO_CLASS)) == null)
cryptoClass = "org.jboss.net.axis.security.JBoss14Crypto";
return JBossCryptoFactory.getInstance(cryptoClass, keystore);
}
private void getSecurityDomain() throws AxisFault
{
String sd;
if ((sd = (String) getOption(SecurityConstants.HANDLER_SEC_DOMAIN)) == null)
sd = "java:/jaas/other";
if (log.isDebugEnabled())
log.debug("WSSReceiveHandler, securityDomain=" + sd);
try
{
Object tempDomain = new InitialContext().lookup(sd);
if (tempDomain != null && tempDomain instanceof SecurityDomain)
domain = (SecurityDomain) tempDomain;
else
{
log.fatal("The SecurityManager named " + sd + " is not a SecurityDomain");
throw new AxisFault("WSSReceiverHandler: No security domain is available.");
}
}
catch (NamingException e)
{
throw new AxisFault("Unable to find the securityDomain named: " + sd, e);
}
}
}