summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimo Sorce <simo@redhat.com>2016-12-16 07:12:45 -0500
committerMartin Babinsky <mbabinsk@redhat.com>2017-03-10 09:17:28 +0100
commit9f13b330aaec468a018472dce5fc77131277de94 (patch)
tree3757a178abffc3a9e16bd93581a4e97144dd6dae
parentabf25d3cb6570e6ae7cd094ea6a5f4a1bd75d8a7 (diff)
downloadfreeipa-9f13b330aaec468a018472dce5fc77131277de94.tar.gz
freeipa-9f13b330aaec468a018472dce5fc77131277de94.tar.xz
freeipa-9f13b330aaec468a018472dce5fc77131277de94.zip
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>
-rw-r--r--daemons/ipa-kdb/ipa_kdb.h10
-rw-r--r--daemons/ipa-kdb/ipa_kdb_common.c103
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);
+}
+