/* * Copyright 2005-2014 the original author or authors. * * 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.springframework.ws.soap.security.wss4j; import java.io.IOException; import java.security.Principal; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.List; import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.UnsupportedCallbackException; import org.apache.ws.security.WSConstants; import org.apache.ws.security.WSSConfig; import org.apache.ws.security.WSSecurityEngine; import org.apache.ws.security.WSSecurityEngineResult; import org.apache.ws.security.WSSecurityException; import org.apache.ws.security.WSUsernameTokenPrincipal; 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.handler.WSHandlerResult; import org.apache.ws.security.message.token.Timestamp; import org.apache.ws.security.saml.SAMLIssuer; import org.apache.ws.security.util.WSSecurityUtil; import org.apache.ws.security.validate.Credential; import org.apache.ws.security.validate.SignatureTrustValidator; import org.apache.ws.security.validate.TimestampValidator; import org.w3c.dom.Document; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import org.springframework.ws.context.MessageContext; import org.springframework.ws.soap.SoapMessage; import org.springframework.ws.soap.security.AbstractWsSecurityInterceptor; import org.springframework.ws.soap.security.WsSecuritySecurementException; import org.springframework.ws.soap.security.WsSecurityValidationException; import org.springframework.ws.soap.security.callback.CallbackHandlerChain; import org.springframework.ws.soap.security.callback.CleanupCallback; import org.springframework.ws.soap.security.wss4j.callback.UsernameTokenPrincipalCallback; /** * A WS-Security endpoint interceptor based on Apache's WSS4J. This interceptor supports messages created by the {@link * org.springframework.ws.soap.axiom.AxiomSoapMessageFactory} and the {@link org.springframework.ws.soap.saaj.SaajSoapMessageFactory}. * * <p>The validation and securement actions executed by this interceptor are configured via {@code validationActions} * and {@code securementActions} properties, respectively. Actions should be passed as a space-separated strings. * * <p>Valid <strong>validation</strong> actions are: * * <blockquote> * <table> * <tr><th>Validation action</th><th>Description</th></tr> * <tr><td>{@code UsernameToken}</td><td>Validates username token</td></tr> * <tr><td>{@code Timestamp}</td><td>Validates the timestamp</td></tr> * <tr><td>{@code Encrypt}</td><td>Decrypts the message</td></tr> * <tr><td>{@code Signature}</td><td>Validates the signature</td></tr> * <tr><td>{@code NoSecurity}</td><td>No action performed</td></tr> * </table></blockquote> * <p> * <strong>Securement</strong> actions are: * * <blockquote> * <table> * <tr><th>Securement action</th><th>Description</th></tr> * <tr><td>{@code UsernameToken}</td><td>Adds a username token</td></tr> * <tr><td>{@code UsernameTokenSignature}</td><td>Adds a username token and a signature username token secret key</td></tr> * <tr><td>{@code Timestamp}</td><td>Adds a timestamp</td></tr> * <tr><td>{@code Encrypt}</td><td>Encrypts the response</td></tr> * <tr><td>{@code Signature}</td><td>Signs the response</td></tr> * <tr><td>{@code NoSecurity}</td><td>No action performed</td></tr> * </table></blockquote> * * <p>The order of the actions that the client performed to secure the messages is significant and is enforced by the * interceptor. * * @author Tareq Abed Rabbo * @author Arjen Poutsma * @author Greg Turnquist * @see <a href="http://ws.apache.org/wss4j/">Apache WSS4J</a> * @since 1.5.0 * @deprecated Transition to {@link org.springframework.ws.soap.security.wss4j2.Wss4jSecurityInterceptor} */ @Deprecated public class Wss4jSecurityInterceptor extends AbstractWsSecurityInterceptor implements InitializingBean { public static final String SECUREMENT_USER_PROPERTY_NAME = "Wss4jSecurityInterceptor.securementUser"; private static final String SAML_ISSUER_PROPERTY_NAME = "Wss4jSecurityInterceptor.samlIssuer"; private int securementAction; private String securementActions; private List<Integer> securementActionsVector; private String securementUsername; private CallbackHandler validationCallbackHandler; private int validationAction; private String validationActions; private List<Integer> validationActionsVector; private String validationActor; private Crypto validationDecryptionCrypto; private Crypto validationSignatureCrypto; private boolean timestampStrict = true; private boolean enableSignatureConfirmation; private int validationTimeToLive = 300; private int securementTimeToLive = 300; private int futureTimeToLive = 60; private SAMLIssuer samlIssuer; private WSSConfig wssConfig; private final Wss4jHandler handler = new Wss4jHandler(); private final WSSecurityEngine securityEngine = new WSSecurityEngine(); private boolean enableRevocation; private boolean bspCompliant; private boolean securementUseDerivedKey; // To maintain same behavior as default, this flag is set to true private boolean removeSecurityHeader = true; public void setSecurementActions(String securementActions) { this.securementActions = securementActions; securementActionsVector = new ArrayList<Integer>(); try { securementAction = WSSecurityUtil.decodeAction(securementActions, securementActionsVector); } catch (WSSecurityException ex) { throw new IllegalArgumentException(ex); } } /** * The actor name of the {@code wsse:Security} header. * * <p>If this parameter is omitted, the actor name is not set. * * <p>The value of the actor or role has to match the receiver's setting or may contain standard values. */ public void setSecurementActor(String securementActor) { handler.setOption(WSHandlerConstants.ACTOR, securementActor); } public void setSecurementEncryptionCrypto(Crypto securementEncryptionCrypto) { handler.setSecurementEncryptionCrypto(securementEncryptionCrypto); } /** Sets the key name that needs to be sent for encryption. */ public void setSecurementEncryptionEmbeddedKeyName(String securementEncryptionEmbeddedKeyName) { handler.setOption(WSHandlerConstants.ENC_KEY_NAME, securementEncryptionEmbeddedKeyName); } /** * Defines which key identifier type to use. The WS-Security specifications recommends to use the identifier type * {@code IssuerSerial}. For possible encryption key identifier types refer to {@link * org.apache.ws.security.handler.WSHandlerConstants#keyIdentifier}. For encryption {@code IssuerSerial}, * {@code X509KeyIdentifier}, {@code DirectReference}, {@code Thumbprint}, * {@code SKIKeyIdentifier}, and {@code EmbeddedKeyName} are valid only. */ public void setSecurementEncryptionKeyIdentifier(String securementEncryptionKeyIdentifier) { handler.setOption(WSHandlerConstants.ENC_KEY_ID, securementEncryptionKeyIdentifier); } /** * Defines which algorithm to use to encrypt the generated symmetric key. Currently WSS4J supports {@link * WSConstants#KEYTRANSPORT_RSA15} and {@link WSConstants#KEYTRANSPORT_RSAOEP}. */ public void setSecurementEncryptionKeyTransportAlgorithm(String securementEncryptionKeyTransportAlgorithm) { handler.setOption(WSHandlerConstants.ENC_KEY_TRANSPORT, securementEncryptionKeyTransportAlgorithm); } /** * Property to define which parts of the request shall be encrypted. * * <p>The value of this property is a list of semicolon separated element names that identify the elements to encrypt. * An encryption mode specifier and a namespace identification, each inside a pair of curly brackets, may precede * each element name. * * <p>The encryption mode specifier is either {@code {Content}} or {@code {Element}}. Please refer to the W3C * XML Encryption specification about the differences between Element and Content encryption. The encryption mode * defaults to {@code Content} if it is omitted. Example of a list: * <pre> * <property name="securementEncryptionParts" * value="{Content}{http://example.org/paymentv2}CreditCard; * {Element}{}UserName" /> * </pre> * The first entry of the list identifies the element {@code CreditCard} in the namespace * {@code http://example.org/paymentv2}, and will encrypt its content. Be aware that the element name, the * namespace identifier, and the encryption modifier are case sensitive. * * <p>The encryption modifier and the namespace identifier can be omitted. In this case the encryption mode defaults to * {@code Content} and the namespace is set to the SOAP namespace. * * <p>An empty encryption mode defaults to {@code Content}, an empty namespace identifier defaults to the SOAP * namespace. The second line of the example defines {@code Element} as encryption mode for an * {@code UserName} element in the SOAP namespace. * * <p>To specify an element without a namespace use the string {@code Null} as the namespace name (this is a case * sensitive string) * * <p>If no list is specified, the handler encrypts the SOAP Body in {@code Content} mode by default. */ public void setSecurementEncryptionParts(String securementEncryptionParts) { handler.setOption(WSHandlerConstants.ENCRYPTION_PARTS, securementEncryptionParts); } /** * Defines which symmetric encryption algorithm to use. WSS4J supports the following alorithms: {@link * WSConstants#TRIPLE_DES}, {@link WSConstants#AES_128}, {@link WSConstants#AES_256}, and {@link * WSConstants#AES_192}. Except for AES 192 all of these algorithms are required by the XML Encryption * specification. */ public void setSecurementEncryptionSymAlgorithm(String securementEncryptionSymAlgorithm) { this.handler.setOption(WSHandlerConstants.ENC_SYM_ALGO, securementEncryptionSymAlgorithm); } /** * The user's name for encryption. * * <p>The encryption functions uses the public key of this user's certificate to encrypt the generated symmetric key. * * <p>If this parameter is not set, then the encryption function falls back to the {@link * org.apache.ws.security.handler.WSHandlerConstants#USER} parameter to get the certificate. * * <p>If <b>only</b> encryption of the SOAP body data is requested, it is recommended to use this parameter to define * the username. The application can then use the standard user and password functions (see example at {@link * org.apache.ws.security.handler.WSHandlerConstants#USER} to enable HTTP authentication functions. * * <p>Encryption only does not authenticate a user / sender, therefore it does not need a password. * * <p>Placing the username of the encryption certificate in the configuration file is not a security risk, because the * public key of that certificate is used only. */ public void setSecurementEncryptionUser(String securementEncryptionUser) { handler.setOption(WSHandlerConstants.ENCRYPTION_USER, securementEncryptionUser); } public void setSecurementPassword(String securementPassword) { this.handler.setSecurementPassword(securementPassword); } /** * Specific parameter for UsernameToken action to define the encoding of the passowrd. * * <p>The parameter can be set to either {@link WSConstants#PW_DIGEST} or to {@link WSConstants#PW_TEXT}. * * <p>The default setting is PW_DIGEST. */ public void setSecurementPasswordType(String securementUsernameTokenPasswordType) { handler.setOption(WSHandlerConstants.PASSWORD_TYPE, securementUsernameTokenPasswordType); } /** * Defines which signature algorithm to use. * @see WSConstants#RSA * @see WSConstants#DSA */ public void setSecurementSignatureAlgorithm(String securementSignatureAlgorithm) { handler.setOption(WSHandlerConstants.SIG_ALGO, securementSignatureAlgorithm); } /** * Defines which signature digest algorithm to use. */ public void setSecurementSignatureDigestAlgorithm(String digestAlgorithm) { handler.setOption(WSHandlerConstants.SIG_DIGEST_ALGO, digestAlgorithm); } public void setSecurementSignatureCrypto(Crypto securementSignatureCrypto) { handler.setSecurementSignatureCrypto(securementSignatureCrypto); } /** * Defines which key identifier type to use. The WS-Security specifications recommends to use the identifier type * {@code IssuerSerial}. For possible signature key identifier types refer to {@link * org.apache.ws.security.handler.WSHandlerConstants#keyIdentifier}. For signature {@code IssuerSerial} and * {@code DirectReference} are valid only. */ public void setSecurementSignatureKeyIdentifier(String securementSignatureKeyIdentifier) { handler.setOption(WSHandlerConstants.SIG_KEY_ID, securementSignatureKeyIdentifier); } /** * Property to define which parts of the request shall be signed. * * <p>Refer to {@link #setSecurementEncryptionParts(String)} for a detailed description of the format of the value * string. * * <p>If this property is not specified the handler signs the SOAP Body by default. * * <p>The WS Security specifications define several formats to transfer the signature tokens (certificates) or * references to these tokens. Thus, the plain element name {@code Token} signs the token and takes care of the * different formats. * * <p>To sign the SOAP body <b>and</b> the signature token the value of this parameter must contain: * <pre> * <property name="securementSignatureParts" * value="{}{http://schemas.xmlsoap.org/soap/envelope/}Body; Token" /> * </pre> * To specify an element without a namespace use the string {@code Null} as the namespace name (this is a case * sensitive string) * * <p>If there is no other element in the request with a local name of {@code Body} then the SOAP namespace * identifier can be empty ({@code {}}). */ public void setSecurementSignatureParts(String securementSignatureParts) { handler.setOption(WSHandlerConstants.SIGNATURE_PARTS, securementSignatureParts); } /** * The user's name for signature. * * <p>This name is used as the alias name in the keystore to get user's * certificate and private key to perform signing. * * <p>If this parameter is not set, then the signature * function falls back to the alias specified by {@link #setSecurementUsername(String)}. * */ public void setSecurementSignatureUser(String securementSignatureUser) { handler.setOption(WSHandlerConstants.SIGNATURE_USER, securementSignatureUser); } /** Sets the username for securement username token or/and the alias of the private key for securement signature */ public void setSecurementUsername(String securementUsername) { this.securementUsername = securementUsername; } /** Sets the time to live on the outgoing message */ public void setSecurementTimeToLive(int securementTimeToLive) { if (securementTimeToLive <= 0) { throw new IllegalArgumentException("timeToLive must be positive"); } this.securementTimeToLive = securementTimeToLive; } /** * Enables the derivation of keys as per the UsernameTokenProfile 1.1 spec. Default is {@code true}. */ public void setSecurementUseDerivedKey(boolean securementUseDerivedKey) { this.securementUseDerivedKey = securementUseDerivedKey; } /** Sets the server-side time to live */ public void setValidationTimeToLive(int validationTimeToLive) { if (validationTimeToLive <= 0) { throw new IllegalArgumentException("timeToLive must be positive"); } this.validationTimeToLive = validationTimeToLive; } /** Sets the validation actions to be executed by the interceptor. */ public void setValidationActions(String actions) { this.validationActions = actions; try { validationActionsVector = new ArrayList<Integer>(); validationAction = WSSecurityUtil.decodeAction(actions, validationActionsVector); } catch (WSSecurityException ex) { throw new IllegalArgumentException(ex); } } public void setValidationActor(String validationActor) { this.validationActor = validationActor; } /** * Sets the {@link org.apache.ws.security.WSPasswordCallback} handler to use when validating messages. * * @see #setValidationCallbackHandlers(CallbackHandler[]) */ public void setValidationCallbackHandler(CallbackHandler callbackHandler) { this.validationCallbackHandler = callbackHandler; } /** * Sets the {@link org.apache.ws.security.WSPasswordCallback} handlers to use when validating messages. * * @see #setValidationCallbackHandler(CallbackHandler) */ public void setValidationCallbackHandlers(CallbackHandler[] callbackHandler) { this.validationCallbackHandler = new CallbackHandlerChain(callbackHandler); } /** Sets the Crypto to use to decrypt incoming messages */ public void setValidationDecryptionCrypto(Crypto decryptionCrypto) { this.validationDecryptionCrypto = decryptionCrypto; } /** Sets the Crypto to use to verify the signature of incoming messages */ public void setValidationSignatureCrypto(Crypto signatureCrypto) { this.validationSignatureCrypto = signatureCrypto; } /** Whether to enable signatureConfirmation or not. By default signatureConfirmation is enabled */ public void setEnableSignatureConfirmation(boolean enableSignatureConfirmation) { handler.setOption(WSHandlerConstants.ENABLE_SIGNATURE_CONFIRMATION, enableSignatureConfirmation); this.enableSignatureConfirmation = enableSignatureConfirmation; } /** Sets if the generated timestamp header's precision is in milliseconds. */ public void setTimestampPrecisionInMilliseconds(boolean timestampPrecisionInMilliseconds) { handler.setOption(WSHandlerConstants.TIMESTAMP_PRECISION, timestampPrecisionInMilliseconds); } /** Sets whether or not timestamp verification is done with the server-side time to live */ public void setTimestampStrict(boolean timestampStrict) { this.timestampStrict = timestampStrict; } /** * Enables the {@code mustUnderstand} attribute on WS-Security headers on outgoing messages. Default is * {@code true}. */ public void setSecurementMustUnderstand(boolean securementMustUnderstand) { handler.setOption(WSHandlerConstants.MUST_UNDERSTAND, securementMustUnderstand); } /** * Sets the additional elements in {@code UsernameToken}s. * * <p>The value of this parameter is a list of element names that are added to the UsernameToken. The names of the list * a separated by spaces. * * <p>The list may contain the names {@code Nonce} and {@code Created} only (case sensitive). Use this option * if the password type is {@code passwordText} and the handler shall add the {@code Nonce} and/or * {@code Created} elements. */ public void setSecurementUsernameTokenElements(String securementUsernameTokenElements) { handler.setOption(WSHandlerConstants.ADD_UT_ELEMENTS, securementUsernameTokenElements); } /** * Sets the web service specification settings. * <p> * The default settings follow the latest OASIS and changing anything might violate the OASIS specs. * * @param config web service security configuration or {@code null} to use default settings */ public void setWssConfig(WSSConfig config) { securityEngine.setWssConfig(config); wssConfig = config; } /** * Set whether to enable CRL checking or not when verifying trust in a certificate. */ public void setEnableRevocation(boolean enableRevocation) { this.enableRevocation = enableRevocation; } /** * Set the WS-I Basic Security Profile compliance mode. Default is {@code true}. */ public void setBspCompliant(boolean bspCompliant) { this.handler.setOption(WSHandlerConstants.IS_BSP_COMPLIANT, bspCompliant); this.bspCompliant = bspCompliant; } /** * Sets the location of the SAML properties file. The file should be available on the classpath. */ public void setSamlProperties(String location) { handler.setOption(WSHandlerConstants.SAML_PROP_FILE, location); } /** * Sets the time in seconds in the future within which the Created time of an * incoming Timestamp is valid. The default is 60 seconds. */ public void setFutureTimeToLive(int futureTimeToLive) { if (futureTimeToLive <= 0) { throw new IllegalArgumentException("futureTimeToLive must be positive"); } this.futureTimeToLive = futureTimeToLive; } /** * Sets the SAML issuer. */ public void setSamlIssuer(SAMLIssuer samlIssuer) { handler.setOption(WSHandlerConstants.SAML_PROP_REF_ID, SAML_ISSUER_PROPERTY_NAME); this.samlIssuer = samlIssuer; } public boolean getRemoveSecurityHeader() { return removeSecurityHeader; } public void setRemoveSecurityHeader(boolean removeSecurityHeader) { this.removeSecurityHeader = removeSecurityHeader; } @Override public void afterPropertiesSet() throws Exception { Assert.isTrue(validationActions != null || securementActions != null, "validationActions or securementActions are required"); if (validationActions != null) { if ((validationAction & WSConstants.UT) != 0) { Assert.notNull(validationCallbackHandler, "validationCallbackHandler is required"); } if ((validationAction & WSConstants.SIGN) != 0) { Assert.notNull(validationSignatureCrypto, "validationSignatureCrypto is required"); } } // securement actions are not to be validated at start up as they could // be configured dynamically via the message context // allow for qualified password types for .Net interoperability securityEngine.getWssConfig().setAllowNamespaceQualifiedPasswordTypes(true); securityEngine.getWssConfig().setWsiBSPCompliant(bspCompliant); } @Override protected void secureMessage(SoapMessage soapMessage, MessageContext messageContext) throws WsSecuritySecurementException { if (securementAction == WSConstants.NO_SECURITY && !enableSignatureConfirmation) { return; } if (logger.isDebugEnabled()) { logger.debug("Securing message [" + soapMessage + "] with actions [" + securementActions + "]"); } RequestData requestData = initializeRequestData(messageContext); Document envelopeAsDocument = soapMessage.getDocument(); try { // In case on signature confirmation with no other securement // action, we need to pass an empty securementActionsVector to avoid // NPE if (securementAction == WSConstants.NO_SECURITY) { securementActionsVector = new ArrayList<Integer>(0); } handler.doSenderAction(securementAction, envelopeAsDocument, requestData, securementActionsVector, false); } catch (WSSecurityException ex) { throw new Wss4jSecuritySecurementException(ex.getMessage(), ex); } soapMessage.setDocument(envelopeAsDocument); } /** * Creates and initializes a request data for the given message context. * * @param messageContext the message context * @return the request data */ protected RequestData initializeRequestData(MessageContext messageContext) { RequestData requestData = new RequestData(); requestData.setMsgContext(messageContext); // reads securementUsername first from the context then from the property String contextUsername = (String) messageContext.getProperty(SECUREMENT_USER_PROPERTY_NAME); if (StringUtils.hasLength(contextUsername)) { requestData.setUsername(contextUsername); } else { requestData.setUsername(securementUsername); } requestData.setTimeToLive(securementTimeToLive); requestData.setUseDerivedKey(securementUseDerivedKey); requestData.setWssConfig(wssConfig); messageContext.setProperty(WSHandlerConstants.TTL_TIMESTAMP, Integer.toString(securementTimeToLive)); messageContext.setProperty(SAML_ISSUER_PROPERTY_NAME, samlIssuer); return requestData; } @Override protected void validateMessage(SoapMessage soapMessage, MessageContext messageContext) throws WsSecurityValidationException { if (logger.isDebugEnabled()) { logger.debug("Validating message [" + soapMessage + "] with actions [" + validationActions + "]"); } if (validationAction == WSConstants.NO_SECURITY) { return; } Document envelopeAsDocument = soapMessage.getDocument(); // Header processing try { List<WSSecurityEngineResult> results = securityEngine .processSecurityHeader(envelopeAsDocument, validationActor, validationCallbackHandler, validationSignatureCrypto, validationDecryptionCrypto); // Results verification if (CollectionUtils.isEmpty(results)) { throw new Wss4jSecurityValidationException("No WS-Security header found"); } checkResults(results, validationActionsVector); // puts the results in the context // useful for Signature Confirmation updateContextWithResults(messageContext, results); verifyCertificateTrust(results); verifyTimestamp(results); processPrincipal(results); } catch (WSSecurityException ex) { throw new Wss4jSecurityValidationException(ex.getMessage(), ex); } soapMessage.setDocument(envelopeAsDocument); if (this.getRemoveSecurityHeader()) { soapMessage.getEnvelope().getHeader().removeHeaderElement(WS_SECURITY_NAME); } } /** * Checks whether the received headers match the configured validation actions. Subclasses could override this method * for custom verification behavior. * * * @param results the results of the validation function * @param validationActions the decoded validation actions * @throws Wss4jSecurityValidationException if the results are deemed invalid */ protected void checkResults(List<WSSecurityEngineResult> results, List<Integer> validationActions) throws Wss4jSecurityValidationException { if (!handler.checkReceiverResultsAnyOrder(results, validationActions)) { throw new Wss4jSecurityValidationException("Security processing failed (actions mismatch)"); } } /** * Puts the results of WS-Security headers processing in the message context. Some actions like Signature * Confirmation require this. */ @SuppressWarnings("unchecked") private void updateContextWithResults(MessageContext messageContext, List<WSSecurityEngineResult> results) { List<WSHandlerResult> handlerResults; if ((handlerResults = (List<WSHandlerResult>) messageContext.getProperty(WSHandlerConstants.RECV_RESULTS)) == null) { handlerResults = new ArrayList<WSHandlerResult>(); messageContext.setProperty(WSHandlerConstants.RECV_RESULTS, handlerResults); } WSHandlerResult rResult = new WSHandlerResult(validationActor, results); handlerResults.add(0, rResult); messageContext.setProperty(WSHandlerConstants.RECV_RESULTS, handlerResults); } /** Verifies the trust of a certificate. */ protected void verifyCertificateTrust(List<WSSecurityEngineResult> results) throws WSSecurityException { WSSecurityEngineResult actionResult = WSSecurityUtil.fetchActionResult(results, WSConstants.SIGN); if (actionResult != null) { X509Certificate returnCert = (X509Certificate) actionResult.get(WSSecurityEngineResult.TAG_X509_CERTIFICATE); Credential credential = new Credential(); credential.setCertificates(new X509Certificate[] { returnCert}); RequestData requestData = new RequestData(); requestData.setSigCrypto(validationSignatureCrypto); requestData.setEnableRevocation(enableRevocation); SignatureTrustValidator validator = new SignatureTrustValidator(); validator.validate(credential, requestData); } } /** Verifies the timestamp. */ protected void verifyTimestamp(List<WSSecurityEngineResult> results) throws WSSecurityException { WSSecurityEngineResult actionResult = WSSecurityUtil.fetchActionResult(results, WSConstants.TS); if (actionResult != null) { Timestamp timestamp = (Timestamp) actionResult.get(WSSecurityEngineResult.TAG_TIMESTAMP); if (timestamp != null && timestampStrict) { Credential credential = new Credential(); credential.setTimestamp(timestamp); RequestData requestData = new RequestData(); WSSConfig config = new WSSConfig(); config.setTimeStampTTL(validationTimeToLive); config.setTimeStampStrict(timestampStrict); config.setTimeStampFutureTTL(futureTimeToLive); requestData.setWssConfig(config); TimestampValidator validator = new TimestampValidator(); validator.validate(credential, requestData); } } } private void processPrincipal(List<WSSecurityEngineResult> results) { WSSecurityEngineResult actionResult = WSSecurityUtil.fetchActionResult(results, WSConstants.UT); if (actionResult != null) { Principal principal = (Principal) actionResult.get(WSSecurityEngineResult.TAG_PRINCIPAL); if (principal != null && principal instanceof WSUsernameTokenPrincipal) { WSUsernameTokenPrincipal usernameTokenPrincipal = (WSUsernameTokenPrincipal) principal; UsernameTokenPrincipalCallback callback = new UsernameTokenPrincipalCallback(usernameTokenPrincipal); try { validationCallbackHandler.handle(new Callback[]{callback}); } catch (IOException ex) { logger.warn("Principal callback resulted in IOException", ex); } catch (UnsupportedCallbackException ex) { // ignore } } } } @Override protected void cleanUp() { if (validationCallbackHandler != null) { try { CleanupCallback cleanupCallback = new CleanupCallback(); validationCallbackHandler.handle(new Callback[]{cleanupCallback}); } catch (IOException ex) { logger.warn("Cleanup callback resulted in IOException", ex); } catch (UnsupportedCallbackException ex) { // ignore } } } }