mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Valery Kharseko
yesterday 07bad95016f2cfafaf217114f9b0b50429af7d2f
[#726] Reject malformed bracketed IPv6 hosts in HostPort (#732)
3 files modified
148 ■■■■■ changed files
opendj-server-legacy/src/main/java/org/opends/server/types/HostPort.java 37 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/test/java/org/opends/server/authorization/dseecompat/UserDNTestCase.java 45 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/test/java/org/opends/server/types/HostPortTest.java 66 ●●●●● patch | view | raw | blame | history
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,15 +308,24 @@
   * @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;
    }
    return host.substring(1, host.length() - 1);
    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 + "'");
  }
  /**
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()
  {