I'm a bit new to the openldap package - my experience really dates back to the X500 QUIPU days in the early 90's so while I understand the priciples, it's the details of the software package that are something of a mystery.
We're implementing LDAP for a variety of applications and we're going to use boolean attributes in the schema to determine whether a service should be enabled or disabled for a particular user.
So, for example, we have an attribute of "kdiremail" which is true if the user is allowed to use the email service and false if their not. This works well with tools like dovecot because we can set up the search filter to only authenticate users who have that attribute set to true.
However, some applications are born into an Active Directory world where such things seem to be unknown.
I'm battling the Blackboard WebCT Vista product which allows me to specify attributes to look up for the username, but does not allow me to specifically define the search filter.
My plan is to use the rewrite/remap overlay to create a fake hierarchy within our exisiting DIT where the search filter values are re-written to include a check to see if kdirvle is true. So then any searches on that DN will only return users who are allowed to use the VLE, I can then point our WebCT service to that basedn.
I think this overlay will do the job I want, but I can see that there are many overlays in the openldap package and I wanted to check with someone more experienced that I am that the rewrite/remap overlay is the right choice for this kind of job.
Jon.
On Mon, 26 Jan 2009, Jonathan Knight wrote:
[...cut...]
I'm battling the Blackboard WebCT Vista product which allows me to specify attributes to look up for the username, but does not allow me to specifically define the search filter.
My plan is to use the rewrite/remap overlay to create a fake hierarchy within
[...cut...]
Well, configuring OpenLDAP Software in the name of workarounds for poorly designed clients is a slippery slope (albeit all too often necessary)...your best bet is of course client enhancement. With that said...
I think you're making this harder than it needs to be, or at least in a way that I find less intuitive. If you can configure a bind DN, might I suggest:
access to dn.subtree="ou=People,dc=example,dc=com" filter="(isAWebCTUser=FALSE)" by dn.exact="cn=pullTheWoolOverMyEyes,dc=example,dc=com" none by * none break
# [...add more here, possibly w/ (isAWebCTUser=TRUE)...]
If you can't configure the bind DN, you can back-relay your database and apply a similar ACL. I believe the bind DN will have lower overhead than the back-relay, although they're both relatively cheap in the grand scheme of things.
Aaron Richton wrote:
I think you're making this harder than it needs to be, or at least in a way that I find less intuitive.
Many thanks for your help Aaron. I went down the ACL route but chose a slightly different method.
What I did was to use the "relay" backend to duplicate the dc=people,dc=kdir,dc=keele,dc=ac,dc=uk tree and then apply an ACL as you suggested to block access to the relay tree if the attribute wasn't set.
i.e.
access to dn.children="dc=webct,dc=kdir,dc=keele,dc=keele,dc=ac,dc=uk" filter="(kdirVle=no)" by * =rcsd
access to * by * read
with the aim of blocking the auth bit (x) if the flag was set to "no". That way the broken client could find the user, but would not be able to authenticate. I expected that would give a better error message or "authentication failed" rather than "user unknown".
This didn't work - I could bind as a user in that subtree with the flag set to false with no trouble at all.
I started slapd with debug set for the ACL's to see where I'd gone wrong and although there are a lot of calls to acl_mask, acl_get and so on after the bind, the bind itself doesn't seem to call any acl's at all.
So I wonder if I've missed something. Should I see calls to acl's in the bind call?
Jon.
Jonathan Knight wrote:
Aaron Richton wrote:
I think you're making this harder than it needs to be, or at least in a way that I find less intuitive.
Many thanks for your help Aaron. I went down the ACL route but chose a slightly different method.
What I did was to use the "relay" backend to duplicate the dc=people,dc=kdir,dc=keele,dc=ac,dc=uk tree and then apply an ACL as you suggested to block access to the relay tree if the attribute wasn't set.
i.e.
access to dn.children="dc=webct,dc=kdir,dc=keele,dc=keele,dc=ac,dc=uk" filter="(kdirVle=no)" by * =rcsd
access to * by * read
with the aim of blocking the auth bit (x) if the flag was set to "no". That way the broken client could find the user, but would not be able to authenticate. I expected that would give a better error message or "authentication failed" rather than "user unknown".
This didn't work - I could bind as a user in that subtree with the flag set to false with no trouble at all.
I started slapd with debug set for the ACL's to see where I'd gone wrong and although there are a lot of calls to acl_mask, acl_get and so on after the bind, the bind itself doesn't seem to call any acl's at all.
So I wonder if I've missed something. Should I see calls to acl's in the bind call?
It's hard to tell without seeing your whole configuration. Auth (by simple bind) uses ACLs. In detail, it needs auth access to userPassword. The ACL you show above should indeed prevent auth; however, everybody would see the userPassword of everybody under that tree (=r). If this doesn't actually happen, then there must be an earlier
access to attrs=userPassword by * auth
that intercepts auth requests, thus defeating your rule.
Something along the lines
access to dn.children="dc=example,dc=com" filter="(yourmagicfilter)" attrs=userPassword by * none
access to dn.children="dc=example,dc=com" filter="(yourmagicfilter)" by * =rcsd
access to attrs=userPassword by * auth
access to * by * read
In any case, I don't quite understand why you need back-relay; is it because you also need to fake the naming context? Or because you want "smart" applications to have regular privileges? Otherwise ACLs for your real database would just suffice.
p.
Ing. Pierangelo Masarati OpenLDAP Core Team
SysNet s.r.l. via Dossi, 8 - 27100 Pavia - ITALIA http://www.sys-net.it ----------------------------------- Office: +39 02 23998309 Mobile: +39 333 4963172 Fax: +39 0382 476497 Email: ando@sys-net.it -----------------------------------
It's hard to tell without seeing your whole configuration. Auth (by simple bind) uses ACLs. In detail, it needs auth access to userPassword. The ACL you show above should indeed prevent auth; however, everybody would see the userPassword of everybody under that tree (=r).
Here's the config file I'm currently playing with.
access to * by * none
database ldap uri "ldap://ldap.isc.keele.ac.uk/" suffix "dc=people,dc=kdir,dc=keele,dc=ac,dc=uk" rootdn "dc=people,dc=kdir,dc=keele,dc=ac,dc=uk"
database relay suffix "dc=webct,dc=kdir,dc=keele,dc=ac,dc=uk" relay "dc=people,dc=kdir,dc=keele,dc=ac,dc=uk" overlay rwm rwm-suffixmassage "dc=people,dc=kdir,dc=keele,dc=ac,dc=uk"
If I've understood the manual correctly then this should stop all access to the entire DIT.
I start slapd with:
/usr/local/ldap-proxy/libexec/slapd -d 128
@(#) $OpenLDAP: slapd 2.4.11 (Dec 18 2008 18:18:07) $
root@romeo.kis.keele.ac.uk:/var/sysdist/src/ldap/openldap-2.4.11/servers/slapd Backend ACL: access to * by * none
Backend ACL: access to * by * none
config_back_db_open: line 0: warning: cannot assess the validity of the ACL scope within backend naming context slapd starting
I then run this command on the client: ldapwhoami -x -h romeo.kis.keele.ac.uk -D uniqueIdentifier=124E652A-4A4B-11DD-AF40-9CC5CB0AF2BD,dc=webct,dc=kdir,dc=keele,dc=ac,dc=uk -W Enter LDAP Password: dn:uniqueIdentifier=124E652A-4A4B-11DD-AF40-9CC5CB0AF2BD,dc=people,dc=kdir,dc=keele,dc=ac,dc=uk
As you can see the BIND succeeds and the DN is returned. If I get the password wrong, I get the invalid credentials error rather than the DN. There is no debug output on the slapd server. Any attempt at an ldapsearch will fail on the search and I get some ACL debug output, but the initial bind always succeeds.
So how do I use an ACL to stop a bind?
Jon.
Jonathan Knight wrote:
It's hard to tell without seeing your whole configuration. Auth (by simple bind) uses ACLs. In detail, it needs auth access to userPassword. The ACL you show above should indeed prevent auth; however, everybody would see the userPassword of everybody under that tree (=r).
Here's the config file I'm currently playing with.
access to * by * none
database ldap uri "ldap://ldap.isc.keele.ac.uk/" suffix "dc=people,dc=kdir,dc=keele,dc=ac,dc=uk" rootdn "dc=people,dc=kdir,dc=keele,dc=ac,dc=uk"
database relay suffix "dc=webct,dc=kdir,dc=keele,dc=ac,dc=uk" relay "dc=people,dc=kdir,dc=keele,dc=ac,dc=uk" overlay rwm rwm-suffixmassage "dc=people,dc=kdir,dc=keele,dc=ac,dc=uk"
If I've understood the manual correctly then this should stop all access to the entire DIT.
I start slapd with:
/usr/local/ldap-proxy/libexec/slapd -d 128
@(#) $OpenLDAP: slapd 2.4.11 (Dec 18 2008 18:18:07) $
root@romeo.kis.keele.ac.uk:/var/sysdist/src/ldap/openldap-2.4.11/servers/slapd
Backend ACL: access to * by * none
Backend ACL: access to * by * none
config_back_db_open: line 0: warning: cannot assess the validity of the ACL scope within backend naming context slapd starting
I then run this command on the client: ldapwhoami -x -h romeo.kis.keele.ac.uk -D uniqueIdentifier=124E652A-4A4B-11DD-AF40-9CC5CB0AF2BD,dc=webct,dc=kdir,dc=keele,dc=ac,dc=uk -W Enter LDAP Password: dn:uniqueIdentifier=124E652A-4A4B-11DD-AF40-9CC5CB0AF2BD,dc=people,dc=kdir,dc=keele,dc=ac,dc=uk
As you can see the BIND succeeds and the DN is returned. If I get the password wrong, I get the invalid credentials error rather than the DN. There is no debug output on the slapd server. Any attempt at an ldapsearch will fail on the search and I get some ACL debug output, but the initial bind always succeeds.
So how do I use an ACL to stop a bind?
You see, you did not illustrate an important part of your configuration in your first message. slapd.access(5) states:
OPERATION REQUIREMENTS Operations require different privileges on different portions of entries. The following summary applies to primary database backends such as the BDB and HDB backends. Requirements for other backends may (and often do) differ.
(snip)
The bind operation, when credentials are stored in the directory, requires auth (=x) privileges on the attribute the credentials are stored in (usually userPassword).
(snip)
Access control to search entries is checked by the frontend, so it is fully honored by all backends; for all other operations and for the discovery phase of the search operation, full ACL semantics is only supported by the primary backends, i.e. back-bdb(5), and back-hdb(5).
Some other backend, like back-sql(5), may fully support them; others may only support a portion of the described semantics, or even differ in some aspects. The relevant details are described in the backend- specific man pages.
And slapd-ldap(5) states:
ACCESS CONTROL The ldap backend does not honor all ACL semantics as described in slapd.access(5). In general, access checking is delegated to the remote server(s). Only read (=r) access to the entry pseudo-attribute and to the other attribute values of the entries returned by the search operation is honored, which is performed by the frontend.
A similar statement appears in slapd-relay(5):
ACCESS CONTROL The relay backend does not honor any of the access control semantics described in slapd.access(5); all access control is delegated to the relayed database(s). Only read (=r) access to the entry pseudo- attribute and to the other attribute values of the entries returned by the search operation is honored, which is performed by the frontend.
So yes, as clearly documented, there is no way to use ACLs to enforce bind policies unless you're using back-bdb, back-hdb or back-sql.
An alternative consists in using the rewrite engine of slapo-rwm(5) to intercept binds and do filtering for you. Something along the lines of the example in slapo-rwm(3) that defines and uses a map called "attr2dn". Beware that this is not trivial and may result in significant overhead, as it will likely need to perform internal requests for each bind operation.
p.
Ing. Pierangelo Masarati OpenLDAP Core Team
SysNet s.r.l. via Dossi, 8 - 27100 Pavia - ITALIA http://www.sys-net.it ----------------------------------- Office: +39 02 23998309 Mobile: +39 333 4963172 Fax: +39 0382 476497 Email: ando@sys-net.it -----------------------------------
openldap-software@openldap.org