From 751a7930d5af7c1a3c36936e3c5b9205189c6b92 Mon Sep 17 00:00:00 2001 From: Pavel Březina Date: Mon, 23 Apr 2012 13:22:25 +0200 Subject: sudo ldap provider: give sdap_sudo_refresh_send() search and purge filters --- src/providers/ldap/sdap_async_sudo.c | 357 +++++++++-------------------------- src/providers/ldap/sdap_sudo.c | 4 +- src/providers/ldap/sdap_sudo.h | 5 +- src/providers/ldap/sdap_sudo_timer.c | 5 +- 4 files changed, 93 insertions(+), 278 deletions(-) (limited to 'src/providers/ldap') diff --git a/src/providers/ldap/sdap_async_sudo.c b/src/providers/ldap/sdap_async_sudo.c index d24420a2..5051110d 100644 --- a/src/providers/ldap/sdap_async_sudo.c +++ b/src/providers/ldap/sdap_async_sudo.c @@ -34,13 +34,25 @@ #include "providers/ldap/sdap_sudo_cache.h" #include "db/sysdb_sudo.h" +struct sdap_sudo_refresh_state { + struct be_ctx *be_ctx; + struct sdap_options *opts; + struct sdap_id_op *sdap_op; + struct sdap_id_conn_cache *sdap_conn_cache; + + const char *ldap_filter; /* search */ + const char *sysdb_filter; /* delete */ + + int dp_error; + int error; +}; + 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 */ + size_t ldap_rules_count; /* search result will be stored here */ const char **attrs; const char *filter; @@ -49,26 +61,15 @@ struct sdap_sudo_load_sudoers_state { 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; +static int sdap_sudo_refresh_retry(struct tevent_req *req); - 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 void sdap_sudo_refresh_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); + struct sdap_handle *sh, + const char *ldap_filter); static errno_t sdap_sudo_load_sudoers_next_base(struct tevent_req *req); @@ -79,32 +80,19 @@ static int sdap_sudo_load_sudoers_recv(struct tevent_req *req, 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 void sdap_sudo_load_sudoers_done(struct tevent_req *subreq); 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 sdap_id_conn_cache *conn_cache, + const char *ldap_filter, + const char *sysdb_filter) { struct tevent_req *req = NULL; struct sdap_sudo_refresh_state *state = NULL; @@ -115,32 +103,32 @@ struct tevent_req *sdap_sudo_refresh_send(TALLOC_CTX *mem_ctx, return NULL; } + /* if we don't have a search filter, this request is meaningless */ + if (ldap_filter == NULL) { + ret = EINVAL; + goto immediately; + } + state->be_ctx = be_ctx; - state->sudo_req = sudo_req; state->opts = opts; state->sdap_op = NULL; state->sdap_conn_cache = conn_cache; + state->ldap_filter = talloc_strdup(state, ldap_filter); + state->sysdb_filter = talloc_strdup(state, sysdb_filter); 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: \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; + if (state->ldap_filter == NULL) { + ret = ENOMEM; + goto immediately; + } + + if (sysdb_filter != NULL && state->sysdb_filter == NULL) { + ret = ENOMEM; goto immediately; } - ret = sdap_sudo_connect(req); + ret = sdap_sudo_refresh_retry(req); if (ret == EAGAIN) { /* asynchronous processing */ return req; @@ -173,7 +161,7 @@ int sdap_sudo_refresh_recv(struct tevent_req *req, return EOK; } -int sdap_sudo_connect(struct tevent_req *req) +static int sdap_sudo_refresh_retry(struct tevent_req *req) { struct tevent_req *subreq = NULL; struct sdap_sudo_refresh_state *state = NULL; @@ -207,12 +195,12 @@ int sdap_sudo_connect(struct tevent_req *req) return ret; } - tevent_req_set_callback(subreq, sdap_sudo_connect_done, req); + tevent_req_set_callback(subreq, sdap_sudo_refresh_connect_done, req); return EAGAIN; } -void sdap_sudo_connect_done(struct tevent_req *subreq) +static void sdap_sudo_refresh_connect_done(struct tevent_req *subreq) { struct tevent_req *req = NULL; /* req from sdap_sudo_refresh_send() */ struct sdap_sudo_refresh_state *state = NULL; @@ -240,8 +228,9 @@ void sdap_sudo_connect_done(struct tevent_req *subreq) 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)); + state->opts, + sdap_id_op_handle(state->sdap_op), + state->ldap_filter); if (subreq == NULL) { ret = EFAULT; goto fail; @@ -257,11 +246,11 @@ fail: 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) +static struct tevent_req * sdap_sudo_load_sudoers_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sdap_options *opts, + struct sdap_handle *sh, + const char *ldap_filter) @@ -280,6 +269,7 @@ struct tevent_req * sdap_sudo_load_sudoers_send(TALLOC_CTX *mem_ctx, state->sh = sh; state->base_iter = 0; state->search_bases = opts->sudo_search_bases; + state->filter = ldap_filter; state->timeout = dp_opt_get_int(opts->basic, SDAP_SEARCH_TIMEOUT); state->ldap_rules = NULL; state->ldap_rules_count = 0; @@ -291,12 +281,6 @@ struct tevent_req * sdap_sudo_load_sudoers_send(TALLOC_CTX *mem_ctx, 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, NULL, &state->attrs, NULL); @@ -426,10 +410,10 @@ static void sdap_sudo_load_sudoers_process(struct tevent_req *subreq) 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) +static 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; @@ -443,13 +427,15 @@ int sdap_sudo_load_sudoers_recv(struct tevent_req *req, return EOK; } -void sdap_sudo_load_sudoers_done(struct tevent_req *subreq) +static 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; + errno_t sret; + bool in_transaction = false; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sdap_sudo_refresh_state); @@ -462,131 +448,61 @@ void sdap_sudo_load_sudoers_done(struct tevent_req *subreq) 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); + /* start transaction */ + ret = sysdb_transaction_start(state->be_ctx->sysdb); 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); + /* purge cache */ + if (state->sysdb_filter != NULL) { + ret = sysdb_sudo_purge_byfilter(state->be_ctx->sysdb, + state->sysdb_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; } + /* store rules */ + ret = sdap_sudo_store_sudoers(state->be_ctx->sysdb, state->opts, + rules_count, rules); 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); + /* commit transaction */ + ret = sysdb_transaction_commit(state->be_ctx->sysdb); if (ret == EOK) { in_transaction = false; } + DEBUG(SSSDBG_TRACE_FUNC, ("Sudoers is successfuly stored in cache\n")); + + ret = EOK; + done: if (in_transaction) { - sret = sysdb_transaction_cancel(sysdb_ctx); + sret = sysdb_transaction_cancel(state->be_ctx->sysdb); if (sret != EOK) { DEBUG(SSSDBG_OP_FAILURE, ("Could not cancel transaction\n")); } } - talloc_free(tmp_ctx); - return ret; + 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_store_sudoers(struct sysdb_ctx *sysdb_ctx, - struct sdap_options *opts, - size_t rules_count, - struct sysdb_attrs **rules) +static 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; @@ -605,106 +521,3 @@ int sdap_sudo_store_sudoers(struct sysdb_ctx *sysdb_ctx, 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 3bef454a..c7e76729 100644 --- a/src/providers/ldap/sdap_sudo.c +++ b/src/providers/ldap/sdap_sudo.c @@ -176,8 +176,8 @@ void sdap_sudo_handler(struct be_req *be_req) sudo_req->groups = NULL; } - req = sdap_sudo_refresh_send(be_req, id_ctx->be, sudo_req, id_ctx->opts, - id_ctx->conn_cache); + req = sdap_sudo_refresh_send(be_req, id_ctx->be, id_ctx->opts, + id_ctx->conn_cache, NULL, NULL); if (req == NULL) { ret = ENOMEM; goto fail; diff --git a/src/providers/ldap/sdap_sudo.h b/src/providers/ldap/sdap_sudo.h index dd42f368..6d395496 100644 --- a/src/providers/ldap/sdap_sudo.h +++ b/src/providers/ldap/sdap_sudo.h @@ -31,9 +31,10 @@ int sdap_sudo_init(struct be_ctx *be_ctx, /* sdap async interface */ 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 sdap_id_conn_cache *conn_cache, + const char *ldap_filter, + const char *sysdb_filter); int sdap_sudo_refresh_recv(struct tevent_req *req, int *dp_error, diff --git a/src/providers/ldap/sdap_sudo_timer.c b/src/providers/ldap/sdap_sudo_timer.c index 9996aae8..56386f42 100644 --- a/src/providers/ldap/sdap_sudo_timer.c +++ b/src/providers/ldap/sdap_sudo_timer.c @@ -129,9 +129,10 @@ static void sdap_sudo_refresh_timer(struct tevent_context *ev, sudo_req->username = NULL; /* send request */ - req = sdap_sudo_refresh_send(refresh_ctx, refresh_ctx->id_ctx->be, sudo_req, + req = sdap_sudo_refresh_send(refresh_ctx, refresh_ctx->id_ctx->be, refresh_ctx->id_ctx->opts, - refresh_ctx->id_ctx->conn_cache); + refresh_ctx->id_ctx->conn_cache, + NULL, NULL); if (req == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to schedule refresh of SUDO rules, " "retrying later!\n")); -- cgit