summaryrefslogtreecommitdiffstats
path: root/src/confdb
diff options
context:
space:
mode:
Diffstat (limited to 'src/confdb')
-rw-r--r--src/confdb/confdb.c288
-rw-r--r--src/confdb/confdb.h4
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