summaryrefslogtreecommitdiff
path: root/src/responder/sudo
diff options
context:
space:
mode:
authorPavel Březina <pbrezina@redhat.com>2012-03-12 10:07:35 +0100
committerStephen Gallagher <sgallagh@redhat.com>2012-06-29 11:37:16 -0400
commit46d3d2c731e8c7e138462e5b60a39a279dc77d81 (patch)
treebf34e85372bbffbed1e4f648d284cc9cc487da1a /src/responder/sudo
parentcda8ff6cfdef22356dc3c06ec5204344912f0f0b (diff)
downloadsssd-46d3d2c731e8c7e138462e5b60a39a279dc77d81.tar.gz
sssd-46d3d2c731e8c7e138462e5b60a39a279dc77d81.tar.bz2
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/responder/sudo')
-rw-r--r--src/responder/sudo/sudosrv_cmd.c133
-rw-r--r--src/responder/sudo/sudosrv_get_sudorules.c51
-rw-r--r--src/responder/sudo/sudosrv_private.h3
-rw-r--r--src/responder/sudo/sudosrv_query.c24
4 files changed, 102 insertions, 109 deletions
diff --git a/src/responder/sudo/sudosrv_cmd.c b/src/responder/sudo/sudosrv_cmd.c
index 7fe02a2c..400d4053 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 c392027d..1f4270d4 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 9c17c59d..b806c96e 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 dd9e1e88..7ba80e2a 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 */