Java tutorial
/** * Copyright (c) Codice Foundation * <p> * This is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser * General Public License as published by the Free Software Foundation, either version 3 of the * License, or any later version. * <p> * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. A copy of the GNU Lesser General Public License * is distributed along with this program and can be found at * <http://www.gnu.org/licenses/lgpl.html>. */ package org.codice.ddf.security.interceptor; import java.io.IOException; import java.io.StringReader; import java.io.StringWriter; import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.UUID; import javax.servlet.http.HttpServletRequest; import javax.xml.namespace.QName; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.soap.SOAPElement; import javax.xml.soap.SOAPException; import javax.xml.soap.SOAPFactory; import javax.xml.soap.SOAPMessage; import javax.xml.stream.FactoryConfigurationError; import javax.xml.stream.XMLOutputFactory; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamWriter; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpression; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; import org.apache.commons.lang.StringUtils; import org.apache.cxf.Bus; import org.apache.cxf.binding.soap.SoapBindingConstants; import org.apache.cxf.binding.soap.SoapFault; import org.apache.cxf.binding.soap.SoapMessage; import org.apache.cxf.binding.soap.SoapVersion; import org.apache.cxf.binding.soap.saaj.SAAJInInterceptor; import org.apache.cxf.common.classloader.ClassLoaderUtils; import org.apache.cxf.endpoint.Endpoint; import org.apache.cxf.interceptor.Fault; import org.apache.cxf.message.Exchange; import org.apache.cxf.message.MessageUtils; import org.apache.cxf.phase.Phase; import org.apache.cxf.service.model.BindingOperationInfo; import org.apache.cxf.service.model.EndpointInfo; import org.apache.cxf.transport.http.AbstractHTTPDestination; import org.apache.cxf.ws.addressing.AddressingProperties; import org.apache.cxf.ws.addressing.AttributedURIType; import org.apache.cxf.ws.addressing.EndpointReferenceType; import org.apache.cxf.ws.policy.AssertionInfo; import org.apache.cxf.ws.policy.AssertionInfoMap; import org.apache.cxf.ws.policy.EffectivePolicy; import org.apache.cxf.ws.policy.PolicyEngine; import org.apache.cxf.ws.security.SecurityConstants; import org.apache.cxf.ws.security.tokenstore.SecurityToken; import org.apache.cxf.ws.security.wss4j.AbstractWSS4JInterceptor; import org.apache.cxf.ws.security.wss4j.PolicyBasedWSS4JInInterceptor; import org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor; import org.apache.neethi.Policy; import org.apache.shiro.subject.PrincipalCollection; import org.apache.wss4j.common.ext.WSSecurityException; import org.apache.wss4j.dom.WSConstants; import org.apache.wss4j.dom.WSSConfig; import org.apache.wss4j.dom.WSSecurityEngine; import org.apache.wss4j.dom.handler.RequestData; import org.apache.wss4j.dom.handler.WSHandlerConstants; import org.apache.wss4j.dom.util.WSSecurityUtil; import org.apache.wss4j.dom.validate.Validator; import org.apache.wss4j.policy.SP12Constants; import org.codice.ddf.security.handler.api.AnonymousAuthenticationToken; import org.codice.ddf.security.handler.api.BaseAuthenticationToken; import org.codice.ddf.security.policy.context.ContextPolicyManager; import org.joda.time.DateTime; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import ddf.security.Subject; import ddf.security.assertion.SecurityAssertion; import ddf.security.common.audit.SecurityLogger; import ddf.security.common.util.Security; import ddf.security.encryption.EncryptionService; import ddf.security.service.SecurityManager; import ddf.security.service.SecurityServiceException; import ddf.security.sts.client.configuration.STSClientConfiguration; /** * Interceptor for anonymous access to SOAP endpoints. */ public class AnonymousInterceptor extends AbstractWSS4JInterceptor { private static final Logger LOGGER = LoggerFactory.getLogger(AnonymousInterceptor.class); //Token Assertions private static final String TOKEN_SAML20 = "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0"; private static final ThreadLocal<DocumentBuilder> BUILDER = new ThreadLocal<DocumentBuilder>() { @Override protected DocumentBuilder initialValue() { try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(false); return factory.newDocumentBuilder(); } catch (ParserConfigurationException ex) { // This exception should not happen throw new IllegalArgumentException("Unable to create new DocumentBuilder", ex); } } }; private EncryptionService encryptionService; private SecurityManager securityManager; private STSClientConfiguration stsClientConfiguration; private ContextPolicyManager contextPolicyManager; private boolean anonymousAccessDenied = false; private boolean overrideEndpointPolicies = false; private Map<String, Subject> cachedAnonymousSubjectMap = new HashMap<>(); public AnonymousInterceptor(SecurityManager securityManager, ContextPolicyManager contextPolicyManager) { super(); LOGGER.trace("Constructing AnonymousInterceptor"); this.securityManager = securityManager; this.contextPolicyManager = contextPolicyManager; setPhase(Phase.PRE_PROTOCOL); //make sure this interceptor runs before the WSS4J one in the same Phase, otherwise it won't work Set<String> before = getBefore(); before.add(WSS4JInInterceptor.class.getName()); before.add(PolicyBasedWSS4JInInterceptor.class.getName()); LOGGER.trace("Exiting AnonymousInterceptor constructor."); } @Override public void handleMessage(SoapMessage message) throws Fault { if (anonymousAccessDenied) { LOGGER.debug("AnonymousAccess not enabled - no message checking performed."); return; } if (message != null) { SoapVersion version = message.getVersion(); SOAPMessage soapMessage = getSOAPMessage(message); SOAPFactory soapFactory = null; SOAPElement securityHeader = null; //Check if security header exists; if not, execute AnonymousInterceptor logic String actor = (String) getOption(WSHandlerConstants.ACTOR); if (actor == null) { actor = (String) message.getContextualProperty(SecurityConstants.ACTOR); } Element existingSecurityHeader = null; try { LOGGER.debug("Checking for security header."); existingSecurityHeader = WSSecurityUtil.getSecurityHeader(soapMessage.getSOAPPart(), actor); } catch (WSSecurityException e1) { LOGGER.debug("Issue with getting security header", e1); } if (existingSecurityHeader == null) { LOGGER.debug("Current request has no security header, continuing with AnonymousInterceptor"); AssertionInfoMap assertionInfoMap = message.get(AssertionInfoMap.class); // if there is a policy we need to follow or we are ignoring policies, prepare the SOAP message if ((assertionInfoMap != null) || overrideEndpointPolicies) { RequestData reqData = new CXFRequestData(); WSSConfig config = (WSSConfig) message.getContextualProperty(WSSConfig.class.getName()); WSSecurityEngine engine = null; if (config != null) { engine = new WSSecurityEngine(); engine.setWssConfig(config); } if (engine == null) { engine = new WSSecurityEngine(); config = engine.getWssConfig(); } reqData.setWssConfig(config); try { soapFactory = SOAPFactory.newInstance(); } catch (SOAPException e) { LOGGER.error("Could not create a SOAPFactory.", e); return; // can't add anything if we can't create it } if (soapFactory != null) { //Create security header try { securityHeader = soapFactory.createElement(WSConstants.WSSE_LN, WSConstants.WSSE_PREFIX, WSConstants.WSSE_NS); securityHeader.addAttribute( new QName(WSConstants.URI_SOAP11_ENV, WSConstants.ATTR_MUST_UNDERSTAND), "1"); } catch (SOAPException e) { LOGGER.error("Unable to create security header for anonymous user.", e); return; // can't create the security - just return } } } EffectivePolicy effectivePolicy = message.get(EffectivePolicy.class); Exchange exchange = message.getExchange(); BindingOperationInfo bindingOperationInfo = exchange.getBindingOperationInfo(); Endpoint endpoint = exchange.get(Endpoint.class); if (null == endpoint) { return; } EndpointInfo endpointInfo = endpoint.getEndpointInfo(); Bus bus = exchange.get(Bus.class); PolicyEngine policyEngine = bus.getExtension(PolicyEngine.class); if (effectivePolicy == null) { if (policyEngine != null) { if (MessageUtils.isRequestor(message)) { effectivePolicy = policyEngine.getEffectiveClientResponsePolicy(endpointInfo, bindingOperationInfo, message); } else { effectivePolicy = policyEngine.getEffectiveServerRequestPolicy(endpointInfo, bindingOperationInfo, message); } } } //Auto analyze endpoint policies //Token Assertions String tokenAssertion = null; String tokenType = null; //Security Binding Assertions boolean layoutLax = false; boolean layoutStrict = false; boolean layoutLaxTimestampFirst = false; boolean layoutLaxTimestampLast = false; boolean requireClientCert = false; QName secBindingAssertion = null; //Supporting Token Assertions QName supportingTokenAssertion = null; boolean policyRequirementsSupported = false; // if there is a policy, try to follow it as closely as possible if (effectivePolicy != null) { Policy policy = effectivePolicy.getPolicy(); if (policy != null) { AssertionInfoMap infoMap = new AssertionInfoMap(policy); Set<Map.Entry<QName, Collection<AssertionInfo>>> entries = infoMap.entrySet(); for (Map.Entry<QName, Collection<AssertionInfo>> entry : entries) { Collection<AssertionInfo> assetInfoList = entry.getValue(); for (AssertionInfo info : assetInfoList) { LOGGER.debug("Assertion Name: {}", info.getAssertion().getName().getLocalPart()); QName qName = info.getAssertion().getName(); StringWriter out = new StringWriter(); XMLStreamWriter writer = null; try { writer = XMLOutputFactory.newInstance().createXMLStreamWriter(out); } catch (XMLStreamException e) { LOGGER.debug("Error with XMLStreamWriter", e); } catch (FactoryConfigurationError e) { LOGGER.debug("Error with FactoryConfiguration", e); } try { if (writer != null) { info.getAssertion().serialize(writer); writer.flush(); } } catch (XMLStreamException e) { LOGGER.debug("Error with XMLStream", e); } finally { if (writer != null) { try { writer.close(); } catch (XMLStreamException ignore) { //ignore } } } LOGGER.trace("Assertion XML: {}", out.toString()); String xml = out.toString(); // TODO DDF-1205 complete support for dynamic policy handling if (qName.equals(SP12Constants.TRANSPORT_BINDING)) { secBindingAssertion = qName; } else if (qName.equals(SP12Constants.INCLUDE_TIMESTAMP)) { createIncludeTimestamp(soapFactory, securityHeader); } else if (qName.equals(SP12Constants.LAYOUT)) { String xpathLax = "/Layout/Policy/Lax"; String xpathStrict = "/Layout/Policy/Strict"; String xpathLaxTimestampFirst = "/Layout/Policy/LaxTimestampFirst"; String xpathLaxTimestampLast = "/Layout/Policy/LaxTimestampLast"; } else if (qName.equals(SP12Constants.TRANSPORT_TOKEN)) { } else if (qName.equals(SP12Constants.HTTPS_TOKEN)) { String xpath = "/HttpsToken/Policy/RequireClientCertificate"; } else if (qName.equals(SP12Constants.SIGNED_SUPPORTING_TOKENS)) { String xpath = "/SignedSupportingTokens/Policy//IssuedToken/RequestSecurityTokenTemplate/TokenType"; tokenType = retrieveXmlValue(xml, xpath); supportingTokenAssertion = qName; } else if (qName.equals(SP12Constants.SUPPORTING_TOKENS)) { String xpath = "/SupportingTokens/Policy//IssuedToken/RequestSecurityTokenTemplate/TokenType"; tokenType = retrieveXmlValue(xml, xpath); supportingTokenAssertion = qName; } else if (qName.equals( org.apache.cxf.ws.addressing.policy.MetadataConstants.ADDRESSING_ASSERTION_QNAME)) { createAddressing(message, soapMessage, soapFactory); } else if (qName.equals(SP12Constants.TRUST_13)) { } else if (qName.equals(SP12Constants.ISSUED_TOKEN)) { //Check Token Assertion String xpath = "/IssuedToken/@IncludeToken"; tokenAssertion = retrieveXmlValue(xml, xpath); } else if (qName.equals(SP12Constants.WSS11)) { } } } //Check security and token policies if (tokenAssertion != null && tokenType != null && tokenAssertion.trim().equals(SP12Constants.INCLUDE_ALWAYS_TO_RECIPIENT) && tokenType.trim().equals(TOKEN_SAML20)) { policyRequirementsSupported = true; } else { LOGGER.warn( "AnonymousInterceptor does not support the policies presented by the endpoint."); } } else { if (overrideEndpointPolicies) { LOGGER.debug( "WS Policy is null, override is true - an anonymous assertion will be generated"); } else { LOGGER.warn( "WS Policy is null, override flag is false - no anonymous assertion will be generated."); } } } else { if (overrideEndpointPolicies) { LOGGER.debug( "Effective WS Policy is null, override is true - an anonymous assertion will be generated"); } else { LOGGER.warn( "Effective WS Policy is null, override flag is false - no anonymous assertion will be generated."); } } if (policyRequirementsSupported || overrideEndpointPolicies) { LOGGER.debug("Creating anonymous security token."); if (soapFactory != null) { HttpServletRequest request = (HttpServletRequest) message .get(AbstractHTTPDestination.HTTP_REQUEST); createSecurityToken(version, soapFactory, securityHeader, request.getRemoteAddr()); try { // Add security header to SOAP message soapMessage.getSOAPHeader().addChildElement(securityHeader); } catch (SOAPException e) { LOGGER.error("Issue when adding security header to SOAP message:" + e.getMessage()); } } else { LOGGER.debug("Security Header was null so not creating a SAML Assertion"); } } } else { LOGGER.debug("SOAP message contains security header, no action taken by the AnonymousInterceptor."); } if (LOGGER.isTraceEnabled()) { try { LOGGER.trace("SOAP request after anonymous interceptor: {}", SecurityLogger.getFormattedXml(soapMessage.getSOAPHeader().getParentNode())); } catch (SOAPException e) { //ignore } } } else { LOGGER.error("Incoming SOAP message is null - anonymous interceptor makes no sense."); } } private void createSecurityToken(SoapVersion version, SOAPFactory soapFactory, SOAPElement securityHeader, String ipAddress) { Subject subject = getSubject(ipAddress); LOGGER.trace("Attempting to create Security token."); if (subject != null) { PrincipalCollection principals = subject.getPrincipals(); if (principals != null) { SecurityAssertion securityAssertion = principals.oneByType(SecurityAssertion.class); if (securityAssertion != null) { SecurityToken securityToken = securityAssertion.getSecurityToken(); Element samlElement = securityToken.getToken(); SOAPElement samlAssertion = null; try { samlAssertion = soapFactory.createElement(samlElement); securityHeader.addChildElement(samlAssertion); } catch (SOAPException e) { LOGGER.error("Unable to convert SecurityToken to SOAPElement.", e); } } else { LOGGER.warn("Subject did not contain a security assertion, could not assertion" + "to security header."); } } else { LOGGER.warn("Subject did not contain any principals, could not create element."); } } } private synchronized Subject getSubject(String ipAddress) { Subject subject = cachedAnonymousSubjectMap.get(ipAddress); if (Security.tokenAboutToExpire(subject)) { AnonymousAuthenticationToken token = new AnonymousAuthenticationToken( BaseAuthenticationToken.DEFAULT_REALM, ipAddress); LOGGER.debug("Getting new Anonymous user token for {}", ipAddress); try { subject = securityManager.getSubject(token); cachedAnonymousSubjectMap.put(ipAddress, subject); } catch (SecurityServiceException sse) { LOGGER.warn("Unable to request subject for anonymous user.", sse); } } else { LOGGER.debug("Using cached Anonymous user token for {}", ipAddress); } return subject; } private void createIncludeTimestamp(SOAPFactory soapFactory, SOAPElement securityHeader) { SOAPElement timestamp = null; try { timestamp = soapFactory.createElement(WSConstants.TIMESTAMP_TOKEN_LN, WSConstants.WSU_PREFIX, WSConstants.WSU_NS); SOAPElement created = soapFactory.createElement(WSConstants.CREATED_LN, WSConstants.WSU_PREFIX, WSConstants.WSU_NS); DateTime dateTime = new DateTime(); created.addTextNode(dateTime.toString()); SOAPElement expires = soapFactory.createElement(WSConstants.EXPIRES_LN, WSConstants.WSU_PREFIX, WSConstants.WSU_NS); expires.addTextNode(dateTime.plusMinutes(5).toString()); timestamp.addChildElement(created); timestamp.addChildElement(expires); securityHeader.addChildElement(timestamp); } catch (SOAPException e) { LOGGER.error("Unable to create security timestamp.", e); } } private void createAddressing(SoapMessage message, SOAPMessage soapMessage, SOAPFactory soapFactory) { String addressingProperty = org.apache.cxf.ws.addressing.JAXWSAConstants.CLIENT_ADDRESSING_PROPERTIES_INBOUND; AddressingProperties addressingProperties = new AddressingProperties(); SOAPElement action = null; try { action = soapFactory.createElement(org.apache.cxf.ws.addressing.Names.WSA_ACTION_NAME, org.apache.cxf.ws.addressing.JAXWSAConstants.WSA_PREFIX, org.apache.cxf.ws.security.wss4j.DefaultCryptoCoverageChecker.WSA_NS); action.addTextNode((String) message.get(org.apache.cxf.message.Message.REQUEST_URL)); AttributedURIType attributedString = new AttributedURIType(); String actionValue = StringUtils.defaultIfEmpty((String) message.get(SoapBindingConstants.SOAP_ACTION), ""); attributedString.setValue(actionValue); addressingProperties.setAction(attributedString); } catch (SOAPException e) { LOGGER.error("Unable to add addressing action.", e); } SOAPElement messageId = null; try { messageId = soapFactory.createElement(org.apache.cxf.ws.addressing.Names.WSA_MESSAGEID_NAME, org.apache.cxf.ws.addressing.JAXWSAConstants.WSA_PREFIX, org.apache.cxf.ws.security.wss4j.DefaultCryptoCoverageChecker.WSA_NS); String uuid = "urn:uuid:" + UUID.randomUUID().toString(); messageId.addTextNode(uuid); AttributedURIType attributedString = new AttributedURIType(); attributedString.setValue(uuid); addressingProperties.setMessageID(attributedString); } catch (SOAPException e) { LOGGER.error("Unable to add addressing action.", e); } SOAPElement to = null; try { to = soapFactory.createElement(org.apache.cxf.ws.addressing.Names.WSA_TO_NAME, org.apache.cxf.ws.addressing.JAXWSAConstants.WSA_PREFIX, org.apache.cxf.ws.security.wss4j.DefaultCryptoCoverageChecker.WSA_NS); to.addTextNode((String) message.get(org.apache.cxf.message.Message.REQUEST_URL)); EndpointReferenceType endpointReferenceType = new EndpointReferenceType(); AttributedURIType attributedString = new AttributedURIType(); attributedString.setValue((String) message.get(org.apache.cxf.message.Message.REQUEST_URL)); endpointReferenceType.setAddress(attributedString); addressingProperties.setTo(endpointReferenceType); } catch (SOAPException e) { LOGGER.error("Unable to add addressing action.", e); } SOAPElement replyTo = null; try { replyTo = soapFactory.createElement(org.apache.cxf.ws.addressing.Names.WSA_REPLYTO_NAME, org.apache.cxf.ws.addressing.JAXWSAConstants.WSA_PREFIX, org.apache.cxf.ws.security.wss4j.DefaultCryptoCoverageChecker.WSA_NS); SOAPElement address = soapFactory.createElement(org.apache.cxf.ws.addressing.Names.WSA_ADDRESS_NAME, org.apache.cxf.ws.addressing.JAXWSAConstants.WSA_PREFIX, org.apache.cxf.ws.security.wss4j.DefaultCryptoCoverageChecker.WSA_NS); address.addTextNode(org.apache.cxf.ws.addressing.Names.WSA_ANONYMOUS_ADDRESS); replyTo.addChildElement(address); soapMessage.getSOAPHeader().addChildElement(messageId); soapMessage.getSOAPHeader().addChildElement(action); soapMessage.getSOAPHeader().addChildElement(to); soapMessage.getSOAPHeader().addChildElement(replyTo); message.put(addressingProperty, addressingProperties); } catch (SOAPException e) { LOGGER.error("Unable to add addressing action.", e); } } private SoapFault createSoapFault(SoapVersion version, WSSecurityException e) { SoapFault fault; javax.xml.namespace.QName faultCode = e.getFaultCode(); if (version.getVersion() == 1.1 && faultCode != null) { fault = new SoapFault(e.getMessage(), e, faultCode); } else { fault = new SoapFault(e.getMessage(), e, version.getSender()); if (version.getVersion() != 1.1 && faultCode != null) { fault.setSubCode(faultCode); } } return fault; } private String retrieveXmlValue(String xml, String xpathStmt) { String result = null; Document document = createDocument(xml); XPathFactory xFactory = XPathFactory.newInstance(); XPath xpath = xFactory.newXPath(); try { XPathExpression expr = xpath.compile(xpathStmt); result = (String) expr.evaluate(document, XPathConstants.STRING); } catch (XPathExpressionException e) { LOGGER.warn("Error processing XPath statement on policy XML."); } return result; } private boolean evaluateExpression(String xml, String xpathStmt) { Boolean result = false; Document document = createDocument(xml); XPathFactory xFactory = XPathFactory.newInstance(); XPath xpath = xFactory.newXPath(); try { XPathExpression expr = xpath.compile("boolean(" + xpathStmt + ")"); result = (Boolean) expr.evaluate(document, XPathConstants.BOOLEAN); } catch (XPathExpressionException e) { LOGGER.warn("Error processing XPath statement on policy XML.", e); } return result; } private Document createDocument(String xml) { InputSource source = new InputSource(new StringReader(xml)); Document document = null; BUILDER.get().reset(); try { document = BUILDER.get().parse(source); } catch (SAXException e1) { LOGGER.warn("Error parsing policy XML.", e1); } catch (IOException e1) { LOGGER.warn("Error creating Document for XPath parsing.", e1); } return document; } private SOAPMessage getSOAPMessage(SoapMessage msg) { SAAJInInterceptor.INSTANCE.handleMessage(msg); return msg.getContent(SOAPMessage.class); } public EncryptionService getEncryptionService() { return encryptionService; } public void setEncryptionService(EncryptionService encryptionService) { this.encryptionService = encryptionService; } public STSClientConfiguration getStsClientConfiguration() { return stsClientConfiguration; } public void setStsClientConfiguration(STSClientConfiguration stsClientConfiguration) { this.stsClientConfiguration = stsClientConfiguration; } public ContextPolicyManager getContextPolicyManager() { return contextPolicyManager; } public void setContextPolicyManager(ContextPolicyManager contextPolicyManager) { this.contextPolicyManager = contextPolicyManager; } public boolean isAnonymousAccessDenied() { return anonymousAccessDenied; } public void setAnonymousAccessDenied(boolean deny) { anonymousAccessDenied = deny; } public void setOverrideEndpointPolicies(boolean override) { overrideEndpointPolicies = override; } public void destroy() { BUILDER.remove(); } static class CXFRequestData extends RequestData { public CXFRequestData() { } public Validator getValidator(QName qName) throws WSSecurityException { String key = null; if (WSSecurityEngine.SAML_TOKEN.equals(qName)) { key = SecurityConstants.SAML1_TOKEN_VALIDATOR; } else if (WSSecurityEngine.SAML2_TOKEN.equals(qName)) { key = SecurityConstants.SAML2_TOKEN_VALIDATOR; } else if (WSSecurityEngine.USERNAME_TOKEN.equals(qName)) { key = SecurityConstants.USERNAME_TOKEN_VALIDATOR; } else if (WSSecurityEngine.SIGNATURE.equals(qName)) { key = SecurityConstants.SIGNATURE_TOKEN_VALIDATOR; } else if (WSSecurityEngine.TIMESTAMP.equals(qName)) { key = SecurityConstants.TIMESTAMP_TOKEN_VALIDATOR; } else if (WSSecurityEngine.BINARY_TOKEN.equals(qName)) { key = SecurityConstants.BST_TOKEN_VALIDATOR; } else if (WSSecurityEngine.SECURITY_CONTEXT_TOKEN_05_02.equals(qName) || WSSecurityEngine.SECURITY_CONTEXT_TOKEN_05_12.equals(qName)) { key = SecurityConstants.SCT_TOKEN_VALIDATOR; } if (key != null) { Object o = ((SoapMessage) this.getMsgContext()).getContextualProperty(key); try { if (o instanceof Validator) { return (Validator) o; } else if (o instanceof Class) { return (Validator) ((Class<?>) o).newInstance(); } else if (o instanceof String) { return (Validator) ClassLoaderUtils.loadClass(o.toString(), WSS4JInInterceptor.class) .newInstance(); } } catch (RuntimeException t) { throw t; } catch (Throwable t) { throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, t.getMessage(), t); } } return super.getValidator(qName); } } }