Custom module to handle LDAP query returning multiple results?
Hello, 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.) 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. Best regards, and thanks in advance Nicolas PS: Thanks Alan for your answer to my other question yesterday.
On Jan 19, 2018, at 8:32 AM, Nicolas Reich <nicolas.reich@switch.ch> 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.
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.
PS: Thanks Alan for your answer to my other question yesterday.
You're welcome. Alan DeKok.
On Jan 19, 2018, at 6:43 AM, Alan DeKok <aland@deployingradius.com> wrote:
On Jan 19, 2018, at 8:32 AM, Nicolas Reich <nicolas.reich@switch.ch> 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; } } -Arran
On Jan 19, 2018, at 6:32 AM, Nicolas Reich <nicolas.reich@switch.ch> wrote:
Hello,
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.)
OpenLDAP does support server side sorting, you need to load/configure the slapo-sssvlv overlay. You can then sort the results server side by one or more attributes. If you're really intent on writing code, it would likely be easier to write something to do client side sorting. The point here is to make sure the same result is used consistently, as there's no guarantee results from the server will be returned in the same order. -Arran
participants (3)
-
Alan DeKok -
Arran Cudbard-Bell -
Nicolas Reich