https://bugs.openldap.org/show_bug.cgi?id=9657
Issue ID: 9657 Summary: Different access privileges required for SIMPLE BIND (attr: userPassword) and SASL BIND (whole entry) Product: OpenLDAP Version: 2.5.6 Hardware: All OS: All Status: UNCONFIRMED Severity: normal Priority: --- Component: slapd Assignee: bugs@openldap.org Reporter: dpa-openldap@aegee.org Target Milestone: ---
I configure a database with:
dn: cn=config objectClass: olcGlobal cn: config olcAuthzRegexp: uid=([^@,]+)(@aegee.org)?(,cn=aegee.org)?,cn=[^,]*,cn=auth uid=$1,ou=persons,o=AEGEE olcSaslSecProps: none
####################################################################### # LMDB database definitions ####################################################################### # dn: olcDatabase=mdb,cn=config objectClass: olcDatabaseConfig objectClass: olcMdbConfig olcDatabase: mdb olcDbMaxSize: 10485760 olcSuffix: o=AEGEE olcRootDN: uid=zzz,ou=persons,o=AEGEE olcRootPW: zzz olcDbDirectory: /home/d/ldap/aegee olcDbIndex: objectClass eq olcAccess: to dn.one="ou=persons,o=AEGEE" attrs=userPassword by anonymous auth olcAccess: to dn.one="ou=persons,o=AEGEE" by self read
fill the database with
/usr/local/bin/ldapadd -x -w zzz -D "uid=zzz;ou=persons;o=AEGEE" -H ldap://localhost <<ABC dn:o=AEGEE o:AEGEE objectClass:organization telephoneNumber:+32 2 246 0320 street:Rue du Noyer / Notelaarsstraat 55 st:Brussels postalAddress:Rue du Noyer / Notelaarsstraat 55, 1000 Brussels, Belgium
dn:ou=persons,o=AEGEE objectClass:organizationalUnit description:AEGEE members (persons) with account at https://my.aegee.eu/
dn: uid=lui.veve,ou=persons,o=AEGEE objectClass: top objectClass: person objectClass: organizationalPerson objectClass: inetOrgPerson sn: Veve cn: Lui Veve uid: lui.veve employeeNumber: 444 givenName: Lui mail: lui.veve@zzzz userPassword:: dXAx structuralObjectClass: inetOrgPerson ABC
Its content is ( slapcat -n1 -F conf/ ) ---- dn: o=AEGEE o: AEGEE objectClass: organization telephoneNumber: +32 2 246 0320 street: Rue du Noyer / Notelaarsstraat 55 st: Brussels postalAddress: Rue du Noyer / Notelaarsstraat 55, 1000 Brussels, Belgium structuralObjectClass: organization entryUUID: 223703d3-812e-405c-b57e-4233b55847c3 creatorsName: uid=zzz,ou=persons,o=AEGEE createTimestamp: 20210830161645Z entryCSN: 20210830161645.797291Z#000000#000#000000 modifiersName: uid=zzz,ou=persons,o=AEGEE modifyTimestamp: 20210830161645Z
dn: ou=persons,o=AEGEE objectClass: organizationalUnit description: AEGEE members (persons) with account at https://my.aegee.eu/ structuralObjectClass: organizationalUnit ou: persons entryUUID: 17f8ff72-250b-4cbd-873f-340aaed2f0d9 creatorsName: uid=zzz,ou=persons,o=AEGEE createTimestamp: 20210830161645Z entryCSN: 20210830161645.802430Z#000000#000#000000 modifiersName: uid=zzz,ou=persons,o=AEGEE modifyTimestamp: 20210830161645Z
dn: uid=lui.veve,ou=persons,o=AEGEE objectClass: top objectClass: person objectClass: organizationalPerson objectClass: inetOrgPerson sn: Veve cn: Lui Veve uid: lui.veve employeeNumber: 444 givenName: Lui mail:: bHVpLnZldmVAenp6eiA= userPassword:: dXAx structuralObjectClass: inetOrgPerson entryUUID: 2e37d641-6865-4a08-87f9-b12653f52d12 creatorsName: uid=zzz,ou=persons,o=AEGEE createTimestamp: 20210830161645Z entryCSN: 20210830161645.806532Z#000000#000#000000 modifiersName: uid=zzz,ou=persons,o=AEGEE modifyTimestamp: 20210830161645Z
----
When I try to authenticate with SIMPLE BIND, OpenLDAP requests only access to the userPassword attribute:
ldapwhoami -x -D "uid=lui.veve;ou=persons;o=AEGEE" -v -w up1 -H ldap://localhost/
logs:
612d04f3.27f67994 0x7f50731ac640 <= ldap_dn2bv(uid=lui.veve,ou=persons,o=AEGEE)=0 612d04f3.27f6a83b 0x7f50731ac640 => ldap_dn2bv(272) 612d04f3.27f6cbf9 0x7f50731ac640 <= ldap_dn2bv(uid=lui.veve,ou=persons,o=aegee)=0 612d04f3.27f6e92a 0x7f50731ac640 <<< dnPrettyNormal: <uid=lui.veve,ou=persons,o=AEGEE>, <uid=lui.veve,ou=persons,o=aegee> 612d04f3.27f7035b 0x7f50731ac640 conn=1001 op=0 BIND dn="uid=lui.veve,ou=persons,o=AEGEE" method=128 612d04f3.27f744d5 0x7f50731ac640 do_bind: version=3 dn="uid=lui.veve,ou=persons,o=AEGEE" method=128 612d04f3.27f77c7c 0x7f50731ac640 ==> mdb_bind: dn: uid=lui.veve,ou=persons,o=AEGEE 612d04f3.27f82a00 0x7f50731ac640 mdb_dn2entry("uid=lui.veve,ou=persons,o=aegee") 612d04f3.27f847bd 0x7f50731ac640 => mdb_dn2id("uid=lui.veve,ou=persons,o=aegee") 612d04f3.27f8a6f4 0x7f50731ac640 <= mdb_dn2id: got id=0x3 612d04f3.27f916cf 0x7f50731ac640 => mdb_entry_decode: 612d04f3.27f942bb 0x7f50731ac640 <= mdb_entry_decode 612d04f3.27f96490 0x7f50731ac640 => access_allowed: result not in cache (userPassword) 612d04f3.27f97b35 0x7f50731ac640 => access_allowed: auth access to "uid=lui.veve,ou=persons,o=AEGEE" "userPassword" requested 612d04f3.27f9ab7f 0x7f50731ac640 => dn: [1] ou=persons,o=aegee 612d04f3.27f9ccc7 0x7f50731ac640 => acl_get: [1] matched 612d04f3.27f9ddb2 0x7f50731ac640 => acl_get: [1] attr userPassword 612d04f3.27f9f63f 0x7f50731ac640 => acl_mask: access to entry "uid=lui.veve,ou=persons,o=AEGEE", attr "userPassword" requested 612d04f3.27fa0913 0x7f50731ac640 => acl_mask: to value by "", (=0) 612d04f3.27fa24a1 0x7f50731ac640 <= check a_dn_pat: anonymous 612d04f3.27fa492f 0x7f50731ac640 <= acl_mask: [1] applying auth(=xd) (stop) 612d04f3.27fa5bbd 0x7f50731ac640 <= acl_mask: [1] mask: auth(=xd) 612d04f3.27fa721c 0x7f50731ac640 => slap_access_allowed: auth access granted by auth(=xd) 612d04f3.27fa8306 0x7f50731ac640 => access_allowed: auth access granted by auth(=xd) 612d04f3.27fa9f20 0x7f50731ac640 conn=1001 op=0 BIND dn="uid=lui.veve,ou=persons,o=AEGEE" mech=SIMPLE bind_ssf=0 ssf=0 612d04f3.27fb0385 0x7f50731ac640 do_bind: v3 bind: "uid=lui.veve,ou=persons,o=AEGEE" to "uid=lui.veve,ou=persons,o=AEGEE"
When I try to SASL connect, then OpenLDAP requests access to the whole uid=lui.veve,ou=persons,o=AEGEE entry:
ldapwhoami -Y LOGIN -U"lui.veve" -v -w up1 -H ldap://localhost/
logs:
612d053d.03ab64b8 0x7f50731ac640 => ldap_bv2dn(uid=lui.veve,ou=persons,o=AEGEE,0) 612d053d.03abb462 0x7f50731ac640 <= ldap_bv2dn(uid=lui.veve,ou=persons,o=AEGEE)=0 612d053d.03abddda 0x7f50731ac640 => ldap_dn2bv(272) 612d053d.03abf0ad 0x7f50731ac640 <= ldap_dn2bv(uid=lui.veve,ou=persons,o=aegee)=0 612d053d.03ac070c 0x7f50731ac640 <<< dnNormalize: <uid=lui.veve,ou=persons,o=aegee> 612d053d.03ac2626 0x7f50731ac640 <==slap_sasl2dn: Converted SASL name to uid=lui.veve,ou=persons,o=aegee 612d053d.03ac68fe 0x7f50731ac640 slap_sasl_getdn: dn:id converted to uid=lui.veve,ou=persons,o=aegee 612d053d.03ac82e9 0x7f50731ac640 SASL Canonicalize [conn=1002]: slapAuthcDN="uid=lui.veve,ou=persons,o=aegee" 612d053d.03acd965 0x7f50731ac640 => mdb_search 612d053d.03ada119 0x7f50731ac640 mdb_dn2entry("uid=lui.veve,ou=persons,o=aegee") 612d053d.03adcf7a 0x7f50731ac640 => mdb_dn2id("uid=lui.veve,ou=persons,o=aegee") 612d053d.03ae10f4 0x7f50731ac640 <= mdb_dn2id: got id=0x3 612d053d.03ae33e0 0x7f50731ac640 => mdb_entry_decode: 612d053d.03ae6313 0x7f50731ac640 <= mdb_entry_decode 612d053d.03ae845b 0x7f50731ac640 => access_allowed: auth access to "uid=lui.veve,ou=persons,o=AEGEE" "entry" requested 612d053d.03aea02f 0x7f50731ac640 => dn: [1] ou=persons,o=aegee 612d053d.03aeba1a 0x7f50731ac640 => acl_get: [1] matched 612d053d.03aed0bf 0x7f50731ac640 => dn: [2] ou=persons,o=aegee 612d053d.03aee392 0x7f50731ac640 => acl_get: [2] matched 612d053d.03aef47c 0x7f50731ac640 => acl_get: [2] attr entry 612d053d.03af0c39 0x7f50731ac640 => acl_mask: access to entry "uid=lui.veve,ou=persons,o=AEGEE", attr "entry" requested 612d053d.03af2f6a 0x7f50731ac640 => acl_mask: to all values by "", (=0) 612d053d.03af45c9 0x7f50731ac640 <= check a_dn_pat: self 612d053d.03af513f 0x7f50731ac640 <= acl_mask: no more <who> clauses, returning =0 (stop) 612d053d.03af626f 0x7f50731ac640 => slap_access_allowed: auth access denied by =0 612d053d.03af7a71 0x7f50731ac640 => access_allowed: no more rules
This is inconsistent. SASL bind shall also request only AUTH access to the userPassword, just as SIMPLE BIND does.
Moreover, https://www.openldap.org/doc/admin25/access-control.html#Basic%20ACLs does suggest:
Generally one should start with some basic ACLs such as:
access to attrs=userPassword by self =xw by anonymous auth by * none
access to * by self write by users read by * none
So the suggestion is to grant "by anonymous auth" access only to attrs=userPassword , before granting any other access.
If I change to
olcAccess: to dn.one="ou=persons,o=AEGEE" by self read by anonymous auth
then both SASL BIND and SIMPLE BIND work.
Version 2.5.7-g22d1c5954e8629b.
https://bugs.openldap.org/show_bug.cgi?id=9657
Quanah Gibson-Mount quanah@openldap.org changed:
What |Removed |Added ---------------------------------------------------------------------------- Keywords| |needs_review
https://bugs.openldap.org/show_bug.cgi?id=9657
--- Comment #1 from Michael Ströder michael@stroeder.com --- On 8/30/21 18:35, openldap-its@openldap.org wrote:
This is inconsistent. SASL bind shall also request only AUTH access to the userPassword, just as SIMPLE BIND does.
Isn't that somewhat expected?
SASL has to find the user's entry and this requires at least auth access to the entry pseudo attribute.
Furthermore there are various password-less SASL mechs for which you might also want to have some authc access control, e.g. for temporarily deactivating authc.
https://bugs.openldap.org/show_bug.cgi?id=9657
--- Comment #2 from dpa-openldap@aegee.org dpa-openldap@aegee.org --- No, it is not expected. The expectation is to follow what the Guide suggests, and this is to grant auth privilege to anonymous only on the userPassword attribute. With the configuration
olcAuthzRegexp: uid=([^@,]+)(@aegee.org)?(,cn=aegee.org)?,cn=[^,]*,cn=auth uid=$1,ou=persons,o=AEGEE
I expect that the simple bind
ldapwhoami -x -D "uid=lui.veve;ou=persons;o=AEGEE" -w up1 -H ldap://localhost/
is in all matters identical to
ldapwhoami -Y LOGIN -U"lui.veve" -w up1 -H ldap://localhost/
and the whole purpose of olcAuthzRegexp is to rewrite the username.
SASL has to find the user's entry
Simple bind does not have to find the user’s entry?
https://bugs.openldap.org/show_bug.cgi?id=9657
Quanah Gibson-Mount quanah@openldap.org changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|UNCONFIRMED |RESOLVED Resolution|--- |INVALID Keywords|needs_review |
--- Comment #3 from Quanah Gibson-Mount quanah@openldap.org --- (In reply to dpa-openldap@aegee.org from comment #2)
No, it is not expected. The expectation is to follow what the Guide suggests, and this is to grant auth privilege to anonymous only on the userPassword attribute.
The guide is purely talking about simple binds in this case. The guide is not an exhaustive reference for the thousands of potential configurations possible.
https://bugs.openldap.org/show_bug.cgi?id=9657
Quanah Gibson-Mount quanah@openldap.org changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|RESOLVED |VERIFIED
https://bugs.openldap.org/show_bug.cgi?id=9657
--- Comment #4 from Michael Ströder michael@stroeder.com --- On 8/30/21 18:49, openldap-its@openldap.org wrote:
I expect that the simple bind
ldapwhoami -x -D "uid=lui.veve;ou=persons;o=AEGEE" -w up1 -H ldap://localhost/
is in all matters identical to
ldapwhoami -Y LOGIN -U"lui.veve" -w up1 -H ldap://localhost/
and the whole purpose of olcAuthzRegexp is to rewrite the username.
That's a false assumption.
SASL has to find the user's entry
Simple bind does not have to find the user’s entry?
Yes.
To be very clear on this: I would be really angry if the current behaviour would be changed because it will seriously break security properties of existing systems (e.g. https://ae-dir.com and all my other customer setups).
It's easy for you to simply fix your ACLs and be done with it.
https://bugs.openldap.org/show_bug.cgi?id=9657
--- Comment #5 from Ondřej Kuzník ondra@mistotebe.net --- On Mon, Aug 30, 2021 at 04:49:56PM +0000, openldap-its@openldap.org wrote:
and the whole purpose of olcAuthzRegexp is to rewrite the username.
SASL has to find the user's entry
Simple bind does not have to find the user’s entry?
I would note that the purpose of olcAuthzRegexp is to locate the right identity (entry), not just do username rewriting. If that entry belongs to a database with configured ACLs, those apply to give the admin a chance to control this part of the authentication+authorization process.
If you want to improve the existing documentation, please help review ITS#9256 which, sadly, has been on hold for a while. And maybe propose tweaks/additions to the admin guide, that would be much appreciated.
Thanks,