From 987e758bfc639d5f45fd6acdd71f3b2c6a76996a Mon Sep 17 00:00:00 2001 From: Robbie Harwood (frozencemetery) Date: Aug 27 2015 17:12:28 +0000 Subject: [PATCH 1/4] Remove one layer of abstraction over dinglibs A handful of parameter name differences (`key` vs. `keyname`) have been tweaked but the function bodies are otherwise unchanged. Signed-off-by: Robbie Harwood (frozencemetery) --- diff --git a/proxy/Makefile.am b/proxy/Makefile.am index 8213625..013098b 100644 --- a/proxy/Makefile.am +++ b/proxy/Makefile.am @@ -132,7 +132,6 @@ dist_noinst_HEADERS = \ src/gp_export.h \ src/gp_conv.h \ src/gp_config.h \ - src/gp_config_dinglibs.h \ src/gp_debug.h \ src/gp_rpc_creds.h \ src/gp_selinux.h \ @@ -145,7 +144,6 @@ dist_noinst_HEADERS = \ gssproxy_SOURCES = \ src/gp_config.c \ - src/gp_config_dinglibs.c \ src/gp_init.c \ src/gp_socket.c \ src/gp_workers.c \ diff --git a/proxy/configure.ac b/proxy/configure.ac index 26430f8..c0bc9b0 100644 --- a/proxy/configure.ac +++ b/proxy/configure.ac @@ -95,7 +95,6 @@ else fi if test x$have_libini_config = x1; then - AC_DEFINE([WITH_DINGLIBS], [1], [Using ini_config]) INI_CFLAGS="$INI_CONFIG_CFLAGS" INI_LIBS="$INI_CONFIG_LIBS" else diff --git a/proxy/src/gp_config.c b/proxy/src/gp_config.c index bace4c8..2812e88 100644 --- a/proxy/src/gp_config.c +++ b/proxy/src/gp_config.c @@ -35,6 +35,8 @@ #include +#include + struct gp_flag_def { const char *name; uint32_t value; @@ -583,13 +585,62 @@ void free_config(struct gp_config **cfg) *cfg = NULL; } -#ifdef WITH_DINGLIBS -#include "gp_config_dinglibs.h" - int gp_config_init(const char *config_file, struct gp_ini_context *ctx) { - return gp_dinglibs_init(config_file, ctx); + struct ini_cfgobj *ini_config = NULL; + struct ini_cfgfile *file_ctx = NULL; + int ret; + + if (!ctx) { + return EINVAL; + } + + ret = ini_config_create(&ini_config); + if (ret) { + return ENOENT; + } + + ret = ini_config_file_open(config_file, + 0, /* metadata_flags, FIXME */ + &file_ctx); + if (ret) { + GPDEBUG("Failed to open config file: %d (%s)\n", + ret, gp_strerror(ret)); + ini_config_destroy(ini_config); + return ret; + } + + ret = ini_config_parse(file_ctx, + INI_STOP_ON_ANY, /* error_level */ + /* Merge section but allow duplicates */ + INI_MS_MERGE | + INI_MV1S_ALLOW | + INI_MV2S_ALLOW, + INI_PARSE_NOWRAP, /* parse_flags */ + ini_config); + if (ret) { + char **errors = NULL; + /* we had a parsing failure */ + GPDEBUG("Failed to parse config file: %d (%s)\n", + ret, gp_strerror(ret)); + if (ini_config_error_count(ini_config)) { + ini_config_get_errors(ini_config, &errors); + if (errors) { + ini_config_print_errors(stderr, errors); + ini_config_free_errors(errors); + } + } + ini_config_file_destroy(file_ctx); + ini_config_destroy(ini_config); + return ret; + } + + ini_config_file_destroy(file_ctx); + + ctx->private_data = ini_config; + + return 0; } int gp_config_get_string(struct gp_ini_context *ctx, @@ -597,7 +648,37 @@ int gp_config_get_string(struct gp_ini_context *ctx, const char *keyname, const char **value) { - return gp_dinglibs_get_string(ctx, secname, keyname, value); + struct ini_cfgobj *ini_config = (struct ini_cfgobj *)ctx->private_data; + struct value_obj *vo = NULL; + int ret; + const char *val; + + if (!value) { + return -1; + } + + *value = NULL; + + ret = ini_get_config_valueobj(secname, + keyname, + ini_config, + INI_GET_FIRST_VALUE, + &vo); + if (ret) { + return ret; + } + if (!vo) { + return ENOENT; + } + + val = ini_get_const_string_config_value(vo, &ret); + if (ret) { + return ret; + } + + *value = val; + + return 0; } int gp_config_get_string_array(struct gp_ini_context *ctx, @@ -606,8 +687,100 @@ int gp_config_get_string_array(struct gp_ini_context *ctx, int *num_values, const char ***values) { - return gp_dinglibs_get_string_array(ctx, secname, keyname, - num_values, values); + struct ini_cfgobj *ini_config = (struct ini_cfgobj *)ctx->private_data; + struct value_obj *vo = NULL; + const char *value; + int ret; + int i, count = 0; + const char **array = NULL; + const char **t_array; + + if (!values || !num_values) { + return EINVAL; + } + + *num_values = 0; + *values = NULL; + + ret = ini_get_config_valueobj(secname, + keyname, + ini_config, + INI_GET_FIRST_VALUE, + &vo); + if (ret) { + return ret; + } + if (!vo) { + return ENOENT; + } + + value = ini_get_const_string_config_value(vo, &ret); + if (ret) { + return ret; + } + + array = calloc(1, sizeof(char *)); + if (array == NULL) { + ret = ENOMEM; + goto done; + } + + array[count] = strdup(value); + if (array[count] == NULL) { + ret = ENOMEM; + goto done; + } + + count++; + + do { + ret = ini_get_config_valueobj(secname, + keyname, + ini_config, + INI_GET_NEXT_VALUE, + &vo); + if (ret) { + goto done; + } + if (!vo) { + break; + } + + value = ini_get_const_string_config_value(vo, &ret); + if (ret) { + goto done; + } + + t_array = realloc(array, (count+1) * sizeof(char *)); + if (t_array == NULL) { + ret = ENOMEM; + goto done; + } + array = t_array; + + array[count] = strdup(value); + if (array[count] == NULL) { + ret = ENOMEM; + goto done; + } + + count++; + + } while (1); + + *num_values = count; + *values = array; + + ret = 0; + +done: + if (ret && array) { + for (i = 0; i < count; i++) { + safefree(array[i]); + } + safefree(array); + } + return ret; } int gp_config_get_int(struct gp_ini_context *ctx, @@ -615,23 +788,98 @@ int gp_config_get_int(struct gp_ini_context *ctx, const char *keyname, int *value) { - return gp_dinglibs_get_int(ctx, secname, keyname, value); + struct ini_cfgobj *ini_config = (struct ini_cfgobj *)ctx->private_data; + struct value_obj *vo = NULL; + int ret; + int val; + + if (!value) { + return EINVAL; + } + + *value = -1; + + ret = ini_get_config_valueobj(secname, + keyname, + ini_config, + INI_GET_FIRST_VALUE, + &vo); + + if (ret) { + return ret; + } + if (!vo) { + return ENOENT; + } + + val = ini_get_int_config_value(vo, + 0, /* strict */ + 0, /* default */ + &ret); + if (ret) { + return ret; + } + + *value = val; + + return 0; } int gp_config_get_nsec(struct gp_ini_context *ctx) { - return gp_dinglibs_get_nsec(ctx); + struct ini_cfgobj *ini_config = (struct ini_cfgobj *)ctx->private_data; + char **list = NULL; + int count; + int error; + + list = ini_get_section_list(ini_config, &count, &error); + if (error) { + return 0; + } + + ini_free_section_list(list); + + return count; } char *gp_config_get_secname(struct gp_ini_context *ctx, int i) { - return gp_dinglibs_get_secname(ctx, i); + struct ini_cfgobj *ini_config = (struct ini_cfgobj *)ctx->private_data; + char **list = NULL; + int count; + int error; + char *secname; + + list = ini_get_section_list(ini_config, &count, &error); + if (error) { + return NULL; + } + + if (i >= count) { + return NULL; + } + + secname = strdup(list[i]); + ini_free_section_list(list); + if (!secname) { + return NULL; + } + + return secname; } int gp_config_close(struct gp_ini_context *ctx) { - return gp_dinglibs_close(ctx); -} + struct ini_cfgobj *ini_config = NULL; + + if (!ctx) { + return 0; + } -#endif /* WITH_DINGLIBS */ + ini_config = (struct ini_cfgobj *)ctx->private_data; + + ini_config_destroy(ini_config); + + return 0; +} diff --git a/proxy/src/gp_config_dinglibs.c b/proxy/src/gp_config_dinglibs.c deleted file mode 100644 index d2bd0e4..0000000 --- a/proxy/src/gp_config_dinglibs.c +++ /dev/null @@ -1,339 +0,0 @@ -/* - GSS-PROXY - - Copyright (C) 2011 Red Hat, Inc. - Copyright (C) 2011 Simo Sorce - Copyright (C) 2012-2013 Guenther Deschner - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. -*/ - -#include "config.h" -#include -#include -#include -#include -#include "gp_proxy.h" -#include "gp_config.h" -#include "gp_config_dinglibs.h" - -#ifdef WITH_DINGLIBS - -#include - -int gp_dinglibs_get_string(struct gp_ini_context *ctx, - const char *secname, - const char *key, - const char **value) -{ - struct ini_cfgobj *ini_config = (struct ini_cfgobj *)ctx->private_data; - struct value_obj *vo = NULL; - int ret; - const char *val; - - if (!value) { - return -1; - } - - *value = NULL; - - ret = ini_get_config_valueobj(secname, - key, - ini_config, - INI_GET_FIRST_VALUE, - &vo); - if (ret) { - return ret; - } - if (!vo) { - return ENOENT; - } - - val = ini_get_const_string_config_value(vo, &ret); - if (ret) { - return ret; - } - - *value = val; - - return 0; -} - -int gp_dinglibs_get_string_array(struct gp_ini_context *ctx, - const char *secname, - const char *key, - int *num_values, - const char ***values) -{ - struct ini_cfgobj *ini_config = (struct ini_cfgobj *)ctx->private_data; - struct value_obj *vo = NULL; - const char *value; - int ret; - int i, count = 0; - const char **array = NULL; - const char **t_array; - - if (!values || !num_values) { - return EINVAL; - } - - *num_values = 0; - *values = NULL; - - ret = ini_get_config_valueobj(secname, - key, - ini_config, - INI_GET_FIRST_VALUE, - &vo); - if (ret) { - return ret; - } - if (!vo) { - return ENOENT; - } - - value = ini_get_const_string_config_value(vo, &ret); - if (ret) { - return ret; - } - - array = calloc(1, sizeof(char *)); - if (array == NULL) { - ret = ENOMEM; - goto done; - } - - array[count] = strdup(value); - if (array[count] == NULL) { - ret = ENOMEM; - goto done; - } - - count++; - - do { - ret = ini_get_config_valueobj(secname, - key, - ini_config, - INI_GET_NEXT_VALUE, - &vo); - if (ret) { - goto done; - } - if (!vo) { - break; - } - - value = ini_get_const_string_config_value(vo, &ret); - if (ret) { - goto done; - } - - t_array = realloc(array, (count+1) * sizeof(char *)); - if (t_array == NULL) { - ret = ENOMEM; - goto done; - } - array = t_array; - - array[count] = strdup(value); - if (array[count] == NULL) { - ret = ENOMEM; - goto done; - } - - count++; - - } while (1); - - *num_values = count; - *values = array; - - ret = 0; - -done: - if (ret && array) { - for (i = 0; i < count; i++) { - safefree(array[i]); - } - safefree(array); - } - return ret; -} - -int gp_dinglibs_get_int(struct gp_ini_context *ctx, - const char *secname, - const char *key, - int *value) -{ - struct ini_cfgobj *ini_config = (struct ini_cfgobj *)ctx->private_data; - struct value_obj *vo = NULL; - int ret; - int val; - - if (!value) { - return EINVAL; - } - - *value = -1; - - ret = ini_get_config_valueobj(secname, - key, - ini_config, - INI_GET_FIRST_VALUE, - &vo); - - if (ret) { - return ret; - } - if (!vo) { - return ENOENT; - } - - val = ini_get_int_config_value(vo, - 0, /* strict */ - 0, /* default */ - &ret); - if (ret) { - return ret; - } - - *value = val; - - return 0; -} - -int gp_dinglibs_init(const char *config_file, - struct gp_ini_context *ctx) -{ - struct ini_cfgobj *ini_config = NULL; - struct ini_cfgfile *file_ctx = NULL; - int ret; - - if (!ctx) { - return EINVAL; - } - - ret = ini_config_create(&ini_config); - if (ret) { - return ENOENT; - } - - ret = ini_config_file_open(config_file, - 0, /* metadata_flags, FIXME */ - &file_ctx); - if (ret) { - GPDEBUG("Failed to open config file: %d (%s)\n", - ret, gp_strerror(ret)); - ini_config_destroy(ini_config); - return ret; - } - - ret = ini_config_parse(file_ctx, - INI_STOP_ON_ANY, /* error_level */ - /* Merge section but allow duplicates */ - INI_MS_MERGE | - INI_MV1S_ALLOW | - INI_MV2S_ALLOW, - INI_PARSE_NOWRAP, /* parse_flags */ - ini_config); - if (ret) { - char **errors = NULL; - /* we had a parsing failure */ - GPDEBUG("Failed to parse config file: %d (%s)\n", - ret, gp_strerror(ret)); - if (ini_config_error_count(ini_config)) { - ini_config_get_errors(ini_config, &errors); - if (errors) { - ini_config_print_errors(stderr, errors); - ini_config_free_errors(errors); - } - } - ini_config_file_destroy(file_ctx); - ini_config_destroy(ini_config); - return ret; - } - - ini_config_file_destroy(file_ctx); - - ctx->private_data = ini_config; - - return 0; -} - -int gp_dinglibs_close(struct gp_ini_context *ctx) -{ - struct ini_cfgobj *ini_config = NULL; - - if (!ctx) { - return 0; - } - - ini_config = (struct ini_cfgobj *)ctx->private_data; - - ini_config_destroy(ini_config); - - return 0; -} - -int gp_dinglibs_get_nsec(struct gp_ini_context *ctx) -{ - struct ini_cfgobj *ini_config = (struct ini_cfgobj *)ctx->private_data; - char **list = NULL; - int count; - int error; - - list = ini_get_section_list(ini_config, &count, &error); - if (error) { - return 0; - } - - ini_free_section_list(list); - - return count; -} - -char *gp_dinglibs_get_secname(struct gp_ini_context *ctx, - int i) -{ - struct ini_cfgobj *ini_config = (struct ini_cfgobj *)ctx->private_data; - char **list = NULL; - int count; - int error; - char *secname; - - list = ini_get_section_list(ini_config, &count, &error); - if (error) { - return NULL; - } - - if (i >= count) { - return NULL; - } - - secname = strdup(list[i]); - ini_free_section_list(list); - if (!secname) { - return NULL; - } - - return secname; -} - -#endif /* WITH_DINGLIBS */ diff --git a/proxy/src/gp_config_dinglibs.h b/proxy/src/gp_config_dinglibs.h deleted file mode 100644 index b969c76..0000000 --- a/proxy/src/gp_config_dinglibs.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - GSS-PROXY - - Copyright (C) 2011 Red Hat, Inc. - Copyright (C) 2011 Simo Sorce - Copyright (C) 2012-2013 Guenther Deschner - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. -*/ - -int gp_dinglibs_get_string(struct gp_ini_context *ctx, - const char *secname, - const char *key, - const char **value); -int gp_dinglibs_get_string_array(struct gp_ini_context *ctx, - const char *secname, - const char *key, - int *num_values, - const char ***values); -int gp_dinglibs_get_int(struct gp_ini_context *ctx, - const char *secname, - const char *key, - int *value); -int gp_dinglibs_init(const char *config_file, - struct gp_ini_context *ctx); -int gp_dinglibs_close(struct gp_ini_context *ctx); -int gp_dinglibs_get_nsec(struct gp_ini_context *ctx); -char *gp_dinglibs_get_secname(struct gp_ini_context *ctx, - int i); From 8be46b8f26b021bbd0518614c69dc2c515351cd2 Mon Sep 17 00:00:00 2001 From: Robbie Harwood (frozencemetery) Date: Aug 27 2015 17:13:02 +0000 Subject: [PATCH 2/4] Add support for config directories Option '-d|--configdir' has been added, and defaults to /etc/gssproxy. All files ending in ".conf" from that directory will be read. Ticket: https://fedorahosted.org/gss-proxy/ticket/122 Signed-off-by: Robbie Harwood (frozencemetery) --- diff --git a/proxy/src/gp_config.c b/proxy/src/gp_config.c index 2812e88..da58c86 100644 --- a/proxy/src/gp_config.c +++ b/proxy/src/gp_config.c @@ -427,6 +427,7 @@ done: } static int gp_init_ini_context(const char *config_file, + const char *config_dir, struct gp_ini_context **ctxp) { struct gp_ini_context *ctx; @@ -441,7 +442,7 @@ static int gp_init_ini_context(const char *config_file, return ENOENT; } - ret = gp_config_init(config_file, ctx); + ret = gp_config_init(config_file, config_dir, ctx); if (ret) { free(ctx); @@ -457,7 +458,7 @@ int load_config(struct gp_config *cfg) const char *tmpstr; int ret; - ret = gp_init_ini_context(cfg->config_file, &ctx); + ret = gp_init_ini_context(cfg->config_file, cfg->config_dir, &ctx); if (ret) { return ret; } @@ -499,10 +500,9 @@ done: return ret; } -struct gp_config *read_config(char *config_file, char *socket_name, - int opt_daemonize) +struct gp_config *read_config(char *config_file, char *config_dir, + char *socket_name, int opt_daemonize) { - const char *socket = GP_SOCKET_NAME; struct gp_config *cfg; int ret; @@ -514,21 +514,19 @@ struct gp_config *read_config(char *config_file, char *socket_name, if (config_file) { cfg->config_file = strdup(config_file); if (!cfg->config_file) { - free(cfg); - return NULL; + ret = ENOMEM; + goto done; } } else { - ret = asprintf(&cfg->config_file, "%s/gssproxy.conf", PUBCONF_PATH); - if (ret == -1) { - free(cfg); - return NULL; + cfg->config_dir = strdup(config_dir ? config_dir : PUBCONF_PATH); + if (!cfg->config_dir) { + ret = ENOMEM; + goto done; } } - if (socket_name) socket = socket_name; - - cfg->socket_name = strdup(socket); - if (cfg->socket_name == NULL) { + cfg->socket_name = strdup(socket_name ? socket_name : GP_SOCKET_NAME); + if (!cfg->socket_name) { ret = ENOMEM; goto done; } @@ -546,12 +544,22 @@ struct gp_config *read_config(char *config_file, char *socket_name, ret = load_config(cfg); if (ret) { - GPDEBUG("Config file not found!\n"); + GPDEBUG("Config file(s) not found!\n"); } done: if (ret) { + if (cfg->config_file) { + free(cfg->config_file); + } + if (cfg->config_dir) { + free(cfg->config_dir); + } + if (cfg->socket_name) { + free(cfg->socket_name); + } free_config(&cfg); + return NULL; } return cfg; @@ -585,45 +593,34 @@ void free_config(struct gp_config **cfg) *cfg = NULL; } -int gp_config_init(const char *config_file, - struct gp_ini_context *ctx) +static int gp_config_from_file(const char *config_file, + struct gp_ini_context *ctx, + struct ini_cfgobj *ini_config, + const uint32_t collision_flags) { - struct ini_cfgobj *ini_config = NULL; struct ini_cfgfile *file_ctx = NULL; int ret; - if (!ctx) { - return EINVAL; - } - - ret = ini_config_create(&ini_config); - if (ret) { - return ENOENT; - } - ret = ini_config_file_open(config_file, 0, /* metadata_flags, FIXME */ &file_ctx); if (ret) { GPDEBUG("Failed to open config file: %d (%s)\n", - ret, gp_strerror(ret)); + ret, gp_strerror(ret)); ini_config_destroy(ini_config); return ret; } ret = ini_config_parse(file_ctx, INI_STOP_ON_ANY, /* error_level */ - /* Merge section but allow duplicates */ - INI_MS_MERGE | - INI_MV1S_ALLOW | - INI_MV2S_ALLOW, + collision_flags, INI_PARSE_NOWRAP, /* parse_flags */ ini_config); if (ret) { char **errors = NULL; /* we had a parsing failure */ GPDEBUG("Failed to parse config file: %d (%s)\n", - ret, gp_strerror(ret)); + ret, gp_strerror(ret)); if (ini_config_error_count(ini_config)) { ini_config_get_errors(ini_config, &errors); if (errors) { @@ -637,7 +634,95 @@ int gp_config_init(const char *config_file, } ini_config_file_destroy(file_ctx); + return 0; +} +static int gp_config_from_dir(const char *config_dir, + struct gp_ini_context *ctx, + struct ini_cfgobj **ini_config, + const uint32_t collision_flags) +{ + struct ini_cfgobj *result_cfg = NULL; + struct ref_array *error_list = NULL; + int ret; + + const char *patterns[] = { + /* match only files ending in ".conf" */ + "^.*\\.conf$", + NULL, + }; + + const char *sections[] = { + /* match either "gssproxy" or sections that start with "service/" */ + "^gssproxy$", + "^service/.*$", + NULL, + }; + + /* Permission check failures silently skip the file, so they are not + * useful to us. */ + ret = ini_config_augment(*ini_config, + config_dir, + patterns, + sections, + NULL, /* check_perm */ + INI_STOP_ON_ANY, /* error_level */ + collision_flags, + INI_PARSE_NOWRAP, + INI_MS_ERROR, + &result_cfg, + &error_list, + NULL); + if (ret) { + if (error_list) { + uint32_t i; + uint32_t len = ref_array_getlen(error_list, &i); + for (i = 0; i < len; i++) { + GPDEBUG("Error when reading config directory: %s\n", + (const char *) ref_array_get(error_list, i, NULL)); + } + ref_array_destroy(error_list); + } else { + GPDEBUG("Error when reading config directory number: %d\n", ret); + } + return ret; + } + + ini_config_destroy(*ini_config); + *ini_config = result_cfg; + return 0; +} + +int gp_config_init(const char *config_file, const char *config_dir, + struct gp_ini_context *ctx) +{ + struct ini_cfgobj *ini_config = NULL; + int ret; + + /* Merge section but allow duplicates */ + const uint32_t collision_flags = + INI_MS_MERGE | INI_MV1S_ALLOW | INI_MV2S_ALLOW; + + if (!ctx) { + return EINVAL; + } + + ret = ini_config_create(&ini_config); + if (ret) { + return ENOENT; + } + + if (config_file) { + ret = gp_config_from_file(config_file, ctx, ini_config, + collision_flags); + } else { + ret = gp_config_from_dir(config_dir, ctx, &ini_config, + collision_flags); + } + if (ret) { + return ret; + } + ctx->private_data = ini_config; return 0; diff --git a/proxy/src/gp_config.h b/proxy/src/gp_config.h index 9d0d1d7..1bc756c 100644 --- a/proxy/src/gp_config.h +++ b/proxy/src/gp_config.h @@ -31,7 +31,7 @@ struct gp_ini_context { void *private_data; }; -int gp_config_init(const char *config_file, +int gp_config_init(const char *config_file, const char *config_dir, struct gp_ini_context *ctx); int gp_config_get_string(struct gp_ini_context *ctx, const char *secname, diff --git a/proxy/src/gp_proxy.h b/proxy/src/gp_proxy.h index 68c724c..72bbc5c 100644 --- a/proxy/src/gp_proxy.h +++ b/proxy/src/gp_proxy.h @@ -68,6 +68,7 @@ struct gp_service { struct gp_config { char *config_file; /* gssproxy configuration file */ + char *config_dir; /* gssproxy configuration directory */ bool daemonize; /* let gssproxy daemonize */ char *socket_name; /* the socket name to use for */ int num_workers; /* number of worker threads */ @@ -101,8 +102,8 @@ struct gp_call_ctx { }; /* from gp_config.c */ -struct gp_config *read_config(char *config_file, char *socket_name, - int opt_daemonize); +struct gp_config *read_config(char *config_file, char *config_dir, + char *socket_name, int opt_daemonize); struct gp_creds_handle *gp_service_get_creds_handle(struct gp_service *svc); void free_config(struct gp_config **config); diff --git a/proxy/src/gssproxy.c b/proxy/src/gssproxy.c index 354d595..35040e3 100644 --- a/proxy/src/gssproxy.c +++ b/proxy/src/gssproxy.c @@ -36,6 +36,7 @@ int main(int argc, const char *argv[]) int opt_interactive = 0; int opt_version = 0; char *opt_config_file = NULL; + char *opt_config_dir = NULL; char *opt_config_socket = NULL; int opt_debug = 0; verto_ctx *vctx; @@ -55,6 +56,8 @@ int main(int argc, const char *argv[]) _("Run interactive (not a daemon)"), NULL}, \ {"config", 'c', POPT_ARG_STRING, &opt_config_file, 0, \ _("Specify a non-default config file"), NULL}, \ + {"configdir", 'd', POPT_ARG_STRING, &opt_config_dir, 0, \ + _("Specify a non-default config directory"), NULL}, \ {"socket", 's', POPT_ARG_STRING, &opt_config_socket, 0, \ _("Specify a custom default socket"), NULL}, \ {"debug", 'd', POPT_ARG_NONE, &opt_debug, 0, \ @@ -90,6 +93,12 @@ int main(int argc, const char *argv[]) return 1; } + if (opt_config_file && opt_config_dir) { + fprintf(stderr, "Option -d|--configdir is not allowed together with -c|--config\n"); + poptPrintUsage(pc, stderr, 0); + return 1; + } + if (opt_interactive) { opt_daemon = 2; } @@ -97,6 +106,7 @@ int main(int argc, const char *argv[]) gpctx = calloc(1, sizeof(struct gssproxy_ctx)); gpctx->config = read_config(opt_config_file, + opt_config_dir, opt_config_socket, opt_daemon); if (!gpctx->config) { From 75673f1251d3ca2a4f1c636a02d42756921a1928 Mon Sep 17 00:00:00 2001 From: Robbie Harwood (frozencemetery) Date: Aug 27 2015 17:13:06 +0000 Subject: [PATCH 3/4] Update man pages for symbolic euids and config snippets Signed-off-by: Robbie Harwood (frozencemetery) --- diff --git a/proxy/man/gssproxy.8.xml b/proxy/man/gssproxy.8.xml index 68f5ff7..87cf778 100644 --- a/proxy/man/gssproxy.8.xml +++ b/proxy/man/gssproxy.8.xml @@ -72,9 +72,29 @@ - Specify a non-default config file. The default is - /etc/gssproxy/gssproxy.conf. For reference - on the config file syntax and options, consult the + Specify a config file to use instead of the + default directory. The default is to use the + directory /etc/gssproxy + instead. For reference on the config file + syntax and options, consult the + + gssproxy.conf + 5 + + manual page. + + + + + + , + + + + Specify a non-default config dir. The default + is /etc/gssproxy. For + reference on the config file syntax and + options, consult the gssproxy.conf 5 diff --git a/proxy/man/gssproxy.conf.5.xml b/proxy/man/gssproxy.conf.5.xml index 95fdb65..b7770c9 100644 --- a/proxy/man/gssproxy.conf.5.xml +++ b/proxy/man/gssproxy.conf.5.xml @@ -25,7 +25,7 @@ Optional configuration directives for the gssproxy daemon. - The gssproxy.conf file is a classic ini-style configuration file. + GSS-Proxy conf files are classic ini-style configuration files. Each option consist of a key = value pair. Any characters behind '#' will be treated as comments and will be ignored. Boolean parameters accept "1", "true", "yes" and "on" as @@ -37,7 +37,7 @@ SECTIONS - A section in the gssproxy.conf file is identified by the sectionname in square brackets ([sectionname]). + A section in a GSS-Proxy conf file is identified by the sectionname in square brackets ([sectionname]). There is one special section for global gssproxy settings, called @@ -152,9 +152,11 @@ - euid (integer) + euid (integer or string) - The numeric effective uid of a running process, required to identify a service. + Either the numeric (e.g., 48) or symbolic (e.g., + apache) effective uid of a running process, + required to identify a service. The "euid" parameter is imperative, any section without it will be discarded. Default: euid = From 92d964205a3a02b3bcfe0f11bb3d24f8ec91cf58 Mon Sep 17 00:00:00 2001 From: Robbie Harwood (frozencemetery) Date: Aug 27 2015 20:12:21 +0000 Subject: [PATCH 4/4] Error on `allow_any_uid` issues As per gssproxy.conf(5), setting allow_any_uid without also setting socket or selinux_context is known to cause problems. Signed-off-by: Robbie Harwood (frozencemetery) --- diff --git a/proxy/src/gp_config.c b/proxy/src/gp_config.c index da58c86..bfc0222 100644 --- a/proxy/src/gp_config.c +++ b/proxy/src/gp_config.c @@ -206,6 +206,42 @@ static int setup_service_creds_handle(struct gp_service *svc) return 0; } +static int check_services(const struct gp_config *cfg) +{ + int i; + char *blocker_name = NULL; + + /* [gssproxy] section does not got placed in svcs */ + for (i = 0; i < cfg->num_svcs; i++) { + if (!blocker_name) { + if (cfg->svcs[i]->any_uid && i + 1 != cfg->num_svcs && + !cfg->svcs[i]->socket && !cfg->svcs[i]->selinux_ctx) { + if (i + 1 == cfg->num_svcs) { + /* it is not fatal to do this as the last service */ + GPAUDIT("Service '%s' sets allow_any_uid (but not " + "socket or selinux_context); consider fixing.", + cfg->svcs[i]->name); + break; + } + + blocker_name = cfg->svcs[i]->name; + GPERROR("Service '%s' sets allow_any_uid (but not socket or " + "selinux_context) and is not the last service!\n", + blocker_name); + GPERROR("See gssproxy.conf(5). Services masked this way:\n"); + } + } else { + GPERROR("(service '%s' masks service '%s')", blocker_name, + cfg->svcs[i]->name); + } + } + + if (blocker_name) { + return EINVAL; + } + return 0; +} + static int load_services(struct gp_config *cfg, struct gp_ini_context *ctx) { int num_sec; @@ -419,7 +455,7 @@ static int load_services(struct gp_config *cfg, struct gp_ini_context *ctx) return ENOENT; } - ret = 0; + ret = check_services(cfg); done: safefree(secname);