summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJakub Hrozek <jhrozek@redhat.com>2016-06-22 10:33:09 +0200
committerJakub Hrozek <jhrozek@redhat.com>2016-07-06 17:40:22 +0200
commitdd9651c395bbba72443a31d17a767be60581da2c (patch)
tree6577cf75dd86189feeb07df39802bfe3ea65bfe2 /src
parentcc1f70155706873db7fe67f2466e302b4496f5fc (diff)
downloadsssd-dd9651c395bbba72443a31d17a767be60581da2c.tar.gz
sssd-dd9651c395bbba72443a31d17a767be60581da2c.tar.xz
sssd-dd9651c395bbba72443a31d17a767be60581da2c.zip
LDAP: Qualify user and group names when saving the sudo users
If the sudoUser values we fetch from LDAP correspond to a user or a group name per: http://www.sudo.ws/man/1.8.14/sudoers.ldap.man.html then we parse the usernames into (name,domain) tuples and store them qualified. This patch not only makes the sudo provider work with qualified names, but also makes it possible to use qualified names on the LDAP side, allowing for example AD users from different domains to access sudo rules.
Diffstat (limited to 'src')
-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 de26ff19f..bf668f5fd 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
*