Hi,

currently the sdap interface is only used by the ID provider and
consequently only offers special search for users and groups. This patch
adds a generic search, i.e. the caller can specify the search base and
and an attribute list. This will be used by the IPA access provider to
load HABC rules from the IPA server.

bye,
Sumit
>From 464e9879103f2a5f708435737ad2653b63b3f999 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sb...@redhat.com>
Date: Thu, 17 Sep 2009 11:12:36 +0200
Subject: [PATCH] added generic LDAP search sdap_get_generic_send/_recv

---
 server/providers/ldap/sdap_async.c |  261 ++++++++++++++++++++++++++++++++++++
 server/providers/ldap/sdap_async.h |   17 +++
 2 files changed, 278 insertions(+), 0 deletions(-)

diff --git a/server/providers/ldap/sdap_async.c 
b/server/providers/ldap/sdap_async.c
index f088e51..1de2f34 100644
--- a/server/providers/ldap/sdap_async.c
+++ b/server/providers/ldap/sdap_async.c
@@ -3020,3 +3020,264 @@ int sdap_cli_connect_recv(struct tevent_req *req, 
TALLOC_CTX *memctx,
     }
     return EOK;
 }
+
+/* ==Generic Search============================================ */
+
+struct sdap_get_generic_state {
+    struct tevent_context *ev;
+    struct sdap_options *opts;
+    struct sdap_handle *sh;
+    struct sss_domain_info *dom;
+    const char **attrs;
+    const char *filter;
+    const char *search_base;
+    struct reply_item *reply_list;
+
+    struct sysdb_handle *handle;
+    struct sdap_op *op;
+};
+
+static int sdap_parse_generic_entry(TALLOC_CTX *memctx,
+                                    struct sdap_handle *sh,
+                                    struct sdap_msg *sm,
+                                    struct sysdb_attrs **_attrs)
+{
+    struct sysdb_attrs *attrs;
+    BerElement *ber = NULL;
+    struct berval **vals;
+    struct ldb_val v;
+    char *str;
+    int lerrno;
+    int i;
+    int ret;
+
+    lerrno = 0;
+    ldap_set_option(sh->ldap, LDAP_OPT_RESULT_CODE, &lerrno);
+
+    attrs = sysdb_new_attrs(memctx);
+    if (!attrs) return ENOMEM;
+
+    str = ldap_get_dn(sh->ldap, sm->msg);
+    if (!str) {
+        ldap_get_option(sh->ldap, LDAP_OPT_RESULT_CODE, &lerrno);
+        DEBUG(1, ("ldap_get_dn failed: %d(%s)\n",
+                  lerrno, ldap_err2string(lerrno)));
+        ret = EIO;
+        goto fail;
+    }
+
+    DEBUG(9, ("OriginalDN: [%s].\n", str));
+    ret = sysdb_attrs_add_string(attrs, SYSDB_ORIG_DN, str);
+    if (ret) goto fail;
+    ldap_memfree(str);
+
+    str = ldap_first_attribute(sh->ldap, sm->msg, &ber);
+    if (!str) {
+        ldap_get_option(sh->ldap, LDAP_OPT_RESULT_CODE, &lerrno);
+        DEBUG(9, ("Entry has no attributes [%d(%s)]!?\n",
+                  lerrno, ldap_err2string(lerrno)));
+    }
+    while (str) {
+        vals = ldap_get_values_len(sh->ldap, sm->msg, str);
+        if (!vals) {
+            ldap_get_option(sh->ldap, LDAP_OPT_RESULT_CODE, &lerrno);
+            DEBUG(1, ("LDAP Library error: %d(%s)",
+                      lerrno, ldap_err2string(lerrno)));
+            ret = EIO;
+            goto fail;
+        }
+        if (!vals[0]) {
+            DEBUG(1, ("Missing value after ldap_get_values() ??\n"));
+            ret = EINVAL;
+            goto fail;
+        }
+        for (i = 0; vals[i]; i++) {
+            v.data = (uint8_t *) vals[i]->bv_val;
+            v.length = vals[i]->bv_len;
+
+            ret = sysdb_attrs_add_val(attrs, str, &v);
+            if (ret) goto fail;
+        }
+        ldap_value_free_len(vals);
+
+        ldap_memfree(str);
+        str = ldap_next_attribute(sh->ldap, sm->msg, ber);
+    }
+    ber_free(ber, 0);
+
+    ldap_get_option(sh->ldap, LDAP_OPT_RESULT_CODE, &lerrno);
+    if (lerrno) {
+        DEBUG(1, ("LDAP Library error: %d(%s)",
+                  lerrno, ldap_err2string(lerrno)));
+        ret = EIO;
+        goto fail;
+    }
+
+    *_attrs = attrs;
+    return EOK;
+
+fail:
+    if (ber) ber_free(ber, 0);
+    talloc_free(attrs);
+    return ret;
+}
+
+static void sdap_get_generic_done(struct sdap_op *op,
+                                 struct sdap_msg *reply,
+                                 int error, void *pvt);
+
+struct tevent_req *sdap_get_generic_send(TALLOC_CTX *memctx,
+                                       struct tevent_context *ev,
+                                       struct sss_domain_info *dom,
+                                       struct sysdb_ctx *sysdb,
+                                       struct sdap_options *opts,
+                                       struct sdap_handle *sh,
+                                       const char **attrs,
+                                       const char *filter,
+                                       const char *search_base)
+{
+    struct tevent_req *req = NULL;
+    struct sdap_get_generic_state *state = NULL;
+    int lret;
+    int ret;
+    int msgid;
+
+    req = tevent_req_create(memctx, &state, struct sdap_get_generic_state);
+    if (!req) return NULL;
+
+    state->ev = ev;
+    state->opts = opts;
+    state->dom = dom;
+    state->sh = sh;
+    state->filter = filter;
+    state->attrs = attrs;
+    state->search_base = search_base;
+    state->reply_list = NULL;
+
+    DEBUG(7, ("calling ldap_search_ext with [%s][%s].\n", state->filter,
+                                                          state->search_base));
+    if (debug_level >= 7) {
+        int i;
+
+        for (i = 0; state->attrs[i]; i++) {
+            DEBUG(7, ("Requesting attrs: [%s]\n", state->attrs[i]));
+        }
+    }
+
+    lret = ldap_search_ext(state->sh->ldap, state->search_base,
+                           LDAP_SCOPE_SUBTREE, state->filter,
+                           discard_const(state->attrs),
+                           false, NULL, NULL, NULL, 0, &msgid);
+    if (lret != LDAP_SUCCESS) {
+        DEBUG(3, ("ldap_search_ext failed: %s\n", ldap_err2string(lret)));
+        ret = EIO;
+        goto fail;
+    }
+    DEBUG(8, ("ldap_search_ext called, msgid = %d\n", msgid));
+
+    /* FIXME: get timeouts from configuration, for now 10 minutes */
+    ret = sdap_op_add(state, state->ev, state->sh, msgid,
+                      sdap_get_generic_done, req, 600, &state->op);
+    if (ret != EOK) {
+        DEBUG(1, ("Failed to set up operation!\n"));
+        goto fail;
+    }
+
+    return req;
+
+fail:
+    tevent_req_error(req, ret);
+    tevent_req_post(req, ev);
+    return req;
+}
+
+
+static void sdap_get_generic_done(struct sdap_op *op,
+                                 struct sdap_msg *reply,
+                                 int error, void *pvt)
+{
+    struct tevent_req *req = talloc_get_type(pvt, struct tevent_req);
+    struct sdap_get_generic_state *state = tevent_req_data(req,
+                                            struct sdap_get_generic_state);
+    struct reply_item *reply_item;
+    int ret;
+    struct sysdb_attrs *attrs;
+
+    if (error) {
+        tevent_req_error(req, error);
+        return;
+    }
+
+    switch (ldap_msgtype(reply->msg)) {
+    case LDAP_RES_SEARCH_REFERENCE:
+        /* ignore references for now */
+        talloc_free(reply);
+
+        /* unlock the operation so that we can proceed with the next result */
+        sdap_unlock_next_reply(state->op);
+        break;
+
+    case LDAP_RES_SEARCH_ENTRY:
+        ret = sdap_parse_generic_entry(state, state->sh, reply, &attrs);
+        if (ret != EOK) {
+            DEBUG(1, ("sdap_parse_generic_entry failed.\n"));
+            tevent_req_error(req, ENOMEM);
+            return;
+        }
+
+        reply_item = talloc(state, struct reply_item);
+        if (reply_item == NULL) {
+            DEBUG(1, ("talloc failed.\n"));
+            tevent_req_error(req, ENOMEM);
+            return;
+        }
+
+        talloc_steal(reply_item, attrs);
+        reply_item->attrs = attrs;
+        reply_item->next = state->reply_list;
+
+        state->reply_list = reply_item;
+
+        sdap_unlock_next_reply(state->op);
+        break;
+    case LDAP_RES_SEARCH_RESULT:
+        tevent_req_done(req);
+        return;
+
+        break;
+    default:
+        /* what is going on here !? */
+        tevent_req_error(req, EIO);
+        return;
+    }
+
+    return;
+}
+
+int sdap_get_generic_recv(struct tevent_req *req,
+                          TALLOC_CTX *mem_ctx,
+                          struct reply_item **reply_list)
+{
+    struct sdap_get_generic_state *state = tevent_req_data(req,
+                                            struct sdap_get_generic_state);
+    enum tevent_req_state tstate;
+    uint64_t err;
+    struct reply_item *ri;
+
+    if (tevent_req_is_error(req, &tstate, &err)) {
+        if (err) return err;
+        return EIO;
+    }
+
+    if (reply_list) {
+        ri = state->reply_list;
+        while (ri != NULL) {
+            talloc_steal(mem_ctx, ri);
+            ri = ri->next;
+        }
+        *reply_list = state->reply_list;
+    }
+
+    return EOK;
+}
+
diff --git a/server/providers/ldap/sdap_async.h 
b/server/providers/ldap/sdap_async.h
index c50133c..8baf0c9 100644
--- a/server/providers/ldap/sdap_async.h
+++ b/server/providers/ldap/sdap_async.h
@@ -95,3 +95,20 @@ struct tevent_req *sdap_cli_connect_send(TALLOC_CTX *memctx,
                                                 struct sdap_options *opts);
 int sdap_cli_connect_recv(struct tevent_req *req, TALLOC_CTX *memctx,
                                  struct sdap_handle **gsh);
+
+struct reply_item {
+    struct sysdb_attrs *attrs;
+    struct reply_item *next;
+};
+
+struct tevent_req *sdap_get_generic_send(TALLOC_CTX *memctx,
+                                       struct tevent_context *ev,
+                                       struct sss_domain_info *dom,
+                                       struct sysdb_ctx *sysdb,
+                                       struct sdap_options *opts,
+                                       struct sdap_handle *sh,
+                                       const char **attrs,
+                                       const char *filter,
+                                       const char *search_base);
+int sdap_get_generic_recv(struct tevent_req *req,
+                         TALLOC_CTX *mem_ctx, struct reply_item **reply_list);
-- 
1.6.2.5

_______________________________________________
sssd-devel mailing list
sssd-devel@lists.fedorahosted.org
https://fedorahosted.org/mailman/listinfo/sssd-devel

Reply via email to