diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/providers/ldap/sdap_sudo.c | 173 | ||||
-rw-r--r-- | src/providers/ldap/sdap_sudo.h | 8 |
2 files changed, 138 insertions, 43 deletions
diff --git a/src/providers/ldap/sdap_sudo.c b/src/providers/ldap/sdap_sudo.c index 387cf0c1..ea90bb7e 100644 --- a/src/providers/ldap/sdap_sudo.c +++ b/src/providers/ldap/sdap_sudo.c @@ -45,8 +45,14 @@ struct sdap_sudo_load_sudoers_state { int timeout; }; -static int sdap_sudo_connect(struct sdap_sudo_ctx *sudo_ctx); -static void sdap_sudo_connect_done(struct tevent_req *req); +struct sdap_sudo_refresh_state { + struct sdap_sudo_ctx *sudo_ctx; + 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 sdap_sudo_ctx *sudo_ctx); @@ -69,30 +75,29 @@ const char *sdap_sudo_build_filter(TALLOC_CTX *mem_ctx, uid_t uid, char **groups); -static void sdap_sudo_reply(struct sdap_sudo_ctx *sudo_ctx, int errcode) +static void sdap_sudo_reply(struct tevent_req *req) { - struct be_req *be_req = sudo_ctx->be_req; + struct be_req *be_req = NULL; + struct sdap_sudo_ctx *sudo_ctx = NULL; + int dp_error; + int error; + int ret; + be_req = tevent_req_callback_data(req, struct be_req); + ret = sdap_sudo_refresh_recv(req, &sudo_ctx, &dp_error, &error); + talloc_zfree(req); talloc_zfree(sudo_ctx); - - if (errcode == EOK) { - sdap_handler_done(be_req, DP_ERR_OK, errcode, strerror(errcode)); - } else { - sdap_handler_done(be_req, DP_ERR_FATAL, errcode, strerror(errcode)); + if (ret != EOK) { + sdap_handler_done(be_req, DP_ERR_FATAL, ret, strerror(ret)); + return; } -} -static void sdap_sudo_reply_offline(struct sdap_sudo_ctx *sudo_ctx) -{ - struct be_req *be_req = sudo_ctx->be_req; - - talloc_zfree(sudo_ctx); - - sdap_handler_done(be_req, DP_ERR_OFFLINE, EAGAIN, "Provider is offline"); + sdap_handler_done(be_req, dp_error, error, strerror(error)); } void sdap_sudo_handler(struct be_req *be_req) { + struct tevent_req *req = NULL; struct sdap_sudo_ctx *sudo_ctx = NULL; struct be_sudo_req *sudo_req = NULL; struct sdap_id_ctx *id_ctx = NULL; @@ -131,28 +136,87 @@ void sdap_sudo_handler(struct be_req *be_req) sudo_ctx->groups = NULL; } - DEBUG(SSSDBG_FUNC_DATA, ("Requested refresh for: %s\n", - sudo_req->username ? sudo_req->username : "<ALL>\n")); - - ret = sdap_sudo_connect(sudo_ctx); - if (ret != EOK) { + req = sdap_sudo_refresh_send(sudo_ctx, sudo_ctx); + if (req == NULL) { + ret = ENOMEM; goto fail; } + tevent_req_set_callback(req, sdap_sudo_reply, be_req); + return; fail: talloc_free(sudo_ctx); - be_req->fn(be_req, DP_ERR_FATAL, ret, NULL); + sdap_handler_done(be_req, DP_ERR_FATAL, ret, NULL); } -int sdap_sudo_connect(struct sdap_sudo_ctx *sudo_ctx) +struct tevent_req *sdap_sudo_refresh_send(TALLOC_CTX *mem_ctx, + struct sdap_sudo_ctx *sudo_ctx) { 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->sudo_ctx = sudo_ctx; + state->dp_error = DP_ERR_OK; + state->error = EOK; + + DEBUG(SSSDBG_FUNC_DATA, ("Requested refresh for: %s\n", + sudo_ctx->username ? sudo_ctx->username : "<ALL>\n")); + + ret = sdap_sudo_connect(req); + if (ret == EAGAIN) { + /* asynchronous processing */ + return req; + } + + if (ret == EOK) { + tevent_req_done(req); + } else { + tevent_req_error(req, ret); + } + tevent_req_post(req, sudo_ctx->be_ctx->ev); + + return req; +} + +int sdap_sudo_refresh_recv(struct tevent_req *req, + struct sdap_sudo_ctx **sudo_ctx, + 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); + + *sudo_ctx = state->sudo_ctx; + *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; + struct sdap_sudo_ctx *sudo_ctx = NULL; int ret; + state = tevent_req_data(req, struct sdap_sudo_refresh_state); + sudo_ctx = state->sudo_ctx; + if (be_is_offline(sudo_ctx->be_ctx)) { - sdap_sudo_reply_offline(sudo_ctx); + state->dp_error = DP_ERR_OFFLINE; + state->error = EAGAIN; return EOK; } @@ -161,37 +225,47 @@ int sdap_sudo_connect(struct sdap_sudo_ctx *sudo_ctx) sudo_ctx->sdap_conn_cache); if (sudo_ctx->sdap_op == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, ("sdap_id_op_create() failed\n")); + state->dp_error = DP_ERR_FATAL; + state->error = EIO; return EIO; } } - req = sdap_id_op_connect_send(sudo_ctx->sdap_op, sudo_ctx, &ret); - if (req == NULL) { + subreq = sdap_id_op_connect_send(sudo_ctx->sdap_op, sudo_ctx, &ret); + if (subreq == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, ("sdap_id_op_connect_send() failed: %d(%s)\n", ret, strerror(ret))); talloc_zfree(sudo_ctx->sdap_op); + state->dp_error = DP_ERR_FATAL; + state->error = ret; return ret; } - tevent_req_set_callback(req, sdap_sudo_connect_done, sudo_ctx); + tevent_req_set_callback(subreq, sdap_sudo_connect_done, req); - return EOK; + return EAGAIN; } -void sdap_sudo_connect_done(struct tevent_req *req) +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; struct sdap_sudo_ctx *sudo_ctx = NULL; int dp_error; int ret; - sudo_ctx = tevent_req_callback_data(req, struct sdap_sudo_ctx); + req = tevent_req_callback_data(subreq, struct tevent_req); + state = tevent_req_data(req, struct sdap_sudo_refresh_state); + sudo_ctx = state->sudo_ctx; - ret = sdap_id_op_connect_recv(req, &dp_error); - talloc_zfree(req); + ret = sdap_id_op_connect_recv(subreq, &dp_error); + talloc_zfree(subreq); if (dp_error == DP_ERR_OFFLINE) { talloc_zfree(sudo_ctx->sdap_op); - sdap_sudo_reply_offline(sudo_ctx); + state->dp_error = DP_ERR_OFFLINE; + state->error = EAGAIN; + tevent_req_done(req); return; } else if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, @@ -201,18 +275,20 @@ void sdap_sudo_connect_done(struct tevent_req *req) DEBUG(SSSDBG_TRACE_FUNC, ("SUDO LDAP connection successful\n")); - req = sdap_sudo_load_sudoers_send(sudo_ctx, sudo_ctx); - if (req == NULL) { + subreq = sdap_sudo_load_sudoers_send(sudo_ctx, sudo_ctx); + if (subreq == NULL) { ret = EFAULT; goto fail; } - tevent_req_set_callback(req, sdap_sudo_load_sudoers_done, sudo_ctx); + tevent_req_set_callback(subreq, sdap_sudo_load_sudoers_done, req); return; fail: - sdap_sudo_reply(sudo_ctx, ret); + 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, @@ -390,17 +466,21 @@ int sdap_sudo_load_sudoers_recv(struct tevent_req *req, return EOK; } -void sdap_sudo_load_sudoers_done(struct tevent_req *req) +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 sdap_sudo_ctx *sudo_ctx = NULL; struct sysdb_attrs **rules = NULL; size_t rules_count; int ret; - sudo_ctx = tevent_req_callback_data(req, struct sdap_sudo_ctx); + req = tevent_req_callback_data(subreq, struct tevent_req); + state = tevent_req_data(req, struct sdap_sudo_refresh_state); + sudo_ctx = state->sudo_ctx; - ret = sdap_sudo_load_sudoers_recv(req, sudo_ctx, &rules_count, &rules); - talloc_zfree(req); + ret = sdap_sudo_load_sudoers_recv(subreq, sudo_ctx, &rules_count, &rules); + talloc_zfree(subreq); if (ret != EOK) { goto done; } @@ -424,7 +504,14 @@ void sdap_sudo_load_sudoers_done(struct tevent_req *req) ret = EOK; done: - sdap_sudo_reply(sudo_ctx, 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_purge_sudoers(struct sdap_sudo_ctx *sudo_ctx) diff --git a/src/providers/ldap/sdap_sudo.h b/src/providers/ldap/sdap_sudo.h index bfea6bff..1e53c117 100644 --- a/src/providers/ldap/sdap_sudo.h +++ b/src/providers/ldap/sdap_sudo.h @@ -33,6 +33,14 @@ struct sdap_sudo_ctx { char **groups; }; +struct tevent_req *sdap_sudo_refresh_send(TALLOC_CTX *mem_ctx, + struct sdap_sudo_ctx *sudo_ctx); + +int sdap_sudo_refresh_recv(struct tevent_req *req, + struct sdap_sudo_ctx **sudo_ctx, + int *dp_error, + int *error); + /* (&(objectClass=sudoRole)(|(cn=defaults)(sudoUser=ALL)%s)) */ #define SDAP_SUDO_FILTER_USER "(&(objectClass=%s)(|(%s=%s)(%s=ALL)%s))" #define SDAP_SUDO_FILTER_ALL "(objectClass=%s)" |