diff options
author | Pavel Březina <pbrezina@redhat.com> | 2012-03-12 10:07:35 +0100 |
---|---|---|
committer | Stephen Gallagher <sgallagh@redhat.com> | 2012-06-29 11:37:16 -0400 |
commit | 46d3d2c731e8c7e138462e5b60a39a279dc77d81 (patch) | |
tree | bf34e85372bbffbed1e4f648d284cc9cc487da1a /src | |
parent | cda8ff6cfdef22356dc3c06ec5204344912f0f0b (diff) | |
download | sssd-46d3d2c731e8c7e138462e5b60a39a279dc77d81.tar.gz sssd-46d3d2c731e8c7e138462e5b60a39a279dc77d81.tar.xz sssd-46d3d2c731e8c7e138462e5b60a39a279dc77d81.zip |
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.
Diffstat (limited to 'src')
-rw-r--r-- | src/responder/sudo/sudosrv_cmd.c | 133 | ||||
-rw-r--r-- | src/responder/sudo/sudosrv_get_sudorules.c | 51 | ||||
-rw-r--r-- | src/responder/sudo/sudosrv_private.h | 3 | ||||
-rw-r--r-- | src/responder/sudo/sudosrv_query.c | 24 | ||||
-rw-r--r-- | src/sss_client/sudo/sss_sudo.c | 107 | ||||
-rw-r--r-- | src/sss_client/sudo/sss_sudo.h | 40 | ||||
-rw-r--r-- | src/sss_client/sudo/sss_sudo_private.h | 1 | ||||
-rw-r--r-- | src/sss_client/sudo/sss_sudo_response.c | 12 | ||||
-rw-r--r-- | src/sss_client/sudo_testcli/sudo_testcli.c | 64 |
9 files changed, 260 insertions, 175 deletions
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 : "<ALL>")); - 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 : "<ALL>")); + 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 : "<ALL>")); + 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: - * <error_code(uint32_t)><num_entries(uint32_t)><rule1><rule2>... + * <error_code(uint32_t)><domain(char*)>\0<num_entries(uint32_t)><rule1><rule2>... * <ruleN> = <num_attrs(uint32_t)><attr1><attr2>... * <attrN> = <name(char*)>\0<num_values(uint32_t)><value1(char*)>\0<value2(char*)>\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: - * <username[@domain]> + * <uid><username[@domain]> */ 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 */ diff --git a/src/sss_client/sudo/sss_sudo.c b/src/sss_client/sudo/sss_sudo.c index 378df9843..e2bb3e00d 100644 --- a/src/sss_client/sudo/sss_sudo.c +++ b/src/sss_client/sudo/sss_sudo.c @@ -18,17 +18,22 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include "config.h" + #include <stdlib.h> +#include <stdio.h> #include <string.h> #include <errno.h> +#include "util/util.h" #include "sss_client/sss_cli.h" #include "sss_client/sudo/sss_sudo.h" #include "sss_client/sudo/sss_sudo_private.h" -static int sss_sudo_create_query(const char *username, - char **_query, - int *_query_len); +int sss_sudo_create_query(uid_t uid, + const char *username, + uint8_t **_query, + size_t *_query_len); static void sss_sudo_free_rules(unsigned int num_rules, struct sss_sudo_rule *rules); @@ -37,19 +42,34 @@ static void sss_sudo_free_attrs(unsigned int num_attrs, struct sss_sudo_attr *attrs); static int sss_sudo_send_recv_generic(enum sss_cli_command command, - struct sss_cli_req_data *request, + uid_t uid, + const char *username, uint32_t *_error, + char **_domainname, struct sss_sudo_result **_result) { + struct sss_cli_req_data request; + uint8_t *query_buf = NULL; + size_t query_len = 0; uint8_t *reply_buf = NULL; size_t reply_len = 0; int errnop = 0; int ret = 0; + /* create query */ + + ret = sss_sudo_create_query(uid, username, &query_buf, &query_len); + if (ret != EOK) { + goto done; + } + + request.len = query_len; + request.data = (const void*)query_buf; + /* send query and receive response */ errnop = 0; - ret = sss_sudo_make_request(command, request, + ret = sss_sudo_make_request(command, &request, &reply_buf, &reply_len, &errnop); if (ret != SSS_STATUS_SUCCESS) { ret = errnop; @@ -59,69 +79,76 @@ static int sss_sudo_send_recv_generic(enum sss_cli_command command, /* parse structure */ ret = sss_sudo_parse_response((const char*)reply_buf, reply_len, - _result, _error); + _domainname, _result, _error); done: + free(query_buf); free(reply_buf); return ret; } -int sss_sudo_send_recv(const char *username, +int sss_sudo_send_recv(uid_t uid, + const char *username, + const char *domainname, uint32_t *_error, struct sss_sudo_result **_result) { - struct sss_cli_req_data request; - char *query = NULL; - int query_len = 0; - int ret = 0; + char *fullname = NULL; + int ret; - /* create query */ - - ret = sss_sudo_create_query(username, &query, &query_len); - if (ret != EOK) { - goto done; + if (username == NULL || strlen(username) == 0) { + return EINVAL; } - request.len = query_len; - request.data = (const void*)query; - - /* send query and recieve response */ + if (domainname != NULL) { + ret = asprintf(&fullname, "%s@%s", username, domainname); + if (ret == -1) { + return ENOMEM; + } + } else { + fullname = strdup(username); + if (fullname == NULL) { + return ENOMEM; + } + } - ret = sss_sudo_send_recv_generic(SSS_SUDO_GET_SUDORULES, &request, - _error, _result); + /* send query and receive response */ -done: - free(query); + ret = sss_sudo_send_recv_generic(SSS_SUDO_GET_SUDORULES, uid, fullname, + _error, NULL, _result); + free(fullname); return ret; } -int sss_sudo_send_recv_defaults(uint32_t *_error, +int sss_sudo_send_recv_defaults(uid_t uid, + const char *username, + uint32_t *_error, + char **_domainname, struct sss_sudo_result **_result) { - struct sss_cli_req_data request; - - request.len = 0; - request.data = (const void*)NULL; + if (username == NULL || strlen(username) == 0) { + return EINVAL; + } - return sss_sudo_send_recv_generic(SSS_SUDO_GET_DEFAULTS, &request, - _error, _result); + return sss_sudo_send_recv_generic(SSS_SUDO_GET_DEFAULTS, uid, username, + _error, _domainname, _result); } -int sss_sudo_create_query(const char *username, char **_query, int *_query_len) +int sss_sudo_create_query(uid_t uid, const char *username, + uint8_t **_query, size_t *_query_len) { - char *data = NULL; - int data_len = strlen(username) + 1; - - if (data_len <= 1) { - return EINVAL; - } + uint8_t *data = NULL; + size_t username_len = strlen(username) * sizeof(char) + 1; + size_t data_len = sizeof(uid_t) + username_len; + size_t offset = 0; - data = (char*)malloc(data_len * sizeof(char)); + data = (uint8_t*)malloc(data_len * sizeof(uint8_t)); if (data == NULL) { return ENOMEM; } - memcpy(data, username, data_len); + SAFEALIGN_SET_VALUE(data, uid, uid_t, &offset); + memcpy(data + offset, username, username_len); *_query = data; *_query_len = data_len; diff --git a/src/sss_client/sudo/sss_sudo.h b/src/sss_client/sudo/sss_sudo.h index fe01e65d3..1a275cfaf 100644 --- a/src/sss_client/sudo/sss_sudo.h +++ b/src/sss_client/sudo/sss_sudo.h @@ -30,6 +30,7 @@ */ #include <stdint.h> +#include <sys/types.h> /** The value returned when the communication with SUDO is successful and * the user was found in one of the domains @@ -89,7 +90,9 @@ struct sss_sudo_result { * @brief Send a request to SSSD to retreive all SUDO rules for a given * user. * + * @param[in] uid The uid of the user to retreive the rules for. * @param[in] username The username to retreive the rules for + * @param[in] domainname The domain name the user is a member of. * @param[out] _error The result of the search in SSSD's domains. If the * user was present in the domain, the _error code is * SSS_SUDO_ERROR_OK and the _result structure is @@ -109,7 +112,9 @@ struct sss_sudo_result { * tell whether the result contains any rules or whether SSSD knew the * user at all. That information is transferred in the _error parameter. */ -int sss_sudo_send_recv(const char *username, +int sss_sudo_send_recv(uid_t uid, + const char *username, + const char *domainname, uint32_t *_error, struct sss_sudo_result **_result); @@ -117,24 +122,35 @@ int sss_sudo_send_recv(const char *username, * @brief Send a request to SSSD to retrieve the default options, commonly * stored in the "cn=defaults" record, * - * @param[out] _error The result of the search in SSSD's domains. If the - * options were present in the domain, the _error code - * is SSS_SUDO_ERROR_OK and the _result structure is - * returned even if it was empty (in other words - * _result->num_rules == 0). Other problems are returned - * as errno codes. + * @param[in] uid The uid of the user to retreive the rules for. * - * @param[out] _result Newly allocated structure sss_result that contains - * the options. If no options were found this structure - * is "empty", which means that the num_rules member - * is 0. + * @param[in] username The username to retreive the rules for. + * + * @param[out] _error The result of the search in SSSD's domains. If the + * options were present in the domain, the _error code + * is SSS_SUDO_ERROR_OK and the _result structure is + * returned even if it was empty (in other words + * _result->num_rules == 0). Other problems are returned + * as errno codes. + * + * @param[out] _domainname The domain name the user is a member of. + * + * @param[out] _result Newly allocated structure sss_result that contains + * the options. If no options were found this structure + * is "empty", which means that the num_rules member + * is 0. * * @return 0 on success and other errno values on failure. The return value * denotes whether communication with SSSD was successful. It does not * tell whether the result contains any rules or whether SSSD knew the * user at all. That information is transferred in the _error parameter. + * + * @note The _domainname should be freed using free(). */ -int sss_sudo_send_recv_defaults(uint32_t *_error, +int sss_sudo_send_recv_defaults(uid_t uid, + const char *username, + uint32_t *_error, + char **_domainname, struct sss_sudo_result **_result); /** diff --git a/src/sss_client/sudo/sss_sudo_private.h b/src/sss_client/sudo/sss_sudo_private.h index 674bf125f..2827a94d1 100644 --- a/src/sss_client/sudo/sss_sudo_private.h +++ b/src/sss_client/sudo/sss_sudo_private.h @@ -26,6 +26,7 @@ int sss_sudo_parse_response(const char *message, size_t message_len, + char **_domainname, struct sss_sudo_result **_result, uint32_t *_error); diff --git a/src/sss_client/sudo/sss_sudo_response.c b/src/sss_client/sudo/sss_sudo_response.c index 4e74d83ab..471d42ed4 100644 --- a/src/sss_client/sudo/sss_sudo_response.c +++ b/src/sss_client/sudo/sss_sudo_response.c @@ -51,10 +51,12 @@ static int sss_sudo_parse_string(const char *message, int sss_sudo_parse_response(const char *message, size_t message_len, + char **_domainname, struct sss_sudo_result **_result, uint32_t *_error) { struct sss_sudo_result *result = NULL; + char *domainname = NULL; size_t cursor = 0; int ret = EOK; int i = 0; @@ -65,6 +67,16 @@ int sss_sudo_parse_response(const char *message, return ret; } + /* domain name */ + ret = sss_sudo_parse_string(message, message_len, &cursor, &domainname); + if (ret != EOK) { + return ret; + } + + if (_domainname != NULL) { + *_domainname = domainname; + } + /* result */ result = malloc(sizeof(struct sss_sudo_result)); if (result == NULL) { diff --git a/src/sss_client/sudo_testcli/sudo_testcli.c b/src/sss_client/sudo_testcli/sudo_testcli.c index b498acec5..d86fb7521 100644 --- a/src/sss_client/sudo_testcli/sudo_testcli.c +++ b/src/sss_client/sudo_testcli/sudo_testcli.c @@ -23,6 +23,8 @@ #include <errno.h> #include <string.h> #include <talloc.h> +#include <sys/types.h> +#include <pwd.h> #include "sss_client/sss_cli.h" #include "sss_client/sudo/sss_sudo.h" @@ -38,40 +40,74 @@ int main(int argc, char **argv) { int ret = 0; struct sss_sudo_result *result = NULL; + struct passwd *passwd = NULL; + const char *username = NULL; + char *domainname = NULL; + uid_t uid = 0; uint32_t error = 0; - if (argc > 2) { - fprintf(stderr, "Usage: sss_sudo_cli username\n"); + if (argc > 3) { + fprintf(stderr, "Usage: sss_sudo_cli username [uid]\n"); goto fail; } - /* get sss_result - it will send new query to responder */ - - if (argc == 1) { - ret = sss_sudo_send_recv_defaults(&error, &result); - if (ret != EOK) { - fprintf(stderr, "sss_sudo_send_recv_defaults() failed: %s\n", strerror(ret)); - goto fail; - } + username = argv[1]; + if (argc == 3) { + uid = atoi(argv[2]); } else { - ret = sss_sudo_send_recv(argv[1], &error, &result); - if (ret != EOK) { - fprintf(stderr, "sss_sudo_send_recv() failed: %s\n", strerror(ret)); + passwd = getpwnam(username); + if (passwd == NULL) { + fprintf(stderr, "Unknown user\n"); goto fail; } + uid = passwd->pw_uid; + } + + /* get sss_result - it will send new query to responder */ + + /* get default options */ + + ret = sss_sudo_send_recv_defaults(uid, username, &error, + &domainname, &result); + if (ret != EOK) { + fprintf(stderr, "sss_sudo_send_recv_defaults() failed: %s\n", + strerror(ret)); + goto fail; + } + + printf("User [%s:%llu] found in domain: %s\n\n", + username, (unsigned long long)uid, + domainname != NULL ? domainname : "<NULL>"); + + printf("=== Printing response data [default options] ===\n"); + printf("Response code: %d\n\n", error); + if (error == SSS_SUDO_ERROR_OK) { + print_sss_result(result); + } + + sss_sudo_free_result(result); + + /* get rules */ + + ret = sss_sudo_send_recv(uid, username, domainname, &error, &result); + if (ret != EOK) { + fprintf(stderr, "sss_sudo_send_recv() failed: %s\n", strerror(ret)); + goto fail; } - printf("=== Printing response data ===\n"); + printf("\n=== Printing response data [rules] ===\n"); printf("Response code: %d\n\n", error); if (error == SSS_SUDO_ERROR_OK) { print_sss_result(result); } + free(domainname); sss_sudo_free_result(result); return 0; fail: + free(domainname); sss_sudo_free_result(result); return 1; } |