/* SSSD System Database 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 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 "db/sysdb_private.h" #include "confdb/confdb.h" #include struct ldb_dn *sysdb_user_dn(struct sysdb_ctx *ctx, void *memctx, const char *domain, const char *name) { return ldb_dn_new_fmt(memctx, ctx->ldb, SYSDB_TMPL_USER, name, domain); } struct ldb_dn *sysdb_group_dn(struct sysdb_ctx *ctx, void *memctx, const char *domain, const char *name) { return ldb_dn_new_fmt(memctx, ctx->ldb, SYSDB_TMPL_GROUP, name, domain); } struct ldb_dn *sysdb_domain_dn(struct sysdb_ctx *ctx, void *memctx, const char *domain) { return ldb_dn_new_fmt(memctx, ctx->ldb, SYSDB_DOM_BASE, domain); } struct ldb_context *sysdb_ctx_get_ldb(struct sysdb_ctx *ctx) { return ctx->ldb; } struct sysdb_attrs *sysdb_new_attrs(TALLOC_CTX *memctx) { return talloc_zero(memctx, struct sysdb_attrs); } static int sysdb_attrs_get_el(struct sysdb_attrs *attrs, const char *name, struct ldb_message_element **el) { struct ldb_message_element *e = NULL; int i; for (i = 0; i < attrs->num; i++) { if (strcasecmp(name, attrs->a[i].name) == 0) e = &(attrs->a[i]); } if (!e) { e = talloc_realloc(attrs, attrs->a, struct ldb_message_element, attrs->num+1); if (!e) return ENOMEM; attrs->a = e; e[attrs->num].name = talloc_strdup(e, name); if (!e[attrs->num].name) return ENOMEM; e[attrs->num].num_values = 0; e[attrs->num].values = NULL; e[attrs->num].flags = 0; e = &(attrs->a[attrs->num]); attrs->num++; } *el = e; return EOK; } int sysdb_attrs_add_val(struct sysdb_attrs *attrs, const char *name, const struct ldb_val *val) { struct ldb_message_element *el = NULL; struct ldb_val *vals; int ret; ret = sysdb_attrs_get_el(attrs, name, &el); vals = talloc_realloc(attrs->a, el->values, struct ldb_val, el->num_values+1); if (!vals) return ENOMEM; vals[el->num_values] = ldb_val_dup(vals, val); if (vals[el->num_values].data == NULL && vals[el->num_values].length != 0) { return ENOMEM; } el->values = vals; el->num_values++; return EOK; } int sysdb_attrs_add_string(struct sysdb_attrs *attrs, const char *name, const char *str) { struct ldb_val v; v.data = (uint8_t *)discard_const(str); v.length = strlen(str); return sysdb_attrs_add_val(attrs, name, &v); } int sysdb_attrs_add_long(struct sysdb_attrs *attrs, const char *name, long value) { struct ldb_val v; char *str; int ret; str = talloc_asprintf(attrs, "%ld", value); if (!str) return ENOMEM; v.data = (uint8_t *)str; v.length = strlen(str); ret = sysdb_attrs_add_val(attrs, name, &v); talloc_free(str); return ret; } /* TODO: make a more complete and precise mapping */ int sysdb_error_to_errno(int ldberr) { switch (ldberr) { case LDB_SUCCESS: return EOK; case LDB_ERR_OPERATIONS_ERROR: return EIO; case LDB_ERR_NO_SUCH_OBJECT: return ENOENT; case LDB_ERR_BUSY: return EBUSY; case LDB_ERR_ENTRY_ALREADY_EXISTS: return EEXIST; default: return EFAULT; } } /************************************************ * Initialiazation stuff */ static int sysdb_read_var(TALLOC_CTX *mem_ctx, struct confdb_ctx *cdb, const char *name, const char *def_value, char **target) { 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); 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; } 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_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; char *version = NULL; int ret; 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; } } 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; } int sysdb_init(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct confdb_ctx *cdb, const char *alt_db_path, struct sysdb_ctx **_ctx) { struct sysdb_ctx *ctx; int ret; if (!ev) return EINVAL; ctx = talloc_zero(mem_ctx, struct sysdb_ctx); if (!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; } } else { ctx->ldb_file = talloc_strdup(ctx, alt_db_path); } if (ctx->ldb_file == NULL) { return ENOMEM; } DEBUG(3, ("DB Path is: %s\n", 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); if (ret != EOK) { talloc_free(ctx); return ret; } *_ctx = ctx; return EOK; }