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

Matthew Swift
16.15.2016 a3765efb5b8fda69465b9f8fb433bdf16eb21307
OPENDJ-2776 Remove trailing spaces from AVAs and RDNs during parsing

Leading and trailing whitespace in RDN attribute values must be escaped
according to RFC 4514, otherwise the RDN is invalid. However, it is
often best practice to be tolerant of malformed data, so we should
really trim off any leading or trailing whitespaces. The AVA class was
already trimming leading whitespace, but not trailing.
3 files modified
55 ■■■■■ changed files
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/AVA.java 5 ●●●●● patch | view | raw | blame | history
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/AVATestCase.java 28 ●●●●● patch | view | raw | blame | history
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/RDNTestCase.java 22 ●●●●● patch | view | raw | blame | history
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/AVA.java
@@ -182,6 +182,7 @@
        reader.skipWhitespaces();
        boolean escaped = false;
        int trailingSpaces = 0;
        while (reader.remaining() > 0) {
            final char c = reader.read();
            if (escaped) {
@@ -216,21 +217,25 @@
                escaped = false;
            } else if (c == '\\') {
                escaped = true;
                trailingSpaces = 0;
            } else {
                // Check for delimited chars.
                if (c == '+' || c == ',' || c == ';') {
                    reader.reset();
                    appendHexChars(reader, valueBuffer, hexBuffer);
                    valueBuffer.setLength(valueBuffer.length() - trailingSpaces);
                    return ByteString.valueOfUtf8(valueBuffer);
                }
                // It is definitely not a delimiter at this point.
                appendHexChars(reader, valueBuffer, hexBuffer);
                valueBuffer.append(c);
                trailingSpaces = c != ' ' ? 0 : trailingSpaces + 1;
            }
            reader.mark();
        }
        reader.reset();
        valueBuffer.setLength(valueBuffer.length() - trailingSpaces);
        return ByteString.valueOfUtf8(valueBuffer);
    }
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/AVATestCase.java
@@ -52,4 +52,32 @@
        final String roundtrippedValue = AVA.valueOf(avaString).toString();
        assertThat(AVA.valueOf(roundtrippedValue).toString()).isEqualTo(avaString);
    }
    @DataProvider
    public Object[][] toStringShouldStripOutIllegalWhitespaceDataProvider() {
        // @formatter:off
        return new Object[][] {
            { " dc = hello  world ", "dc=hello  world" },
            { " dc =\\  hello  world\\  ", "dc=\\  hello  world\\ " },
        };
        // @formatter:on
    }
    @Test(dataProvider = "toStringShouldStripOutIllegalWhitespaceDataProvider")
    public void toStringShouldStripOutIllegalWhitespace(String withWhiteSpace, String withoutWhiteSpace) {
        assertThat(AVA.valueOf(withWhiteSpace).toString()).isEqualTo(withoutWhiteSpace);
        assertThat(AVA.valueOf(withWhiteSpace).toNormalizedByteString(new ByteStringBuilder()))
                .isEqualTo(AVA.valueOf(withoutWhiteSpace).toNormalizedByteString(new ByteStringBuilder()));
    }
    @Test
    public void avaConstructedWithValueContainingLeadingAndTrailingSpacesShouldBeEscaped() {
        AVA ava = new AVA("dc", " hello  world ");
        assertThat(ava.toString()).isEqualTo("dc=\\ hello  world\\ ");
    }
    @Test
    public void valueOfDecodesTrailingEscapedChars() {
        assertThat(AVA.valueOf("dc=\\41\\42\\43").toString()).isEqualTo("dc=ABC");
    }
}
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/RDNTestCase.java
@@ -12,12 +12,12 @@
 * information: "Portions Copyright [year] [name of copyright owner]".
 *
 * Copyright 2010 Sun Microsystems, Inc.
 * Portions copyright 2011-2015 ForgeRock AS.
 * Portions copyright 2011-2016 ForgeRock AS.
 */
package org.forgerock.opendj.ldap;
import static org.fest.assertions.Assertions.*;
import static org.assertj.core.api.Assertions.assertThat;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
@@ -449,4 +449,22 @@
                    .isNotEqualTo(h2);
        }
    }
    @DataProvider
    public Object[][] toStringShouldStripOutIllegalWhitespaceDataProvider() {
        // @formatter:off
        return new Object[][] {
            { " dc = hello  world ", "dc=hello  world" },
            { " dc =\\  hello  world\\  ", "dc=\\  hello  world\\ " },
            { " uid = cpfc + dc = example ", "uid=cpfc+dc=example" },
        };
        // @formatter:on
    }
    @Test(dataProvider = "toStringShouldStripOutIllegalWhitespaceDataProvider")
    public void toStringShouldStripOutIllegalWhitespace(String withWhiteSpace, String withoutWhiteSpace) {
        assertThat(RDN.valueOf(withWhiteSpace).toString()).isEqualTo(withoutWhiteSpace);
        assertThat(RDN.valueOf(withWhiteSpace).toNormalizedByteString(new ByteStringBuilder()))
                .isEqualTo(RDN.valueOf(withoutWhiteSpace).toNormalizedByteString(new ByteStringBuilder()));
    }
}