Description of problem: Suffix massaging fails for DNs containing UTF-8 characters after restarting slapd. Version-Release number of selected component (if applicable): openldap-servers-2.6.2-2.el9 How reproducible: Always when DN contains UTF-8 characters. Steps to Reproduce: 1. Install openldap-servers-2.6.2-2.el9.x86_64. 2. Set system locale to some UTF-8 locale, for example: localectl set-locale ja_JP.UTF-8 3. Set up LDAP backend and rwm overlay, for example: dn: olcDatabase={3}ldap,cn=config objectClass: olcDatabaseConfig objectClass: olcLDAPConfig olcDatabase: ldap olcSuffix: dc=local,dc=example,dc=com olcDbURI: ldap://remote.example.net/ ... dn: olcOverlay={0}rwm,olcDatabase={3}ldap,cn=config objectClass: olcOverlayConfig objectClass: olcRwmConfig olcOverlay: rwm olcRwmRewrite: rwm-suffixmassage "dc=remote,dc=example,dc=net" ... 4. Search an entry with DN containing UTF-8 characters. The resulting DN is correct: dn: cn=<UTF-8 characters>,dc=local,dc=example,dc=com 5. Restart slapd. 6. Search the same entry. The resulting DN is wrong: dn: dc=local,dc=example,dc=com Actual results: After restarting slapd, DNs containing UTF-8 characters are not correctly rewritten: dn: dc=local,dc=example,dc=com The issue is temporarily resolved by overwriting the same rwm setting: dn: olcOverlay={0}rwm,olcDatabase={3}ldap,cn=config changeType: modify replace: olcRwmRewrite olcRwmRewrite: rwm-suffixmassage "dc=remote,dc=example,dc=net" But when I restart slapd it happens again. Expected results: All DNs are correctly rewritten after restart. dn: cn=<UTF-8 characters>,dc=local,dc=example,dc=com Additional info: After some investigation, it turns out that this problem occurs when the Perl backend module is statically loaded at startup. When the Perl backend is initialized, locale of the main thread is set from the environment (LANG=ja_JP.UTF-8), and then the rwm regular expression "(.+,)?dc=remote,dc=example,dc=net" is compiled with UTF-8 enabled. On the other hand, LDAP searches are processed in a separate thread with LANG=C, so UTF-8 characters do not match the "." in the regular expression and elements before naming context are omitted. Note that "man 3p regcomp" states "If, when regexec() is called, the locale is different from when the regular expression was compiled, the result is undefined." This issue can be worked around by adding environment "LANG=C" or "PERL_SKIP_LOCALE_INIT=" to systemd service unit file.
Is this the same issue as the one described here: https://bugs.openldap.org/show_bug.cgi?id=9817 rwm overlay : Issue with DN containing special characters The above issue is fixed in version 2.6.3. Since RHEL 9 contains some packages built from the openldap source RPM, but not the server package, the openldap-epel package that build the server package must use the same source version (currently 2.6.2) in order to not introduce incompatibilities, but it might be possible to backport the fix for the above issue if this would be helpful. Do you think this would help your use case?
(In reply to Mattias Ellert from comment #1) > Is this the same issue as the one described here: > > https://bugs.openldap.org/show_bug.cgi?id=9817 > rwm overlay : Issue with DN containing special characters > > The above issue is fixed in version 2.6.3. > Since RHEL 9 contains some packages built from the openldap source RPM, but > not the server package, the openldap-epel package that build the server > package must use the same source version (currently 2.6.2) in order to not > introduce incompatibilities, but it might be possible to backport the fix > for the above issue if this would be helpful. Do you think this would help > your use case? Dear Mittias, Thank you for reply, but I don't think it is not the same issue as ours. In the issue you mention, the problem is that the input DN is not properly escaped when it is used as part of a search filter. In our case, on the other hand, the input DN is only used as the string to match the regex. The problem is that the locale when regexec() is called is different from when regcomp() was called. So backporting the fix you mention doesn't seem to help solve our problem. A possible solution to our issue would be ether of (1) Modify the RPM spec file to not load the Perl backend module statically at startup, or (2) Modify the rwm overlay code to ensure that the same locale is used when calling regcomp() and regexec(). Solution (1) doesn't really solve the problem, but because we don't use the Perl backend at all, it is enough for us. I think the preferred solution would be (2). Regards,
Is this issue present in the current upstream version of openldap (2.6.4) or is it fix there? I.e. is the bug already fixed upstream, or is it an upstream bug? From your description of the bug, I do not have enough information to reproduce it. Or possibly the information is there, but in a form I can not parse into something that makes sense to me. Can you please provide a reproducer with step by step instructions. Every command used and every config file needed.
Although I did not confirm, I believe that the issue is not fixed in the current upstream version. In our environment we are using an Azure AD LDAPS server as the remote database, but the problem can be reproduced using the same local LDAP server as follows: 1. Prepare a fresh RHEL9 installation. 2. Set system locale to some UTF-8 locale: $ sudo localectl set-locale en_US.UTF-8 3. Install epel repository and openldap: $ sudo dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm $ sudo dnf install openldap-servers openldap-clients 4. Start slapd (with default configuration): $ sudo systemctl start slapd 5. Configure mdb database to simulate the remote LDAP server: $ sudo ldapmodify -Y EXTERNAL -H ldapi:/// <<END dn: olcDatabase={2}mdb,cn=config changeType: modify replace: olcSuffix olcSuffix: dc=remote,dc=example,dc=net - replace: olcRootDN olcRootDN: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth - replace: olcAccess olcAccess: to * by anonymous read END 6. Configure ldap database with rwm overlay: $ sudo ldapadd -Y EXTERNAL -H ldapi:/// <<END dn: cn=module{0},cn=config objectClass: olcModuleList cn: module olcModulePath: /usr/lib64/openldap olcModuleLoad: back_ldap.la olcModuleLoad: rwm.la dn: olcDatabase={3}ldap,cn=config objectClass: olcDatabaseConfig objectClass: olcLDAPConfig olcDatabase: ldap olcRootDN: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth olcAccess: to * by anonymous read olcSuffix: dc=local,dc=example,dc=com olcDbURI: ldap:/// dn: olcOverlay={0}rwm,olcDatabase={3}ldap,cn=config objectClass: olcOverlayConfig objectClass: olcRwmConfig olcOverlay: rwm olcRwmRewrite: rwm-suffixmassage "dc=remote,dc=example,dc=net" END 7. Add some entries to the "remote" database: $ sudo ldapadd -Y EXTERNAL -H ldapi:/// <<END dn: dc=remote,dc=example,dc=net objectClass: dcObject objectClass: organization dc: remote o: example dn: cn=US-ASCII,dc=remote,dc=example,dc=net objectClass: device cn: US-ASCII dn: cn=UTF-8,dc=remote,dc=example,dc=net objectClass: device cn: UTF-8 8. Search the "remote" database: $ ldapsearch -x -H ldapi:/// -LLL -b dc=remote,dc=example,dc=net 1.1 The response is: dn: dc=remote,dc=example,dc=net dn: cn=US-ASCII,dc=remote,dc=example,dc=net dn:: Y24977y177y077ym77yN77yYLGRjPXJlbW90ZSxkYz1leGFtcGxlLGRjPW5ldA== $ echo Y24977y177y077ym77yN77yYLGRjPXJlbW90ZSxkYz1leGFtcGxlLGRjPW5ldA== | base64 -d cn=UTF-8,dc=remote,dc=example,dc=net 9. Search the "local" database: $ ldapsearch -x -H ldapi:/// -LLL -b dc=local,dc=example,dc=com 1.1 The response is correct; all DNs are rewritten as expected: dn: dc=local,dc=example,dc=com dn: cn=US-ASCII,dc=local,dc=example,dc=com dn:: Y24977y177y077ym77yN77yYLGRjPWxvY2FsLGRjPWV4YW1wbGUsZGM9Y29t $ echo Y24977y177y077ym77yN77yYLGRjPWxvY2FsLGRjPWV4YW1wbGUsZGM9Y29t | base64 -d cn=UTF-8,dc=local,dc=example,dc=com 10. Restart slapd $ sudo systemctl restart slapd 11. Search the "local" database: $ ldapsearch -x -H ldapi:/// -LLL -b dc=local,dc=example,dc=com 1.1 The response is wrong; "cn=UTF-8," is ommitted from DN of the third entry: dn: dc=local,dc=example,dc=com dn: cn=US-ASCII,dc=local,dc=example,dc=com dn: dc=local,dc=example,dc=com