From 9f13b330aaec468a018472dce5fc77131277de94 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mar 10 2017 08:17:28 +0000 Subject: Add code to retrieve results from multiple bases Internally performs multiple seraches as needed based on the basedn strings passed in and whether the caller indicated that any result is ok or all results are needed. Signed-off-by: Simo Sorce Reviewed-By: Martin Babinsky --- diff --git a/daemons/ipa-kdb/ipa_kdb.h b/daemons/ipa-kdb/ipa_kdb.h index d5a3433..3c62205 100644 --- a/daemons/ipa-kdb/ipa_kdb.h +++ b/daemons/ipa-kdb/ipa_kdb.h @@ -174,6 +174,16 @@ int ipadb_ldap_attr_has_value(LDAP *lcontext, LDAPMessage *le, int ipadb_ldap_deref_results(LDAP *lcontext, LDAPMessage *le, LDAPDerefRes **results); +struct ipadb_multires; +krb5_error_code ipadb_multires_init(LDAP *lcontext, struct ipadb_multires **r); +void ipadb_multires_free(struct ipadb_multires *r); +LDAPMessage *ipadb_multires_next_entry(struct ipadb_multires *r); +krb5_error_code ipadb_multibase_search(struct ipadb_context *ipactx, + char **basedns, int scope, + char *filter, char **attrs, + struct ipadb_multires **res, + bool any); + /* PRINCIPALS FUNCTIONS */ krb5_error_code ipadb_get_principal(krb5_context kcontext, krb5_const_principal search_for, diff --git a/daemons/ipa-kdb/ipa_kdb_common.c b/daemons/ipa-kdb/ipa_kdb_common.c index 7438f35..5995efe 100644 --- a/daemons/ipa-kdb/ipa_kdb_common.c +++ b/daemons/ipa-kdb/ipa_kdb_common.c @@ -610,3 +610,106 @@ done: ldap_controls_free(ctrls); return ret; } + +struct ipadb_multires { + LDAP *lcontext; + LDAPMessage **res; + LDAPMessage *next; + ssize_t cursor; + ssize_t count; +}; + +krb5_error_code ipadb_multires_init(LDAP *lcontext, struct ipadb_multires **r) +{ + *r = malloc(sizeof(struct ipadb_multires)); + if (!*r) return ENOMEM; + (*r)->lcontext = lcontext; + (*r)->res = NULL; + (*r)->next = NULL; + (*r)->cursor = -1; + (*r)->count = 0; + + return 0; +} + +void ipadb_multires_free(struct ipadb_multires *r) +{ + for (int i = 0; i < r->count; i++) { + ldap_msgfree(r->res[i]); + } + free(r); +} + +LDAPMessage *ipadb_multires_next_entry(struct ipadb_multires *r) +{ + if (r->count == 0) return NULL; + + if (r->next) { + r->next = ldap_next_entry(r->lcontext, r->next); + } + if (r->next == NULL) { + if (r->cursor >= r->count - 1) { + return NULL; + } + r->cursor++; + r->next = ldap_first_entry(r->lcontext, r->res[r->cursor]); + } + + return r->next; +} + +krb5_error_code ipadb_multibase_search(struct ipadb_context *ipactx, + char **basedns, int scope, + char *filter, char **attrs, + struct ipadb_multires **res, + bool any) +{ + int ret; + + ret = ipadb_multires_init(ipactx->lcontext, res); + if (ret != 0) return ret; + + ret = ipadb_check_connection(ipactx); + if (ret != 0) + return ipadb_simple_ldap_to_kerr(ret); + + for (int b = 0; basedns[b]; b++) { + LDAPMessage *r; + ret = ldap_search_ext_s(ipactx->lcontext, basedns[b], scope, + filter, attrs, 0, NULL, NULL, + &std_timeout, LDAP_NO_LIMIT, &r); + + /* first test if we need to retry to connect */ + if (ret != 0 && + ipadb_need_retry(ipactx, ret)) { + ldap_msgfree(r); + ret = ldap_search_ext_s(ipactx->lcontext, basedns[b], scope, + filter, attrs, 0, NULL, NULL, + &std_timeout, LDAP_NO_LIMIT, &r); + } + + if (ret != 0) break; + + if (ldap_count_entries(ipactx->lcontext, r) > 0) { + void *tmp = realloc((*res)->res, (((*res)->count + 1) * + sizeof(LDAPMessage *))); + if (tmp == NULL) { + ret = ENOMEM; + break; + } + (*res)->res = tmp; + (*res)->res[(*res)->count] = r; + (*res)->count++; + + if (any) break; + } + } + + if (ret != 0) { + ipadb_multires_free(*res); + *res = NULL; + } + + return ipadb_simple_ldap_to_kerr(ret); +} +