diff options
author | Jakub Hrozek <jhrozek@redhat.com> | 2017-03-27 09:48:46 +0200 |
---|---|---|
committer | Jakub Hrozek <jhrozek@redhat.com> | 2017-03-30 14:09:10 +0200 |
commit | 825e8bf2f73a815c2eceb36ae805145fcbacf74d (patch) | |
tree | 8456d4851d62d582d64961a8939708ff13c2a051 /src/confdb | |
parent | 6324eaf1fb321c41ca9883966118df6d45259b7e (diff) | |
download | sssd-825e8bf2f73a815c2eceb36ae805145fcbacf74d.tar.gz sssd-825e8bf2f73a815c2eceb36ae805145fcbacf74d.tar.xz sssd-825e8bf2f73a815c2eceb36ae805145fcbacf74d.zip |
CONFDB: Allow configuring [application] sections as non-POSIX domains
Related to:
https://pagure.io/SSSD/sssd/issue/3310
Allows to add a new section:
[application/$name]
This section internally (on the confdb level) expands to:
[domain/$name]
domain_type = application
The reasons to add this new section is two-fold. One, to make the
configuration of application domains more explicit and two, to make it
possible to share configuration between two domains, one POSIX and one
non-POSIX by application domain's inherit_from option:
[application/$name]
inherit_from = posix_domain_name
Reviewed-by: Sumit Bose <sbose@redhat.com>
Reviewed-by: Pavel Březina <pbrezina@redhat.com>
Diffstat (limited to 'src/confdb')
-rw-r--r-- | src/confdb/confdb.c | 288 | ||||
-rw-r--r-- | src/confdb/confdb.h | 4 |
2 files changed, 275 insertions, 17 deletions
diff --git a/src/confdb/confdb.c b/src/confdb/confdb.c index 70a1eb7b2..88e114457 100644 --- a/src/confdb/confdb.c +++ b/src/confdb/confdb.c @@ -813,6 +813,50 @@ done: return ret; } +static int confdb_get_domain_section(TALLOC_CTX *mem_ctx, + struct confdb_ctx *cdb, + const char *section, + const char *name, + struct ldb_result **_res) +{ + TALLOC_CTX *tmp_ctx; + int ret; + struct ldb_result *res; + struct ldb_dn *dn; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + return ENOMEM; + } + + dn = ldb_dn_new_fmt(tmp_ctx, cdb->ldb, "cn=%s,%s", name, section); + if (dn == NULL) { + ret = ENOMEM; + goto done; + } + + ret = ldb_search(cdb->ldb, tmp_ctx, &res, dn, + LDB_SCOPE_BASE, NULL, NULL); + if (ret != LDB_SUCCESS) { + ret = sysdb_error_to_errno(ret); + goto done; + } + + if (res->count == 0) { + ret = ENOENT; + goto done; + } else if (res->count > 1) { + ret = E2BIG; + goto done; + } + + *_res = talloc_steal(mem_ctx, res); + ret = EOK; +done: + talloc_free(tmp_ctx); + return ret; +} + static int confdb_get_domain_internal(struct confdb_ctx *cdb, TALLOC_CTX *mem_ctx, const char *name, @@ -821,7 +865,6 @@ static int confdb_get_domain_internal(struct confdb_ctx *cdb, struct sss_domain_info *domain; struct ldb_result *res; TALLOC_CTX *tmp_ctx; - struct ldb_dn *dn; const char *tmp; int ret, val; uint32_t entry_cache_timeout; @@ -833,23 +876,15 @@ static int confdb_get_domain_internal(struct confdb_ctx *cdb, tmp_ctx = talloc_new(mem_ctx); if (!tmp_ctx) return ENOMEM; - dn = ldb_dn_new_fmt(tmp_ctx, cdb->ldb, - "cn=%s,%s", name, CONFDB_DOMAIN_BASEDN); - if (!dn) { - ret = ENOMEM; - goto done; - } - - ret = ldb_search(cdb->ldb, tmp_ctx, &res, dn, - LDB_SCOPE_BASE, NULL, NULL); - if (ret != LDB_SUCCESS) { - ret = EIO; - goto done; - } - - if (res->count != 1) { + ret = confdb_get_domain_section(tmp_ctx, cdb, CONFDB_DOMAIN_BASEDN, + name, &res); + if (ret == ENOENT) { DEBUG(SSSDBG_FATAL_FAILURE, "Unknown domain [%s]\n", name); - ret = ENOENT; + goto done; + } else if (ret != EOK) { + DEBUG(SSSDBG_FATAL_FAILURE, + "Error %d: %s while retrieving %s\n", + ret, sss_strerror(ret), name); goto done; } @@ -1841,3 +1876,222 @@ int confdb_ensure_files_domain(struct confdb_ctx *cdb, return activate_files_domain(cdb, implicit_files_dom_name); #endif /* ADD_FILES_DOMAIN */ } + +static int confdb_get_parent_domain(TALLOC_CTX *mem_ctx, + const char *name, + struct confdb_ctx *cdb, + struct ldb_result *app_dom, + struct ldb_result **_parent_dom) +{ + const char *inherit_from; + + inherit_from = ldb_msg_find_attr_as_string(app_dom->msgs[0], + CONFDB_DOMAIN_INHERIT_FROM, NULL); + if (inherit_from == NULL) { + DEBUG(SSSDBG_CONF_SETTINGS, + "%s does not inherit from any POSIX domain\n", name); + *_parent_dom = NULL; + return EOK; + } + + return confdb_get_domain_section(mem_ctx, cdb, + CONFDB_DOMAIN_BASEDN, inherit_from, + _parent_dom); +} + +static int confdb_add_app_domain(TALLOC_CTX *mem_ctx, + struct confdb_ctx *cdb, + const char *name) +{ + char *cdb_path = NULL; + const char *val[2] = { NULL, NULL }; + int ret; + + cdb_path = talloc_asprintf(mem_ctx, CONFDB_DOMAIN_PATH_TMPL, name); + if (cdb_path == NULL) { + return ENOMEM; + } + + val[0] = CONFDB_DOMAIN_TYPE_APP; + ret = confdb_add_param(cdb, true, cdb_path, CONFDB_DOMAIN_TYPE, val); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to add id_provider [%d]: %s\n", + ret, sss_strerror(ret)); + return ret; + } + + return EOK; +} + +static int confdb_merge_parent_domain(const char *name, + struct confdb_ctx *cdb, + struct ldb_result *app_section) +{ + int ret; + int ldb_flag; + struct ldb_result *parent_domain = NULL; + struct ldb_message *replace_msg = NULL; + struct ldb_message *app_msg = NULL; + struct ldb_dn *domain_dn; + TALLOC_CTX *tmp_ctx = NULL; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n"); + return ENOMEM; + } + + domain_dn = ldb_dn_new_fmt(tmp_ctx, + cdb->ldb, + "%s=%s,%s", + CONFDB_DOMAIN_ATTR, + name, + CONFDB_DOMAIN_BASEDN); + if (domain_dn == NULL) { + ret = ENOMEM; + goto done; + } + + /* Copy the parent domain parameters */ + ret = confdb_get_parent_domain(tmp_ctx, name, cdb, + app_section, &parent_domain); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "Cannot retrieve the parent domain [%d]: %s\n", + ret, sss_strerror(ret)); + goto done; + } + + if (parent_domain != NULL) { + replace_msg = ldb_msg_copy(tmp_ctx, parent_domain->msgs[0]); + if (replace_msg == NULL) { + ret = ENOMEM; + goto done; + } + replace_msg->dn = domain_dn; + + for (unsigned i = 0; i < replace_msg->num_elements; i++) { + replace_msg->elements[i].flags = LDB_FLAG_MOD_ADD; + } + + ret = ldb_modify(cdb->ldb, replace_msg); + if (ret != LDB_SUCCESS) { + ret = sysdb_error_to_errno(ret); + DEBUG(SSSDBG_OP_FAILURE, + "Inheriting options from parent domain failed [%d]: %s\n", + ret, sss_strerror(ret)); + goto done; + } + } + + /* Finally, add any app-domain specific overrides */ + app_msg = ldb_msg_new(tmp_ctx); + if (app_msg == NULL) { + ret = ENOMEM; + goto done; + } + app_msg->dn = domain_dn; + + for (unsigned i = 0; i < app_section->msgs[0]->num_elements; i++) { + struct ldb_message_element *el = NULL; + + if (replace_msg != NULL) { + el = ldb_msg_find_element(replace_msg, + app_section->msgs[0]->elements[i].name); + if (el == NULL) { + /* Adding an element */ + ldb_flag = LDB_FLAG_MOD_ADD; + } else { + /* Overriding an element */ + ldb_flag = LDB_FLAG_MOD_REPLACE; + } + } else { + /* If there was no domain to inherit from, just add all */ + ldb_flag = LDB_FLAG_MOD_ADD; + } + + ret = ldb_msg_add(app_msg, + &app_section->msgs[0]->elements[i], + ldb_flag); + if (ret != EOK) { + continue; + } + } + + ret = ldb_modify(cdb->ldb, app_msg); + if (ret != LDB_SUCCESS) { + ret = sysdb_error_to_errno(ret); + DEBUG(SSSDBG_OP_FAILURE, + "Adding app-specific options failed [%d]: %s\n", + ret, sss_strerror(ret)); + goto done; + } + + DEBUG(SSSDBG_TRACE_LIBS, "Added a domain section for %s\n", name); + ret = EOK; +done: + talloc_free(tmp_ctx); + return ret; +} + +int confdb_expand_app_domains(struct confdb_ctx *cdb) +{ + int ret; + char **domlist; + TALLOC_CTX *tmp_ctx; + struct ldb_result *app_domain = NULL; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + return ENOMEM; + } + + ret = confdb_get_string_as_list(cdb, tmp_ctx, + CONFDB_MONITOR_CONF_ENTRY, + CONFDB_MONITOR_ACTIVE_DOMAINS, + &domlist); + if (ret == ENOENT) { + DEBUG(SSSDBG_FATAL_FAILURE, "No domains configured, fatal error!\n"); + goto done; + } else if (ret != EOK ) { + DEBUG(SSSDBG_FATAL_FAILURE, "Fatal error retrieving domains list!\n"); + goto done; + } + + for (int i = 0; domlist[i]; i++) { + ret = confdb_get_domain_section(tmp_ctx, cdb, + CONFDB_APP_DOMAIN_BASEDN, domlist[i], + &app_domain); + if (ret == ENOENT) { + DEBUG(SSSDBG_TRACE_INTERNAL, + "%s is not an app domain\n", domlist[i]); + continue; + } else if (ret != EOK) { + DEBUG(SSSDBG_FATAL_FAILURE, + "Error %d: %s while retrieving %s\n", + ret, sss_strerror(ret), domlist[i]); + goto done; + } + + ret = confdb_add_app_domain(tmp_ctx, cdb, domlist[i]); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "Cannot add the app domain section [%d]: %s\n", + ret, sss_strerror(ret)); + goto done; + } + + ret = confdb_merge_parent_domain(domlist[i], cdb, app_domain); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "Cannot add options into the app domain section [%d]: %s\n", + ret, sss_strerror(ret)); + goto done; + } + } + + ret = EOK; +done: + talloc_free(tmp_ctx); + return ret; +} diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h index a4046610f..5a8d377c3 100644 --- a/src/confdb/confdb.h +++ b/src/confdb/confdb.h @@ -164,6 +164,7 @@ /* Domains */ #define CONFDB_DOMAIN_PATH_TMPL "config/domain/%s" #define CONFDB_DOMAIN_BASEDN "cn=domain,cn=config" +#define CONFDB_APP_DOMAIN_BASEDN "cn=application,cn=config" #define CONFDB_DOMAIN_ID_PROVIDER "id_provider" #define CONFDB_DOMAIN_AUTH_PROVIDER "auth_provider" #define CONFDB_DOMAIN_ACCESS_PROVIDER "access_provider" @@ -212,6 +213,7 @@ #define CONFDB_DOMAIN_TYPE "domain_type" #define CONFDB_DOMAIN_TYPE_POSIX "posix" #define CONFDB_DOMAIN_TYPE_APP "application" +#define CONFDB_DOMAIN_INHERIT_FROM "inherit_from" /* Local Provider */ #define CONFDB_LOCAL_DEFAULT_SHELL "default_shell" @@ -398,6 +400,8 @@ int confdb_get_domains(struct confdb_ctx *cdb, int confdb_ensure_files_domain(struct confdb_ctx *cdb, const char *implicit_files_dom_name); +int confdb_expand_app_domains(struct confdb_ctx *cdb); + /** * Get a null-terminated linked-list of all domain names * @param[in] mem_ctx The parent memory context for the value list |