High severityNVD Advisory· Published Sep 24, 2012· Updated Apr 29, 2026
CVE-2012-3451
CVE-2012-3451
Description
Apache CXF before 2.4.9, 2.5.x before 2.5.5, and 2.6.x before 2.6.2 allows remote attackers to execute unintended web-service operations by sending a header with a SOAP Action String that is inconsistent with the message body.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
org.apache.cxf:cxfMaven | < 2.4.9 | 2.4.9 |
org.apache.cxf:cxfMaven | >= 2.5.0, < 2.5.5 | 2.5.5 |
org.apache.cxf:cxfMaven | >= 2.6.0, < 2.6.2 | 2.6.2 |
Affected products
2Patches
4deeeaa95a861Merged revisions 1368608 via git cherry-pick from
10 files changed · +760 −21
rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/Messages.properties+1 −0 modified@@ -31,3 +31,4 @@ INVALID_11_VERSION=A SOAP 1.2 message is not valid when sent to a SOAP 1.1 only NO_NAMESPACE=No namespace on "{0}" element. BP_2211_RPCLIT_CANNOT_BE_NULL=Cannot write part {0}. RPC/Literal parts cannot be null. (WS-I BP R2211) UNKNOWN_RPC_LIT_PART=Found element {0} but could not find matching RPC/Literal part +SOAP_ACTION_MISMATCH=The given SOAPAction {0} does not match an operation.
rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/SoapActionInInterceptor.java+52 −14 modified@@ -22,12 +22,14 @@ import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.logging.Logger; import org.apache.cxf.binding.soap.Soap11; import org.apache.cxf.binding.soap.Soap12; import org.apache.cxf.binding.soap.SoapBindingConstants; import org.apache.cxf.binding.soap.SoapMessage; import org.apache.cxf.binding.soap.model.SoapOperationInfo; +import org.apache.cxf.common.logging.LogUtils; import org.apache.cxf.common.util.StringUtils; import org.apache.cxf.endpoint.Endpoint; import org.apache.cxf.helpers.CastUtils; @@ -40,6 +42,8 @@ public class SoapActionInInterceptor extends AbstractSoapInterceptor { + private static final Logger LOG = LogUtils.getL7dLogger(SoapActionInInterceptor.class); + public SoapActionInInterceptor() { super(Phase.READ); addAfter(ReadHeadersInterceptor.class.getName()); @@ -91,6 +95,10 @@ public static String getSoapAction(Message m) { } public void handleMessage(SoapMessage message) throws Fault { + if (isRequestor(message)) { + return; + } + String action = getSoapAction(message); if (!StringUtils.isEmpty(action)) { getAndSetOperation(message, action); @@ -108,24 +116,54 @@ private void getAndSetOperation(SoapMessage message, String action) { BindingOperationInfo bindingOp = null; - Collection<BindingOperationInfo> bops = ep.getBinding().getBindingInfo().getOperations(); - if (bops == null) { - return; - } - for (BindingOperationInfo boi : bops) { - SoapOperationInfo soi = (SoapOperationInfo) boi.getExtensor(SoapOperationInfo.class); - if (soi != null && action.equals(soi.getAction())) { - if (bindingOp != null) { - //more than one op with the same action, will need to parse normally - return; + Collection<BindingOperationInfo> bops = ep.getEndpointInfo() + .getBinding().getOperations(); + if (bops != null) { + for (BindingOperationInfo boi : bops) { + SoapOperationInfo soi = boi.getExtensor(SoapOperationInfo.class); + if (soi != null && action.equals(soi.getAction())) { + if (bindingOp != null) { + //more than one op with the same action, will need to parse normally + return; + } + bindingOp = boi; } - bindingOp = boi; } } - if (bindingOp != null) { - ex.put(BindingOperationInfo.class, bindingOp); - ex.put(OperationInfo.class, bindingOp.getOperationInfo()); + + if (bindingOp == null) { + //we didn't match the an operation, we'll try again later to make + //sure the incoming message did end up matching an operation. + //This could occur in some cases like WS-RM and WS-SecConv that will + //intercept the message with a new endpoint/operation + message.getInterceptorChain().add(new SoapActionInAttemptTwoInterceptor()); + return; + } + + ex.put(BindingOperationInfo.class, bindingOp); + ex.put(OperationInfo.class, bindingOp.getOperationInfo()); + } + + public static class SoapActionInAttemptTwoInterceptor extends AbstractSoapInterceptor { + public SoapActionInAttemptTwoInterceptor() { + super(Phase.PRE_LOGICAL); + } + public void handleMessage(SoapMessage message) throws Fault { + BindingOperationInfo boi = message.getExchange().getBindingOperationInfo(); + if (boi == null) { + return; + } + String action = getSoapAction(message); + if (StringUtils.isEmpty(action)) { + return; + } + SoapOperationInfo soi = boi.getExtensor(SoapOperationInfo.class); + if (soi == null || action.equals(soi.getAction())) { + return; + } + throw new Fault("SOAP_ACTION_MISMATCH", LOG, null, action); } } + }
rt/core/src/main/java/org/apache/cxf/interceptor/DocLiteralInInterceptor.java+43 −6 modified@@ -192,12 +192,11 @@ public void handleMessage(Message message) { } else { p = findMessagePart(exchange, operations, elName, client, paramNum, message); } - - if (p == null) { - throw new Fault(new org.apache.cxf.common.i18n.Message("NO_PART_FOUND", LOG, elName), - Fault.FAULT_CODE_CLIENT); - } - + + //Make sure the elName found on the wire is actually OK for + //the purpose we need it + validatePart(p, elName, si); + o = dr.read(p, xmlReader); if (Boolean.TRUE.equals(si.getProperty("soap.force.doclit.bare")) && parameters.isEmpty()) { @@ -224,6 +223,44 @@ public void handleMessage(Message message) { } } + private void validatePart(MessagePartInfo p, QName elName, ServiceInfo si) { + if (p == null) { + throw new Fault(new org.apache.cxf.common.i18n.Message("NO_PART_FOUND", LOG, elName), + Fault.FAULT_CODE_CLIENT); + + } + + Boolean synth = Boolean.FALSE; + if (p.getMessageInfo() != null && p.getMessageInfo().getOperation() != null) { + OperationInfo op = p.getMessageInfo().getOperation(); + Boolean b = (Boolean)op.getProperty("operation.is.synthetic"); + if (b != null) { + synth = b; + } + } + if (si != null && Boolean.TRUE.equals(si.getProperty("soap.force.doclit.bare"))) { + // something like a Provider service or similar that is forcing a + // doc/lit/bare on an endpoint that may not really be doc/lit/bare. + // we need to just let these through per spec so the endpoint + // can process it + synth = true; + } + if (p.isElement()) { + if (p.getConcreteName() != null + && !elName.equals(p.getConcreteName()) + && !Boolean.TRUE.equals(synth)) { + throw new Fault("UNEXPECTED_ELEMENT", LOG, null, elName, + p.getConcreteName()); + } + } else { + if (!(elName.equals(p.getName()) || elName.equals(p.getConcreteName())) + && !Boolean.TRUE.equals(synth)) { + throw new Fault("UNEXPECTED_ELEMENT", LOG, null, elName, + p.getConcreteName()); + } + } + } + private void getPara(DepthXMLStreamReader xmlReader, DataReader<XMLStreamReader> dr, MessageContentsList parameters,
rt/core/src/main/java/org/apache/cxf/interceptor/Messages.properties+1 −0 modified@@ -40,4 +40,5 @@ COULD_NOT_FIND_SEICLASS=Could not find the class: {0} EXCEPTION_WHILE_WRITING_FAULT = Exception occurred while writing fault. EXCEPTION_WHILE_CREATING_EXCEPTION = Exception occurred while creating exception: {0} UNEXPECTED_WRAPPER_ELEMENT = Unexpected wrapper element {0} found. Expected {1}. +UNEXPECTED_ELEMENT = Unexpected element {0} found. Expected {1}.
systests/uncategorized/src/test/java/org/apache/cxf/systest/soap/RPCEncodedSoapActionGreeterImpl.java+40 −0 added@@ -0,0 +1,40 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.cxf.systest.soap; + +import javax.jws.WebService; +import javax.jws.soap.SOAPBinding; + +import org.apache.hello_world_soap_action.WrappedGreeter; + +@WebService(endpointInterface = "org.apache.hello_world_soap_action.WrappedGreeter", +serviceName = "WrappedSOAPService") +@SOAPBinding(style = SOAPBinding.Style.RPC, use = SOAPBinding.Use.ENCODED) +public class RPCEncodedSoapActionGreeterImpl implements WrappedGreeter { + + public String sayHiRequestWrapped(String in) { + return "sayHi"; + } + + public String sayHiRequest2Wrapped(String in) { + return "sayHi2"; + } + +}
systests/uncategorized/src/test/java/org/apache/cxf/systest/soap/RPCLitSoapActionGreeterImpl.java+40 −0 added@@ -0,0 +1,40 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.cxf.systest.soap; + +import javax.jws.WebService; +import javax.jws.soap.SOAPBinding; + +import org.apache.hello_world_soap_action.WrappedGreeter; + +@WebService(endpointInterface = "org.apache.hello_world_soap_action.WrappedGreeter", +serviceName = "WrappedSOAPService") +@SOAPBinding(style = SOAPBinding.Style.RPC) +public class RPCLitSoapActionGreeterImpl implements WrappedGreeter { + + public String sayHiRequestWrapped(String in) { + return "sayHi"; + } + + public String sayHiRequest2Wrapped(String in) { + return "sayHi2"; + } + +}
systests/uncategorized/src/test/java/org/apache/cxf/systest/soap/SoapActionTest.java+390 −1 modified@@ -19,6 +19,8 @@ package org.apache.cxf.systest.soap; +import javax.xml.ws.BindingProvider; + import org.apache.cxf.Bus; import org.apache.cxf.BusFactory; import org.apache.cxf.binding.soap.Soap12; @@ -27,6 +29,7 @@ import org.apache.cxf.jaxws.JaxWsServerFactoryBean; import org.apache.cxf.testutil.common.TestUtil; import org.apache.hello_world_soap_action.Greeter; +import org.apache.hello_world_soap_action.WrappedGreeter; import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; @@ -35,11 +38,20 @@ public class SoapActionTest extends Assert { static final String PORT1 = TestUtil.getPortNumber(SoapActionTest.class, 1); static final String PORT2 = TestUtil.getPortNumber(SoapActionTest.class, 2); + static final String PORT3 = TestUtil.getPortNumber(SoapActionTest.class, 3); + static final String PORT4 = TestUtil.getPortNumber(SoapActionTest.class, 4); + static final String PORT5 = TestUtil.getPortNumber(SoapActionTest.class, 5); + static final String PORT6 = TestUtil.getPortNumber(SoapActionTest.class, 6); + static final String PORT7 = TestUtil.getPortNumber(SoapActionTest.class, 7); static Bus bus; static String add11 = "http://localhost:" + PORT1 + "/test11"; static String add12 = "http://localhost:" + PORT2 + "/test12"; - + static String add13 = "http://localhost:" + PORT3 + "/testWrapped"; + static String add14 = "http://localhost:" + PORT4 + "/testWrapped12"; + static String add15 = "http://localhost:" + PORT5 + "/testRPCLit"; + static String add16 = "http://localhost:" + PORT6 + "/testRPCEncoded"; + static String add17 = "http://localhost:" + PORT7 + "/testWrappedEncoded"; @BeforeClass public static void createServers() throws Exception { @@ -58,7 +70,40 @@ public static void createServers() throws Exception { config.setVersion(Soap12.getInstance()); sf.setBindingConfig(config); sf.create(); + + sf = new JaxWsServerFactoryBean(); + sf.setServiceBean(new WrappedSoapActionGreeterImpl()); + sf.setAddress(add13); + sf.setBus(bus); + sf.create(); + + sf = new JaxWsServerFactoryBean(); + sf.setServiceBean(new WrappedSoapActionGreeterImpl()); + sf.setAddress(add14); + sf.setBus(bus); + config.setVersion(Soap12.getInstance()); + sf.setBindingConfig(config); + sf.create(); + + sf = new JaxWsServerFactoryBean(); + sf.setServiceBean(new RPCLitSoapActionGreeterImpl()); + sf.setAddress(add15); + sf.setBus(bus); + sf.create(); + + sf = new JaxWsServerFactoryBean(); + sf.setServiceBean(new RPCEncodedSoapActionGreeterImpl()); + sf.setAddress(add16); + sf.setBus(bus); + sf.create(); + + sf = new JaxWsServerFactoryBean(); + sf.setServiceBean(new WrappedEncodedSoapActionGreeterImpl()); + sf.setAddress(add17); + sf.setBus(bus); + sf.create(); } + @AfterClass public static void shutdown() throws Exception { bus.shutdown(true); @@ -93,4 +138,348 @@ public void testSoap12Endpoint() throws Exception { assertEquals("sayHi", greeter.sayHi("test")); assertEquals("sayHi2", greeter.sayHi2("test")); } + + + @Test + public void testBareSoapActionSpoofing() throws Exception { + JaxWsProxyFactoryBean pf = new JaxWsProxyFactoryBean(); + pf.setServiceClass(Greeter.class); + pf.setAddress(add11); + pf.setBus(bus); + Greeter greeter = (Greeter) pf.create(); + + assertEquals("sayHi", greeter.sayHi("test")); + assertEquals("sayHi2", greeter.sayHi2("test")); + + // Now test spoofing attack + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_2" + ); + try { + greeter.sayHi("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test the other operation + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_1" + ); + try { + greeter.sayHi2("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test a SOAP Action that does not exist in the binding + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_UNKNOWN" + ); + try { + greeter.sayHi("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + } + + @Test + public void testBareSoap12ActionSpoofing() throws Exception { + JaxWsProxyFactoryBean pf = new JaxWsProxyFactoryBean(); + pf.setServiceClass(Greeter.class); + pf.setAddress(add12); + SoapBindingConfiguration config = new SoapBindingConfiguration(); + config.setVersion(Soap12.getInstance()); + pf.setBindingConfig(config); + pf.setBus(bus); + Greeter greeter = (Greeter) pf.create(); + + assertEquals("sayHi", greeter.sayHi("test")); + assertEquals("sayHi2", greeter.sayHi2("test")); + + // Now test spoofing attack + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_2" + ); + try { + greeter.sayHi("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test the other operation + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_1" + ); + try { + greeter.sayHi2("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test a SOAP Action that does not exist in the binding + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_UNKNOWN" + ); + try { + greeter.sayHi("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + } + + @Test + public void testWrappedSoapActionSpoofing() throws Exception { + JaxWsProxyFactoryBean pf = new JaxWsProxyFactoryBean(); + pf.setServiceClass(WrappedGreeter.class); + pf.setAddress(add13); + pf.setBus(bus); + WrappedGreeter greeter = (WrappedGreeter) pf.create(); + + assertEquals("sayHi", greeter.sayHiRequestWrapped("test")); + assertEquals("sayHi2", greeter.sayHiRequest2Wrapped("test")); + + // Now test spoofing attack + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_2" + ); + try { + greeter.sayHiRequestWrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test the other operation + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_1" + ); + try { + greeter.sayHiRequest2Wrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test a SOAP Action that does not exist in the binding + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_UNKNOWN" + ); + try { + greeter.sayHiRequestWrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + } + + @Test + public void testWrappedSoap12ActionSpoofing() throws Exception { + JaxWsProxyFactoryBean pf = new JaxWsProxyFactoryBean(); + pf.setServiceClass(WrappedGreeter.class); + pf.setAddress(add14); + SoapBindingConfiguration config = new SoapBindingConfiguration(); + config.setVersion(Soap12.getInstance()); + pf.setBindingConfig(config); + pf.setBus(bus); + WrappedGreeter greeter = (WrappedGreeter) pf.create(); + + assertEquals("sayHi", greeter.sayHiRequestWrapped("test")); + assertEquals("sayHi2", greeter.sayHiRequest2Wrapped("test")); + + // Now test spoofing attack + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_2" + ); + try { + greeter.sayHiRequestWrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test the other operation + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_1" + ); + try { + greeter.sayHiRequest2Wrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test a SOAP Action that does not exist in the binding + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_UNKNOWN" + ); + try { + greeter.sayHiRequestWrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + } + + @Test + public void testRPCLitSoapActionSpoofing() throws Exception { + JaxWsProxyFactoryBean pf = new JaxWsProxyFactoryBean(); + pf.setServiceClass(WrappedGreeter.class); + pf.setAddress(add15); + pf.setBus(bus); + WrappedGreeter greeter = (WrappedGreeter) pf.create(); + + assertEquals("sayHi", greeter.sayHiRequestWrapped("test")); + assertEquals("sayHi2", greeter.sayHiRequest2Wrapped("test")); + + // Now test spoofing attack + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_2" + ); + try { + greeter.sayHiRequestWrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test the other operation + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_1" + ); + try { + greeter.sayHiRequest2Wrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test a SOAP Action that does not exist in the binding + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_UNKNOWN" + ); + try { + greeter.sayHiRequestWrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + } + + @Test + public void testRPCEncodedSoapActionSpoofing() throws Exception { + JaxWsProxyFactoryBean pf = new JaxWsProxyFactoryBean(); + pf.setServiceClass(WrappedGreeter.class); + pf.setAddress(add16); + pf.setBus(bus); + WrappedGreeter greeter = (WrappedGreeter) pf.create(); + + assertEquals("sayHi", greeter.sayHiRequestWrapped("test")); + assertEquals("sayHi2", greeter.sayHiRequest2Wrapped("test")); + + // Now test spoofing attack + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_2" + ); + try { + greeter.sayHiRequestWrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test the other operation + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_1" + ); + try { + greeter.sayHiRequest2Wrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test a SOAP Action that does not exist in the binding + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_UNKNOWN" + ); + try { + greeter.sayHiRequestWrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + } + + @Test + public void testWrappedEncodedSoapActionSpoofing() throws Exception { + JaxWsProxyFactoryBean pf = new JaxWsProxyFactoryBean(); + pf.setServiceClass(WrappedGreeter.class); + pf.setAddress(add17); + pf.setBus(bus); + WrappedGreeter greeter = (WrappedGreeter) pf.create(); + + assertEquals("sayHi", greeter.sayHiRequestWrapped("test")); + assertEquals("sayHi2", greeter.sayHiRequest2Wrapped("test")); + + // Now test spoofing attack + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_2" + ); + try { + greeter.sayHiRequestWrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test the other operation + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_1" + ); + try { + greeter.sayHiRequest2Wrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test a SOAP Action that does not exist in the binding + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_UNKNOWN" + ); + try { + greeter.sayHiRequestWrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + } + }
systests/uncategorized/src/test/java/org/apache/cxf/systest/soap/WrappedEncodedSoapActionGreeterImpl.java+40 −0 added@@ -0,0 +1,40 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.cxf.systest.soap; + +import javax.jws.WebService; +import javax.jws.soap.SOAPBinding; + +import org.apache.hello_world_soap_action.WrappedGreeter; + +@WebService(endpointInterface = "org.apache.hello_world_soap_action.WrappedGreeter", + serviceName = "WrappedSOAPService") +@SOAPBinding(use = SOAPBinding.Use.ENCODED) +public class WrappedEncodedSoapActionGreeterImpl implements WrappedGreeter { + + public String sayHiRequestWrapped(String in) { + return "sayHi"; + } + + public String sayHiRequest2Wrapped(String in) { + return "sayHi2"; + } + +}
systests/uncategorized/src/test/java/org/apache/cxf/systest/soap/WrappedSoapActionGreeterImpl.java+38 −0 added@@ -0,0 +1,38 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.cxf.systest.soap; + +import javax.jws.WebService; + +import org.apache.hello_world_soap_action.WrappedGreeter; + +@WebService(endpointInterface = "org.apache.hello_world_soap_action.WrappedGreeter", + serviceName = "WrappedSOAPService") +public class WrappedSoapActionGreeterImpl implements WrappedGreeter { + + public String sayHiRequestWrapped(String in) { + return "sayHi"; + } + + public String sayHiRequest2Wrapped(String in) { + return "sayHi2"; + } + +}
testutils/src/main/resources/wsdl/hello_world_soap_action.wsdl+115 −0 modified@@ -26,6 +26,7 @@ xmlns:jms="http://cxf.apache.org/transports/jms" xmlns:tns="http://apache.org/hello_world_soap_action" xmlns:x1="http://apache.org/hello_world_soap_action/types" + xmlns:x2="http://apache.org/hello_world_soap_action/types/wrapped" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" targetNamespace="http://apache.org/hello_world_soap_action" name="HelloWorld"> @@ -37,6 +38,36 @@ <element name="text" type="xsd:string" /> <element name="text2" type="xsd:string" /> </schema> + <xsd:schema targetNamespace="http://apache.org/hello_world_soap_action/types/wrapped"> + <xsd:element name="sayHiRequestWrapped"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="wrappedText" type="xsd:string" /> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + <xsd:element name="sayHiResponseWrapped"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="wrappedTextResponse" type="xsd:string" /> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + <xsd:element name="sayHiRequest2Wrapped"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="wrappedText" type="xsd:string" /> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + <xsd:element name="sayHiResponse2Wrapped"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="wrappedTextResponse" type="xsd:string" /> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + </xsd:schema> </wsdl:types> <wsdl:message name="sayHiRequest"> <wsdl:part name="in" element="x1:text" /> @@ -50,6 +81,19 @@ <wsdl:message name="sayHiResponse2"> <wsdl:part name="out" element="x1:text" /> </wsdl:message> + + <wsdl:message name="sayHiRequestWrapped"> + <wsdl:part element="x2:sayHiRequestWrapped" name="parameters" /> + </wsdl:message> + <wsdl:message name="sayHiResponseWrapped"> + <wsdl:part element="x2:sayHiResponseWrapped" name="parameters" /> + </wsdl:message> + <wsdl:message name="sayHiRequest2Wrapped"> + <wsdl:part element="x2:sayHiRequest2Wrapped" name="parameters" /> + </wsdl:message> + <wsdl:message name="sayHiResponse2Wrapped"> + <wsdl:part element="x2:sayHiResponse2Wrapped" name="parameters" /> + </wsdl:message> <wsdl:portType name="Greeter"> <wsdl:operation name="sayHi"> @@ -63,6 +107,19 @@ </wsdl:operation> </wsdl:portType> + + <wsdl:portType name="WrappedGreeter"> + <wsdl:operation name="sayHiRequestWrapped"> + <wsdl:input message="tns:sayHiRequestWrapped" /> + <wsdl:output message="tns:sayHiResponseWrapped" /> + </wsdl:operation> + + <wsdl:operation name="sayHiRequest2Wrapped"> + <wsdl:input message="tns:sayHiRequest2Wrapped" /> + <wsdl:output message="tns:sayHiResponse2Wrapped" /> + </wsdl:operation> + </wsdl:portType> + <wsdl:binding name="Greeter_SOAPBinding" type="tns:Greeter"> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" /> @@ -86,6 +143,7 @@ </wsdl:operation> </wsdl:binding> + <wsdl:binding name="Greeter_SOAP12Binding" type="tns:Greeter"> <soap12:binding style="document" transport="http://www.w3.org/2003/05/soap/bindings/HTTP/" /> @@ -109,6 +167,53 @@ </wsdl:operation> </wsdl:binding> + + <wsdl:binding name="Greeter_WrappedSOAPBinding" type="tns:WrappedGreeter"> + <soap:binding style="document" + transport="http://schemas.xmlsoap.org/soap/http" /> + <wsdl:operation name="sayHiRequestWrapped"> + <soap:operation soapAction="SAY_HI_1" /> + <wsdl:input> + <soap:body use="literal" /> + </wsdl:input> + <wsdl:output> + <soap:body use="literal" /> + </wsdl:output> + </wsdl:operation> + <wsdl:operation name="sayHiRequest2Wrapped"> + <soap:operation soapAction="SAY_HI_2" /> + <wsdl:input> + <soap:body use="literal" /> + </wsdl:input> + <wsdl:output> + <soap:body use="literal" /> + </wsdl:output> + </wsdl:operation> + </wsdl:binding> + + <wsdl:binding name="Greeter_WrappedSOAP12Binding" type="tns:WrappedGreeter"> + <soap12:binding style="document" + transport="http://www.w3.org/2003/05/soap/bindings/HTTP/" /> + <wsdl:operation name="sayHiRequestWrapped"> + <soap12:operation soapAction="SAY_HI_1" /> + <wsdl:input> + <soap12:body use="literal" /> + </wsdl:input> + <wsdl:output> + <soap12:body use="literal" /> + </wsdl:output> + </wsdl:operation> + <wsdl:operation name="sayHiRequest2Wrapped"> + <soap12:operation soapAction="SAY_HI_2" /> + <wsdl:input> + <soap12:body use="literal" /> + </wsdl:input> + <wsdl:output> + <soap12:body use="literal" /> + </wsdl:output> + </wsdl:operation> + </wsdl:binding> + <wsdl:service name="SOAPService"> <wsdl:port name="SoapPort" binding="tns:Greeter_SOAPBinding"> <soap:address @@ -121,4 +226,14 @@ location="http://localhost:9001/SOAPDocLitService/Soap12Port" /> </wsdl:port> </wsdl:service> + <wsdl:service name="WrappedSOAPService"> + <wsdl:port name="WrappedSoapPort" binding="tns:Greeter_WrappedSOAPBinding"> + <soap:address location="http://localhost:9001/SOAPDocLitService/WrappedSoapPort" /> + </wsdl:port> + </wsdl:service> + <wsdl:service name="WrappedSOAP12Service"> + <wsdl:port name="WrappedSoap12Port" binding="tns:Greeter_WrappedSOAP12Binding"> + <soap:address location="http://localhost:9001/SOAPDocLitService/WrappedSoap12Port" /> + </wsdl:port> + </wsdl:service> </wsdl:definitions>
7230648f9657Merged revisions 1368559 via git cherry-pick from
10 files changed · +760 −21
rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/Messages.properties+1 −0 modified@@ -31,3 +31,4 @@ INVALID_11_VERSION=A SOAP 1.2 message is not valid when sent to a SOAP 1.1 only NO_NAMESPACE=No namespace on "{0}" element. BP_2211_RPCLIT_CANNOT_BE_NULL=Cannot write part {0}. RPC/Literal parts cannot be null. (WS-I BP R2211) UNKNOWN_RPC_LIT_PART=Found element {0} but could not find matching RPC/Literal part +SOAP_ACTION_MISMATCH=The given SOAPAction {0} does not match an operation.
rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/SoapActionInInterceptor.java+52 −14 modified@@ -22,12 +22,14 @@ import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.logging.Logger; import org.apache.cxf.binding.soap.Soap11; import org.apache.cxf.binding.soap.Soap12; import org.apache.cxf.binding.soap.SoapBindingConstants; import org.apache.cxf.binding.soap.SoapMessage; import org.apache.cxf.binding.soap.model.SoapOperationInfo; +import org.apache.cxf.common.logging.LogUtils; import org.apache.cxf.common.util.StringUtils; import org.apache.cxf.endpoint.Endpoint; import org.apache.cxf.helpers.CastUtils; @@ -40,6 +42,8 @@ public class SoapActionInInterceptor extends AbstractSoapInterceptor { + private static final Logger LOG = LogUtils.getL7dLogger(SoapActionInInterceptor.class); + public SoapActionInInterceptor() { super(Phase.READ); addAfter(ReadHeadersInterceptor.class.getName()); @@ -91,6 +95,10 @@ public static String getSoapAction(Message m) { } public void handleMessage(SoapMessage message) throws Fault { + if (isRequestor(message)) { + return; + } + String action = getSoapAction(message); if (!StringUtils.isEmpty(action)) { getAndSetOperation(message, action); @@ -108,24 +116,54 @@ private void getAndSetOperation(SoapMessage message, String action) { BindingOperationInfo bindingOp = null; - Collection<BindingOperationInfo> bops = ep.getBinding().getBindingInfo().getOperations(); - if (bops == null) { - return; - } - for (BindingOperationInfo boi : bops) { - SoapOperationInfo soi = (SoapOperationInfo) boi.getExtensor(SoapOperationInfo.class); - if (soi != null && action.equals(soi.getAction())) { - if (bindingOp != null) { - //more than one op with the same action, will need to parse normally - return; + Collection<BindingOperationInfo> bops = ep.getEndpointInfo() + .getBinding().getOperations(); + if (bops != null) { + for (BindingOperationInfo boi : bops) { + SoapOperationInfo soi = boi.getExtensor(SoapOperationInfo.class); + if (soi != null && action.equals(soi.getAction())) { + if (bindingOp != null) { + //more than one op with the same action, will need to parse normally + return; + } + bindingOp = boi; } - bindingOp = boi; } } - if (bindingOp != null) { - ex.put(BindingOperationInfo.class, bindingOp); - ex.put(OperationInfo.class, bindingOp.getOperationInfo()); + + if (bindingOp == null) { + //we didn't match the an operation, we'll try again later to make + //sure the incoming message did end up matching an operation. + //This could occur in some cases like WS-RM and WS-SecConv that will + //intercept the message with a new endpoint/operation + message.getInterceptorChain().add(new SoapActionInAttemptTwoInterceptor()); + return; + } + + ex.put(BindingOperationInfo.class, bindingOp); + ex.put(OperationInfo.class, bindingOp.getOperationInfo()); + } + + public static class SoapActionInAttemptTwoInterceptor extends AbstractSoapInterceptor { + public SoapActionInAttemptTwoInterceptor() { + super(Phase.PRE_LOGICAL); + } + public void handleMessage(SoapMessage message) throws Fault { + BindingOperationInfo boi = message.getExchange().getBindingOperationInfo(); + if (boi == null) { + return; + } + String action = getSoapAction(message); + if (StringUtils.isEmpty(action)) { + return; + } + SoapOperationInfo soi = boi.getExtensor(SoapOperationInfo.class); + if (soi == null || action.equals(soi.getAction())) { + return; + } + throw new Fault("SOAP_ACTION_MISMATCH", LOG, null, action); } } + }
rt/core/src/main/java/org/apache/cxf/interceptor/DocLiteralInInterceptor.java+43 −6 modified@@ -192,12 +192,11 @@ public void handleMessage(Message message) { } else { p = findMessagePart(exchange, operations, elName, client, paramNum, message); } - - if (p == null) { - throw new Fault(new org.apache.cxf.common.i18n.Message("NO_PART_FOUND", LOG, elName), - Fault.FAULT_CODE_CLIENT); - } - + + //Make sure the elName found on the wire is actually OK for + //the purpose we need it + validatePart(p, elName, si); + o = dr.read(p, xmlReader); if (Boolean.TRUE.equals(si.getProperty("soap.force.doclit.bare")) && parameters.isEmpty()) { @@ -224,6 +223,44 @@ public void handleMessage(Message message) { } } + private void validatePart(MessagePartInfo p, QName elName, ServiceInfo si) { + if (p == null) { + throw new Fault(new org.apache.cxf.common.i18n.Message("NO_PART_FOUND", LOG, elName), + Fault.FAULT_CODE_CLIENT); + + } + + Boolean synth = Boolean.FALSE; + if (p.getMessageInfo() != null && p.getMessageInfo().getOperation() != null) { + OperationInfo op = p.getMessageInfo().getOperation(); + Boolean b = (Boolean)op.getProperty("operation.is.synthetic"); + if (b != null) { + synth = b; + } + } + if (si != null && Boolean.TRUE.equals(si.getProperty("soap.force.doclit.bare"))) { + // something like a Provider service or similar that is forcing a + // doc/lit/bare on an endpoint that may not really be doc/lit/bare. + // we need to just let these through per spec so the endpoint + // can process it + synth = true; + } + if (p.isElement()) { + if (p.getConcreteName() != null + && !elName.equals(p.getConcreteName()) + && !Boolean.TRUE.equals(synth)) { + throw new Fault("UNEXPECTED_ELEMENT", LOG, null, elName, + p.getConcreteName()); + } + } else { + if (!(elName.equals(p.getName()) || elName.equals(p.getConcreteName())) + && !Boolean.TRUE.equals(synth)) { + throw new Fault("UNEXPECTED_ELEMENT", LOG, null, elName, + p.getConcreteName()); + } + } + } + private void getPara(DepthXMLStreamReader xmlReader, DataReader<XMLStreamReader> dr, MessageContentsList parameters,
rt/core/src/main/java/org/apache/cxf/interceptor/Messages.properties+1 −0 modified@@ -40,4 +40,5 @@ COULD_NOT_FIND_SEICLASS=Could not find the class: {0} EXCEPTION_WHILE_WRITING_FAULT = Exception occurred while writing fault. EXCEPTION_WHILE_CREATING_EXCEPTION = Exception occurred while creating exception: {0} UNEXPECTED_WRAPPER_ELEMENT = Unexpected wrapper element {0} found. Expected {1}. +UNEXPECTED_ELEMENT = Unexpected element {0} found. Expected {1}.
systests/uncategorized/src/test/java/org/apache/cxf/systest/soap/RPCEncodedSoapActionGreeterImpl.java+40 −0 added@@ -0,0 +1,40 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.cxf.systest.soap; + +import javax.jws.WebService; +import javax.jws.soap.SOAPBinding; + +import org.apache.hello_world_soap_action.WrappedGreeter; + +@WebService(endpointInterface = "org.apache.hello_world_soap_action.WrappedGreeter", +serviceName = "WrappedSOAPService") +@SOAPBinding(style = SOAPBinding.Style.RPC, use = SOAPBinding.Use.ENCODED) +public class RPCEncodedSoapActionGreeterImpl implements WrappedGreeter { + + public String sayHiRequestWrapped(String in) { + return "sayHi"; + } + + public String sayHiRequest2Wrapped(String in) { + return "sayHi2"; + } + +}
systests/uncategorized/src/test/java/org/apache/cxf/systest/soap/RPCLitSoapActionGreeterImpl.java+40 −0 added@@ -0,0 +1,40 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.cxf.systest.soap; + +import javax.jws.WebService; +import javax.jws.soap.SOAPBinding; + +import org.apache.hello_world_soap_action.WrappedGreeter; + +@WebService(endpointInterface = "org.apache.hello_world_soap_action.WrappedGreeter", +serviceName = "WrappedSOAPService") +@SOAPBinding(style = SOAPBinding.Style.RPC) +public class RPCLitSoapActionGreeterImpl implements WrappedGreeter { + + public String sayHiRequestWrapped(String in) { + return "sayHi"; + } + + public String sayHiRequest2Wrapped(String in) { + return "sayHi2"; + } + +}
systests/uncategorized/src/test/java/org/apache/cxf/systest/soap/SoapActionTest.java+390 −1 modified@@ -19,6 +19,8 @@ package org.apache.cxf.systest.soap; +import javax.xml.ws.BindingProvider; + import org.apache.cxf.Bus; import org.apache.cxf.BusFactory; import org.apache.cxf.binding.soap.Soap12; @@ -27,6 +29,7 @@ import org.apache.cxf.jaxws.JaxWsServerFactoryBean; import org.apache.cxf.testutil.common.TestUtil; import org.apache.hello_world_soap_action.Greeter; +import org.apache.hello_world_soap_action.WrappedGreeter; import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; @@ -35,11 +38,20 @@ public class SoapActionTest extends Assert { static final String PORT1 = TestUtil.getPortNumber(SoapActionTest.class, 1); static final String PORT2 = TestUtil.getPortNumber(SoapActionTest.class, 2); + static final String PORT3 = TestUtil.getPortNumber(SoapActionTest.class, 3); + static final String PORT4 = TestUtil.getPortNumber(SoapActionTest.class, 4); + static final String PORT5 = TestUtil.getPortNumber(SoapActionTest.class, 5); + static final String PORT6 = TestUtil.getPortNumber(SoapActionTest.class, 6); + static final String PORT7 = TestUtil.getPortNumber(SoapActionTest.class, 7); static Bus bus; static String add11 = "http://localhost:" + PORT1 + "/test11"; static String add12 = "http://localhost:" + PORT2 + "/test12"; - + static String add13 = "http://localhost:" + PORT3 + "/testWrapped"; + static String add14 = "http://localhost:" + PORT4 + "/testWrapped12"; + static String add15 = "http://localhost:" + PORT5 + "/testRPCLit"; + static String add16 = "http://localhost:" + PORT6 + "/testRPCEncoded"; + static String add17 = "http://localhost:" + PORT7 + "/testWrappedEncoded"; @BeforeClass public static void createServers() throws Exception { @@ -58,7 +70,40 @@ public static void createServers() throws Exception { config.setVersion(Soap12.getInstance()); sf.setBindingConfig(config); sf.create(); + + sf = new JaxWsServerFactoryBean(); + sf.setServiceBean(new WrappedSoapActionGreeterImpl()); + sf.setAddress(add13); + sf.setBus(bus); + sf.create(); + + sf = new JaxWsServerFactoryBean(); + sf.setServiceBean(new WrappedSoapActionGreeterImpl()); + sf.setAddress(add14); + sf.setBus(bus); + config.setVersion(Soap12.getInstance()); + sf.setBindingConfig(config); + sf.create(); + + sf = new JaxWsServerFactoryBean(); + sf.setServiceBean(new RPCLitSoapActionGreeterImpl()); + sf.setAddress(add15); + sf.setBus(bus); + sf.create(); + + sf = new JaxWsServerFactoryBean(); + sf.setServiceBean(new RPCEncodedSoapActionGreeterImpl()); + sf.setAddress(add16); + sf.setBus(bus); + sf.create(); + + sf = new JaxWsServerFactoryBean(); + sf.setServiceBean(new WrappedEncodedSoapActionGreeterImpl()); + sf.setAddress(add17); + sf.setBus(bus); + sf.create(); } + @AfterClass public static void shutdown() throws Exception { bus.shutdown(true); @@ -93,4 +138,348 @@ public void testSoap12Endpoint() throws Exception { assertEquals("sayHi", greeter.sayHi("test")); assertEquals("sayHi2", greeter.sayHi2("test")); } + + + @Test + public void testBareSoapActionSpoofing() throws Exception { + JaxWsProxyFactoryBean pf = new JaxWsProxyFactoryBean(); + pf.setServiceClass(Greeter.class); + pf.setAddress(add11); + pf.setBus(bus); + Greeter greeter = (Greeter) pf.create(); + + assertEquals("sayHi", greeter.sayHi("test")); + assertEquals("sayHi2", greeter.sayHi2("test")); + + // Now test spoofing attack + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_2" + ); + try { + greeter.sayHi("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test the other operation + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_1" + ); + try { + greeter.sayHi2("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test a SOAP Action that does not exist in the binding + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_UNKNOWN" + ); + try { + greeter.sayHi("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + } + + @Test + public void testBareSoap12ActionSpoofing() throws Exception { + JaxWsProxyFactoryBean pf = new JaxWsProxyFactoryBean(); + pf.setServiceClass(Greeter.class); + pf.setAddress(add12); + SoapBindingConfiguration config = new SoapBindingConfiguration(); + config.setVersion(Soap12.getInstance()); + pf.setBindingConfig(config); + pf.setBus(bus); + Greeter greeter = (Greeter) pf.create(); + + assertEquals("sayHi", greeter.sayHi("test")); + assertEquals("sayHi2", greeter.sayHi2("test")); + + // Now test spoofing attack + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_2" + ); + try { + greeter.sayHi("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test the other operation + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_1" + ); + try { + greeter.sayHi2("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test a SOAP Action that does not exist in the binding + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_UNKNOWN" + ); + try { + greeter.sayHi("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + } + + @Test + public void testWrappedSoapActionSpoofing() throws Exception { + JaxWsProxyFactoryBean pf = new JaxWsProxyFactoryBean(); + pf.setServiceClass(WrappedGreeter.class); + pf.setAddress(add13); + pf.setBus(bus); + WrappedGreeter greeter = (WrappedGreeter) pf.create(); + + assertEquals("sayHi", greeter.sayHiRequestWrapped("test")); + assertEquals("sayHi2", greeter.sayHiRequest2Wrapped("test")); + + // Now test spoofing attack + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_2" + ); + try { + greeter.sayHiRequestWrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test the other operation + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_1" + ); + try { + greeter.sayHiRequest2Wrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test a SOAP Action that does not exist in the binding + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_UNKNOWN" + ); + try { + greeter.sayHiRequestWrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + } + + @Test + public void testWrappedSoap12ActionSpoofing() throws Exception { + JaxWsProxyFactoryBean pf = new JaxWsProxyFactoryBean(); + pf.setServiceClass(WrappedGreeter.class); + pf.setAddress(add14); + SoapBindingConfiguration config = new SoapBindingConfiguration(); + config.setVersion(Soap12.getInstance()); + pf.setBindingConfig(config); + pf.setBus(bus); + WrappedGreeter greeter = (WrappedGreeter) pf.create(); + + assertEquals("sayHi", greeter.sayHiRequestWrapped("test")); + assertEquals("sayHi2", greeter.sayHiRequest2Wrapped("test")); + + // Now test spoofing attack + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_2" + ); + try { + greeter.sayHiRequestWrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test the other operation + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_1" + ); + try { + greeter.sayHiRequest2Wrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test a SOAP Action that does not exist in the binding + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_UNKNOWN" + ); + try { + greeter.sayHiRequestWrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + } + + @Test + public void testRPCLitSoapActionSpoofing() throws Exception { + JaxWsProxyFactoryBean pf = new JaxWsProxyFactoryBean(); + pf.setServiceClass(WrappedGreeter.class); + pf.setAddress(add15); + pf.setBus(bus); + WrappedGreeter greeter = (WrappedGreeter) pf.create(); + + assertEquals("sayHi", greeter.sayHiRequestWrapped("test")); + assertEquals("sayHi2", greeter.sayHiRequest2Wrapped("test")); + + // Now test spoofing attack + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_2" + ); + try { + greeter.sayHiRequestWrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test the other operation + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_1" + ); + try { + greeter.sayHiRequest2Wrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test a SOAP Action that does not exist in the binding + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_UNKNOWN" + ); + try { + greeter.sayHiRequestWrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + } + + @Test + public void testRPCEncodedSoapActionSpoofing() throws Exception { + JaxWsProxyFactoryBean pf = new JaxWsProxyFactoryBean(); + pf.setServiceClass(WrappedGreeter.class); + pf.setAddress(add16); + pf.setBus(bus); + WrappedGreeter greeter = (WrappedGreeter) pf.create(); + + assertEquals("sayHi", greeter.sayHiRequestWrapped("test")); + assertEquals("sayHi2", greeter.sayHiRequest2Wrapped("test")); + + // Now test spoofing attack + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_2" + ); + try { + greeter.sayHiRequestWrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test the other operation + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_1" + ); + try { + greeter.sayHiRequest2Wrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test a SOAP Action that does not exist in the binding + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_UNKNOWN" + ); + try { + greeter.sayHiRequestWrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + } + + @Test + public void testWrappedEncodedSoapActionSpoofing() throws Exception { + JaxWsProxyFactoryBean pf = new JaxWsProxyFactoryBean(); + pf.setServiceClass(WrappedGreeter.class); + pf.setAddress(add17); + pf.setBus(bus); + WrappedGreeter greeter = (WrappedGreeter) pf.create(); + + assertEquals("sayHi", greeter.sayHiRequestWrapped("test")); + assertEquals("sayHi2", greeter.sayHiRequest2Wrapped("test")); + + // Now test spoofing attack + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_2" + ); + try { + greeter.sayHiRequestWrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test the other operation + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_1" + ); + try { + greeter.sayHiRequest2Wrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test a SOAP Action that does not exist in the binding + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_UNKNOWN" + ); + try { + greeter.sayHiRequestWrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + } + }
systests/uncategorized/src/test/java/org/apache/cxf/systest/soap/WrappedEncodedSoapActionGreeterImpl.java+40 −0 added@@ -0,0 +1,40 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.cxf.systest.soap; + +import javax.jws.WebService; +import javax.jws.soap.SOAPBinding; + +import org.apache.hello_world_soap_action.WrappedGreeter; + +@WebService(endpointInterface = "org.apache.hello_world_soap_action.WrappedGreeter", + serviceName = "WrappedSOAPService") +@SOAPBinding(use = SOAPBinding.Use.ENCODED) +public class WrappedEncodedSoapActionGreeterImpl implements WrappedGreeter { + + public String sayHiRequestWrapped(String in) { + return "sayHi"; + } + + public String sayHiRequest2Wrapped(String in) { + return "sayHi2"; + } + +}
systests/uncategorized/src/test/java/org/apache/cxf/systest/soap/WrappedSoapActionGreeterImpl.java+38 −0 added@@ -0,0 +1,38 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.cxf.systest.soap; + +import javax.jws.WebService; + +import org.apache.hello_world_soap_action.WrappedGreeter; + +@WebService(endpointInterface = "org.apache.hello_world_soap_action.WrappedGreeter", + serviceName = "WrappedSOAPService") +public class WrappedSoapActionGreeterImpl implements WrappedGreeter { + + public String sayHiRequestWrapped(String in) { + return "sayHi"; + } + + public String sayHiRequest2Wrapped(String in) { + return "sayHi2"; + } + +}
testutils/src/main/resources/wsdl/hello_world_soap_action.wsdl+115 −0 modified@@ -26,6 +26,7 @@ xmlns:jms="http://cxf.apache.org/transports/jms" xmlns:tns="http://apache.org/hello_world_soap_action" xmlns:x1="http://apache.org/hello_world_soap_action/types" + xmlns:x2="http://apache.org/hello_world_soap_action/types/wrapped" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" targetNamespace="http://apache.org/hello_world_soap_action" name="HelloWorld"> @@ -37,6 +38,36 @@ <element name="text" type="xsd:string" /> <element name="text2" type="xsd:string" /> </schema> + <xsd:schema targetNamespace="http://apache.org/hello_world_soap_action/types/wrapped"> + <xsd:element name="sayHiRequestWrapped"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="wrappedText" type="xsd:string" /> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + <xsd:element name="sayHiResponseWrapped"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="wrappedTextResponse" type="xsd:string" /> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + <xsd:element name="sayHiRequest2Wrapped"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="wrappedText" type="xsd:string" /> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + <xsd:element name="sayHiResponse2Wrapped"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="wrappedTextResponse" type="xsd:string" /> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + </xsd:schema> </wsdl:types> <wsdl:message name="sayHiRequest"> <wsdl:part name="in" element="x1:text" /> @@ -50,6 +81,19 @@ <wsdl:message name="sayHiResponse2"> <wsdl:part name="out" element="x1:text" /> </wsdl:message> + + <wsdl:message name="sayHiRequestWrapped"> + <wsdl:part element="x2:sayHiRequestWrapped" name="parameters" /> + </wsdl:message> + <wsdl:message name="sayHiResponseWrapped"> + <wsdl:part element="x2:sayHiResponseWrapped" name="parameters" /> + </wsdl:message> + <wsdl:message name="sayHiRequest2Wrapped"> + <wsdl:part element="x2:sayHiRequest2Wrapped" name="parameters" /> + </wsdl:message> + <wsdl:message name="sayHiResponse2Wrapped"> + <wsdl:part element="x2:sayHiResponse2Wrapped" name="parameters" /> + </wsdl:message> <wsdl:portType name="Greeter"> <wsdl:operation name="sayHi"> @@ -63,6 +107,19 @@ </wsdl:operation> </wsdl:portType> + + <wsdl:portType name="WrappedGreeter"> + <wsdl:operation name="sayHiRequestWrapped"> + <wsdl:input message="tns:sayHiRequestWrapped" /> + <wsdl:output message="tns:sayHiResponseWrapped" /> + </wsdl:operation> + + <wsdl:operation name="sayHiRequest2Wrapped"> + <wsdl:input message="tns:sayHiRequest2Wrapped" /> + <wsdl:output message="tns:sayHiResponse2Wrapped" /> + </wsdl:operation> + </wsdl:portType> + <wsdl:binding name="Greeter_SOAPBinding" type="tns:Greeter"> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" /> @@ -86,6 +143,7 @@ </wsdl:operation> </wsdl:binding> + <wsdl:binding name="Greeter_SOAP12Binding" type="tns:Greeter"> <soap12:binding style="document" transport="http://www.w3.org/2003/05/soap/bindings/HTTP/" /> @@ -109,6 +167,53 @@ </wsdl:operation> </wsdl:binding> + + <wsdl:binding name="Greeter_WrappedSOAPBinding" type="tns:WrappedGreeter"> + <soap:binding style="document" + transport="http://schemas.xmlsoap.org/soap/http" /> + <wsdl:operation name="sayHiRequestWrapped"> + <soap:operation soapAction="SAY_HI_1" /> + <wsdl:input> + <soap:body use="literal" /> + </wsdl:input> + <wsdl:output> + <soap:body use="literal" /> + </wsdl:output> + </wsdl:operation> + <wsdl:operation name="sayHiRequest2Wrapped"> + <soap:operation soapAction="SAY_HI_2" /> + <wsdl:input> + <soap:body use="literal" /> + </wsdl:input> + <wsdl:output> + <soap:body use="literal" /> + </wsdl:output> + </wsdl:operation> + </wsdl:binding> + + <wsdl:binding name="Greeter_WrappedSOAP12Binding" type="tns:WrappedGreeter"> + <soap12:binding style="document" + transport="http://www.w3.org/2003/05/soap/bindings/HTTP/" /> + <wsdl:operation name="sayHiRequestWrapped"> + <soap12:operation soapAction="SAY_HI_1" /> + <wsdl:input> + <soap12:body use="literal" /> + </wsdl:input> + <wsdl:output> + <soap12:body use="literal" /> + </wsdl:output> + </wsdl:operation> + <wsdl:operation name="sayHiRequest2Wrapped"> + <soap12:operation soapAction="SAY_HI_2" /> + <wsdl:input> + <soap12:body use="literal" /> + </wsdl:input> + <wsdl:output> + <soap12:body use="literal" /> + </wsdl:output> + </wsdl:operation> + </wsdl:binding> + <wsdl:service name="SOAPService"> <wsdl:port name="SoapPort" binding="tns:Greeter_SOAPBinding"> <soap:address @@ -121,4 +226,14 @@ location="http://localhost:9001/SOAPDocLitService/Soap12Port" /> </wsdl:port> </wsdl:service> + <wsdl:service name="WrappedSOAPService"> + <wsdl:port name="WrappedSoapPort" binding="tns:Greeter_WrappedSOAPBinding"> + <soap:address location="http://localhost:9001/SOAPDocLitService/WrappedSoapPort" /> + </wsdl:port> + </wsdl:service> + <wsdl:service name="WrappedSOAP12Service"> + <wsdl:port name="WrappedSoap12Port" binding="tns:Greeter_WrappedSOAP12Binding"> + <soap:address location="http://localhost:9001/SOAPDocLitService/WrappedSoap12Port" /> + </wsdl:port> + </wsdl:service> </wsdl:definitions>
878fe37f0b09Merged revisions 1368559 via git cherry-pick from
10 files changed · +759 −20
api/src/main/java/org/apache/cxf/interceptor/DocLiteralInInterceptor.java+43 −6 modified@@ -191,12 +191,11 @@ public void handleMessage(Message message) { } else { p = findMessagePart(exchange, operations, elName, client, paramNum, message); } - - if (p == null) { - throw new Fault(new org.apache.cxf.common.i18n.Message("NO_PART_FOUND", LOG, elName), - Fault.FAULT_CODE_CLIENT); - } - + + //Make sure the elName found on the wire is actually OK for + //the purpose we need it + validatePart(p, elName, si); + o = dr.read(p, xmlReader); if (Boolean.TRUE.equals(si.getProperty("soap.force.doclit.bare")) && parameters.isEmpty()) { @@ -223,6 +222,44 @@ public void handleMessage(Message message) { } } + private void validatePart(MessagePartInfo p, QName elName, ServiceInfo si) { + if (p == null) { + throw new Fault(new org.apache.cxf.common.i18n.Message("NO_PART_FOUND", LOG, elName), + Fault.FAULT_CODE_CLIENT); + + } + + Boolean synth = Boolean.FALSE; + if (p.getMessageInfo() != null && p.getMessageInfo().getOperation() != null) { + OperationInfo op = p.getMessageInfo().getOperation(); + Boolean b = (Boolean)op.getProperty("operation.is.synthetic"); + if (b != null) { + synth = b; + } + } + if (si != null && Boolean.TRUE.equals(si.getProperty("soap.force.doclit.bare"))) { + // something like a Provider service or similar that is forcing a + // doc/lit/bare on an endpoint that may not really be doc/lit/bare. + // we need to just let these through per spec so the endpoint + // can process it + synth = true; + } + if (p.isElement()) { + if (p.getConcreteName() != null + && !elName.equals(p.getConcreteName()) + && !Boolean.TRUE.equals(synth)) { + throw new Fault("UNEXPECTED_ELEMENT", LOG, null, elName, + p.getConcreteName()); + } + } else { + if (!(elName.equals(p.getName()) || elName.equals(p.getConcreteName())) + && !Boolean.TRUE.equals(synth)) { + throw new Fault("UNEXPECTED_ELEMENT", LOG, null, elName, + p.getConcreteName()); + } + } + } + private void getPara(DepthXMLStreamReader xmlReader, DataReader<XMLStreamReader> dr, MessageContentsList parameters,
api/src/main/java/org/apache/cxf/interceptor/Messages.properties+1 −0 modified@@ -40,4 +40,5 @@ COULD_NOT_FIND_SEICLASS=Could not find the class: {0} EXCEPTION_WHILE_WRITING_FAULT = Exception occurred while writing fault. EXCEPTION_WHILE_CREATING_EXCEPTION = Exception occurred while creating exception: {0} UNEXPECTED_WRAPPER_ELEMENT = Unexpected wrapper element {0} found. Expected {1}. +UNEXPECTED_ELEMENT = Unexpected element {0} found. Expected {1}.
rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/Messages.properties+1 −0 modified@@ -31,3 +31,4 @@ INVALID_11_VERSION=A SOAP 1.2 message is not valid when sent to a SOAP 1.1 only NO_NAMESPACE=No namespace on "{0}" element. BP_2211_RPCLIT_CANNOT_BE_NULL=Cannot write part {0}. RPC/Literal parts cannot be null. (WS-I BP R2211) UNKNOWN_RPC_LIT_PART=Found element {0} but could not find matching RPC/Literal part +SOAP_ACTION_MISMATCH=The given SOAPAction {0} does not match an operation.
rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/SoapActionInInterceptor.java+51 −13 modified@@ -22,12 +22,14 @@ import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.logging.Logger; import org.apache.cxf.binding.soap.Soap11; import org.apache.cxf.binding.soap.Soap12; import org.apache.cxf.binding.soap.SoapBindingConstants; import org.apache.cxf.binding.soap.SoapMessage; import org.apache.cxf.binding.soap.model.SoapOperationInfo; +import org.apache.cxf.common.logging.LogUtils; import org.apache.cxf.common.util.StringUtils; import org.apache.cxf.endpoint.Endpoint; import org.apache.cxf.helpers.CastUtils; @@ -40,6 +42,8 @@ public class SoapActionInInterceptor extends AbstractSoapInterceptor { + private static final Logger LOG = LogUtils.getL7dLogger(SoapActionInInterceptor.class); + public SoapActionInInterceptor() { super(Phase.READ); addAfter(ReadHeadersInterceptor.class.getName()); @@ -91,6 +95,10 @@ public static String getSoapAction(Message m) { } public void handleMessage(SoapMessage message) throws Fault { + if (isRequestor(message)) { + return; + } + String action = getSoapAction(message); if (!StringUtils.isEmpty(action)) { getAndSetOperation(message, action); @@ -108,24 +116,54 @@ private void getAndSetOperation(SoapMessage message, String action) { BindingOperationInfo bindingOp = null; - Collection<BindingOperationInfo> bops = ep.getBinding().getBindingInfo().getOperations(); - if (bops == null) { + Collection<BindingOperationInfo> bops = ep.getEndpointInfo() + .getBinding().getOperations(); + if (bops != null) { + for (BindingOperationInfo boi : bops) { + SoapOperationInfo soi = boi.getExtensor(SoapOperationInfo.class); + if (soi != null && action.equals(soi.getAction())) { + if (bindingOp != null) { + //more than one op with the same action, will need to parse normally + return; + } + bindingOp = boi; + } + } + } + + if (bindingOp == null) { + //we didn't match the an operation, we'll try again later to make + //sure the incoming message did end up matching an operation. + //This could occur in some cases like WS-RM and WS-SecConv that will + //intercept the message with a new endpoint/operation + message.getInterceptorChain().add(new SoapActionInAttemptTwoInterceptor()); return; } - for (BindingOperationInfo boi : bops) { + + ex.put(BindingOperationInfo.class, bindingOp); + ex.put(OperationInfo.class, bindingOp.getOperationInfo()); + } + + public static class SoapActionInAttemptTwoInterceptor extends AbstractSoapInterceptor { + public SoapActionInAttemptTwoInterceptor() { + super(Phase.PRE_LOGICAL); + } + public void handleMessage(SoapMessage message) throws Fault { + BindingOperationInfo boi = message.getExchange().getBindingOperationInfo(); + if (boi == null) { + return; + } + String action = getSoapAction(message); + if (StringUtils.isEmpty(action)) { + return; + } SoapOperationInfo soi = boi.getExtensor(SoapOperationInfo.class); - if (soi != null && action.equals(soi.getAction())) { - if (bindingOp != null) { - //more than one op with the same action, will need to parse normally - return; - } - bindingOp = boi; + if (soi == null || action.equals(soi.getAction())) { + return; } - } - if (bindingOp != null) { - ex.put(BindingOperationInfo.class, bindingOp); - ex.put(OperationInfo.class, bindingOp.getOperationInfo()); + throw new Fault("SOAP_ACTION_MISMATCH", LOG, null, action); } } + }
systests/uncategorized/src/test/java/org/apache/cxf/systest/soap/RPCEncodedSoapActionGreeterImpl.java+40 −0 added@@ -0,0 +1,40 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.cxf.systest.soap; + +import javax.jws.WebService; +import javax.jws.soap.SOAPBinding; + +import org.apache.hello_world_soap_action.WrappedGreeter; + +@WebService(endpointInterface = "org.apache.hello_world_soap_action.WrappedGreeter", +serviceName = "WrappedSOAPService") +@SOAPBinding(style = SOAPBinding.Style.RPC, use = SOAPBinding.Use.ENCODED) +public class RPCEncodedSoapActionGreeterImpl implements WrappedGreeter { + + public String sayHiRequestWrapped(String in) { + return "sayHi"; + } + + public String sayHiRequest2Wrapped(String in) { + return "sayHi2"; + } + +}
systests/uncategorized/src/test/java/org/apache/cxf/systest/soap/RPCLitSoapActionGreeterImpl.java+40 −0 added@@ -0,0 +1,40 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.cxf.systest.soap; + +import javax.jws.WebService; +import javax.jws.soap.SOAPBinding; + +import org.apache.hello_world_soap_action.WrappedGreeter; + +@WebService(endpointInterface = "org.apache.hello_world_soap_action.WrappedGreeter", +serviceName = "WrappedSOAPService") +@SOAPBinding(style = SOAPBinding.Style.RPC) +public class RPCLitSoapActionGreeterImpl implements WrappedGreeter { + + public String sayHiRequestWrapped(String in) { + return "sayHi"; + } + + public String sayHiRequest2Wrapped(String in) { + return "sayHi2"; + } + +}
systests/uncategorized/src/test/java/org/apache/cxf/systest/soap/SoapActionTest.java+390 −1 modified@@ -19,6 +19,8 @@ package org.apache.cxf.systest.soap; +import javax.xml.ws.BindingProvider; + import org.apache.cxf.Bus; import org.apache.cxf.BusFactory; import org.apache.cxf.binding.soap.Soap12; @@ -27,6 +29,7 @@ import org.apache.cxf.jaxws.JaxWsServerFactoryBean; import org.apache.cxf.testutil.common.TestUtil; import org.apache.hello_world_soap_action.Greeter; +import org.apache.hello_world_soap_action.WrappedGreeter; import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; @@ -35,11 +38,20 @@ public class SoapActionTest extends Assert { static final String PORT1 = TestUtil.getPortNumber(SoapActionTest.class, 1); static final String PORT2 = TestUtil.getPortNumber(SoapActionTest.class, 2); + static final String PORT3 = TestUtil.getPortNumber(SoapActionTest.class, 3); + static final String PORT4 = TestUtil.getPortNumber(SoapActionTest.class, 4); + static final String PORT5 = TestUtil.getPortNumber(SoapActionTest.class, 5); + static final String PORT6 = TestUtil.getPortNumber(SoapActionTest.class, 6); + static final String PORT7 = TestUtil.getPortNumber(SoapActionTest.class, 7); static Bus bus; static String add11 = "http://localhost:" + PORT1 + "/test11"; static String add12 = "http://localhost:" + PORT2 + "/test12"; - + static String add13 = "http://localhost:" + PORT3 + "/testWrapped"; + static String add14 = "http://localhost:" + PORT4 + "/testWrapped12"; + static String add15 = "http://localhost:" + PORT5 + "/testRPCLit"; + static String add16 = "http://localhost:" + PORT6 + "/testRPCEncoded"; + static String add17 = "http://localhost:" + PORT7 + "/testWrappedEncoded"; @BeforeClass public static void createServers() throws Exception { @@ -58,7 +70,40 @@ public static void createServers() throws Exception { config.setVersion(Soap12.getInstance()); sf.setBindingConfig(config); sf.create(); + + sf = new JaxWsServerFactoryBean(); + sf.setServiceBean(new WrappedSoapActionGreeterImpl()); + sf.setAddress(add13); + sf.setBus(bus); + sf.create(); + + sf = new JaxWsServerFactoryBean(); + sf.setServiceBean(new WrappedSoapActionGreeterImpl()); + sf.setAddress(add14); + sf.setBus(bus); + config.setVersion(Soap12.getInstance()); + sf.setBindingConfig(config); + sf.create(); + + sf = new JaxWsServerFactoryBean(); + sf.setServiceBean(new RPCLitSoapActionGreeterImpl()); + sf.setAddress(add15); + sf.setBus(bus); + sf.create(); + + sf = new JaxWsServerFactoryBean(); + sf.setServiceBean(new RPCEncodedSoapActionGreeterImpl()); + sf.setAddress(add16); + sf.setBus(bus); + sf.create(); + + sf = new JaxWsServerFactoryBean(); + sf.setServiceBean(new WrappedEncodedSoapActionGreeterImpl()); + sf.setAddress(add17); + sf.setBus(bus); + sf.create(); } + @AfterClass public static void shutdown() throws Exception { bus.shutdown(true); @@ -93,4 +138,348 @@ public void testSoap12Endpoint() throws Exception { assertEquals("sayHi", greeter.sayHi("test")); assertEquals("sayHi2", greeter.sayHi2("test")); } + + + @Test + public void testBareSoapActionSpoofing() throws Exception { + JaxWsProxyFactoryBean pf = new JaxWsProxyFactoryBean(); + pf.setServiceClass(Greeter.class); + pf.setAddress(add11); + pf.setBus(bus); + Greeter greeter = (Greeter) pf.create(); + + assertEquals("sayHi", greeter.sayHi("test")); + assertEquals("sayHi2", greeter.sayHi2("test")); + + // Now test spoofing attack + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_2" + ); + try { + greeter.sayHi("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test the other operation + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_1" + ); + try { + greeter.sayHi2("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test a SOAP Action that does not exist in the binding + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_UNKNOWN" + ); + try { + greeter.sayHi("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + } + + @Test + public void testBareSoap12ActionSpoofing() throws Exception { + JaxWsProxyFactoryBean pf = new JaxWsProxyFactoryBean(); + pf.setServiceClass(Greeter.class); + pf.setAddress(add12); + SoapBindingConfiguration config = new SoapBindingConfiguration(); + config.setVersion(Soap12.getInstance()); + pf.setBindingConfig(config); + pf.setBus(bus); + Greeter greeter = (Greeter) pf.create(); + + assertEquals("sayHi", greeter.sayHi("test")); + assertEquals("sayHi2", greeter.sayHi2("test")); + + // Now test spoofing attack + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_2" + ); + try { + greeter.sayHi("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test the other operation + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_1" + ); + try { + greeter.sayHi2("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test a SOAP Action that does not exist in the binding + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_UNKNOWN" + ); + try { + greeter.sayHi("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + } + + @Test + public void testWrappedSoapActionSpoofing() throws Exception { + JaxWsProxyFactoryBean pf = new JaxWsProxyFactoryBean(); + pf.setServiceClass(WrappedGreeter.class); + pf.setAddress(add13); + pf.setBus(bus); + WrappedGreeter greeter = (WrappedGreeter) pf.create(); + + assertEquals("sayHi", greeter.sayHiRequestWrapped("test")); + assertEquals("sayHi2", greeter.sayHiRequest2Wrapped("test")); + + // Now test spoofing attack + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_2" + ); + try { + greeter.sayHiRequestWrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test the other operation + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_1" + ); + try { + greeter.sayHiRequest2Wrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test a SOAP Action that does not exist in the binding + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_UNKNOWN" + ); + try { + greeter.sayHiRequestWrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + } + + @Test + public void testWrappedSoap12ActionSpoofing() throws Exception { + JaxWsProxyFactoryBean pf = new JaxWsProxyFactoryBean(); + pf.setServiceClass(WrappedGreeter.class); + pf.setAddress(add14); + SoapBindingConfiguration config = new SoapBindingConfiguration(); + config.setVersion(Soap12.getInstance()); + pf.setBindingConfig(config); + pf.setBus(bus); + WrappedGreeter greeter = (WrappedGreeter) pf.create(); + + assertEquals("sayHi", greeter.sayHiRequestWrapped("test")); + assertEquals("sayHi2", greeter.sayHiRequest2Wrapped("test")); + + // Now test spoofing attack + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_2" + ); + try { + greeter.sayHiRequestWrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test the other operation + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_1" + ); + try { + greeter.sayHiRequest2Wrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test a SOAP Action that does not exist in the binding + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_UNKNOWN" + ); + try { + greeter.sayHiRequestWrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + } + + @Test + public void testRPCLitSoapActionSpoofing() throws Exception { + JaxWsProxyFactoryBean pf = new JaxWsProxyFactoryBean(); + pf.setServiceClass(WrappedGreeter.class); + pf.setAddress(add15); + pf.setBus(bus); + WrappedGreeter greeter = (WrappedGreeter) pf.create(); + + assertEquals("sayHi", greeter.sayHiRequestWrapped("test")); + assertEquals("sayHi2", greeter.sayHiRequest2Wrapped("test")); + + // Now test spoofing attack + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_2" + ); + try { + greeter.sayHiRequestWrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test the other operation + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_1" + ); + try { + greeter.sayHiRequest2Wrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test a SOAP Action that does not exist in the binding + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_UNKNOWN" + ); + try { + greeter.sayHiRequestWrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + } + + @Test + public void testRPCEncodedSoapActionSpoofing() throws Exception { + JaxWsProxyFactoryBean pf = new JaxWsProxyFactoryBean(); + pf.setServiceClass(WrappedGreeter.class); + pf.setAddress(add16); + pf.setBus(bus); + WrappedGreeter greeter = (WrappedGreeter) pf.create(); + + assertEquals("sayHi", greeter.sayHiRequestWrapped("test")); + assertEquals("sayHi2", greeter.sayHiRequest2Wrapped("test")); + + // Now test spoofing attack + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_2" + ); + try { + greeter.sayHiRequestWrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test the other operation + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_1" + ); + try { + greeter.sayHiRequest2Wrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test a SOAP Action that does not exist in the binding + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_UNKNOWN" + ); + try { + greeter.sayHiRequestWrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + } + + @Test + public void testWrappedEncodedSoapActionSpoofing() throws Exception { + JaxWsProxyFactoryBean pf = new JaxWsProxyFactoryBean(); + pf.setServiceClass(WrappedGreeter.class); + pf.setAddress(add17); + pf.setBus(bus); + WrappedGreeter greeter = (WrappedGreeter) pf.create(); + + assertEquals("sayHi", greeter.sayHiRequestWrapped("test")); + assertEquals("sayHi2", greeter.sayHiRequest2Wrapped("test")); + + // Now test spoofing attack + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_2" + ); + try { + greeter.sayHiRequestWrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test the other operation + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_1" + ); + try { + greeter.sayHiRequest2Wrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test a SOAP Action that does not exist in the binding + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_UNKNOWN" + ); + try { + greeter.sayHiRequestWrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + } + }
systests/uncategorized/src/test/java/org/apache/cxf/systest/soap/WrappedEncodedSoapActionGreeterImpl.java+40 −0 added@@ -0,0 +1,40 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.cxf.systest.soap; + +import javax.jws.WebService; +import javax.jws.soap.SOAPBinding; + +import org.apache.hello_world_soap_action.WrappedGreeter; + +@WebService(endpointInterface = "org.apache.hello_world_soap_action.WrappedGreeter", + serviceName = "WrappedSOAPService") +@SOAPBinding(use = SOAPBinding.Use.ENCODED) +public class WrappedEncodedSoapActionGreeterImpl implements WrappedGreeter { + + public String sayHiRequestWrapped(String in) { + return "sayHi"; + } + + public String sayHiRequest2Wrapped(String in) { + return "sayHi2"; + } + +}
systests/uncategorized/src/test/java/org/apache/cxf/systest/soap/WrappedSoapActionGreeterImpl.java+38 −0 added@@ -0,0 +1,38 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.cxf.systest.soap; + +import javax.jws.WebService; + +import org.apache.hello_world_soap_action.WrappedGreeter; + +@WebService(endpointInterface = "org.apache.hello_world_soap_action.WrappedGreeter", + serviceName = "WrappedSOAPService") +public class WrappedSoapActionGreeterImpl implements WrappedGreeter { + + public String sayHiRequestWrapped(String in) { + return "sayHi"; + } + + public String sayHiRequest2Wrapped(String in) { + return "sayHi2"; + } + +}
testutils/src/main/resources/wsdl/hello_world_soap_action.wsdl+115 −0 modified@@ -26,6 +26,7 @@ xmlns:jms="http://cxf.apache.org/transports/jms" xmlns:tns="http://apache.org/hello_world_soap_action" xmlns:x1="http://apache.org/hello_world_soap_action/types" + xmlns:x2="http://apache.org/hello_world_soap_action/types/wrapped" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" targetNamespace="http://apache.org/hello_world_soap_action" name="HelloWorld"> @@ -37,6 +38,36 @@ <element name="text" type="xsd:string" /> <element name="text2" type="xsd:string" /> </schema> + <xsd:schema targetNamespace="http://apache.org/hello_world_soap_action/types/wrapped"> + <xsd:element name="sayHiRequestWrapped"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="wrappedText" type="xsd:string" /> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + <xsd:element name="sayHiResponseWrapped"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="wrappedTextResponse" type="xsd:string" /> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + <xsd:element name="sayHiRequest2Wrapped"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="wrappedText" type="xsd:string" /> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + <xsd:element name="sayHiResponse2Wrapped"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="wrappedTextResponse" type="xsd:string" /> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + </xsd:schema> </wsdl:types> <wsdl:message name="sayHiRequest"> <wsdl:part name="in" element="x1:text" /> @@ -50,6 +81,19 @@ <wsdl:message name="sayHiResponse2"> <wsdl:part name="out" element="x1:text" /> </wsdl:message> + + <wsdl:message name="sayHiRequestWrapped"> + <wsdl:part element="x2:sayHiRequestWrapped" name="parameters" /> + </wsdl:message> + <wsdl:message name="sayHiResponseWrapped"> + <wsdl:part element="x2:sayHiResponseWrapped" name="parameters" /> + </wsdl:message> + <wsdl:message name="sayHiRequest2Wrapped"> + <wsdl:part element="x2:sayHiRequest2Wrapped" name="parameters" /> + </wsdl:message> + <wsdl:message name="sayHiResponse2Wrapped"> + <wsdl:part element="x2:sayHiResponse2Wrapped" name="parameters" /> + </wsdl:message> <wsdl:portType name="Greeter"> <wsdl:operation name="sayHi"> @@ -63,6 +107,19 @@ </wsdl:operation> </wsdl:portType> + + <wsdl:portType name="WrappedGreeter"> + <wsdl:operation name="sayHiRequestWrapped"> + <wsdl:input message="tns:sayHiRequestWrapped" /> + <wsdl:output message="tns:sayHiResponseWrapped" /> + </wsdl:operation> + + <wsdl:operation name="sayHiRequest2Wrapped"> + <wsdl:input message="tns:sayHiRequest2Wrapped" /> + <wsdl:output message="tns:sayHiResponse2Wrapped" /> + </wsdl:operation> + </wsdl:portType> + <wsdl:binding name="Greeter_SOAPBinding" type="tns:Greeter"> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" /> @@ -86,6 +143,7 @@ </wsdl:operation> </wsdl:binding> + <wsdl:binding name="Greeter_SOAP12Binding" type="tns:Greeter"> <soap12:binding style="document" transport="http://www.w3.org/2003/05/soap/bindings/HTTP/" /> @@ -109,6 +167,53 @@ </wsdl:operation> </wsdl:binding> + + <wsdl:binding name="Greeter_WrappedSOAPBinding" type="tns:WrappedGreeter"> + <soap:binding style="document" + transport="http://schemas.xmlsoap.org/soap/http" /> + <wsdl:operation name="sayHiRequestWrapped"> + <soap:operation soapAction="SAY_HI_1" /> + <wsdl:input> + <soap:body use="literal" /> + </wsdl:input> + <wsdl:output> + <soap:body use="literal" /> + </wsdl:output> + </wsdl:operation> + <wsdl:operation name="sayHiRequest2Wrapped"> + <soap:operation soapAction="SAY_HI_2" /> + <wsdl:input> + <soap:body use="literal" /> + </wsdl:input> + <wsdl:output> + <soap:body use="literal" /> + </wsdl:output> + </wsdl:operation> + </wsdl:binding> + + <wsdl:binding name="Greeter_WrappedSOAP12Binding" type="tns:WrappedGreeter"> + <soap12:binding style="document" + transport="http://www.w3.org/2003/05/soap/bindings/HTTP/" /> + <wsdl:operation name="sayHiRequestWrapped"> + <soap12:operation soapAction="SAY_HI_1" /> + <wsdl:input> + <soap12:body use="literal" /> + </wsdl:input> + <wsdl:output> + <soap12:body use="literal" /> + </wsdl:output> + </wsdl:operation> + <wsdl:operation name="sayHiRequest2Wrapped"> + <soap12:operation soapAction="SAY_HI_2" /> + <wsdl:input> + <soap12:body use="literal" /> + </wsdl:input> + <wsdl:output> + <soap12:body use="literal" /> + </wsdl:output> + </wsdl:operation> + </wsdl:binding> + <wsdl:service name="SOAPService"> <wsdl:port name="SoapPort" binding="tns:Greeter_SOAPBinding"> <soap:address @@ -121,4 +226,14 @@ location="http://localhost:9001/SOAPDocLitService/Soap12Port" /> </wsdl:port> </wsdl:service> + <wsdl:service name="WrappedSOAPService"> + <wsdl:port name="WrappedSoapPort" binding="tns:Greeter_WrappedSOAPBinding"> + <soap:address location="http://localhost:9001/SOAPDocLitService/WrappedSoapPort" /> + </wsdl:port> + </wsdl:service> + <wsdl:service name="WrappedSOAP12Service"> + <wsdl:port name="WrappedSoap12Port" binding="tns:Greeter_WrappedSOAP12Binding"> + <soap:address location="http://localhost:9001/SOAPDocLitService/WrappedSoap12Port" /> + </wsdl:port> + </wsdl:service> </wsdl:definitions>
9c70abe28fbfSome improvements to handling SOAP Actions
10 files changed · +759 −20
api/src/main/java/org/apache/cxf/interceptor/DocLiteralInInterceptor.java+43 −6 modified@@ -191,12 +191,11 @@ public void handleMessage(Message message) { } else { p = findMessagePart(exchange, operations, elName, client, paramNum, message); } - - if (p == null) { - throw new Fault(new org.apache.cxf.common.i18n.Message("NO_PART_FOUND", LOG, elName), - Fault.FAULT_CODE_CLIENT); - } - + + //Make sure the elName found on the wire is actually OK for + //the purpose we need it + validatePart(p, elName, si); + o = dr.read(p, xmlReader); if (Boolean.TRUE.equals(si.getProperty("soap.force.doclit.bare")) && parameters.isEmpty()) { @@ -223,6 +222,44 @@ public void handleMessage(Message message) { } } + private void validatePart(MessagePartInfo p, QName elName, ServiceInfo si) { + if (p == null) { + throw new Fault(new org.apache.cxf.common.i18n.Message("NO_PART_FOUND", LOG, elName), + Fault.FAULT_CODE_CLIENT); + + } + + Boolean synth = Boolean.FALSE; + if (p.getMessageInfo() != null && p.getMessageInfo().getOperation() != null) { + OperationInfo op = p.getMessageInfo().getOperation(); + Boolean b = (Boolean)op.getProperty("operation.is.synthetic"); + if (b != null) { + synth = b; + } + } + if (si != null && Boolean.TRUE.equals(si.getProperty("soap.force.doclit.bare"))) { + // something like a Provider service or similar that is forcing a + // doc/lit/bare on an endpoint that may not really be doc/lit/bare. + // we need to just let these through per spec so the endpoint + // can process it + synth = true; + } + if (p.isElement()) { + if (p.getConcreteName() != null + && !elName.equals(p.getConcreteName()) + && !Boolean.TRUE.equals(synth)) { + throw new Fault("UNEXPECTED_ELEMENT", LOG, null, elName, + p.getConcreteName()); + } + } else { + if (!(elName.equals(p.getName()) || elName.equals(p.getConcreteName())) + && !Boolean.TRUE.equals(synth)) { + throw new Fault("UNEXPECTED_ELEMENT", LOG, null, elName, + p.getConcreteName()); + } + } + } + private void getPara(DepthXMLStreamReader xmlReader, DataReader<XMLStreamReader> dr, MessageContentsList parameters,
api/src/main/java/org/apache/cxf/interceptor/Messages.properties+1 −0 modified@@ -40,4 +40,5 @@ COULD_NOT_FIND_SEICLASS=Could not find the class: {0} EXCEPTION_WHILE_WRITING_FAULT = Exception occurred while writing fault. EXCEPTION_WHILE_CREATING_EXCEPTION = Exception occurred while creating exception: {0} UNEXPECTED_WRAPPER_ELEMENT = Unexpected wrapper element {0} found. Expected {1}. +UNEXPECTED_ELEMENT = Unexpected element {0} found. Expected {1}.
rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/Messages.properties+1 −0 modified@@ -31,3 +31,4 @@ INVALID_11_VERSION=A SOAP 1.2 message is not valid when sent to a SOAP 1.1 only NO_NAMESPACE=No namespace on "{0}" element. BP_2211_RPCLIT_CANNOT_BE_NULL=Cannot write part {0}. RPC/Literal parts cannot be null. (WS-I BP R2211) UNKNOWN_RPC_LIT_PART=Found element {0} but could not find matching RPC/Literal part +SOAP_ACTION_MISMATCH=The given SOAPAction {0} does not match an operation.
rt/bindings/soap/src/main/java/org/apache/cxf/binding/soap/interceptor/SoapActionInInterceptor.java+51 −13 modified@@ -22,12 +22,14 @@ import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.logging.Logger; import org.apache.cxf.binding.soap.Soap11; import org.apache.cxf.binding.soap.Soap12; import org.apache.cxf.binding.soap.SoapBindingConstants; import org.apache.cxf.binding.soap.SoapMessage; import org.apache.cxf.binding.soap.model.SoapOperationInfo; +import org.apache.cxf.common.logging.LogUtils; import org.apache.cxf.common.util.StringUtils; import org.apache.cxf.endpoint.Endpoint; import org.apache.cxf.helpers.CastUtils; @@ -40,6 +42,8 @@ public class SoapActionInInterceptor extends AbstractSoapInterceptor { + private static final Logger LOG = LogUtils.getL7dLogger(SoapActionInInterceptor.class); + public SoapActionInInterceptor() { super(Phase.READ); addAfter(ReadHeadersInterceptor.class.getName()); @@ -91,6 +95,10 @@ public static String getSoapAction(Message m) { } public void handleMessage(SoapMessage message) throws Fault { + if (isRequestor(message)) { + return; + } + String action = getSoapAction(message); if (!StringUtils.isEmpty(action)) { getAndSetOperation(message, action); @@ -108,24 +116,54 @@ private void getAndSetOperation(SoapMessage message, String action) { BindingOperationInfo bindingOp = null; - Collection<BindingOperationInfo> bops = ep.getBinding().getBindingInfo().getOperations(); - if (bops == null) { + Collection<BindingOperationInfo> bops = ep.getEndpointInfo() + .getBinding().getOperations(); + if (bops != null) { + for (BindingOperationInfo boi : bops) { + SoapOperationInfo soi = boi.getExtensor(SoapOperationInfo.class); + if (soi != null && action.equals(soi.getAction())) { + if (bindingOp != null) { + //more than one op with the same action, will need to parse normally + return; + } + bindingOp = boi; + } + } + } + + if (bindingOp == null) { + //we didn't match the an operation, we'll try again later to make + //sure the incoming message did end up matching an operation. + //This could occur in some cases like WS-RM and WS-SecConv that will + //intercept the message with a new endpoint/operation + message.getInterceptorChain().add(new SoapActionInAttemptTwoInterceptor()); return; } - for (BindingOperationInfo boi : bops) { + + ex.put(BindingOperationInfo.class, bindingOp); + ex.put(OperationInfo.class, bindingOp.getOperationInfo()); + } + + public static class SoapActionInAttemptTwoInterceptor extends AbstractSoapInterceptor { + public SoapActionInAttemptTwoInterceptor() { + super(Phase.PRE_LOGICAL); + } + public void handleMessage(SoapMessage message) throws Fault { + BindingOperationInfo boi = message.getExchange().getBindingOperationInfo(); + if (boi == null) { + return; + } + String action = getSoapAction(message); + if (StringUtils.isEmpty(action)) { + return; + } SoapOperationInfo soi = boi.getExtensor(SoapOperationInfo.class); - if (soi != null && action.equals(soi.getAction())) { - if (bindingOp != null) { - //more than one op with the same action, will need to parse normally - return; - } - bindingOp = boi; + if (soi == null || action.equals(soi.getAction())) { + return; } - } - if (bindingOp != null) { - ex.put(BindingOperationInfo.class, bindingOp); - ex.put(OperationInfo.class, bindingOp.getOperationInfo()); + throw new Fault("SOAP_ACTION_MISMATCH", LOG, null, action); } } + }
systests/uncategorized/src/test/java/org/apache/cxf/systest/soap/RPCEncodedSoapActionGreeterImpl.java+40 −0 added@@ -0,0 +1,40 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.cxf.systest.soap; + +import javax.jws.WebService; +import javax.jws.soap.SOAPBinding; + +import org.apache.hello_world_soap_action.WrappedGreeter; + +@WebService(endpointInterface = "org.apache.hello_world_soap_action.WrappedGreeter", +serviceName = "WrappedSOAPService") +@SOAPBinding(style = SOAPBinding.Style.RPC, use = SOAPBinding.Use.ENCODED) +public class RPCEncodedSoapActionGreeterImpl implements WrappedGreeter { + + public String sayHiRequestWrapped(String in) { + return "sayHi"; + } + + public String sayHiRequest2Wrapped(String in) { + return "sayHi2"; + } + +}
systests/uncategorized/src/test/java/org/apache/cxf/systest/soap/RPCLitSoapActionGreeterImpl.java+40 −0 added@@ -0,0 +1,40 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.cxf.systest.soap; + +import javax.jws.WebService; +import javax.jws.soap.SOAPBinding; + +import org.apache.hello_world_soap_action.WrappedGreeter; + +@WebService(endpointInterface = "org.apache.hello_world_soap_action.WrappedGreeter", +serviceName = "WrappedSOAPService") +@SOAPBinding(style = SOAPBinding.Style.RPC) +public class RPCLitSoapActionGreeterImpl implements WrappedGreeter { + + public String sayHiRequestWrapped(String in) { + return "sayHi"; + } + + public String sayHiRequest2Wrapped(String in) { + return "sayHi2"; + } + +}
systests/uncategorized/src/test/java/org/apache/cxf/systest/soap/SoapActionTest.java+390 −1 modified@@ -19,6 +19,8 @@ package org.apache.cxf.systest.soap; +import javax.xml.ws.BindingProvider; + import org.apache.cxf.Bus; import org.apache.cxf.BusFactory; import org.apache.cxf.binding.soap.Soap12; @@ -27,6 +29,7 @@ import org.apache.cxf.jaxws.JaxWsServerFactoryBean; import org.apache.cxf.testutil.common.TestUtil; import org.apache.hello_world_soap_action.Greeter; +import org.apache.hello_world_soap_action.WrappedGreeter; import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; @@ -35,11 +38,20 @@ public class SoapActionTest extends Assert { static final String PORT1 = TestUtil.getPortNumber(SoapActionTest.class, 1); static final String PORT2 = TestUtil.getPortNumber(SoapActionTest.class, 2); + static final String PORT3 = TestUtil.getPortNumber(SoapActionTest.class, 3); + static final String PORT4 = TestUtil.getPortNumber(SoapActionTest.class, 4); + static final String PORT5 = TestUtil.getPortNumber(SoapActionTest.class, 5); + static final String PORT6 = TestUtil.getPortNumber(SoapActionTest.class, 6); + static final String PORT7 = TestUtil.getPortNumber(SoapActionTest.class, 7); static Bus bus; static String add11 = "http://localhost:" + PORT1 + "/test11"; static String add12 = "http://localhost:" + PORT2 + "/test12"; - + static String add13 = "http://localhost:" + PORT3 + "/testWrapped"; + static String add14 = "http://localhost:" + PORT4 + "/testWrapped12"; + static String add15 = "http://localhost:" + PORT5 + "/testRPCLit"; + static String add16 = "http://localhost:" + PORT6 + "/testRPCEncoded"; + static String add17 = "http://localhost:" + PORT7 + "/testWrappedEncoded"; @BeforeClass public static void createServers() throws Exception { @@ -58,7 +70,40 @@ public static void createServers() throws Exception { config.setVersion(Soap12.getInstance()); sf.setBindingConfig(config); sf.create(); + + sf = new JaxWsServerFactoryBean(); + sf.setServiceBean(new WrappedSoapActionGreeterImpl()); + sf.setAddress(add13); + sf.setBus(bus); + sf.create(); + + sf = new JaxWsServerFactoryBean(); + sf.setServiceBean(new WrappedSoapActionGreeterImpl()); + sf.setAddress(add14); + sf.setBus(bus); + config.setVersion(Soap12.getInstance()); + sf.setBindingConfig(config); + sf.create(); + + sf = new JaxWsServerFactoryBean(); + sf.setServiceBean(new RPCLitSoapActionGreeterImpl()); + sf.setAddress(add15); + sf.setBus(bus); + sf.create(); + + sf = new JaxWsServerFactoryBean(); + sf.setServiceBean(new RPCEncodedSoapActionGreeterImpl()); + sf.setAddress(add16); + sf.setBus(bus); + sf.create(); + + sf = new JaxWsServerFactoryBean(); + sf.setServiceBean(new WrappedEncodedSoapActionGreeterImpl()); + sf.setAddress(add17); + sf.setBus(bus); + sf.create(); } + @AfterClass public static void shutdown() throws Exception { bus.shutdown(true); @@ -93,4 +138,348 @@ public void testSoap12Endpoint() throws Exception { assertEquals("sayHi", greeter.sayHi("test")); assertEquals("sayHi2", greeter.sayHi2("test")); } + + + @Test + public void testBareSoapActionSpoofing() throws Exception { + JaxWsProxyFactoryBean pf = new JaxWsProxyFactoryBean(); + pf.setServiceClass(Greeter.class); + pf.setAddress(add11); + pf.setBus(bus); + Greeter greeter = (Greeter) pf.create(); + + assertEquals("sayHi", greeter.sayHi("test")); + assertEquals("sayHi2", greeter.sayHi2("test")); + + // Now test spoofing attack + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_2" + ); + try { + greeter.sayHi("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test the other operation + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_1" + ); + try { + greeter.sayHi2("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test a SOAP Action that does not exist in the binding + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_UNKNOWN" + ); + try { + greeter.sayHi("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + } + + @Test + public void testBareSoap12ActionSpoofing() throws Exception { + JaxWsProxyFactoryBean pf = new JaxWsProxyFactoryBean(); + pf.setServiceClass(Greeter.class); + pf.setAddress(add12); + SoapBindingConfiguration config = new SoapBindingConfiguration(); + config.setVersion(Soap12.getInstance()); + pf.setBindingConfig(config); + pf.setBus(bus); + Greeter greeter = (Greeter) pf.create(); + + assertEquals("sayHi", greeter.sayHi("test")); + assertEquals("sayHi2", greeter.sayHi2("test")); + + // Now test spoofing attack + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_2" + ); + try { + greeter.sayHi("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test the other operation + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_1" + ); + try { + greeter.sayHi2("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test a SOAP Action that does not exist in the binding + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_UNKNOWN" + ); + try { + greeter.sayHi("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + } + + @Test + public void testWrappedSoapActionSpoofing() throws Exception { + JaxWsProxyFactoryBean pf = new JaxWsProxyFactoryBean(); + pf.setServiceClass(WrappedGreeter.class); + pf.setAddress(add13); + pf.setBus(bus); + WrappedGreeter greeter = (WrappedGreeter) pf.create(); + + assertEquals("sayHi", greeter.sayHiRequestWrapped("test")); + assertEquals("sayHi2", greeter.sayHiRequest2Wrapped("test")); + + // Now test spoofing attack + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_2" + ); + try { + greeter.sayHiRequestWrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test the other operation + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_1" + ); + try { + greeter.sayHiRequest2Wrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test a SOAP Action that does not exist in the binding + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_UNKNOWN" + ); + try { + greeter.sayHiRequestWrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + } + + @Test + public void testWrappedSoap12ActionSpoofing() throws Exception { + JaxWsProxyFactoryBean pf = new JaxWsProxyFactoryBean(); + pf.setServiceClass(WrappedGreeter.class); + pf.setAddress(add14); + SoapBindingConfiguration config = new SoapBindingConfiguration(); + config.setVersion(Soap12.getInstance()); + pf.setBindingConfig(config); + pf.setBus(bus); + WrappedGreeter greeter = (WrappedGreeter) pf.create(); + + assertEquals("sayHi", greeter.sayHiRequestWrapped("test")); + assertEquals("sayHi2", greeter.sayHiRequest2Wrapped("test")); + + // Now test spoofing attack + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_2" + ); + try { + greeter.sayHiRequestWrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test the other operation + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_1" + ); + try { + greeter.sayHiRequest2Wrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test a SOAP Action that does not exist in the binding + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_UNKNOWN" + ); + try { + greeter.sayHiRequestWrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + } + + @Test + public void testRPCLitSoapActionSpoofing() throws Exception { + JaxWsProxyFactoryBean pf = new JaxWsProxyFactoryBean(); + pf.setServiceClass(WrappedGreeter.class); + pf.setAddress(add15); + pf.setBus(bus); + WrappedGreeter greeter = (WrappedGreeter) pf.create(); + + assertEquals("sayHi", greeter.sayHiRequestWrapped("test")); + assertEquals("sayHi2", greeter.sayHiRequest2Wrapped("test")); + + // Now test spoofing attack + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_2" + ); + try { + greeter.sayHiRequestWrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test the other operation + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_1" + ); + try { + greeter.sayHiRequest2Wrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test a SOAP Action that does not exist in the binding + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_UNKNOWN" + ); + try { + greeter.sayHiRequestWrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + } + + @Test + public void testRPCEncodedSoapActionSpoofing() throws Exception { + JaxWsProxyFactoryBean pf = new JaxWsProxyFactoryBean(); + pf.setServiceClass(WrappedGreeter.class); + pf.setAddress(add16); + pf.setBus(bus); + WrappedGreeter greeter = (WrappedGreeter) pf.create(); + + assertEquals("sayHi", greeter.sayHiRequestWrapped("test")); + assertEquals("sayHi2", greeter.sayHiRequest2Wrapped("test")); + + // Now test spoofing attack + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_2" + ); + try { + greeter.sayHiRequestWrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test the other operation + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_1" + ); + try { + greeter.sayHiRequest2Wrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test a SOAP Action that does not exist in the binding + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_UNKNOWN" + ); + try { + greeter.sayHiRequestWrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + } + + @Test + public void testWrappedEncodedSoapActionSpoofing() throws Exception { + JaxWsProxyFactoryBean pf = new JaxWsProxyFactoryBean(); + pf.setServiceClass(WrappedGreeter.class); + pf.setAddress(add17); + pf.setBus(bus); + WrappedGreeter greeter = (WrappedGreeter) pf.create(); + + assertEquals("sayHi", greeter.sayHiRequestWrapped("test")); + assertEquals("sayHi2", greeter.sayHiRequest2Wrapped("test")); + + // Now test spoofing attack + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_2" + ); + try { + greeter.sayHiRequestWrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test the other operation + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_1" + ); + try { + greeter.sayHiRequest2Wrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + + // Test a SOAP Action that does not exist in the binding + ((BindingProvider)greeter).getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, "true"); + ((BindingProvider)greeter).getRequestContext().put( + BindingProvider.SOAPACTION_URI_PROPERTY, "SAY_HI_UNKNOWN" + ); + try { + greeter.sayHiRequestWrapped("test"); + fail("Failure expected on spoofing attack"); + } catch (Exception ex) { + // expected + } + } + }
systests/uncategorized/src/test/java/org/apache/cxf/systest/soap/WrappedEncodedSoapActionGreeterImpl.java+40 −0 added@@ -0,0 +1,40 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.cxf.systest.soap; + +import javax.jws.WebService; +import javax.jws.soap.SOAPBinding; + +import org.apache.hello_world_soap_action.WrappedGreeter; + +@WebService(endpointInterface = "org.apache.hello_world_soap_action.WrappedGreeter", + serviceName = "WrappedSOAPService") +@SOAPBinding(use = SOAPBinding.Use.ENCODED) +public class WrappedEncodedSoapActionGreeterImpl implements WrappedGreeter { + + public String sayHiRequestWrapped(String in) { + return "sayHi"; + } + + public String sayHiRequest2Wrapped(String in) { + return "sayHi2"; + } + +}
systests/uncategorized/src/test/java/org/apache/cxf/systest/soap/WrappedSoapActionGreeterImpl.java+38 −0 added@@ -0,0 +1,38 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.cxf.systest.soap; + +import javax.jws.WebService; + +import org.apache.hello_world_soap_action.WrappedGreeter; + +@WebService(endpointInterface = "org.apache.hello_world_soap_action.WrappedGreeter", + serviceName = "WrappedSOAPService") +public class WrappedSoapActionGreeterImpl implements WrappedGreeter { + + public String sayHiRequestWrapped(String in) { + return "sayHi"; + } + + public String sayHiRequest2Wrapped(String in) { + return "sayHi2"; + } + +}
testutils/src/main/resources/wsdl/hello_world_soap_action.wsdl+115 −0 modified@@ -26,6 +26,7 @@ xmlns:jms="http://cxf.apache.org/transports/jms" xmlns:tns="http://apache.org/hello_world_soap_action" xmlns:x1="http://apache.org/hello_world_soap_action/types" + xmlns:x2="http://apache.org/hello_world_soap_action/types/wrapped" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" targetNamespace="http://apache.org/hello_world_soap_action" name="HelloWorld"> @@ -37,6 +38,36 @@ <element name="text" type="xsd:string" /> <element name="text2" type="xsd:string" /> </schema> + <xsd:schema targetNamespace="http://apache.org/hello_world_soap_action/types/wrapped"> + <xsd:element name="sayHiRequestWrapped"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="wrappedText" type="xsd:string" /> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + <xsd:element name="sayHiResponseWrapped"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="wrappedTextResponse" type="xsd:string" /> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + <xsd:element name="sayHiRequest2Wrapped"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="wrappedText" type="xsd:string" /> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + <xsd:element name="sayHiResponse2Wrapped"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="wrappedTextResponse" type="xsd:string" /> + </xsd:sequence> + </xsd:complexType> + </xsd:element> + </xsd:schema> </wsdl:types> <wsdl:message name="sayHiRequest"> <wsdl:part name="in" element="x1:text" /> @@ -50,6 +81,19 @@ <wsdl:message name="sayHiResponse2"> <wsdl:part name="out" element="x1:text" /> </wsdl:message> + + <wsdl:message name="sayHiRequestWrapped"> + <wsdl:part element="x2:sayHiRequestWrapped" name="parameters" /> + </wsdl:message> + <wsdl:message name="sayHiResponseWrapped"> + <wsdl:part element="x2:sayHiResponseWrapped" name="parameters" /> + </wsdl:message> + <wsdl:message name="sayHiRequest2Wrapped"> + <wsdl:part element="x2:sayHiRequest2Wrapped" name="parameters" /> + </wsdl:message> + <wsdl:message name="sayHiResponse2Wrapped"> + <wsdl:part element="x2:sayHiResponse2Wrapped" name="parameters" /> + </wsdl:message> <wsdl:portType name="Greeter"> <wsdl:operation name="sayHi"> @@ -63,6 +107,19 @@ </wsdl:operation> </wsdl:portType> + + <wsdl:portType name="WrappedGreeter"> + <wsdl:operation name="sayHiRequestWrapped"> + <wsdl:input message="tns:sayHiRequestWrapped" /> + <wsdl:output message="tns:sayHiResponseWrapped" /> + </wsdl:operation> + + <wsdl:operation name="sayHiRequest2Wrapped"> + <wsdl:input message="tns:sayHiRequest2Wrapped" /> + <wsdl:output message="tns:sayHiResponse2Wrapped" /> + </wsdl:operation> + </wsdl:portType> + <wsdl:binding name="Greeter_SOAPBinding" type="tns:Greeter"> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" /> @@ -86,6 +143,7 @@ </wsdl:operation> </wsdl:binding> + <wsdl:binding name="Greeter_SOAP12Binding" type="tns:Greeter"> <soap12:binding style="document" transport="http://www.w3.org/2003/05/soap/bindings/HTTP/" /> @@ -109,6 +167,53 @@ </wsdl:operation> </wsdl:binding> + + <wsdl:binding name="Greeter_WrappedSOAPBinding" type="tns:WrappedGreeter"> + <soap:binding style="document" + transport="http://schemas.xmlsoap.org/soap/http" /> + <wsdl:operation name="sayHiRequestWrapped"> + <soap:operation soapAction="SAY_HI_1" /> + <wsdl:input> + <soap:body use="literal" /> + </wsdl:input> + <wsdl:output> + <soap:body use="literal" /> + </wsdl:output> + </wsdl:operation> + <wsdl:operation name="sayHiRequest2Wrapped"> + <soap:operation soapAction="SAY_HI_2" /> + <wsdl:input> + <soap:body use="literal" /> + </wsdl:input> + <wsdl:output> + <soap:body use="literal" /> + </wsdl:output> + </wsdl:operation> + </wsdl:binding> + + <wsdl:binding name="Greeter_WrappedSOAP12Binding" type="tns:WrappedGreeter"> + <soap12:binding style="document" + transport="http://www.w3.org/2003/05/soap/bindings/HTTP/" /> + <wsdl:operation name="sayHiRequestWrapped"> + <soap12:operation soapAction="SAY_HI_1" /> + <wsdl:input> + <soap12:body use="literal" /> + </wsdl:input> + <wsdl:output> + <soap12:body use="literal" /> + </wsdl:output> + </wsdl:operation> + <wsdl:operation name="sayHiRequest2Wrapped"> + <soap12:operation soapAction="SAY_HI_2" /> + <wsdl:input> + <soap12:body use="literal" /> + </wsdl:input> + <wsdl:output> + <soap12:body use="literal" /> + </wsdl:output> + </wsdl:operation> + </wsdl:binding> + <wsdl:service name="SOAPService"> <wsdl:port name="SoapPort" binding="tns:Greeter_SOAPBinding"> <soap:address @@ -121,4 +226,14 @@ location="http://localhost:9001/SOAPDocLitService/Soap12Port" /> </wsdl:port> </wsdl:service> + <wsdl:service name="WrappedSOAPService"> + <wsdl:port name="WrappedSoapPort" binding="tns:Greeter_WrappedSOAPBinding"> + <soap:address location="http://localhost:9001/SOAPDocLitService/WrappedSoapPort" /> + </wsdl:port> + </wsdl:service> + <wsdl:service name="WrappedSOAP12Service"> + <wsdl:port name="WrappedSoap12Port" binding="tns:Greeter_WrappedSOAP12Binding"> + <soap:address location="http://localhost:9001/SOAPDocLitService/WrappedSoap12Port" /> + </wsdl:port> + </wsdl:service> </wsdl:definitions>
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
33- svn.apache.org/viewvcnvdPatchVendor AdvisoryWEB
- cxf.apache.org/cve-2012-3451.htmlnvdVendor AdvisoryWEB
- rhn.redhat.com/errata/RHSA-2012-1591.htmlnvdThird Party AdvisoryWEB
- rhn.redhat.com/errata/RHSA-2012-1592.htmlnvdThird Party AdvisoryWEB
- rhn.redhat.com/errata/RHSA-2012-1594.htmlnvdThird Party AdvisoryWEB
- rhn.redhat.com/errata/RHSA-2013-0256.htmlnvdThird Party AdvisoryWEB
- rhn.redhat.com/errata/RHSA-2013-0257.htmlnvdThird Party AdvisoryWEB
- rhn.redhat.com/errata/RHSA-2013-0258.htmlnvdThird Party AdvisoryWEB
- rhn.redhat.com/errata/RHSA-2013-0259.htmlnvdThird Party AdvisoryWEB
- rhn.redhat.com/errata/RHSA-2013-0726.htmlnvdThird Party AdvisoryWEB
- rhn.redhat.com/errata/RHSA-2013-0743.htmlnvdThird Party AdvisoryWEB
- secunia.com/advisories/51607nvdThird Party Advisory
- secunia.com/advisories/52183nvdThird Party Advisory
- bugzilla.redhat.com/show_bug.cginvdIssue TrackingThird Party AdvisoryWEB
- exchange.xforce.ibmcloud.com/vulnerabilities/78734nvdThird Party AdvisoryVDB EntryWEB
- github.com/advisories/GHSA-55j7-f5wf-43m4ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2012-3451ghsaADVISORY
- github.com/apache/cxf/commit/7230648f96573820d5bfa82c92c637391b448897ghsaWEB
- github.com/apache/cxf/commit/878fe37f0b09888a42005fedc725ce497b5a694aghsaWEB
- github.com/apache/cxf/commit/9c70abe28fbf2b4c4df0b93ed12295ea5a012554ghsaWEB
- github.com/apache/cxf/commit/deeeaa95a861b355068ca6febc7aa02a4a8c51e5ghsaWEB
- lists.apache.org/thread.html/r36e44ffc1a9b365327df62cdfaabe85b9a5637de102cea07d79b2dbf%40%3Ccommits.cxf.apache.org%3EnvdWEB
- lists.apache.org/thread.html/r36e44ffc1a9b365327df62cdfaabe85b9a5637de102cea07d79b2dbf@%3Ccommits.cxf.apache.org%3EghsaWEB
- lists.apache.org/thread.html/rc774278135816e7afc943dc9fc78eb0764f2c84a2b96470a0187315c%40%3Ccommits.cxf.apache.org%3EnvdWEB
- lists.apache.org/thread.html/rc774278135816e7afc943dc9fc78eb0764f2c84a2b96470a0187315c@%3Ccommits.cxf.apache.org%3EghsaWEB
- lists.apache.org/thread.html/rd49aabd984ed540c8ff7916d4d79405f3fa311d2fdbcf9ed307839a6%40%3Ccommits.cxf.apache.org%3EnvdWEB
- lists.apache.org/thread.html/rd49aabd984ed540c8ff7916d4d79405f3fa311d2fdbcf9ed307839a6@%3Ccommits.cxf.apache.org%3EghsaWEB
- lists.apache.org/thread.html/rec7160382badd3ef4ad017a22f64a266c7188b9ba71394f0d321e2d4%40%3Ccommits.cxf.apache.org%3EnvdWEB
- lists.apache.org/thread.html/rec7160382badd3ef4ad017a22f64a266c7188b9ba71394f0d321e2d4@%3Ccommits.cxf.apache.org%3EghsaWEB
- lists.apache.org/thread.html/rfb87e0bf3995e7d560afeed750fac9329ff5f1ad49da365129b7f89e%40%3Ccommits.cxf.apache.org%3EnvdWEB
- lists.apache.org/thread.html/rfb87e0bf3995e7d560afeed750fac9329ff5f1ad49da365129b7f89e@%3Ccommits.cxf.apache.org%3EghsaWEB
- lists.apache.org/thread.html/rff42cfa5e7d75b7c1af0e37589140a8f1999e578a75738740b244bd4%40%3Ccommits.cxf.apache.org%3EnvdWEB
- lists.apache.org/thread.html/rff42cfa5e7d75b7c1af0e37589140a8f1999e578a75738740b244bd4@%3Ccommits.cxf.apache.org%3EghsaWEB
News mentions
0No linked articles in our index yet.