https://bugs.openldap.org/show_bug.cgi?id=9817
Issue ID: 9817 Summary: rwm overlay : Issue with DN containing special characters Product: OpenLDAP Version: unspecified Hardware: All OS: All Status: UNCONFIRMED Keywords: needs_review Severity: normal Priority: --- Component: overlays Assignee: bugs@openldap.org Reporter: thierry.pubellier@paris.fr Target Milestone: ---
Hi,
I'm using rwn to select the database useg for bind operations based on the result of a rewriteMap requets.
Sample configuration in global section : #Rewrite Map to request a remote server rwm-rewriteMap ldap checkEntry "ldap://10.1.2.3/ou=users,dc=paris,dc=local?dn?sub" binddn="cn=myuser,ou=users,dc=paris,dc=local" credentials="XXX" # Backing up original DN rwm-rewriteRule ".+" "${&binddn($0)}$0" ":" # Contructing LDAP Filter for remote search. Combined with a rewrite Map, the requested DN is returned if there is a match. rwm-rewriteRule ".+" "(&(!(description=TEST))(distinguishedName=$0))" ":" # If filter matches, end of rewriting. Going to 'dc=paris,dc=local' database rwm-rewriteRule ".+" "${checkIfPasswordExpiredDN($0)}" ":@I" # Otherwise, restoring the original DN. rwm-rewriteRule ".+" "${*binddn}" ":" # And final DN massaging from "dc=paris,dc=local" to "dc=paris,dc=local2" database rwm-rewriteRule "(.+,)?ou=users,dc=paris,dc=local$" "$1ou=users,dc=paris,dc=local2" ":@"
Everything goes fine until I use DN with special characters, like ',' or '['. For example : 'cn=Pubellier, Thierry (TEST),ou=users,dc=paris,dc=local'
In this case, the rwm-rewriteRule contructs a LDAP filter with incorrect syntax, as special caracters are not being escaped.
I have to use some ugly tricks to escape these caracters, as shown below : #Rewrite Map to request a remote server rwm-rewriteMap ldap checkEntry "ldap://10.1.2.3/ou=users,dc=paris,dc=local?dn?sub" binddn="cn=myuser,ou=users,dc=paris,dc=local" credentials="XXX" # Backing up original DN rwm-rewriteRule ".+" "${&binddn($0)}$0" ":" # Rewriting for ',' rwm-rewriteRule "(.+).\2C(.+)" "$1\,$2" # Adding a special '#' (asserting it in none of my DNs) suffix for special characters, in order to escape them without looping forever rwm-rewriteRule "(.*)([)*(\])([^#].*|$)" "$1$2#$3" # Escaping of special characters with dedicated '#' suffix, avoiding infinite loops rwm-rewriteRule "(.*)([)*(\])#(.*)" "$1\$2$3" # Contructing LDAP Filter for remote search. Combined with a rewrite Map, the requested DN is returned if there is a match. rwm-rewriteRule ".+" "(&(!(description=TEST))(distinguishedName=$0))" ":" # If filter matches, end of rewriting. Going to 'dc=paris,dc=local' database rwm-rewriteRule ".+" "${checkIfPasswordExpiredDN($0)}" ":@I" # Otherwise, restoring the original DN. rwm-rewriteRule ".+" "${*binddn}" ":" # And final DN massaging from "dc=paris,dc=local" to "dc=paris,dc=local2" database rwm-rewriteRule "(.+,)?ou=users,dc=paris,dc=local$" "$1ou=users,dc=paris,dc=local2" ":@"
Could there be a way to integrate the ldap escape mechanism when making an variable assignment (like using a '#' character in place of the usual '&') ?
Thanks by advance,
Best regards,
Thierry
https://bugs.openldap.org/show_bug.cgi?id=9817
--- Comment #1 from Quanah Gibson-Mount quanah@openldap.org --- Please specify the version of OpenLDAP you are using, thanks.
https://bugs.openldap.org/show_bug.cgi?id=9817
Thierry PUBELLIER thierry.pubellier@paris.fr changed:
What |Removed |Added ---------------------------------------------------------------------------- Version|unspecified |2.6.1
https://bugs.openldap.org/show_bug.cgi?id=9817
Thierry PUBELLIER thierry.pubellier@paris.fr changed:
What |Removed |Added ---------------------------------------------------------------------------- OS|All |Linux Hardware|All |x86_64
https://bugs.openldap.org/show_bug.cgi?id=9817
--- Comment #2 from Thierry PUBELLIER thierry.pubellier@paris.fr --- Hi,
I am running OpenLDAP 2.6.1, on Ubuntu 20.04.
I updated the description of this issue.
Best regards,
Thierry
https://bugs.openldap.org/show_bug.cgi?id=9817
Quanah Gibson-Mount quanah@openldap.org changed:
What |Removed |Added ---------------------------------------------------------------------------- Keywords|needs_review | Target Milestone|--- |2.6.3
https://bugs.openldap.org/show_bug.cgi?id=9817
--- Comment #3 from Ondřej Kuzník ondra@mistotebe.net --- On Thu, Mar 24, 2022 at 09:30:08PM +0000, openldap-its@openldap.org wrote:
I'm using rwn to select the database useg for bind operations based on the result of a rewriteMap requets.
[...]
Everything goes fine until I use DN with special characters, like ',' or '['. For example : 'cn=Pubellier, Thierry (TEST),ou=users,dc=paris,dc=local'
In this case, the rwm-rewriteRule contructs a LDAP filter with incorrect syntax, as special caracters are not being escaped.
Hi Thierry, it's been a while since I've done anything of note with rwm and the configuration snippet you provided is missing substantial elements, e.g. a workable definition of the checkIfPasswordExpiredDN map. Could you provide a minimal script (preferably one that can be included in the OpenLDAP regression suite) that reproduces this?
Thanks,
https://bugs.openldap.org/show_bug.cgi?id=9817
--- Comment #4 from Quanah Gibson-Mount quanah@openldap.org --- Hi Thierry,
Can you please answer Ondrej's questions in comment#3?
Thanks!
https://bugs.openldap.org/show_bug.cgi?id=9817
--- Comment #5 from Thierry PUBELLIER thierry.pubellier@paris.fr --- Hi,
Please accept my apologies for responding so lately and for the imprecision of my request.
Basically, I want to route bind operations to different databases based on the result of a LDAP request : - The initial bind operation is for cn=myuser,ou=users,dc=paris,dc=local - If there is a match for a LDAP search on a remote server, I want to choose local database A (dc=paris,dc=local), whose suffix is the same than the remote one. Otherwise, I want to choose database B (dc=paris2,dc=local), whose suffix can be obtained with basic substitution.
Here my global configuration, with the correct rewriteMap : rwm-rewriteEngine on # Line 1 rwm-rewriteContext bindDN # Line 2 rwm-rewriteMap ldap checkIfPasswordExpiredDN "ldaps://10.2.3.4/ou=users,dc=paris,dc=local?dn?sub" binddn="remote-DN" credentials="remote-cred" # Line 3 rwm-rewriteRule ".+" "${&binddn($0)}$0" ":" # Line 4 : backup of the initial DN rwm-rewriteRule ".+" "(&(!(description=TEST))(distinguishedName=$0))" ":" # Line 5 : creating LDAP filter based on the original DN. rwm-rewriteRule ".+" "${checkIfPasswordExpiredDN($0)}" ":@I" # Line 6 : if there is a match, it will reflect the initial DN and stop rewriting rwm-rewriteRule ".+" "${*binddn}" ":" # Line 7 : restoring initial DN rwm-rewriteRule "(.+,)?ou=users,dc=paris,dc=local$" "$1ou=users,dc=paris2,dc=local" ":@" # Line 8 : basic substitution for A --> B
More generally, as I am working with "bindDN" rewrite context, data that will be manipulated is a DN. Using a rewrite-map (Line 6 above) will require the construction of a LDAP filter in a way like this : %myDN% --> (&(!(description=TEST))(distinguishedName=$0)), with the help of an rewrite-rule (Line "5" above). This works fine for DNs like "cn=myuser,ou=users,dc=paris,dc=local", which has no "," or other special characters in it.
But in my own directory, I have DNs like 'cn=Pubellier, Thierry (TEST),ou=users,dc=paris,dc=local'. In this case, line 5 will generate an incorrect LDAP filter. So I need to simulate an escape of the special characters (according to RFC 4515, like with 'escape_filter_value' in Net::LDAP::Util Perl Module) : - for ",", I need to insert a line like 'rwm-rewriteRule "(.+).\2C(.+)" "$1\,$2"', as the "," character seems to be replace internally by a '\2C'. - for other special characters ( ')', '*', '(' and ''), I try to emulate the escape mechanism, in an unperfect way, with the two following lines : rwm-rewriteRule "(.*)([)*(\])([^#].*|$)" "$1$2#$3" # Supposing there is no '#' in my DNs, I add a '#' after each special character. rwm-rewriteRule "(.*)([)*(\])#(.*)" "$1\$2$3" # I replace each 1 special character + '#' by ''+ special character. This trick avoids infinite loop for adding an '' before each special character.
So my request is to have a way to natively escape the DN value, like having a '#' operator in place of the usual '&' for use in Substitution Patterns.
Could you please precise me what is OpenLDAP regression suite ? Is this a test/scripts directory of OpenLDAP source ? In this case, I'll try to make a script to reproduce my issue.
Best regards,
Thierry
https://bugs.openldap.org/show_bug.cgi?id=9817
--- Comment #6 from Quanah Gibson-Mount quanah@openldap.org --- (In reply to Thierry PUBELLIER from comment #5)
Could you please precise me what is OpenLDAP regression suite ? Is this a test/scripts directory of OpenLDAP source ? In this case, I'll try to make a script to reproduce my issue.
tests/data/regressions has various regression suite tests for different ITSes.
https://bugs.openldap.org/show_bug.cgi?id=9817
--- Comment #7 from Thierry PUBELLIER thierry.pubellier@paris.fr --- Hi Quanah,
Thank you for the clarification. I'm looking on it.
Best regards,
Thierry
https://bugs.openldap.org/show_bug.cgi?id=9817
Quanah Gibson-Mount quanah@openldap.org changed:
What |Removed |Added ---------------------------------------------------------------------------- Assignee|bugs@openldap.org |ondra@mistotebe.net
https://bugs.openldap.org/show_bug.cgi?id=9817
--- Comment #8 from Ondřej Kuzník ondra@mistotebe.net --- Maybe we could introduce a new rewrite map 'dn2filter' or somesuch, which unescapes DN-special characters (e.g. '=', ',', '+', ...) and escapes filter-special characters (parentheses, '*', ...) correctly. Then you could add that between lines 4 and 5 in your example. Or pairs of 'escapeDN'+'unescapeDN' and 'escapeFilter'+'unescapeFilter' for more free-form work (and call 'unescapeDN' then 'escapeFilter').
librewrite already calls into libldap so if there are helpers there that might be of use, we'd be free to call them.
https://bugs.openldap.org/show_bug.cgi?id=9817
--- Comment #9 from Thierry PUBELLIER thierry.pubellier@paris.fr --- Created attachment 901 --> https://bugs.openldap.org/attachment.cgi?id=901&action=edit Regression script for ITS9817
https://bugs.openldap.org/show_bug.cgi?id=9817
--- Comment #10 from Thierry PUBELLIER thierry.pubellier@paris.fr --- Hi Ondřej,
This could be a very good solution to my issue. Wish it could be added to OpenLDAP in a future release.
I created a regression script. Please fin it attached.
Best regards,
Thierry
https://bugs.openldap.org/show_bug.cgi?id=9817
--- Comment #11 from Ondřej Kuzník ondra@mistotebe.net --- On Thu, May 19, 2022 at 08:11:49PM +0000, openldap-its@openldap.org wrote:
https://bugs.openldap.org/show_bug.cgi?id=9817
--- Comment #10 from Thierry PUBELLIER thierry.pubellier@paris.fr --- Hi Ondřej,
This could be a very good solution to my issue. Wish it could be added to OpenLDAP in a future release.
I created a regression script. Please fin it attached.
Best regards,
Thierry
Hi Thierry, Haven't looked into adopting your script yet but I've now posted a draft MR here if you want to test it some: https://git.openldap.org/openldap/openldap/-/merge_requests/529
What it allows you to do is turn line 5 into something like:
rwm-rewriteMap escape escapeThisDN escape2filter rwm-rewriteRule ".+" "${escapeThisDN($0)}" ":" # make value safe for embedding in a filter assertion rwm-rewriteRule ".+" "(&(!(description=TEST))(entryDN=$0))" ":" # construct LDAP filter based on the escaped DN
Or you can chain them if you're parsing a part of a DN (it should even be safe for intermediate values to contain embedded nul bytes so long as the last step escapes them):
rwm-rewriteMap escape reencodeValue unescapeDN escape2filter # unescape value from DN and escape for use in a filter rwm-rewriteRule "^cn=([^,+]*)" "${reencodeValue($0)}" ":" # convert value for embedding in a filter assertion rwm-rewriteRule ".+" "(&(!(description=TEST))(cn=$0))" ":" # construct LDAP filter based on the escaped value of cn
Regards,
https://bugs.openldap.org/show_bug.cgi?id=9817
Ondřej Kuzník ondra@mistotebe.net changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|UNCONFIRMED |IN_PROGRESS Ever confirmed|0 |1
https://bugs.openldap.org/show_bug.cgi?id=9817
--- Comment #12 from Thierry PUBELLIER thierry.pubellier@paris.fr --- Hi Ondřej,
Thank you very much for making this MR so rapidly.
According to my tests, it works perfectly. This escaping mechanism allowed me to remove totally my ugly workaround, leaving only a clean configuration.
Do you need me to produce a test script based on the regression one's, so it can be included in the global tests suite ?
Best regards,
Thierry
https://bugs.openldap.org/show_bug.cgi?id=9817
Quanah Gibson-Mount quanah@openldap.org changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|IN_PROGRESS |RESOLVED Resolution|--- |FIXED
--- Comment #13 from Quanah Gibson-Mount quanah@openldap.org --- head:
• 56877e33 by Ondřej Kuzník at 2022-06-07T09:47:41+01:00 ITS#9817 Introduce DN and filter manipulation tools
RE26:
• c0bc8b45 by Ondřej Kuzník at 2022-06-07T15:59:06+00:00 ITS#9817 Introduce DN and filter manipulation tools
https://bugs.openldap.org/show_bug.cgi?id=9817
--- Comment #14 from Quanah Gibson-Mount quanah@openldap.org --- head:
• bb87cc89 by Ondřej Kuzník at 2022-06-17T12:25:28+01:00 ITS#9817 Fix test087 set up
RE26:
• 926bf389 by Ondřej Kuzník at 2022-06-23T18:42:19+00:00 ITS#9817 Fix test087 set up
https://bugs.openldap.org/show_bug.cgi?id=9817
Quanah Gibson-Mount quanah@openldap.org changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|RESOLVED |VERIFIED
https://bugs.openldap.org/show_bug.cgi?id=9817
--- Comment #15 from Quanah Gibson-Mount quanah@openldap.org --- head:
• 4697f4b3 by Ondřej Kuzník at 2022-09-01T10:09:27+01:00 ITS#9817 Fix leaks and nul-terminate string passed to ldap_bv2dn
• 9d528c11 by Ondřej Kuzník at 2022-09-02T16:49:45+01:00 ITS#9817 One more leak plugged
RE26:
• 681d7612 by Ondřej Kuzník at 2022-09-12T20:43:21+00:00 ITS#9817 Fix leaks and nul-terminate string passed to ldap_bv2dn
• e8566d09 by Ondřej Kuzník at 2022-09-12T20:45:33+00:00 ITS#9817 One more leak plugged