Custom module to handle LDAP query returning multiple results?

Arran Cudbard-Bell a.cudbardb at
Sat Jan 20 17:45:59 CET 2018

> On Jan 19, 2018, at 6:43 AM, Alan DeKok <aland at> wrote:
> On Jan 19, 2018, at 8:32 AM, Nicolas Reich <nicolas.reich at> wrote:
>> The system looks like this: the users are each affiliated to one or more organisations. For each affiliation to an organisation, there's an entry in LDAP. So there can be several entries for the same user, each one with a different organisation. Now, granted the rest of the authentication process goes well, the user is accepted if he or she is affiliated to one of the whitelisted organisations, i.e. there is at least one entry with their name and a whitelisted organisation.
>> This should be pretty straightforward to check: get all entries for the user, and check if at least one is for a whitelisted organisation. Except the ldap module throws an error if the search returns more than one result, and I can't use server-side sorting because it is an openldap server, which doesn't implement the ldap_create_sort_control function. (I think, I might have gotten that wrong though.)
>  And OpenLDAP doesn't implement numsubordinates either.

Hm, how would that be used in this scenario? and yes, they don't tend to implement internet drafts unless there's a really good reason.  There are so many of them floating around for LDAP.

>> Is it possible to write a custom module to handle an LDAP query returning potentially multiple results? Or is there another solution you can think of? The obvious one is to serially query ldap for each organisation, but that's really ineffective. Final note to take into account: I cannot modify anything on the ldap side, it is used for other projects as well.
>  TBH, the simplest solution would be to:
> - copy the ldap_xlat() from src/modules/rlm_ldap/rlm_ldap.c
> - make a new function ldap_xlat_count()
> - have it print the *count* of attributes returned, instead of the attribute data
> - call xlat_register() for the new function.
>  You can then do a search using the same query.  Instead of getting one value, you get the count of values.  Which I think should work for you.
>  That's much simpler than writing a whole new module.

Even easier, use the LDAP xlat to pull back the DN of the first userobject with the requisite attribute, and then write the value to control:LDAP-UserDN before calling the LDAP module.

It'll use the DN provided instead of querying.

char const *rlm_ldap_find_user(rlm_ldap_t const *inst, REQUEST *request, fr_ldap_connection_t **pconn,
			       char const *attrs[], bool force, LDAPMessage **result, rlm_rcode_t *rcode)

	 *	If the caller isn't looking for the result we can just return the current userdn value.
	if (!force) {
		vp = fr_pair_find_by_num(request->control, 0, FR_LDAP_USERDN, TAG_ANY);
		if (vp) {
			RDEBUG("Using user DN from request \"%s\"", vp->vp_strvalue);
			*rcode = RLM_MODULE_OK;
			return vp->vp_strvalue;


-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 874 bytes
Desc: Message signed with OpenPGP
URL: <>

More information about the Freeradius-Users mailing list