From 28d9dcbeabdf919506fe59e9d1cbed84fbd6e649 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Thu, 3 Sep 2009 19:29:41 -0400 Subject: 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. --- server/Makefile.am | 1 + server/confdb/confdb.c | 52 +- server/confdb/confdb.h | 2 - server/confdb/confdb_private.h | 2 + server/db/sysdb.c | 793 +++++++++++++++++++++++------ server/db/sysdb.h | 18 +- server/db/sysdb_private.h | 28 +- server/monitor/monitor.c | 17 +- server/providers/data_provider_be.c | 4 +- server/responder/common/responder.h | 2 +- server/responder/common/responder_common.c | 4 +- server/responder/nss/nsssrv_cmd.c | 205 +++++++- server/responder/pam/pam_LOCAL_domain.c | 8 +- server/responder/pam/pamsrv_cache.c | 9 +- server/responder/pam/pamsrv_cmd.c | 29 +- server/tests/sysdb-tests.c | 127 ++--- server/tools/sss_groupadd.c | 10 +- server/tools/sss_groupdel.c | 12 +- server/tools/sss_groupmod.c | 18 +- server/tools/sss_useradd.c | 16 +- server/tools/sss_userdel.c | 12 +- server/tools/sss_usermod.c | 18 +- server/tools/tools_util.c | 4 +- server/tools/tools_util.h | 3 +- server/util/backup_file.c | 122 +++++ server/util/util.h | 3 + 26 files changed, 1184 insertions(+), 335 deletions(-) create mode 100644 server/util/backup_file.c diff --git a/server/Makefile.am b/server/Makefile.am index e1f7f3bc..e7885b37 100644 --- a/server/Makefile.am +++ b/server/Makefile.am @@ -159,6 +159,7 @@ SSSD_UTIL_OBJ = \ util/server.c \ util/signal.c \ util/usertools.c \ + util/backup_file.c \ $(SSSD_DEBUG_OBJ) SSSD_RESPONDER_OBJ = \ diff --git a/server/confdb/confdb.c b/server/confdb/confdb.c index 72e5eeb4..7d89f75f 100644 --- a/server/confdb/confdb.c +++ b/server/confdb/confdb.c @@ -673,10 +673,10 @@ int confdb_init(TALLOC_CTX *mem_ctx, return EOK; } -int confdb_get_domain(struct confdb_ctx *cdb, - TALLOC_CTX *mem_ctx, - const char *name, - struct sss_domain_info **_domain) +static int confdb_get_domain_internal(struct confdb_ctx *cdb, + TALLOC_CTX *mem_ctx, + const char *name, + struct sss_domain_info **_domain) { struct sss_domain_info *domain; struct ldb_result *res; @@ -803,16 +803,19 @@ done: } int confdb_get_domains(struct confdb_ctx *cdb, - TALLOC_CTX *mem_ctx, struct sss_domain_info **domains) { TALLOC_CTX *tmp_ctx; struct sss_domain_info *domain, *prevdom = NULL; - struct sss_domain_info *first = NULL; char **domlist; int ret, i; - tmp_ctx = talloc_new(mem_ctx); + if (cdb->doms) { + *domains = cdb->doms; + return EOK; + } + + tmp_ctx = talloc_new(NULL); if (!tmp_ctx) return ENOMEM; ret = confdb_get_string_as_list(cdb, tmp_ctx, @@ -827,7 +830,7 @@ int confdb_get_domains(struct confdb_ctx *cdb, } for (i = 0; domlist[i]; i++) { - ret = confdb_get_domain(cdb, mem_ctx, domlist[i], &domain); + ret = confdb_get_domain_internal(cdb, cdb, domlist[i], &domain); if (ret) { DEBUG(0, ("Error (%d [%s]) retrieving domain [%s], skipping!\n", ret, strerror(ret), domlist[i])); @@ -835,23 +838,46 @@ int confdb_get_domains(struct confdb_ctx *cdb, continue; } - if (first == NULL) { - first = domain; - prevdom = first; + if (cdb->doms == NULL) { + cdb->doms = domain; + prevdom = cdb->doms; } else { prevdom->next = domain; prevdom = domain; } } - if (first == NULL) { + if (cdb->doms == NULL) { DEBUG(0, ("No domains configured, fatal error!\n")); ret = ENOENT; } - *domains = first; + *domains = cdb->doms; + ret = EOK; done: talloc_free(tmp_ctx); return ret; } + +int confdb_get_domain(struct confdb_ctx *cdb, + const char *name, + struct sss_domain_info **_domain) +{ + struct sss_domain_info *dom, *doms; + int ret; + + ret = confdb_get_domains(cdb, &doms); + if (ret != EOK) { + return ret; + } + + for (dom = doms; dom; dom = dom->next) { + if (strcasecmp(dom->name, name) == 0) { + *_domain = dom; + return EOK; + } + } + + return ENOENT; +} diff --git a/server/confdb/confdb.h b/server/confdb/confdb.h index f5650887..d325ac8f 100644 --- a/server/confdb/confdb.h +++ b/server/confdb/confdb.h @@ -91,12 +91,10 @@ int confdb_init(TALLOC_CTX *mem_ctx, char *confdb_location); int confdb_get_domain(struct confdb_ctx *cdb, - TALLOC_CTX *mem_ctx, const char *name, struct sss_domain_info **domain); int confdb_get_domains(struct confdb_ctx *cdb, - TALLOC_CTX *mem_ctx, struct sss_domain_info **domains); #endif diff --git a/server/confdb/confdb_private.h b/server/confdb/confdb_private.h index 41fcd269..1bab99ca 100644 --- a/server/confdb/confdb_private.h +++ b/server/confdb/confdb_private.h @@ -25,6 +25,8 @@ struct confdb_ctx { struct tevent_context *pev; struct ldb_context *ldb; + + struct sss_domain_info *doms; }; int parse_section(TALLOC_CTX *mem_ctx, const char *section, diff --git a/server/db/sysdb.c b/server/db/sysdb.c index 90482b52..d4f25797 100644 --- a/server/db/sysdb.c +++ b/server/db/sysdb.c @@ -3,7 +3,7 @@ System Database - Copyright (C) Simo Sorce 2008 + Copyright (C) Simo Sorce 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 3d75f507..2d8b3eae 100644 --- a/server/db/sysdb.h +++ b/server/db/sysdb.h @@ -26,7 +26,8 @@ #include #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 d8b66cd7..e380c827 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. diff --git a/server/monitor/monitor.c b/server/monitor/monitor.c index 893de9b1..86b2364c 100644 --- a/server/monitor/monitor.c +++ b/server/monitor/monitor.c @@ -866,7 +866,7 @@ int get_monitor_config(struct mt_ctx *ctx) if(!ctx->domain_ctx) { return ENOMEM; } - ret = confdb_get_domains(ctx->cdb, ctx->domain_ctx, &ctx->domains); + ret = confdb_get_domains(ctx->cdb, &ctx->domains); if (ret != EOK) { DEBUG(0, ("No domains configured.\n")); return ret; @@ -1780,7 +1780,7 @@ int monitor_process_init(TALLOC_CTX *mem_ctx, const char *config_file) { struct mt_ctx *ctx; - struct sysdb_ctx *sysdb; + struct sysdb_ctx_list *db_list; struct tevent_signal *tes; int ret, i; char *cdb_file; @@ -1860,19 +1860,16 @@ int monitor_process_init(TALLOC_CTX *mem_ctx, return ret; } - /* Avoid a startup race condition between InfoPipe - * and NSS. If the sysdb doesn't exist yet, both - * will try to create it at the same time. So - * we'll have the monitor create it before either of - * those processes start. + /* Avoid a startup race condition between process. + * We need to handle DB upgrades or DB creation only + * in one process before all other start. */ - ret = sysdb_init(mem_ctx, ctx->ev, ctx->cdb, - NULL, &sysdb); + ret = sysdb_init(mem_ctx, ctx->ev, ctx->cdb, NULL, true, &db_list); if (ret != EOK) { talloc_free(ctx); return ret; } - talloc_free(sysdb); + talloc_free(db_list); /* Initialize D-BUS Server * The monitor will act as a D-BUS server for all diff --git a/server/providers/data_provider_be.c b/server/providers/data_provider_be.c index 8428954a..55fc2787 100644 --- a/server/providers/data_provider_be.c +++ b/server/providers/data_provider_be.c @@ -944,13 +944,13 @@ int be_process_init(TALLOC_CTX *mem_ctx, return ENOMEM; } - ret = confdb_get_domain(cdb, ctx, be_domain, &ctx->domain); + ret = confdb_get_domain(cdb, be_domain, &ctx->domain); if (ret != EOK) { DEBUG(0, ("fatal error retrieving domain configuration\n")); return ret; } - ret = sysdb_init(ctx, ev, cdb, NULL, &ctx->sysdb); + ret = sysdb_domain_init(ctx, ev, ctx->domain, DB_PATH, &ctx->sysdb); if (ret != EOK) { DEBUG(0, ("fatal error opening cache database\n")); return ret; diff --git a/server/responder/common/responder.h b/server/responder/common/responder.h index 59a58a5c..ddf8b893 100644 --- a/server/responder/common/responder.h +++ b/server/responder/common/responder.h @@ -62,7 +62,6 @@ struct resp_ctx { int lfd; struct tevent_fd *priv_lfde; int priv_lfd; - struct sysdb_ctx *sysdb; struct confdb_ctx *cdb; const char *sock_name; const char *priv_sock_name; @@ -71,6 +70,7 @@ struct resp_ctx { struct sbus_connection *dp_conn; struct sss_domain_info *domains; + struct sysdb_ctx_list *db_list; struct sss_cmd_table *sss_cmds; const char *sss_pipe_name; diff --git a/server/responder/common/responder_common.c b/server/responder/common/responder_common.c index f1030c04..57c8678b 100644 --- a/server/responder/common/responder_common.c +++ b/server/responder/common/responder_common.c @@ -510,7 +510,7 @@ int sss_process_init(TALLOC_CTX *mem_ctx, rctx->priv_sock_name = sss_priv_pipe_name; rctx->confdb_service_path = confdb_service_path; - ret = confdb_get_domains(rctx->cdb, rctx, &rctx->domains); + ret = confdb_get_domains(rctx->cdb, &rctx->domains); if (ret != EOK) { DEBUG(0, ("fatal error setting up domain map\n")); return ret; @@ -534,7 +534,7 @@ int sss_process_init(TALLOC_CTX *mem_ctx, return EIO; } - ret = sysdb_init(rctx, ev, cdb, NULL, &rctx->sysdb); + ret = sysdb_init(rctx, ev, cdb, NULL, false, &rctx->db_list); if (ret != EOK) { DEBUG(0, ("fatal error initializing resp_ctx\n")); return ret; diff --git a/server/responder/nss/nsssrv_cmd.c b/server/responder/nss/nsssrv_cmd.c index abd20a1b..405dae81 100644 --- a/server/responder/nss/nsssrv_cmd.c +++ b/server/responder/nss/nsssrv_cmd.c @@ -271,6 +271,7 @@ static void nss_cmd_getpwnam_callback(void *ptr, int status, struct nss_dom_ctx *dctx = talloc_get_type(ptr, struct nss_dom_ctx); struct nss_cmd_ctx *cmdctx = dctx->cmdctx; struct cli_ctx *cctx = cmdctx->cctx; + struct sysdb_ctx *sysdb; struct sss_domain_info *dom; struct nss_ctx *nctx; int timeout; @@ -388,7 +389,13 @@ static void nss_cmd_getpwnam_callback(void *ptr, int status, DEBUG(4, ("Requesting info for [%s@%s]\n", cmdctx->name, dctx->domain->name)); - ret = sysdb_getpwnam(cmdctx, cctx->rctx->sysdb, + ret = sysdb_get_ctx_from_list(cctx->rctx->db_list, + dctx->domain, &sysdb); + if (ret != EOK) { + DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n")); + NSS_CMD_FATAL_ERROR(cctx); + } + ret = sysdb_getpwnam(cmdctx, sysdb, dctx->domain, cmdctx->name, nss_cmd_getpwnam_callback, dctx); if (ret != EOK) { @@ -458,6 +465,7 @@ static void nss_cmd_getpwnam_dp_callback(uint16_t err_maj, uint32_t err_min, struct nss_dom_ctx *dctx = talloc_get_type(ptr, struct nss_dom_ctx); struct nss_cmd_ctx *cmdctx = dctx->cmdctx; struct cli_ctx *cctx = cmdctx->cctx; + struct sysdb_ctx *sysdb; int ret; if (err_maj) { @@ -479,7 +487,13 @@ static void nss_cmd_getpwnam_dp_callback(uint16_t err_maj, uint32_t err_min, return; } - ret = sysdb_getpwnam(cmdctx, cctx->rctx->sysdb, + ret = sysdb_get_ctx_from_list(cctx->rctx->db_list, + dctx->domain, &sysdb); + if (ret != EOK) { + DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n")); + NSS_CMD_FATAL_ERROR(cctx); + } + ret = sysdb_getpwnam(cmdctx, sysdb, dctx->domain, cmdctx->name, nss_cmd_getpwnam_callback, dctx); @@ -501,6 +515,7 @@ static int nss_cmd_getpwnam(struct cli_ctx *cctx) struct nss_cmd_ctx *cmdctx; struct nss_dom_ctx *dctx; struct sss_domain_info *dom; + struct sysdb_ctx *sysdb; struct nss_ctx *nctx; const char *rawname; char *domname; @@ -602,7 +617,14 @@ static int nss_cmd_getpwnam(struct cli_ctx *cctx) DEBUG(4, ("Requesting info for [%s@%s]\n", cmdctx->name, dctx->domain->name)); - ret = sysdb_getpwnam(cmdctx, cctx->rctx->sysdb, + ret = sysdb_get_ctx_from_list(cctx->rctx->db_list, + dctx->domain, &sysdb); + if (ret != EOK) { + DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n")); + ret = EFAULT; + goto done; + } + ret = sysdb_getpwnam(cmdctx, sysdb, dctx->domain, cmdctx->name, nss_cmd_getpwnam_callback, dctx); if (ret != EOK) { @@ -644,6 +666,7 @@ static void nss_cmd_getpwuid_callback(void *ptr, int status, struct nss_cmd_ctx *cmdctx = dctx->cmdctx; struct cli_ctx *cctx = cmdctx->cctx; struct sss_domain_info *dom; + struct sysdb_ctx *sysdb; struct nss_ctx *nctx; int timeout; uint64_t lastUpdate; @@ -748,7 +771,13 @@ static void nss_cmd_getpwuid_callback(void *ptr, int status, DEBUG(4, ("Requesting info for [%s@%s]\n", cmdctx->name, dctx->domain->name)); - ret = sysdb_getpwuid(cmdctx, cctx->rctx->sysdb, + ret = sysdb_get_ctx_from_list(cctx->rctx->db_list, + dctx->domain, &sysdb); + if (ret != EOK) { + DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n")); + NSS_CMD_FATAL_ERROR(cctx); + } + ret = sysdb_getpwuid(cmdctx, sysdb, dctx->domain, cmdctx->id, nss_cmd_getpwuid_callback, dctx); if (ret != EOK) { @@ -818,6 +847,7 @@ static void nss_cmd_getpwuid_dp_callback(uint16_t err_maj, uint32_t err_min, struct nss_dom_ctx *dctx = talloc_get_type(ptr, struct nss_dom_ctx); struct nss_cmd_ctx *cmdctx = dctx->cmdctx; struct cli_ctx *cctx = cmdctx->cctx; + struct sysdb_ctx *sysdb; int ret; if (err_maj) { @@ -839,7 +869,13 @@ static void nss_cmd_getpwuid_dp_callback(uint16_t err_maj, uint32_t err_min, return; } - ret = sysdb_getpwuid(cmdctx, cctx->rctx->sysdb, + ret = sysdb_get_ctx_from_list(cctx->rctx->db_list, + dctx->domain, &sysdb); + if (ret != EOK) { + DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n")); + NSS_CMD_FATAL_ERROR(cctx); + } + ret = sysdb_getpwuid(cmdctx, sysdb, dctx->domain, cmdctx->id, nss_cmd_getpwuid_callback, dctx); @@ -860,6 +896,7 @@ static int nss_cmd_getpwuid(struct cli_ctx *cctx) struct nss_cmd_ctx *cmdctx; struct nss_dom_ctx *dctx; struct sss_domain_info *dom; + struct sysdb_ctx *sysdb; struct nss_ctx *nctx; uint8_t *body; size_t blen; @@ -920,7 +957,14 @@ static int nss_cmd_getpwuid(struct cli_ctx *cctx) DEBUG(4, ("Requesting info for [%lu@%s]\n", cmdctx->id, dctx->domain->name)); - ret = sysdb_getpwuid(cmdctx, cctx->rctx->sysdb, + ret = sysdb_get_ctx_from_list(cctx->rctx->db_list, + dctx->domain, &sysdb); + if (ret != EOK) { + DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n")); + ret = EFAULT; + goto done; + } + ret = sysdb_getpwuid(cmdctx, sysdb, dctx->domain, cmdctx->id, nss_cmd_getpwuid_callback, dctx); if (ret != EOK) { @@ -978,6 +1022,7 @@ static void nss_cmd_setpwent_callback(void *ptr, int status, struct nss_cmd_ctx *cmdctx = dctx->cmdctx; struct cli_ctx *cctx = cmdctx->cctx; struct sss_domain_info *dom; + struct sysdb_ctx *sysdb; struct getent_ctx *pctx; struct nss_ctx *nctx; int timeout; @@ -1040,7 +1085,13 @@ static void nss_cmd_setpwent_callback(void *ptr, int status, timeout, dom->name, SSS_DP_USER, NULL, 0); } else { - ret = sysdb_enumpwent(dctx, cctx->rctx->sysdb, + ret = sysdb_get_ctx_from_list(cctx->rctx->db_list, + dctx->domain, &sysdb); + if (ret != EOK) { + DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n")); + NSS_CMD_FATAL_ERROR(cctx); + } + ret = sysdb_enumpwent(dctx, sysdb, dctx->domain, NULL, nss_cmd_setpwent_callback, dctx); } @@ -1085,6 +1136,7 @@ static void nss_cmd_setpw_dp_callback(uint16_t err_maj, uint32_t err_min, struct nss_dom_ctx *dctx = talloc_get_type(ptr, struct nss_dom_ctx); struct nss_cmd_ctx *cmdctx = dctx->cmdctx; struct cli_ctx *cctx = cmdctx->cctx; + struct sysdb_ctx *sysdb; int ret; if (err_maj) { @@ -1094,7 +1146,13 @@ static void nss_cmd_setpw_dp_callback(uint16_t err_maj, uint32_t err_min, (unsigned int)err_maj, (unsigned int)err_min, err_msg)); } - ret = sysdb_enumpwent(cmdctx, cctx->rctx->sysdb, + ret = sysdb_get_ctx_from_list(cctx->rctx->db_list, + dctx->domain, &sysdb); + if (ret != EOK) { + DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n")); + NSS_CMD_FATAL_ERROR(cctx); + } + ret = sysdb_enumpwent(cmdctx, sysdb, dctx->domain, NULL, nss_cmd_setpwent_callback, dctx); if (ret != EOK) { @@ -1111,6 +1169,7 @@ static void nss_cmd_setpw_dp_callback(uint16_t err_maj, uint32_t err_min, static int nss_cmd_setpwent_ext(struct cli_ctx *cctx, bool immediate) { struct sss_domain_info *dom; + struct sysdb_ctx *sysdb; struct nss_cmd_ctx *cmdctx; struct nss_dom_ctx *dctx; struct nss_ctx *nctx; @@ -1173,7 +1232,14 @@ static int nss_cmd_setpwent_ext(struct cli_ctx *cctx, bool immediate) timeout, dom->name, SSS_DP_USER, NULL, 0); } else { - ret = sysdb_enumpwent(dctx, cctx->rctx->sysdb, + ret = sysdb_get_ctx_from_list(cctx->rctx->db_list, + dctx->domain, &sysdb); + if (ret != EOK) { + DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n")); + ret = EFAULT; + goto done; + } + ret = sysdb_enumpwent(dctx, sysdb, dctx->domain, NULL, nss_cmd_setpwent_callback, dctx); } @@ -1634,6 +1700,7 @@ static void nss_cmd_getgrnam_callback(void *ptr, int status, struct nss_cmd_ctx *cmdctx = dctx->cmdctx; struct cli_ctx *cctx = cmdctx->cctx; struct sss_domain_info *dom; + struct sysdb_ctx *sysdb; struct nss_ctx *nctx; int timeout; uint64_t lastUpdate; @@ -1740,7 +1807,13 @@ static void nss_cmd_getgrnam_callback(void *ptr, int status, DEBUG(4, ("Requesting info for [%s@%s]\n", cmdctx->name, dctx->domain->name)); - ret = sysdb_getgrnam(cmdctx, cctx->rctx->sysdb, + ret = sysdb_get_ctx_from_list(cctx->rctx->db_list, + dctx->domain, &sysdb); + if (ret != EOK) { + DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n")); + NSS_CMD_FATAL_ERROR(cctx); + } + ret = sysdb_getgrnam(cmdctx, sysdb, dctx->domain, cmdctx->name, nss_cmd_getgrnam_callback, dctx); if (ret != EOK) { @@ -1806,6 +1879,7 @@ static void nss_cmd_getgrnam_dp_callback(uint16_t err_maj, uint32_t err_min, struct nss_dom_ctx *dctx = talloc_get_type(ptr, struct nss_dom_ctx); struct nss_cmd_ctx *cmdctx = dctx->cmdctx; struct cli_ctx *cctx = cmdctx->cctx; + struct sysdb_ctx *sysdb; int ret; if (err_maj) { @@ -1827,7 +1901,13 @@ static void nss_cmd_getgrnam_dp_callback(uint16_t err_maj, uint32_t err_min, return; } - ret = sysdb_getgrnam(cmdctx, cctx->rctx->sysdb, + ret = sysdb_get_ctx_from_list(cctx->rctx->db_list, + dctx->domain, &sysdb); + if (ret != EOK) { + DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n")); + NSS_CMD_FATAL_ERROR(cctx); + } + ret = sysdb_getgrnam(cmdctx, sysdb, dctx->domain, cmdctx->name, nss_cmd_getgrnam_callback, dctx); @@ -1849,6 +1929,7 @@ static int nss_cmd_getgrnam(struct cli_ctx *cctx) struct nss_cmd_ctx *cmdctx; struct nss_dom_ctx *dctx; struct sss_domain_info *dom; + struct sysdb_ctx *sysdb; struct nss_ctx *nctx; const char *rawname; char *domname; @@ -1950,7 +2031,14 @@ static int nss_cmd_getgrnam(struct cli_ctx *cctx) DEBUG(4, ("Requesting info for [%s@%s]\n", cmdctx->name, dctx->domain->name)); - ret = sysdb_getgrnam(cmdctx, cctx->rctx->sysdb, + ret = sysdb_get_ctx_from_list(cctx->rctx->db_list, + dctx->domain, &sysdb); + if (ret != EOK) { + DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n")); + ret = EFAULT; + goto done; + } + ret = sysdb_getgrnam(cmdctx, sysdb, dctx->domain, cmdctx->name, nss_cmd_getgrnam_callback, dctx); if (ret != EOK) { @@ -1992,6 +2080,7 @@ static void nss_cmd_getgrgid_callback(void *ptr, int status, struct nss_cmd_ctx *cmdctx = dctx->cmdctx; struct cli_ctx *cctx = cmdctx->cctx; struct sss_domain_info *dom; + struct sysdb_ctx *sysdb; struct nss_ctx *nctx; int timeout; uint64_t lastUpdate; @@ -2087,7 +2176,13 @@ static void nss_cmd_getgrgid_callback(void *ptr, int status, DEBUG(4, ("Requesting info for [%s@%s]\n", cmdctx->name, dctx->domain->name)); - ret = sysdb_getgrgid(cmdctx, cctx->rctx->sysdb, + ret = sysdb_get_ctx_from_list(cctx->rctx->db_list, + dctx->domain, &sysdb); + if (ret != EOK) { + DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n")); + NSS_CMD_FATAL_ERROR(cctx); + } + ret = sysdb_getgrgid(cmdctx, sysdb, dctx->domain, cmdctx->id, nss_cmd_getgrgid_callback, dctx); if (ret != EOK) { @@ -2151,6 +2246,7 @@ static void nss_cmd_getgrgid_dp_callback(uint16_t err_maj, uint32_t err_min, struct nss_dom_ctx *dctx = talloc_get_type(ptr, struct nss_dom_ctx); struct nss_cmd_ctx *cmdctx = dctx->cmdctx; struct cli_ctx *cctx = cmdctx->cctx; + struct sysdb_ctx *sysdb; int ret; if (err_maj) { @@ -2172,7 +2268,13 @@ static void nss_cmd_getgrgid_dp_callback(uint16_t err_maj, uint32_t err_min, return; } - ret = sysdb_getgrgid(cmdctx, cctx->rctx->sysdb, + ret = sysdb_get_ctx_from_list(cctx->rctx->db_list, + dctx->domain, &sysdb); + if (ret != EOK) { + DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n")); + NSS_CMD_FATAL_ERROR(cctx); + } + ret = sysdb_getgrgid(cmdctx, sysdb, dctx->domain, cmdctx->id, nss_cmd_getgrgid_callback, dctx); @@ -2193,6 +2295,7 @@ static int nss_cmd_getgrgid(struct cli_ctx *cctx) struct nss_cmd_ctx *cmdctx; struct nss_dom_ctx *dctx; struct sss_domain_info *dom; + struct sysdb_ctx *sysdb; struct nss_ctx *nctx; uint8_t *body; size_t blen; @@ -2253,7 +2356,14 @@ static int nss_cmd_getgrgid(struct cli_ctx *cctx) DEBUG(4, ("Requesting info for [%lu@%s]\n", cmdctx->id, dctx->domain->name)); - ret = sysdb_getgrgid(cmdctx, cctx->rctx->sysdb, + ret = sysdb_get_ctx_from_list(cctx->rctx->db_list, + dctx->domain, &sysdb); + if (ret != EOK) { + DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n")); + ret = EFAULT; + goto done; + } + ret = sysdb_getgrgid(cmdctx, sysdb, dctx->domain, cmdctx->id, nss_cmd_getgrgid_callback, dctx); if (ret != EOK) { @@ -2311,6 +2421,7 @@ static void nss_cmd_setgrent_callback(void *ptr, int status, struct nss_cmd_ctx *cmdctx = dctx->cmdctx; struct cli_ctx *cctx = cmdctx->cctx; struct sss_domain_info *dom; + struct sysdb_ctx *sysdb; struct getent_ctx *gctx; struct nss_ctx *nctx; int timeout; @@ -2369,7 +2480,13 @@ static void nss_cmd_setgrent_callback(void *ptr, int status, timeout, dom->name, SSS_DP_GROUP, NULL, 0); } else { - ret = sysdb_enumgrent(dctx, cctx->rctx->sysdb, + ret = sysdb_get_ctx_from_list(cctx->rctx->db_list, + dctx->domain, &sysdb); + if (ret != EOK) { + DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n")); + NSS_CMD_FATAL_ERROR(cctx); + } + ret = sysdb_enumgrent(dctx, sysdb, dctx->domain, nss_cmd_setgrent_callback, dctx); } @@ -2414,6 +2531,7 @@ static void nss_cmd_setgr_dp_callback(uint16_t err_maj, uint32_t err_min, struct nss_dom_ctx *dctx = talloc_get_type(ptr, struct nss_dom_ctx); struct nss_cmd_ctx *cmdctx = dctx->cmdctx; struct cli_ctx *cctx = cmdctx->cctx; + struct sysdb_ctx *sysdb; int ret; if (err_maj) { @@ -2423,7 +2541,13 @@ static void nss_cmd_setgr_dp_callback(uint16_t err_maj, uint32_t err_min, (unsigned int)err_maj, (unsigned int)err_min, err_msg)); } - ret = sysdb_enumgrent(dctx, cctx->rctx->sysdb, + ret = sysdb_get_ctx_from_list(cctx->rctx->db_list, + dctx->domain, &sysdb); + if (ret != EOK) { + DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n")); + NSS_CMD_FATAL_ERROR(cctx); + } + ret = sysdb_enumgrent(dctx, sysdb, dctx->domain, nss_cmd_setgrent_callback, dctx); if (ret != EOK) { @@ -2440,6 +2564,7 @@ static void nss_cmd_setgr_dp_callback(uint16_t err_maj, uint32_t err_min, static int nss_cmd_setgrent_ext(struct cli_ctx *cctx, bool immediate) { struct sss_domain_info *dom; + struct sysdb_ctx *sysdb; struct nss_cmd_ctx *cmdctx; struct nss_dom_ctx *dctx; struct nss_ctx *nctx; @@ -2502,7 +2627,14 @@ static int nss_cmd_setgrent_ext(struct cli_ctx *cctx, bool immediate) timeout, dom->name, SSS_DP_GROUP, NULL, 0); } else { - ret = sysdb_enumgrent(dctx, cctx->rctx->sysdb, + ret = sysdb_get_ctx_from_list(cctx->rctx->db_list, + dctx->domain, &sysdb); + if (ret != EOK) { + DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n")); + ret = EFAULT; + goto done; + } + ret = sysdb_enumgrent(dctx, sysdb, dctx->domain, nss_cmd_setgrent_callback, dctx); } @@ -2728,6 +2860,7 @@ static void nss_cmd_getinitgr_callback(uint16_t err_maj, uint32_t err_min, struct nss_dom_ctx *dctx = talloc_get_type(ptr, struct nss_dom_ctx); struct nss_cmd_ctx *cmdctx = dctx->cmdctx; struct cli_ctx *cctx = cmdctx->cctx; + struct sysdb_ctx *sysdb; int ret; if (err_maj) { @@ -2737,7 +2870,13 @@ static void nss_cmd_getinitgr_callback(uint16_t err_maj, uint32_t err_min, (unsigned int)err_maj, (unsigned int)err_min, err_msg)); } - ret = sysdb_initgroups(cmdctx, cctx->rctx->sysdb, + ret = sysdb_get_ctx_from_list(cctx->rctx->db_list, + dctx->domain, &sysdb); + if (ret != EOK) { + DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n")); + NSS_CMD_FATAL_ERROR(cctx); + } + ret = sysdb_initgroups(cmdctx, sysdb, dctx->domain, cmdctx->name, nss_cmd_initgr_callback, cmdctx); if (ret != EOK) { @@ -2760,6 +2899,7 @@ static void nss_cmd_getinitnam_dp_callback(uint16_t err_maj, uint32_t err_min, struct nss_dom_ctx *dctx = talloc_get_type(ptr, struct nss_dom_ctx); struct nss_cmd_ctx *cmdctx = dctx->cmdctx; struct cli_ctx *cctx = cmdctx->cctx; + struct sysdb_ctx *sysdb; int ret; if (err_maj) { @@ -2781,7 +2921,13 @@ static void nss_cmd_getinitnam_dp_callback(uint16_t err_maj, uint32_t err_min, return; } - ret = sysdb_getpwnam(cmdctx, cctx->rctx->sysdb, + ret = sysdb_get_ctx_from_list(cctx->rctx->db_list, + dctx->domain, &sysdb); + if (ret != EOK) { + DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n")); + NSS_CMD_FATAL_ERROR(cctx); + } + ret = sysdb_getpwnam(cmdctx, sysdb, dctx->domain, cmdctx->name, nss_cmd_getinit_callback, dctx); @@ -2804,6 +2950,7 @@ static void nss_cmd_getinit_callback(void *ptr, int status, struct nss_cmd_ctx *cmdctx = dctx->cmdctx; struct cli_ctx *cctx = cmdctx->cctx; struct sss_domain_info *dom; + struct sysdb_ctx *sysdb; struct nss_ctx *nctx; int timeout; uint64_t lastUpdate; @@ -2920,7 +3067,13 @@ static void nss_cmd_getinit_callback(void *ptr, int status, DEBUG(4, ("Requesting info for [%s@%s]\n", cmdctx->name, dctx->domain->name)); - ret = sysdb_getpwnam(cmdctx, cctx->rctx->sysdb, + ret = sysdb_get_ctx_from_list(cctx->rctx->db_list, + dctx->domain, &sysdb); + if (ret != EOK) { + DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n")); + NSS_CMD_FATAL_ERROR(cctx); + } + ret = sysdb_getpwnam(cmdctx, sysdb, dctx->domain, cmdctx->name, nss_cmd_getinit_callback, dctx); if (ret != EOK) { @@ -2991,6 +3144,7 @@ static int nss_cmd_initgroups(struct cli_ctx *cctx) struct nss_cmd_ctx *cmdctx; struct nss_dom_ctx *dctx; struct sss_domain_info *dom; + struct sysdb_ctx *sysdb; struct nss_ctx *nctx; const char *rawname; char *domname; @@ -3092,7 +3246,14 @@ static int nss_cmd_initgroups(struct cli_ctx *cctx) DEBUG(4, ("Requesting info for [%s@%s]\n", cmdctx->name, dctx->domain->name)); - ret = sysdb_getpwnam(cmdctx, cctx->rctx->sysdb, + ret = sysdb_get_ctx_from_list(cctx->rctx->db_list, + dctx->domain, &sysdb); + if (ret != EOK) { + DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n")); + ret = EFAULT; + goto done; + } + ret = sysdb_getpwnam(cmdctx, sysdb, dctx->domain, cmdctx->name, nss_cmd_getinit_callback, dctx); if (ret != EOK) { diff --git a/server/responder/pam/pam_LOCAL_domain.c b/server/responder/pam/pam_LOCAL_domain.c index 5d76891f..41d64b3e 100644 --- a/server/responder/pam/pam_LOCAL_domain.c +++ b/server/responder/pam/pam_LOCAL_domain.c @@ -459,7 +459,13 @@ int LOCAL_pam_handler(struct pam_auth_req *preq) return ENOMEM; } - lreq->dbctx = preq->cctx->rctx->sysdb; + ret = sysdb_get_ctx_from_list(preq->cctx->rctx->db_list, + preq->domain, &lreq->dbctx); + if (ret != EOK) { + DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n")); + talloc_free(lreq); + return ret; + } lreq->ev = preq->cctx->ev; lreq->preq = preq; diff --git a/server/responder/pam/pamsrv_cache.c b/server/responder/pam/pamsrv_cache.c index 7cfd97b1..9c5c209f 100644 --- a/server/responder/pam/pamsrv_cache.c +++ b/server/responder/pam/pamsrv_cache.c @@ -132,6 +132,7 @@ done: int pam_cache_auth(struct pam_auth_req *preq) { + struct sysdb_ctx *sysdb; int ret; static const char *attrs[] = {SYSDB_NAME, @@ -144,7 +145,13 @@ int pam_cache_auth(struct pam_auth_req *preq) "lastFailedLogin", NULL}; - ret = sysdb_get_user_attr(preq, preq->cctx->rctx->sysdb, + ret = sysdb_get_ctx_from_list(preq->cctx->rctx->db_list, + preq->domain, &sysdb); + if (ret != EOK) { + DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n")); + return ret; + } + ret = sysdb_get_user_attr(preq, sysdb, preq->domain, preq->pd->user, attrs, pam_cache_auth_callback, preq); diff --git a/server/responder/pam/pamsrv_cmd.c b/server/responder/pam/pamsrv_cmd.c index 12625509..1204e325 100644 --- a/server/responder/pam/pamsrv_cmd.c +++ b/server/responder/pam/pamsrv_cmd.c @@ -382,6 +382,7 @@ static void pam_dom_forwarder(struct pam_auth_req *preq); static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd) { struct sss_domain_info *dom; + struct sysdb_ctx *sysdb; struct pam_auth_req *preq; struct pam_data *pd; uint8_t *body; @@ -486,7 +487,13 @@ static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd) else { preq->check_provider = NEED_CHECK_PROVIDER(preq->domain->provider); - ret = sysdb_getpwnam(preq, cctx->rctx->sysdb, + ret = sysdb_get_ctx_from_list(cctx->rctx->db_list, + preq->domain, &sysdb); + if (ret != EOK) { + DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n")); + goto done; + } + ret = sysdb_getpwnam(preq, sysdb, preq->domain, preq->pd->user, pam_check_user_callback, preq); } @@ -509,6 +516,7 @@ static void pam_check_user_dp_callback(uint16_t err_maj, uint32_t err_min, { struct pam_auth_req *preq = talloc_get_type(ptr, struct pam_auth_req); struct ldb_result *res = NULL; + struct sysdb_ctx *sysdb; int ret; if ((err_maj != DP_ERR_OK) && (err_maj != DP_ERR_OFFLINE)) { @@ -531,7 +539,13 @@ static void pam_check_user_dp_callback(uint16_t err_maj, uint32_t err_min, return; } - ret = sysdb_getpwnam(preq, preq->cctx->rctx->sysdb, + ret = sysdb_get_ctx_from_list(preq->cctx->rctx->db_list, + preq->domain, &sysdb); + if (ret != EOK) { + DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n")); + goto done; + } + ret = sysdb_getpwnam(preq, sysdb, preq->domain, preq->pd->user, pam_check_user_callback, preq); @@ -547,6 +561,7 @@ static void pam_check_user_callback(void *ptr, int status, { struct pam_auth_req *preq = talloc_get_type(ptr, struct pam_auth_req); struct sss_domain_info *dom; + struct sysdb_ctx *sysdb; uint64_t lastUpdate; bool call_provider = false; time_t timeout; @@ -673,7 +688,15 @@ static void pam_check_user_callback(void *ptr, int status, else { preq->check_provider = NEED_CHECK_PROVIDER(preq->domain->provider); - ret = sysdb_getpwnam(preq, preq->cctx->rctx->sysdb, + ret = sysdb_get_ctx_from_list(preq->cctx->rctx->db_list, + preq->domain, &sysdb); + if (ret != EOK) { + DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n")); + preq->pd->pam_status = PAM_SYSTEM_ERR; + pam_reply(preq); + return; + } + ret = sysdb_getpwnam(preq, sysdb, preq->domain, preq->pd->user, pam_check_user_callback, preq); } diff --git a/server/tests/sysdb-tests.c b/server/tests/sysdb-tests.c index 72514e3b..38bfcb10 100644 --- a/server/tests/sysdb-tests.c +++ b/server/tests/sysdb-tests.c @@ -24,15 +24,19 @@ #include #include #include +#include +#include #include "util/util.h" #include "confdb/confdb_setup.h" #include "db/sysdb_private.h" +#define TESTS_PATH "tests_sysdb" + struct sysdb_test_ctx { struct sysdb_ctx *sysdb; struct confdb_ctx *confdb; struct tevent_context *ev; - struct sss_domain_info *domains; + struct sss_domain_info *domain; }; static int setup_sysdb_tests(struct sysdb_test_ctx **ctx) @@ -44,6 +48,14 @@ static int setup_sysdb_tests(struct sysdb_test_ctx **ctx) const char *val[2]; val[1] = NULL; + /* Create tests directory if it doesn't exist */ + /* (relative to current dir) */ + ret = mkdir(TESTS_PATH, 0775); + if (ret == -1 && errno != EEXIST) { + fail("Could not create %s directory", TESTS_PATH); + return EFAULT; + } + test_ctx = talloc_zero(NULL, struct sysdb_test_ctx); if (test_ctx == NULL) { fail("Could not allocate memory for test context"); @@ -60,7 +72,7 @@ static int setup_sysdb_tests(struct sysdb_test_ctx **ctx) return EIO; } - conf_db = talloc_asprintf(test_ctx, "tests_conf.ldb"); + conf_db = talloc_asprintf(test_ctx, "%s/tests_conf.ldb", TESTS_PATH); if (conf_db == NULL) { fail("Out of memory, aborting!"); talloc_free(test_ctx); @@ -77,58 +89,52 @@ static int setup_sysdb_tests(struct sysdb_test_ctx **ctx) } val[0] = "LOCAL"; - ret = confdb_add_param(test_ctx->confdb, true, "config/domains", "domains", val); + ret = confdb_add_param(test_ctx->confdb, true, + "config/domains", "domains", val); if (ret != EOK) { fail("Could not initialize domains placeholder"); talloc_free(test_ctx); return ret; } - val[0] = "foo"; - ret = confdb_add_param(test_ctx->confdb, true, "config/domains/LOCAL", "provider", val); + val[0] = "local"; + ret = confdb_add_param(test_ctx->confdb, true, + "config/domains/LOCAL", "provider", val); if (ret != EOK) { - fail("Could not initialize domains placeholder"); + fail("Could not initialize provider"); talloc_free(test_ctx); return ret; } /* val[0] = "TRUE"; - ret = confdb_add_param(test_ctx->confdb, true, "config/domains/LOCAL", "legacy", val); + ret = confdb_add_param(test_ctx->confdb, true, + "config/domains/LOCAL", "magicPrivateGroups", val); if (ret != EOK) { fail("Could not initialize LOCAL domain"); talloc_free(test_ctx); return ret; } */ -/* val[0] = "TRUE"; - ret = confdb_add_param(test_ctx->confdb, true, "config/domains/LOCAL", "magicPrivateGroups", val); - if (ret != EOK) { - fail("Could not initialize LOCAL domain"); - talloc_free(test_ctx); - return ret; - } -*/ - val[0] = "3"; - ret = confdb_add_param(test_ctx->confdb, true, "config/domains/LOCAL", "enumerate", val); + ret = confdb_add_param(test_ctx->confdb, true, + "config/domains/LOCAL", "enumerate", val); if (ret != EOK) { fail("Could not initialize LOCAL domain"); talloc_free(test_ctx); return ret; } - ret = sysdb_init(test_ctx, test_ctx->ev, test_ctx->confdb, "tests.ldb", - &test_ctx->sysdb); + ret = confdb_get_domain(test_ctx->confdb, "local", &test_ctx->domain); if (ret != EOK) { - fail("Could not initialize connection to the sysdb"); + fail("Could not retrieve LOCAL domain"); talloc_free(test_ctx); return ret; } - ret = confdb_get_domains(test_ctx->confdb, test_ctx, - &test_ctx->domains); + ret = sysdb_domain_init(test_ctx, test_ctx->ev, + test_ctx->domain, TESTS_PATH, &test_ctx->sysdb); if (ret != EOK) { - fail("Could not initialize domains"); + fail("Could not initialize connection to the sysdb (%d)", ret); talloc_free(test_ctx); return ret; } @@ -140,7 +146,6 @@ static int setup_sysdb_tests(struct sysdb_test_ctx **ctx) struct test_data { struct tevent_context *ev; struct sysdb_handle *handle; - struct sss_domain_info *domain; struct sysdb_test_ctx *ctx; const char *username; @@ -156,25 +161,6 @@ struct test_data { const char *attrval; /* testing sysdb_get_user_attr */ }; -static struct sss_domain_info *get_local_domain(struct sss_domain_info *domlist) -{ - struct sss_domain_info *local = domlist; - - while (local) { - if (strcmp(local->name, "LOCAL") == 0) - break; - - local = local->next; - } - - if (local == NULL) { - fail("Could not set up the test (missing LOCAL domain)"); - return NULL; - } - - return local; -} - static int test_loop(struct test_data *data) { while (!data->finished) @@ -236,7 +222,7 @@ static void test_add_user(struct tevent_req *subreq) gecos = talloc_asprintf(data, "Test User %d", data->uid); subreq = sysdb_add_user_send(data, data->ev, data->handle, - data->domain, data->username, + data->ctx->domain, data->username, data->uid, 0, gecos, homedir, "/bin/bash", NULL); @@ -276,7 +262,7 @@ static void test_store_user(struct tevent_req *req) gecos = talloc_asprintf(data, "Test User %d", data->uid); subreq = sysdb_store_user_send(data, data->ev, data->handle, - data->domain, data->username, "x", + data->ctx->domain, data->username, "x", data->uid, 0, gecos, homedir, data->shell ? data->shell : "/bin/bash", @@ -349,7 +335,7 @@ static void test_remove_user_by_uid(struct tevent_req *req) subreq = sysdb_delete_user_by_uid_send(data, data->ev, data->handle, - data->domain, data->uid, + data->ctx->domain, data->uid, true); if (!subreq) return test_return(data, ENOMEM); @@ -383,7 +369,7 @@ static void test_remove_nonexistent_group(struct tevent_req *req) subreq = sysdb_delete_group_by_gid_send(data, data->ev, data->handle, - data->domain, data->uid, + data->ctx->domain, data->uid, false); if (!subreq) return test_return(data, ENOMEM); @@ -417,7 +403,7 @@ static void test_remove_nonexistent_user(struct tevent_req *req) subreq = sysdb_delete_user_by_uid_send(data, data->ev, data->handle, - data->domain, data->uid, + data->ctx->domain, data->uid, false); if (!subreq) return test_return(data, ENOMEM); @@ -451,7 +437,7 @@ static void test_add_group(struct tevent_req *req) } subreq = sysdb_add_group_send(data, data->ev, data->handle, - data->domain, data->groupname, + data->ctx->domain, data->groupname, data->gid, NULL); if (!subreq) { test_return(data, ret); @@ -484,7 +470,7 @@ static void test_store_group(struct tevent_req *req) } subreq = sysdb_store_group_send(data, data->ev, data->handle, - data->domain, data->groupname, + data->ctx->domain, data->groupname, data->gid, NULL, NULL); if (!subreq) { test_return(data, ret); @@ -551,7 +537,7 @@ static void test_remove_group_by_gid(struct tevent_req *req) } subreq = sysdb_delete_group_by_gid_send(data, data->ev, data->handle, - data->domain, data->gid, + data->ctx->domain, data->gid, true); if (!subreq) return test_return(data, ENOMEM); @@ -723,7 +709,7 @@ static void test_set_user_attr(struct tevent_req *req) } subreq = sysdb_set_user_attr_send(data, data->ev, data->handle, - data->domain, data->username, + data->ctx->domain, data->username, data->attrs, SYSDB_MOD_REP); if (!subreq) return test_return(data, ENOMEM); @@ -787,7 +773,7 @@ static void test_add_group_member(struct tevent_req *req) } subreq = sysdb_add_group_member_send(data, data->ev, - data->handle, data->domain, + data->handle, data->ctx->domain, data->groupname, username); if (!subreq) { test_return(data, ENOMEM); @@ -825,7 +811,7 @@ static void test_remove_group_member(struct tevent_req *req) } subreq = sysdb_remove_group_member_send(data, data->ev, - data->handle, data->domain, + data->handle, data->ctx->domain, data->groupname, username); if (!subreq) { test_return(data, ENOMEM); @@ -863,7 +849,6 @@ START_TEST (test_sysdb_store_user) data->uid = _i; data->gid = _i; data->username = talloc_asprintf(data, "testuser%d", _i); - data->domain = get_local_domain(test_ctx->domains); req = sysdb_transaction_send(data, data->ev, test_ctx->sysdb); if (!req) { @@ -901,7 +886,6 @@ START_TEST (test_sysdb_store_user_existing) data->uid = _i; data->gid = _i; data->username = talloc_asprintf(data, "testuser%d", _i); - data->domain = get_local_domain(test_ctx->domains); data->shell = talloc_asprintf(data, "/bin/ksh"); req = sysdb_transaction_send(data, data->ev, test_ctx->sysdb); @@ -939,7 +923,6 @@ START_TEST (test_sysdb_store_group) data->ev = test_ctx->ev; data->gid = _i; data->groupname = talloc_asprintf(data, "testgroup%d", _i); - data->domain = get_local_domain(test_ctx->domains); req = sysdb_transaction_send(data, data->ev, test_ctx->sysdb); if (!req) { @@ -1010,7 +993,6 @@ START_TEST (test_sysdb_remove_local_user_by_uid) data->ctx = test_ctx; data->ev = test_ctx->ev; data->uid = _i; - data->domain = get_local_domain(test_ctx->domains); req = sysdb_transaction_send(data, data->ev, test_ctx->sysdb); if (!req) { @@ -1081,7 +1063,6 @@ START_TEST (test_sysdb_remove_local_group_by_gid) data->ctx = test_ctx; data->ev = test_ctx->ev; data->gid = _i; - data->domain = get_local_domain(test_ctx->domains); req = sysdb_transaction_send(data, data->ev, test_ctx->sysdb); if (!req) { @@ -1119,7 +1100,6 @@ START_TEST (test_sysdb_add_user) data->uid = _i; data->gid = _i; data->username = talloc_asprintf(data, "testuser%d", _i); - data->domain = get_local_domain(test_ctx->domains); subreq = sysdb_transaction_send(data, data->ev, test_ctx->sysdb); if (!subreq) { @@ -1157,7 +1137,6 @@ START_TEST (test_sysdb_add_group) data->uid = _i; data->gid = _i; data->groupname = talloc_asprintf(data, "testgroup%d", _i); - data->domain = get_local_domain(test_ctx->domains); subreq = sysdb_transaction_send(data, data->ev, test_ctx->sysdb); if (!subreq) { @@ -1191,11 +1170,10 @@ START_TEST (test_sysdb_getpwnam) data = talloc_zero(test_ctx, struct test_data); data->ctx = test_ctx; data->username = talloc_asprintf(data, "testuser%d", _i); - data->domain = get_local_domain(test_ctx->domains); ret = sysdb_getpwnam(test_ctx, test_ctx->sysdb, - data->domain, + data->ctx->domain, data->username, test_getpwent, data); @@ -1231,11 +1209,10 @@ START_TEST (test_sysdb_getgrnam) data = talloc_zero(test_ctx, struct test_data); data->ctx = test_ctx; data->groupname = talloc_asprintf(data, "testgroup%d", _i); - data->domain = get_local_domain(test_ctx->domains); ret = sysdb_getgrnam(test_ctx, test_ctx->sysdb, - data->domain, + data->ctx->domain, data->groupname, test_getgrent, data); @@ -1279,11 +1256,10 @@ START_TEST (test_sysdb_getgrgid) data = talloc_zero(test_ctx, struct test_data); data->ctx = test_ctx; data->gid = _i; - data->domain = get_local_domain(test_ctx->domains); ret = sysdb_getgrgid(test_ctx, test_ctx->sysdb, - data->domain, + data->ctx->domain, data->gid, test_getgrgid, data); @@ -1327,11 +1303,10 @@ START_TEST (test_sysdb_getpwuid) data = talloc_zero(test_ctx, struct test_data); data->ctx = test_ctx; data->uid = _i; - data->domain = get_local_domain(test_ctx->domains); ret = sysdb_getpwuid(test_ctx, test_ctx->sysdb, - data->domain, + data->ctx->domain, data->uid, test_getpwuid, data); @@ -1368,11 +1343,10 @@ START_TEST (test_sysdb_enumgrent) data = talloc_zero(test_ctx, struct test_data); data->ctx = test_ctx; - data->domain = get_local_domain(test_ctx->domains); ret = sysdb_enumgrent(test_ctx, test_ctx->sysdb, - data->domain, + data->ctx->domain, test_enumgrent, data); if (ret == EOK) { @@ -1402,11 +1376,10 @@ START_TEST (test_sysdb_enumpwent) data = talloc_zero(test_ctx, struct test_data); data->ctx = test_ctx; - data->domain = get_local_domain(test_ctx->domains); ret = sysdb_enumpwent(test_ctx, test_ctx->sysdb, - data->domain, + data->ctx->domain, NULL, test_enumpwent, data); @@ -1441,7 +1414,6 @@ START_TEST (test_sysdb_set_user_attr) data->ctx = test_ctx; data->ev = test_ctx->ev; data->username = talloc_asprintf(data, "testuser%d", _i); - data->domain = get_local_domain(test_ctx->domains); data->attrs = sysdb_new_attrs(test_ctx); if (ret != EOK) { @@ -1491,11 +1463,10 @@ START_TEST (test_sysdb_get_user_attr) data = talloc_zero(test_ctx, struct test_data); data->ctx = test_ctx; data->username = talloc_asprintf(data, "testuser%d", _i); - data->domain = get_local_domain(test_ctx->domains); ret = sysdb_get_user_attr(data, data->ctx->sysdb, - data->domain, + data->ctx->domain, data->username, attrs, test_get_user_attr, @@ -1535,7 +1506,6 @@ START_TEST (test_sysdb_add_group_member) data->ev = test_ctx->ev; data->groupname = talloc_asprintf(data, "testgroup%d", _i); data->uid = _i - 1000; /* the UID of user to add */ - data->domain = get_local_domain(test_ctx->domains); req = sysdb_transaction_send(data, data->ev, test_ctx->sysdb); if (!req) { @@ -1572,7 +1542,6 @@ START_TEST (test_sysdb_remove_group_member) data->ev = test_ctx->ev; data->groupname = talloc_asprintf(data, "testgroup%d", _i); data->uid = _i - 1000; /* the UID of user to add */ - data->domain = get_local_domain(test_ctx->domains); req = sysdb_transaction_send(data, data->ev, test_ctx->sysdb); if (!req) { @@ -1607,7 +1576,6 @@ START_TEST (test_sysdb_remove_nonexistent_user) data->ctx = test_ctx; data->ev = test_ctx->ev; data->uid = 12345; - data->domain = get_local_domain(test_ctx->domains); req = sysdb_transaction_send(data, data->ev, test_ctx->sysdb); if (!req) { @@ -1643,7 +1611,6 @@ START_TEST (test_sysdb_remove_nonexistent_group) data->ctx = test_ctx; data->ev = test_ctx->ev; data->uid = 12345; - data->domain = get_local_domain(test_ctx->domains); req = sysdb_transaction_send(data, data->ev, test_ctx->sysdb); if (!req) { diff --git a/server/tools/sss_groupadd.c b/server/tools/sss_groupadd.c index 5c4733d7..10bb9649 100644 --- a/server/tools/sss_groupadd.c +++ b/server/tools/sss_groupadd.c @@ -261,8 +261,16 @@ int main(int argc, const char **argv) goto fini; } + ret = sysdb_get_ctx_from_list(ctx->db_list, data->domain, &data->sysdb); + if (ret != EOK) { + DEBUG(0, ("Cannot get domain database!\n")); + ERROR("Internal error accesing database\n"); + ret = EXIT_FAILURE; + goto fini; + } + /* add_group */ - req = sysdb_transaction_send(ctx, ctx->ev, ctx->sysdb); + req = sysdb_transaction_send(ctx, ctx->ev, data->sysdb); if (!req) { DEBUG(1, ("Could not start transaction (%d)[%s]\n", ret, strerror(ret))); ERROR("Transaction error. Could not add group.\n"); diff --git a/server/tools/sss_groupdel.c b/server/tools/sss_groupdel.c index 1cf9ed0c..8f02cf3d 100644 --- a/server/tools/sss_groupdel.c +++ b/server/tools/sss_groupdel.c @@ -90,7 +90,7 @@ static void group_del(struct tevent_req *req) return groupdel_done(data, ret, NULL); } - group_dn = sysdb_group_dn(data->ctx->sysdb, data, + group_dn = sysdb_group_dn(data->sysdb, data, data->domain->name, data->name); if (group_dn == NULL) { DEBUG(1, ("Could not construct a group DN\n")); @@ -265,8 +265,16 @@ int main(int argc, const char **argv) goto fini; } + ret = sysdb_get_ctx_from_list(ctx->db_list, data->domain, &data->sysdb); + if (ret != EOK) { + DEBUG(0, ("Cannot get domain database!\n")); + ERROR("Internal error accesing database\n"); + ret = EXIT_FAILURE; + goto fini; + } + /* groupdel */ - req = sysdb_transaction_send(ctx, ctx->ev, ctx->sysdb); + req = sysdb_transaction_send(ctx, ctx->ev, data->sysdb); if (!req) { DEBUG(1, ("Could not start transaction (%d)[%s]\n", ret, strerror(ret))); ERROR("Transaction error. Could not remove group.\n"); diff --git a/server/tools/sss_groupmod.c b/server/tools/sss_groupmod.c index cca9abc6..6f60b6eb 100644 --- a/server/tools/sss_groupmod.c +++ b/server/tools/sss_groupmod.c @@ -156,13 +156,13 @@ static void remove_from_groups(struct ops_ctx *data) struct ldb_dn *member_dn; struct tevent_req *req; - parent_dn = sysdb_group_dn(data->ctx->sysdb, data, + parent_dn = sysdb_group_dn(data->sysdb, data, data->domain->name, data->name); if (!parent_dn) { return mod_group_done(data, ENOMEM); } - member_dn = sysdb_group_dn(data->ctx->sysdb, data, + member_dn = sysdb_group_dn(data->sysdb, data, data->domain->name, data->rmgroups[data->cur]); if (!member_dn) { @@ -213,13 +213,13 @@ static void add_to_groups(struct ops_ctx *data) struct ldb_dn *member_dn; struct tevent_req *req; - parent_dn = sysdb_group_dn(data->ctx->sysdb, data, + parent_dn = sysdb_group_dn(data->sysdb, data, data->domain->name, data->name); if (!parent_dn) { return mod_group_done(data, ENOMEM); } - member_dn = sysdb_group_dn(data->ctx->sysdb, data, + member_dn = sysdb_group_dn(data->sysdb, data, data->domain->name, data->addgroups[data->cur]); if (!member_dn) { @@ -463,7 +463,15 @@ int main(int argc, const char **argv) goto fini; } - req = sysdb_transaction_send(ctx, ctx->ev, ctx->sysdb); + ret = sysdb_get_ctx_from_list(ctx->db_list, data->domain, &data->sysdb); + if (ret != EOK) { + DEBUG(0, ("Cannot get domain database!\n")); + ERROR("Internal error accesing database\n"); + ret = EXIT_FAILURE; + goto fini; + } + + req = sysdb_transaction_send(ctx, ctx->ev, data->sysdb); if (!req) { DEBUG(1, ("Could not start transaction (%d)[%s]\n", ret, strerror(ret))); ERROR("Transaction error. Could not modify group.\n"); diff --git a/server/tools/sss_useradd.c b/server/tools/sss_useradd.c index 51f0eed8..928212d4 100644 --- a/server/tools/sss_useradd.c +++ b/server/tools/sss_useradd.c @@ -126,7 +126,7 @@ static int get_gid(struct ops_ctx *data, const char *groupname) errno != 0 || data->gid == 0) { /* Does not look like a gid - find the group name */ - ret = sysdb_getgrnam(data, data->ctx->sysdb, + ret = sysdb_getgrnam(data, data->sysdb, data->domain, groupname, get_gid_callback, data); if (ret != EOK) { @@ -233,13 +233,13 @@ static void add_to_groups(struct ops_ctx *data) struct ldb_dn *member_dn; struct tevent_req *subreq; - member_dn = sysdb_user_dn(data->ctx->sysdb, data, + member_dn = sysdb_user_dn(data->sysdb, data, data->domain->name, data->name); if (!member_dn) { return add_user_terminate(data, ENOMEM); } - parent_dn = sysdb_group_dn(data->ctx->sysdb, data, + parent_dn = sysdb_group_dn(data->sysdb, data, data->domain->name, data->groups[data->cur]); if (!parent_dn) { @@ -526,8 +526,16 @@ int main(int argc, const char **argv) goto fini; } + ret = sysdb_get_ctx_from_list(ctx->db_list, data->domain, &data->sysdb); + if (ret != EOK) { + DEBUG(0, ("Cannot get domain database!\n")); + ERROR("Internal error accesing database\n"); + ret = EXIT_FAILURE; + goto fini; + } + /* useradd */ - req = sysdb_transaction_send(ctx, ctx->ev, ctx->sysdb); + req = sysdb_transaction_send(ctx, ctx->ev, data->sysdb); if (!req) { DEBUG(1, ("Could not start transaction (%d)[%s]\n", ret, strerror(ret))); ERROR("Transaction error. Could not modify user.\n"); diff --git a/server/tools/sss_userdel.c b/server/tools/sss_userdel.c index 7c796bb6..2e595f55 100644 --- a/server/tools/sss_userdel.c +++ b/server/tools/sss_userdel.c @@ -91,7 +91,7 @@ static void user_del(struct tevent_req *req) return userdel_done(data, ret, NULL); } - user_dn = sysdb_user_dn(data->ctx->sysdb, data, + user_dn = sysdb_user_dn(data->sysdb, data, data->domain->name, data->name); if (!user_dn) { DEBUG(1, ("Could not construct a user DN\n")); @@ -265,8 +265,16 @@ int main(int argc, const char **argv) goto fini; } + ret = sysdb_get_ctx_from_list(ctx->db_list, data->domain, &data->sysdb); + if (ret != EOK) { + DEBUG(0, ("Cannot get domain database!\n")); + ERROR("Internal error accesing database\n"); + ret = EXIT_FAILURE; + goto fini; + } + /* userdel */ - req = sysdb_transaction_send(ctx, ctx->ev, ctx->sysdb); + req = sysdb_transaction_send(ctx, ctx->ev, data->sysdb); if (!req) { DEBUG(1, ("Could not start transaction (%d)[%s]\n", ret, strerror(ret))); ERROR("Transaction error. Could not remove user.\n"); diff --git a/server/tools/sss_usermod.c b/server/tools/sss_usermod.c index 1dfd2a72..b53c8706 100644 --- a/server/tools/sss_usermod.c +++ b/server/tools/sss_usermod.c @@ -182,13 +182,13 @@ static void remove_from_groups(struct ops_ctx *data) struct ldb_dn *member_dn; struct tevent_req *req; - member_dn = sysdb_user_dn(data->ctx->sysdb, data, + member_dn = sysdb_user_dn(data->sysdb, data, data->domain->name, data->name); if (!member_dn) { return mod_user_done(data, ENOMEM); } - parent_dn = sysdb_group_dn(data->ctx->sysdb, data, + parent_dn = sysdb_group_dn(data->sysdb, data, data->domain->name, data->rmgroups[data->cur]); if (!parent_dn) { @@ -239,13 +239,13 @@ static void add_to_groups(struct ops_ctx *data) struct ldb_dn *member_dn; struct tevent_req *req; - member_dn = sysdb_user_dn(data->ctx->sysdb, data, + member_dn = sysdb_user_dn(data->sysdb, data, data->domain->name, data->name); if (!member_dn) { return mod_user_done(data, ENOMEM); } - parent_dn = sysdb_group_dn(data->ctx->sysdb, data, + parent_dn = sysdb_group_dn(data->sysdb, data, data->domain->name, data->addgroups[data->cur]); if (!parent_dn) { @@ -589,7 +589,15 @@ int main(int argc, const char **argv) "Could not add attribute to changeset\n"); } - req = sysdb_transaction_send(ctx, ctx->ev, ctx->sysdb); + ret = sysdb_get_ctx_from_list(ctx->db_list, data->domain, &data->sysdb); + if (ret != EOK) { + DEBUG(0, ("Cannot get domain database!\n")); + ERROR("Internal error accesing database\n"); + ret = EXIT_FAILURE; + goto fini; + } + + req = sysdb_transaction_send(ctx, ctx->ev, data->sysdb); if (!req) { DEBUG(1, ("Could not start transaction (%d)[%s]\n", ret, strerror(ret))); ERROR("Transaction error. Could not modify user.\n"); diff --git a/server/tools/tools_util.c b/server/tools/tools_util.c index 62013994..3b16f593 100644 --- a/server/tools/tools_util.c +++ b/server/tools/tools_util.c @@ -167,7 +167,7 @@ int setup_db(struct tools_ctx **tools_ctx) return ret; } - ret = confdb_get_domains(ctx->confdb, ctx, &ctx->domains); + ret = confdb_get_domains(ctx->confdb, &ctx->domains); if (ret != EOK) { DEBUG(1, ("Could not get domains")); talloc_free(ctx); @@ -175,7 +175,7 @@ int setup_db(struct tools_ctx **tools_ctx) } /* open sysdb at default path */ - ret = sysdb_init(ctx, ctx->ev, ctx->confdb, NULL, &ctx->sysdb); + ret = sysdb_init(ctx, ctx->ev, ctx->confdb, NULL, false, &ctx->db_list); if (ret != EOK) { DEBUG(1, ("Could not initialize connection to the sysdb")); talloc_free(ctx); diff --git a/server/tools/tools_util.h b/server/tools/tools_util.h index 772ba36b..5e2dd95c 100644 --- a/server/tools/tools_util.h +++ b/server/tools/tools_util.h @@ -43,7 +43,7 @@ enum id_domain { struct tools_ctx { struct tevent_context *ev; struct confdb_ctx *confdb; - struct sysdb_ctx *sysdb; + struct sysdb_ctx_list *db_list; struct sss_names_ctx *snctx; struct sss_domain_info *domains; @@ -53,6 +53,7 @@ struct ops_ctx { struct tools_ctx *ctx; struct tevent_context *ev; struct sss_domain_info *domain; + struct sysdb_ctx *sysdb; char *name; uid_t uid; diff --git a/server/util/backup_file.c b/server/util/backup_file.c new file mode 100644 index 00000000..cf9ddf30 --- /dev/null +++ b/server/util/backup_file.c @@ -0,0 +1,122 @@ +/* + SSSD + + Backup files + + Copyright (C) Simo Sorce 2009 + + 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "util/util.h" +#include +#include +#include + +#define BUFFER_SIZE 65536 + +int backup_file(const char *src_file, int dbglvl) +{ + TALLOC_CTX *tmp_ctx = NULL; + char buf[BUFFER_SIZE]; + int src_fd = -1; + int dst_fd = -1; + char *dst_file; + ssize_t count; + ssize_t num; + ssize_t pos; + int ret, i; + + src_fd = open(src_file, O_RDONLY); + if (src_fd < 0) { + ret = errno; + DEBUG(dbglvl, ("Error (%d [%s]) opening source file %s\n", + ret, strerror(ret), src_file)); + goto done; + } + + tmp_ctx = talloc_new(NULL); + if (!tmp_ctx) { + ret = ENOMEM; + goto done; + } + + /* try a few times to come up with a new backup file, then give up */ + for (i = 0; i < 10; i++) { + if (i == 0) { + dst_file = talloc_asprintf(tmp_ctx, "%s.bak", src_file); + } else { + dst_file = talloc_asprintf(tmp_ctx, "%s.bak%d", src_file, i); + } + if (!dst_file) { + ret = ENOMEM; + goto done; + } + + errno = 0; + dst_fd = open(dst_file, O_CREAT|O_EXCL|O_WRONLY, 0600); + ret = errno; + + if (dst_fd > 0) break; + + if (ret != EEXIST) { + DEBUG(dbglvl, ("Error (%d [%s]) opening destination file %s\n", + ret, strerror(ret), dst_file)); + goto done; + } + } + if (ret != 0) { + DEBUG(dbglvl, ("Error (%d [%s]) opening destination file %s\n", + ret, strerror(ret), dst_file)); + goto done; + } + + /* copy file contents */ + while (1) { + num = read(src_fd, buf, BUFFER_SIZE); + if (num < 0) { + if (errno == EINTR) continue; + ret = errno; + DEBUG(dbglvl, ("Error (%d [%s]) reading from source %s\n", + ret, strerror(ret), src_file)); + goto done; + } + if (num == 0) break; + + count = num; + + while (count > 0) { + pos = 0; + errno = 0; + num = write(dst_fd, &buf[pos], count); + if (num < 0) { + if (errno == EINTR) continue; + ret = errno; + DEBUG(dbglvl, ("Error (%d [%s]) writing to destination %s\n", + ret, strerror(ret), dst_file)); + goto done; + } + pos += num; + count -= num; + } + } + + ret = EOK; + +done: + if (src_fd != -1) close(src_fd); + if (dst_fd != -1) close(dst_fd); + talloc_free(tmp_ctx); + return ret; +} diff --git a/server/util/util.h b/server/util/util.h index f289f9c5..93e5dc97 100644 --- a/server/util/util.h +++ b/server/util/util.h @@ -157,4 +157,7 @@ int sss_parse_name(TALLOC_CTX *memctx, struct sss_names_ctx *snctx, const char *orig, char **domain, char **name); +/* from backup-file.c */ +int backup_file(const char *src, int dbglvl); + #endif /* __SSSD_UTIL_H__ */ -- cgit