From 2b16db2fea5552225437ac7d622706b597b7a71d Mon Sep 17 00:00:00 2001 From: Jakub Filak Date: Fri, 19 Dec 2014 00:41:16 +0100 Subject: [ABRT PATCH 80/82] auto-reporting: add options to specify auth type See abrt-auto-reporting man page for more details about this commit. Related: #1174833 Signed-off-by: Jakub Filak --- doc/abrt-auto-reporting.txt | 41 ++++++- src/daemon/abrt-auto-reporting.c | 258 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 280 insertions(+), 19 deletions(-) diff --git a/doc/abrt-auto-reporting.txt b/doc/abrt-auto-reporting.txt index 1cc534e..2a27945 100644 --- a/doc/abrt-auto-reporting.txt +++ b/doc/abrt-auto-reporting.txt @@ -3,11 +3,14 @@ abrt-auto-reporting(1) NAME ---- -abrt-auto-reporting - Get or modify a value of the auto reporting option +abrt-auto-reporting - Get or modify the auto reporting option values SYNOPSIS -------- -'abrt-auto-reporting' [-v] [ enabled | yes | 1 | disabled | no | 0 ] +'abrt-auto-reporting' [-v] [ enabled | yes | 1 | on | disabled | no | 0 | off ] + [ [--anonymous] | + [--username USERNAME [--password PASSWORD] ] | + [--certificate SOURCE] ] DESCRIPTION ----------- @@ -23,6 +26,9 @@ process and will be persistent. ABRT uploads an uReport which was generated for a detected problem immediately after the detection phase. +Reads and saves the authentication configuration options in +/etc/libreport/plugins/ureport.conf and /etc/libreport/plugins/rhtsupport.conf + uReport description ~~~~~~~~~~~~~~~~~~~ ABRT supports uReports for four types of crashes: crashes of C/C++ programs @@ -51,6 +57,14 @@ for kernel oopses:: these are list of loaded kernel modules, list of taint flags, and full text of the kernel oops. +The authenticated uReports also contains *hostname* and *machineid* to enable a +server side filtering at https://access.redhat.com/. + +The authenticated uReports have the benefit of rich server replies which may +include a solution for the submitted crash. The authentication is done using +either Red Hat Subscription Certificates or Red Hat Customer Portal +credentials. + 'Warning': The full text of a kernel oops might contain information like the identification of the host hardware type. You should disable the autoreporting @@ -62,9 +76,30 @@ OPTIONS -v, --verbose:: Be more verbose. Can be given multiple times. +-a, --anonymous:: + Turns the authentication off by clearing both 'SSLClientAuth' and 'HTTPAuth' + configuration options in /etc/libreport/plugins/ureport.conf + +-u, --username USERNAME:: + Turns HTTP Authentication on by setting 'HTTPAuth' configuration option to + *rhts-credentials* in /etc/libreport/plugins/ureport.conf and storing + USERNAME and PASSWORD in /etc/libreport/plugins/rhtsupport.conf + Also turns the SSL Client Authentication off, because these methods cannot + be used together. + +-p, --password PASSWORD:: + Password for HTTP Authentication. If not provided, a prompt asking for it + will be issued. + +-c, --certificate SOURCE:: + Turns SSL Client Authentication on by setting 'SSLClientAuth' configuration + option to SOURCE in /etc/libreport/plugins/ureport.conf. + Also turns the HTTP Authentication off, because these methods cannot + be used together. + SEE ALSO -------- -abrt.conf(5) +abrt.conf(5), ureport.conf(5), rhtsupport.conf(5) AUTHORS ------- diff --git a/src/daemon/abrt-auto-reporting.c b/src/daemon/abrt-auto-reporting.c index 0909bed..f50c4c2 100644 --- a/src/daemon/abrt-auto-reporting.c +++ b/src/daemon/abrt-auto-reporting.c @@ -17,6 +17,7 @@ */ #include "libabrt.h" +#include "client.h" #include @@ -26,13 +27,24 @@ #define STATE_MANUAL "disabled" #define STATE_AUTO "enabled" -const char *const REPORTING_STATES[6][2] = { +#define RHTS_NAME "rhtsupport.conf" +#define RHTS_USERNAME_OPTION "Login" +#define RHTS_PASSWORD_OPTION "Password" + +#define UREPORT_NAME "ureport.conf" +#define UREPORT_HTTP_AUTH_OPTION "HTTPAuth" +#define UREPORT_CLIENT_AUTH_OPTION "SSLClientAuth" +#define UREPORT_RTHS_CREDENTIALS_AUTH "rhts-credentials" + +const char *const REPORTING_STATES[8][2] = { {STATE_MANUAL, "no" }, {STATE_AUTO, "yes"}, {"no", "no" }, {"yes", "yes"}, {"0", "no" }, {"1", "yes"}, + {"off", "no" }, + {"on", "yes"}, }; static int @@ -52,6 +64,77 @@ set_abrt_reporting(map_string_t *conf, const char *opt_value) return 1; } +static int +set_ureport_http_auth(map_string_t *conf, const char *opt_value) +{ + const char *const cur_value = get_map_string_item_or_NULL(conf, UREPORT_HTTP_AUTH_OPTION); + + if (cur_value == NULL || strcmp(cur_value, opt_value) != 0) + { + replace_map_string_item(conf, xstrdup(UREPORT_HTTP_AUTH_OPTION), xstrdup(opt_value)); + remove_map_string_item(conf, UREPORT_CLIENT_AUTH_OPTION); + + return save_plugin_conf_file(UREPORT_NAME, conf); + } + + /* No changes needed -> success */ + return 1; +} + +static int +set_ureport_client_auth(map_string_t *conf, const char *opt_value) +{ + const char *const cur_value = get_map_string_item_or_NULL(conf, UREPORT_CLIENT_AUTH_OPTION); + + if (cur_value == NULL || strcmp(cur_value, opt_value) != 0) + { + replace_map_string_item(conf, xstrdup(UREPORT_CLIENT_AUTH_OPTION), xstrdup(opt_value)); + remove_map_string_item(conf, UREPORT_HTTP_AUTH_OPTION); + + return save_plugin_conf_file(UREPORT_NAME, conf); + } + + /* No changes needed -> success */ + return 1; +} + +static int +clear_ureport_auth(map_string_t *conf) +{ + const char *const http_cur_value = get_map_string_item_or_NULL(conf, UREPORT_HTTP_AUTH_OPTION); + const char *const ssl_cur_value = get_map_string_item_or_NULL(conf, UREPORT_CLIENT_AUTH_OPTION); + + if (http_cur_value != NULL || ssl_cur_value != NULL) + { + remove_map_string_item(conf, UREPORT_HTTP_AUTH_OPTION); + remove_map_string_item(conf, UREPORT_CLIENT_AUTH_OPTION); + + return save_plugin_conf_file(UREPORT_NAME, conf); + } + + /* No changes needed -> success */ + return 1; +} + +static int +set_rhts_credentials(map_string_t *conf, const char *username, const char *password) +{ + const char *const username_cur_value = get_map_string_item_or_NULL(conf, RHTS_USERNAME_OPTION); + const char *const password_cur_value = get_map_string_item_or_NULL(conf, RHTS_PASSWORD_OPTION); + + if ( (username_cur_value == NULL || strcmp(username_cur_value, username) != 0) + || (password_cur_value == NULL || strcmp(password_cur_value, password) != 0)) + { + replace_map_string_item(conf, xstrdup(RHTS_USERNAME_OPTION), xstrdup(username)); + replace_map_string_item(conf, xstrdup(RHTS_PASSWORD_OPTION), xstrdup(password)); + + return save_plugin_conf_file(RHTS_NAME, conf); + } + + /* No changes needed -> success */ + return 1; +} + static const char * get_abrt_reporting(map_string_t *conf) { @@ -60,6 +143,18 @@ get_abrt_reporting(map_string_t *conf) return REPORTING_STATES[index][0]; } +static const char * +get_ureport_http_auth(map_string_t *conf) +{ + return get_map_string_item_or_NULL(conf, UREPORT_HTTP_AUTH_OPTION); +} + +static const char * +get_ureport_client_auth(map_string_t *conf) +{ + return get_map_string_item_or_NULL(conf, UREPORT_CLIENT_AUTH_OPTION); +} + int main(int argc, char *argv[]) { setlocale(LC_ALL, ""); @@ -78,7 +173,8 @@ int main(int argc, char *argv[]) abrt_init(argv); const char *program_usage_string = _( - "& [ "STATE_MANUAL" | "STATE_AUTO" | yes | no | 1 | 0 ]\n" + "& [ "STATE_MANUAL" | "STATE_AUTO" | yes | no | 1 | 0 ] \\\n" + " [[--anonymous] | [--username USERNAME [--password PASSWORD]] | [--certificate SOURCE]]\n" "\n" "Get or modify a value of the auto-reporting option. The changes will take\n" "effect immediately and will be persistent.\n" @@ -94,36 +190,72 @@ int main(int argc, char *argv[]) "contains identification of the operating system, versions of the RPM packages\n" "involved in the crash, and whether the program ran under a root user.\n" "\n" - "See abrt-auto-reporting(1) for more details.\n" + "See abrt-auto-reporting(1), reporter-ureport(1) and reporter-rhtsupport(1)\n" + "for more details.\n" ); + enum { + OPT_v = 1 << 0, + OPT_a = 1 << 1, + OPT_u = 1 << 2, + OPT_p = 1 << 3, + OPT_c = 1 << 4, + }; + + bool anonymous = false; + const char *username = NULL; + const char *password = NULL; + const char *certificate = NULL; + /* Keep enum above and order of options below in sync! */ struct options program_options[] = { OPT__VERBOSE(&g_verbose), + OPT_BOOL ( 'a', "anonymous", &anonymous, _("Turns the authentication off")), + OPT_STRING( 'u', "username", &username, "USERNAME", _("Red Hat Support user name")), + OPT_STRING( 'p', "password", &password, "PASSWORD", _("Red Hat Support password, if not given, a prompt for it will be issued")), + OPT_STRING( 'c', "certificate", &certificate, "SOURCE", _("uReport SSL certificate paths or certificate type")), OPT_END() }; - const unsigned optind = parse_opts(argc, argv, program_options, program_usage_string); + const unsigned opts = parse_opts(argc, argv, program_options, program_usage_string); argv += optind; argc -= optind; - if (argc > 2) + if ((opts & OPT_p) && !(opts & OPT_u)) { - error_msg(_("Invalid number of arguments")); + error_msg(_("You also need to specify --username for --password")); show_usage_and_die(program_usage_string, program_options); } - int exit_code = EXIT_FAILURE; + if ((opts & OPT_u) && (opts & OPT_c)) + { + error_msg(_("You can use either --username or --certificate")); + show_usage_and_die(program_usage_string, program_options); + } - map_string_t *conf = new_map_string(); - if (!load_abrt_conf_file(CONF_NAME, conf)) - goto finito; + if ((opts & OPT_u) && (opts & OPT_a)) + { + error_msg(_("You can use either --username or --anonymous")); + show_usage_and_die(program_usage_string, program_options); + } + + if ((opts & OPT_a) && (opts & OPT_c)) + { + error_msg(_("You can use either --anonymous or --certificate")); + show_usage_and_die(program_usage_string, program_options); + } + + if (argc > 1) + { + error_msg(_("Invalid number of arguments")); + show_usage_and_die(program_usage_string, program_options); + } - if (argc == 2) + const char *opt_value = NULL; + if (argc == 1) { - const char *const new_value = argv[1]; - const char *opt_value = NULL; + const char *const new_value = argv[0]; for (int i = 0; i < sizeof(REPORTING_STATES)/sizeof(REPORTING_STATES[0]); ++i) { if (strcasecmp(new_value, REPORTING_STATES[i][0]) == 0) @@ -138,15 +270,109 @@ int main(int argc, char *argv[]) error_msg(_("Unknown option value: '%s'\n"), new_value); show_usage_and_die(program_usage_string, program_options); } + } + + int exit_code = EXIT_FAILURE; + + map_string_t *conf = new_map_string(); + map_string_t *rhts_conf = new_map_string(); + map_string_t *rhts_conf_bck = NULL; + map_string_t *ureport_conf = new_map_string(); + map_string_t *ureport_conf_bck = NULL; + + if (!load_abrt_conf_file(CONF_NAME, conf)) + goto finito; - exit_code = set_abrt_reporting(conf, opt_value) ? EXIT_SUCCESS : EXIT_FAILURE; + if (!load_plugin_conf_file(RHTS_NAME, rhts_conf, false)) goto finito; + + if (!load_plugin_conf_file(UREPORT_NAME, ureport_conf, false)) + goto finito; + + if ((opts & OPT_a)) + { + ureport_conf_bck = clone_map_string(ureport_conf); + + if (!clear_ureport_auth(ureport_conf)) + goto finito; + } + + if ((opts & OPT_u)) + { + char *tmp_password = NULL; + if (!(opts & OPT_p)) + { + password = tmp_password = ask_password(_("Password:")); + if (tmp_password == NULL) + { + error_msg(_("Cannot continue without password\n")); + goto finito; + } + } + + ureport_conf_bck = clone_map_string(ureport_conf); + + if (!set_ureport_http_auth(ureport_conf, UREPORT_RTHS_CREDENTIALS_AUTH)) + goto finito; + + rhts_conf_bck = clone_map_string(rhts_conf); + + if (!set_rhts_credentials(rhts_conf, username, password)) + { + save_plugin_conf_file(UREPORT_NAME, ureport_conf_bck); + goto finito; + } + + free(tmp_password); + } + + if ((opts & OPT_c)) + { + ureport_conf_bck = clone_map_string(ureport_conf); + + if (!set_ureport_client_auth(ureport_conf, certificate)) + goto finito; + } + + if (argc == 0) + { + printf("%s", get_abrt_reporting(conf)); + exit_code = EXIT_SUCCESS; + + if (g_verbose >= 1) + { + const char *tmp = get_ureport_http_auth(ureport_conf); + if (tmp != NULL) + /* Print only the part before ':' of a string like "username:password" */ + printf(" %s (%*s)", _("HTTP Authenticated auto reporting"), (int)(strchrnul(tmp, ':') - tmp), tmp); + else if ((tmp = get_ureport_client_auth(ureport_conf)) != NULL) + printf(" %s (%s)", _("SSL Client Authenticated auto reporting"), tmp); + else + printf(" %s", _("anonymous auto reporting")); + } + + putchar('\n'); + + goto finito; + } + + exit_code = set_abrt_reporting(conf, opt_value) ? EXIT_SUCCESS : EXIT_FAILURE; + + if (exit_code == EXIT_FAILURE) + { + if (ureport_conf_bck != NULL) + save_plugin_conf_file(UREPORT_NAME, ureport_conf_bck); + + if (rhts_conf_bck != NULL) + save_plugin_conf_file(RHTS_NAME, rhts_conf_bck); } - printf("%s\n", get_abrt_reporting(conf)); - exit_code = EXIT_SUCCESS; finito: + free_map_string(ureport_conf); + free_map_string(ureport_conf_bck); + free_map_string(rhts_conf); + free_map_string(rhts_conf_bck); free_map_string(conf); return exit_code; } -- 1.8.3.1