| | |
| | | * |
| | | * 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.*; |
| | |
| | | // 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(); |
| | |
| | | |
| | | // 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++); |
| | |
| | | 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--; |
| | |
| | | // 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) |
| | |
| | | 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 == '\\') |
| | |
| | | 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); |
| | | } |
| | | } |
| | |
| | | { |
| | | 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); |