summaryrefslogtreecommitdiffstats
path: root/server/db
diff options
context:
space:
mode:
authorSimo Sorce <ssorce@redhat.com>2009-09-03 19:29:41 -0400
committerStephen Gallagher <sgallagh@redhat.com>2009-09-08 15:10:50 -0400
commit28d9dcbeabdf919506fe59e9d1cbed84fbd6e649 (patch)
tree3d5d878b1adc0ec8af94a52359d219689c763bd8 /server/db
parentaef967dc115c64f0288b8ecc3ff1d927aa42af70 (diff)
downloadsssd-28d9dcbeabdf919506fe59e9d1cbed84fbd6e649.tar.gz
sssd-28d9dcbeabdf919506fe59e9d1cbed84fbd6e649.tar.xz
sssd-28d9dcbeabdf919506fe59e9d1cbed84fbd6e649.zip
Split database in multiple files
The special persistent local database retains the original name. All other backends now have their own cache-NAME.ldb file.
Diffstat (limited to 'server/db')
-rw-r--r--server/db/sysdb.c793
-rw-r--r--server/db/sysdb.h18
-rw-r--r--server/db/sysdb_private.h28
3 files changed, 663 insertions, 176 deletions
diff --git a/server/db/sysdb.c b/server/db/sysdb.c
index 90482b52a..d4f257977 100644
--- a/server/db/sysdb.c
+++ b/server/db/sysdb.c
@@ -3,7 +3,7 @@
System Database
- Copyright (C) Simo Sorce <ssorce@redhat.com> 2008
+ Copyright (C) Simo Sorce <ssorce@redhat.com> 2008
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -565,145 +565,26 @@ void sysdb_operation_done(struct sysdb_handle *handle)
/* =Initialization======================================================== */
-static int sysdb_read_var(TALLOC_CTX *mem_ctx,
- struct confdb_ctx *cdb,
- const char *name,
- const char *def_value,
- char **target)
+static int sysdb_get_db_file(TALLOC_CTX *mem_ctx,
+ struct sss_domain_info *domain,
+ const char *base_path, char **_ldb_file)
{
- int ret;
- char **values;
-
- ret = confdb_get_param(cdb, mem_ctx,
- SYSDB_CONF_SECTION,
- name, &values);
- if (ret != EOK)
- return ret;
-
- if (values[0])
- *target = values[0];
- else
- *target = talloc_strdup(mem_ctx, def_value);
+ char *ldb_file;
- return EOK;
-}
-
-static int sysdb_get_db_path(TALLOC_CTX *mem_ctx,
- struct confdb_ctx *cdb,
- char **db_path)
-{
- TALLOC_CTX *tmp_ctx;
- char *default_ldb_path;
- char *path;
- int ret;
-
- tmp_ctx = talloc_new(mem_ctx);
- if (!tmp_ctx)
- return ENOMEM;
-
- default_ldb_path = talloc_asprintf(tmp_ctx, "%s/%s", DB_PATH, SYSDB_FILE);
- if (default_ldb_path == NULL) {
- ret = ENOMEM;
- goto done;
+ /* special case for the local domain */
+ if (strcasecmp(domain->provider, "local") == 0) {
+ ldb_file = talloc_asprintf(mem_ctx, "%s/"LOCAL_SYSDB_FILE,
+ base_path);
+ } else {
+ ldb_file = talloc_asprintf(mem_ctx, "%s/"CACHE_SYSDB_FILE,
+ base_path, domain->name);
}
-
- sysdb_read_var(tmp_ctx, cdb, "ldbFile",
- default_ldb_path, &path);
-
- *db_path = talloc_steal(mem_ctx, path);
- ret = EOK;
-
-done:
- talloc_free(tmp_ctx);
- return ret;
-}
-
-static int sysdb_upgrade_01(struct sysdb_ctx *ctx, const char **ver);
-
-static int sysdb_check_init(struct sysdb_ctx *ctx)
-{
- TALLOC_CTX *tmp_ctx;
- const char *base_ldif;
- struct ldb_ldif *ldif;
- struct ldb_message_element *el;
- struct ldb_result *res;
- struct ldb_dn *verdn;
- const char *version = NULL;
- int ret;
-
- tmp_ctx = talloc_new(ctx);
- if (!tmp_ctx)
+ if (!ldb_file) {
return ENOMEM;
-
- verdn = ldb_dn_new(tmp_ctx, ctx->ldb, "cn=sysdb");
- if (!verdn) {
- ret = EIO;
- goto done;
- }
-
- ret = ldb_search(ctx->ldb, tmp_ctx, &res,
- verdn, LDB_SCOPE_BASE,
- NULL, NULL);
- if (ret != LDB_SUCCESS) {
- ret = EIO;
- goto done;
- }
- if (res->count > 1) {
- ret = EIO;
- goto done;
- }
-
- if (res->count == 1) {
- el = ldb_msg_find_element(res->msgs[0], "version");
- if (el) {
- if (el->num_values != 1) {
- ret = EINVAL;
- goto done;
- }
- version = talloc_strndup(tmp_ctx,
- (char *)(el->values[0].data),
- el->values[0].length);
- if (!version) {
- ret = ENOMEM;
- goto done;
- }
-
- if (strcmp(version, SYSDB_VERSION_0_1) == 0) {
- /* convert database */
- ret = sysdb_upgrade_01(ctx, &version);
- if (ret != EOK) goto done;
- }
-
- if (strcmp(version, SYSDB_VERSION) == 0) {
- /* all fine, return */
- ret = EOK;
- goto done;
- }
- }
-
- DEBUG(0,("Unknown DB version [%s], expected [%s], aborting!\n",
- version?version:"not found", SYSDB_VERSION));
- ret = EINVAL;
- goto done;
- }
-
- /* cn=sysdb does not exists, means db is empty, populate */
- base_ldif = SYSDB_BASE_LDIF;
- while ((ldif = ldb_ldif_read_string(ctx->ldb, &base_ldif))) {
- ret = ldb_add(ctx->ldb, ldif->msg);
- if (ret != LDB_SUCCESS) {
- DEBUG(0, ("Failed to inizialiaze DB (%d,[%s]), aborting!\n",
- ret, ldb_errstring(ctx->ldb)));
- ret = EIO;
- goto done;
- }
- ldb_ldif_read_free(ctx->ldb, ldif);
}
- ret = EOK;
-done:
- talloc_free(tmp_ctx);
- return ret;
+ *_ldb_file = ldb_file;
+ return EOK;
}
/* serach all groups that have a memberUid attribute.
@@ -837,7 +718,7 @@ static int sysdb_upgrade_01(struct sysdb_ctx *ctx, const char **ver)
ret = ENOMEM;
goto done;
}
- ret = ldb_msg_add_string(msg, "version", "0.2");
+ ret = ldb_msg_add_string(msg, "version", SYSDB_VERSION_0_2);
if (ret != LDB_SUCCESS) {
ret = ENOMEM;
goto done;
@@ -866,62 +747,654 @@ done:
return ret;
}
-int sysdb_init(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct confdb_ctx *cdb,
- const char *alt_db_path,
- struct sysdb_ctx **_ctx)
+static int sysdb_upgrade_02(struct confdb_ctx *cdb,
+ struct tevent_context *ev,
+ struct sysdb_ctx *local,
+ struct sysdb_ctx_list *list)
{
+ TALLOC_CTX *tmp_ctx;
struct sysdb_ctx *ctx;
- int ret;
-
- if (!ev) return EINVAL;
+ struct ldb_message_element *el;
+ struct ldb_message *msg;
+ struct ldb_result *res;
+ struct ldb_dn *basedn;
+ const char *version;
+ bool loc_trans = false;
+ bool ctx_trans = false;
+ int ret, i, j;
- ctx = talloc_zero(mem_ctx, struct sysdb_ctx);
- if (!ctx) {
+ tmp_ctx = talloc_new(list);
+ if (!tmp_ctx) {
return ENOMEM;
}
- ctx->ev = ev;
- if (!alt_db_path) {
- ret = sysdb_get_db_path(ctx, cdb, &ctx->ldb_file);
- if (ret != EOK) {
- return ret;
+ /* first check local has the expected version for an upgrade */
+
+ basedn = ldb_dn_new(tmp_ctx, local->ldb, "cn=sysdb");
+ if (!basedn) {
+ ret = EIO;
+ goto done;
+ }
+
+ ret = ldb_search(local->ldb, tmp_ctx, &res,
+ basedn, LDB_SCOPE_BASE,
+ NULL, NULL);
+ if (ret != LDB_SUCCESS) {
+ ret = EIO;
+ goto done;
+ }
+ if (res->count != 1) {
+ ret = EIO;
+ goto done;
+ }
+
+ el = ldb_msg_find_element(res->msgs[0], "version");
+ if (el) {
+ if (el->num_values != 1) {
+ ret = EINVAL;
+ goto done;
+ }
+ version = talloc_strndup(tmp_ctx,
+ (char *)(el->values[0].data),
+ el->values[0].length);
+ if (!version) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ if (strcmp(version, SYSDB_VERSION_0_2) != 0) {
+ DEBUG(0,("Wrong DB version [%s],"
+ " expected [%s] for this upgrade!\n",
+ version, SYSDB_VERSION));
+ ret = EINVAL;
+ goto done;
+ }
+ }
+ talloc_zfree(res);
+
+ DEBUG(0, ("UPGRADING DB TO VERSION %s\n", SYSDB_VERSION_0_3));
+
+ /* ldb uses posix locks,
+ * posix is stupid and kills all locks when you close *any* file
+ * descriptor associated to the same file.
+ * Therefore we must close and reopen the ldb file here */
+
+ /* == Backup and reopen ldb == */
+
+ /* close */
+ talloc_zfree(local->ldb);
+
+ /* backup*/
+ ret = backup_file(local->ldb_file, 0);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ /* reopen */
+ local->ldb = ldb_init(local, ev);
+ if (!local->ldb) {
+ return EIO;
+ }
+
+ ret = ldb_set_debug(local->ldb, ldb_debug_messages, NULL);
+ if (ret != LDB_SUCCESS) {
+ return EIO;
+ }
+
+ ret = ldb_connect(local->ldb, local->ldb_file, 0, NULL);
+ if (ret != LDB_SUCCESS) {
+ return EIO;
+ }
+
+ /* open a transaction */
+ ret = ldb_transaction_start(local->ldb);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(1, ("Failed to start ldb transaction! (%d)\n", ret));
+ return EIO;
+ }
+ loc_trans = true;
+
+ /* == Upgrade contents == */
+
+ for (i = 0; i < list->num_dbs; i++) {
+ struct ldb_dn *domain_dn;
+ struct ldb_dn *users_dn;
+ struct ldb_dn *groups_dn;
+
+ ctx = list->dbs[i];
+
+ /* skip local */
+ if (list->dbs[i] == local) continue;
+
+ ret = ldb_transaction_start(ctx->ldb);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(1, ("Failed to start ldb transaction! (%d)\n", ret));
+ ret = EIO;
+ goto done;
+ }
+ ctx_trans = true;
+
+ /* search all entries for this domain in local,
+ * copy them all in the new database,
+ * then remove them from local */
+
+ domain_dn = ldb_dn_new_fmt(tmp_ctx, ctx->ldb,
+ SYSDB_DOM_BASE, ctx->domain->name);
+ if (!domain_dn) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = ldb_search(local->ldb, tmp_ctx, &res,
+ domain_dn, LDB_SCOPE_SUBTREE,
+ NULL, NULL);
+ if (ret != LDB_SUCCESS) {
+ ret = EIO;
+ goto done;
+ }
+
+ users_dn = ldb_dn_new_fmt(tmp_ctx, ctx->ldb,
+ SYSDB_TMPL_USER_BASE, ctx->domain->name);
+ if (!users_dn) {
+ ret = ENOMEM;
+ goto done;
+ }
+ groups_dn = ldb_dn_new_fmt(tmp_ctx, ctx->ldb,
+ SYSDB_TMPL_GROUP_BASE, ctx->domain->name);
+ if (!groups_dn) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ for (j = 0; j < res->count; j++) {
+
+ msg = res->msgs[j];
+
+ /* skip pre-created congtainers */
+ if ((ldb_dn_compare(msg->dn, domain_dn) == 0) ||
+ (ldb_dn_compare(msg->dn, users_dn) == 0) ||
+ (ldb_dn_compare(msg->dn, groups_dn) == 0)) {
+ continue;
+ }
+
+ ret = ldb_add(ctx->ldb, msg);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(0, ("WARNING: Could not add entry %s,"
+ " to new ldb file! (%d [%s])\n",
+ ldb_dn_get_linearized(msg->dn),
+ ret, ldb_errstring(ctx->ldb)));
+ }
+
+ ret = ldb_delete(local->ldb, msg->dn);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(0, ("WARNING: Could not remove entry %s,"
+ " from old ldb file! (%d [%s])\n",
+ ldb_dn_get_linearized(msg->dn),
+ ret, ldb_errstring(local->ldb)));
+ }
+ }
+
+ /* now remove the basic containers from local */
+ /* these were optional so debug at level 9 in case
+ * of failure just for tracing */
+ ret = ldb_delete(local->ldb, groups_dn);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(9, ("WARNING: Could not remove entry %s,"
+ " from old ldb file! (%d [%s])\n",
+ ldb_dn_get_linearized(msg->dn),
+ ret, ldb_errstring(local->ldb)));
+ }
+ ret = ldb_delete(local->ldb, users_dn);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(9, ("WARNING: Could not remove entry %s,"
+ " from old ldb file! (%d [%s])\n",
+ ldb_dn_get_linearized(msg->dn),
+ ret, ldb_errstring(local->ldb)));
+ }
+ ret = ldb_delete(local->ldb, domain_dn);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(9, ("WARNING: Could not remove entry %s,"
+ " from old ldb file! (%d [%s])\n",
+ ldb_dn_get_linearized(msg->dn),
+ ret, ldb_errstring(local->ldb)));
+ }
+
+ ret = ldb_transaction_commit(ctx->ldb);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(1, ("Failed to commit ldb transaction! (%d)\n", ret));
+ ret = EIO;
+ goto done;
+ }
+ ctx_trans = false;
+
+ talloc_zfree(domain_dn);
+ talloc_zfree(groups_dn);
+ talloc_zfree(users_dn);
+ talloc_zfree(res);
+ }
+
+ /* conversion done, upgrade version number */
+ msg = ldb_msg_new(tmp_ctx);
+ if (!msg) {
+ ret = ENOMEM;
+ goto done;
+ }
+ msg->dn = ldb_dn_new(tmp_ctx, local->ldb, "cn=sysdb");
+ if (!msg->dn) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = ldb_msg_add_empty(msg, "version", LDB_FLAG_MOD_REPLACE, NULL);
+ if (ret != LDB_SUCCESS) {
+ ret = ENOMEM;
+ goto done;
+ }
+ ret = ldb_msg_add_string(msg, "version", SYSDB_VERSION_0_3);
+ if (ret != LDB_SUCCESS) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = ldb_modify(local->ldb, msg);
+ if (ret != LDB_SUCCESS) {
+ ret = sysdb_error_to_errno(ret);
+ goto done;
+ }
+
+ ret = ldb_transaction_commit(local->ldb);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(1, ("Failed to commit ldb transaction! (%d)\n", ret));
+ ret = EIO;
+ goto done;
+ }
+ loc_trans = false;
+
+ ret = EOK;
+
+done:
+ if (ret != EOK) {
+ if (ctx_trans) {
+ ret = ldb_transaction_cancel(ctx->ldb);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(1, ("Failed to cancel ldb transaction! (%d)\n", ret));
+ }
+ }
+ if (loc_trans) {
+ ret = ldb_transaction_cancel(local->ldb);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(1, ("Failed to cancel ldb transaction! (%d)\n", ret));
+ }
}
- } else {
- ctx->ldb_file = talloc_strdup(ctx, alt_db_path);
}
- if (ctx->ldb_file == NULL) {
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
+
+static int sysdb_domain_init_internal(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sss_domain_info *domain,
+ const char *db_path,
+ bool allow_upgrade,
+ struct sysdb_ctx **_ctx,
+ bool *need_02_upgrade)
+{
+ TALLOC_CTX *tmp_ctx = NULL;
+ struct sysdb_ctx *ctx;
+ const char *base_ldif;
+ struct ldb_ldif *ldif;
+ struct ldb_message *msg;
+ struct ldb_message_element *el;
+ struct ldb_result *res;
+ struct ldb_dn *verdn;
+ const char *version = NULL;
+ int ret;
+
+ ctx = talloc_zero(mem_ctx, struct sysdb_ctx);
+ if (!ctx) {
return ENOMEM;
}
+ ctx->ev = ev;
+ ctx->domain = domain;
- DEBUG(3, ("DB Path is: %s\n", ctx->ldb_file));
+ ret = sysdb_get_db_file(ctx, domain, db_path, &ctx->ldb_file);
+ if (ret != EOK) {
+ return ret;
+ }
+ DEBUG(5, ("DB File for %s: %s\n", domain->name, ctx->ldb_file));
ctx->ldb = ldb_init(ctx, ev);
if (!ctx->ldb) {
- talloc_free(ctx);
return EIO;
}
ret = ldb_set_debug(ctx->ldb, ldb_debug_messages, NULL);
if (ret != LDB_SUCCESS) {
- talloc_free(ctx);
return EIO;
}
ret = ldb_connect(ctx->ldb, ctx->ldb_file, 0, NULL);
if (ret != LDB_SUCCESS) {
- talloc_free(ctx);
return EIO;
}
- ret = sysdb_check_init(ctx);
+ tmp_ctx = talloc_new(ctx);
+ if (!tmp_ctx) {
+ return ENOMEM;
+ }
+
+ verdn = ldb_dn_new(tmp_ctx, ctx->ldb, "cn=sysdb");
+ if (!verdn) {
+ ret = EIO;
+ goto done;
+ }
+
+ ret = ldb_search(ctx->ldb, tmp_ctx, &res,
+ verdn, LDB_SCOPE_BASE,
+ NULL, NULL);
+ if (ret != LDB_SUCCESS) {
+ ret = EIO;
+ goto done;
+ }
+ if (res->count > 1) {
+ ret = EIO;
+ goto done;
+ }
+
+ if (res->count == 1) {
+ el = ldb_msg_find_element(res->msgs[0], "version");
+ if (el) {
+ if (el->num_values != 1) {
+ ret = EINVAL;
+ goto done;
+ }
+ version = talloc_strndup(tmp_ctx,
+ (char *)(el->values[0].data),
+ el->values[0].length);
+ if (!version) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ if (strcmp(version, SYSDB_VERSION) == 0) {
+ /* all fine, return */
+ ret = EOK;
+ goto done;
+ }
+
+ if (!allow_upgrade) {
+ DEBUG(0, ("Wrong DB version (got %s expected %s)\n",
+ version, SYSDB_VERSION));
+ ret = EINVAL;
+ goto done;
+ }
+
+ if (strcmp(version, SYSDB_VERSION_0_1) == 0) {
+ /* convert database */
+ ret = sysdb_upgrade_01(ctx, &version);
+ if (ret != EOK) goto done;
+ }
+
+ if (strcmp(version, SYSDB_VERSION_0_2) == 0) {
+ /* if this is not local we have a big problem */
+ if (strcasecmp(domain->provider, "local") != 0) {
+ DEBUG(0, ("Fatal: providers other than 'local'"
+ " shouldn't present v0.2, db corrupted?\n"));
+ ret = EFAULT;
+ goto done;
+ }
+
+ /* need to convert database to split files */
+ /* this need to be done later when all domains are set up */
+ if (need_02_upgrade) {
+ *need_02_upgrade = true;
+ } else {
+ DEBUG(0, ("DB file seem to need an upgrade,"
+ " but upgrade flag is not provided,"
+ " db corrupted?\n"));
+ ret = EFAULT;
+ goto done;
+ }
+
+ ret = EOK;
+ goto done;
+ }
+
+ }
+
+ DEBUG(0,("Unknown DB version [%s], expected [%s] for domain %s!\n",
+ version?version:"not found", SYSDB_VERSION, domain->name));
+ ret = EINVAL;
+ goto done;
+ }
+
+ /* cn=sysdb does not exists, means db is empty, populate */
+
+ base_ldif = SYSDB_BASE_LDIF;
+ while ((ldif = ldb_ldif_read_string(ctx->ldb, &base_ldif))) {
+ ret = ldb_add(ctx->ldb, ldif->msg);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(0, ("Failed to initialize DB (%d, [%s]) for domain %s!",
+ ret, ldb_errstring(ctx->ldb), domain->name));
+ ret = EIO;
+ goto done;
+ }
+ ldb_ldif_read_free(ctx->ldb, ldif);
+ }
+
+ /* == create base domain object == */
+
+ msg = ldb_msg_new(tmp_ctx);
+ if (!msg) {
+ ret = ENOMEM;
+ goto done;
+ }
+ msg->dn = ldb_dn_new_fmt(msg, ctx->ldb, SYSDB_DOM_BASE, domain->name);
+ if (!msg->dn) {
+ ret = ENOMEM;
+ goto done;
+ }
+ ret = ldb_msg_add_fmt(msg, "cn", "%s", domain->name);
+ if (ret != LDB_SUCCESS) {
+ ret = EIO;
+ goto done;
+ }
+ /* do a synchronous add */
+ ret = ldb_add(ctx->ldb, msg);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(0, ("Failed to initialize DB (%d, [%s]) for domain %s!",
+ ret, ldb_errstring(ctx->ldb), domain->name));
+ ret = EIO;
+ goto done;
+ }
+ talloc_free(msg);
+
+ /* == create Users tree == */
+
+ msg = ldb_msg_new(tmp_ctx);
+ if (!msg) {
+ ret = ENOMEM;
+ goto done;
+ }
+ msg->dn = ldb_dn_new_fmt(msg, ctx->ldb,
+ SYSDB_TMPL_USER_BASE, domain->name);
+ if (!msg->dn) {
+ ret = ENOMEM;
+ goto done;
+ }
+ ret = ldb_msg_add_fmt(msg, "cn", "Users");
+ if (ret != LDB_SUCCESS) {
+ ret = EIO;
+ goto done;
+ }
+ /* do a synchronous add */
+ ret = ldb_add(ctx->ldb, msg);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(0, ("Failed to initialize DB (%d, [%s]) for domain %s!",
+ ret, ldb_errstring(ctx->ldb), domain->name));
+ ret = EIO;
+ goto done;
+ }
+ talloc_free(msg);
+
+ /* == create Groups tree == */
+
+ msg = ldb_msg_new(tmp_ctx);
+ if (!msg) {
+ ret = ENOMEM;
+ goto done;
+ }
+ msg->dn = ldb_dn_new_fmt(msg, ctx->ldb,
+ SYSDB_TMPL_GROUP_BASE, domain->name);
+ if (!msg->dn) {
+ ret = ENOMEM;
+ goto done;
+ }
+ ret = ldb_msg_add_fmt(msg, "cn", "Groups");
+ if (ret != LDB_SUCCESS) {
+ ret = EIO;
+ goto done;
+ }
+ /* do a synchronous add */
+ ret = ldb_add(ctx->ldb, msg);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(0, ("Failed to initialize DB (%d, [%s]) for domain %s!",
+ ret, ldb_errstring(ctx->ldb), domain->name));
+ ret = EIO;
+ goto done;
+ }
+ talloc_free(msg);
+
+ ret = EOK;
+
+done:
+ if (ret == EOK) {
+ *_ctx = ctx;
+ }
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
+int sysdb_init(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct confdb_ctx *cdb,
+ const char *alt_db_path,
+ bool allow_upgrade,
+ struct sysdb_ctx_list **_ctx_list)
+{
+ struct sysdb_ctx_list *ctx_list;
+ struct sss_domain_info *domains, *dom;
+ struct sysdb_ctx *ctx;
+ bool upgrade_02 = false;
+ int ret;
+
+ if (!ev) return EINVAL;
+
+ ctx_list = talloc_zero(mem_ctx, struct sysdb_ctx_list);
+ if (!ctx_list) {
+ return ENOMEM;
+ }
+
+ if (alt_db_path) {
+ ctx_list->db_path = talloc_strdup(ctx_list, alt_db_path);
+ } else {
+ ctx_list->db_path = talloc_strdup(ctx_list, DB_PATH);
+ }
+ if (!ctx_list->db_path) {
+ talloc_zfree(ctx_list);
+ return ENOMEM;
+ }
+
+ /* open a db for each backend */
+ ret = confdb_get_domains(cdb, &domains);
if (ret != EOK) {
- talloc_free(ctx);
+ talloc_zfree(ctx_list);
return ret;
}
- *_ctx = ctx;
+ for (dom = domains; dom; dom = dom->next) {
+
+ ctx_list->dbs = talloc_realloc(ctx_list, ctx_list->dbs,
+ struct sysdb_ctx *,
+ ctx_list->num_dbs + 1);
+ if (!ctx_list->dbs) {
+ talloc_zfree(ctx_list);
+ return ENOMEM;
+ }
+
+ ret = sysdb_domain_init_internal(ctx_list, ev, dom,
+ ctx_list->db_path,
+ allow_upgrade,
+ &ctx, &upgrade_02);
+ if (ret != EOK) {
+ talloc_zfree(ctx_list);
+ return ret;
+ }
+
+ ctx_list->dbs[ctx_list->num_dbs] = ctx;
+ ctx_list->num_dbs++;
+ }
+ if (ctx_list->num_dbs == 0) {
+ /* what? .. */
+ talloc_zfree(ctx_list);
+ return ENOENT;
+ }
+
+ if (upgrade_02) {
+ ret = confdb_get_domain(cdb, "local", &dom);
+ if (ret != EOK) {
+ talloc_zfree(ctx_list);
+ return ret;
+ }
+ ret = sysdb_get_ctx_from_list(ctx_list, dom, &ctx);
+ if (ret != EOK) {
+ talloc_zfree(ctx_list);
+ return ret;
+ }
+
+ ret = sysdb_upgrade_02(cdb, ev, ctx, ctx_list);
+ if (ret != EOK) {
+ DEBUG(0, ("FATAL: Upgrade form db version %d failed!\n",
+ SYSDB_VERSION_0_2));
+ DEBUG(0, ("You can find a backup of the database here: %s\n",
+ backup_file));
+ talloc_zfree(ctx_list);
+ return ret;
+ }
+ }
+
+ *_ctx_list = ctx_list;
return EOK;
}
+
+int sysdb_domain_init(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sss_domain_info *domain,
+ const char *db_path,
+ struct sysdb_ctx **_ctx)
+{
+ return sysdb_domain_init_internal(mem_ctx, ev, domain,
+ db_path, false, _ctx, NULL);
+}
+
+int sysdb_get_ctx_from_list(struct sysdb_ctx_list *ctx_list,
+ struct sss_domain_info *domain,
+ struct sysdb_ctx **ctx)
+{
+ int i;
+
+ for (i = 0; i < ctx_list->num_dbs; i++) {
+ if (ctx_list->dbs[i]->domain == domain) {
+ *ctx = ctx_list->dbs[i];
+ return EOK;
+ }
+ if (strcasecmp(ctx_list->dbs[i]->domain->name, domain->name) == 0) {
+ *ctx = ctx_list->dbs[i];
+ return EOK;
+ }
+ }
+ /* definitely not found */
+ return ENOENT;
+}
diff --git a/server/db/sysdb.h b/server/db/sysdb.h
index 3d75f507e..2d8b3eaea 100644
--- a/server/db/sysdb.h
+++ b/server/db/sysdb.h
@@ -26,7 +26,8 @@
#include <tevent.h>
#define SYSDB_CONF_SECTION "config/sysdb"
-#define SYSDB_FILE "sssd.ldb"
+#define CACHE_SYSDB_FILE "cache_%s.ldb"
+#define LOCAL_SYSDB_FILE "sssd.ldb"
#define SYSDB_BASE "cn=sysdb"
#define SYSDB_DOM_BASE "cn=%s,cn=sysdb"
@@ -137,6 +138,7 @@
#define SYSDB_MOD_REP LDB_FLAG_MOD_REPLACE
struct confdb_ctx;
+struct sysdb_ctx_list;
struct sysdb_ctx;
struct sysdb_handle;
@@ -215,7 +217,19 @@ int sysdb_init(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct confdb_ctx *cdb,
const char *alt_db_path,
- struct sysdb_ctx **dbctx);
+ bool allow_upgrade,
+ struct sysdb_ctx_list **_ctx_list);
+/* used to initialize only one domain database.
+ * Do NOT use if sysdb_init has already been called */
+int sysdb_domain_init(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sss_domain_info *domain,
+ const char *db_path,
+ struct sysdb_ctx **_ctx);
+
+int sysdb_get_ctx_from_list(struct sysdb_ctx_list *ctx_list,
+ struct sss_domain_info *domain,
+ struct sysdb_ctx **_ctx);
/* FIXME: REMOVE */
typedef void (*sysdb_callback_t)(void *, int, struct ldb_result *);
diff --git a/server/db/sysdb_private.h b/server/db/sysdb_private.h
index d8b66cd77..e380c8278 100644
--- a/server/db/sysdb_private.h
+++ b/server/db/sysdb_private.h
@@ -23,7 +23,9 @@
#ifndef __INT_SYS_DB_H__
#define __INT_SYS_DB_H__
-#define SYSDB_VERSION "0.2"
+#define SYSDB_VERSION "0.3"
+#define SYSDB_VERSION_0_3 "0.3"
+#define SYSDB_VERSION_0_2 "0.2"
#define SYSDB_VERSION_0_1 "0.1"
#define SYSDB_BASE_LDIF \
@@ -50,20 +52,8 @@
"\n" \
"dn: cn=sysdb\n" \
"cn: sysdb\n" \
- "version: 0.2\n" \
+ "version: " SYSDB_VERSION "\n" \
"description: base object\n" \
- "\n" \
- "dn: cn=LOCAL,cn=sysdb\n" \
- "cn: local\n" \
- "description: Local system data\n" \
- "\n" \
- "dn: cn=Users,cn=LOCAL,cn=sysdb\n" \
- "cn: users\n" \
- "description: Local POSIX users\n" \
- "\n" \
- "dn: cn=Groups,cn=LOCAL,cn=sysdb\n" \
- "cn: groups\n" \
- "description: Local POSIX groups\n" \
"\n"
#include "db/sysdb.h"
@@ -80,12 +70,22 @@ struct sysdb_handle {
struct sysdb_ctx {
struct tevent_context *ev;
+
+ struct sss_domain_info *domain;
+
struct ldb_context *ldb;
char *ldb_file;
struct sysdb_handle *queue;
};
+struct sysdb_ctx_list {
+ struct sysdb_ctx **dbs;
+ size_t num_dbs;
+
+ char *db_path;
+};
+
/* An operation blocks the transaction queue as well, but does not
* start a transaction, normally useful only for search type calls.
* do *NOT* call within a transaction you'll deadlock sysdb.