From 7de6e3534fd61c7619ed34a6b1afe7230b5e6504 Mon Sep 17 00:00:00 2001 From: Ondrej Kos Date: Thu, 28 Mar 2013 15:35:03 +0100 Subject: DB: Switch to new libini_config API https://fedorahosted.org/sssd/ticket/1786 Since we need to support the old interface as well, the configure scritp is modified and correct ini interface is chosen. --- Makefile.am | 2 + src/confdb/confdb_setup.c | 347 +++++++++---------------- src/external/libini_config.m4 | 24 +- src/monitor/monitor.c | 2 - src/responder/nss/nsssrv_netgroup.c | 2 +- src/responder/nss/nsssrv_services.c | 1 - src/util/sss_ini.c | 488 ++++++++++++++++++++++++++++++++++++ src/util/sss_ini.h | 81 ++++++ 8 files changed, 709 insertions(+), 238 deletions(-) create mode 100644 src/util/sss_ini.c create mode 100644 src/util/sss_ini.h diff --git a/Makefile.am b/Makefile.am index ef180224..c6dfcb2c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -391,6 +391,7 @@ dist_noinst_HEADERS = \ src/util/sss_selinux.h \ src/util/sss_utf8.h \ src/util/sss_ssh.h \ + src/util/sss_ini.h \ src/util/refcount.h \ src/util/find_uid.h \ src/util/user_info_msg.h \ @@ -552,6 +553,7 @@ libsss_util_la_SOURCES = \ src/util/domain_info_utils.c \ src/util/util_lock.c \ src/util/util_errors.c \ + src/util/sss_ini.c \ src/util/io.c libsss_util_la_LIBADD = \ $(SSSD_LIBS) \ diff --git a/src/confdb/confdb_setup.c b/src/confdb/confdb_setup.c index 6c68461f..b13553ea 100644 --- a/src/confdb/confdb_setup.c +++ b/src/confdb/confdb_setup.c @@ -26,9 +26,7 @@ #include "confdb.h" #include "confdb_private.h" #include "confdb_setup.h" -#include "collection.h" -#include "collection_tools.h" -#include "ini_config.h" +#include "util/sss_ini.h" int confdb_test(struct confdb_ctx *cdb) @@ -126,280 +124,159 @@ int confdb_create_base(struct confdb_ctx *cdb) return EOK; } -static int confdb_create_ldif(TALLOC_CTX *mem_ctx, - struct collection_item *sssd_config, - const char **config_ldif) +int confdb_init_db(const char *config_file, struct confdb_ctx *cdb) { - int ret, i, j; - char *ldif; - char *tmp_ldif; - char **sections; - int section_count; - char *dn; - char *tmp_dn; - char *sec_dn; - char **attrs; - int attr_count; - char *ldif_attr; - struct collection_item *attr; TALLOC_CTX *tmp_ctx; - size_t dn_size; - size_t ldif_len; - size_t attr_len; + int ret; + int sret = EOK; + int version; + char timestr[21]; + char *lasttimestr; + bool in_transaction = false; + const char *config_ldif; + const char *vals[2] = { timestr, NULL }; + struct ldb_ldif *ldif; + struct sss_ini_initdata *init_data; - ldif_len = strlen(CONFDB_INTERNAL_LDIF); - ldif = talloc_array(mem_ctx, char, ldif_len+1); - if (!ldif) return ENOMEM; - tmp_ctx = talloc_new(ldif); - if (!tmp_ctx) { - ret = ENOMEM; - goto error; + tmp_ctx = talloc_new(cdb); + if (tmp_ctx == NULL) { + DEBUG(SSSDBG_FATAL_FAILURE, ("Out of memory.\n")); + return ENOMEM; } - memcpy(ldif, CONFDB_INTERNAL_LDIF, ldif_len); - - /* Read in the collection and convert it to an LDIF */ - /* Get the list of sections */ - sections = get_section_list(sssd_config, §ion_count, &ret); - if (ret != EOK) { - goto error; + init_data = sss_ini_initdata_init(tmp_ctx); + if (!init_data) { + DEBUG(SSSDBG_FATAL_FAILURE, ("Out of memory.\n")); + ret = ENOMEM; + goto done; } - for(i = 0; i < section_count; i++) { - const char *rdn = NULL; - DEBUG(6,("Processing config section [%s]\n", sections[i])); - ret = parse_section(tmp_ctx, sections[i], &sec_dn, &rdn); - if (ret != EOK) { - goto error; - } - - dn = talloc_asprintf(tmp_ctx, - "dn: %s,cn=config\n" - "cn: %s\n", - sec_dn, rdn); - if(!dn) { - ret = ENOMEM; - free_section_list(sections); - goto error; - } - dn_size = strlen(dn); - - /* Get all of the attributes and their values as LDIF */ - attrs = get_attribute_list(sssd_config, sections[i], - &attr_count, &ret); - if (ret != EOK) { - free_section_list(sections); - goto error; - } - - for(j = 0; j < attr_count; j++) { - DEBUG(6, ("Processing attribute [%s]\n", attrs[j])); - ret = get_config_item(sections[i], attrs[j], sssd_config, - &attr); - if (ret != EOK) goto error; - - const char *value = get_const_string_config_value(attr, &ret); - if (ret != EOK) goto error; - if (value && value[0] == '\0') { - DEBUG(1, ("Attribute '%s' has empty value, ignoring\n", attrs[j])); - continue; - } - - ldif_attr = talloc_asprintf(tmp_ctx, - "%s: %s\n", attrs[j], value); - DEBUG(9, ("%s", ldif_attr)); - - attr_len = strlen(ldif_attr); - - tmp_dn = talloc_realloc(tmp_ctx, dn, char, - dn_size+attr_len+1); - if(!tmp_dn) { - ret = ENOMEM; - free_attribute_list(attrs); - free_section_list(sections); - goto error; - } - dn = tmp_dn; - memcpy(dn+dn_size, ldif_attr, attr_len+1); - dn_size += attr_len; - } - - dn_size ++; - tmp_dn = talloc_realloc(tmp_ctx, dn, char, - dn_size+1); - if(!tmp_dn) { - ret = ENOMEM; - free_attribute_list(attrs); - free_section_list(sections); - goto error; - } - dn = tmp_dn; - dn[dn_size-1] = '\n'; - dn[dn_size] = '\0'; - - DEBUG(9, ("Section dn\n%s", dn)); - - tmp_ldif = talloc_realloc(mem_ctx, ldif, char, - ldif_len+dn_size+1); - if(!tmp_ldif) { - ret = ENOMEM; - free_attribute_list(attrs); - free_section_list(sections); - goto error; - } - ldif = tmp_ldif; - memcpy(ldif+ldif_len, dn, dn_size); - ldif_len += dn_size; - - free_attribute_list(attrs); - talloc_free(dn); + /* Open config file */ + ret = sss_ini_config_file_open(init_data, config_file); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to open configuration file.\n")); + ret = EIO; + goto done; } - ldif[ldif_len] = '\0'; - - free_section_list(sections); - - *config_ldif = (const char *)ldif; - talloc_free(tmp_ctx); - return EOK; - -error: - talloc_free(ldif); - return ret; -} - -int confdb_init_db(const char *config_file, struct confdb_ctx *cdb) -{ - int ret; - int fd = -1; - struct collection_item *sssd_config = NULL; - struct collection_item *error_list = NULL; - struct collection_item *item = NULL; - const char *config_ldif; - struct ldb_ldif *ldif; - TALLOC_CTX *tmp_ctx; - char *lasttimestr, timestr[21]; - const char *vals[2] = { timestr, NULL }; - struct stat cstat; - int version; - - tmp_ctx = talloc_new(cdb); - if (tmp_ctx == NULL) return ENOMEM; - - ret = check_and_open_readonly(config_file, &fd, 0, 0, (S_IRUSR|S_IWUSR), - CHECK_REG); + ret = sss_ini_config_access_check(init_data); if (ret != EOK) { - DEBUG(1, ("Permission check on config file failed.\n")); - talloc_zfree(tmp_ctx); - return EPERM; + DEBUG(SSSDBG_CRIT_FAILURE, + ("Permission check on config file failed.\n")); + ret = EPERM; + goto done; } /* Determine if the conf file has changed since we last updated * the confdb */ - ret = fstat(fd, &cstat); - if (ret != 0) { - DEBUG(0, ("Unable to stat config file [%s]! (%d [%s])\n", - config_file, errno, strerror(errno))); - close(fd); - talloc_zfree(tmp_ctx); - return errno; - } - ret = snprintf(timestr, 21, "%llu", (long long unsigned)cstat.st_mtime); - if (ret <= 0 || ret >= 21) { - DEBUG(0, ("Failed to convert time_t to string ??\n")); - close(fd); - talloc_zfree(tmp_ctx); - return errno ? errno: EFAULT; + ret = sss_ini_get_stat(init_data); + if (ret != EOK) { + DEBUG(SSSDBG_FATAL_FAILURE, + ("Status check on config file failed.\n")); + ret = errno; + goto done; } - /* check if we need to re-init the db */ - ret = confdb_get_string(cdb, tmp_ctx, "config", "lastUpdate", NULL, &lasttimestr); - if (ret == EOK && lasttimestr != NULL) { + errno = 0; - /* now check if we lastUpdate and last file modification change differ*/ - if (strcmp(lasttimestr, timestr) == 0) { - /* not changed, get out, nothing more to do */ - close(fd); - talloc_zfree(tmp_ctx); - return EOK; - } + ret = sss_ini_get_mtime(init_data, sizeof(timestr), timestr); + if (ret <= 0 || ret >= sizeof(timestr)) { + DEBUG(SSSDBG_FATAL_FAILURE, + ("Failed to convert time_t to string ??\n")); + ret = errno ? errno : EFAULT; } + ret = confdb_get_string(cdb, tmp_ctx, "config", "lastUpdate", + NULL, &lasttimestr); + if (ret == EOK) { - /* Set up a transaction to replace the configuration */ - ret = ldb_transaction_start(cdb->ldb); - if (ret != LDB_SUCCESS) { - DEBUG(0, ("Failed to start a transaction for updating the configuration\n")); - talloc_zfree(tmp_ctx); - close(fd); - return sysdb_error_to_errno(ret); - } - - /* Purge existing database */ - ret = confdb_purge(cdb); - if (ret != EOK) { - DEBUG(0, ("Could not purge existing configuration\n")); - close(fd); + /* check if we lastUpdate and last file modification change differ*/ + if ((lasttimestr != NULL) && (strcmp(lasttimestr, timestr) == 0)) { + /* not changed, get out, nothing more to do */ + ret = EOK; + goto done; + } + } else { + DEBUG(SSSDBG_FATAL_FAILURE, ("Failed to get lastUpdate attribute.\n")); goto done; } - /* Read the configuration into a collection */ - ret = config_from_fd("sssd", fd, config_file, &sssd_config, - INI_STOP_ON_ANY, &error_list); - close(fd); + ret = sss_ini_get_config(init_data, config_file); if (ret != EOK) { - DEBUG(0, ("Parse error reading configuration file [%s]\n", - config_file)); - print_file_parsing_errors(stderr, error_list); - free_ini_config_errors(error_list); - free_ini_config(sssd_config); + DEBUG(SSSDBG_FATAL_FAILURE, ("Failed to load configuration\n")); goto done; } /* Make sure that the config file version matches the confdb version */ - ret = get_config_item("sssd", "config_file_version", - sssd_config, &item); + ret = sss_ini_get_cfgobj(init_data, "sssd", "config_file_version"); if (ret != EOK) { - DEBUG(0, ("Internal error determining config_file_version\n")); + DEBUG(SSSDBG_FATAL_FAILURE, + ("Internal error determining config_file_version\n")); goto done; } - if (item == NULL) { + + ret = sss_ini_check_config_obj(init_data); + if (ret != EOK) { /* No known version. Assumed to be version 1 */ - DEBUG(0, ("Config file is an old version. " - "Please run configuration upgrade script.\n")); + DEBUG(SSSDBG_FATAL_FAILURE, + ("Config file is an old version. " + "Please run configuration upgrade script.\n")); ret = EINVAL; goto done; } - version = get_int_config_value(item, 1, -1, &ret); + + version = sss_ini_get_int_config_value(init_data, 1, -1, &ret); if (ret != EOK) { - DEBUG(0, ("Config file version could not be determined\n")); + DEBUG(SSSDBG_FATAL_FAILURE, + ("Config file version could not be determined\n")); goto done; } else if (version < CONFDB_VERSION_INT) { - DEBUG(0, ("Config file is an old version. " - "Please run configuration upgrade script.\n")); + DEBUG(SSSDBG_FATAL_FAILURE, + ("Config file is an old version. " + "Please run configuration upgrade script.\n")); ret = EINVAL; goto done; } else if (version > CONFDB_VERSION_INT) { - DEBUG(0, ("Config file version is newer than confdb\n")); + DEBUG(SSSDBG_FATAL_FAILURE, + ("Config file version is newer than confdb\n")); ret = EINVAL; goto done; } - ret = confdb_create_ldif(tmp_ctx, sssd_config, &config_ldif); - free_ini_config(sssd_config); + /* Set up a transaction to replace the configuration */ + ret = ldb_transaction_start(cdb->ldb); + if (ret != LDB_SUCCESS) { + DEBUG(SSSDBG_FATAL_FAILURE, + ("Failed to start a transaction for " + "updating the configuration\n")); + ret = sysdb_error_to_errno(ret); + goto done; + } + in_transaction = true; + + /* Purge existing database */ + ret = confdb_purge(cdb); if (ret != EOK) { - DEBUG(0, ("Could not create LDIF for confdb\n")); + DEBUG(SSSDBG_FATAL_FAILURE, + ("Could not purge existing configuration\n")); goto done; } - DEBUG(7, ("LDIF file to import: \n%s", config_ldif)); + ret = sss_confdb_create_ldif(tmp_ctx, init_data, &config_ldif); + if (ret != EOK) { + DEBUG(SSSDBG_FATAL_FAILURE, ("Could not create LDIF for confdb\n")); + goto done; + } + + DEBUG(SSSDBG_TRACE_LIBS, ("LDIF file to import: \n%s", config_ldif)); while ((ldif = ldb_ldif_read_string(cdb->ldb, &config_ldif))) { ret = ldb_add(cdb->ldb, ldif->msg); if (ret != LDB_SUCCESS) { - DEBUG(0, ("Failed to initialize DB (%d,[%s]), aborting!\n", - ret, ldb_errstring(cdb->ldb))); + DEBUG(SSSDBG_FATAL_FAILURE, + ("Failed to initialize DB (%d,[%s]), aborting!\n", + ret, ldb_errstring(cdb->ldb))); ret = EIO; goto done; } @@ -411,15 +288,31 @@ int confdb_init_db(const char *config_file, struct confdb_ctx *cdb) ret = confdb_add_param(cdb, true, "config", "lastUpdate", vals); if (ret != EOK) { - DEBUG(1, ("Failed to set last update time on db!\n")); + DEBUG(SSSDBG_FATAL_FAILURE, + ("Failed to set last update time on db!\n")); + goto done; + } + + ret = ldb_transaction_commit(cdb->ldb); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to commit transaction\n")); + goto done; } + in_transaction = false; ret = EOK; done: - ret == EOK ? - ldb_transaction_commit(cdb->ldb) : - ldb_transaction_cancel(cdb->ldb); + if (in_transaction) { + sret = ldb_transaction_cancel(cdb->ldb); + if (sret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to cancel transaction\n")); + } + } + + sss_ini_config_destroy(init_data); + sss_ini_close_file(init_data); + talloc_zfree(tmp_ctx); return ret; } diff --git a/src/external/libini_config.m4 b/src/external/libini_config.m4 index f41f3191..93a4bd94 100644 --- a/src/external/libini_config.m4 +++ b/src/external/libini_config.m4 @@ -1,10 +1,20 @@ +PKG_CHECK_MODULES(INI_CONFIG, [ + ini_config >= 1.0.0], [ + + AC_DEFINE_UNQUOTED(HAVE_LIBINI_CONFIG_V1, 1, [libini_config version greater than 1.0.0]) + ], [ + AC_MSG_WARN([libini_config-devel >= 1.0.0 not available, trying older version]) + PKG_CHECK_MODULES(INI_CONFIG, [ + ini_config >= 0.6.1], [ + + AC_DEFINE_UNQUOTED(HAVE_LIBINI_CONFIG_V0, 1, [libini_config version lesser than 1.0.0]) + ], [ + AC_MSG_ERROR([Please install libini_config-devel]) + ] + ) + ] +) + AC_SUBST(INI_CONFIG_OBJ) AC_SUBST(INI_CONFIG_CFLAGS) AC_SUBST(INI_CONFIG_LIBS) - -PKG_CHECK_MODULES(INI_CONFIG, - ini_config >= 0.6.1, - , - AC_MSG_ERROR("Please install libini_config-devel") - ) - diff --git a/src/monitor/monitor.c b/src/monitor/monitor.c index 4e81f559..bd22a951 100644 --- a/src/monitor/monitor.c +++ b/src/monitor/monitor.c @@ -44,8 +44,6 @@ #include "tevent.h" #include "confdb/confdb.h" #include "confdb/confdb_setup.h" -#include "collection.h" -#include "ini_config.h" #include "db/sysdb.h" #include "monitor/monitor.h" #include "dbus/dbus.h" diff --git a/src/responder/nss/nsssrv_netgroup.c b/src/responder/nss/nsssrv_netgroup.c index 30459bea..36792365 100644 --- a/src/responder/nss/nsssrv_netgroup.c +++ b/src/responder/nss/nsssrv_netgroup.c @@ -22,7 +22,7 @@ along with this program. If not, see . */ -#include + #include "util/util.h" #include "responder/nss/nsssrv.h" #include "responder/nss/nsssrv_private.h" diff --git a/src/responder/nss/nsssrv_services.c b/src/responder/nss/nsssrv_services.c index 7b76cad8..c9907423 100644 --- a/src/responder/nss/nsssrv_services.c +++ b/src/responder/nss/nsssrv_services.c @@ -21,7 +21,6 @@ */ -#include #include #include "util/util.h" #include "responder/nss/nsssrv.h" diff --git a/src/util/sss_ini.c b/src/util/sss_ini.c new file mode 100644 index 00000000..32e06781 --- /dev/null +++ b/src/util/sss_ini.c @@ -0,0 +1,488 @@ +/* + SSSD + + sss_ini.c + + Authors: + Ondrej Kos + + Copyright (C) 2013 Red Hat + + 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 +#include +#include + +#include "config.h" +#include "util/util.h" +#include "util/sss_ini.h" +#include "confdb/confdb_setup.h" +#include "confdb/confdb_private.h" + +#ifdef HAVE_LIBINI_CONFIG_V1 +#include "ini_configobj.h" +#elif HAVE_LIBINI_CONFIG_V0 +#include "collection.h" +#include "collection_tools.h" +#else +#error "Unsupported libini version" +#endif + +#include "ini_config.h" + + +#ifdef HAVE_LIBINI_CONFIG_V1 + +struct sss_ini_initdata { + char **error_list; + struct ini_cfgobj *sssd_config; + struct value_obj *obj; + const struct stat *cstat; + struct ini_cfgfile *file; +}; + +#define sss_ini_get_sec_list ini_get_section_list +#define sss_ini_get_attr_list ini_get_attribute_list +#define sss_ini_get_const_string_config_value ini_get_const_string_config_value +#define sss_ini_get_config_obj ini_get_config_valueobj + + + +#elif HAVE_LIBINI_CONFIG_V0 + +struct sss_ini_initdata { + struct collection_item *error_list; + struct collection_item *sssd_config; + struct collection_item *obj; + struct stat cstat; + int file; +}; + +#define sss_ini_get_sec_list get_section_list +#define sss_ini_get_attr_list get_attribute_list +#define sss_ini_get_const_string_config_value get_const_string_config_value +#define sss_ini_get_config_obj(secs,attrs,cfg,flag,attr) \ + get_config_item(secs,attrs,cfg,attr) + +#endif + + +/* Initialize data structure */ + +struct sss_ini_initdata* sss_ini_initdata_init(TALLOC_CTX *mem_ctx) +{ + return talloc_zero(mem_ctx, struct sss_ini_initdata); +} + + + +/* Close file descriptor */ + +void sss_ini_close_file(struct sss_ini_initdata *init_data) +{ + if (init_data == NULL) return; +#ifdef HAVE_LIBINI_CONFIG_V1 + if (init_data->file != NULL) { + ini_config_file_destroy(init_data->file); + init_data->file = NULL; + } +#elif HAVE_LIBINI_CONFIG_V0 + if (init_data->file != -1) { + close(init_data->file); + init_data->file = -1; + } +#endif +} + + + +/* Open configuration file */ + +int sss_ini_config_file_open(struct sss_ini_initdata *init_data, + const char *config_file) +{ +#ifdef HAVE_LIBINI_CONFIG_V1 + return ini_config_file_open(config_file, + INI_META_STATS, + &init_data->file); +#elif HAVE_LIBINI_CONFIG_V0 + return check_and_open_readonly(config_file, &init_data->file, 0, 0, + (S_IRUSR|S_IWUSR), CHECK_REG); +#endif +} + + + +/* Check configuration file permissions */ + +int sss_ini_config_access_check(struct sss_ini_initdata *init_data) +{ +#ifdef HAVE_LIBINI_CONFIG_V1 + return ini_config_access_check(init_data->file, + INI_ACCESS_CHECK_MODE | + INI_ACCESS_CHECK_UID | + INI_ACCESS_CHECK_GID, + 0, /* owned by root */ + 0, /* owned by root */ + (S_IRUSR|S_IWUSR), /* rw------- */ + 0); /* check all there parts */ +#elif HAVE_LIBINI_CONFIG_V0 + return EOK; +#endif +} + + + +/* Get cstat */ + +int sss_ini_get_stat(struct sss_ini_initdata *init_data) +{ +#ifdef HAVE_LIBINI_CONFIG_V1 + init_data->cstat = ini_config_get_stat(init_data->file); + + if (!init_data->cstat) return EIO; + + return EOK; +#elif HAVE_LIBINI_CONFIG_V0 + + return fstat(init_data->file, &init_data->cstat); +#endif +} + + + +/* Get mtime */ + +int sss_ini_get_mtime(struct sss_ini_initdata *init_data, + size_t timestr_len, + char *timestr) +{ +#ifdef HAVE_LIBINI_CONFIG_V1 + return snprintf(timestr, timestr_len, "%llu", + (long long unsigned)init_data->cstat->st_mtime); +#elif HAVE_LIBINI_CONFIG_V0 + return snprintf(timestr, timestr_len, "%llu", + (long long unsigned)init_data->cstat.st_mtime); +#endif +} + + + +/* Print ini_config errors */ + +void sss_ini_config_print_errors(char **error_list) +{ +#ifdef HAVE_LIBINI_CONFIG_V1 + unsigned count = 0; + + if (!error_list) { + return; + } + + while (error_list[count]) { + DEBUG(SSSDBG_CRIT_FAILURE, ("%s\n", error_list[count])); + count++; + } +#endif + + return; +} + + + +/* Load configuration */ + +int sss_ini_get_config(struct sss_ini_initdata *init_data, + const char *config_file) +{ + int ret; +#ifdef HAVE_LIBINI_CONFIG_V1 + + /* Create config object */ + ret = ini_config_create(&(init_data->sssd_config)); + if (ret != EOK) { + DEBUG(SSSDBG_FATAL_FAILURE, + ("Failed to create config object. Error %d.\n", ret)); + return ret; + } + + /* Parse file */ + ret = ini_config_parse(init_data->file, + INI_STOP_ON_ANY, + INI_MV1S_OVERWRITE, + 0, + init_data->sssd_config); + + if (ret != EOK) { + DEBUG(SSSDBG_FATAL_FAILURE, + ("Failed to parse configuration. Error %d.\n", ret)); + + if (ini_config_error_count(init_data->sssd_config)) { + DEBUG(SSSDBG_FATAL_FAILURE, + ("Errors detected while parsing: %s\n", + ini_config_get_filename(init_data->file))); + + ini_config_get_errors(init_data->sssd_config, + &init_data->error_list); + sss_ini_config_print_errors(init_data->error_list); + ini_config_free_errors(init_data->error_list); + } + ini_config_destroy(init_data->sssd_config); + return ret; + } + + return ret; + +#elif HAVE_LIBINI_CONFIG_V0 + + /* Read the configuration into a collection */ + ret = config_from_fd("sssd", + init_data->file, + config_file, + &init_data->sssd_config, + INI_STOP_ON_ANY, + &init_data->error_list); + close(init_data->file); + + if (ret != EOK) { + DEBUG(SSSDBG_FATAL_FAILURE, + ("Parse error reading configuration file [%s]\n", + config_file)); + + print_file_parsing_errors(stderr, init_data->error_list); + + free_ini_config_errors(init_data->error_list); + free_ini_config(init_data->sssd_config); + + return ret; + } + + return EOK; + +#endif +} + + + +/* Get configuration object */ + +int sss_ini_get_cfgobj(struct sss_ini_initdata *init_data, + const char *section, const char *name) +{ + return sss_ini_get_config_obj(section,name, init_data->sssd_config, + INI_GET_FIRST_VALUE, &init_data->obj); +} + + + +/* Check configuration object */ + +int sss_ini_check_config_obj(struct sss_ini_initdata *init_data) +{ + if (init_data->obj == NULL) { + return ENOENT; + } + + return EOK; +} + + + +/* Get integer value */ + +int sss_ini_get_int_config_value(struct sss_ini_initdata *init_data, + int strict, int def, int *error) +{ +#ifdef HAVE_LIBINI_CONFIG_V1 + return ini_get_int_config_value(init_data->obj, strict, def, error); +#elif HAVE_LIBINI_CONFIG_V0 + return get_int_config_value(init_data->obj, strict, def, error); +#endif +} + + + +/* Destroy ini config (v1) */ + +void sss_ini_config_destroy(struct sss_ini_initdata *init_data) +{ + if (init_data == NULL) return; +#ifdef HAVE_LIBINI_CONFIG_V1 + if (init_data->sssd_config != NULL) { + ini_config_destroy(init_data->sssd_config); + init_data->sssd_config = NULL; + } +#elif HAVE_LIBINI_CONFIG_V0 + free_ini_config(init_data->sssd_config); +#endif +} + + + +/* Create LDIF */ + +int sss_confdb_create_ldif(TALLOC_CTX *mem_ctx, + struct sss_ini_initdata *init_data, + const char **config_ldif) +{ + int ret, i, j; + char *ldif; + char *tmp_ldif; + char **sections; + int section_count; + char *dn; + char *tmp_dn; + char *sec_dn; + char **attrs; + int attr_count; + char *ldif_attr; + TALLOC_CTX *tmp_ctx; + size_t dn_size; + size_t ldif_len; + size_t attr_len; +#ifdef HAVE_LIBINI_CONFIG_V1 + struct value_obj *obj = NULL; +#elif HAVE_LIBINI_CONFIG_V0 + struct collection_item *obj = NULL; +#endif + + ldif_len = strlen(CONFDB_INTERNAL_LDIF); + ldif = talloc_array(mem_ctx, char, ldif_len+1); + if (!ldif) return ENOMEM; + + tmp_ctx = talloc_new(ldif); + if (!tmp_ctx) { + ret = ENOMEM; + goto error; + } + + memcpy(ldif, CONFDB_INTERNAL_LDIF, ldif_len); + + /* Read in the collection and convert it to an LDIF */ + /* Get the list of sections */ + sections = sss_ini_get_sec_list(init_data->sssd_config, + §ion_count, &ret); + if (ret != EOK) { + goto error; + } + + for (i = 0; i < section_count; i++) { + const char *rdn = NULL; + DEBUG(SSSDBG_TRACE_FUNC, + ("Processing config section [%s]\n", sections[i])); + ret = parse_section(tmp_ctx, sections[i], &sec_dn, &rdn); + if (ret != EOK) { + goto error; + } + + dn = talloc_asprintf(tmp_ctx, + "dn: %s,cn=config\n" + "cn: %s\n", + sec_dn, rdn); + if (!dn) { + ret = ENOMEM; + free_section_list(sections); + goto error; + } + dn_size = strlen(dn); + + /* Get all of the attributes and their values as LDIF */ + attrs = sss_ini_get_attr_list(init_data->sssd_config, sections[i], + &attr_count, &ret); + if (ret != EOK) { + free_section_list(sections); + goto error; + } + + for (j = 0; j < attr_count; j++) { + DEBUG(SSSDBG_TRACE_FUNC, + ("Processing attribute [%s]\n", attrs[j])); + ret = sss_ini_get_config_obj(sections[i], attrs[j], + init_data->sssd_config, + INI_GET_FIRST_VALUE, &obj); + if (ret != EOK) goto error; + + const char *value = sss_ini_get_const_string_config_value(obj, &ret); + if (ret != EOK) goto error; + if (value && value[0] == '\0') { + DEBUG(SSSDBG_CRIT_FAILURE, + ("Attribute '%s' has empty value, ignoring\n", + attrs[j])); + continue; + } + + ldif_attr = talloc_asprintf(tmp_ctx, + "%s: %s\n", attrs[j], value); + DEBUG(SSSDBG_TRACE_ALL, ("%s", ldif_attr)); + + attr_len = strlen(ldif_attr); + + tmp_dn = talloc_realloc(tmp_ctx, dn, char, + dn_size+attr_len+1); + if (!tmp_dn) { + ret = ENOMEM; + free_attribute_list(attrs); + free_section_list(sections); + goto error; + } + dn = tmp_dn; + memcpy(dn+dn_size, ldif_attr, attr_len+1); + dn_size += attr_len; + } + + dn_size ++; + tmp_dn = talloc_realloc(tmp_ctx, dn, char, + dn_size+1); + if (!tmp_dn) { + ret = ENOMEM; + free_attribute_list(attrs); + free_section_list(sections); + goto error; + } + dn = tmp_dn; + dn[dn_size-1] = '\n'; + dn[dn_size] = '\0'; + + DEBUG(SSSDBG_TRACE_ALL, ("Section dn\n%s", dn)); + + tmp_ldif = talloc_realloc(mem_ctx, ldif, char, + ldif_len+dn_size+1); + if (!tmp_ldif) { + ret = ENOMEM; + free_attribute_list(attrs); + free_section_list(sections); + goto error; + } + ldif = tmp_ldif; + memcpy(ldif+ldif_len, dn, dn_size); + ldif_len += dn_size; + + free_attribute_list(attrs); + talloc_free(dn); + } + + ldif[ldif_len] = '\0'; + + free_section_list(sections); + + *config_ldif = (const char *)ldif; + talloc_free(tmp_ctx); + return EOK; + +error: + talloc_free(ldif); + return ret; +} diff --git a/src/util/sss_ini.h b/src/util/sss_ini.h new file mode 100644 index 00000000..3beaca15 --- /dev/null +++ b/src/util/sss_ini.h @@ -0,0 +1,81 @@ +/* + SSSD + + sss_ini.c + + Authors: + Ondrej Kos + + Copyright (C) 2013 Red Hat + + + 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 . +*/ + + +#ifndef __SSS_INI_H__ +#define __SSS_INI_H__ + +/* Structure declarations */ + +/* INI data structure */ +struct sss_ini_initdata; + + +/* Function declarations */ + +/* Initialize data structure */ +struct sss_ini_initdata* sss_ini_initdata_init(TALLOC_CTX *tmp_ctx); + +/* Close file descriptor */ +void sss_ini_close_file(struct sss_ini_initdata *init_data); + +/* Open config file */ +int sss_ini_config_file_open(struct sss_ini_initdata *init_data, + const char *config_file); + +/* Check file permissions */ +int sss_ini_config_access_check(struct sss_ini_initdata *init_data); + +/* Cstat */ +int sss_ini_get_stat(struct sss_ini_initdata *init_data); + +/* Get mtime */ +int sss_ini_get_mtime(struct sss_ini_initdata *init_data, + size_t timestr_len, + char *timestr); + +/* Load configuration */ +int sss_ini_get_config(struct sss_ini_initdata *init_data, + const char *config_file); +/* Get configuration object */ +int sss_ini_get_cfgobj(struct sss_ini_initdata *init_data, + const char *section, const char *name); + +/* Check configuration object */ +int sss_ini_check_config_obj(struct sss_ini_initdata *init_data); + +/* Get int value */ +int sss_ini_get_int_config_value(struct sss_ini_initdata *init_data, + int strict, int def, int *error); + +/* Destroy ini config */ +void sss_ini_config_destroy(struct sss_ini_initdata *init_data); + +/* Create LDIF */ +int sss_confdb_create_ldif(TALLOC_CTX *mem_ctx, + struct sss_ini_initdata *init_data, + const char **config_ldif); + +#endif /* __SSS_INI_H__ */ -- cgit