From 415bec61cd8f2eeb52445ee7a6923b46530f6bbc Mon Sep 17 00:00:00 2001 From: Jakub Hrozek Date: Wed, 20 Apr 2016 15:33:26 +0200 Subject: [PATCH 01/14] SYSDB: Move sysdb initialization into a new module sysdb_init.c The sysdb initialization was in the sysdb.c module. With adding initialization of the timestamp cache, this module would become too big with too many private functions meant only for initialization. This patch only moves code around, there are no functional changes to the initialization. --- Makefile.am | 1 + src/db/sysdb.c | 526 ------------------------------------------------- src/db/sysdb_init.c | 553 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 554 insertions(+), 526 deletions(-) create mode 100644 src/db/sysdb_init.c diff --git a/Makefile.am b/Makefile.am index 3a9858fcfc1c2c9564e881cd4bd8e322ee0cd087..f8e9d15153e166c3ab0c79887b7371692b33fe2f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -827,6 +827,7 @@ libsss_util_la_SOURCES = \ src/db/sysdb_search.c \ src/db/sysdb_selinux.c \ src/db/sysdb_upgrade.c \ + src/db/sysdb_init.c \ src/db/sysdb_services.c \ src/db/sysdb_autofs.c \ src/db/sysdb_subdomains.c \ diff --git a/src/db/sysdb.c b/src/db/sysdb.c index dca8332e2d313dc53f334337ff41d1bcb503b9be..bf47a9d3942a0bc8eb3d12fb8462caa854bd22c9 100644 --- a/src/db/sysdb.c +++ b/src/db/sysdb.c @@ -28,45 +28,6 @@ #include "util/probes.h" #include -#define LDB_MODULES_PATH "LDB_MODULES_PATH" - -errno_t sysdb_ldb_connect(TALLOC_CTX *mem_ctx, const char *filename, - struct ldb_context **_ldb) -{ - int ret; - struct ldb_context *ldb; - const char *mod_path; - - if (_ldb == NULL) { - return EINVAL; - } - - ldb = ldb_init(mem_ctx, NULL); - if (!ldb) { - return EIO; - } - - ret = ldb_set_debug(ldb, ldb_debug_messages, NULL); - if (ret != LDB_SUCCESS) { - return EIO; - } - - mod_path = getenv(LDB_MODULES_PATH); - if (mod_path != NULL) { - DEBUG(SSSDBG_TRACE_ALL, "Setting ldb module path to [%s].\n", mod_path); - ldb_set_modules_dir(ldb, mod_path); - } - - ret = ldb_connect(ldb, filename, 0, NULL); - if (ret != LDB_SUCCESS) { - return EIO; - } - - *_ldb = ldb; - - return EOK; -} - errno_t sysdb_dn_sanitize(TALLOC_CTX *mem_ctx, const char *input, char **sanitized) { @@ -940,493 +901,6 @@ int sysdb_transaction_cancel(struct sysdb_ctx *sysdb) return sysdb_error_to_errno(ret); } -/* =Initialization======================================================== */ - -int sysdb_get_db_file(TALLOC_CTX *mem_ctx, - const char *provider, const char *name, - const char *base_path, char **_ldb_file) -{ - char *ldb_file; - - /* special case for the local domain */ - if (strcasecmp(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, name); - } - if (!ldb_file) { - return ENOMEM; - } - - *_ldb_file = ldb_file; - return EOK; -} - -errno_t sysdb_domain_create(struct sysdb_ctx *sysdb, const char *domain_name) -{ - struct ldb_message *msg; - TALLOC_CTX *tmp_ctx; - int ret; - - tmp_ctx = talloc_new(NULL); - if (tmp_ctx == NULL) { - ret = ENOMEM; - goto done; - } - - /* == create base domain object == */ - - msg = ldb_msg_new(tmp_ctx); - if (!msg) { - ret = ENOMEM; - goto done; - } - msg->dn = ldb_dn_new_fmt(msg, sysdb->ldb, SYSDB_DOM_BASE, domain_name); - if (!msg->dn) { - ret = ENOMEM; - goto done; - } - ret = ldb_msg_add_string(msg, "cn", domain_name); - if (ret != LDB_SUCCESS) { - ret = EIO; - goto done; - } - /* do a synchronous add */ - ret = ldb_add(sysdb->ldb, msg); - if (ret != LDB_SUCCESS) { - DEBUG(SSSDBG_FATAL_FAILURE, "Failed to initialize DB (%d, [%s]) " - "for domain %s!\n", - ret, ldb_errstring(sysdb->ldb), - domain_name); - ret = EIO; - goto done; - } - talloc_zfree(msg); - - /* == create Users tree == */ - - msg = ldb_msg_new(tmp_ctx); - if (!msg) { - ret = ENOMEM; - goto done; - } - msg->dn = ldb_dn_new_fmt(msg, sysdb->ldb, - SYSDB_TMPL_USER_BASE, domain_name); - if (!msg->dn) { - ret = ENOMEM; - goto done; - } - ret = ldb_msg_add_string(msg, "cn", "Users"); - if (ret != LDB_SUCCESS) { - ret = EIO; - goto done; - } - /* do a synchronous add */ - ret = ldb_add(sysdb->ldb, msg); - if (ret != LDB_SUCCESS) { - DEBUG(SSSDBG_FATAL_FAILURE, "Failed to initialize DB (%d, [%s]) " - "for domain %s!\n", - ret, ldb_errstring(sysdb->ldb), - domain_name); - ret = EIO; - goto done; - } - talloc_zfree(msg); - - /* == create Groups tree == */ - - msg = ldb_msg_new(tmp_ctx); - if (!msg) { - ret = ENOMEM; - goto done; - } - msg->dn = ldb_dn_new_fmt(msg, sysdb->ldb, - SYSDB_TMPL_GROUP_BASE, domain_name); - if (!msg->dn) { - ret = ENOMEM; - goto done; - } - ret = ldb_msg_add_string(msg, "cn", "Groups"); - if (ret != LDB_SUCCESS) { - ret = EIO; - goto done; - } - /* do a synchronous add */ - ret = ldb_add(sysdb->ldb, msg); - if (ret != LDB_SUCCESS) { - DEBUG(SSSDBG_FATAL_FAILURE, "Failed to initialize DB (%d, [%s]) for " - "domain %s!\n", - ret, ldb_errstring(sysdb->ldb), - domain_name); - ret = EIO; - goto done; - } - talloc_zfree(msg); - - ret = EOK; - -done: - talloc_zfree(tmp_ctx); - return ret; -} - -/* Compare versions of sysdb, returns ERRNO accordingly */ -static errno_t -sysdb_version_check(const char *expected, - const char *received) -{ - int ret; - unsigned int exp_major, exp_minor, recv_major, recv_minor; - - ret = sscanf(expected, "%u.%u", &exp_major, &exp_minor); - if (ret != 2) { - return EINVAL; - } - ret = sscanf(received, "%u.%u", &recv_major, &recv_minor); - if (ret != 2) { - return EINVAL; - } - - if (recv_major > exp_major) { - return EUCLEAN; - } else if (recv_major < exp_major) { - return EMEDIUMTYPE; - } - - if (recv_minor > exp_minor) { - return EUCLEAN; - } else if (recv_minor < exp_minor) { - return EMEDIUMTYPE; - } - - return EOK; -} - -int sysdb_domain_init_internal(TALLOC_CTX *mem_ctx, - struct sss_domain_info *domain, - const char *db_path, - bool allow_upgrade, - struct sysdb_ctx **_ctx) -{ - TALLOC_CTX *tmp_ctx = NULL; - struct sysdb_ctx *sysdb; - 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; - - sysdb = talloc_zero(mem_ctx, struct sysdb_ctx); - if (!sysdb) { - return ENOMEM; - } - - ret = sysdb_get_db_file(sysdb, domain->provider, - domain->name, db_path, - &sysdb->ldb_file); - if (ret != EOK) { - goto done; - } - DEBUG(SSSDBG_FUNC_DATA, - "DB File for %s: %s\n", domain->name, sysdb->ldb_file); - - ret = sysdb_ldb_connect(sysdb, sysdb->ldb_file, &sysdb->ldb); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_ldb_connect failed.\n"); - goto done; - } - - tmp_ctx = talloc_new(NULL); - if (!tmp_ctx) { - ret = ENOMEM; - goto done; - } - - verdn = ldb_dn_new(tmp_ctx, sysdb->ldb, SYSDB_BASE); - if (!verdn) { - ret = EIO; - goto done; - } - - ret = ldb_search(sysdb->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) { - ret = EIO; - goto done; - } - - 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(SSSDBG_FATAL_FAILURE, - "Wrong DB version (got %s expected %s)\n", - version, SYSDB_VERSION); - ret = sysdb_version_check(SYSDB_VERSION, version); - goto done; - } - - DEBUG(SSSDBG_CONF_SETTINGS, "Upgrading DB [%s] from version: %s\n", - domain->name, version); - - if (strcmp(version, SYSDB_VERSION_0_3) == 0) { - ret = sysdb_upgrade_03(sysdb, &version); - if (ret != EOK) { - goto done; - } - } - - if (strcmp(version, SYSDB_VERSION_0_4) == 0) { - ret = sysdb_upgrade_04(sysdb, &version); - if (ret != EOK) { - goto done; - } - } - - if (strcmp(version, SYSDB_VERSION_0_5) == 0) { - ret = sysdb_upgrade_05(sysdb, &version); - if (ret != EOK) { - goto done; - } - } - - if (strcmp(version, SYSDB_VERSION_0_6) == 0) { - ret = sysdb_upgrade_06(sysdb, &version); - if (ret != EOK) { - goto done; - } - } - - if (strcmp(version, SYSDB_VERSION_0_7) == 0) { - ret = sysdb_upgrade_07(sysdb, &version); - if (ret != EOK) { - goto done; - } - } - - if (strcmp(version, SYSDB_VERSION_0_8) == 0) { - ret = sysdb_upgrade_08(sysdb, &version); - if (ret != EOK) { - goto done; - } - } - - if (strcmp(version, SYSDB_VERSION_0_9) == 0) { - ret = sysdb_upgrade_09(sysdb, &version); - if (ret != EOK) { - goto done; - } - } - - if (strcmp(version, SYSDB_VERSION_0_10) == 0) { - ret = sysdb_upgrade_10(sysdb, domain, &version); - if (ret != EOK) { - goto done; - } - } - - if (strcmp(version, SYSDB_VERSION_0_11) == 0) { - ret = sysdb_upgrade_11(sysdb, domain, &version); - if (ret != EOK) { - goto done; - } - } - - if (strcmp(version, SYSDB_VERSION_0_12) == 0) { - ret = sysdb_upgrade_12(sysdb, &version); - if (ret != EOK) { - goto done; - } - } - - if (strcmp(version, SYSDB_VERSION_0_13) == 0) { - ret = sysdb_upgrade_13(sysdb, &version); - if (ret != EOK) { - goto done; - } - } - - if (strcmp(version, SYSDB_VERSION_0_14) == 0) { - ret = sysdb_upgrade_14(sysdb, &version); - if (ret != EOK) { - goto done; - } - } - - if (strcmp(version, SYSDB_VERSION_0_15) == 0) { - ret = sysdb_upgrade_15(sysdb, &version); - if (ret != EOK) { - goto done; - } - } - - if (strcmp(version, SYSDB_VERSION_0_16) == 0) { - ret = sysdb_upgrade_16(sysdb, &version); - if (ret != EOK) { - goto done; - } - } - - /* The version should now match SYSDB_VERSION. - * If not, it means we didn't match any of the - * known older versions. The DB might be - * corrupt or generated by a newer version of - * SSSD. - */ - if (strcmp(version, SYSDB_VERSION) == 0) { - /* The cache has been upgraded. - * We need to reopen the LDB to ensure that - * any changes made above take effect. - */ - talloc_zfree(sysdb->ldb); - ret = sysdb_ldb_connect(sysdb, sysdb->ldb_file, &sysdb->ldb); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_ldb_connect failed.\n"); - } - goto done; - } - - DEBUG(SSSDBG_FATAL_FAILURE, - "Unknown DB version [%s], expected [%s] for domain %s!\n", - version, SYSDB_VERSION, domain->name); - ret = sysdb_version_check(SYSDB_VERSION, version); - goto done; - } - - /* SYSDB_BASE does not exists, means db is empty, populate */ - - base_ldif = SYSDB_BASE_LDIF; - while ((ldif = ldb_ldif_read_string(sysdb->ldb, &base_ldif))) { - ret = ldb_add(sysdb->ldb, ldif->msg); - if (ret != LDB_SUCCESS) { - DEBUG(SSSDBG_FATAL_FAILURE, - "Failed to initialize DB (%d, [%s]) for domain %s!\n", - ret, ldb_errstring(sysdb->ldb), domain->name); - ret = EIO; - goto done; - } - ldb_ldif_read_free(sysdb->ldb, ldif); - } - - ret = sysdb_domain_create(sysdb, domain->name); - if (ret != EOK) { - goto done; - } - - /* The cache has been newly created. - * We need to reopen the LDB to ensure that - * all of the special values take effect - * (such as enabling the memberOf plugin and - * the various indexes). - */ - talloc_zfree(sysdb->ldb); - ret = sysdb_ldb_connect(sysdb, sysdb->ldb_file, &sysdb->ldb); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_ldb_connect failed.\n"); - } - -done: - talloc_free(tmp_ctx); - if (ret == EOK) { - *_ctx = sysdb; - } else { - talloc_free(sysdb); - } - return ret; -} - -int sysdb_init(TALLOC_CTX *mem_ctx, - struct sss_domain_info *domains, - bool allow_upgrade) -{ - return sysdb_init_ext(mem_ctx, domains, allow_upgrade, false, 0, 0); -} - -int sysdb_init_ext(TALLOC_CTX *mem_ctx, - struct sss_domain_info *domains, - bool allow_upgrade, - bool chown_dbfile, - uid_t uid, - gid_t gid) -{ - struct sss_domain_info *dom; - struct sysdb_ctx *sysdb; - int ret; - - if (allow_upgrade) { - /* check if we have an old sssd.ldb to upgrade */ - ret = sysdb_check_upgrade_02(domains, DB_PATH); - if (ret != EOK) { - return ret; - } - } - - /* open a db for each domain */ - for (dom = domains; dom; dom = dom->next) { - - ret = sysdb_domain_init_internal(mem_ctx, dom, DB_PATH, - allow_upgrade, &sysdb); - if (ret != EOK) { - return ret; - } - - if (chown_dbfile) { - ret = chown(sysdb->ldb_file, uid, gid); - if (ret != 0) { - ret = errno; - DEBUG(SSSDBG_CRIT_FAILURE, - "Cannot set sysdb ownership to %"SPRIuid":%"SPRIgid"\n", - uid, gid); - return ret; - } - } - - dom->sysdb = talloc_move(dom, &sysdb); - } - - return EOK; -} - -int sysdb_domain_init(TALLOC_CTX *mem_ctx, - struct sss_domain_info *domain, - const char *db_path, - struct sysdb_ctx **_ctx) -{ - return sysdb_domain_init_internal(mem_ctx, domain, - db_path, false, _ctx); -} - int compare_ldb_dn_comp_num(const void *m1, const void *m2) { struct ldb_message *msg1 = talloc_get_type(*(void **) discard_const(m1), diff --git a/src/db/sysdb_init.c b/src/db/sysdb_init.c new file mode 100644 index 0000000000000000000000000000000000000000..76783d619623c9528577ae2757660d0efd0c27a2 --- /dev/null +++ b/src/db/sysdb_init.c @@ -0,0 +1,553 @@ +/* + SSSD + + System Database - initialization + + Copyright (C) 2008-2011 Simo Sorce + Copyright (C) 2008-2011 Stephen Gallagher + + 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 "util/strtonum.h" +#include "util/sss_utf8.h" +#include "db/sysdb_private.h" +#include "confdb/confdb.h" +#include "util/probes.h" +#include + +#define LDB_MODULES_PATH "LDB_MODULES_PATH" + +errno_t sysdb_ldb_connect(TALLOC_CTX *mem_ctx, const char *filename, + struct ldb_context **_ldb) +{ + int ret; + struct ldb_context *ldb; + const char *mod_path; + + if (_ldb == NULL) { + return EINVAL; + } + + ldb = ldb_init(mem_ctx, NULL); + if (!ldb) { + return EIO; + } + + ret = ldb_set_debug(ldb, ldb_debug_messages, NULL); + if (ret != LDB_SUCCESS) { + return EIO; + } + + mod_path = getenv(LDB_MODULES_PATH); + if (mod_path != NULL) { + DEBUG(SSSDBG_TRACE_ALL, "Setting ldb module path to [%s].\n", mod_path); + ldb_set_modules_dir(ldb, mod_path); + } + + ret = ldb_connect(ldb, filename, 0, NULL); + if (ret != LDB_SUCCESS) { + return EIO; + } + + *_ldb = ldb; + + return EOK; +} + +int sysdb_get_db_file(TALLOC_CTX *mem_ctx, + const char *provider, const char *name, + const char *base_path, char **_ldb_file) +{ + char *ldb_file; + + /* special case for the local domain */ + if (strcasecmp(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, name); + } + if (!ldb_file) { + return ENOMEM; + } + + *_ldb_file = ldb_file; + return EOK; +} + +errno_t sysdb_domain_create(struct sysdb_ctx *sysdb, const char *domain_name) +{ + struct ldb_message *msg; + TALLOC_CTX *tmp_ctx; + int ret; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + ret = ENOMEM; + goto done; + } + + /* == create base domain object == */ + + msg = ldb_msg_new(tmp_ctx); + if (!msg) { + ret = ENOMEM; + goto done; + } + msg->dn = ldb_dn_new_fmt(msg, sysdb->ldb, SYSDB_DOM_BASE, domain_name); + if (!msg->dn) { + ret = ENOMEM; + goto done; + } + ret = ldb_msg_add_string(msg, "cn", domain_name); + if (ret != LDB_SUCCESS) { + ret = EIO; + goto done; + } + /* do a synchronous add */ + ret = ldb_add(sysdb->ldb, msg); + if (ret != LDB_SUCCESS) { + DEBUG(SSSDBG_FATAL_FAILURE, "Failed to initialize DB (%d, [%s]) " + "for domain %s!\n", + ret, ldb_errstring(sysdb->ldb), + domain_name); + ret = EIO; + goto done; + } + talloc_zfree(msg); + + /* == create Users tree == */ + + msg = ldb_msg_new(tmp_ctx); + if (!msg) { + ret = ENOMEM; + goto done; + } + msg->dn = ldb_dn_new_fmt(msg, sysdb->ldb, + SYSDB_TMPL_USER_BASE, domain_name); + if (!msg->dn) { + ret = ENOMEM; + goto done; + } + ret = ldb_msg_add_string(msg, "cn", "Users"); + if (ret != LDB_SUCCESS) { + ret = EIO; + goto done; + } + /* do a synchronous add */ + ret = ldb_add(sysdb->ldb, msg); + if (ret != LDB_SUCCESS) { + DEBUG(SSSDBG_FATAL_FAILURE, "Failed to initialize DB (%d, [%s]) " + "for domain %s!\n", + ret, ldb_errstring(sysdb->ldb), + domain_name); + ret = EIO; + goto done; + } + talloc_zfree(msg); + + /* == create Groups tree == */ + + msg = ldb_msg_new(tmp_ctx); + if (!msg) { + ret = ENOMEM; + goto done; + } + msg->dn = ldb_dn_new_fmt(msg, sysdb->ldb, + SYSDB_TMPL_GROUP_BASE, domain_name); + if (!msg->dn) { + ret = ENOMEM; + goto done; + } + ret = ldb_msg_add_string(msg, "cn", "Groups"); + if (ret != LDB_SUCCESS) { + ret = EIO; + goto done; + } + /* do a synchronous add */ + ret = ldb_add(sysdb->ldb, msg); + if (ret != LDB_SUCCESS) { + DEBUG(SSSDBG_FATAL_FAILURE, "Failed to initialize DB (%d, [%s]) for " + "domain %s!\n", + ret, ldb_errstring(sysdb->ldb), + domain_name); + ret = EIO; + goto done; + } + talloc_zfree(msg); + + ret = EOK; + +done: + talloc_zfree(tmp_ctx); + return ret; +} + +/* Compare versions of sysdb, returns ERRNO accordingly */ +static errno_t +sysdb_version_check(const char *expected, + const char *received) +{ + int ret; + unsigned int exp_major, exp_minor, recv_major, recv_minor; + + ret = sscanf(expected, "%u.%u", &exp_major, &exp_minor); + if (ret != 2) { + return EINVAL; + } + ret = sscanf(received, "%u.%u", &recv_major, &recv_minor); + if (ret != 2) { + return EINVAL; + } + + if (recv_major > exp_major) { + return EUCLEAN; + } else if (recv_major < exp_major) { + return EMEDIUMTYPE; + } + + if (recv_minor > exp_minor) { + return EUCLEAN; + } else if (recv_minor < exp_minor) { + return EMEDIUMTYPE; + } + + return EOK; +} + +int sysdb_domain_init_internal(TALLOC_CTX *mem_ctx, + struct sss_domain_info *domain, + const char *db_path, + bool allow_upgrade, + struct sysdb_ctx **_ctx) +{ + TALLOC_CTX *tmp_ctx = NULL; + struct sysdb_ctx *sysdb; + 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; + + sysdb = talloc_zero(mem_ctx, struct sysdb_ctx); + if (!sysdb) { + return ENOMEM; + } + + ret = sysdb_get_db_file(sysdb, domain->provider, + domain->name, db_path, + &sysdb->ldb_file); + if (ret != EOK) { + goto done; + } + DEBUG(SSSDBG_FUNC_DATA, + "DB File for %s: %s\n", domain->name, sysdb->ldb_file); + + ret = sysdb_ldb_connect(sysdb, sysdb->ldb_file, &sysdb->ldb); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_ldb_connect failed.\n"); + goto done; + } + + tmp_ctx = talloc_new(NULL); + if (!tmp_ctx) { + ret = ENOMEM; + goto done; + } + + verdn = ldb_dn_new(tmp_ctx, sysdb->ldb, SYSDB_BASE); + if (!verdn) { + ret = EIO; + goto done; + } + + ret = ldb_search(sysdb->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) { + ret = EIO; + goto done; + } + + 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(SSSDBG_FATAL_FAILURE, + "Wrong DB version (got %s expected %s)\n", + version, SYSDB_VERSION); + ret = sysdb_version_check(SYSDB_VERSION, version); + goto done; + } + + DEBUG(SSSDBG_CONF_SETTINGS, "Upgrading DB [%s] from version: %s\n", + domain->name, version); + + if (strcmp(version, SYSDB_VERSION_0_3) == 0) { + ret = sysdb_upgrade_03(sysdb, &version); + if (ret != EOK) { + goto done; + } + } + + if (strcmp(version, SYSDB_VERSION_0_4) == 0) { + ret = sysdb_upgrade_04(sysdb, &version); + if (ret != EOK) { + goto done; + } + } + + if (strcmp(version, SYSDB_VERSION_0_5) == 0) { + ret = sysdb_upgrade_05(sysdb, &version); + if (ret != EOK) { + goto done; + } + } + + if (strcmp(version, SYSDB_VERSION_0_6) == 0) { + ret = sysdb_upgrade_06(sysdb, &version); + if (ret != EOK) { + goto done; + } + } + + if (strcmp(version, SYSDB_VERSION_0_7) == 0) { + ret = sysdb_upgrade_07(sysdb, &version); + if (ret != EOK) { + goto done; + } + } + + if (strcmp(version, SYSDB_VERSION_0_8) == 0) { + ret = sysdb_upgrade_08(sysdb, &version); + if (ret != EOK) { + goto done; + } + } + + if (strcmp(version, SYSDB_VERSION_0_9) == 0) { + ret = sysdb_upgrade_09(sysdb, &version); + if (ret != EOK) { + goto done; + } + } + + if (strcmp(version, SYSDB_VERSION_0_10) == 0) { + ret = sysdb_upgrade_10(sysdb, domain, &version); + if (ret != EOK) { + goto done; + } + } + + if (strcmp(version, SYSDB_VERSION_0_11) == 0) { + ret = sysdb_upgrade_11(sysdb, domain, &version); + if (ret != EOK) { + goto done; + } + } + + if (strcmp(version, SYSDB_VERSION_0_12) == 0) { + ret = sysdb_upgrade_12(sysdb, &version); + if (ret != EOK) { + goto done; + } + } + + if (strcmp(version, SYSDB_VERSION_0_13) == 0) { + ret = sysdb_upgrade_13(sysdb, &version); + if (ret != EOK) { + goto done; + } + } + + if (strcmp(version, SYSDB_VERSION_0_14) == 0) { + ret = sysdb_upgrade_14(sysdb, &version); + if (ret != EOK) { + goto done; + } + } + + if (strcmp(version, SYSDB_VERSION_0_15) == 0) { + ret = sysdb_upgrade_15(sysdb, &version); + if (ret != EOK) { + goto done; + } + } + + if (strcmp(version, SYSDB_VERSION_0_16) == 0) { + ret = sysdb_upgrade_16(sysdb, &version); + if (ret != EOK) { + goto done; + } + } + + /* The version should now match SYSDB_VERSION. + * If not, it means we didn't match any of the + * known older versions. The DB might be + * corrupt or generated by a newer version of + * SSSD. + */ + if (strcmp(version, SYSDB_VERSION) == 0) { + /* The cache has been upgraded. + * We need to reopen the LDB to ensure that + * any changes made above take effect. + */ + talloc_zfree(sysdb->ldb); + ret = sysdb_ldb_connect(sysdb, sysdb->ldb_file, &sysdb->ldb); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_ldb_connect failed.\n"); + } + goto done; + } + + DEBUG(SSSDBG_FATAL_FAILURE, + "Unknown DB version [%s], expected [%s] for domain %s!\n", + version, SYSDB_VERSION, domain->name); + ret = sysdb_version_check(SYSDB_VERSION, version); + goto done; + } + + /* SYSDB_BASE does not exists, means db is empty, populate */ + + base_ldif = SYSDB_BASE_LDIF; + while ((ldif = ldb_ldif_read_string(sysdb->ldb, &base_ldif))) { + ret = ldb_add(sysdb->ldb, ldif->msg); + if (ret != LDB_SUCCESS) { + DEBUG(SSSDBG_FATAL_FAILURE, + "Failed to initialize DB (%d, [%s]) for domain %s!\n", + ret, ldb_errstring(sysdb->ldb), domain->name); + ret = EIO; + goto done; + } + ldb_ldif_read_free(sysdb->ldb, ldif); + } + + ret = sysdb_domain_create(sysdb, domain->name); + if (ret != EOK) { + goto done; + } + + /* The cache has been newly created. + * We need to reopen the LDB to ensure that + * all of the special values take effect + * (such as enabling the memberOf plugin and + * the various indexes). + */ + talloc_zfree(sysdb->ldb); + ret = sysdb_ldb_connect(sysdb, sysdb->ldb_file, &sysdb->ldb); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_ldb_connect failed.\n"); + } + +done: + talloc_free(tmp_ctx); + if (ret == EOK) { + *_ctx = sysdb; + } else { + talloc_free(sysdb); + } + return ret; +} + +int sysdb_init(TALLOC_CTX *mem_ctx, + struct sss_domain_info *domains, + bool allow_upgrade) +{ + return sysdb_init_ext(mem_ctx, domains, allow_upgrade, false, 0, 0); +} + +int sysdb_init_ext(TALLOC_CTX *mem_ctx, + struct sss_domain_info *domains, + bool allow_upgrade, + bool chown_dbfile, + uid_t uid, + gid_t gid) +{ + struct sss_domain_info *dom; + struct sysdb_ctx *sysdb; + int ret; + + if (allow_upgrade) { + /* check if we have an old sssd.ldb to upgrade */ + ret = sysdb_check_upgrade_02(domains, DB_PATH); + if (ret != EOK) { + return ret; + } + } + + /* open a db for each domain */ + for (dom = domains; dom; dom = dom->next) { + + ret = sysdb_domain_init_internal(mem_ctx, dom, DB_PATH, + allow_upgrade, &sysdb); + if (ret != EOK) { + return ret; + } + + if (chown_dbfile) { + ret = chown(sysdb->ldb_file, uid, gid); + if (ret != 0) { + ret = errno; + DEBUG(SSSDBG_CRIT_FAILURE, + "Cannot set sysdb ownership to %"SPRIuid":%"SPRIgid"\n", + uid, gid); + return ret; + } + } + + dom->sysdb = talloc_move(dom, &sysdb); + } + + return EOK; +} + +int sysdb_domain_init(TALLOC_CTX *mem_ctx, + struct sss_domain_info *domain, + const char *db_path, + struct sysdb_ctx **_ctx) +{ + return sysdb_domain_init_internal(mem_ctx, domain, + db_path, false, _ctx); +} -- 2.4.11