SOAPMessage doc = getSOAPMessage(msg);
boolean doDebug = LOG.isLoggable(Level.FINE);
boolean doTimeLog = TIME_LOG.isLoggable(Level.FINE);
SoapVersion version = msg.getVersion();
if (doDebug) {
LOG.fine("WSS4JInInterceptor: enter handleMessage()");
}
long t0 = 0;
long t1 = 0;
long t2 = 0;
long t3 = 0;
if (doTimeLog) {
t0 = System.currentTimeMillis();
}
RequestData reqData = new RequestData();
/*
* The overall try, just to have a finally at the end to perform some
* housekeeping.
*/
try {
reqData.setMsgContext(msg);
computeAction(msg, reqData);
Vector actions = new Vector();
String action = getAction(msg, version);
int doAction = WSSecurityUtil.decodeAction(action, actions);
String actor = (String)getOption(WSHandlerConstants.ACTOR);
CallbackHandler cbHandler = getCallback(reqData, doAction);
/*
* Get and check the Signature specific parameters first because
* they may be used for encryption too.
*/
doReceiverAction(doAction, reqData);
Vector wsResult = null;
if (doTimeLog) {
t1 = System.currentTimeMillis();
}
wsResult = getSecurityEngine().processSecurityHeader(
doc.getSOAPPart(),
actor,
cbHandler,
reqData.getSigCrypto(),
reqData.getDecCrypto()
);
if (doTimeLog) {
t2 = System.currentTimeMillis();
}
if (wsResult == null) { // no security header found
if (doAction == WSConstants.NO_SECURITY) {
return;
} else if (doc.getSOAPPart().getEnvelope().getBody().hasFault()) {
LOG.warning("Request does not contain required Security header, "
+ "but it's a fault.");
return;
} else {
LOG.warning("Request does not contain required Security header");
throw new WSSecurityException(WSSecurityException.INVALID_SECURITY);
}
}
if (reqData.getWssConfig().isEnableSignatureConfirmation()) {
checkSignatureConfirmation(reqData, wsResult);
}
/*
* 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
Vector signatureResults = new Vector();
signatureResults =
WSSecurityUtil.fetchAllActionResults(wsResult, WSConstants.SIGN, signatureResults);
if (!signatureResults.isEmpty()) {
for (int i = 0; i < signatureResults.size(); i++) {
WSSecurityEngineResult result =
(WSSecurityEngineResult) signatureResults.get(i);
X509Certificate returnCert = (X509Certificate)result
.get(WSSecurityEngineResult.TAG_X509_CERTIFICATE);
if (returnCert != null && !verifyTrust(returnCert, reqData)) {
LOG.warning("The certificate used for the signature is not trusted");
throw new WSSecurityException(WSSecurityException.FAILED_CHECK);
}
msg.put(SIGNATURE_RESULT, result);
}
}
/*
* 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
Vector timestampResults = new Vector();
timestampResults =
WSSecurityUtil.fetchAllActionResults(wsResult, WSConstants.TS, timestampResults);
if (!timestampResults.isEmpty()) {
for (int i = 0; i < timestampResults.size(); i++) {
WSSecurityEngineResult result =
(WSSecurityEngineResult) timestampResults.get(i);
Timestamp timestamp = (Timestamp)result.get(WSSecurityEngineResult.TAG_TIMESTAMP);
if (timestamp != null && !verifyTimestamp(timestamp, decodeTimeToLive(reqData))) {
LOG.warning("The timestamp could not be validated");
throw new WSSecurityException(WSSecurityException.MESSAGE_EXPIRED);
}
msg.put(TIMESTAMP_RESULT, result);
}
}
/*
* now check the security actions: do they match, in any order?
*/
if (!ignoreActions && !checkReceiverResultsAnyOrder(wsResult, actions)) {
LOG.warning("Security processing failed (actions mismatch)");
throw new WSSecurityException(WSSecurityException.INVALID_SECURITY);
}
doResults(msg, actor, doc, wsResult);
if (doTimeLog) {
t3 = System.currentTimeMillis();
TIME_LOG.fine("Receive request: total= " + (t3 - t0)
+ " request preparation= " + (t1 - t0)
+ " request processing= " + (t2 - t1)
+ " header, cert verify, timestamp= " + (t3 - t2) + "\n");
}
if (doDebug) {
LOG.fine("WSS4JInInterceptor: exit handleMessage()");
}
} catch (WSSecurityException e) {
LOG.log(Level.WARNING, "", e);
SoapFault fault = createSoapFault(version, e);
throw fault;
} catch (XMLStreamException e) {
throw new SoapFault(new Message("STAX_EX", LOG), e, version.getSender());
} catch (SOAPException e) {
throw new SoapFault(new Message("SAAJ_EX", LOG), e, version.getSender());
} finally {
reqData.clear();
reqData = null;
}
}