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 <simo@redhat.com>
Reviewed-By: Martin Babinsky <mbabinsk@redhat.com>
This commit is contained in:
Simo Sorce 2016-12-16 07:12:45 -05:00 committed by Martin Babinsky
parent abf25d3cb6
commit 9f13b330aa
2 changed files with 113 additions and 0 deletions

View File

@ -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,

View File

@ -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);
}