From 6f701a4dc295ddc997ba5190a3cd72d948d799dc Mon Sep 17 00:00:00 2001 From: Pavel Březina Date: Fri, 2 Dec 2011 12:10:27 +0100 Subject: SUDO Integration - API for sudo --- src/sss_client/sudo/sss_sudo.c | 225 ++++++++++++++++++++++++++++++ src/sss_client/sudo/sss_sudo.h | 60 ++++++++ src/sss_client/sudo/sss_sudo_private.h | 32 +++++ src/sss_client/sudo/sss_sudo_response.c | 236 ++++++++++++++++++++++++++++++++ 4 files changed, 553 insertions(+) create mode 100644 src/sss_client/sudo/sss_sudo.c create mode 100644 src/sss_client/sudo/sss_sudo.h create mode 100644 src/sss_client/sudo/sss_sudo_private.h create mode 100644 src/sss_client/sudo/sss_sudo_response.c (limited to 'src/sss_client/sudo') diff --git a/src/sss_client/sudo/sss_sudo.c b/src/sss_client/sudo/sss_sudo.c new file mode 100644 index 00000000..9a749455 --- /dev/null +++ b/src/sss_client/sudo/sss_sudo.c @@ -0,0 +1,225 @@ +/* + Authors: + Pavel Březina + + Copyright (C) 2011 Red Hat + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include +#include +#include + +#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); + +static void sss_sudo_free_rules(unsigned int num_rules, + struct sss_rule *rules); + +static void sss_sudo_free_attrs(unsigned int num_attrs, + struct sss_attr *attrs); + +int sss_sudo_get_result(const char *username, + uint32_t *_error, + struct sss_result **_result) +{ + struct sss_result *result = NULL; + struct sss_cli_req_data request; + char *query = NULL; + int query_len = 0; + uint8_t *reply_buf = NULL; + size_t reply_len = 0; + uint32_t responder_error = 0; + int errnop = 0; + int ret = 0; + + /* create query */ + + ret = sss_sudo_create_query(username, &query, &query_len); + if (ret != EOK) { + goto done; + } + + request.len = query_len; + request.data = (const void*)query; + + /* send query and recieve response */ + + errnop = 0; + ret = sss_sudo_make_request(SSS_SUDO_GET_SUDORULES, &request, + &reply_buf, &reply_len, &errnop); + if (errnop != EOK) { + ret = errnop; + goto done; + } + + /* parse and print structure */ + + ret = sss_sudo_parse_response((const char*)reply_buf, reply_len, + &result, &responder_error); + if (ret != EOK) { + goto done; + } + + *_error = responder_error; + *_result = result; + + ret = EOK; + +done: + free(query); + + return ret; +} + +int sss_sudo_create_query(const char *username, char **_query, int *_query_len) +{ + char *data = NULL; + int data_len = strlen(username) + 1; + + if (data_len <= 1) { + return EINVAL; + } + + data = (char*)malloc(data_len * sizeof(char)); + if (data == NULL) { + return ENOMEM; + } + + memcpy(data, username, data_len); + + *_query = data; + *_query_len = data_len; + + return EOK; +} + +int sss_sudo_get_values(struct sss_rule *e, + const char *attrname, char ***_values) +{ + struct sss_attr *attr = NULL; + char **values = NULL; + int i, j; + + for (i = 0; i < e->num_attrs; i++) { + attr = e->attrs + i; + if (strcasecmp(attr->name, attrname) == 0) { + values = calloc(attr->num_values + 1, sizeof(char*)); + if (values == NULL) { + return ENOMEM; + } + + for (j = 0; j < attr->num_values; j++) { + values[j] = strdup(attr->values[j]); + if (values[j] == NULL) { + return ENOMEM; + } + } + + values[attr->num_values] = NULL; + } + } + + if (values == 0) { + return ENOENT; + } + + *_values = values; + + return EOK; +} + +void sss_sudo_free_values(char **values) +{ + char **value = NULL; + + if (values == NULL) { + return; + } + + for (value = values; *value != NULL; value++) { + free(*value); + } + + free(values); +} + +void sss_sudo_free_result(struct sss_result *result) +{ + if (result == NULL) { + return; + } + + sss_sudo_free_rules(result->num_rules, result->rules); + free(result); +} + +void sss_sudo_free_rules(unsigned int num_rules, struct sss_rule *rules) +{ + struct sss_rule *rule = NULL; + int i; + + if (rules == NULL) { + return; + } + + for (i = 0; i < num_rules; i++) { + rule = rules + i; + + if (rule == NULL) { + continue; + } + + sss_sudo_free_attrs(rule->num_attrs, rule->attrs); + rule->attrs = NULL; + } + + free(rules); +} + +void sss_sudo_free_attrs(unsigned int num_attrs, struct sss_attr *attrs) +{ + struct sss_attr *attr = NULL;; + int i, j; + + if (attrs == NULL) { + return; + } + + for (i = 0; i < num_attrs; i++) { + attr = attrs + i; + + if (attr == NULL) { + continue; + } + + free(attr->name); + attr->name = NULL; + + for (j = 0; j < attr->num_values; j++) { + free(attr->values[j]); + attr->values[j] = NULL; + } + + free(attr->values); + } + + free(attrs); +} diff --git a/src/sss_client/sudo/sss_sudo.h b/src/sss_client/sudo/sss_sudo.h new file mode 100644 index 00000000..04e19db2 --- /dev/null +++ b/src/sss_client/sudo/sss_sudo.h @@ -0,0 +1,60 @@ +/* + Authors: + Pavel Březina + + Copyright (C) 2011 Red Hat + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef SSS_SUDO_H_ +#define SSS_SUDO_H_ + +#include + +#ifndef EOK +#define EOK 0 +#endif + +#define SSS_SUDO_ERROR_OK 0 + +struct sss_attr { + char *name; + char **values; + unsigned int num_values; +}; + +struct sss_rule { + unsigned int num_attrs; + struct sss_attr *attrs; +}; + +struct sss_result { + unsigned int num_rules; + struct sss_rule *rules; +}; + +int sss_sudo_get_result(const char *username, + uint32_t *_error, + struct sss_result **_result); + +void sss_sudo_free_result(struct sss_result *result); + +int sss_sudo_get_values(struct sss_rule *e, + const char *attrname, + char ***values); + +void sss_sudo_free_values(char **values); + +#endif /* SSS_SUDO_H_ */ diff --git a/src/sss_client/sudo/sss_sudo_private.h b/src/sss_client/sudo/sss_sudo_private.h new file mode 100644 index 00000000..2b20c1cf --- /dev/null +++ b/src/sss_client/sudo/sss_sudo_private.h @@ -0,0 +1,32 @@ +/* + Authors: + Pavel Březina + + Copyright (C) 2011 Red Hat + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef SSS_SUDO_PRIVATE_H_ +#define SSS_SUDO_PRIVATE_H_ + +#include +#include "sss_client/sudo/sss_sudo.h" + +int sss_sudo_parse_response(const char *message, + size_t message_len, + struct sss_result **_result, + uint32_t *_error); + +#endif /* SSS_SUDO_PRIVATE_H_ */ diff --git a/src/sss_client/sudo/sss_sudo_response.c b/src/sss_client/sudo/sss_sudo_response.c new file mode 100644 index 00000000..d33215a0 --- /dev/null +++ b/src/sss_client/sudo/sss_sudo_response.c @@ -0,0 +1,236 @@ +/* + Authors: + Pavel Březina + + Copyright (C) 2011 Red Hat + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include +#include +#include +#include + +#include "sss_client/sudo/sss_sudo.h" +#include "sss_client/sudo/sss_sudo_private.h" + +static int sss_sudo_parse_rule(const char *message, + size_t message_len, + size_t *_cursor, + struct sss_rule *_rule); + +static int sss_sudo_parse_attr(const char *message, + size_t message_len, + size_t *_cursor, + struct sss_attr *_attr); + +static int sss_sudo_parse_uint32(const char *message, + size_t message_len, + size_t *_cursor, + uint32_t *_number); + +static int sss_sudo_parse_string(const char *message, + size_t message_len, + size_t *_cursor, + char **_str); + +int sss_sudo_parse_response(const char *message, + size_t message_len, + struct sss_result **_result, + uint32_t *_error) +{ + struct sss_result *result = NULL; + size_t cursor = 0; + int ret = EOK; + int i = 0; + + /* error code */ + ret = sss_sudo_parse_uint32(message, message_len, &cursor, _error); + if (ret != EOK || *_error != SSS_SUDO_ERROR_OK) { + return ret; + } + + /* result */ + result = malloc(sizeof(struct sss_result)); + if (result == NULL) { + return ENOMEM; + } + + /* rules_num */ + ret = sss_sudo_parse_uint32(message, message_len, + &cursor, &result->num_rules); + if (ret != EOK) { + goto fail; + } + + /* rules */ + result->rules = calloc(result->num_rules, sizeof(struct sss_rule)); + if (result->rules == NULL) { + ret = ENOMEM; + goto fail; + } + + for (i = 0; i < result->num_rules; i++) { + ret = sss_sudo_parse_rule(message, message_len, + &cursor, &result->rules[i]); + if (ret != EOK) { + goto fail; + } + } + + *_result = result; + + return EOK; + +fail: + sss_sudo_free_result(result); + return ret; +} + +int sss_sudo_parse_rule(const char *message, + size_t message_len, + size_t *_cursor, + struct sss_rule *_rule) +{ + int ret = EOK; + int i = 0; + + /* attrs_num */ + ret = sss_sudo_parse_uint32(message, message_len, + _cursor, &_rule->num_attrs); + if (ret != EOK) { + return ret; + } + + /* attrs */ + _rule->attrs = calloc(_rule->num_attrs, sizeof(struct sss_attr)); + if (_rule->attrs == NULL) { + return ENOMEM; + } + + for (i = 0; i < _rule->num_attrs; i++) { + ret = sss_sudo_parse_attr(message, message_len, + _cursor, &_rule->attrs[i]); + if (ret != EOK) { + return ret; + } + } + + return EOK; +} + +int sss_sudo_parse_attr(const char *message, + size_t message_len, + size_t *_cursor, + struct sss_attr *_attr) +{ + char *str = NULL; + int ret = EOK; + int i = 0; + + /* name */ + ret = sss_sudo_parse_string(message, message_len, _cursor, &str); + if (ret != EOK) { + return ret; + } + _attr->name = str; + + /* values_num */ + ret = sss_sudo_parse_uint32(message, message_len, + _cursor, &_attr->num_values); + if (ret != EOK) { + return ret; + } + + /* values */ + _attr->values = calloc(_attr->num_values, sizeof(const char*)); + if (_attr->values == NULL) { + return ENOMEM; + } + + for (i = 0; i < _attr->num_values; i++) { + ret = sss_sudo_parse_string(message, message_len, _cursor, &str); + if (ret != EOK) { + return ret; + } + _attr->values[i] = str; + } + + return EOK; +} + +int sss_sudo_parse_uint32(const char *message, + size_t message_len, + size_t *_cursor, + uint32_t *_number) +{ + size_t start_pos = 0; + + if (_cursor == NULL) { + return EINVAL; + } + + start_pos = *_cursor; + + if (start_pos + sizeof(uint32_t) > message_len) { + return EINVAL; + } + + memcpy(_number, message + start_pos, sizeof(uint32_t)); + *_cursor = start_pos + sizeof(uint32_t); + + return EOK; +} + +int sss_sudo_parse_string(const char *message, + size_t message_len, + size_t *_cursor, + char **_str) +{ + const char *current = NULL; + char *str = NULL; + size_t start_pos = 0; + size_t len = 0; + size_t maxlen = 0; + + if (_cursor == NULL) { + return EINVAL; + } + + start_pos = *_cursor; + maxlen = message_len - start_pos; + + if (start_pos >= message_len ) { + return EINVAL; + } + + current = message + start_pos; + len = strnlen(current, maxlen); + if (len == maxlen) { + /* the string exceeds message length */ + return EINVAL; + } + + str = strndup(current, len); + if (str == NULL) { + return ENOMEM; + } + + /* go after \0 */ + *_cursor = start_pos + len + 1; + *_str = str; + + return EOK; +} -- cgit