From bb89c1a6330f5ffc18331b56120a980ac8ed9758 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
Date: Mon, 23 Apr 2012 13:15:21 +0200
Subject: [PATCH 01/11] sudo ldap provider: move async routines to
 sdap_async_sudo.c

---
 Makefile.am                          |    1 +
 src/providers/ldap/sdap_async_sudo.c |  710 ++++++++++++++++++++++++++++++++++
 src/providers/ldap/sdap_sudo.c       |  675 --------------------------------
 3 files changed, 711 insertions(+), 675 deletions(-)
 create mode 100644 src/providers/ldap/sdap_async_sudo.c

diff --git a/Makefile.am b/Makefile.am
index cb039c2..b07a9ec 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1089,6 +1089,7 @@ if BUILD_SUDO
 libsss_ldap_common_la_SOURCES += \
     src/providers/ldap/sdap_sudo_cache.c \
     src/providers/ldap/sdap_sudo_timer.c \
+    src/providers/ldap/sdap_async_sudo.c \
     src/providers/ldap/sdap_sudo.c
 endif
 
diff --git a/src/providers/ldap/sdap_async_sudo.c b/src/providers/ldap/sdap_async_sudo.c
new file mode 100644
index 0000000..115e3a7
--- /dev/null
+++ b/src/providers/ldap/sdap_async_sudo.c
@@ -0,0 +1,710 @@
+/*
+    SSSD
+
+    Async LDAP Helper routines for sudo
+
+    Authors:
+        Pavel Březina <pbrezina@redhat.com>
+
+    Copyright (C) 2012 Red Hat
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <errno.h>
+#include <talloc.h>
+#include <tevent.h>
+
+#include "providers/dp_backend.h"
+#include "providers/ldap/ldap_common.h"
+#include "providers/ldap/sdap.h"
+#include "providers/ldap/sdap_async.h"
+#include "providers/ldap/sdap_sudo.h"
+#include "providers/ldap/sdap_sudo_cache.h"
+#include "db/sysdb_sudo.h"
+
+struct sdap_sudo_load_sudoers_state {
+    struct tevent_context *ev;
+    struct sdap_sudo_ctx *sudo_ctx;
+    struct sdap_options *opts;
+    struct sdap_handle *sh;
+    struct sysdb_attrs **ldap_rules; /* search result will be stored here */
+    size_t ldap_rules_count; /* search result will be stored here */
+
+    const char **attrs;
+    const char *filter;
+    size_t base_iter;
+    struct sdap_search_base **search_bases;
+    int timeout;
+};
+
+struct sdap_sudo_refresh_state {
+    struct be_ctx *be_ctx;
+    struct be_sudo_req *sudo_req;
+    struct sdap_options *opts;
+    struct sdap_id_op *sdap_op;
+    struct sdap_id_conn_cache *sdap_conn_cache;
+
+    int dp_error;
+    int error;
+};
+
+static int sdap_sudo_connect(struct tevent_req *req);
+
+static void sdap_sudo_connect_done(struct tevent_req *subreq);
+
+static struct tevent_req * sdap_sudo_load_sudoers_send(TALLOC_CTX *mem_ctx,
+                                                       struct tevent_context *ev,
+                                                       struct be_sudo_req *sudo_req,
+                                                       struct sdap_options *opts,
+                                                       struct sdap_handle *sh);
+
+static errno_t sdap_sudo_load_sudoers_next_base(struct tevent_req *req);
+
+static void sdap_sudo_load_sudoers_process(struct tevent_req *subreq);
+
+static int sdap_sudo_load_sudoers_recv(struct tevent_req *req,
+                                       TALLOC_CTX *mem_ctx,
+                                       size_t *rules_count,
+                                       struct sysdb_attrs ***rules);
+
+static void sdap_sudo_load_sudoers_done(struct tevent_req *req);
+
+static int sdap_sudo_purge_sudoers(struct sysdb_ctx *sysdb_ctx,
+                                   struct sss_domain_info *domain,
+                                   struct be_sudo_req *sudo_req);
+
+static int sdap_sudo_store_sudoers(struct sysdb_ctx *sysdb_ctx,
+                                   struct sdap_options *opts,
+                                   size_t rules_count,
+                                   struct sysdb_attrs **rules);
+
+static const char *sdap_sudo_build_filter(TALLOC_CTX *mem_ctx,
+                                          struct sdap_attr_map *map,
+                                          struct be_sudo_req *sudo_req);
+
+static const char *sdap_sudo_build_user_filter(TALLOC_CTX *mem_ctx,
+                                               struct sdap_attr_map *map,
+                                               const char *username,
+                                               uid_t uid,
+                                               char **groups);
+
+struct tevent_req *sdap_sudo_refresh_send(TALLOC_CTX *mem_ctx,
+                                          struct be_ctx *be_ctx,
+                                          struct be_sudo_req *sudo_req,
+                                          struct sdap_options *opts,
+                                          struct sdap_id_conn_cache *conn_cache)
+{
+    struct tevent_req *req = NULL;
+    struct sdap_sudo_refresh_state *state = NULL;
+    int ret;
+
+    req = tevent_req_create(mem_ctx, &state, struct sdap_sudo_refresh_state);
+    if (!req) {
+        return NULL;
+    }
+
+    state->be_ctx = be_ctx;
+    state->sudo_req = sudo_req;
+    state->opts = opts;
+    state->sdap_op = NULL;
+    state->sdap_conn_cache = conn_cache;
+    state->dp_error = DP_ERR_OK;
+    state->error = EOK;
+
+    switch (sudo_req->type) {
+    case BE_REQ_SUDO_ALL:
+        DEBUG(SSSDBG_TRACE_FUNC, ("Requested refresh for: <ALL>\n"));
+        break;
+    case BE_REQ_SUDO_DEFAULTS:
+        DEBUG(SSSDBG_TRACE_FUNC, ("Requested refresh of cn=defaults\n"));
+        break;
+    case BE_REQ_SUDO_USER:
+        DEBUG(SSSDBG_TRACE_FUNC, ("Requested refresh for: %s\n",
+                                  sudo_req->username));
+        break;
+    default:
+        DEBUG(SSSDBG_CRIT_FAILURE, ("Invalid request type %d\n", sudo_req->type));
+        ret = EINVAL;
+        goto immediately;
+    }
+
+    ret = sdap_sudo_connect(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, be_ctx->ev);
+
+    return req;
+}
+
+int sdap_sudo_refresh_recv(struct tevent_req *req,
+                           int *dp_error,
+                           int *error)
+{
+    struct sdap_sudo_refresh_state *state = NULL;
+
+    state = tevent_req_data(req, struct sdap_sudo_refresh_state);
+
+    TEVENT_REQ_RETURN_ON_ERROR(req);
+
+    *dp_error = state->dp_error;
+    *error = state->error;
+
+    return EOK;
+}
+
+int sdap_sudo_connect(struct tevent_req *req)
+{
+    struct tevent_req *subreq = NULL;
+    struct sdap_sudo_refresh_state *state = NULL;
+    int ret;
+
+    state = tevent_req_data(req, struct sdap_sudo_refresh_state);
+
+    if (be_is_offline(state->be_ctx)) {
+        state->dp_error = DP_ERR_OFFLINE;
+        state->error = EAGAIN;
+        return EOK;
+    }
+
+    if (state->sdap_op == NULL) {
+        state->sdap_op = sdap_id_op_create(state, state->sdap_conn_cache);
+        if (state->sdap_op == NULL) {
+            DEBUG(SSSDBG_CRIT_FAILURE, ("sdap_id_op_create() failed\n"));
+            state->dp_error = DP_ERR_FATAL;
+            state->error = EIO;
+            return EIO;
+        }
+    }
+
+    subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret);
+    if (subreq == NULL) {
+        DEBUG(SSSDBG_CRIT_FAILURE,
+              ("sdap_id_op_connect_send() failed: %d(%s)\n", ret, strerror(ret)));
+        talloc_zfree(state->sdap_op);
+        state->dp_error = DP_ERR_FATAL;
+        state->error = ret;
+        return ret;
+    }
+
+    tevent_req_set_callback(subreq, sdap_sudo_connect_done, req);
+
+    return EAGAIN;
+}
+
+void sdap_sudo_connect_done(struct tevent_req *subreq)
+{
+    struct tevent_req *req = NULL; /* req from sdap_sudo_refresh_send() */
+    struct sdap_sudo_refresh_state *state = NULL;
+    int dp_error;
+    int ret;
+
+    req = tevent_req_callback_data(subreq, struct tevent_req);
+    state = tevent_req_data(req, struct sdap_sudo_refresh_state);
+
+    ret = sdap_id_op_connect_recv(subreq, &dp_error);
+    talloc_zfree(subreq);
+
+    if (dp_error == DP_ERR_OFFLINE) {
+        talloc_zfree(state->sdap_op);
+        state->dp_error = DP_ERR_OFFLINE;
+        state->error = EAGAIN;
+        tevent_req_done(req);
+        return;
+    } else if (ret != EOK) {
+        DEBUG(SSSDBG_CRIT_FAILURE,
+              ("SUDO LDAP connection failed - %s\n", strerror(ret)));
+        goto fail;
+    }
+
+    DEBUG(SSSDBG_TRACE_FUNC, ("SUDO LDAP connection successful\n"));
+
+    subreq = sdap_sudo_load_sudoers_send(state, state->be_ctx->ev,
+                                         state->sudo_req, state->opts,
+                                         sdap_id_op_handle(state->sdap_op));
+    if (subreq == NULL) {
+        ret = EFAULT;
+        goto fail;
+    }
+
+    tevent_req_set_callback(subreq, sdap_sudo_load_sudoers_done, req);
+
+    return;
+
+fail:
+    state->dp_error = DP_ERR_FATAL;
+    state->error = ret;
+    tevent_req_error(req, ret);
+}
+
+struct tevent_req * sdap_sudo_load_sudoers_send(TALLOC_CTX *mem_ctx,
+                                                struct tevent_context *ev,
+                                                struct be_sudo_req *sudo_req,
+                                                struct sdap_options *opts,
+                                                struct sdap_handle *sh)
+
+
+
+{
+    struct tevent_req *req = NULL;
+    struct sdap_sudo_load_sudoers_state *state = NULL;
+    int ret;
+
+    req = tevent_req_create(mem_ctx, &state, struct sdap_sudo_load_sudoers_state);
+    if (!req) {
+        return NULL;
+    }
+
+    state->ev = ev;
+    state->opts = opts;
+    state->sh = sh;
+    state->base_iter = 0;
+    state->search_bases = opts->sudo_search_bases;
+    state->timeout = dp_opt_get_int(opts->basic, SDAP_SEARCH_TIMEOUT);
+    state->ldap_rules = NULL;
+    state->ldap_rules_count = 0;
+
+    if (!state->search_bases) {
+        DEBUG(SSSDBG_CRIT_FAILURE,
+              ("SUDOERS lookup request without a search base\n"));
+        ret = EINVAL;
+        goto done;
+    }
+
+    /* create filter */
+    state->filter = sdap_sudo_build_filter(state, opts->sudorule_map, sudo_req);
+    if (state->filter == NULL) {
+        goto fail;
+    }
+
+    /* create attrs from map */
+    ret = build_attrs_from_map(state, opts->sudorule_map, SDAP_OPTS_SUDO,
+                               &state->attrs);
+    if (ret != EOK) {
+        goto fail;
+    }
+
+    /* begin search */
+    ret = sdap_sudo_load_sudoers_next_base(req);
+
+done:
+    if (ret != EOK) {
+        tevent_req_error(req, ret);
+        tevent_req_post(req, ev);
+    }
+
+    return req;
+
+fail:
+    talloc_zfree(req);
+    return NULL;
+}
+
+static errno_t sdap_sudo_load_sudoers_next_base(struct tevent_req *req)
+{
+    struct tevent_req *subreq = NULL;
+    struct sdap_sudo_load_sudoers_state *state = NULL;
+    struct sdap_search_base *search_base = NULL;
+    char *filter = NULL;
+
+    state = tevent_req_data(req, struct sdap_sudo_load_sudoers_state);
+    search_base = state->search_bases[state->base_iter];
+    if (search_base == NULL) {
+        /* should not happen */
+        DEBUG(SSSDBG_CRIT_FAILURE, ("search_base is null\n"));
+        return EFAULT;
+    }
+
+    /* create filter */
+    filter = sdap_get_id_specific_filter(state, state->filter,
+                                         search_base->filter);
+    if (filter == NULL) {
+        return ENOMEM;
+    }
+
+    /* send request */
+    DEBUG(SSSDBG_TRACE_FUNC,
+          ("Searching for sudo rules with base [%s]\n",
+           search_base->basedn));
+
+    subreq = sdap_get_generic_send(state,
+                                   state->ev,
+                                   state->opts,
+                                   state->sh,
+                                   search_base->basedn,
+                                   search_base->scope,
+                                   filter,
+                                   state->attrs,
+                                   state->opts->sudorule_map,
+                                   SDAP_OPTS_SUDO,
+                                   state->timeout,
+                                   true);
+    if (subreq == NULL) {
+        return ENOMEM;
+    }
+
+    tevent_req_set_callback(subreq, sdap_sudo_load_sudoers_process, req);
+
+    return EOK;
+}
+
+static void sdap_sudo_load_sudoers_process(struct tevent_req *subreq)
+{
+    struct tevent_req *req = NULL;
+    struct sdap_sudo_load_sudoers_state *state = NULL;
+    struct sdap_search_base *search_base = NULL;
+    struct sysdb_attrs **attrs = NULL;
+    size_t count;
+    int ret;
+    int i;
+
+    req = tevent_req_callback_data(subreq, struct tevent_req);
+    state = tevent_req_data(req, struct sdap_sudo_load_sudoers_state);
+    search_base = state->search_bases[state->base_iter];
+
+    DEBUG(SSSDBG_TRACE_FUNC,
+          ("Receiving sudo rules with base [%s]\n",
+           search_base->basedn));
+
+    ret = sdap_get_generic_recv(subreq, state, &count, &attrs);
+    talloc_zfree(subreq);
+    if (ret) {
+        tevent_req_error(req, ret);
+        return;
+    }
+
+    /* add rules to result */
+    if (count > 0) {
+        state->ldap_rules = talloc_realloc(state, state->ldap_rules,
+                                           struct sysdb_attrs *,
+                                           state->ldap_rules_count + count);
+        if (state->ldap_rules == NULL) {
+            tevent_req_error(req, ENOMEM);
+            return;
+        }
+
+        for (i = 0; i < count; i++) {
+            state->ldap_rules[state->ldap_rules_count + i] = talloc_steal(
+                                                   state->ldap_rules, attrs[i]);
+        }
+
+        state->ldap_rules_count += count;
+    }
+
+    /* go to next base */
+    state->base_iter++;
+    if (state->search_bases[state->base_iter]) {
+        ret = sdap_sudo_load_sudoers_next_base(req);
+        if (ret != EOK) {
+            tevent_req_error(req, ret);
+        }
+
+        return;
+    }
+
+    /* we are done */
+    tevent_req_done(req);
+}
+
+int sdap_sudo_load_sudoers_recv(struct tevent_req *req,
+                                TALLOC_CTX *mem_ctx,
+                                size_t *rules_count,
+                                struct sysdb_attrs ***rules)
+{
+    struct sdap_sudo_load_sudoers_state *state = NULL;
+
+    state = tevent_req_data(req, struct sdap_sudo_load_sudoers_state);
+
+    TEVENT_REQ_RETURN_ON_ERROR(req);
+
+    *rules_count = state->ldap_rules_count;
+    *rules = talloc_steal(mem_ctx, state->ldap_rules);
+
+    return EOK;
+}
+
+void sdap_sudo_load_sudoers_done(struct tevent_req *subreq)
+{
+    struct tevent_req *req = NULL; /* req from sdap_sudo_refresh_send() */
+    struct sdap_sudo_refresh_state *state = NULL;
+    struct sysdb_attrs **rules = NULL;
+    size_t rules_count;
+    int ret;
+
+    req = tevent_req_callback_data(subreq, struct tevent_req);
+    state = tevent_req_data(req, struct sdap_sudo_refresh_state);
+
+    ret = sdap_sudo_load_sudoers_recv(subreq, state, &rules_count, &rules);
+    talloc_zfree(subreq);
+    if (ret != EOK) {
+        goto done;
+    }
+
+    DEBUG(SSSDBG_TRACE_FUNC, ("Received %d rules\n", rules_count));
+
+    /* purge cache */
+    ret = sdap_sudo_purge_sudoers(state->be_ctx->sysdb, state->be_ctx->domain,
+                                  state->sudo_req);
+    if (ret != EOK) {
+        goto done;
+    }
+
+    /* store rules */
+    ret = sdap_sudo_store_sudoers(state->be_ctx->sysdb, state->opts,
+                                  rules_count, rules);
+    if (ret != EOK) {
+        goto done;
+    }
+
+    DEBUG(SSSDBG_TRACE_FUNC, ("Sudoers is successfuly stored in cache\n"));
+
+    ret = EOK;
+
+done:
+    state->error = ret;
+    if (ret == EOK) {
+        state->dp_error = DP_ERR_OK;
+        tevent_req_done(req);
+    } else {
+        state->dp_error = DP_ERR_FATAL;
+        tevent_req_error(req, ret);
+    }
+}
+
+int sdap_sudo_purge_sudoers(struct sysdb_ctx *sysdb_ctx,
+                            struct sss_domain_info *domain,
+                            struct be_sudo_req *sudo_req)
+{
+    TALLOC_CTX *tmp_ctx;
+    char *filter = NULL;
+    char **sudouser = NULL;
+    int ret = EOK;
+    errno_t sret;
+    bool in_transaction = false;
+
+    tmp_ctx = talloc_new(NULL);
+    if (tmp_ctx == NULL) {
+        DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_new() failed\n"));
+        return ENOMEM;
+    }
+
+    ret = sysdb_transaction_start(sysdb_ctx);
+    if (ret != EOK) {
+        goto done;
+    }
+    in_transaction = true;
+
+    switch (sudo_req->type) {
+    case BE_REQ_SUDO_ALL:
+        DEBUG(SSSDBG_TRACE_FUNC, ("Purging SUDOers cache of all rules\n"));
+        ret = sysdb_sudo_purge_all(sysdb_ctx);
+        break;
+    case BE_REQ_SUDO_DEFAULTS:
+        DEBUG(SSSDBG_TRACE_FUNC, ("Purging SUDOers cache of default options\n"));
+        ret = sysdb_sudo_purge_byname(sysdb_ctx, SDAP_SUDO_DEFAULTS);
+        break;
+    case BE_REQ_SUDO_USER:
+        DEBUG(SSSDBG_TRACE_FUNC, ("Purging SUDOers cache of user's [%s] rules\n",
+              sudo_req->username));
+
+        /* netgroups */
+        ret = sysdb_get_sudo_filter(tmp_ctx, NULL, 0, NULL,
+                                    SYSDB_SUDO_FILTER_NGRS, &filter);
+        if (ret != EOK) {
+            DEBUG(SSSDBG_CRIT_FAILURE, ("Unable to create filter to purge "
+                  "SUDOers cache [%d]: %s\n", ret, strerror(ret)));
+            goto done;
+        }
+
+        ret = sysdb_sudo_purge_byfilter(sysdb_ctx, filter);
+        if (ret != EOK) {
+            DEBUG(SSSDBG_CRIT_FAILURE, ("Unable to purge SUDOers cache "
+                  "(netgroups) [%d]: %s\n", ret, strerror(ret)));
+            goto done;
+        }
+
+        /* user, uid, groups */
+        sudouser = sysdb_sudo_build_sudouser(tmp_ctx, sudo_req->username,
+                                             sudo_req->uid, sudo_req->groups,
+                                             true);
+        if (sudouser == NULL) {
+            DEBUG(SSSDBG_CRIT_FAILURE, ("Unable to create sudoUser to purge "
+                  "SUDOers cache [%d]: %s\n", ret, strerror(ret)));
+            goto done;
+        }
+
+        ret = sysdb_sudo_purge_bysudouser(sysdb_ctx, sudouser);
+        break;
+    default:
+        DEBUG(SSSDBG_CRIT_FAILURE, ("Invalid request type %d\n", sudo_req->type));
+        return EINVAL;
+    }
+
+    if (ret != EOK) {
+        DEBUG(SSSDBG_CRIT_FAILURE, ("Unable to purge SUDOers cache [%d]: %s\n",
+                                    ret, strerror(ret)));
+        goto done;
+    }
+
+    ret = sysdb_transaction_commit(sysdb_ctx);
+    if (ret == EOK) {
+        in_transaction = false;
+    }
+
+done:
+    if (in_transaction) {
+        sret = sysdb_transaction_cancel(sysdb_ctx);
+        if (sret != EOK) {
+            DEBUG(SSSDBG_OP_FAILURE, ("Could not cancel transaction\n"));
+        }
+    }
+
+    talloc_free(tmp_ctx);
+    return ret;
+}
+
+int sdap_sudo_store_sudoers(struct sysdb_ctx *sysdb_ctx,
+                            struct sdap_options *opts,
+                            size_t rules_count,
+                            struct sysdb_attrs **rules)
+{
+    errno_t ret;
+
+    /* Empty sudoers? Done. */
+    if (rules_count == 0 || rules == NULL) {
+        return EOK;
+    }
+
+    ret = sdap_save_native_sudorule_list(sysdb_ctx, opts->sudorule_map,
+                                         rules, rules_count);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE, ("failed to save sudo rules [%d]: %s\n",
+              ret, strerror(ret)));
+        return ret;
+    }
+
+    return EOK;
+}
+
+const char *sdap_sudo_build_filter(TALLOC_CTX *mem_ctx,
+                                   struct sdap_attr_map *map,
+                                   struct be_sudo_req *sudo_req)
+{
+    switch (sudo_req->type) {
+    case BE_REQ_SUDO_ALL:
+        return talloc_asprintf(mem_ctx, SDAP_SUDO_FILTER_ALL,
+                               map[SDAP_OC_SUDORULE].name);
+        break;
+    case BE_REQ_SUDO_DEFAULTS:
+        return talloc_asprintf(mem_ctx, SDAP_SUDO_FILTER_DEFAULTS,
+                               map[SDAP_OC_SUDORULE].name,
+                               map[SDAP_AT_SUDO_NAME].name,
+                               SDAP_SUDO_DEFAULTS); /* FIXME: add option for this */
+        break;
+    case BE_REQ_SUDO_USER:
+        return sdap_sudo_build_user_filter(mem_ctx, map, sudo_req->username,
+                                           sudo_req->uid, sudo_req->groups);
+
+        break;
+    default:
+        DEBUG(SSSDBG_CRIT_FAILURE, ("Invalid request type %d\n", sudo_req->type));
+        return NULL;
+    }
+}
+
+/* alway update cn=defaults and sudoUser=ALL */
+const char *sdap_sudo_build_user_filter(TALLOC_CTX *mem_ctx,
+                                        struct sdap_attr_map *map,
+                                        const char *username,
+                                        uid_t uid,
+                                        char **groups)
+{
+    char *filter = NULL;
+    char *output = NULL;
+    char *sanitized = NULL;
+    char **group = NULL;
+    int ret;
+
+    /* user name */
+    ret = sss_filter_sanitize(filter, username, &sanitized);
+    if (ret != EOK) {
+        goto fail;
+    }
+    filter = talloc_asprintf_append(filter, SDAP_SUDO_FILTER_USERNAME,
+                                    map[SDAP_AT_SUDO_USER].name,
+                                    sanitized);
+    if (filter == NULL) {
+        goto fail;
+    }
+
+    /* user uid */
+    filter = talloc_asprintf_append(filter, SDAP_SUDO_FILTER_UID,
+                                    map[SDAP_AT_SUDO_USER].name,
+                                    uid);
+    if (filter == NULL) {
+        goto fail;
+    }
+
+    /* groups */
+    if (groups != NULL) {
+        for (group = groups; *group != NULL; group++) {
+            ret = sss_filter_sanitize(filter, *group, &sanitized);
+            if (ret != EOK) {
+                goto fail;
+            }
+            filter = talloc_asprintf_append(filter, SDAP_SUDO_FILTER_GROUP,
+                                            map[SDAP_AT_SUDO_USER].name,
+                                            sanitized);
+            if (filter == NULL) {
+                goto fail;
+            }
+        }
+    }
+
+    /* netgroups */
+    /*
+     * FIXME: load only netgroups user is member of
+     * FIXME: add option to disable this filter
+     */
+    filter = talloc_asprintf_append(filter, SDAP_SUDO_FILTER_NETGROUP,
+                                    map[SDAP_AT_SUDO_USER].name,
+                                    "*");
+    if (filter == NULL) {
+        goto fail;
+    }
+
+
+    output = talloc_asprintf(mem_ctx, SDAP_SUDO_FILTER_USER,
+                             map[SDAP_OC_SUDORULE].name,
+                             map[SDAP_AT_SUDO_NAME].name,
+                             SDAP_SUDO_DEFAULTS, /* FIXME: add option for this */
+                             map[SDAP_AT_SUDO_USER].name,
+                             filter);
+
+    talloc_free(filter);
+    return output;
+
+fail:
+    talloc_free(filter);
+    return NULL;
+}
diff --git a/src/providers/ldap/sdap_sudo.c b/src/providers/ldap/sdap_sudo.c
index 02d4f17..3bef454 100644
--- a/src/providers/ldap/sdap_sudo.c
+++ b/src/providers/ldap/sdap_sudo.c
@@ -131,72 +131,6 @@ int sdap_sudo_setup_tasks(struct sdap_id_ctx *id_ctx)
     return EOK;
 }
 
-struct sdap_sudo_load_sudoers_state {
-    struct tevent_context *ev;
-    struct sdap_sudo_ctx *sudo_ctx;
-    struct sdap_options *opts;
-    struct sdap_handle *sh;
-    struct sysdb_attrs **ldap_rules; /* search result will be stored here */
-    size_t ldap_rules_count; /* search result will be stored here */
-
-    const char **attrs;
-    const char *filter;
-    size_t base_iter;
-    struct sdap_search_base **search_bases;
-    int timeout;
-};
-
-struct sdap_sudo_refresh_state {
-    struct be_ctx *be_ctx;
-    struct be_sudo_req *sudo_req;
-    struct sdap_options *opts;
-    struct sdap_id_op *sdap_op;
-    struct sdap_id_conn_cache *sdap_conn_cache;
-
-    int dp_error;
-    int error;
-};
-
-static int sdap_sudo_connect(struct tevent_req *req);
-
-static void sdap_sudo_connect_done(struct tevent_req *subreq);
-
-static struct tevent_req * sdap_sudo_load_sudoers_send(TALLOC_CTX *mem_ctx,
-                                                       struct tevent_context *ev,
-                                                       struct be_sudo_req *sudo_req,
-                                                       struct sdap_options *opts,
-                                                       struct sdap_handle *sh);
-
-static errno_t sdap_sudo_load_sudoers_next_base(struct tevent_req *req);
-
-static void sdap_sudo_load_sudoers_process(struct tevent_req *subreq);
-
-static int sdap_sudo_load_sudoers_recv(struct tevent_req *req,
-                                       TALLOC_CTX *mem_ctx,
-                                       size_t *rules_count,
-                                       struct sysdb_attrs ***rules);
-
-static void sdap_sudo_load_sudoers_done(struct tevent_req *req);
-
-static int sdap_sudo_purge_sudoers(struct sysdb_ctx *sysdb_ctx,
-                                   struct sss_domain_info *domain,
-                                   struct be_sudo_req *sudo_req);
-
-static int sdap_sudo_store_sudoers(struct sysdb_ctx *sysdb_ctx,
-                                   struct sdap_options *opts,
-                                   size_t rules_count,
-                                   struct sysdb_attrs **rules);
-
-static const char *sdap_sudo_build_filter(TALLOC_CTX *mem_ctx,
-                                          struct sdap_attr_map *map,
-                                          struct be_sudo_req *sudo_req);
-
-static const char *sdap_sudo_build_user_filter(TALLOC_CTX *mem_ctx,
-                                               struct sdap_attr_map *map,
-                                               const char *username,
-                                               uid_t uid,
-                                               char **groups);
-
 static void sdap_sudo_reply(struct tevent_req *req)
 {
     struct be_req *be_req = NULL;
@@ -256,612 +190,3 @@ void sdap_sudo_handler(struct be_req *be_req)
 fail:
     sdap_handler_done(be_req, DP_ERR_FATAL, ret, NULL);
 }
-
-struct tevent_req *sdap_sudo_refresh_send(TALLOC_CTX *mem_ctx,
-                                          struct be_ctx *be_ctx,
-                                          struct be_sudo_req *sudo_req,
-                                          struct sdap_options *opts,
-                                          struct sdap_id_conn_cache *conn_cache)
-{
-    struct tevent_req *req = NULL;
-    struct sdap_sudo_refresh_state *state = NULL;
-    int ret;
-
-    req = tevent_req_create(mem_ctx, &state, struct sdap_sudo_refresh_state);
-    if (!req) {
-        return NULL;
-    }
-
-    state->be_ctx = be_ctx;
-    state->sudo_req = sudo_req;
-    state->opts = opts;
-    state->sdap_op = NULL;
-    state->sdap_conn_cache = conn_cache;
-    state->dp_error = DP_ERR_OK;
-    state->error = EOK;
-
-    switch (sudo_req->type) {
-    case BE_REQ_SUDO_ALL:
-        DEBUG(SSSDBG_TRACE_FUNC, ("Requested refresh for: <ALL>\n"));
-        break;
-    case BE_REQ_SUDO_DEFAULTS:
-        DEBUG(SSSDBG_TRACE_FUNC, ("Requested refresh of cn=defaults\n"));
-        break;
-    case BE_REQ_SUDO_USER:
-        DEBUG(SSSDBG_TRACE_FUNC, ("Requested refresh for: %s\n",
-                                  sudo_req->username));
-        break;
-    default:
-        DEBUG(SSSDBG_CRIT_FAILURE, ("Invalid request type %d\n", sudo_req->type));
-        ret = EINVAL;
-        goto immediately;
-    }
-
-    ret = sdap_sudo_connect(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, be_ctx->ev);
-
-    return req;
-}
-
-int sdap_sudo_refresh_recv(struct tevent_req *req,
-                           int *dp_error,
-                           int *error)
-{
-    struct sdap_sudo_refresh_state *state = NULL;
-
-    state = tevent_req_data(req, struct sdap_sudo_refresh_state);
-
-    TEVENT_REQ_RETURN_ON_ERROR(req);
-
-    *dp_error = state->dp_error;
-    *error = state->error;
-
-    return EOK;
-}
-
-int sdap_sudo_connect(struct tevent_req *req)
-{
-    struct tevent_req *subreq = NULL;
-    struct sdap_sudo_refresh_state *state = NULL;
-    int ret;
-
-    state = tevent_req_data(req, struct sdap_sudo_refresh_state);
-
-    if (be_is_offline(state->be_ctx)) {
-        state->dp_error = DP_ERR_OFFLINE;
-        state->error = EAGAIN;
-        return EOK;
-    }
-
-    if (state->sdap_op == NULL) {
-        state->sdap_op = sdap_id_op_create(state, state->sdap_conn_cache);
-        if (state->sdap_op == NULL) {
-            DEBUG(SSSDBG_CRIT_FAILURE, ("sdap_id_op_create() failed\n"));
-            state->dp_error = DP_ERR_FATAL;
-            state->error = EIO;
-            return EIO;
-        }
-    }
-
-    subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret);
-    if (subreq == NULL) {
-        DEBUG(SSSDBG_CRIT_FAILURE,
-              ("sdap_id_op_connect_send() failed: %d(%s)\n", ret, strerror(ret)));
-        talloc_zfree(state->sdap_op);
-        state->dp_error = DP_ERR_FATAL;
-        state->error = ret;
-        return ret;
-    }
-
-    tevent_req_set_callback(subreq, sdap_sudo_connect_done, req);
-
-    return EAGAIN;
-}
-
-void sdap_sudo_connect_done(struct tevent_req *subreq)
-{
-    struct tevent_req *req = NULL; /* req from sdap_sudo_refresh_send() */
-    struct sdap_sudo_refresh_state *state = NULL;
-    int dp_error;
-    int ret;
-
-    req = tevent_req_callback_data(subreq, struct tevent_req);
-    state = tevent_req_data(req, struct sdap_sudo_refresh_state);
-
-    ret = sdap_id_op_connect_recv(subreq, &dp_error);
-    talloc_zfree(subreq);
-
-    if (dp_error == DP_ERR_OFFLINE) {
-        talloc_zfree(state->sdap_op);
-        state->dp_error = DP_ERR_OFFLINE;
-        state->error = EAGAIN;
-        tevent_req_done(req);
-        return;
-    } else if (ret != EOK) {
-        DEBUG(SSSDBG_CRIT_FAILURE,
-              ("SUDO LDAP connection failed - %s\n", strerror(ret)));
-        goto fail;
-    }
-
-    DEBUG(SSSDBG_TRACE_FUNC, ("SUDO LDAP connection successful\n"));
-
-    subreq = sdap_sudo_load_sudoers_send(state, state->be_ctx->ev,
-                                         state->sudo_req, state->opts,
-                                         sdap_id_op_handle(state->sdap_op));
-    if (subreq == NULL) {
-        ret = EFAULT;
-        goto fail;
-    }
-
-    tevent_req_set_callback(subreq, sdap_sudo_load_sudoers_done, req);
-
-    return;
-
-fail:
-    state->dp_error = DP_ERR_FATAL;
-    state->error = ret;
-    tevent_req_error(req, ret);
-}
-
-struct tevent_req * sdap_sudo_load_sudoers_send(TALLOC_CTX *mem_ctx,
-                                                struct tevent_context *ev,
-                                                struct be_sudo_req *sudo_req,
-                                                struct sdap_options *opts,
-                                                struct sdap_handle *sh)
-
-
-
-{
-    struct tevent_req *req = NULL;
-    struct sdap_sudo_load_sudoers_state *state = NULL;
-    int ret;
-
-    req = tevent_req_create(mem_ctx, &state, struct sdap_sudo_load_sudoers_state);
-    if (!req) {
-        return NULL;
-    }
-
-    state->ev = ev;
-    state->opts = opts;
-    state->sh = sh;
-    state->base_iter = 0;
-    state->search_bases = opts->sudo_search_bases;
-    state->timeout = dp_opt_get_int(opts->basic, SDAP_SEARCH_TIMEOUT);
-    state->ldap_rules = NULL;
-    state->ldap_rules_count = 0;
-
-    if (!state->search_bases) {
-        DEBUG(SSSDBG_CRIT_FAILURE,
-              ("SUDOERS lookup request without a search base\n"));
-        ret = EINVAL;
-        goto done;
-    }
-
-    /* create filter */
-    state->filter = sdap_sudo_build_filter(state, opts->sudorule_map, sudo_req);
-    if (state->filter == NULL) {
-        goto fail;
-    }
-
-    /* create attrs from map */
-    ret = build_attrs_from_map(state, opts->sudorule_map, SDAP_OPTS_SUDO,
-                               &state->attrs);
-    if (ret != EOK) {
-        goto fail;
-    }
-
-    /* begin search */
-    ret = sdap_sudo_load_sudoers_next_base(req);
-
-done:
-    if (ret != EOK) {
-        tevent_req_error(req, ret);
-        tevent_req_post(req, ev);
-    }
-
-    return req;
-
-fail:
-    talloc_zfree(req);
-    return NULL;
-}
-
-static errno_t sdap_sudo_load_sudoers_next_base(struct tevent_req *req)
-{
-    struct tevent_req *subreq = NULL;
-    struct sdap_sudo_load_sudoers_state *state = NULL;
-    struct sdap_search_base *search_base = NULL;
-    char *filter = NULL;
-
-    state = tevent_req_data(req, struct sdap_sudo_load_sudoers_state);
-    search_base = state->search_bases[state->base_iter];
-    if (search_base == NULL) {
-        /* should not happen */
-        DEBUG(SSSDBG_CRIT_FAILURE, ("search_base is null\n"));
-        return EFAULT;
-    }
-
-    /* create filter */
-    filter = sdap_get_id_specific_filter(state, state->filter,
-                                         search_base->filter);
-    if (filter == NULL) {
-        return ENOMEM;
-    }
-
-    /* send request */
-    DEBUG(SSSDBG_TRACE_FUNC,
-          ("Searching for sudo rules with base [%s]\n",
-           search_base->basedn));
-
-    subreq = sdap_get_generic_send(state,
-                                   state->ev,
-                                   state->opts,
-                                   state->sh,
-                                   search_base->basedn,
-                                   search_base->scope,
-                                   filter,
-                                   state->attrs,
-                                   state->opts->sudorule_map,
-                                   SDAP_OPTS_SUDO,
-                                   state->timeout,
-                                   true);
-    if (subreq == NULL) {
-        return ENOMEM;
-    }
-
-    tevent_req_set_callback(subreq, sdap_sudo_load_sudoers_process, req);
-
-    return EOK;
-}
-
-static void sdap_sudo_load_sudoers_process(struct tevent_req *subreq)
-{
-    struct tevent_req *req = NULL;
-    struct sdap_sudo_load_sudoers_state *state = NULL;
-    struct sdap_search_base *search_base = NULL;
-    struct sysdb_attrs **attrs = NULL;
-    size_t count;
-    int ret;
-    int i;
-
-    req = tevent_req_callback_data(subreq, struct tevent_req);
-    state = tevent_req_data(req, struct sdap_sudo_load_sudoers_state);
-    search_base = state->search_bases[state->base_iter];
-
-    DEBUG(SSSDBG_TRACE_FUNC,
-          ("Receiving sudo rules with base [%s]\n",
-           search_base->basedn));
-
-    ret = sdap_get_generic_recv(subreq, state, &count, &attrs);
-    talloc_zfree(subreq);
-    if (ret) {
-        tevent_req_error(req, ret);
-        return;
-    }
-
-    /* add rules to result */
-    if (count > 0) {
-        state->ldap_rules = talloc_realloc(state, state->ldap_rules,
-                                           struct sysdb_attrs *,
-                                           state->ldap_rules_count + count);
-        if (state->ldap_rules == NULL) {
-            tevent_req_error(req, ENOMEM);
-            return;
-        }
-
-        for (i = 0; i < count; i++) {
-            state->ldap_rules[state->ldap_rules_count + i] = talloc_steal(
-                                                   state->ldap_rules, attrs[i]);
-        }
-
-        state->ldap_rules_count += count;
-    }
-
-    /* go to next base */
-    state->base_iter++;
-    if (state->search_bases[state->base_iter]) {
-        ret = sdap_sudo_load_sudoers_next_base(req);
-        if (ret != EOK) {
-            tevent_req_error(req, ret);
-        }
-
-        return;
-    }
-
-    /* we are done */
-    tevent_req_done(req);
-}
-
-int sdap_sudo_load_sudoers_recv(struct tevent_req *req,
-                                TALLOC_CTX *mem_ctx,
-                                size_t *rules_count,
-                                struct sysdb_attrs ***rules)
-{
-    struct sdap_sudo_load_sudoers_state *state = NULL;
-
-    state = tevent_req_data(req, struct sdap_sudo_load_sudoers_state);
-
-    TEVENT_REQ_RETURN_ON_ERROR(req);
-
-    *rules_count = state->ldap_rules_count;
-    *rules = talloc_steal(mem_ctx, state->ldap_rules);
-
-    return EOK;
-}
-
-void sdap_sudo_load_sudoers_done(struct tevent_req *subreq)
-{
-    struct tevent_req *req = NULL; /* req from sdap_sudo_refresh_send() */
-    struct sdap_sudo_refresh_state *state = NULL;
-    struct sysdb_attrs **rules = NULL;
-    size_t rules_count;
-    int ret;
-
-    req = tevent_req_callback_data(subreq, struct tevent_req);
-    state = tevent_req_data(req, struct sdap_sudo_refresh_state);
-
-    ret = sdap_sudo_load_sudoers_recv(subreq, state, &rules_count, &rules);
-    talloc_zfree(subreq);
-    if (ret != EOK) {
-        goto done;
-    }
-
-    DEBUG(SSSDBG_TRACE_FUNC, ("Received %d rules\n", rules_count));
-
-    /* purge cache */
-    ret = sdap_sudo_purge_sudoers(state->be_ctx->sysdb, state->be_ctx->domain,
-                                  state->sudo_req);
-    if (ret != EOK) {
-        goto done;
-    }
-
-    /* store rules */
-    ret = sdap_sudo_store_sudoers(state->be_ctx->sysdb, state->opts,
-                                  rules_count, rules);
-    if (ret != EOK) {
-        goto done;
-    }
-
-    DEBUG(SSSDBG_TRACE_FUNC, ("Sudoers is successfuly stored in cache\n"));
-
-    ret = EOK;
-
-done:
-    state->error = ret;
-    if (ret == EOK) {
-        state->dp_error = DP_ERR_OK;
-        tevent_req_done(req);
-    } else {
-        state->dp_error = DP_ERR_FATAL;
-        tevent_req_error(req, ret);
-    }
-}
-
-int sdap_sudo_purge_sudoers(struct sysdb_ctx *sysdb_ctx,
-                            struct sss_domain_info *domain,
-                            struct be_sudo_req *sudo_req)
-{
-    TALLOC_CTX *tmp_ctx;
-    char *filter = NULL;
-    char **sudouser = NULL;
-    int ret = EOK;
-    errno_t sret;
-    bool in_transaction = false;
-
-    tmp_ctx = talloc_new(NULL);
-    if (tmp_ctx == NULL) {
-        DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_new() failed\n"));
-        return ENOMEM;
-    }
-
-    ret = sysdb_transaction_start(sysdb_ctx);
-    if (ret != EOK) {
-        goto done;
-    }
-    in_transaction = true;
-
-    switch (sudo_req->type) {
-    case BE_REQ_SUDO_ALL:
-        DEBUG(SSSDBG_TRACE_FUNC, ("Purging SUDOers cache of all rules\n"));
-        ret = sysdb_sudo_purge_all(sysdb_ctx);
-        break;
-    case BE_REQ_SUDO_DEFAULTS:
-        DEBUG(SSSDBG_TRACE_FUNC, ("Purging SUDOers cache of default options\n"));
-        ret = sysdb_sudo_purge_byname(sysdb_ctx, SDAP_SUDO_DEFAULTS);
-        break;
-    case BE_REQ_SUDO_USER:
-        DEBUG(SSSDBG_TRACE_FUNC, ("Purging SUDOers cache of user's [%s] rules\n",
-              sudo_req->username));
-
-        /* netgroups */
-        ret = sysdb_get_sudo_filter(tmp_ctx, NULL, 0, NULL,
-                                    SYSDB_SUDO_FILTER_NGRS, &filter);
-        if (ret != EOK) {
-            DEBUG(SSSDBG_CRIT_FAILURE, ("Unable to create filter to purge "
-                  "SUDOers cache [%d]: %s\n", ret, strerror(ret)));
-            goto done;
-        }
-
-        ret = sysdb_sudo_purge_byfilter(sysdb_ctx, filter);
-        if (ret != EOK) {
-            DEBUG(SSSDBG_CRIT_FAILURE, ("Unable to purge SUDOers cache "
-                  "(netgroups) [%d]: %s\n", ret, strerror(ret)));
-            goto done;
-        }
-
-        /* user, uid, groups */
-        sudouser = sysdb_sudo_build_sudouser(tmp_ctx, sudo_req->username,
-                                             sudo_req->uid, sudo_req->groups,
-                                             true);
-        if (sudouser == NULL) {
-            DEBUG(SSSDBG_CRIT_FAILURE, ("Unable to create sudoUser to purge "
-                  "SUDOers cache [%d]: %s\n", ret, strerror(ret)));
-            goto done;
-        }
-
-        ret = sysdb_sudo_purge_bysudouser(sysdb_ctx, sudouser);
-        break;
-    default:
-        DEBUG(SSSDBG_CRIT_FAILURE, ("Invalid request type %d\n", sudo_req->type));
-        return EINVAL;
-    }
-
-    if (ret != EOK) {
-        DEBUG(SSSDBG_CRIT_FAILURE, ("Unable to purge SUDOers cache [%d]: %s\n",
-                                    ret, strerror(ret)));
-        goto done;
-    }
-
-    ret = sysdb_transaction_commit(sysdb_ctx);
-    if (ret == EOK) {
-        in_transaction = false;
-    }
-
-done:
-    if (in_transaction) {
-        sret = sysdb_transaction_cancel(sysdb_ctx);
-        if (sret != EOK) {
-            DEBUG(SSSDBG_OP_FAILURE, ("Could not cancel transaction\n"));
-        }
-    }
-
-    talloc_free(tmp_ctx);
-    return ret;
-}
-
-int sdap_sudo_store_sudoers(struct sysdb_ctx *sysdb_ctx,
-                            struct sdap_options *opts,
-                            size_t rules_count,
-                            struct sysdb_attrs **rules)
-{
-    errno_t ret;
-
-    /* Empty sudoers? Done. */
-    if (rules_count == 0 || rules == NULL) {
-        return EOK;
-    }
-
-    ret = sdap_save_native_sudorule_list(sysdb_ctx, opts->sudorule_map,
-                                         rules, rules_count);
-    if (ret != EOK) {
-        DEBUG(SSSDBG_OP_FAILURE, ("failed to save sudo rules [%d]: %s\n",
-              ret, strerror(ret)));
-        return ret;
-    }
-
-    return EOK;
-}
-
-const char *sdap_sudo_build_filter(TALLOC_CTX *mem_ctx,
-                                   struct sdap_attr_map *map,
-                                   struct be_sudo_req *sudo_req)
-{
-    switch (sudo_req->type) {
-    case BE_REQ_SUDO_ALL:
-        return talloc_asprintf(mem_ctx, SDAP_SUDO_FILTER_ALL,
-                               map[SDAP_OC_SUDORULE].name);
-        break;
-    case BE_REQ_SUDO_DEFAULTS:
-        return talloc_asprintf(mem_ctx, SDAP_SUDO_FILTER_DEFAULTS,
-                               map[SDAP_OC_SUDORULE].name,
-                               map[SDAP_AT_SUDO_NAME].name,
-                               SDAP_SUDO_DEFAULTS); /* FIXME: add option for this */
-        break;
-    case BE_REQ_SUDO_USER:
-        return sdap_sudo_build_user_filter(mem_ctx, map, sudo_req->username,
-                                           sudo_req->uid, sudo_req->groups);
-
-        break;
-    default:
-        DEBUG(SSSDBG_CRIT_FAILURE, ("Invalid request type %d\n", sudo_req->type));
-        return NULL;
-    }
-}
-
-/* alway update cn=defaults and sudoUser=ALL */
-const char *sdap_sudo_build_user_filter(TALLOC_CTX *mem_ctx,
-                                        struct sdap_attr_map *map,
-                                        const char *username,
-                                        uid_t uid,
-                                        char **groups)
-{
-    char *filter = NULL;
-    char *output = NULL;
-    char *sanitized = NULL;
-    char **group = NULL;
-    int ret;
-
-    /* user name */
-    ret = sss_filter_sanitize(filter, username, &sanitized);
-    if (ret != EOK) {
-        goto fail;
-    }
-    filter = talloc_asprintf_append(filter, SDAP_SUDO_FILTER_USERNAME,
-                                    map[SDAP_AT_SUDO_USER].name,
-                                    sanitized);
-    if (filter == NULL) {
-        goto fail;
-    }
-
-    /* user uid */
-    filter = talloc_asprintf_append(filter, SDAP_SUDO_FILTER_UID,
-                                    map[SDAP_AT_SUDO_USER].name,
-                                    uid);
-    if (filter == NULL) {
-        goto fail;
-    }
-
-    /* groups */
-    if (groups != NULL) {
-        for (group = groups; *group != NULL; group++) {
-            ret = sss_filter_sanitize(filter, *group, &sanitized);
-            if (ret != EOK) {
-                goto fail;
-            }
-            filter = talloc_asprintf_append(filter, SDAP_SUDO_FILTER_GROUP,
-                                            map[SDAP_AT_SUDO_USER].name,
-                                            sanitized);
-            if (filter == NULL) {
-                goto fail;
-            }
-        }
-    }
-
-    /* netgroups */
-    /*
-     * FIXME: load only netgroups user is member of
-     * FIXME: add option to disable this filter
-     */
-    filter = talloc_asprintf_append(filter, SDAP_SUDO_FILTER_NETGROUP,
-                                    map[SDAP_AT_SUDO_USER].name,
-                                    "*");
-    if (filter == NULL) {
-        goto fail;
-    }
-
-
-    output = talloc_asprintf(mem_ctx, SDAP_SUDO_FILTER_USER,
-                             map[SDAP_OC_SUDORULE].name,
-                             map[SDAP_AT_SUDO_NAME].name,
-                             SDAP_SUDO_DEFAULTS, /* FIXME: add option for this */
-                             map[SDAP_AT_SUDO_USER].name,
-                             filter);
-
-    talloc_free(filter);
-    return output;
-
-fail:
-    talloc_free(filter);
-    return NULL;
-}
-- 
1.7.6.5

