javascript regular expression for DN

Muhammad Imran Tariq picture Muhammad Imran Tariq · Feb 15, 2012 · Viewed 9k times · Source

I wan a regex to alidate all types of possible DN's

I create one but its not so good.

/([A-z0-9=]{1}[A-z0-9]{1})*[,??]/ and some others by changing it, but in vain.

Posible DN's can be

CN=abcd,CN=abcd,O=abcd,C=us
CN=abcd0520,CN=users,O=abcd,C=us
C=us

etc

Answer

Glenn Lane picture Glenn Lane · Oct 21, 2014

I recently had a need for this, so I created one that perfectly follows the LDAPv3 distinguished name syntax at RFC-2253.

Attribute Type

An attributeType can be expressed 2 ways. An alphanumeric string that starts with an alpha, validated using:

[A-Za-z][\w-]*

Or it can be an OID, validated using:

\d+(?:\.\d+)*

So attributeType validates using:

[A-Za-z][\w-]*|\d+(?:\.\d+)*

Attribute Value

An attributeValue can be expressed 3 ways. A hex string, which is a sequence of hex-pairs with a leading #. A hex string validates using:

#(?:[\dA-Fa-f]{2})+

Or an escaped string; each non-special character is expressed "as-is" (validates using [^,=\+<>#;\\"]). Special characters can be expressed with a leading \ (validates using \\[,=\+<>#;\\"]). Finally any character can be expressed as a hex-pair with a leading \ (validates using \\[\dA-Fa-f]{2}). An escaped string validates using:

(?:[^,=\+<>#;\\"]|\\[,=\+<>#;\\"]|\\[\dA-Fa-f]{2})*

Or a quoted-string; the value starts and ends with ", and can contain any character un-escaped except \ and ". Additionally, any of the methods from the escaped string above can be used. A quoted-string validates using:

"(?:[^\\"]|\\[,=\+<>#;\\"]|\\[\dA-Fa-f]{2})*"

All combined, an attributeValue validates using:

#(?:[\dA-Fa-f]{2})+|(?:[^,=\+<>#;\\"]|\\[,=\+<>#;\\"]|\\[\dA-Fa-f]{2})*|"(?:[^\\"]|\\[,=\+<>#;\\"]|\\[\dA-Fa-f]{2})*"

Name component

A name-component in BNF is:

name-component = attributeTypeAndValue *("+" attributeTypeAndValue)
attributeTypeAndValue = attributeType "=" attributeValue

In RegEx is:

(?#attributeType)=(?#attributeValue)(?:\+(?#attributeType)=(?#attributeValue))*

Replacing the (?#attributeType) and (?#attributeValue) placeholders with the values above gives us:

(?:[A-Za-z][\w-]*|\d+(?:\.\d+)*)=(?:#(?:[\dA-Fa-f]{2})+|(?:[^,=\+<>#;\\"]|\\[,=\+<>#;\\"]|\\[\dA-Fa-f]{2})*|"(?:[^\\"]|\\[,=\+<>#;\\"]|\\[\dA-Fa-f]{2})*")(?:\+(?:[A-Za-z][\w-]*|\d+(?:\.\d+)*)=(?:#(?:[\dA-Fa-f]{2})+|(?:[^,=\+<>#;\\"]|\\[,=\+<>#;\\"]|\\[\dA-Fa-f]{2})*|"(?:[^\\"]|\\[,=\+<>#;\\"]|\\[\dA-Fa-f]{2})*"))*

Which validates a single name-component.

Distinguished name

Finally, the BNF for a distinguished name is:

name-component *("," name-component)

In RegEx is:

(?#name-component)(?:,(?#name-component))*

Replacing the (?#name-component) placeholder with the value above gives us:

^(?:[A-Za-z][\w-]*|\d+(?:\.\d+)*)=(?:#(?:[\dA-Fa-f]{2})+|(?:[^,=\+<>#;\\"]|\\[,=\+<>#;\\"]|\\[\dA-Fa-f]{2})*|"(?:[^\\"]|\\[,=\+<>#;\\"]|\\[\dA-Fa-f]{2})*")(?:\+(?:[A-Za-z][\w-]*|\d+(?:\.\d+)*)=(?:#(?:[\dA-Fa-f]{2})+|(?:[^,=\+<>#;\\"]|\\[,=\+<>#;\\"]|\\[\dA-Fa-f]{2})*|"(?:[^\\"]|\\[,=\+<>#;\\"]|\\[\dA-Fa-f]{2})*"))*(?:,(?:[A-Za-z][\w-]*|\d+(?:\.\d+)*)=(?:#(?:[\dA-Fa-f]{2})+|(?:[^,=\+<>#;\\"]|\\[,=\+<>#;\\"]|\\[\dA-Fa-f]{2})*|"(?:[^\\"]|\\[,=\+<>#;\\"]|\\[\dA-Fa-f]{2})*")(?:\+(?:[A-Za-z][\w-]*|\d+(?:\.\d+)*)=(?:#(?:[\dA-Fa-f]{2})+|(?:[^,=\+<>#;\\"]|\\[,=\+<>#;\\"]|\\[\dA-Fa-f]{2})*|"(?:[^\\"]|\\[,=\+<>#;\\"]|\\[\dA-Fa-f]{2})*"))*)*$

Test it here