[Date Prev][Date Next] [Chronological] [Thread] [Top]

(ITS#6296) Strong bind doesn't work in slapd-ldap when used by slapd-relay or slapo-translucent



Full_Name: Martin Rubas
Version: 2.4.18, 2.4.15
OS: Windows, Linux/Ubuntu
URL: ftp://ftp.openldap.org/incoming/
Submission from: (NULL) (195.113.184.10)


Hello.

I have to use slapd-ldap in "strong bind" mode which means that user
binds using its own credentials and no identity assertion is performed.
If slapd-ldap is the only module that is processing request then
everything works fine. If slapd-ldap is processing an request forwarded
from slapd-relay (with slapo-rwm) or request to database with
slapo-translucent then the authentication problem occurs.

First detected in OpenLDAP 2.4.15 but still present in 2.4.18.

=== Test Setup ===

Let's suppose that we have remote LDAP server with disabled anonymous
binding. It could be Active Directory or OpenLDAP with following
configuration:

# --- config for remote server (remote.host.net) ---
# [cut-off] command schema, slapd files & logs definitions
# Load of modules:
modulepath      /usr/lib/ldap
moduleload      back_hdb.la

# VERY IMPORTANT: Disable anonymous binding
disallow        bind_anon

# Configuration Database
database        config
rootdn          "cn=admin,cn=config"
rootpw          secret

# realone.net - local Repository
database        hdb
suffix          "dc=realone,dc=net"
rootdn          "cn=admin,dc=realone,dc=net"
rootpw          secret
directory       /var/lib/slapd/realone.net
index           objectClass eq
index           cn eq
index           uid eq

Let's say there is a common content in database:

# --- Directory content (just an overview) ---
dn: dc=realone,dc=net    # top, domain
dn: ou=people,dc=realone,dc=net     # organizationalUnit
dn: ou=groups,dc=realone,dc=net     # organizationalUnit
dn: cn=idassert,dc=realone,dc=net   # simpleSecurityObject,organizationalRole
dn: cn=admin,dc=realone,dc=net      # same as above
dn: uid=super.account,ou=people,dc=realone,dc=net    #
inetOrgPerson,posixAccount, shadowAccount
dn: uid=power.account,ou=people,dc=realone,dc=net    # same as above
dn: uid=basic.account,ou=people,dc=realone,dc=net    # same as above
dn: cn=admins,ou=groups,dc=realone,dc=net   # posixGroup
dn: cn=users,ou=groups,dc=realone,dc=net    # same as above

I want to use another OpenLDAP server that is configured with
slapo-translucent:

# --- config for local server (trans.local.net) ---
# [cut-off] command schema, slapd files & logs definitions

# Configuration Database
database     config
rootdn         "cn=admin,cn=config"
rootpw         secret

# realone.net - local database extending the remote one
database        bdb
suffix          "dc=realone,dc=net"
directory       ./database/realone.net
index           objectClass eq
index           cn eq
index           uid eq

overlay                 translucent
uri                     ldap://remote.host.net:389/
chase-referrals         true
rebind-as-user          true

... or with slapd-relay (this is probably very very very rare use case
but I used it for debugging):

# --- config for local server (relay.local.net) ---
# [cut-off] command
schema, slapd files & logs definitions

# Configuration Database
database 	config
rootdn 		"cn=admin,cn=config"
rootpw 		secret

# domain (forwarded to remote repository)
database        ldap
suffix          "dc=realone,dc=net"
uri             ldap://remote.host.net
chase-referrals yes

# domain alias
database        relay
suffix          "dc=virtual,dc=net"
relay           "dc=realone,dc=net"

overlay  rwm
rwm-suffixmassage      "dc=virtual,dc=net" "dc=realone,dc=net"


=== Test Cases ===

Now, we can do usual search:
ldapsearch -x -w secret -h <host-D <bindDN-b <baseDN-s sub
"(objectClass=inetOrgPerson)" dn displayName mail
(in my environment I should receive 3 records below
ou=people,dc=realone,dc=net).

But the story is getting interesting here. The command works only in
cases that slapd-ldap is used directly:

===================================================================================================
# | Host            | BindDN                     | BaseDN            | Result
--+-----------------+----------------------------+-------------------+-----------------------------
1 | remote.host.net | cn=admin,dc=realone,dc=net | dc=realone,dc=net | Success
(3 records)
--+-----------------+----------------------------+-------------------+-----------------------------
2 | trans.local.net | cn=admin,dc=realone,dc=net | dc=realone,dc=net | Failure:
Anon.bind.n.allwd.
--+-----------------+----------------------------+-------------------+-----------------------------
3 | relay.local.net | cn=admin,dc=realone,dc=net | dc=realone,dc=net | Success
(3 records)
--+-----------------+----------------------------+-------------------+-----------------------------
4 | relay.local.net | cn=admin,dc=realone,dc=net | dc=virtual,dc=net | Success
(3 records)     !!!!
--+-----------------+----------------------------+-------------------+-----------------------------
5 | relay.local.net | cn=admin,dc=virtual,dc=net | dc=virtual,dc=net | Failure:
Anon.bind.n.allwd.
===================================================================================================

The failures of case #2 and #5 are not expected because the connection
to remote server is handled by slapd-ldap configured the same way like
in case 3. The success in case #3 is correct (although I didn't expected
it) and it was guide to solution. I noticed that each time the request
fail the LDAP connection is correctly opened and bind request is
successful. But the search request was processed using a new connection
that was created for it and anonymous bind executed with failure.

=== Debugging ===

While debugging, I found that ldap_back_getconn() is called by
ldap_back_bind() as well as ldap_back_search() request handlers. For
operations other then op_bind it tests whether connection associated
with Operation (op->o_hdr->oh_conn) was used for authentication in
previous step. If slapd-ldap is NOT using identity assertion then it
checks Operation using SLAP_IS_AUTHZ_BACKEND macro whether
op->o_conn->c_authz_backend is not NULL and is equal to current backend.

This test works fine is the slapd-ldap backend is the only which
processes the LDAP request because op->o_conn->c_authz_backend is set in
the binding handler of the frontend module - fe_op_bind(). In this, case
the test succeeds and connection created during the binding is used also
for searching.

If the slapd-ldap module is used as nested module in slapo-translucent
(case #2), then the fe_op_bind() sets variable
op->o_conn->c_authz_backend to the backend extended by
slapo-translucent. Macro SLAP_IS_AUTHZ_BACKEND returns false and a new
LDAP connection is allocated causing failure due anonymouse binding.

If the slapd-ldap module is target for slapd-relay then it behaves
similar way. In case #5 the bind request is forwarded to slapd-ldap but
slapd-relay is associated with connection as the backend who did the
bind (op->o_conn->c_authz_backend) and subsequent search request fails
the same way like above.

The success in case #4 is a kind of singularity  ;-)  - bind request is
forwarded directly from frontend to slapd-ldap and therefore
op->o_conn->c_authz_backend is set correctly, the subsequent search
request goes first to slapd-relay which forwards it to slapd-ldap but
SLAP_IS_AUTHZ_BACKEND test succeeds.

=== Patches uploaded to ftp.openldap.org ===

mrubas@kerio.com-090917.slapd_back-relay_op.c.2_4_15.patch
mrubas@kerio.com-090917.slapd_back-relay_op.c.2_4_18.patch
mrubas@kerio.com-090917.slapd_overlays_translucent.c.2_4_18.patch

Note: There is probably a better way how to fix that. I guess, 
that fix to slapd-ldap binding handler would be more efficient but
I didn't find the right place to add code assigning the auth. backend 
to connection.