opendj-server-legacy/src/main/java/org/opends/server/types/HostPort.java
@@ -13,7 +13,7 @@ * * Copyright 2006-2008 Sun Microsystems, Inc. * Portions Copyright 2013-2016 ForgeRock AS. * Portions Copyright 2025 3A Systems LLC. * Portions Copyright 2025-2026 3A Systems LLC. */ package org.opends.server.types; @@ -229,8 +229,9 @@ * @throws NumberFormatException * If the "port" in the supplied string cannot be converted to an int * @throws IllegalArgumentException * if no port could be found in the supplied string, or if the port * is not a valid port number * if no port could be found in the supplied string, if the port * is not a valid port number, or if the host is a malformed * bracketed IPv6 address */ public static HostPort valueOf(String hostPort) throws NumberFormatException, IllegalArgumentException @@ -251,12 +252,18 @@ * @throws NumberFormatException * If the "port" in the supplied string cannot be converted to an int * @throws IllegalArgumentException * if no port could be found in the supplied string, or if the port * is not a valid port number * if no port could be found in the supplied string, if the port * is not a valid port number, or if the host is a malformed * bracketed IPv6 address */ public static HostPort valueOf(String hostPort, Integer defaultPort) throws NumberFormatException, IllegalArgumentException { if (hostPort.isEmpty()) { throw new IllegalArgumentException( "Invalid host/port string: no host name was provided in ''"); } final int sepIndex = hostPort.lastIndexOf(':'); if ((hostPort.charAt(0) == '[' && hostPort.charAt(hostPort.length() - 1) == ']') @@ -276,8 +283,9 @@ "Invalid host/port string: no host name was provided in '" + hostPort + "'"); } else if (hostPort.lastIndexOf(':', sepIndex - 1) != -1 && (hostPort.charAt(0) != '[' || hostPort.charAt(sepIndex - 1) != ']')) else if (hostPort.charAt(0) == '[' ? hostPort.charAt(sepIndex - 1) != ']' : hostPort.lastIndexOf(':', sepIndex - 1) != -1) { if (defaultPort != null) { @@ -300,16 +308,25 @@ * @param host * the host name to clean * @return the cleaned up host name * @throws IllegalArgumentException * if the host name starts or ends with a square bracket, but is * not a well-formed "[bracketed IPv6 address]" */ private String removeExtraChars(String host) { final int startsWith = host.indexOf("["); if (startsWith == -1) final boolean startsWithBracket = host.startsWith("["); final boolean endsWithBracket = host.endsWith("]"); if (!startsWithBracket && !endsWithBracket) { return host; } if (startsWithBracket && endsWithBracket && host.length() > 2) { return host.substring(1, host.length() - 1); } throw new IllegalArgumentException( "Invalid host name: expected \"[bracketed IPv6 address]\", but got '" + host + "'"); } /** * Returns a normalized String representation of the supplied host. opendj-server-legacy/src/test/java/org/opends/server/authorization/dseecompat/UserDNTestCase.java
@@ -53,4 +53,49 @@ { Aci.decode(ByteString.valueOfUtf8(aciString), DN.rootDN()); } /** * ACIs whose userdn LDAP URL contains a malformed bracketed IPv6 host - see * issue #726. * * @return The malformed ACIs. */ @DataProvider public Object[][] malformedIPv6HostAcis() { return new Object[][] { { "(version 3.0; acl \"f\"; allow (search) userdn=\"q://[:1\"; )" }, { "(version 3.0; acl \"f\"; allow (search) userdn=\"ldap://[::1:389/dc=example,dc=com\"; )" }, }; } /** * A malformed bracketed IPv6 host in the userdn URL must be rejected with a * clean AciException instead of a StringIndexOutOfBoundsException - see * issue #726. * * @param aciString * The ACI to decode. * @throws Exception * If an unexpected exception occurred. */ @Test(dataProvider = "malformedIPv6HostAcis", expectedExceptions = AciException.class) public void testMalformedIPv6HostInUserDN(String aciString) throws Exception { Aci.decode(ByteString.valueOfUtf8(aciString), DN.rootDN()); } /** * A well-formed bracketed IPv6 host in the userdn URL must still decode. * * @throws Exception * If an unexpected exception occurred. */ @Test public void testValidIPv6HostInUserDN() throws Exception { String aciString = "(version 3.0; acl \"f\"; allow (search) " + "userdn=\"ldap://[::1]:389/uid=user,dc=example,dc=com\"; )"; Aci.decode(ByteString.valueOfUtf8(aciString), DN.rootDN()); } } opendj-server-legacy/src/test/java/org/opends/server/types/HostPortTest.java
@@ -12,6 +12,7 @@ * information: "Portions Copyright [year] [name of copyright owner]". * * Copyright 2013-2016 ForgeRock AS. * Portions Copyright 2026 3A Systems LLC. */ package org.opends.server.types; @@ -210,6 +211,71 @@ HostPort.valueOf("host:99999999"); } /** Issue #726: used to throw StringIndexOutOfBoundsException. */ @Test(expectedExceptions = IllegalArgumentException.class) public void valueOfOpeningBracketOnlyHost() { HostPort.valueOf("[:1"); } /** Issue #726: used to throw StringIndexOutOfBoundsException. */ @Test(expectedExceptions = IllegalArgumentException.class) public void valueOfOpeningBracketOnlyHostDefaultPort() { HostPort.valueOf("[", 1); } @Test(expectedExceptions = IllegalArgumentException.class) public void valueOfIPv6MissingClosingBracket() { HostPort.valueOf("[" + IPV6_ADDRESS + ":389"); } @Test(expectedExceptions = IllegalArgumentException.class) public void valueOfIPv6MissingOpeningBracket() { HostPort.valueOf(IPV6_ADDRESS + "]:389"); } @Test(expectedExceptions = IllegalArgumentException.class) public void valueOfEmptyBracketsHost() { HostPort.valueOf("[]:389"); } @Test(expectedExceptions = IllegalArgumentException.class) public void valueOfEmptyString() { HostPort.valueOf(""); } /** Issue #726: used to throw StringIndexOutOfBoundsException. */ @Test(expectedExceptions = IllegalArgumentException.class) public void constructorOpeningBracketOnlyHost() { new HostPort("[", 1); } @Test(expectedExceptions = IllegalArgumentException.class) public void constructorMissingClosingBracket() { new HostPort("[" + IPV6_ADDRESS, 389); } @Test(expectedExceptions = IllegalArgumentException.class) public void constructorMissingOpeningBracket() { new HostPort(IPV6_ADDRESS + "]", 389); } @Test public void constructorBracketedIPv6() { final HostPort hp = new HostPort("[" + IPV6_ADDRESS + "]", 389); assertThat(hp.getHost()).isEqualTo(IPV6_ADDRESS); assertThat(hp.getPort()).isEqualTo(389); } @Test public void valueOfIPv6NoPort() {