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

Valery Kharseko
15 hours ago e53e018771bf9e30558e21950a8cbcd4c567e103
[#673] Fix ArrayIndexOutOfBoundsException on truncated percent-encoding in LDAP URLs (#676)
4 files modified
1 files added
131 ■■■■■ changed files
opendj-core/src/main/java/org/forgerock/opendj/ldap/LDAPUrl.java 7 ●●●●● patch | view | raw | blame | history
opendj-core/src/test/java/org/forgerock/opendj/ldap/LDAPUrlTestCase.java 30 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/types/LDAPURL.java 3 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/test/java/org/opends/server/authorization/dseecompat/UserDNTestCase.java 56 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/test/java/org/opends/server/types/LDAPURLTestCase.java 35 ●●●●● patch | view | raw | blame | history
opendj-core/src/main/java/org/forgerock/opendj/ldap/LDAPUrl.java
@@ -13,6 +13,7 @@
 *
 * Copyright 2010 Sun Microsystems, Inc.
 * Portions copyright 2012-2016 ForgeRock AS.
 * Portions Copyright 2026 3A Systems, LLC
 */
package org.forgerock.opendj.ldap;
@@ -246,6 +247,12 @@
                dstPos++;
                continue;
            }
            if (srcPos + 2 >= decoded.length()) {
                // A percent sign must be followed by two hexadecimal digits.
                final LocalizableMessage msg =
                        ERR_LDAPURL_INVALID_HEX_BYTE.get(urlString, index + srcPos + 1);
                throw new LocalizedIllegalArgumentException(msg);
            }
            int i = decodeHex(urlString, index + srcPos + 1, decoded.charAt(srcPos + 1)) << 4;
            int j = decodeHex(urlString, index + srcPos + 2, decoded.charAt(srcPos + 2));
            decoded.setCharAt(dstPos, (char) (i | j));
opendj-core/src/test/java/org/forgerock/opendj/ldap/LDAPUrlTestCase.java
@@ -12,6 +12,7 @@
 * information: "Portions Copyright [year] [name of copyright owner]".
 *
 * Copyright 2010 Sun Microsystems, Inc.
 * Portions Copyright 2026 3A Systems, LLC
 */
package org.forgerock.opendj.ldap;
@@ -19,6 +20,7 @@
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import org.forgerock.i18n.LocalizedIllegalArgumentException;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
@@ -181,4 +183,32 @@
            assertTrue(url1.equals(url2));
        }
    }
    /**
     * URLs with a percent sign followed by fewer than two hexadecimal digits.
     *
     * @return The malformed URLs.
     */
    @DataProvider
    public Object[][] truncatedPercentUrls() {
        return new Object[][] {
            { "ldap:///cn=name%B" },
            { "ldap:///cn=name%" },
        };
    }
    /**
     * A truncated percent-encoded sequence must be rejected with a clean decode error
     * instead of a StringIndexOutOfBoundsException - see issue #673.
     *
     * @param url
     *            The URL to decode.
     * @throws Exception
     *             If the test failed unexpectedly.
     */
    @Test(dataProvider = "truncatedPercentUrls",
            expectedExceptions = LocalizedIllegalArgumentException.class)
    public void testTruncatedPercentEncoding(final String url) throws Exception {
        LDAPUrl.valueOf(url);
    }
}
opendj-server-legacy/src/main/java/org/opends/server/types/LDAPURL.java
@@ -13,6 +13,7 @@
 *
 * Copyright 2006-2008 Sun Microsystems, Inc.
 * Portions Copyright 2012-2016 ForgeRock AS.
 * Portions Copyright 2026 3A Systems, LLC
 */
package org.opends.server.types;
@@ -621,7 +622,7 @@
      {
        // There must be at least two bytes left.  If not, then that's
        // a problem.
        if (i+2 > length)
        if (i+2 >= length)
        {
          LocalizableMessage message = ERR_LDAPURL_PERCENT_TOO_CLOSE_TO_END.get(s, i);
          throw new DirectoryException(
opendj-server-legacy/src/test/java/org/opends/server/authorization/dseecompat/UserDNTestCase.java
New file
@@ -0,0 +1,56 @@
/*
 * The contents of this file are subject to the terms of the Common Development and
 * Distribution License (the License). You may not use this file except in compliance with the
 * License.
 *
 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
 * specific language governing permission and limitations under the License.
 *
 * When distributing Covered Software, include this CDDL Header Notice in each file and include
 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
 * Header, with the fields enclosed by brackets [] replaced by your own identifying
 * information: "Portions Copyright [year] [name of copyright owner]".
 *
 * Copyright 2026 3A Systems, LLC
 */
package org.opends.server.authorization.dseecompat;
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.DN;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
/** Tests for decoding of the userdn bind rule. */
public class UserDNTestCase extends AciTestCase
{
  /**
   * ACIs whose userdn LDAP URL contains a percent sign followed by fewer than
   * two hexadecimal digits - see issue #673.
   *
   * @return The malformed ACIs.
   */
  @DataProvider
  public Object[][] truncatedPercentAcis()
  {
    return new Object[][] {
      { "(version 3.0; acl \":\"; allow (search) userdn=\"ldap://cn=name%B\"; )" },
      { "(version 3.0; acl \":\"; allow (search) userdn=\"ldap://cn=name%\"; )" },
    };
  }
  /**
   * A truncated percent-encoded sequence in the userdn URL must be rejected
   * with a clean AciException instead of an ArrayIndexOutOfBoundsException -
   * see issue #673.
   *
   * @param aciString
   *          The ACI to decode.
   * @throws Exception
   *           If an unexpected exception occurred.
   */
  @Test(dataProvider = "truncatedPercentAcis", expectedExceptions = AciException.class)
  public void testTruncatedPercentInUserDN(String aciString) throws Exception
  {
    Aci.decode(ByteString.valueOfUtf8(aciString), DN.rootDN());
  }
}
opendj-server-legacy/src/test/java/org/opends/server/types/LDAPURLTestCase.java
@@ -12,6 +12,7 @@
 * information: "Portions Copyright [year] [name of copyright owner]".
 *
 * Portions Copyright 2012-2016 ForgeRock AS.
 * Portions Copyright 2026 3A Systems, LLC
 */
package org.opends.server.types;
@@ -98,4 +99,38 @@
    assertEquals(url.getRawFilter(), filterString);
  }
  /**
   * Test data for testTruncatedPercentEncoding.
   *
   * @return URLs with a percent sign followed by fewer than two hexadecimal digits.
   */
  @DataProvider
  public Object[][] truncatedPercentData()
  {
    return new Object[][] {
        { "ldap:///cn=name%B" },
        { "ldap:///cn=name%" },
    };
  }
  /**
   * A percent sign followed by fewer than two hexadecimal digits must be rejected with a
   * clean decode error instead of an ArrayIndexOutOfBoundsException - see issue #673.
   *
   * @param urlString
   *          The URL to decode.
   * @throws Exception
   *           If an unexpected exception occurred.
   */
  @Test(dataProvider = "truncatedPercentData",
        expectedExceptions = DirectoryException.class)
  public void testTruncatedPercentEncoding(String urlString) throws Exception
  {
    LDAPURL.decode(urlString, true);
  }
}