summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/providers/ldap/sdap_async_sudo.c62
-rw-r--r--src/util/util.c31
-rw-r--r--src/util/util.h3
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
*