if ((action = (String) getOption(WSHandlerConstants.ACTION)) == null) {
action = (String) mc.getProperty(WSHandlerConstants.ACTION);
}
}
if (action == null) {
throw new JAXRPCException("WSS4JHandler: No action defined");
}
int doAction = WSSecurityUtil.decodeAction(action, actions);
String actor = (String) getOption(WSHandlerConstants.ACTOR);
SOAPMessage message = ((SOAPMessageContext)mc).getMessage();
SOAPPart sPart = message.getSOAPPart();
Document doc = null;
try {
doc = messageToDocument(message);
} catch (Exception ex) {
throw new JAXRPCException("WSS4JHandler: cannot convert into document",
ex);
}
/*
* Check if it's a fault. Don't process faults.
*
*/
SOAPConstants soapConstants =
WSSecurityUtil.getSOAPConstants(doc.getDocumentElement());
if (WSSecurityUtil
.findElement(doc.getDocumentElement(),
"Fault",
soapConstants.getEnvelopeURI())
!= null) {
return false;
}
/*
* 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);
}
/*
* 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) {
ex.printStackTrace();
throw new JAXRPCException("WSS4JHandler: security processing failed",
ex);
}
if (wsResult == null) { // no security header found
if (doAction == WSConstants.NO_SECURITY) {
return true;
} else {
throw new JAXRPCException("WSS4JHandler: Request does not contain required Security header");
}
}
if (reqData.getWssConfig().isEnableSignatureConfirmation() && !isRequest) {
checkSignatureConfirmation(reqData, wsResult);
}
/*
* If we had some security processing, get the original
* SOAP part of Axis' message and replace it with new SOAP
* part. This new part may contain decrypted elements.
*/
ByteArrayOutputStream os = new ByteArrayOutputStream();
XMLUtils.outputDOM(doc, os, true);
try {
sPart.setContent(new StreamSource(new ByteArrayInputStream(os.toByteArray())));
} catch (SOAPException se) {
throw new JAXRPCException("Couldn't set content on SOAPPart" + se.getMessage());
}
if (doDebug) {
log.debug("Processed received SOAP request");
}
/*
* 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 sHeader = null;
try {
sHeader = message.getSOAPPart().getEnvelope().getHeader();
} catch (Exception ex) {
throw new JAXRPCException("WSS4JHandler: cannot get SOAP header after security processing", ex);
}
Iterator headers = sHeader.examineHeaderElements(actor);
SOAPHeaderElement headerElement = null;
while (headers.hasNext()) {
SOAPHeaderElement hE = (SOAPHeaderElement) headers.next();
if (hE.getElementName().getLocalName().equals(WSConstants.WSSE_LN)
&& ((Node) hE).getNamespaceURI().equals(WSConstants.WSSE_NS)) {
headerElement = hE;
break;
}
}
/* JAXRPC conversion changes */
headerElement.setMustUnderstand(false); // is this sufficient?
/*
* 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 JAXRPCException("WSS4JHandler: 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 && reqData.getWssConfig().isTimeStampStrict()) {
if (!verifyTimestamp(timestamp, decodeTimeToLive(reqData))) {
throw new JAXRPCException("WSS4JHandler: The timestamp could not be validated");
}
}
}
/*
* now check the security actions: do they match, in right order?
*/
if (!checkReceiverResults(wsResult, actions)) {
throw new JAXRPCException("WSS4JHandler: security processing failed (actions mismatch)");
}
/*
* All ok up to this point. Now construct and setup the
* security result structure. The service may fetch this