From 3f4deb91789189521d577457bd6da27de8fd75b1 Mon Sep 17 00:00:00 2001
From: Valery Kharseko <vharseko@3a-systems.ru>
Date: Wed, 07 Oct 2026 08:31:10 +0000
Subject: [PATCH] [#1153] Parse the whole DN string, and build or split DN strings through DN instead of string operations (#1171)
---
opendj-server-legacy/src/main/java/org/opends/server/authorization/dseecompat/PatternDN.java | 38 ++++++++++++++++++++++++++++++++------
1 files changed, 32 insertions(+), 6 deletions(-)
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/authorization/dseecompat/PatternDN.java b/opendj-server-legacy/src/main/java/org/opends/server/authorization/dseecompat/PatternDN.java
index d93fea0..5275c41 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/authorization/dseecompat/PatternDN.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/authorization/dseecompat/PatternDN.java
@@ -13,9 +13,11 @@
*
* Copyright 2008 Sun Microsystems, Inc.
* Portions Copyright 2014-2016 ForgeRock AS.
+ * Portions Copyright 2026 3A Systems, LLC.
*/
package org.opends.server.authorization.dseecompat;
+import static com.forgerock.opendj.ldap.CoreMessages.ERR_ATTR_SYNTAX_DN_TRAILING_ESCAPE;
import static org.opends.messages.AccessControlMessages.*;
import static org.opends.messages.SchemaMessages.*;
import static org.opends.server.util.CollectionUtils.*;
@@ -973,7 +975,13 @@
// Look at the first character. If it is an octothorpe (#), then
// that means that the value should be a hex string.
char c = dnString.charAt(pos++);
- if (c == '#')
+ if (c == ',' || c == ';' || c == '+')
+ {
+ // The value is empty and followed by the next RDN or AVA, as DN.valueOf() reads it.
+ attributeValues.add(ByteString.empty());
+ return pos - 1;
+ }
+ else if (c == '#')
{
// The first two characters must be hex characters.
StringBuilder hexString = new StringBuilder();
@@ -999,7 +1007,7 @@
// The rest of the value must be a multiple of two hex
// characters. The end of the value may be designated by the
- // end of the DN, a comma or semicolon, or a space.
+ // end of the DN, a comma or semicolon, a plus sign, or a space.
while (pos < length)
{
c = dnString.charAt(pos++);
@@ -1026,7 +1034,7 @@
throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX, message);
}
}
- else if (c == ' ' || c == ',' || c == ';')
+ else if (c == ' ' || c == ',' || c == ';' || c == '+')
{
// This denotes the end of the value.
pos--;
@@ -1063,6 +1071,7 @@
// Keep reading until we find an unescaped closing quotation mark.
boolean escaped = false;
StringBuilder valueString = new StringBuilder();
+ StringBuilder hexChars = new StringBuilder();
while (true)
{
if (pos >= length)
@@ -1076,9 +1085,18 @@
c = dnString.charAt(pos++);
if (escaped)
{
- // The previous character was an escape, so we'll take this
- // one no matter what.
- valueString.append(c);
+ // The previous character was an escape. As in an unquoted value, and as DN.valueOf() reads
+ // a quoted value, an escaped pair of hex digits is one byte of the UTF-8 encoded value.
+ if (isHexDigit(c) && pos < length && isHexDigit(dnString.charAt(pos)))
+ {
+ hexChars.append(c);
+ hexChars.append(dnString.charAt(pos++));
+ }
+ else
+ {
+ appendHexChars(dnString, valueString, hexChars);
+ valueString.append(c);
+ }
escaped = false;
}
else if (c == '\\')
@@ -1090,12 +1108,14 @@
else if (c == '"')
{
// This is the end of the value.
+ appendHexChars(dnString, valueString, hexChars);
break;
}
else
{
// This is just a regular character that should be in the
// value.
+ appendHexChars(dnString, valueString, hexChars);
valueString.append(c);
}
}
@@ -1131,6 +1151,12 @@
{
if (pos >= length)
{
+ if (escaped)
+ {
+ // A lone backslash at the end, which DN.valueOf() rejects with the same message.
+ throw new DirectoryException(ResultCode.INVALID_DN_SYNTAX,
+ ERR_ATTR_SYNTAX_DN_TRAILING_ESCAPE.get(dnString));
+ }
// This is the end of the DN and therefore the end of the value.
// If there are any hex characters, then we need to deal with them accordingly.
appendHexChars(dnString, valueString, hexChars);
--
Gitblit v1.10.0