From c8437c1e65cc8a87ffbe1d11613ce817d6fade70 Mon Sep 17 00:00:00 2001 From: Christian Ortlepp Date: Mon, 13 Jan 2025 09:12:43 +0100 Subject: [PATCH 1/6] fix: make hostname extraction work with IPv6 addresses --- .../axis2/util/WSDLSerializationUtil.java | 30 +++++++++++-------- .../axis2/transport/http/ListingAgent.java | 22 +++----------- 2 files changed, 21 insertions(+), 31 deletions(-) diff --git a/modules/kernel/src/org/apache/axis2/util/WSDLSerializationUtil.java b/modules/kernel/src/org/apache/axis2/util/WSDLSerializationUtil.java index aaf1035ca5..363cdf5a18 100644 --- a/modules/kernel/src/org/apache/axis2/util/WSDLSerializationUtil.java +++ b/modules/kernel/src/org/apache/axis2/util/WSDLSerializationUtil.java @@ -23,7 +23,6 @@ import org.apache.axiom.om.OMFactory; import org.apache.axiom.om.OMNamespace; import org.apache.axiom.om.OMNode; -import org.apache.axis2.AxisFault; import org.apache.axis2.addressing.AddressingConstants; import org.apache.axis2.description.*; import org.apache.axis2.description.java2wsdl.Java2WSDLConstants; @@ -36,12 +35,15 @@ import org.apache.neethi.PolicyReference; import javax.xml.namespace.QName; +import java.net.URI; +import java.net.URISyntaxException; import java.util.*; /** * Helps the AxisService to WSDL process */ public class WSDLSerializationUtil { + private static final OnDemandLogger log = new OnDemandLogger(WSDLSerializationUtil.class); public static final String CDATA_START = "= 0) { - ip = serviceURL.substring(ipindex + 2, serviceURL.length()); + ip = serviceURL.substring(ipindex + 2); int seperatorIndex = ip.indexOf(":"); int slashIndex = ip.indexOf("/"); - + if (seperatorIndex >= 0) { ip = ip.substring(0, seperatorIndex); } else { ip = ip.substring(0, slashIndex); - } + } } } - - return ip; - } - + return ip; + } + } } diff --git a/modules/transport/http/src/main/java/org/apache/axis2/transport/http/ListingAgent.java b/modules/transport/http/src/main/java/org/apache/axis2/transport/http/ListingAgent.java index d057adeaa4..448740a059 100644 --- a/modules/transport/http/src/main/java/org/apache/axis2/transport/http/ListingAgent.java +++ b/modules/transport/http/src/main/java/org/apache/axis2/transport/http/ListingAgent.java @@ -27,10 +27,7 @@ import org.apache.axis2.description.Parameter; import org.apache.axis2.description.PolicyInclude; import org.apache.axis2.transport.http.server.HttpUtils; -import org.apache.axis2.util.ExternalPolicySerializer; -import org.apache.axis2.util.IOUtils; -import org.apache.axis2.util.JavaUtils; -import org.apache.axis2.util.OnDemandLogger; +import org.apache.axis2.util.*; import org.apache.neethi.Policy; import org.apache.neethi.PolicyComponent; import org.apache.neethi.PolicyRegistry; @@ -46,11 +43,12 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.net.URI; +import java.net.URISyntaxException; import java.util.Collection; import java.util.Enumeration; import java.util.HashMap; import java.util.Iterator; -import java.util.List; public class ListingAgent extends AbstractAgent { @@ -99,19 +97,7 @@ protected void processIndex(HttpServletRequest httpServletRequest, } private String extractHost(String filePart) { - int ipindex = filePart.indexOf("//"); - String ip = null; - if (ipindex >= 0) { - ip = filePart.substring(ipindex + 2, filePart.length()); - int seperatorIndex = ip.indexOf(":"); - int slashIndex = ip.indexOf("/"); - if (seperatorIndex >= 0) { - ip = ip.substring(0, seperatorIndex); - } else { - ip = ip.substring(0, slashIndex); - } - } - return ip; + return WSDLSerializationUtil.extractHostIP(filePart); } public void processExplicitSchemaAndWSDL(HttpServletRequest req, From 62c005afaa47313ec7f05132d80ff70aba1655cb Mon Sep 17 00:00:00 2001 From: Christian Ortlepp Date: Mon, 13 Jan 2025 09:21:13 +0100 Subject: [PATCH 2/6] fix: make local IP address detection support IPv6 --- .../src/org/apache/axis2/util/Utils.java | 105 ++++++++++++++---- 1 file changed, 84 insertions(+), 21 deletions(-) diff --git a/modules/kernel/src/org/apache/axis2/util/Utils.java b/modules/kernel/src/org/apache/axis2/util/Utils.java index 962a17d3a6..8ebb4f4fea 100644 --- a/modules/kernel/src/org/apache/axis2/util/Utils.java +++ b/modules/kernel/src/org/apache/axis2/util/Utils.java @@ -64,6 +64,7 @@ import java.net.InetAddress; import java.net.NetworkInterface; import java.net.SocketException; +import java.net.UnknownHostException; import java.security.AccessController; import java.security.PrivilegedAction; import java.security.PrivilegedExceptionAction; @@ -71,6 +72,8 @@ import java.util.HashMap; import java.util.Iterator; import java.util.Map; +import java.util.List; +import java.util.ArrayList; public class Utils { private static final Log log = LogFactory.getLog(Utils.class); @@ -569,6 +572,86 @@ public static int getMtomThreshold(MessageContext msgCtxt){ } return threshold; } + /** + * Returns all InetAddress objects encapsulating what are most likely the machine's + * LAN IP addresses. This method was copied from apache-commons-jcs HostNameUtil.java. + *

+ * This method will scan all IP addresses on all network interfaces on the host machine to + * determine the IP addresses most likely to be the machine's LAN addresses. + *

+ * @return List + * @throws IllegalStateException If the LAN address of the machine cannot be found. + */ + public static List getLocalHostLANAddresses() throws SocketException + { + final List addresses = new ArrayList<>(); + + try + { + InetAddress candidateAddress = null; + // Iterate all NICs (network interface cards)... + final Enumeration ifaces = NetworkInterface.getNetworkInterfaces(); + while ( ifaces.hasMoreElements() ) + { + final NetworkInterface iface = ifaces.nextElement(); + + // Skip loopback interfaces + if (iface.isLoopback() || !iface.isUp()) + { + continue; + } + + // Iterate all IP addresses assigned to each card... + for ( final Enumeration inetAddrs = iface.getInetAddresses(); inetAddrs.hasMoreElements(); ) + { + final InetAddress inetAddr = inetAddrs.nextElement(); + if ( !inetAddr.isLoopbackAddress() ) + { + if (inetAddr.isSiteLocalAddress()) + { + // Found non-loopback site-local address. + addresses.add(inetAddr); + } + if ( candidateAddress == null ) + { + // Found non-loopback address, but not necessarily site-local. + // Store it as a candidate to be returned if site-local address is not subsequently found... + candidateAddress = inetAddr; + // Note that we don't repeatedly assign non-loopback non-site-local addresses as candidates, + // only the first. For subsequent iterations, candidate will be non-null. + } + } + } + } + if (candidateAddress != null && addresses.isEmpty()) + { + // We did not find a site-local address, but we found some other non-loopback address. + // Server might have a non-site-local address assigned to its NIC (or it might be running + // IPv6 which deprecates the "site-local" concept). + addresses.add(candidateAddress); + } + // At this point, we did not find a non-loopback address. + // Fall back to returning whatever InetAddress.getLocalHost() returns... + if (addresses.isEmpty()) + { + final InetAddress jdkSuppliedAddress = InetAddress.getLocalHost(); + if ( jdkSuppliedAddress == null ) + { + throw new IllegalStateException( "The JDK InetAddress.getLocalHost() method unexpectedly returned null." ); + } + addresses.add(jdkSuppliedAddress); + } + } + catch (UnknownHostException e ) + { + var throwable = new SocketException("Failed to determine LAN address"); + throwable.initCause(e); + throw throwable; + } + + return addresses; + } + /** * Returns the ip address to be used for the replyto epr * CAUTION: @@ -582,25 +665,9 @@ public static int getMtomThreshold(MessageContext msgCtxt){ * - Obtain the ip to be used here from the Call API * * @return Returns String. - * @throws java.net.SocketException */ public static String getIpAddress() throws SocketException { - Enumeration e = NetworkInterface.getNetworkInterfaces(); - String address = "127.0.0.1"; - - while (e.hasMoreElements()) { - NetworkInterface netface = (NetworkInterface) e.nextElement(); - Enumeration addresses = netface.getInetAddresses(); - - while (addresses.hasMoreElements()) { - InetAddress ip = (InetAddress) addresses.nextElement(); - if (!ip.isLoopbackAddress() && isIP(ip.getHostAddress())) { - return ip.getHostAddress(); - } - } - } - - return address; + return getLocalHostLANAddresses().stream().findFirst().map(InetAddress::toString).orElse("127.0.0.1"); } /** @@ -639,10 +706,6 @@ public static String getHostname(AxisConfiguration axisConfiguration) { return null; } - private static boolean isIP(String hostAddress) { - return hostAddress.split("[.]").length == 4; - } - /** * Get the scheme part from a URI (or URL). * From d590bce99004c7cefe02813bc09d5d207879dbf3 Mon Sep 17 00:00:00 2001 From: Christian Ortlepp Date: Wed, 29 Jan 2025 08:14:52 +0100 Subject: [PATCH 3/6] fix: use `InetAddress::getHostAddress` instead of `InetAddress::toString` --- modules/kernel/src/org/apache/axis2/util/Utils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/kernel/src/org/apache/axis2/util/Utils.java b/modules/kernel/src/org/apache/axis2/util/Utils.java index 8ebb4f4fea..f98d8a7c67 100644 --- a/modules/kernel/src/org/apache/axis2/util/Utils.java +++ b/modules/kernel/src/org/apache/axis2/util/Utils.java @@ -667,7 +667,7 @@ public static List getLocalHostLANAddresses() throws SocketExceptio * @return Returns String. */ public static String getIpAddress() throws SocketException { - return getLocalHostLANAddresses().stream().findFirst().map(InetAddress::toString).orElse("127.0.0.1"); + return getLocalHostLANAddresses().stream().findFirst().map(InetAddress::getHostAddress).orElse("127.0.0.1"); } /** From 97199077c04d06351421951f29bc9c5b5e9d85f6 Mon Sep 17 00:00:00 2001 From: Christian Ortlepp Date: Tue, 4 Mar 2025 15:07:33 +0100 Subject: [PATCH 4/6] fix: improve getLocalHostLANAddresses() for IPv6 --- .../src/org/apache/axis2/util/Utils.java | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/modules/kernel/src/org/apache/axis2/util/Utils.java b/modules/kernel/src/org/apache/axis2/util/Utils.java index f98d8a7c67..2381a33ed6 100644 --- a/modules/kernel/src/org/apache/axis2/util/Utils.java +++ b/modules/kernel/src/org/apache/axis2/util/Utils.java @@ -61,6 +61,8 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import java.net.Inet4Address; +import java.net.Inet6Address; import java.net.InetAddress; import java.net.NetworkInterface; import java.net.SocketException; @@ -607,11 +609,25 @@ public static List getLocalHostLANAddresses() throws SocketExceptio final InetAddress inetAddr = inetAddrs.nextElement(); if ( !inetAddr.isLoopbackAddress() ) { - if (inetAddr.isSiteLocalAddress()) + if (!inetAddr.isLinkLocalAddress()) { - // Found non-loopback site-local address. - addresses.add(inetAddr); + if (inetAddr instanceof Inet6Address) { + Inet6Address inet6Addr = (Inet6Address) inetAddr; + if ((inet6Addr.getAddress()[0] ^ 0xfc) > 1) + { + // we ignore the site-local attribute for IPv6 because + // it has been deprecated, see https://www.ietf.org/rfc/rfc3879.txt + // instead we verify that this is not a unique local address, + // this check is unfortunately not in the standard library (yet) + // https://en.wikipedia.org/wiki/Unique_local_address + addresses.add(inetAddr); + } + } else if (inetAddr instanceof Inet4Address && inetAddr.isSiteLocalAddress()) { + // check site-local + addresses.add(inetAddr); + } } + if ( candidateAddress == null ) { // Found non-loopback address, but not necessarily site-local. From 1cfb14f99a019fe9106545a7c26b2b0362ee93ad Mon Sep 17 00:00:00 2001 From: Christian Ortlepp Date: Wed, 16 Apr 2025 11:34:18 +0200 Subject: [PATCH 5/6] refactor: remove unique local addresses special case, prefer IPv4 --- .../src/org/apache/axis2/util/Utils.java | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/modules/kernel/src/org/apache/axis2/util/Utils.java b/modules/kernel/src/org/apache/axis2/util/Utils.java index 2381a33ed6..16098ccc41 100644 --- a/modules/kernel/src/org/apache/axis2/util/Utils.java +++ b/modules/kernel/src/org/apache/axis2/util/Utils.java @@ -76,6 +76,8 @@ import java.util.Map; import java.util.List; import java.util.ArrayList; +import java.util.Comparator; +import java.util.function.Function; public class Utils { private static final Log log = LogFactory.getLog(Utils.class); @@ -612,16 +614,9 @@ public static List getLocalHostLANAddresses() throws SocketExceptio if (!inetAddr.isLinkLocalAddress()) { if (inetAddr instanceof Inet6Address) { - Inet6Address inet6Addr = (Inet6Address) inetAddr; - if ((inet6Addr.getAddress()[0] ^ 0xfc) > 1) - { - // we ignore the site-local attribute for IPv6 because - // it has been deprecated, see https://www.ietf.org/rfc/rfc3879.txt - // instead we verify that this is not a unique local address, - // this check is unfortunately not in the standard library (yet) - // https://en.wikipedia.org/wiki/Unique_local_address - addresses.add(inetAddr); - } + // we ignore the site-local attribute for IPv6 because + // it has been deprecated, see https://www.ietf.org/rfc/rfc3879.txt + addresses.add(inetAddr); } else if (inetAddr instanceof Inet4Address && inetAddr.isSiteLocalAddress()) { // check site-local addresses.add(inetAddr); @@ -683,7 +678,11 @@ public static List getLocalHostLANAddresses() throws SocketExceptio * @return Returns String. */ public static String getIpAddress() throws SocketException { - return getLocalHostLANAddresses().stream().findFirst().map(InetAddress::getHostAddress).orElse("127.0.0.1"); + //prefer ipv4 for backwards compatibility, we used to only consider ipv4 addresses + Function preferIpv4 = (i) -> i instanceof Inet4Address ? 1 : 0; + return getLocalHostLANAddresses().stream() + .min(Comparator.comparing(preferIpv4)) + .map(InetAddress::getHostAddress).orElse("127.0.0.1"); } /** From 7c2181ff30e830e0075a13b9b9cfcf328dabef0e Mon Sep 17 00:00:00 2001 From: Christian Ortlepp Date: Wed, 16 Apr 2025 13:43:42 +0200 Subject: [PATCH 6/6] fix: wrong order in comparator --- modules/kernel/src/org/apache/axis2/util/Utils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/kernel/src/org/apache/axis2/util/Utils.java b/modules/kernel/src/org/apache/axis2/util/Utils.java index 16098ccc41..35efd3fc5f 100644 --- a/modules/kernel/src/org/apache/axis2/util/Utils.java +++ b/modules/kernel/src/org/apache/axis2/util/Utils.java @@ -681,7 +681,7 @@ public static String getIpAddress() throws SocketException { //prefer ipv4 for backwards compatibility, we used to only consider ipv4 addresses Function preferIpv4 = (i) -> i instanceof Inet4Address ? 1 : 0; return getLocalHostLANAddresses().stream() - .min(Comparator.comparing(preferIpv4)) + .max(Comparator.comparing(preferIpv4)) .map(InetAddress::getHostAddress).orElse("127.0.0.1"); }