summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Březina <pbrezina@redhat.com>2016-05-24 09:29:54 +0200
committerJakub Hrozek <jhrozek@redhat.com>2016-06-20 14:48:47 +0200
commit565b9955cc439ade58cc24a98168060a60f33e7a (patch)
tree47f3da10a8361ce537e9f48402cc99ffef2e17d4
parentf48b1dda750511b57dce360fd18da2402adbcbb0 (diff)
downloadsssd-565b9955cc439ade58cc24a98168060a60f33e7a.tar.gz
sssd-565b9955cc439ade58cc24a98168060a60f33e7a.tar.xz
sssd-565b9955cc439ade58cc24a98168060a60f33e7a.zip
sdap ops: add support for deref
Reviewed-by: Sumit Bose <sbose@redhat.com> Reviewed-by: Jakub Hrozek <jhrozek@redhat.com> Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
-rw-r--r--src/providers/ldap/sdap_ops.c253
-rw-r--r--src/providers/ldap/sdap_ops.h36
2 files changed, 289 insertions, 0 deletions
diff --git a/src/providers/ldap/sdap_ops.c b/src/providers/ldap/sdap_ops.c
index 5cbacdcdb..3fc968f0b 100644
--- a/src/providers/ldap/sdap_ops.c
+++ b/src/providers/ldap/sdap_ops.c
@@ -292,3 +292,256 @@ int sdap_search_bases_return_first_recv(struct tevent_req *req,
{
return sdap_search_bases_ex_recv(req, mem_ctx, _reply_count, _reply);
}
+
+struct sdap_deref_bases_ex_state {
+ struct tevent_context *ev;
+ struct sdap_options *opts;
+ struct sdap_handle *sh;
+ const char *filter;
+ const char **attrs;
+ const char *deref_attr;
+ struct sdap_attr_map_info *maps;
+ size_t num_maps;
+ unsigned int flags;
+ bool return_first_reply;
+ int timeout;
+
+ size_t base_iter;
+ struct sdap_search_base *cur_base;
+ struct sdap_search_base **bases;
+
+ size_t reply_count;
+ struct sdap_deref_attrs **reply;
+};
+
+static errno_t sdap_deref_bases_ex_next_base(struct tevent_req *req);
+static void sdap_deref_bases_ex_done(struct tevent_req *subreq);
+
+static struct tevent_req *
+sdap_deref_bases_ex_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sdap_options *opts,
+ struct sdap_handle *sh,
+ struct sdap_search_base **bases,
+ struct sdap_attr_map_info *maps,
+ const char *filter,
+ const char **attrs,
+ const char *deref_attr,
+ unsigned int flags,
+ bool return_first_reply,
+ int timeout)
+{
+ struct tevent_req *req;
+ struct sdap_deref_bases_ex_state *state;
+ errno_t ret;
+
+ req = tevent_req_create(mem_ctx, &state, struct sdap_deref_bases_ex_state);
+ if (req == NULL) {
+ return NULL;
+ }
+
+ if (bases == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "No search base specified!\n");
+ ret = ERR_INTERNAL;
+ goto immediately;
+ }
+
+ if (maps == NULL || attrs == NULL || deref_attr == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "No attributes or map specified!\n");
+ ret = ERR_INTERNAL;
+ goto immediately;
+ }
+
+ state->ev = ev;
+ state->opts = opts;
+ state->sh = sh;
+ state->bases = bases;
+ state->maps = maps;
+ state->filter = filter;
+ state->attrs = attrs;
+ state->deref_attr = deref_attr;
+ state->return_first_reply = return_first_reply;
+ state->flags = flags;
+
+ state->timeout = timeout == 0
+ ? dp_opt_get_int(opts->basic, SDAP_SEARCH_TIMEOUT)
+ : timeout;
+
+ for (state->num_maps = 0; maps[state->num_maps].map != NULL;
+ state->num_maps++) {
+ /* no op */;
+ }
+
+ state->base_iter = 0;
+ ret = sdap_deref_bases_ex_next_base(req);
+ if (ret == EAGAIN) {
+ /* asynchronous processing */
+ return req;
+ }
+
+immediately:
+ if (ret == EOK) {
+ tevent_req_done(req);
+ } else {
+ tevent_req_error(req, ret);
+ }
+ tevent_req_post(req, ev);
+
+ return req;
+}
+
+static errno_t sdap_deref_bases_ex_next_base(struct tevent_req *req)
+{
+ struct sdap_deref_bases_ex_state *state;
+ struct tevent_req *subreq;
+
+ state = tevent_req_data(req, struct sdap_deref_bases_ex_state);
+ state->cur_base = state->bases[state->base_iter];
+ if (state->cur_base == NULL) {
+ return EOK;
+ }
+
+ DEBUG(SSSDBG_TRACE_FUNC, "Issuing LDAP deref lookup with base [%s]\n",
+ state->cur_base->basedn);
+
+ subreq = sdap_deref_search_with_filter_send(state, state->ev, state->opts,
+ state->sh, state->cur_base->basedn, state->filter,
+ state->deref_attr, state->attrs, state->num_maps, state->maps,
+ state->timeout, state->flags);
+ if (subreq == NULL) {
+ return ENOMEM;
+ }
+
+ tevent_req_set_callback(subreq, sdap_deref_bases_ex_done, req);
+
+ state->base_iter++;
+ return EAGAIN;
+}
+
+static void sdap_deref_bases_ex_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req;
+ struct sdap_deref_bases_ex_state *state;
+ struct sdap_deref_attrs **attrs;
+ size_t count;
+ size_t i;
+ int ret;
+
+ req = tevent_req_callback_data(subreq, struct tevent_req);
+ state = tevent_req_data(req, struct sdap_deref_bases_ex_state);
+
+ DEBUG(SSSDBG_TRACE_FUNC, "Receiving data from base [%s]\n",
+ state->cur_base->basedn);
+
+ ret = sdap_deref_search_with_filter_recv(subreq, state, &count, &attrs);
+ talloc_zfree(subreq);
+ if (ret != EOK) {
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ /* Add rules to result. */
+ if (count > 0) {
+ if (state->return_first_reply == false) {
+ /* Merge with previous reply. */
+ state->reply = talloc_realloc(state, state->reply,
+ struct sdap_deref_attrs *,
+ state->reply_count + count);
+ if (state->reply == NULL) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+
+ for (i = 0; i < count; i++) {
+ state->reply[state->reply_count + i] = talloc_steal(state->reply,
+ attrs[i]);
+ }
+
+ state->reply_count += count;
+ } else {
+ /* Return the first successful search result. */
+ state->reply_count = count;
+ state->reply = attrs;
+ tevent_req_done(req);
+ return;
+ }
+ }
+
+ /* Try next search base. */
+ ret = sdap_deref_bases_ex_next_base(req);
+ if (ret == EOK) {
+ tevent_req_done(req);
+ } else if (ret != EAGAIN) {
+ tevent_req_error(req, ret);
+ }
+
+ return;
+}
+
+static int sdap_deref_bases_ex_recv(struct tevent_req *req,
+ TALLOC_CTX *mem_ctx,
+ size_t *reply_count,
+ struct sdap_deref_attrs ***reply)
+{
+ struct sdap_deref_bases_ex_state *state =
+ tevent_req_data(req, struct sdap_deref_bases_ex_state);
+
+ TEVENT_REQ_RETURN_ON_ERROR(req);
+
+ *reply_count = state->reply_count;
+ *reply = talloc_steal(mem_ctx, state->reply);
+
+ return EOK;
+}
+
+struct tevent_req *
+sdap_deref_bases_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sdap_options *opts,
+ struct sdap_handle *sh,
+ struct sdap_search_base **bases,
+ struct sdap_attr_map_info *maps,
+ const char *filter,
+ const char **attrs,
+ const char *deref_attr,
+ unsigned int flags,
+ int timeout)
+{
+ return sdap_deref_bases_ex_send(mem_ctx, ev, opts, sh, bases, maps,
+ filter, attrs, deref_attr, flags,
+ false, timeout);
+}
+
+int sdap_deref_bases_recv(struct tevent_req *req,
+ TALLOC_CTX *mem_ctx,
+ size_t *_reply_count,
+ struct sdap_deref_attrs ***_reply)
+{
+ return sdap_deref_bases_ex_recv(req, mem_ctx, _reply_count, _reply);
+}
+
+struct tevent_req *
+sdap_deref_bases_return_first_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sdap_options *opts,
+ struct sdap_handle *sh,
+ struct sdap_search_base **bases,
+ struct sdap_attr_map_info *maps,
+ const char *filter,
+ const char **attrs,
+ const char *deref_attr,
+ unsigned int flags,
+ int timeout)
+{
+ return sdap_deref_bases_ex_send(mem_ctx, ev, opts, sh, bases, maps,
+ filter, attrs, deref_attr, flags,
+ true, timeout);
+}
+
+int sdap_deref_bases_return_first_recv(struct tevent_req *req,
+ TALLOC_CTX *mem_ctx,
+ size_t *_reply_count,
+ struct sdap_deref_attrs ***_reply)
+{
+ return sdap_deref_bases_ex_recv(req, mem_ctx, _reply_count, _reply);
+}
diff --git a/src/providers/ldap/sdap_ops.h b/src/providers/ldap/sdap_ops.h
index 928c264f4..cc9de00d2 100644
--- a/src/providers/ldap/sdap_ops.h
+++ b/src/providers/ldap/sdap_ops.h
@@ -58,4 +58,40 @@ int sdap_search_bases_return_first_recv(struct tevent_req *req,
size_t *_reply_count,
struct sysdb_attrs ***_reply);
+struct tevent_req *
+sdap_deref_bases_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sdap_options *opts,
+ struct sdap_handle *sh,
+ struct sdap_search_base **bases,
+ struct sdap_attr_map_info *maps,
+ const char *filter,
+ const char **attrs,
+ const char *deref_attr,
+ unsigned int flags,
+ int timeout);
+
+int sdap_deref_bases_recv(struct tevent_req *req,
+ TALLOC_CTX *mem_ctx,
+ size_t *_reply_count,
+ struct sdap_deref_attrs ***_reply);
+
+struct tevent_req *
+sdap_deref_bases_return_first_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sdap_options *opts,
+ struct sdap_handle *sh,
+ struct sdap_search_base **bases,
+ struct sdap_attr_map_info *maps,
+ const char *filter,
+ const char **attrs,
+ const char *deref_attr,
+ unsigned int flags,
+ int timeout);
+
+int sdap_deref_bases_return_first_recv(struct tevent_req *req,
+ TALLOC_CTX *mem_ctx,
+ size_t *_reply_count,
+ struct sdap_deref_attrs ***_reply);
+
#endif /* _SDAP_OPS_H_ */