This is an automated email from the ASF dual-hosted git repository.

robertlazarski pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/axis-axis2-java-core.git

commit 52c7ba310fcaca1ff60d596d2b118d34851eb4b7
Author: Robert Lazarski <[email protected]>
AuthorDate: Wed Aug 5 07:48:02 2026 -1000

    Also gate the response endpoint where the transport is acquired
    
    Corrects a claim I had made: CXF does not check at the inbound-parsing 
layer.
    Its check sits in DecoupledDestination.getBackChannel -- the method that 
hands
    back the conduit for a decoupled response -- so anything reaching for that
    back channel is screened however the endpoint reference arrived. Checking 
only
    in AddressingInHandler was weaker, and the report's proof-of-concept showed
    it: it builds
    a MessageContext, calls setReplyTo directly and drives the transport sender,
    never passing through header parsing, and the server still connected out.
    
    MessageContextBuilder.setupCorrectTransportOut is the Axis2 analogue. It 
runs
    only for a server-side response to a non-anonymous, non-none destination, 
and
    it is where that destination's transport is resolved -- the same depth as 
CXF's
    check. The policy therefore moves to the kernel org.apache.axis2.addressing
    package, beside EndpointReference and AddressingFaultsHelper, so both the
    handler and the kernel can use it. The handler check stays: it faults early
    with a proper wsa fault on the path a remote caller actually has.
    
    The PoC now fails on both its positive cases. The resolver pool shutdown 
moves
    from the addressing module to AxisConfiguration.cleanup(), next to the
    multipart reaper, since the policy is no longer module-scoped.
    
    Co-Authored-By: Claude Fable 5 <[email protected]>
---
 .../apache/axis2/handlers/addressing/Addressing.java  |  1 -
 .../handlers/addressing/AddressingInHandler.java      |  1 +
 .../addressing/ResponseEndpointPolicyHandlerTest.java |  1 +
 .../axis2}/addressing/ResponseEndpointPolicy.java     | 19 +++++++++----------
 .../org/apache/axis2/engine/AxisConfiguration.java    |  2 ++
 .../org/apache/axis2/util/MessageContextBuilder.java  | 15 +++++++++++++++
 .../axis2}/addressing/ResponseEndpointPolicyTest.java |  4 +---
 7 files changed, 29 insertions(+), 14 deletions(-)

diff --git 
a/modules/addressing/src/org/apache/axis2/handlers/addressing/Addressing.java 
b/modules/addressing/src/org/apache/axis2/handlers/addressing/Addressing.java
index 63dbbaefbe..047e8e1be6 100644
--- 
a/modules/addressing/src/org/apache/axis2/handlers/addressing/Addressing.java
+++ 
b/modules/addressing/src/org/apache/axis2/handlers/addressing/Addressing.java
@@ -54,7 +54,6 @@ public class Addressing implements Module {
     }
 
     public void shutdown(ConfigurationContext configurationContext) throws 
AxisFault {
-        ResponseEndpointPolicy.shutdown();
     }
 
 }
diff --git 
a/modules/addressing/src/org/apache/axis2/handlers/addressing/AddressingInHandler.java
 
b/modules/addressing/src/org/apache/axis2/handlers/addressing/AddressingInHandler.java
index 1c6ffc1547..8b64481476 100644
--- 
a/modules/addressing/src/org/apache/axis2/handlers/addressing/AddressingInHandler.java
+++ 
b/modules/addressing/src/org/apache/axis2/handlers/addressing/AddressingInHandler.java
@@ -32,6 +32,7 @@ import org.apache.axis2.addressing.AddressingFaultsHelper;
 import org.apache.axis2.addressing.EndpointReference;
 import org.apache.axis2.addressing.EndpointReferenceHelper;
 import org.apache.axis2.addressing.RelatesTo;
+import org.apache.axis2.addressing.ResponseEndpointPolicy;
 import org.apache.axis2.client.Options;
 import org.apache.axis2.context.MessageContext;
 import org.apache.axis2.description.HandlerDescription;
diff --git 
a/modules/addressing/test/org/apache/axis2/handlers/addressing/ResponseEndpointPolicyHandlerTest.java
 
b/modules/addressing/test/org/apache/axis2/handlers/addressing/ResponseEndpointPolicyHandlerTest.java
index 970294cf6b..8a2cbe3810 100644
--- 
a/modules/addressing/test/org/apache/axis2/handlers/addressing/ResponseEndpointPolicyHandlerTest.java
+++ 
b/modules/addressing/test/org/apache/axis2/handlers/addressing/ResponseEndpointPolicyHandlerTest.java
@@ -29,6 +29,7 @@ import org.apache.axis2.addressing.AddressingConstants;
 import org.apache.axis2.context.ConfigurationContext;
 import org.apache.axis2.context.ConfigurationContextFactory;
 import org.apache.axis2.context.MessageContext;
+import org.apache.axis2.addressing.ResponseEndpointPolicy;
 import org.apache.axis2.description.Parameter;
 
 /**
diff --git 
a/modules/addressing/src/org/apache/axis2/handlers/addressing/ResponseEndpointPolicy.java
 b/modules/kernel/src/org/apache/axis2/addressing/ResponseEndpointPolicy.java
similarity index 96%
rename from 
modules/addressing/src/org/apache/axis2/handlers/addressing/ResponseEndpointPolicy.java
rename to 
modules/kernel/src/org/apache/axis2/addressing/ResponseEndpointPolicy.java
index 83fcfa058d..6aab3227a8 100644
--- 
a/modules/addressing/src/org/apache/axis2/handlers/addressing/ResponseEndpointPolicy.java
+++ b/modules/kernel/src/org/apache/axis2/addressing/ResponseEndpointPolicy.java
@@ -17,9 +17,8 @@
  * under the License.
  */
 
-package org.apache.axis2.handlers.addressing;
+package org.apache.axis2.addressing;
 
-import org.apache.axis2.addressing.EndpointReference;
 import org.apache.axis2.context.MessageContext;
 import org.apache.axis2.description.Parameter;
 import org.apache.axis2.util.JavaUtils;
@@ -85,15 +84,15 @@ import java.util.concurrent.TimeoutException;
  * appear in it, which supersedes the network-range check.</dd>
  * </dl>
  */
-final class ResponseEndpointPolicy {
+public final class ResponseEndpointPolicy {
 
     private static final Log log = 
LogFactory.getLog(ResponseEndpointPolicy.class);
 
-    static final String ALLOW_NON_ANONYMOUS = 
"allowNonAnonymousResponseEndpoints";
-    static final String BLOCK_PRIVATE_NETWORKS = 
"blockPrivateNetworkResponseEndpoints";
-    static final String ALLOWED_HOSTS = "allowedResponseEndpointHosts";
-    static final String ALLOWED_SCHEMES_PARAMETER = 
"allowedResponseEndpointSchemes";
-    static final String RESOLVE_TIMEOUT = 
"responseEndpointResolveTimeoutMillis";
+    public static final String ALLOW_NON_ANONYMOUS = 
"allowNonAnonymousResponseEndpoints";
+    public static final String BLOCK_PRIVATE_NETWORKS = 
"blockPrivateNetworkResponseEndpoints";
+    public static final String ALLOWED_HOSTS = "allowedResponseEndpointHosts";
+    public static final String ALLOWED_SCHEMES_PARAMETER = 
"allowedResponseEndpointSchemes";
+    public static final String RESOLVE_TIMEOUT = 
"responseEndpointResolveTimeoutMillis";
 
     /** Long enough for a healthy resolver, short enough not to pin a thread. 
*/
     static final long DEFAULT_RESOLVE_TIMEOUT_MILLIS = 2000L;
@@ -136,7 +135,7 @@ final class ResponseEndpointPolicy {
      * @param messageContext the inbound message, for parameter resolution
      * @return true if the endpoint may be used as a send destination
      */
-    static boolean isAllowed(EndpointReference epr, MessageContext 
messageContext) {
+    public static boolean isAllowed(EndpointReference epr, MessageContext 
messageContext) {
         if (epr == null || epr.hasAnonymousAddress() || epr.hasNoneAddress()) {
             return true;
         }
@@ -359,7 +358,7 @@ final class ResponseEndpointPolicy {
      * Stop the resolver pool. Called from the addressing module's shutdown so
      * the threads do not outlive the configuration that created them.
      */
-    static synchronized void shutdown() {
+    public static synchronized void shutdown() {
         if (resolver != null) {
             resolver.shutdownNow();
             resolver = null;
diff --git a/modules/kernel/src/org/apache/axis2/engine/AxisConfiguration.java 
b/modules/kernel/src/org/apache/axis2/engine/AxisConfiguration.java
index fd2d8e4606..a0dc32ac12 100644
--- a/modules/kernel/src/org/apache/axis2/engine/AxisConfiguration.java
+++ b/modules/kernel/src/org/apache/axis2/engine/AxisConfiguration.java
@@ -1342,6 +1342,8 @@ public class AxisConfiguration extends AxisDescription {
         // Stop the multipart temp-file reaper so its thread does not outlive a
         // redeployment and pin this web application's class loader.
         MultipartTempFileTracker.shutdown();
+        // Same reason: the WS-Addressing endpoint resolver runs a thread pool.
+        org.apache.axis2.addressing.ResponseEndpointPolicy.shutdown();
         this.policySupportedModules.clear();
         this.moduleConfigmap.clear();
         this.allEndpoints.clear();
diff --git 
a/modules/kernel/src/org/apache/axis2/util/MessageContextBuilder.java 
b/modules/kernel/src/org/apache/axis2/util/MessageContextBuilder.java
index 9bf82f965c..91a3f786f2 100644
--- a/modules/kernel/src/org/apache/axis2/util/MessageContextBuilder.java
+++ b/modules/kernel/src/org/apache/axis2/util/MessageContextBuilder.java
@@ -43,6 +43,7 @@ import org.apache.axis2.addressing.AddressingConstants;
 import org.apache.axis2.addressing.AddressingConstants.Final;
 import org.apache.axis2.addressing.AddressingHelper;
 import org.apache.axis2.addressing.EndpointReference;
+import org.apache.axis2.addressing.ResponseEndpointPolicy;
 import org.apache.axis2.addressing.RelatesTo;
 import org.apache.axis2.context.ConfigurationContext;
 import org.apache.axis2.context.MessageContext;
@@ -380,6 +381,20 @@ public class MessageContextBuilder {
             EndpointReference responseEPR = context.getTo();
             if (context.isServerSide() && responseEPR != null) {
                 if (!responseEPR.hasAnonymousAddress() && 
!responseEPR.hasNoneAddress()) {
+                    // Last gate before a server-side response acquires a 
transport
+                    // for a caller-nominated destination. AddressingInHandler
+                    // already screens the inbound header, which is the only 
route
+                    // a remote client has; this catches everything else that 
turns
+                    // an endpoint reference into an outbound target — a custom
+                    // handler, service code, or a future dispatch path — so 
the
+                    // check cannot be walked around by reaching the sender 
another
+                    // way. Apache CXF places its equivalent check at the same
+                    // depth, in DecoupledDestination.getBackChannel.
+                    if (!ResponseEndpointPolicy.isAllowed(responseEPR, 
context)) {
+                        throw new AxisFault("Refusing to send a response to 
the "
+                                + "endpoint reference named by this message; 
see the "
+                                + ResponseEndpointPolicy.ALLOW_NON_ANONYMOUS + 
" parameter");
+                    }
                     URI uri = new URI(responseEPR.getAddress());
                     String scheme = uri.getScheme();
                     if ((transportOut == null) || 
!transportOut.getName().equals(scheme)) {
diff --git 
a/modules/addressing/test/org/apache/axis2/handlers/addressing/ResponseEndpointPolicyTest.java
 
b/modules/kernel/test/org/apache/axis2/addressing/ResponseEndpointPolicyTest.java
similarity index 98%
rename from 
modules/addressing/test/org/apache/axis2/handlers/addressing/ResponseEndpointPolicyTest.java
rename to 
modules/kernel/test/org/apache/axis2/addressing/ResponseEndpointPolicyTest.java
index 478d0acdf8..d672157d5c 100644
--- 
a/modules/addressing/test/org/apache/axis2/handlers/addressing/ResponseEndpointPolicyTest.java
+++ 
b/modules/kernel/test/org/apache/axis2/addressing/ResponseEndpointPolicyTest.java
@@ -17,11 +17,9 @@
  * under the License.
  */
 
-package org.apache.axis2.handlers.addressing;
+package org.apache.axis2.addressing;
 
 import junit.framework.TestCase;
-import org.apache.axis2.addressing.AddressingConstants;
-import org.apache.axis2.addressing.EndpointReference;
 import org.apache.axis2.context.ConfigurationContext;
 import org.apache.axis2.context.MessageContext;
 import org.apache.axis2.description.Parameter;

Reply via email to