Shumin Li created CXF-8077:
------------------------------

             Summary: WSS4JInInterceptor is not thread safe
                 Key: CXF-8077
                 URL: https://issues.apache.org/jira/browse/CXF-8077
             Project: CXF
          Issue Type: Bug
          Components: WS-* Components
    Affects Versions: 3.3.2
            Reporter: Shumin Li


org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor uses a cached property 
WSSecurityEngine secEngineOverride.  In the situation that the same instance of 
secEngineOverride is used for 2 or more threads,  Following code in 
handleMessageInternal() will cause WSS4J to lookup wrong XML document.

if (soapBody != null) {
 engine.setCallbackLookup(new CXFCallbackLookup(soapBody.getOwnerDocument(), 
soapBody));
 }

In my case, interceptor is used to do X.509 authentication with Signature for 
signing. When 2 or more requests comes at the almost the same time, it produces 
following error for victim thread(s).

org.apache.cxf.binding.soap.SoapFault: A security error was encountered when 
verifying the message
 at 
org.apache.cxf.ws.security.wss4j.WSS4JUtils.createSoapFault(WSS4JUtils.java:234)
 at 
org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.handleMessageInternal(WSS4JInInterceptor.java:376)
 at 
org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.handleMessage(WSS4JInInterceptor.java:212)
 at 
org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.handleMessage(WSS4JInInterceptor.java:92)
 at 
org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308)
 at 
org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)
 at 
org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:267)
 at 
org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:234)
 at 
org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:208)
 at 
org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:160)
 at 
org.apache.cxf.transport.servlet.CXFNonSpringServlet.invoke(CXFNonSpringServlet.java:216)
 at 
org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:301)
 at 
org.apache.cxf.transport.servlet.AbstractHTTPServlet.doPost(AbstractHTTPServlet.java:220)
 at javax.servlet.http.HttpServlet.service(HttpServlet.java:660)
 at 
org.apache.cxf.transport.servlet.AbstractHTTPServlet.service(AbstractHTTPServlet.java:276)
 at 
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
 at 
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
 at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
 at 
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
 at 
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
 at 
org.springframework.boot.actuate.web.trace.servlet.HttpTraceFilter.doFilterInternal(HttpTraceFilter.java:88)
 at 
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109)
 at 
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
 at 
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
 at 
org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:209)
 at 
org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178)
 at 
org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:357)
 at 
org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:270)
 at 
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
 at 
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
 at 
org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
 at 
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109)
 at 
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
 at 
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
 at 
org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92)
 at 
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109)
 at 
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
 at 
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
 at 
org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93)
 at 
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109)
 at 
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
 at 
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
 at 
org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:114)
 at 
org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:104)
 at 
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109)
 at 
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
 at 
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
 at 
org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
 at 
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109)
 at 
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
 at 
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
 at 
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
 at 
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
 at 
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490)
 at 
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
 at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
 at 
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
 at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
 at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
 at 
org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
 at 
org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:853)
 at 
org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1587)
 at 
org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
 at 
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
 at 
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
 at 
org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
 at java.lang.Thread.run(Thread.java:748)
Caused by: org.apache.wss4j.common.ext.WSSecurityException: 
javax.xml.crypto.URIReferenceException: 
org.apache.xml.security.utils.resolver.ResourceResolverException: Cannot 
resolve element with ID id-e41ca583-c6f1-40d5-8acc-f3968287b0cb
 at 
org.apache.wss4j.dom.processor.SignatureProcessor.verifyXMLSignature(SignatureProcessor.java:399)
 at 
org.apache.wss4j.dom.processor.SignatureProcessor.handleToken(SignatureProcessor.java:232)
 at 
org.apache.wss4j.dom.engine.WSSecurityEngine.processSecurityHeader(WSSecurityEngine.java:340)
 at 
org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.handleMessageInternal(WSS4JInInterceptor.java:320)
 ... 65 common frames omitted
Caused by: javax.xml.crypto.dsig.XMLSignatureException: 
javax.xml.crypto.URIReferenceException: 
org.apache.xml.security.utils.resolver.ResourceResolverException: Cannot 
resolve element with ID id-e41ca583-c6f1-40d5-8acc-f3968287b0cb
 at 
org.apache.jcp.xml.dsig.internal.dom.DOMReference.dereference(DOMReference.java:418)
 at 
org.apache.jcp.xml.dsig.internal.dom.DOMReference.validate(DOMReference.java:382)
 at 
org.apache.jcp.xml.dsig.internal.dom.DOMXMLSignature.validate(DOMXMLSignature.java:277)
 at 
org.apache.wss4j.dom.processor.SignatureProcessor.verifyXMLSignature(SignatureProcessor.java:372)
 ... 68 common frames omitted
Caused by: javax.xml.crypto.URIReferenceException: 
org.apache.xml.security.utils.resolver.ResourceResolverException: Cannot 
resolve element with ID id-e41ca583-c6f1-40d5-8acc-f3968287b0cb
 at 
org.apache.jcp.xml.dsig.internal.dom.DOMURIDereferencer.dereference(DOMURIDereferencer.java:117)
 at 
org.apache.jcp.xml.dsig.internal.dom.DOMReference.dereference(DOMReference.java:414)
 ... 71 common frames omitted
Caused by: org.apache.xml.security.utils.resolver.ResourceResolverException: 
Cannot resolve element with ID id-e41ca583-c6f1-40d5-8acc-f3968287b0cb
 at 
org.apache.xml.security.utils.resolver.implementations.ResolverFragment.engineResolveURI(ResolverFragment.java:78)
 at 
org.apache.xml.security.utils.resolver.ResourceResolver.resolve(ResourceResolver.java:278)
 at 
org.apache.jcp.xml.dsig.internal.dom.DOMURIDereferencer.dereference(DOMURIDereferencer.java:110)
 ... 72 common frames omitted

 

I ended up to override protected WSSecurityEngine getSecurityEngine(boolean 
utWithCallbacks)  to create WSSecurityEngine everything to avoid the issue.

 

It can be fixed using antonymous inner class to replace previous code as 
following as a concept.  Please note that calling new 
CXFCallbackLookup(soapBody.getOwnerDocument(), soapBody) in each interface 
method might not be most efficient.

 

final Element soapBody = SAAJUtils.getBody(doc);
 if (soapBody != null) {
 engine.setCallbackLookup(new CallbackLookup() {
 @Override
 public Element getElement(String s, String s1, boolean b) throws 
WSSecurityException {
 return new CXFCallbackLookup(soapBody.getOwnerDocument(), 
soapBody).getElement(s, s1, b);
 }

@Override
 public Element getAndRegisterElement(String s, String s1, boolean b, 
DOMCryptoContext domCryptoContext) throws WSSecurityException {
 return new CXFCallbackLookup(soapBody.getOwnerDocument(), 
soapBody).getAndRegisterElement(s, s1, b, domCryptoContext);
 }

@Override
 public List<Element> getElements(String s, String s1) throws 
WSSecurityException {
 return new CXFCallbackLookup(soapBody.getOwnerDocument(), 
soapBody).getElements(s, s1);
 }

@Override
 public Element getSOAPBody() {
 return new CXFCallbackLookup(soapBody.getOwnerDocument(), 
soapBody).getSOAPBody();
 }
 });
 }



--
This message was sent by Atlassian JIRA
(v7.6.14#76016)

Reply via email to