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/sss_client/sudo/sss_sudo.c | 107 ++++++++++++++++++----------- src/sss_client/sudo/sss_sudo.h | 40 +++++++---- src/sss_client/sudo/sss_sudo_private.h | 1 + src/sss_client/sudo/sss_sudo_response.c | 12 ++++ src/sss_client/sudo_testcli/sudo_testcli.c | 64 +++++++++++++---- 5 files changed, 158 insertions(+), 66 deletions(-) (limited to 'src/sss_client') diff --git a/src/sss_client/sudo/sss_sudo.c b/src/sss_client/sudo/sss_sudo.c index 378df984..e2bb3e00 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 . */ +#include "config.h" + #include +#include #include #include +#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 fe01e65d..1a275cfa 100644 --- a/src/sss_client/sudo/sss_sudo.h +++ b/src/sss_client/sudo/sss_sudo.h @@ -30,6 +30,7 @@ */ #include +#include /** 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 674bf125..2827a94d 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 4e74d83a..471d42ed 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 b498acec..d86fb752 100644 --- a/src/sss_client/sudo_testcli/sudo_testcli.c +++ b/src/sss_client/sudo_testcli/sudo_testcli.c @@ -23,6 +23,8 @@ #include #include #include +#include +#include #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 : ""); + + 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; } -- cgit