diff options
-rw-r--r-- | src/providers/ldap/sdap_async_sudo.c | 62 | ||||
-rw-r--r-- | src/util/util.c | 31 | ||||
-rw-r--r-- | src/util/util.h | 3 |
3 files changed, 96 insertions, 0 deletions
diff --git a/src/providers/ldap/sdap_async_sudo.c b/src/providers/ldap/sdap_async_sudo.c index feb533cf3..3c69837fd 100644 --- a/src/providers/ldap/sdap_async_sudo.c +++ b/src/providers/ldap/sdap_async_sudo.c @@ -492,6 +492,61 @@ static errno_t sdap_sudo_refresh_sudoers(struct tevent_req *req) return EAGAIN; } +static errno_t sdap_sudo_qualify_names(struct sss_domain_info *dom, + struct sysdb_attrs **rules, + size_t rules_count) +{ + errno_t ret; + bool qualify; + struct ldb_message_element *el; + char *domain; + char *name; + const char *orig_name; + + for (size_t i = 0; i < rules_count; i++) { + ret = sysdb_attrs_get_el_ext(rules[i], SYSDB_SUDO_CACHE_AT_USER, + false, &el); + if (ret != EOK) { + continue; + } + + for (size_t ii = 0; ii < el->num_values; ii++) { + orig_name = (const char *) el->values[ii].data; + + qualify = is_user_or_group_name(orig_name); + if (qualify) { + ret = sss_parse_name(rules, dom->names, orig_name, + &domain, &name); + if (ret != EOK) { + continue; + } + + if (domain == NULL) { + domain = talloc_strdup(rules, dom->name); + if (domain == NULL) { + talloc_zfree(name); + return ENOMEM; + } + } + + el->values[ii].data = (uint8_t * ) sss_create_internal_fqname( + rules, + name, + domain); + talloc_zfree(domain); + talloc_zfree(name); + if (el->values[ii].data == NULL) { + return ENOMEM; + } + el->values[ii].length = strlen( + (const char *) el->values[ii].data); + } + } + } + + return EOK; +} + static void sdap_sudo_refresh_done(struct tevent_req *subreq) { struct tevent_req *req; @@ -525,6 +580,13 @@ static void sdap_sudo_refresh_done(struct tevent_req *subreq) DEBUG(SSSDBG_TRACE_FUNC, "Received %zu rules\n", rules_count); + /* Save users and groups fully qualified */ + ret = sdap_sudo_qualify_names(state->domain, rules, rules_count); + if (ret != EOK) { + goto done; + } + + /* start transaction */ ret = sysdb_transaction_start(state->sysdb); if (ret != EOK) { diff --git a/src/util/util.c b/src/util/util.c index d7d3ac90a..89abfe734 100644 --- a/src/util/util.c +++ b/src/util/util.c @@ -1244,3 +1244,34 @@ done: return ret; } + +bool is_user_or_group_name(const char *sudo_user_value) +{ + if (sudo_user_value == NULL) { + return false; + } + + /* See man sudoers.ldap for explanation */ + if (strcmp(sudo_user_value, "ALL") == 0) { + return false; + } + + switch (sudo_user_value[0]) { + case '#': /* user id */ + case '+': /* netgroup */ + case '\0': /* empty value */ + return false; + } + + if (sudo_user_value[0] == '%') { + switch (sudo_user_value[1]) { + case '#': /* POSIX group ID */ + case ':': /* non-POSIX group */ + case '\0': /* empty value */ + return false; + } + } + + /* Now it's either a username or a groupname */ + return true; +} diff --git a/src/util/util.h b/src/util/util.h index 3b8acd1c5..3ed8444b5 100644 --- a/src/util/util.h +++ b/src/util/util.h @@ -381,6 +381,9 @@ errno_t sss_hash_create_ex(TALLOC_CTX *mem_ctx, hash_delete_callback *delete_callback, void *delete_private_data); +/* Returns true if sudoUser value is a username or a groupname */ +bool is_user_or_group_name(const char *sudo_user_value); + /** * @brief Add two list of strings * |