URL: https://github.com/SSSD/sssd/pull/946 Author: thalman Title: #946: INI: sssctl config-check giving the wrong message Action: synchronized
To pull the PR as Git branch: git remote add ghsssd https://github.com/SSSD/sssd git fetch ghsssd pull/946/head:pr946 git checkout pr946
From 183e99ccd7bb6146929c1b02bc9f7aed7478e8e9 Mon Sep 17 00:00:00 2001 From: Tomas Halman <thal...@redhat.com> Date: Fri, 22 Nov 2019 15:00:26 +0100 Subject: [PATCH] INI: sssctl config-check giving the wrong message The sssctl config-check is giving the wrong error message when there are only snippet files and no sssd.conf. To address this problem sss_ini code had to be partially rewritten to allow proper configuration testing. Resolves: https://pagure.io/SSSD/sssd/issue/3938 --- src/confdb/confdb.h | 3 + src/confdb/confdb_setup.c | 50 +-- src/tests/cmocka/test_config_check.c | 13 +- src/tools/sssctl/sssctl_config.c | 88 +++-- .../sssd_check_socket_activated_responders.c | 90 +---- src/util/sss_ini.c | 344 +++++++++++++----- src/util/sss_ini.h | 171 ++++++--- src/util/util_errors.c | 6 + src/util/util_errors.h | 6 + 9 files changed, 464 insertions(+), 307 deletions(-) diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h index 2560efc767..ec9be60e69 100644 --- a/src/confdb/confdb.h +++ b/src/confdb/confdb.h @@ -45,6 +45,9 @@ #define SSSD_MIN_ID 1 #define SSSD_LOCAL_MINID 1000 #define CONFDB_DEFAULT_SHELL_FALLBACK "/bin/sh" +#define CONFDB_FALLBACK_CONFIG \ + "[sssd]\n" \ + "services = nss\n" /* Configuration options */ diff --git a/src/confdb/confdb_setup.c b/src/confdb/confdb_setup.c index b7b316fd6f..1df9c3c089 100644 --- a/src/confdb/confdb_setup.c +++ b/src/confdb/confdb_setup.c @@ -129,38 +129,22 @@ static int confdb_ldif_from_ini_file(TALLOC_CTX *mem_ctx, const char *config_file, const char *config_dir, const char *only_section, - struct sss_ini_initdata *init_data, + struct sss_ini *init_data, const char **_timestr, const char **_ldif) { errno_t ret; char timestr[21]; int version; - char fallback_cfg[] = - "[sssd]\n" - "services = nss\n"; - /* Open config file */ - ret = sss_ini_config_file_open(init_data, config_file); - if (ret == ENOENT) { - DEBUG(SSSDBG_TRACE_FUNC, "No sssd.conf.\n"); - ret = sss_ini_config_file_from_mem(fallback_cfg, - strlen(fallback_cfg), - init_data); - if (ret != EOK) { - DEBUG(SSSDBG_FATAL_FAILURE, - "sss_ini_config_file_from_mem failed. Error %d: %s\n", - ret, sss_strerror(ret)); - return ret; - } - } else if (ret == EOK) { - ret = sss_ini_config_access_check(init_data); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, - "Permission check on config file failed.\n"); - return EPERM; - } + ret = sss_ini_read_sssd_conf(init_data, + config_file, + config_dir); + if (ret != EOK) { + return ret; + } + if (sss_ini_exists(init_data)) { ret = sss_ini_get_stat(init_data); if (ret != EOK) { ret = errno; @@ -177,11 +161,6 @@ static int confdb_ldif_from_ini_file(TALLOC_CTX *mem_ctx, "Failed to convert time_t to string??\n"); return ret; } - } else { - DEBUG(SSSDBG_CONF_SETTINGS, - "sss_ini_config_file_open failed: %s [%d]\n", sss_strerror(ret), - ret); - return ret; } /* FIXME: Determine if the conf file or any snippet has changed @@ -189,12 +168,6 @@ static int confdb_ldif_from_ini_file(TALLOC_CTX *mem_ctx, * added or removed. */ - ret = sss_ini_get_config(init_data, config_file, config_dir); - if (ret != EOK) { - DEBUG(SSSDBG_FATAL_FAILURE, "Failed to load configuration\n"); - return ret; - } - ret = sss_ini_call_validators(init_data, SSSDDATADIR"/cfg_rules.ini"); if (ret != EOK) { @@ -303,7 +276,7 @@ static int confdb_init_db(const char *config_file, const char *timestr = NULL; const char *config_ldif; const char *vals[2] = { NULL, NULL }; - struct sss_ini_initdata *init_data; + struct sss_ini *init_data; tmp_ctx = talloc_new(cdb); if (tmp_ctx == NULL) { @@ -311,7 +284,7 @@ static int confdb_init_db(const char *config_file, return ENOMEM; } - init_data = sss_ini_initdata_init(tmp_ctx); + init_data = sss_ini_new(tmp_ctx); if (!init_data) { DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory.\n"); ret = ENOMEM; @@ -390,9 +363,6 @@ static int confdb_init_db(const char *config_file, } } - sss_ini_config_destroy(init_data); - sss_ini_close_file(init_data); - talloc_zfree(tmp_ctx); return ret; } diff --git a/src/tests/cmocka/test_config_check.c b/src/tests/cmocka/test_config_check.c index dcb560bbf9..861875743c 100644 --- a/src/tests/cmocka/test_config_check.c +++ b/src/tests/cmocka/test_config_check.c @@ -31,7 +31,7 @@ #define RULES_PATH ABS_SRC_DIR"/src/config/cfg_rules.ini" -struct sss_ini_initdata { +struct sss_ini { char **error_list; struct ref_array *ra_success_list; struct ref_array *ra_error_list; @@ -39,13 +39,14 @@ struct sss_ini_initdata { struct value_obj *obj; const struct stat *cstat; struct ini_cfgfile *file; + bool main_config_exists; }; void config_check_test_common(const char *cfg_string, size_t num_errors_expected, const char **errors_expected) { - struct sss_ini_initdata *init_data; + struct sss_ini *init_data; size_t num_errors; char **strs; int ret; @@ -54,11 +55,9 @@ void config_check_test_common(const char *cfg_string, tmp_ctx = talloc_new(NULL); assert_non_null(tmp_ctx); - init_data = sss_ini_initdata_init(tmp_ctx); + init_data = sss_ini_new(tmp_ctx); - ret = ini_config_file_from_mem(discard_const(cfg_string), - strlen(cfg_string), - &init_data->file); + ret = sss_ini_open(init_data, NULL, cfg_string); assert_int_equal(ret, EOK); ret = ini_config_create(&(init_data->sssd_config)); @@ -90,8 +89,6 @@ void config_check_test_common(const char *cfg_string, /* Check if the number of errors is the same */ assert_int_equal(num_errors_expected, num_errors); - sss_ini_close_file(init_data); - sss_ini_config_destroy(init_data); talloc_free(tmp_ctx); } diff --git a/src/tools/sssctl/sssctl_config.c b/src/tools/sssctl/sssctl_config.c index 4852e22165..4889e5f25e 100644 --- a/src/tools/sssctl/sssctl_config.c +++ b/src/tools/sssctl/sssctl_config.c @@ -31,19 +31,20 @@ #include "tools/sssctl/sssctl.h" #include "confdb/confdb.h" + + #ifdef HAVE_LIBINI_CONFIG_V1_3 errno_t sssctl_config_check(struct sss_cmdline *cmdline, struct sss_tool_ctx *tool_ctx, void *pvt) { errno_t ret; - struct ini_errobj *errobj = NULL; - struct sss_ini_initdata *init_data; - struct ref_array *ra; + struct sss_ini *init_data; + struct ref_array *ra_error, *ra_success; char *msg; uint32_t i = 0; size_t num_errors; - size_t num_ra_error; + size_t num_ra_error, num_ra_success; char **strs = NULL; TALLOC_CTX *tmp_ctx = NULL; @@ -54,79 +55,89 @@ errno_t sssctl_config_check(struct sss_cmdline *cmdline, } tmp_ctx = talloc_new(NULL); - init_data = sss_ini_initdata_init(tmp_ctx); + init_data = sss_ini_new(tmp_ctx); if (!init_data) { DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory.\n"); ret = ENOMEM; goto done; } - /* Open config file */ - ret = sss_ini_config_file_open(init_data, SSSD_CONFIG_FILE); - if (ret == ENOENT) { - PRINT("File %1$s does not exist. SSSD will use default " - "configuration with files provider.\n", SSSD_CONFIG_FILE); - ret = EOK; - } else if (ret != EOK) { - DEBUG(SSSDBG_TRACE_FUNC, - "sss_ini_config_file_open failed: %s [%d]\n", - sss_strerror(ret), - ret); + ret = sss_ini_read_sssd_conf(init_data, + SSSD_CONFIG_FILE, + CONFDB_DEFAULT_CONFIG_DIR); + + if (ret == ERR_INI_OPEN_FAILED) { + PRINT("Failed to open %s\n", SSSD_CONFIG_FILE); goto done; } - /* Check the file permissions */ - ret = sss_ini_config_access_check(init_data); - if (ret != EOK) { + if (!sss_ini_exists(init_data)) { + PRINT("File %1$s does not exist.\n", SSSD_CONFIG_FILE); + } + + if (ret == ERR_INI_INVALID_PERMISSION) { PRINT("File ownership and permissions check failed. " "Expected root:root and 0600.\n"); - ret = EPERM; goto done; } - ret = sss_ini_get_config(init_data, - SSSD_CONFIG_FILE, - CONFDB_DEFAULT_CONFIG_DIR); - if (ret != EOK) { - DEBUG(SSSDBG_FATAL_FAILURE, "Failed to load configuration\n"); + if (ret == ERR_INI_PARSE_FAILED) { + PRINT("Failed to load configuration configuration from %s.\n", + SSSD_CONFIG_FILE); + goto done; + } + + if (ret == ERR_INI_ADD_SNIPPETS_FAILED) { + PRINT("Error while reading configuration directory.\n"); goto done; } - /* Read rules */ + /* Used snippet files */ + ra_success = sss_ini_get_ra_success_list(init_data); + num_ra_success = ref_array_len(ra_success); + if ((sss_ini_exists(init_data) == false) && (num_ra_success == 0)) { + PRINT("There is no configuration." +#ifdef ADD_FILES_DOMAIN + " SSSD will use default configuration with files provider." +#endif + "\n"); + } + + /* Run validators */ ret = sss_ini_call_validators_strs(tmp_ctx, init_data, SSSDDATADIR"/cfg_rules.ini", &strs, &num_errors); if (ret) { + PRINT("Failed to run validators"); goto done; } - /* Output from validators */ PRINT("Issues identified by validators: %zu\n", num_errors); for (i = 0; i < num_errors; i++) { printf("%s\n", strs[i]); } + printf("\n"); + /* Merging issues */ - ra = sss_ini_get_ra_error_list(init_data); - num_ra_error = ref_array_len(ra); + ra_error = sss_ini_get_ra_error_list(init_data); + num_ra_error = ref_array_len(ra_error); - printf("\n"); - PRINT("Messages generated during configuration merging: %zu\n",num_ra_error); + PRINT("Messages generated during configuration merging: %zu\n", num_ra_error); i = 0; - while (ref_array_get(ra, i, &msg) != NULL) { + while (ref_array_get(ra_error, i, &msg) != NULL) { printf("%s\n", msg); i++; } - /* Used snippet files */ - ra = sss_ini_get_ra_success_list(init_data); - printf("\n"); - PRINT("Used configuration snippet files: %u\n", ref_array_len(ra)); + + /* Used snippets */ + PRINT("Used configuration snippet files: %zu\n", num_ra_success); i = 0; - while (ref_array_get(ra, i, &msg) != NULL) { + while (ref_array_get(ra_success, i, &msg) != NULL) { printf("%s\n", msg); i++; } @@ -138,8 +149,7 @@ errno_t sssctl_config_check(struct sss_cmdline *cmdline, } done: - ini_errobj_destroy(&errobj); - sss_ini_config_destroy(init_data); + talloc_free(tmp_ctx); return ret; } #endif /* HAVE_LIBINI_CONFIG_V1_3 */ diff --git a/src/tools/sssd_check_socket_activated_responders.c b/src/tools/sssd_check_socket_activated_responders.c index fb9df39091..dbd2331026 100644 --- a/src/tools/sssd_check_socket_activated_responders.c +++ b/src/tools/sssd_check_socket_activated_responders.c @@ -22,109 +22,61 @@ #include <popt.h> #include <stdio.h> -#include <ini_configobj.h> #include "util/util.h" +#include "util/sss_ini.h" #include "confdb/confdb.h" static errno_t check_socket_activated_responder(const char *responder) { errno_t ret; - struct ini_cfgfile *file_ctx = NULL; - struct ini_cfgobj *ini_config = NULL; - struct ini_cfgobj *modified_ini_config = NULL; - struct value_obj *vobj = NULL; - struct access_check snip_check; const char *services; - const char *patterns[] = { "^[^\\.].*\\.conf$", NULL }; - const char *sections[] = { "sssd", NULL }; const char *str; TALLOC_CTX *tmp_ctx; + struct sss_ini *init_data; tmp_ctx = talloc_new(NULL); if (tmp_ctx == NULL) { return ENOMEM; } - ret = ini_config_create(&ini_config); - if (ret != 0) { - DEBUG(SSSDBG_CRIT_FAILURE, "ini_config_create() failed [%d][%s]\n", - ret, sss_strerror(ret)); + init_data = sss_ini_new(tmp_ctx); + if (init_data == NULL) { + ret = ENOMEM; goto done; } - ret = ini_config_file_open(SSSD_CONFIG_FILE, 0, &file_ctx); - if (ret != 0) { - DEBUG(SSSDBG_CRIT_FAILURE, "ini_config_file_open() failed [%d][%s]\n", - ret, sss_strerror(ret)); - goto done; - } - - /* Using the same flags used by sss_ini_get_config(), which is used to - * load the config file ... */ - ret = ini_config_parse(file_ctx, - INI_STOP_ON_ANY, - INI_MV1S_OVERWRITE, - INI_PARSE_NOWRAP, - ini_config); - if (ret != 0) { - DEBUG(SSSDBG_CRIT_FAILURE, "ini_config_parse() failed [%d][%s]\n", - ret, sss_strerror(ret)); - goto done; - } - - /* And also check the snippets ... */ - snip_check.flags = INI_ACCESS_CHECK_MODE | - INI_ACCESS_CHECK_UID | - INI_ACCESS_CHECK_GID; - snip_check.uid = 0; /* owned by root */ - snip_check.gid = 0; /* owned by root */ - snip_check.mode = S_IRUSR; /* r**------ */ - snip_check.mask = ALLPERMS & ~(S_IWUSR | S_IXUSR); - - ret = ini_config_augment(ini_config, - CONFDB_DEFAULT_CONFIG_DIR, - patterns, - sections, - &snip_check, - INI_STOP_ON_ANY, - INI_MV1S_OVERWRITE, - INI_PARSE_NOWRAP, - INI_MV2S_OVERWRITE, - &modified_ini_config, - NULL, - NULL); + ret = sss_ini_read_sssd_conf(init_data, + SSSD_CONFIG_FILE, + CONFDB_DEFAULT_CONFIG_DIR); if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, "ini_config_augment failed [%d][%s]\n", - ret, sss_strerror(ret)); + DEBUG(SSSDBG_CRIT_FAILURE, + "Failed to read configuration: [%d] [%s]", + ret, + sss_strerror(ret)); goto done; } - if (modified_ini_config != NULL) { - ini_config_destroy(ini_config); - ini_config = modified_ini_config; - } + ret = sss_ini_get_cfgobj(init_data, "sssd", "services"); - ret = ini_get_config_valueobj("sssd", "services", ini_config, - INI_GET_FIRST_VALUE, &vobj); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, - "ini_get_config_valueobj() failed [%d][%s]\n", - ret, sss_strerror(ret)); + "sss_ini_get_cfgobj() failed [%d].\n", ret); goto done; } - /* In case there's no services' line at all, just return EOK. */ - if (vobj == NULL) { + ret = sss_ini_check_config_obj(init_data); + if (ret == ENOENT) { + /* In case there's no services' line at all, just return EOK. */ ret = EOK; goto done; } - services = ini_get_string_config_value(vobj, &ret); + services = sss_ini_get_string_config_value(init_data, &ret); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, - "ini_get_string_config_value() failed [%d][%s]\n", - ret, sss_strerror(ret)); + "sss_ini_get_string_config_value() failed [%d]\n", + ret); goto done; } @@ -137,8 +89,6 @@ static errno_t check_socket_activated_responder(const char *responder) ret = EOK; done: - ini_config_file_destroy(file_ctx); - ini_config_destroy(ini_config); talloc_free(tmp_ctx); return ret; diff --git a/src/util/sss_ini.c b/src/util/sss_ini.c index cf61a17225..e3699805de 100644 --- a/src/util/sss_ini.c +++ b/src/util/sss_ini.c @@ -35,7 +35,7 @@ #include "ini_configobj.h" #include "ini_config.h" -struct sss_ini_initdata { +struct sss_ini { char **error_list; struct ref_array *ra_success_list; struct ref_array *ra_error_list; @@ -43,6 +43,7 @@ struct sss_ini_initdata { struct value_obj *obj; const struct stat *cstat; struct ini_cfgfile *file; + bool main_config_exists; }; #define sss_ini_get_sec_list ini_get_section_list @@ -50,51 +51,109 @@ struct sss_ini_initdata { #define sss_ini_get_const_string_config_value ini_get_const_string_config_value #define sss_ini_get_config_obj ini_get_config_valueobj -/* Initialize data structure */ -struct sss_ini_initdata* sss_ini_initdata_init(TALLOC_CTX *mem_ctx) +static void sss_ini_free_error_messages(struct sss_ini *self) { - return talloc_zero(mem_ctx, struct sss_ini_initdata); + if (self != NULL) { + ini_config_free_errors(self->error_list); + self->error_list = NULL; + } } +static void sss_ini_free_ra_messages(struct sss_ini *self) +{ + if (self != NULL) { + ref_array_destroy(self->ra_success_list); + self->ra_success_list = NULL; + ref_array_destroy(self->ra_error_list); + self->ra_error_list = NULL; + } +} +static void sss_ini_free_config(struct sss_ini *self) +{ + if (self != NULL && self->sssd_config != NULL) { + ini_config_destroy(self->sssd_config); + self->sssd_config = NULL; + } +} /* Close file descriptor */ -void sss_ini_close_file(struct sss_ini_initdata *init_data) +static void sss_ini_close_file(struct sss_ini *self) { - if (init_data == NULL) return; - if (init_data->file != NULL) { - ini_config_file_destroy(init_data->file); - init_data->file = NULL; + if (self != NULL && self->file != NULL) { + ini_config_file_destroy(self->file); + self->file = NULL; } } +/* sss_ini destructor */ + +static int sss_ini_destroy(struct sss_ini *self) +{ + sss_ini_free_error_messages(self); + sss_ini_free_ra_messages(self); + sss_ini_free_config(self); + sss_ini_close_file(self); + return 0; +} + +/* Initialize data structure */ + +struct sss_ini* sss_ini_new(TALLOC_CTX *mem_ctx) +{ + struct sss_ini *self; + + self = talloc_zero(mem_ctx, struct sss_ini); + if (!self) { + DEBUG(SSSDBG_CRIT_FAILURE, "Not enough memory for sss_ini_data.\n"); + return NULL; + } + talloc_set_destructor(self, sss_ini_destroy); + return self; +} /* Open configuration file */ -int sss_ini_config_file_open(struct sss_ini_initdata *init_data, - const char *config_file) +static int sss_ini_config_file_open(struct sss_ini *self, + const char *config_file) { - return ini_config_file_open(config_file, - INI_META_STATS, - &init_data->file); + int ret; + + if (self == NULL) { + return EINVAL; + } + + ret = ini_config_file_open(config_file, + INI_META_STATS, + &self->file); + self->main_config_exists = (ret != ENOENT); + return ret; } -int sss_ini_config_file_from_mem(void *data_buf, - uint32_t data_len, - struct sss_ini_initdata *init_data) +static int sss_ini_config_file_from_mem(struct sss_ini *self, + void *data_buf, + uint32_t data_len) { + if (self == NULL) { + return EINVAL; + } + return ini_config_file_from_mem(data_buf, strlen(data_buf), - &init_data->file); + &self->file); } /* Check configuration file permissions */ -int sss_ini_config_access_check(struct sss_ini_initdata *init_data) +static int sss_ini_access_check(struct sss_ini *self) { - return ini_config_access_check(init_data->file, + if (!self->main_config_exists) { + return EOK; + } + + return ini_config_access_check(self->file, INI_ACCESS_CHECK_MODE | INI_ACCESS_CHECK_UID | INI_ACCESS_CHECK_GID, @@ -108,11 +167,11 @@ int sss_ini_config_access_check(struct sss_ini_initdata *init_data) /* Get cstat */ -int sss_ini_get_stat(struct sss_ini_initdata *init_data) +int sss_ini_get_stat(struct sss_ini *self) { - init_data->cstat = ini_config_get_stat(init_data->file); + self->cstat = ini_config_get_stat(self->file); - if (!init_data->cstat) return EIO; + if (!self->cstat) return EIO; return EOK; } @@ -121,15 +180,20 @@ int sss_ini_get_stat(struct sss_ini_initdata *init_data) /* Get mtime */ -int sss_ini_get_mtime(struct sss_ini_initdata *init_data, +int sss_ini_get_mtime(struct sss_ini *self, size_t timestr_len, char *timestr) { return snprintf(timestr, timestr_len, "%llu", - (long long unsigned)init_data->cstat->st_mtime); + (long long unsigned)self->cstat->st_mtime); } +/* Get file_exists */ +bool sss_ini_exists(struct sss_ini *self) +{ + return self->main_config_exists; +} /* Print ini_config errors */ @@ -147,26 +211,19 @@ static void sss_ini_config_print_errors(char **error_list) } } - - -/* Load configuration */ - -int sss_ini_get_config(struct sss_ini_initdata *init_data, - const char *config_file, - const char *config_dir) +static int sss_ini_parse(struct sss_ini *self) { int ret; -#ifdef HAVE_LIBINI_CONFIG_V1_3 - const char *patterns[] = { "^[^\\.].*\\.conf$", NULL }; - const char *sections[] = { ".*", NULL }; - uint32_t i = 0; - char *msg = NULL; - struct access_check snip_check; - struct ini_cfgobj *modified_sssd_config = NULL; -#endif /* HAVE_LIBINI_CONFIG_V1_3 */ + + if (!self) { + return EINVAL; + } + + sss_ini_free_error_messages(self); + sss_ini_free_config(self); /* Create config object */ - ret = ini_config_create(&(init_data->sssd_config)); + ret = ini_config_create(&(self->sssd_config)); if (ret != EOK) { DEBUG(SSSDBG_FATAL_FAILURE, "Failed to create config object. Error %d.\n", ret); @@ -174,32 +231,46 @@ int sss_ini_get_config(struct sss_ini_initdata *init_data, } /* Parse file */ - ret = ini_config_parse(init_data->file, + ret = ini_config_parse(self->file, INI_STOP_ON_ANY, INI_MV1S_OVERWRITE, INI_PARSE_NOWRAP, - init_data->sssd_config); + self->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)) { + if (ini_config_error_count(self->sssd_config)) { DEBUG(SSSDBG_FATAL_FAILURE, "Errors detected while parsing: %s\n", - ini_config_get_filename(init_data->file)); + ini_config_get_filename(self->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_get_errors(self->sssd_config, + &(self->error_list)); } - ini_config_destroy(init_data->sssd_config); - init_data->sssd_config = NULL; - return ret; } + return ret; +} +static int sss_ini_add_snippets(struct sss_ini *self, + const char *config_dir) +{ #ifdef HAVE_LIBINI_CONFIG_V1_3 + int ret; + const char *patterns[] = { "^[^\\.].*\\.conf$", NULL }; + const char *sections[] = { ".*", NULL }; + uint32_t i = 0; + char *msg = NULL; + struct ini_cfgobj *modified_sssd_config = NULL; + struct access_check snip_check; + + if (self == NULL || self->sssd_config == NULL || config_dir == NULL) { + return EINVAL; + } + + sss_ini_free_ra_messages(self); + snip_check.flags = INI_ACCESS_CHECK_MODE | INI_ACCESS_CHECK_UID | INI_ACCESS_CHECK_GID; snip_check.uid = 0; /* owned by root */ @@ -207,7 +278,7 @@ int sss_ini_get_config(struct sss_ini_initdata *init_data, snip_check.mode = S_IRUSR; /* r**------ */ snip_check.mask = ALLPERMS & ~(S_IWUSR | S_IXUSR); - ret = ini_config_augment(init_data->sssd_config, + ret = ini_config_augment(self->sssd_config, config_dir, patterns, sections, @@ -217,22 +288,22 @@ int sss_ini_get_config(struct sss_ini_initdata *init_data, INI_PARSE_NOWRAP, INI_MV2S_OVERWRITE, &modified_sssd_config, - &init_data->ra_error_list, - &init_data->ra_success_list); + &self->ra_error_list, + &self->ra_success_list); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, - "Failed to augment configuration [%d]: %s", - ret, sss_strerror(ret)); + "Failed to augment configuration: Error %d", + ret); } - while (ref_array_get(init_data->ra_success_list, i, &msg) != NULL) { + while (ref_array_get(self->ra_success_list, i, &msg) != NULL) { DEBUG(SSSDBG_TRACE_FUNC, "Config merge success: %s\n", msg); i++; } i = 0; - while (ref_array_get(init_data->ra_error_list, i, &msg) != NULL) { + while (ref_array_get(self->ra_error_list, i, &msg) != NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "Config merge error: %s\n", msg); i++; @@ -240,31 +311,34 @@ int sss_ini_get_config(struct sss_ini_initdata *init_data, /* switch config objects if there are no errors */ if (modified_sssd_config != NULL) { - ini_config_destroy(init_data->sssd_config); - init_data->sssd_config = modified_sssd_config; + ini_config_destroy(self->sssd_config); + self->sssd_config = modified_sssd_config; } else { DEBUG(SSSDBG_TRACE_FUNC, "Using only main configuration file due to errors in merging\n"); } -#endif return ret; + +#else /* HAVE_LIBINI_CONFIG_V1_3 */ + return EOK +#endif /* ! HAVE_LIBINI_CONFIG_V1_3 */ } struct ref_array * -sss_ini_get_ra_success_list(struct sss_ini_initdata *init_data) +sss_ini_get_ra_success_list(struct sss_ini *self) { #ifdef HAVE_LIBINI_CONFIG_V1_3 - return init_data->ra_success_list; + return self->ra_success_list; #else return NULL; #endif /* HAVE_LIBINI_CONFIG_V1_3 */ } struct ref_array * -sss_ini_get_ra_error_list(struct sss_ini_initdata *init_data) +sss_ini_get_ra_error_list(struct sss_ini *self) { #ifdef HAVE_LIBINI_CONFIG_V1_3 - return init_data->ra_error_list; + return self->ra_error_list; #else return NULL; #endif /* HAVE_LIBINI_CONFIG_V1_3 */ @@ -272,18 +346,18 @@ sss_ini_get_ra_error_list(struct sss_ini_initdata *init_data) /* Get configuration object */ -int sss_ini_get_cfgobj(struct sss_ini_initdata *init_data, +int sss_ini_get_cfgobj(struct sss_ini *self, 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); + return sss_ini_get_config_obj(section,name, self->sssd_config, + INI_GET_FIRST_VALUE, &self->obj); } /* Check configuration object */ -int sss_ini_check_config_obj(struct sss_ini_initdata *init_data) +int sss_ini_check_config_obj(struct sss_ini *self) { - if (init_data->obj == NULL) { + if (self->obj == NULL) { return ENOENT; } @@ -294,32 +368,24 @@ int sss_ini_check_config_obj(struct sss_ini_initdata *init_data) /* Get integer value */ -int sss_ini_get_int_config_value(struct sss_ini_initdata *init_data, +int sss_ini_get_int_config_value(struct sss_ini *self, int strict, int def, int *error) { - return ini_get_int_config_value(init_data->obj, strict, def, error); + return ini_get_int_config_value(self->obj, strict, def, error); } +/* Get string value */ - -/* Destroy ini config (v1) */ - -void sss_ini_config_destroy(struct sss_ini_initdata *init_data) +const char *sss_ini_get_string_config_value(struct sss_ini *self, + int *error) { - if (init_data == NULL) return; - - if (init_data->sssd_config != NULL) { - ini_config_destroy(init_data->sssd_config); - init_data->sssd_config = NULL; - } + return ini_get_string_config_value(self->obj, error); } - - /* Create LDIF */ int sss_confdb_create_ldif(TALLOC_CTX *mem_ctx, - struct sss_ini_initdata *init_data, + struct sss_ini *self, const char *only_section, const char **config_ldif) { @@ -362,7 +428,7 @@ int sss_confdb_create_ldif(TALLOC_CTX *mem_ctx, /* 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, + sections = sss_ini_get_sec_list(self->sssd_config, §ion_count, &ret); if (ret != EOK) { goto error; @@ -401,7 +467,7 @@ int sss_confdb_create_ldif(TALLOC_CTX *mem_ctx, 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], + attrs = sss_ini_get_attr_list(self->sssd_config, sections[i], &attr_count, &ret); if (ret != EOK) { free_section_list(sections); @@ -412,7 +478,7 @@ int sss_confdb_create_ldif(TALLOC_CTX *mem_ctx, DEBUG(SSSDBG_TRACE_FUNC, "Processing attribute [%s]\n", attrs[j]); ret = sss_ini_get_config_obj(sections[i], attrs[j], - init_data->sssd_config, + self->sssd_config, INI_GET_FIRST_VALUE, &obj); if (ret != EOK) goto error; @@ -570,7 +636,7 @@ static int custom_sssd_checks(const char *rule_name, return EOK; } -static int sss_ini_call_validators_errobj(struct sss_ini_initdata *data, +static int sss_ini_call_validators_errobj(struct sss_ini *data, const char *rules_path, struct ini_errobj *errobj) { @@ -601,7 +667,7 @@ static int sss_ini_call_validators_errobj(struct sss_ini_initdata *data, } #endif /* HAVE_LIBINI_CONFIG_V1_3 */ -int sss_ini_call_validators(struct sss_ini_initdata *data, +int sss_ini_call_validators(struct sss_ini *data, const char *rules_path) { #ifdef HAVE_LIBINI_CONFIG_V1_3 @@ -643,7 +709,7 @@ int sss_ini_call_validators(struct sss_ini_initdata *data, } int sss_ini_call_validators_strs(TALLOC_CTX *mem_ctx, - struct sss_ini_initdata *data, + struct sss_ini *data, const char *rules_path, char ***_errors, size_t *_num_errors) @@ -710,7 +776,7 @@ int sss_ini_call_validators_strs(TALLOC_CTX *mem_ctx, #else DEBUG(SSSDBG_TRACE_FUNC, - "libini_config does not support configuration file validataion\n"); + "libini_config does not support configuration file validation\n"); if (_num_errors == NULL || _errors == NULL) { return EINVAL; @@ -720,3 +786,95 @@ int sss_ini_call_validators_strs(TALLOC_CTX *mem_ctx, return EOK; #endif /* HAVE_LIBINI_CONFIG_V1_3 */ } + +int sss_ini_open(struct sss_ini *self, + const char *config_file, + const char *fallback_cfg) +{ + int ret; + + if (self == NULL) { + return EINVAL; + } + + if (config_file != NULL) { + ret = sss_ini_config_file_open(self, config_file); + } else { + ret = ENOENT; + } + + switch (ret) { + case EOK: + break; + case ENOENT: + DEBUG(SSSDBG_TRACE_FUNC, "No %s.\n", config_file); + if (fallback_cfg == NULL) { + return ret; + } + + ret = sss_ini_config_file_from_mem(self, + discard_const(fallback_cfg), + strlen(fallback_cfg)); + if (ret != EOK) { + DEBUG(SSSDBG_FATAL_FAILURE, + "sss_ini_config_file_from_mem failed. Error %d\n", + ret); + } + break; + default: + DEBUG(SSSDBG_CONF_SETTINGS, + "sss_ini_config_file_open failed: Error %d\n", + ret); + sss_ini_config_print_errors(self->error_list); + break; + } + return ret; +} + +int sss_ini_read_sssd_conf(struct sss_ini *self, + const char *config_file, + const char *config_dir) +{ + errno_t ret; + + if (self == NULL) { + return EINVAL; + } + + ret = sss_ini_open(self, config_file, CONFDB_FALLBACK_CONFIG); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + "The sss_ini_open failed %s: %d\n", + config_file, + ret); + return ERR_INI_OPEN_FAILED; + } + + if (sss_ini_exists(self)) { + ret = sss_ini_access_check(self); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Permission check on config file failed.\n"); + return ERR_INI_INVALID_PERMISSION; + } else { + DEBUG(SSSDBG_CONF_SETTINGS, + "File %1$s does not exist.\n", + (config_file ? config_file : "NULL")); + } + } + + ret = sss_ini_parse(self); + if (ret != EOK) { + DEBUG(SSSDBG_FATAL_FAILURE, "Failed to parse configuration.\n"); + return ERR_INI_PARSE_FAILED; + } + + ret = sss_ini_add_snippets(self, config_dir); + if (ret != EOK) { + DEBUG(SSSDBG_FATAL_FAILURE, + "Error while reading configuration directory.\n"); + return ERR_INI_ADD_SNIPPETS_FAILED; + } + + return ret; +} diff --git a/src/util/sss_ini.h b/src/util/sss_ini.h index 0bf9c0ff5b..4e3f67fd6d 100644 --- a/src/util/sss_ini.h +++ b/src/util/sss_ini.h @@ -27,81 +27,138 @@ #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); - -/* Load config from buffer */ -int sss_ini_config_file_from_mem(void *data_buf, - uint32_t data_len, - struct sss_ini_initdata *init_data); - -/* 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, +#include <stdbool.h> + +/** + * @brief INI data structure + */ +struct sss_ini; + +/** + * @brief create new ini data object + * + * @param[in] tmp_ctx talloc context + * + * @return + * - pointer to newly allocated and initialized structure + * - NULL in case of error + */ +struct sss_ini* sss_ini_new(TALLOC_CTX *tmp_ctx); + + +/** + * @brief Open ini file or use fallback_cfg if file is not present. Include + * configuration snippets and perform access check. + * + * @param[in] self pointer to sss_ini structure + * @param[in] config_file ini file + * @param[in] config_dir directory containing ini files to be included + * + * @return + * - EOK - success + * - ERR_INI_OPEN_FAILED - sss_ini_open failed + * - ERR_INI_INVALID_PERMISSION - access check failed + * - ERR_INI_PARSE_FAILED - failed to parse configuration file + * - ERR_INI_ADD_SNIPPETS_FAILED - failed to add configuration snippets + */ +int sss_ini_read_sssd_conf(struct sss_ini *self, + const char *config_file, + const char *config_dir); + +/** + * @brief Open ini file or use fallback_cfg if file is not present + * + * @param[in] self pointer to sss_ini structure + * @param[in] config_file ini file + * @param[in] fallback_cfg string with ini content. This parameter is used + * when config_file doesn't exist or it is set to NULL + * + * @return error code + */ +int sss_ini_open(struct sss_ini *self, + const char *config_file, + const char *fallback_cfg); + +/** + * @brief Check whether sss_ini_open() reported that ini file is + * not present + * + * @param[in] self pointer to sss_ini structure + * + * @return + * - true we are using ini file + * - false file was not found + */ +bool sss_ini_exists(struct sss_ini *self); + +/** + * @brief get Cstat structure of the ini file + */ +int sss_ini_get_stat(struct sss_ini *self); + +/** + * @brief Get mtime of the ini file + */ +int sss_ini_get_mtime(struct sss_ini *self, size_t timestr_len, char *timestr); -/* Load configuration */ -int sss_ini_get_config(struct sss_ini_initdata *init_data, - const char *config_file, - const char *config_dir); -/* Get configuration object */ -int sss_ini_get_cfgobj(struct sss_ini_initdata *init_data, +/** + * @brief Get pointer to list of snippet parsing errors + */ +struct ref_array * +sss_ini_get_ra_error_list(struct sss_ini *self); + +/** + * @brief Get pointer to list of successfully merged snippet files + */ +struct ref_array * +sss_ini_get_ra_success_list(struct sss_ini *self); + +/** + * @brief Get configuration object + */ +int sss_ini_get_cfgobj(struct sss_ini *self, const char *section, const char *name); -/* Check configuration object */ -int sss_ini_check_config_obj(struct sss_ini_initdata *init_data); +/** + * @brief Check configuration object + */ +int sss_ini_check_config_obj(struct sss_ini *self); -/* Get int value */ -int sss_ini_get_int_config_value(struct sss_ini_initdata *init_data, +/** + * @brief Get int value + */ +int sss_ini_get_int_config_value(struct sss_ini *self, int strict, int def, int *error); -/* Destroy ini config */ -void sss_ini_config_destroy(struct sss_ini_initdata *init_data); +/** + * @brief Get string value + */ +const char *sss_ini_get_string_config_value(struct sss_ini *self, + int *error); -/* Create LDIF */ +/** + * @brief Create LDIF + */ int sss_confdb_create_ldif(TALLOC_CTX *mem_ctx, - struct sss_ini_initdata *init_data, + struct sss_ini *self, const char *only_section, const char **config_ldif); -/* Validate sssd.conf if libini_config support it */ -int sss_ini_call_validators(struct sss_ini_initdata *data, +/** + * @brief Validate sssd.conf if libini_config support it + */ +int sss_ini_call_validators(struct sss_ini *data, const char *rules_path); -/* Get errors from validators in array of strings */ +/** + * @brief Get errors from validators in array of strings + */ int sss_ini_call_validators_strs(TALLOC_CTX *mem_ctx, - struct sss_ini_initdata *data, + struct sss_ini *data, const char *rules_path, char ***_strs, size_t *_num_errors); -/* Get pointer to list of snippet parsing errors */ -struct ref_array * -sss_ini_get_ra_error_list(struct sss_ini_initdata *init_data); - -/* Get pointer to list of successfully merged snippet files */ -struct ref_array * -sss_ini_get_ra_success_list(struct sss_ini_initdata *init_data); - #endif /* __SSS_INI_H__ */ diff --git a/src/util/util_errors.c b/src/util/util_errors.c index 0148958d35..05a66d293b 100644 --- a/src/util/util_errors.c +++ b/src/util/util_errors.c @@ -137,6 +137,12 @@ struct err_string error_to_str[] = { { "Unknown bus owner" }, /* ERR_SBUS_UNKNOWN_OWNER */ { "No reply was received" }, /* ERR_SBUS_NO_REPLY */ + /* ini parsing errors */ + { "Failed to open configuration" }, /* ERR_INI_OPEN_FAILED */ + { "File ownership and permissions check failed" }, /* ERR_INI_INVALID_PERMISSION */ + { "Error while parsing configuration file" }, /* ERR_INI_PARSE_FAILED */ + { "Failed to add configuration snippets" }, /* ERR_INI_ADD_SNIPPETS_FAILED */ + { "ERR_LAST" } /* ERR_LAST */ }; diff --git a/src/util/util_errors.h b/src/util/util_errors.h index ec31a9ee93..41697ea522 100644 --- a/src/util/util_errors.h +++ b/src/util/util_errors.h @@ -158,6 +158,12 @@ enum sssd_errors { ERR_SBUS_UNKNOWN_OWNER, ERR_SBUS_NO_REPLY, + /* ini parsing errors */ + ERR_INI_OPEN_FAILED, + ERR_INI_INVALID_PERMISSION, + ERR_INI_PARSE_FAILED, + ERR_INI_ADD_SNIPPETS_FAILED, + ERR_LAST /* ALWAYS LAST */ };
_______________________________________________ sssd-devel mailing list -- sssd-devel@lists.fedorahosted.org To unsubscribe send an email to sssd-devel-le...@lists.fedorahosted.org Fedora Code of Conduct: https://docs.fedoraproject.org/en-US/project/code-of-conduct/ List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedorahosted.org/archives/list/sssd-devel@lists.fedorahosted.org