summaryrefslogtreecommitdiffstats
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
parentcda8ff6cfdef22356dc3c06ec5204344912f0f0b (diff)
downloadsssd-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.
-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
-rw-r--r--src/sss_client/sudo/sss_sudo.c107
-rw-r--r--src/sss_client/sudo/sss_sudo.h40
-rw-r--r--src/sss_client/sudo/sss_sudo_private.h1
-rw-r--r--src/sss_client/sudo/sss_sudo_response.c12
-rw-r--r--src/sss_client/sudo_testcli/sudo_testcli.c64
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;
}