summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.am1
-rw-r--r--src/db/sysdb.c526
-rw-r--r--src/db/sysdb_init.c553
3 files changed, 554 insertions, 526 deletions
diff --git a/Makefile.am b/Makefile.am
index ba4b0b47c..3b90602e3 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -863,6 +863,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 80feb8266..fcdea0e01 100644
--- a/src/db/sysdb.c
+++ b/src/db/sysdb.c
@@ -29,45 +29,6 @@
#include "util/probes.h"
#include <time.h>
-#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)
{
@@ -962,493 +923,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 000000000..76783d619
--- /dev/null
+++ b/src/db/sysdb_init.c
@@ -0,0 +1,553 @@
+/*
+ SSSD
+
+ System Database - initialization
+
+ Copyright (C) 2008-2011 Simo Sorce <ssorce@redhat.com>
+ Copyright (C) 2008-2011 Stephen Gallagher <ssorce@redhat.com>
+
+ 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 <http://www.gnu.org/licenses/>.
+*/
+
+#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 <time.h>
+
+#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);
+}