diff options
-rw-r--r-- | daemons/ipa-kdb/ipa_kdb.h | 10 | ||||
-rw-r--r-- | daemons/ipa-kdb/ipa_kdb_common.c | 103 |
2 files changed, 113 insertions, 0 deletions
diff --git a/daemons/ipa-kdb/ipa_kdb.h b/daemons/ipa-kdb/ipa_kdb.h index d5a343345..3c62205aa 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 7438f3504..5995efe6b 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); +} + |