diff options
Diffstat (limited to 'src/tools/sssctl/sssctl_logs.c')
-rw-r--r-- | src/tools/sssctl/sssctl_logs.c | 292 |
1 files changed, 292 insertions, 0 deletions
diff --git a/src/tools/sssctl/sssctl_logs.c b/src/tools/sssctl/sssctl_logs.c index 472a553d1..32e0a7ac5 100644 --- a/src/tools/sssctl/sssctl_logs.c +++ b/src/tools/sssctl/sssctl_logs.c @@ -18,6 +18,17 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include "config.h" + +#include <stdlib.h> +#include <limits.h> +#include <talloc.h> +#include <sys/types.h> +#include <dirent.h> +#include <ctype.h> +#include <signal.h> +#include <utime.h> +#include <ldb.h> #include <popt.h> #include <stdio.h> #include <signal.h> @@ -26,15 +37,194 @@ #include "tools/common/sss_process.h" #include "tools/sssctl/sssctl.h" #include "tools/tools_util.h" +#include "confdb/confdb.h" #define LOG_FILE(file) " " LOG_PATH "/" file #define LOG_FILES LOG_FILE("*.log") +#define CHECK(expr, done, msg) do { \ + if (expr) { \ + ERROR(msg "\n"); \ + goto done; \ + } \ +} while(0) + +struct debuglevel_tool_ctx { + struct confdb_ctx *confdb; + char **sections; +}; + struct sssctl_logs_opts { int delete; int archived; }; +errno_t set_debug_level(struct debuglevel_tool_ctx *tool_ctx, + int debug_to_set, const char *config_file) +{ + int ret; + int err; + const char *values[2]; + char **section = NULL; + TALLOC_CTX *tmp_ctx = talloc_new(NULL); + + if (tmp_ctx == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n"); + return ENOMEM; + } + + /* convert debug_to_set to string */ + values[0] = talloc_asprintf(tmp_ctx, "0x%.4x", debug_to_set); + if (values[0] == NULL) { + ret = ENOMEM; + goto done; + } + values[1] = NULL; + + /* write to confdb */ + for (section = tool_ctx->sections; *section != NULL; section++) { + ret = confdb_add_param(tool_ctx->confdb, 1, *section, + CONFDB_SERVICE_DEBUG_LEVEL, values); + if (ret != EOK) { + goto done; + } + } + + /* + * Change atime and mtime of sssd.conf, + * so the configuration can be restored on next start. + */ + errno = 0; + if (utime(config_file, NULL) == -1) { + err = errno; + DEBUG(SSSDBG_MINOR_FAILURE, "Unable to change mtime of \"%s\": %s\n", + config_file, strerror(err)); + } + + ret = EOK; + +done: + talloc_free(tmp_ctx); + return ret; +} + +errno_t connect_to_confdb(TALLOC_CTX *ctx, struct confdb_ctx **cdb_ctx) +{ + int ret; + char *confdb_path = NULL; + + confdb_path = talloc_asprintf(ctx, "%s/%s", DB_PATH, CONFDB_FILE); + if (confdb_path == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Could not allocate memory for confdb path\n"); + return ENOMEM; + } + + ret = confdb_init(ctx, cdb_ctx, confdb_path); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Could not initialize connection to the confdb\n"); + } + + talloc_free(confdb_path); + return ret; +} + +errno_t get_confdb_sections(TALLOC_CTX *ctx, struct confdb_ctx *confdb, + char ***output_sections) +{ + int ret; + int domain_count = 0; + int i = 0; + struct sss_domain_info *domain = NULL; + struct sss_domain_info *domain_list = NULL; + char **sections; + const char *known_services[] = { + CONFDB_MONITOR_CONF_ENTRY, + CONFDB_NSS_CONF_ENTRY, + CONFDB_PAM_CONF_ENTRY, + CONFDB_PAC_CONF_ENTRY, + CONFDB_SSH_CONF_ENTRY, + CONFDB_SUDO_CONF_ENTRY, + CONFDB_AUTOFS_CONF_ENTRY, + CONFDB_IFP_CONF_ENTRY, + }; + static const int known_services_count = sizeof(known_services) + / sizeof(*known_services); + TALLOC_CTX *tmp_ctx = talloc_new(NULL); + + if (tmp_ctx == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n"); + return ENOMEM; + } + + /* get domains */ + ret = confdb_get_domains(confdb, &domain_list); + if (ret != EOK) + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get domain list\n"); + + for (domain = domain_list; + domain; + domain = get_next_domain(domain, 0)) { + domain_count++; + } + + /* allocate output space */ + sections = talloc_array(ctx, char *, + domain_count + known_services_count + 1); + if (sections == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Could not allocate memory for sections\n"); + ret = ENOMEM; + goto fail; + } + + for (i = 0; i < known_services_count; i++) { + sections[i] = talloc_strdup(tmp_ctx, known_services[i]); + if (sections[i] == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup() failed\n"); + ret = ENOMEM; + goto fail; + } + } + + for (domain = domain_list; + domain; + domain = get_next_domain(domain, 0), i++) { + sections[i] = talloc_asprintf(tmp_ctx, CONFDB_DOMAIN_PATH_TMPL, + domain->name); + if (sections[i] == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf() failed\n"); + ret = ENOMEM; + goto fail; + } + } + + /* add NULL to the end */ + sections[i] = NULL; + + *output_sections = talloc_steal(ctx, sections); + + return EOK; +fail: + talloc_free(tmp_ctx); + return ret; +} + +int parse_debug_level(const char *strlevel) +{ + long value; + char *endptr; + + errno = 0; + value = strtol(strlevel, &endptr, 0); + if ((errno != 0) || (endptr == strlevel) || (*endptr != '\0')) { + return SSSDBG_INVALID; + } + + return debug_convert_old_level(value); +} + errno_t sssctl_logs_remove(struct sss_cmdline *cmdline, struct sss_tool_ctx *tool_ctx, void *pvt) @@ -105,3 +295,105 @@ errno_t sssctl_logs_fetch(struct sss_cmdline *cmdline, return EOK; } + +errno_t sssctl_debug_level(struct sss_cmdline *cmdline, + struct sss_tool_ctx *tool_ctx, + void *pvt) +{ + int ret; + int pc_debug = SSSDBG_DEFAULT; + int debug_to_set = SSSDBG_INVALID; + const char *debug_as_string = NULL; + const char *config_file = NULL; + const char *pc_config_file = NULL; + struct debuglevel_tool_ctx *ctx = NULL; + struct poptOption long_options[] = { + POPT_AUTOHELP + {"debug", '\0', POPT_ARG_INT | POPT_ARGFLAG_DOC_HIDDEN, &pc_debug, + 0, _("The debug level to run with"), NULL }, + {"config", 'c', POPT_ARG_STRING, &pc_config_file, + 0, _("Specify a non-default config file"), NULL}, + POPT_TABLEEND + }; + poptContext pc = NULL; + + debug_prg_name = cmdline->argv[0]; + + /* parse parameters */ + pc = poptGetContext(cmdline->argv[0], cmdline->argc, cmdline->argv, + long_options, POPT_CONTEXT_KEEP_FIRST); + poptSetOtherOptionHelp(pc, "DEBUG_LEVEL_TO_SET"); + while ((ret = poptGetNextOpt(pc)) != -1) { + switch (ret) { + default: + fprintf(stderr, "\nInvalid option %s: %s\n\n", + poptBadOption(pc, 0), poptStrerror(ret)); + poptPrintUsage(pc, stderr, 0); + ret = EXIT_FAILURE; + goto fini; + } + } + DEBUG_CLI_INIT(pc_debug); + + /* get debug level */ + debug_as_string = poptGetArg(pc); + if (debug_as_string == NULL) { + BAD_POPT_PARAMS(pc, _("Specify debug level you want to set\n"), + ret, fini); + } + + /* No more arguments expected. If something follows it is an error. */ + if (poptGetArg(pc)) { + BAD_POPT_PARAMS(pc, _("Only one argument expected\n"), + ret, fini); + } + + /* get config file */ + if (pc_config_file) { + config_file = talloc_strdup(ctx, pc_config_file); + } else { + config_file = talloc_strdup(ctx, SSSD_CONFIG_FILE); + } + + if (config_file == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup() failed\n"); + ret = ENOMEM; + goto fini; + } + + CHECK_ROOT(ret, debug_prg_name); + + /* free pc_config_file? */ + /* free debug_as_string? */ + + debug_to_set = parse_debug_level(debug_as_string); + CHECK(debug_to_set == SSSDBG_INVALID, fini, "Invalid debug level."); + + /* allocate context */ + ctx = talloc_zero(NULL, struct debuglevel_tool_ctx); + if (ctx == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Could not allocate memory for tools context\n"); + ret = ENOMEM; + goto fini; + } + + ret = connect_to_confdb(ctx, &ctx->confdb); + CHECK(ret != EOK, fini, "Could not connect to configuration database."); + + ret = get_confdb_sections(ctx, ctx->confdb, &ctx->sections); + CHECK(ret != EOK, fini, "Could not get all configuration sections."); + + ret = set_debug_level(ctx, debug_to_set, config_file); + CHECK(ret != EOK, fini, "Could not set debug level."); + + ret = sss_signal(SIGHUP); + CHECK(ret != EOK, fini, + "Could not force sssd processes to reload configuration. " + "Is sssd running?"); + +fini: + poptFreeContext(pc); + talloc_free(ctx); + return ret; +} |