From 46d3d2c731e8c7e138462e5b60a39a279dc77d81 Mon Sep 17 00:00:00 2001 From: Pavel Březina Date: Mon, 12 Mar 2012 10:07:35 +0100 Subject: sudo api: send uid, username and domainname https://fedorahosted.org/sssd/ticket/1239 Test client was changed accordingly. The new usage is: sss_sudo_cli username [uid] If uid is not set, getpwnam(username) is called. It will retrieve both default options and rules. --- src/responder/sudo/sudosrv_cmd.c | 133 ++++++++++------------------- src/responder/sudo/sudosrv_get_sudorules.c | 51 ++++++----- src/responder/sudo/sudosrv_private.h | 3 + src/responder/sudo/sudosrv_query.c | 24 +++++- 4 files changed, 102 insertions(+), 109 deletions(-) (limited to 'src/responder') diff --git a/src/responder/sudo/sudosrv_cmd.c b/src/responder/sudo/sudosrv_cmd.c index 7fe02a2c3..400d4053b 100644 --- a/src/responder/sudo/sudosrv_cmd.c +++ b/src/responder/sudo/sudosrv_cmd.c @@ -84,7 +84,7 @@ static errno_t sudosrv_cmd_send_error(TALLOC_CTX *mem_ctx, return EFAULT; } - ret = sudosrv_build_response(mem_ctx, error, 0, NULL, + ret = sudosrv_build_response(mem_ctx, error, NULL, 0, NULL, &response_body, &response_len); if (ret != EOK) { return ret; @@ -117,7 +117,7 @@ errno_t sudosrv_cmd_done(struct sudo_cmd_ctx *cmd_ctx, int ret) /* send result */ ret = sudosrv_build_response(cmd_ctx, SSS_SUDO_ERROR_OK, - num_rules, rules, + cmd_ctx->domain->name, num_rules, rules, &response_body, &response_len); if (ret != EOK) { return EFAULT; @@ -158,10 +158,12 @@ errno_t sudosrv_cmd_done(struct sudo_cmd_ctx *cmd_ctx, int ret) static int sudosrv_cmd(enum sss_dp_sudo_type type, struct cli_ctx *cli_ctx) { struct sudo_cmd_ctx *cmd_ctx = NULL; - struct sudo_dom_ctx *dctx = NULL; + struct sudo_dom_ctx *dom_ctx = NULL; uint8_t *query_body = NULL; size_t query_len = 0; - errno_t ret = EOK; + errno_t ret; + + /* create cmd_ctx */ cmd_ctx = talloc_zero(cli_ctx, struct sudo_cmd_ctx); if (cmd_ctx == NULL) { @@ -169,109 +171,66 @@ static int sudosrv_cmd(enum sss_dp_sudo_type type, struct cli_ctx *cli_ctx) DEBUG(SSSDBG_FATAL_FAILURE, ("Out of memory?\n")); return ENOMEM; } + cmd_ctx->domain = NULL; cmd_ctx->cli_ctx = cli_ctx; cmd_ctx->type = type; - cmd_ctx->username = NULL; - cmd_ctx->check_next = false; - - /* get responder ctx */ cmd_ctx->sudo_ctx = talloc_get_type(cli_ctx->rctx->pvt_ctx, struct sudo_ctx); - if (!cmd_ctx->sudo_ctx) { + if (cmd_ctx->sudo_ctx == NULL) { DEBUG(SSSDBG_FATAL_FAILURE, ("sudo_ctx not set, killing connection!\n")); - ret = EFAULT; - goto done; + return EFAULT; } - /* create domain ctx */ - dctx = talloc_zero(cmd_ctx, struct sudo_dom_ctx); - if (dctx == NULL) { - ret = ENOMEM; + /* parse query */ + + sss_packet_get_body(cli_ctx->creq->in, &query_body, &query_len); + if (query_len <= 0 || query_body == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, ("Query is empty\n")); + ret = EINVAL; goto done; } - dctx->cmd_ctx = cmd_ctx; - - switch (cmd_ctx->type) { - case SSS_DP_SUDO_USER: - /* get query */ - sss_packet_get_body(cli_ctx->creq->in, &query_body, &query_len); - if (query_len <= 0 || query_body == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, ("Query is empty\n")); - ret = EINVAL; - goto done; - } - - ret = sudosrv_parse_query(cmd_ctx, cli_ctx->rctx, - query_body, query_len, - &cmd_ctx->username, &cmd_ctx->domain); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, ("Invalid query: %s\n", strerror(ret))); - goto done; - } - - DEBUG(SSSDBG_FUNC_DATA, ("Requesting sudo rules for [%s] from [%s]\n", - cmd_ctx->username, cmd_ctx->domain ? cmd_ctx->domain->name : "")); - if (cmd_ctx->domain == NULL) { - /* this is a multidomain search */ - dctx->domain = cli_ctx->rctx->domains; - cmd_ctx->check_next = true; - } else { - dctx->domain = cmd_ctx->domain; - cmd_ctx->check_next = false; - } - - /* try to find rules in in-memory cache */ - ret = sudosrv_cache_lookup(cmd_ctx->sudo_ctx->cache, dctx, - cmd_ctx->check_next, cmd_ctx->username, - &cmd_ctx->num_rules, &cmd_ctx->rules); - if (ret == EOK) { - /* cache hit */ - DEBUG(SSSDBG_FUNC_DATA, ("Returning rules for [%s@%s] " - "from in-memory cache\n", cmd_ctx->username, dctx->domain->name)); - } else if (ret == ENOENT) { - /* cache expired or missed */ - ret = sudosrv_get_sudorules(dctx); - } /* else error */ + ret = sudosrv_parse_query(cmd_ctx, cli_ctx->rctx, + query_body, query_len, + &cmd_ctx->uid, &cmd_ctx->username, &cmd_ctx->domain); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, ("Invalid query: %s\n", strerror(ret))); + goto done; + } - break; - case SSS_DP_SUDO_DEFAULTS: - DEBUG(SSSDBG_FUNC_DATA, ("Requesting cn=defaults\n")); - - /* sudo currently does not support domain selection - * so find first available domain - * TODO - support domain selection */ - dctx->domain = cli_ctx->rctx->domains; - while (dctx->domain && dctx->domain->fqnames) { - dctx->domain = dctx->domain->next; - } - if (!dctx->domain) { - DEBUG(SSSDBG_MINOR_FAILURE, ("No valid domain found\n")); - ret = ENOENT; - goto done; - } + cmd_ctx->check_next = cmd_ctx->domain == NULL; - ret = sudosrv_cache_lookup(cmd_ctx->sudo_ctx->cache, dctx, - cmd_ctx->check_next, cmd_ctx->username, - &cmd_ctx->num_rules, &cmd_ctx->rules); + switch (cmd_ctx->type) { + case SSS_DP_SUDO_DEFAULTS: + DEBUG(SSSDBG_FUNC_DATA, ("Requesting default options " + "for [%s] from [%s]\n", cmd_ctx->username, + cmd_ctx->domain ? cmd_ctx->domain->name : "")); + break; + case SSS_DP_SUDO_USER: + DEBUG(SSSDBG_FUNC_DATA, ("Requesting rules " + "for [%s] from [%s]\n", cmd_ctx->username, + cmd_ctx->domain ? cmd_ctx->domain->name : "")); + break; + } - if (ret == EOK) { - /* cache hit */ - DEBUG(SSSDBG_FUNC_DATA, ("Returning defaults settings for [%s] " - "from in-memory cache\n", dctx->domain->name)); - } else if (ret == ENOENT) { - /* cache expired or missed */ - cmd_ctx->domain = dctx->domain; - ret = sudosrv_get_rules(cmd_ctx); - } /* else error */ + /* create domain ctx */ - break; + dom_ctx = talloc_zero(cmd_ctx, struct sudo_dom_ctx); + if (dom_ctx == NULL) { + ret = ENOMEM; + goto done; } + dom_ctx->cmd_ctx = cmd_ctx; + dom_ctx->domain = cmd_ctx->domain != NULL ? cmd_ctx->domain + : cli_ctx->rctx->domains; + + ret = sudosrv_get_sudorules(dom_ctx); done: return sudosrv_cmd_done(cmd_ctx, ret); } + static int sudosrv_cmd_get_sudorules(struct cli_ctx *cli_ctx) { return sudosrv_cmd(SSS_DP_SUDO_USER, cli_ctx); diff --git a/src/responder/sudo/sudosrv_get_sudorules.c b/src/responder/sudo/sudosrv_get_sudorules.c index c392027d7..1f4270d49 100644 --- a/src/responder/sudo/sudosrv_get_sudorules.c +++ b/src/responder/sudo/sudosrv_get_sudorules.c @@ -79,6 +79,7 @@ static errno_t sudosrv_get_user(struct sudo_dom_ctx *dctx) struct dp_callback_ctx *cb_ctx; const char *original_name = NULL; char *name = NULL; + uid_t uid = 0; errno_t ret; tmp_ctx = talloc_new(NULL); @@ -186,6 +187,21 @@ static errno_t sudosrv_get_user(struct sudo_dom_ctx *dctx) goto done; } + /* check uid */ + uid = ldb_msg_find_attr_as_int(user->msgs[0], SYSDB_UIDNUM, 0); + if (uid != cmd_ctx->uid) { + /* if a multidomain search, try with next */ + if (cmd_ctx->check_next) { + dctx->check_provider = true; + dom = dom->next; + if (dom) continue; + } + + DEBUG(SSSDBG_MINOR_FAILURE, ("UID does not match\n")); + ret = ENOENT; + goto done; + } + /* user is stored in cache, remember cased and original name */ original_name = ldb_msg_find_attr_as_string(user->msgs[0], SYSDB_NAME, NULL); @@ -265,7 +281,7 @@ static void sudosrv_check_user_dp_callback(uint16_t err_maj, uint32_t err_min, DEBUG(SSSDBG_OP_FAILURE, ("Could not look up the user [%d]: %s\n", ret, strerror(ret))); - sudosrv_cmd_done(dctx->cmd_ctx, EIO); + sudosrv_cmd_done(dctx->cmd_ctx, ret); return; } @@ -297,8 +313,18 @@ errno_t sudosrv_get_rules(struct sudo_cmd_ctx *cmd_ctx) struct tevent_req *dpreq; struct dp_callback_ctx *cb_ctx = NULL; - DEBUG(SSSDBG_TRACE_FUNC, ("getting rules for %s\n", - cmd_ctx->username ? cmd_ctx->username : "default options")); + switch (cmd_ctx->type) { + case SSS_DP_SUDO_DEFAULTS: + DEBUG(SSSDBG_TRACE_FUNC, ("Retrieving default options " + "for [%s] from [%s]\n", cmd_ctx->orig_username, + cmd_ctx->domain->name)); + break; + case SSS_DP_SUDO_USER: + DEBUG(SSSDBG_TRACE_FUNC, ("Retrieving rules " + "for [%s] from [%s]\n", cmd_ctx->orig_username, + cmd_ctx->domain->name)); + break; + } dpreq = sss_dp_get_sudoers_send(cmd_ctx->cli_ctx, cmd_ctx->cli_ctx->rctx, @@ -393,8 +419,6 @@ static errno_t sudosrv_get_sudorules_from_cache(struct sudo_cmd_ctx *cmd_ctx) TALLOC_CTX *tmp_ctx; errno_t ret; struct sysdb_ctx *sysdb; - struct sudo_ctx *sudo_ctx = cmd_ctx->sudo_ctx; - uid_t uid = 0; char **groupnames = NULL; const char *debug_name = NULL; @@ -421,7 +445,7 @@ static errno_t sudosrv_get_sudorules_from_cache(struct sudo_cmd_ctx *cmd_ctx) case SSS_DP_SUDO_USER: debug_name = cmd_ctx->cased_username; ret = sysdb_get_sudo_user_info(tmp_ctx, cmd_ctx->orig_username, sysdb, - &uid, &groupnames); + NULL, &groupnames); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, ("Unable to retrieve user info [%d]: %s\n", strerror(ret))); @@ -435,7 +459,7 @@ static errno_t sudosrv_get_sudorules_from_cache(struct sudo_cmd_ctx *cmd_ctx) ret = sudosrv_get_sudorules_query_cache(cmd_ctx, sysdb, cmd_ctx->type, cmd_ctx->orig_username, - uid, groupnames, + cmd_ctx->uid, groupnames, &cmd_ctx->rules, &cmd_ctx->num_rules); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, @@ -443,19 +467,6 @@ static errno_t sudosrv_get_sudorules_from_cache(struct sudo_cmd_ctx *cmd_ctx) goto done; } - /* Store result in in-memory cache */ - ret = sudosrv_cache_set_entry(sudo_ctx->rctx->ev, sudo_ctx, sudo_ctx->cache, - cmd_ctx->domain, cmd_ctx->cased_username, - cmd_ctx->num_rules, cmd_ctx->rules, - sudo_ctx->cache_timeout); - if (ret != EOK) { - DEBUG(SSSDBG_MINOR_FAILURE, ("Unable to store rules in cache for " - "[%s@%s]\n", debug_name, cmd_ctx->domain->name)); - } else { - DEBUG(SSSDBG_FUNC_DATA, ("Rules for [%s@%s] stored in in-memory cache\n", - debug_name, cmd_ctx->domain->name)); - } - DEBUG(SSSDBG_TRACE_FUNC, ("Returning rules for [%s@%s]\n", debug_name, cmd_ctx->domain->name)); diff --git a/src/responder/sudo/sudosrv_private.h b/src/responder/sudo/sudosrv_private.h index 9c17c59dd..b806c96e9 100644 --- a/src/responder/sudo/sudosrv_private.h +++ b/src/responder/sudo/sudosrv_private.h @@ -60,6 +60,7 @@ struct sudo_cmd_ctx { enum sss_dp_sudo_type type; /* input data */ + uid_t uid; char *username; const char *orig_username; const char *cased_username; @@ -94,11 +95,13 @@ errno_t sudosrv_parse_query(TALLOC_CTX *mem_ctx, struct resp_ctx *rctx, uint8_t *query_body, size_t query_len, + uid_t *_uid, char **_username, struct sss_domain_info **_domain); errno_t sudosrv_build_response(TALLOC_CTX *mem_ctx, uint32_t error, + const char *domain, int rules_num, struct sysdb_attrs **rules, uint8_t **_response_body, diff --git a/src/responder/sudo/sudosrv_query.c b/src/responder/sudo/sudosrv_query.c index dd9e1e880..7ba80e2ac 100644 --- a/src/responder/sudo/sudosrv_query.c +++ b/src/responder/sudo/sudosrv_query.c @@ -179,7 +179,7 @@ done: /* * Response format: - * ... + * \0... * = ... * = \0\0\0... * @@ -187,6 +187,7 @@ done: */ errno_t sudosrv_build_response(TALLOC_CTX *mem_ctx, uint32_t error, + const char *domain, int rules_num, struct sysdb_attrs **rules, uint8_t **_response_body, @@ -215,6 +216,13 @@ errno_t sudosrv_build_response(TALLOC_CTX *mem_ctx, goto done; } + /* domain name */ + ret = sudosrv_response_append_string(tmp_ctx, domain, strlen(domain) + 1, + &response_body, &response_len); + if (ret != EOK) { + goto fail; + } + /* rules count */ ret = sudosrv_response_append_uint32(tmp_ctx, (uint32_t)rules_num, &response_body, &response_len); @@ -244,12 +252,13 @@ fail: /* * Query format: - * + * */ errno_t sudosrv_parse_query(TALLOC_CTX *mem_ctx, struct resp_ctx *rctx, uint8_t *query_body, size_t query_len, + uid_t *_uid, char **_username, struct sss_domain_info **_domain) { @@ -260,6 +269,7 @@ errno_t sudosrv_parse_query(TALLOC_CTX *mem_ctx, char *rawname = NULL; char *domainname = NULL; char *username = NULL; + uid_t uid; errno_t ret; tmp_ctx = talloc_new(NULL); @@ -268,6 +278,15 @@ errno_t sudosrv_parse_query(TALLOC_CTX *mem_ctx, return ENOMEM; } + /* uid */ + + if (query_len < sizeof(uid_t)) { + DEBUG(SSSDBG_CRIT_FAILURE, ("Query is too small\n")); + ret = EINVAL; + goto done; + } + safealign_memcpy(&uid, query_body, sizeof(uid_t), &offset); + /* username[@domain] */ rawname = (char*)(query_body + offset); @@ -310,6 +329,7 @@ errno_t sudosrv_parse_query(TALLOC_CTX *mem_ctx, } } + *_uid = uid; *_username = talloc_steal(mem_ctx, username); *_domain = domain; /* do not steal on mem_ctx */ -- cgit