This is a howto for using remoteauth (from the ldap in iredadminpro to authenticate in an AD)
This has been tested with debian 11 bullseye iredadminproldap5.4.1 and iredamin 1.6.2
A) in debian replace ldap2.4 with ldap2.5 from backports eg "apt-get -t bullseye-backports install slapd"
even with iredadmin already installed upgrade works fine;
B) modify you slapd to user remoteauth
B1) in the part of slapd.conf where you find serveral "moduloads" add the line :
moduleload remoteauth.la
B2) in databases section (at the end of slapd.conf) add (replace <..> with correct values):
overlay remoteauth
remoteauth_dn_attribute associatedName
# attribute used to resolve the domain
remoteauth_domain_attribute associatedDomain
# default domain if none is present in user entry
remoteauth_default_domain <NAME OF AD DOMAIN old style not FQDN> (eg DOMAIN\user -> DOMAIN) in lowercase
# domain mapping => [ list of hostnames or URIs]
# file europe.list contains a hostname or LDAP URI, one per line
# OpenLDAP tries to connect to first server, then if it fails or timeouts, to second server,...
#remoteauth_mapping europe file:///usr/local/openldap/etc/openldap/europe.list
# domain usa will use only one hostname
remoteauth_mapping <NAME OF AD DOMAIN old style not FQDN> <DNS_AD_SERVER_NMAE>
# fallback server to connect if no domain found in domain mapping
remoteauth_default_realm <NAME OF AD REALM : OR DNS NAME OF DOMAIN>
# number of retries attempted
remoteauth_retry_count 1
# store the password in case of successfull bind?
remoteauth_store off
okay that's the first part, for slapd
C) modify your slapd users accounts
C1) add objectClass extensibleObject to user accounts
C2) add 2 attributes to users records in ldap
C21) "associatedName"=> dn of user account in AD to authenticate against
C22) "associatedDomain" => Account in old NT style Form eg DOMAIN:user (seems that only DOMAIN: should work)
D) modify ZhangHuangbin code (do not blame me, i m not python-code-writer, so it is certainly awfull)
D1) in auth.py
comment the part
#~ if not conn:
#~ _wrap = LDAPWrap()
#~ conn = _wrap.conn
#~ try:
#~ qr = conn.search_s(dn,
#~ ldap.SCOPE_BASE,
#~ '(objectClass=*)',
#~ ['userPassword'])
#~ if not qr:
#~ # No such account.
#~ return False, 'INVALID_CREDENTIALS'
#~ _ldif = iredutils.bytes2str(qr[0][1])
#~ pw = _ldif.get('userPassword', [''])[0]
#~ if iredpwd.verify_password_hash(pw, password):
#~ return True,
#~ else:
#~ return False, 'INVALID_CREDENTIALS'
#~ except Exception as e:
#~ return False, repr(e)
and add
_wrap2 = LDAPWrap()
conn_new = _wrap2.conn
conn_new.unbind()
try:
qr=conn.bind_s(dn, password)
if not qr:
return False, 'INVALID_CREDENTIALS'
else:
return True,
except Exception as e:
return False, repr(e)
D2) in api_misc.py
comment :
#~ try:
#~ _wrap = LDAPWrap()
#~ conn = _wrap.conn
#~ # Get password from LDAP
#~ qr = conn.search_s(dn,
#~ ldap.SCOPE_BASE,
#~ "(objectClass=*)",
#~ ['userPassword'])
#~ if not qr:
#~ return api_render((False, 'NO_SUCH_ACCOUNT'))
#~ _ldif = iredutils.bytes2str(qr[0][1])
#~ # Compare first password
#~ pw_in_ldap = _ldif.get('userPassword', [''])[0]
#~ qr = iredpwd.verify_password_hash(pw_in_ldap, pw)
#~ return api_render(qr)
#~ except Exception as e:
#~ return api_render((False, repr(e)))
and add :
_wrap2 = LDAPWrap()
conn_new = _wrap2.conn
conn_new.unbind()
try:
_wrap2 = LDAPWrap()
conn_new = _wrap2.conn
conn_new.unbind()
qr=conn.bind_s(dn, pw)
if not qr:
return False, 'INVALID_CREDENTIALS'
else:
return True,
except Exception as e:
return False, repr(e)
WARNING :
if in the ldap on iredamin a user has his userPassword field not empty it will use this field as password for the user;
if the field userPassword is empty the it fallback using remoteauth against AD.