From fcb6f55c09d1d6f6487d771ac829e02565393c56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20B=C5=99ezina?= Date: Thu, 15 Aug 2019 12:42:05 +0200 Subject: [PATCH 85/90] ldap: implement autofs get map MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This will obtain only the map object. Resolves: https://pagure.io/SSSD/sssd/issue/2607 Reviewed-by: Tomáš Halman --- src/providers/ipa/ipa_autofs.c | 4 + src/providers/ldap/ldap_common.h | 11 + src/providers/ldap/sdap_async_autofs.c | 207 ++++++++++++++++++ src/providers/ldap/sdap_autofs.c | 123 +++++++++-- src/providers/ldap/sdap_autofs.h | 7 + .../plugins/cache_req_autofs_map_by_name.c | 2 +- 6 files changed, 340 insertions(+), 14 deletions(-) diff --git a/src/providers/ipa/ipa_autofs.c b/src/providers/ipa/ipa_autofs.c index 50e30f39f..19d74071f 100644 --- a/src/providers/ipa/ipa_autofs.c +++ b/src/providers/ipa/ipa_autofs.c @@ -51,5 +51,9 @@ errno_t ipa_autofs_init(TALLOC_CTX *mem_ctx, sdap_autofs_enumerate_handler_send, sdap_autofs_enumerate_handler_recv, id_ctx, struct sdap_id_ctx, struct dp_autofs_data, struct dp_reply_std); + dp_set_method(dp_methods, DPM_AUTOFS_GET_MAP, + sdap_autofs_get_map_handler_send, sdap_autofs_get_map_handler_recv, id_ctx, + struct sdap_id_ctx, struct dp_autofs_data, struct dp_reply_std); + return ret; } diff --git a/src/providers/ldap/ldap_common.h b/src/providers/ldap/ldap_common.h index 85dc6949c..36623aca8 100644 --- a/src/providers/ldap/ldap_common.h +++ b/src/providers/ldap/ldap_common.h @@ -166,6 +166,17 @@ sdap_autofs_enumerate_handler_recv(TALLOC_CTX *mem_ctx, struct tevent_req *req, struct dp_reply_std *data); +struct tevent_req * +sdap_autofs_get_map_handler_send(TALLOC_CTX *mem_ctx, + struct sdap_id_ctx *id_ctx, + struct dp_autofs_data *data, + struct dp_req_params *params); + +errno_t +sdap_autofs_get_map_handler_recv(TALLOC_CTX *mem_ctx, + struct tevent_req *req, + struct dp_reply_std *data); + int sdap_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx, const char *service_name, const char *dns_service_name, const char *urls, const char *backup_urls, diff --git a/src/providers/ldap/sdap_async_autofs.c b/src/providers/ldap/sdap_async_autofs.c index 7548d4a67..52ceb84ac 100644 --- a/src/providers/ldap/sdap_async_autofs.c +++ b/src/providers/ldap/sdap_async_autofs.c @@ -28,6 +28,7 @@ #include "db/sysdb_autofs.h" #include "providers/ldap/ldap_common.h" #include "providers/ldap/sdap_autofs.h" +#include "providers/ldap/sdap_ops.h" enum autofs_map_op { AUTOFS_MAP_OP_ADD, @@ -970,3 +971,209 @@ sdap_autofs_setautomntent_recv(struct tevent_req *req) return EOK; } +struct sdap_autofs_get_map_state { + struct sdap_id_ctx *id_ctx; + struct sdap_options *opts; + struct sdap_id_op *sdap_op; + const char *mapname; + int dp_error; +}; + +static errno_t sdap_autofs_get_map_retry(struct tevent_req *req); +static void sdap_autofs_get_map_connect_done(struct tevent_req *subreq); +static void sdap_autofs_get_map_done(struct tevent_req *subreq); + +struct tevent_req *sdap_autofs_get_map_send(TALLOC_CTX *mem_ctx, + struct sdap_id_ctx *id_ctx, + const char *mapname) +{ + struct tevent_req *req; + struct sdap_autofs_get_map_state *state; + int ret; + + req = tevent_req_create(mem_ctx, &state, struct sdap_autofs_get_map_state); + if (!req) { + return NULL; + } + + state->id_ctx = id_ctx; + state->opts = id_ctx->opts; + state->mapname = mapname; + state->dp_error = DP_ERR_FATAL; + + state->sdap_op = sdap_id_op_create(state, id_ctx->conn->conn_cache); + if (!state->sdap_op) { + DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create() failed\n"); + ret = ENOMEM; + goto done; + } + + ret = sdap_autofs_get_map_retry(req); + if (ret == EAGAIN) { + /* asynchronous processing */ + return req; + } + +done: + if (ret == EOK) { + tevent_req_done(req); + } else { + tevent_req_error(req, ret); + } + tevent_req_post(req, id_ctx->be->ev); + + return req; +} + +static errno_t sdap_autofs_get_map_retry(struct tevent_req *req) +{ + struct sdap_autofs_get_map_state *state; + struct tevent_req *subreq; + int ret; + + state = tevent_req_data(req, struct sdap_autofs_get_map_state); + + 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)); + return ret; + } + + tevent_req_set_callback(subreq, sdap_autofs_get_map_connect_done, req); + + return EAGAIN; +} + +static void sdap_autofs_get_map_connect_done(struct tevent_req *subreq) +{ + struct tevent_req *req; + struct sdap_autofs_get_map_state *state; + char *filter; + char *safe_mapname; + const char **attrs; + int dp_error; + int ret; + + req = tevent_req_callback_data(subreq, struct tevent_req); + state = tevent_req_data(req, struct sdap_autofs_get_map_state); + + ret = sdap_id_op_connect_recv(subreq, &dp_error); + talloc_zfree(subreq); + + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "LDAP connection failed " + "[%d]: %s\n", ret, strerror(ret)); + state->dp_error = dp_error; + tevent_req_error(req, ret); + return; + } + + DEBUG(SSSDBG_TRACE_FUNC, "LDAP connection successful\n"); + + ret = sss_filter_sanitize(state, state->mapname, &safe_mapname); + if (ret != EOK) { + tevent_req_error(req, ret); + return; + } + + filter = talloc_asprintf(state, "(&(%s=%s)(objectclass=%s))", + state->opts->autofs_mobject_map[SDAP_AT_AUTOFS_MAP_NAME].name, + safe_mapname, + state->opts->autofs_mobject_map[SDAP_OC_AUTOFS_MAP].name); + if (filter == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Failed to build filter\n"); + tevent_req_error(req, ret); + return; + } + + ret = build_attrs_from_map(state, state->opts->autofs_mobject_map, + SDAP_OPTS_AUTOFS_MAP, NULL, &attrs, NULL); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Failed to build attributes from map\n"); + tevent_req_error(req, ret); + return; + } + + subreq = sdap_search_bases_return_first_send(state, state->id_ctx->be->ev, + state->opts, sdap_id_op_handle(state->sdap_op), + state->opts->sdom->autofs_search_bases, + state->opts->autofs_mobject_map, false, + dp_opt_get_int(state->opts->basic, SDAP_SEARCH_TIMEOUT), + filter, attrs); + if (subreq == NULL) { + state->dp_error = DP_ERR_FATAL; + tevent_req_error(req, ENOMEM); + return; + } + + tevent_req_set_callback(subreq, sdap_autofs_get_map_done, req); +} + +static void sdap_autofs_get_map_done(struct tevent_req *subreq) +{ + struct tevent_req *req; + struct sdap_autofs_get_map_state *state; + struct sysdb_attrs **reply; + size_t reply_count; + errno_t ret; + + req = tevent_req_callback_data(subreq, struct tevent_req); + state = tevent_req_data(req, struct sdap_autofs_get_map_state); + + ret = sdap_search_bases_return_first_recv(subreq, state, &reply_count, + &reply); + talloc_zfree(subreq); + + ret = sdap_id_op_done(state->sdap_op, ret, &state->dp_error); + if (state->dp_error == DP_ERR_OK && ret != EOK) { + /* retry */ + ret = sdap_autofs_get_map_retry(req); + if (ret != EOK) { + tevent_req_error(req, ret); + } + return; + } else if (ret != EOK) { + tevent_req_error(req, ret); + return; + } + + if (reply_count == 0) { + ret = sysdb_delete_autofsmap(state->id_ctx->be->domain, state->mapname); + if (ret != EOK && ret != ENOENT) { + DEBUG(SSSDBG_OP_FAILURE, + "Cannot delete autofs map %s [%d]: %s\n", + state->mapname, ret, strerror(ret)); + tevent_req_error(req, ret); + return; + } + + tevent_req_done(req); + return; + } + + ret = save_autofs_map(state->id_ctx->be->domain, state->opts, reply[0], false); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "Cannot save autofs map %s [%d]: %s\n", + state->mapname, ret, strerror(ret)); + tevent_req_error(req, ret); + return; + } + + tevent_req_done(req); +} + +errno_t sdap_autofs_get_map_recv(struct tevent_req *req, + int *dp_error) +{ + struct sdap_autofs_get_map_state *state; + + state = tevent_req_data(req, struct sdap_autofs_get_map_state); + + TEVENT_REQ_RETURN_ON_ERROR(req); + + *dp_error = state->dp_error; + + return EOK; +} diff --git a/src/providers/ldap/sdap_autofs.c b/src/providers/ldap/sdap_autofs.c index 5b9146199..9a5ed11e8 100644 --- a/src/providers/ldap/sdap_autofs.c +++ b/src/providers/ldap/sdap_autofs.c @@ -34,6 +34,27 @@ #include "db/sysdb_autofs.h" #include "util/util.h" +static void +sdap_autofs_invalidate_maps(struct sdap_id_ctx *id_ctx, + const char *mapname) +{ + const char *master_map; + errno_t ret; + + master_map = dp_opt_get_string(id_ctx->opts->basic, + SDAP_AUTOFS_MAP_MASTER_NAME); + if (strcmp(master_map, mapname) == 0) { + DEBUG(SSSDBG_FUNC_DATA, "Refresh of automount master map triggered: " + "%s\n", mapname); + + ret = sysdb_invalidate_autofs_maps(id_ctx->be->domain); + if (ret != EOK) { + DEBUG(SSSDBG_MINOR_FAILURE, "Could not invalidate autofs maps, " + "backend might return stale entries\n"); + } + } +} + struct sdap_autofs_enumerate_state { struct tevent_context *ev; struct sdap_id_ctx *ctx; @@ -216,7 +237,6 @@ sdap_autofs_enumerate_handler_send(TALLOC_CTX *mem_ctx, struct sdap_autofs_enumerate_handler_state *state; struct tevent_req *subreq; struct tevent_req *req; - const char *master_map; errno_t ret; req = tevent_req_create(mem_ctx, &state, struct sdap_autofs_enumerate_handler_state); @@ -227,18 +247,7 @@ sdap_autofs_enumerate_handler_send(TALLOC_CTX *mem_ctx, DEBUG(SSSDBG_FUNC_DATA, "Requested refresh for: %s\n", data->mapname); - master_map = dp_opt_get_string(id_ctx->opts->basic, - SDAP_AUTOFS_MAP_MASTER_NAME); - if (strcmp(master_map, data->mapname) == 0) { - DEBUG(SSSDBG_FUNC_DATA, "Refresh of automount master map triggered: " - "%s\n", data->mapname); - - ret = sysdb_invalidate_autofs_maps(id_ctx->be->domain); - if (ret != EOK) { - DEBUG(SSSDBG_MINOR_FAILURE, "Could not invalidate autofs maps, " - "backend might return stale entries\n"); - } - } + sdap_autofs_invalidate_maps(id_ctx, data->mapname); subreq = sdap_autofs_enumerate_send(mem_ctx, params->ev, id_ctx, data->mapname); @@ -298,6 +307,90 @@ sdap_autofs_enumerate_handler_recv(TALLOC_CTX *mem_ctx, return EOK; } +struct sdap_autofs_get_map_handler_state { + struct dp_reply_std reply; +}; + +static void sdap_autofs_get_map_handler_done(struct tevent_req *subreq); + +struct tevent_req * +sdap_autofs_get_map_handler_send(TALLOC_CTX *mem_ctx, + struct sdap_id_ctx *id_ctx, + struct dp_autofs_data *data, + struct dp_req_params *params) +{ + struct sdap_autofs_get_map_handler_state *state; + struct tevent_req *subreq; + struct tevent_req *req; + errno_t ret; + + req = tevent_req_create(mem_ctx, &state, + struct sdap_autofs_get_map_handler_state); + if (req == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n"); + return NULL; + } + + DEBUG(SSSDBG_FUNC_DATA, "Requested refresh for: %s\n", data->mapname); + + sdap_autofs_invalidate_maps(id_ctx, data->mapname); + + subreq = sdap_autofs_get_map_send(mem_ctx, id_ctx, data->mapname); + if (subreq == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to send request for %s.\n", + data->mapname); + ret = ENOMEM; + goto immediately; + } + + tevent_req_set_callback(subreq, sdap_autofs_get_map_handler_done, req); + + return req; + +immediately: + dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL); + + /* TODO For backward compatibility we always return EOK to DP now. */ + tevent_req_done(req); + tevent_req_post(req, params->ev); + + return req; +} + +static void sdap_autofs_get_map_handler_done(struct tevent_req *subreq) +{ + struct sdap_autofs_get_map_handler_state *state; + struct tevent_req *req; + int dp_error; + errno_t ret; + + req = tevent_req_callback_data(subreq, struct tevent_req); + state = tevent_req_data(req, struct sdap_autofs_get_map_handler_state); + + ret = sdap_autofs_get_map_recv(subreq, &dp_error); + talloc_zfree(subreq); + + /* TODO For backward compatibility we always return EOK to DP now. */ + dp_reply_std_set(&state->reply, dp_error, ret, NULL); + tevent_req_done(req); +} + +errno_t +sdap_autofs_get_map_handler_recv(TALLOC_CTX *mem_ctx, + struct tevent_req *req, + struct dp_reply_std *data) +{ + struct sdap_autofs_get_map_handler_state *state = NULL; + + state = tevent_req_data(req, struct sdap_autofs_get_map_handler_state); + + TEVENT_REQ_RETURN_ON_ERROR(req); + + *data = state->reply; + + return EOK; +} + errno_t sdap_autofs_init(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, struct sdap_id_ctx *id_ctx, @@ -317,5 +410,9 @@ errno_t sdap_autofs_init(TALLOC_CTX *mem_ctx, sdap_autofs_enumerate_handler_send, sdap_autofs_enumerate_handler_recv, id_ctx, struct sdap_id_ctx, struct dp_autofs_data, struct dp_reply_std); + dp_set_method(dp_methods, DPM_AUTOFS_GET_MAP, + sdap_autofs_get_map_handler_send, sdap_autofs_get_map_handler_recv, id_ctx, + struct sdap_id_ctx, struct dp_autofs_data, struct dp_reply_std); + return EOK; } diff --git a/src/providers/ldap/sdap_autofs.h b/src/providers/ldap/sdap_autofs.h index 593d8c94f..34b9ca953 100644 --- a/src/providers/ldap/sdap_autofs.h +++ b/src/providers/ldap/sdap_autofs.h @@ -43,5 +43,12 @@ sdap_autofs_setautomntent_send(TALLOC_CTX *memctx, errno_t sdap_autofs_setautomntent_recv(struct tevent_req *req); +struct tevent_req *sdap_autofs_get_map_send(TALLOC_CTX *mem_ctx, + struct sdap_id_ctx *id_ctx, + const char *mapname); + +errno_t sdap_autofs_get_map_recv(struct tevent_req *req, + int *dp_error); + #endif /* _SDAP_AUTOFS_H_ */ diff --git a/src/responder/common/cache_req/plugins/cache_req_autofs_map_by_name.c b/src/responder/common/cache_req/plugins/cache_req_autofs_map_by_name.c index 268711678..4c1685728 100644 --- a/src/responder/common/cache_req/plugins/cache_req_autofs_map_by_name.c +++ b/src/responder/common/cache_req/plugins/cache_req_autofs_map_by_name.c @@ -69,7 +69,7 @@ cache_req_autofs_map_by_name_dp_send(TALLOC_CTX *mem_ctx, struct ldb_result *result) { return sss_dp_get_autofs_send(mem_ctx, cr->rctx, domain, true, - SSS_DP_AUTOFS_ENUMERATE, + SSS_DP_AUTOFS_GET_MAP, data->name.name, NULL); } -- 2.20.1