I have tried to create virtual views of existing local data and I have
realized that the rewrite/remap overlay (slapo-rwm) in conjunction with
the relay backend (slapd-relay) (both are experimental) does not exactly
do what I would like to have.
To explain the problem, let me consider the following hypothetical
situation. We have two groups of UNIX clients. All clients should be
accessed by the same set of users having different user ID on each
client group. In addition, it would be nice to have different user
passwords for each client group.
In the local schema, we define two new attributes xxxUidNumber and
xxxUserPassword, and a new object class xxxPosixAccount holding them.
The local.schema file, the initial slapd.conf file (OpenLDAP 2.4.22),
and the real data ldif file are at the end of this email. The real data
are in 'ou=users,ou=auth,o=example', and the virtual view is in
'ou=xxxUsers,ou=auth,o=example'.
1 The search problem
====================
Here are some queries and results to demonstrate it:
Real data:
----------
Search request A
~~~~~~~~~~~~~~~~
/usr/local/bin/ldapsearch -LLL -H ldaps://censor.ethz.ch -x \
-D "cn=ldap_manager,ou=auth,o=example" \
-w qwerty \
-b 'cn=user10,ou=users,ou=auth,o=example'
dn: cn=user10,ou=users,ou=auth,o=example
objectClass: top
objectClass: person
objectClass: posixAccount
objectClass: xxxPosixAccount
cn: user10
sn: user10
uid: user10
uidNumber: 1111
xxxUidNumber: 2222
gidNumber: 3333
homeDirectory: /tmp
loginShell: /bin/tcsh
gecos: User 10
userPassword:: e1NTSEF9QWlmMWtyQXhkRGQ3bHJ5amp6VzFoTUgxOFdVU01BPT0=
xxxUserPassword: {SSHA}BaPK4xvEKVpYwj3qK0zbOWpVOAwSMA==
Virtual view:
-------------
Search request B
~~~~~~~~~~~~~~~~
/usr/local/bin/ldapsearch -LLL -H ldaps://censor.ethz.ch -x \
-D "cn=ldap_manager,ou=auth,o=example" \
-w qwerty \
-b 'cn=user10,ou=xxxUsers,ou=auth,o=example'
dn: cn=user10,ou=xxxUsers,ou=auth,o=example
objectClass: top
objectClass: person
objectClass: posixAccount
objectClass: xxxPosixAccount
cn: user10
sn: user10
uid: user10
uidNumber: 1111
uidNumber: 2222
gidNumber: 3333
homeDirectory: /tmp
loginShell: /bin/tcsh
gecos: User 10
userPassword:: e1NTSEF9QWlmMWtyQXhkRGQ3bHJ5amp6VzFoTUgxOFdVU01BPT0=
userPassword:: e1NTSEF9QmFQSzR4dkVLVnBZd2ozcUswemJPV3BWT0F3U01BPT0=
The rewrite/remap part in slapd.conf was as follows:
overlay rwm
rwm-suffixmassage "ou=users,ou=auth,o=example"
rwm-map attribute userPassword xxxUserPassword
rwm-map attribute uidNumber xxxUidNumber
Because of the simple mapping, the reply contains uidNumber and
userPassword attributes two times. To eliminate this, we modify the
rewrite/remap part in slapd.conf:
overlay rwm
rwm-suffixmassage "ou=users,ou=auth,o=example"
rwm-map attribute userPassword xxxUserPassword
rwm-map attribute userPassword
rwm-map attribute uidNumber xxxUidNumber
rwm-map attribute uidNumber
Now the answer from the previous search request (B) seems to be as desired:
dn: cn=user10,ou=xxxUsers,ou=auth,o=example
objectClass: top
objectClass: person
objectClass: posixAccount
objectClass: xxxPosixAccount
cn: user10
sn: user10
uid: user10
uidNumber: 2222
gidNumber: 3333
homeDirectory: /tmp
loginShell: /bin/tcsh
gecos: User 10
userPassword:: e1NTSEF9QmFQSzR4dkVLVnBZd2ozcUswemJPV3BWT0F3U01BPT0=
But the next search request returns values, although one would expect an
empty result set, as the attribute xxxUidNumber (used in the filter) is
not explicitly present in the virtual view (it is mapped):
Search request C
~~~~~~~~~~~~~~~~
/usr/local/bin/ldapsearch -LLL -H ldaps://censor.ethz.ch -x \
-D "cn=ldap_manager,ou=auth,o=example" \
-w qwerty \
-b 'ou=xxxUsers,ou=auth,o=example' \
'(xxxUidNumber=*)'
dn: cn=user10,ou=xxxUsers,ou=auth,o=example
objectClass: top
objectClass: person
objectClass: posixAccount
objectClass: xxxPosixAccount
cn: user10
sn: user10
uid: user10
uidNumber: 2222
gidNumber: 3333
homeDirectory: /tmp
loginShell: /bin/tcsh
gecos: User 10
userPassword:: e1NTSEF9QmFQSzR4dkVLVnBZd2ozcUswemJPV3BWT0F3U01BPT0=
I think the attribute xxxUidNumber should be removed from the internal
query to the foreign data set, because it is used as a foreign name (and
in the same time not as a local name) in the mapping, and the query (C)
above should return an empty result set.
One can improve this by modifying the rewrite/remap part in slapd.conf
as follows:
overlay rwm
rwm-suffixmassage "ou=users,ou=auth,o=example"
rwm-map attribute cn *
rwm-map attribute sn *
rwm-map attribute uid *
rwm-map attribute gidNumber *
rwm-map attribute homeDirectory *
rwm-map attribute loginShell *
rwm-map attribute gecos *
rwm-map attribute userPassword xxxUserPassword
rwm-map attribute uidNumber xxxUidNumber
rwm-map attribute *
Now both search requests (B and C) work as expected. The last remap line
correctly removes everything what is not mapped. The problem here is
that one has to explicitly list all desired attributes in the remap
configuration. If a new attribute is added to the real data, it would
not show in the result set without a change in the remap configuration.
2 The authentication problem
============================
The following two bind request use the same password for authentication,
regardless of the mapping and the value of the attribute xxxUserPassword.
/usr/local/bin/ldapsearch -LLL -H ldaps://censor.ethz.ch -x \
-D "cn=user10,ou=users,ou=auth,o=example" \
-w abc123 \
-b 'cn=user10,ou=users,ou=auth,o=example' dn
dn: cn=user10,ou=users,ou=auth,o=example
/usr/local/bin/ldapsearch -LLL -H ldaps://censor.ethz.ch -x \
-D "cn=user10,ou=xxxUsers,ou=auth,o=example" \
-w abc123 \
-b 'cn=user10,ou=xxxUsers,ou=auth,o=example' dn
dn: cn=user10,ou=xxxUsers,ou=auth,o=example
If we use the userPassword (xyz789), reported by the view (e.g. query
B), the bind request returns 'Invalid credentials'.
If I understand it correctly, this is not a bug. The LDAP bind request
does not contain the name of the attribute holding the user password at
the server site, so there is (unfortunately) nothing to map.
There are many real life situations where, for security reasons, it
would be desirable to have different passwords for different
applications, or groups of applications/clients (e.g. web access, UNIX
login, etc.). Unfortunately, it seems the present virtual views
(slapo-rwm + slapd-relay) cannot solve it. For the moment, I see only
one possibility -- to create a copy of the user entries and to modify
the userPassword attribute. (Please let me know, if you know a better
solution.) But there are disadvantages connected with this approach, for
example the maintenance of the data consistency, large indices, etc.
My question is -- would it be possible to solve the password mapping in
the OpenLDAP software? For example, (i) to extend the structure holding
the bind request data to include an attribute name, (ii) to initialise
its value to 'userPassword', (iii) to allow slapo-rwm to rewrite/remap
it, and then (iv) to use the new value of the attribute name for the
internal user password verification.
With best regards,
Vlado
-------------------------------------------------------------------------
local.schema:
=============
attributetype ( 1.3.6.1.4.1.9999.2.1.102
NAME 'xxxUidNumber'
DESC 'An integer uniquely identifying a user in an administrative
domain (XXX private)'
EQUALITY integerMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
attributetype ( 1.3.6.1.4.1.9999.2.1.105
NAME 'xxxUserPassword'
DESC 'RFC2256/2307: password of user (XXX private)'
EQUALITY octetStringMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.40{128} )
objectclass ( 1.3.6.1.4.1.9999.2.2.10
NAME 'xxxPosixAccount'
DESC 'Abstraction of an account with POSIX attributes (XXX private)'
SUP top AUXILIARY
MAY ( xxxUidNumber $ xxxUserPassword ) )
slapd.conf:
===========
include /usr/local/openldap/etc/openldap/schema/core.schema
include /usr/local/openldap/etc/openldap/schema/cosine.schema
include /usr/local/openldap/etc/openldap/schema/nis.schema
include /etc/openldap/local.schema
pidfile /var/openldap/slapd.pid
argsfile /var/openldap/slapd.args
loglevel 256
TLSCertificateFile /etc/openldap/xxx_cert.pem
TLSCertificateKeyFile /etc/openldap/xxx_key.pem
TLSRandFile /var/run/prngd-socket
TLSCACertificateFile /etc/openldap/yyy_cacert.pem
database relay
suffix "ou=xxxUsers,ou=auth,o=example"
subordinate
overlay rwm
rwm-suffixmassage "ou=users,ou=auth,o=example"
rwm-map attribute userPassword xxxUserPassword
rwm-map attribute uidNumber xxxUidNumber
database hdb
suffix "ou=auth,o=example"
directory /var/openldap/hdb
rootdn "cn=ldap_manager,ou=auth,o=example"
rootpw {SSHA}jN4XaG5UmYFwpY/47aW0nLralRwSMA==
dbconfig set_cachesize 0 268435456 0
dbconfig set_flags DB_TXN_NOSYNC
dbconfig set_flags DB_LOG_AUTOREMOVE
dbconfig set_lk_max_locks 3000
dbconfig set_lk_max_lockers 3000
dbconfig set_lk_max_objects 3000
dbconfig set_lg_regionmax 1048576
dbconfig set_lg_max 10485760
dbconfig set_lg_bsize 2097152
dbconfig set_lg_dir /var/log/hdb
dbconfig set_tmp_dir /tmp
Real data:
==========
dn: ou=auth,o=example
objectClass: top
objectClass: organizationalUnit
ou: auth
dn: ou=users,ou=auth,o=example
objectClass: top
objectClass: organizationalUnit
ou: users
dn: cn=user10,ou=users,ou=auth,o=example
objectClass: top
objectClass: person
objectClass: posixAccount
objectClass: xxxPosixAccount
cn: user10
sn: user10
uid: user10
uidNumber: 1111
xxxUidNumber: 2222
gidNumber: 3333
homeDirectory: /tmp
loginShell: /bin/tcsh
gecos: User 10
# abc123
userPassword: {SSHA}Aif1krAxdDd7lryjjzW1hMH18WUSMA==
# xyz789
xxxUserPassword: {SSHA}BaPK4xvEKVpYwj3qK0zbOWpVOAwSMA==