/* Copyright (C) 2014 RedHat inc. 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 2 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, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "libabrt.h" #include "client.h" #include #define CONF_NAME "abrt.conf" #define OPTION_NAME "AutoreportingEnabled" #define STATE_MANUAL "disabled" #define STATE_AUTO "enabled" #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 set_abrt_reporting(map_string_t *conf, const char *opt_value) { const char *const def_value = REPORTING_STATES[0][1]; const char *const cur_value = get_map_string_item_or_NULL(conf, OPTION_NAME); if ( (cur_value == NULL && strcmp(def_value, opt_value) != 0) || (cur_value != NULL && strcmp(cur_value, opt_value) != 0)) { replace_map_string_item(conf, xstrdup(OPTION_NAME), xstrdup(opt_value)); return save_abrt_conf_file(CONF_NAME, conf); } /* No changes needed -> success */ return 1; } #if AUTHENTICATED_AUTOREPORTING != 0 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; } #endif static const char * get_abrt_reporting(map_string_t *conf) { const char *const cur_value = get_map_string_item_or_empty(conf, OPTION_NAME); const int index = !!string_to_bool(cur_value); return REPORTING_STATES[index][0]; } #if AUTHENTICATED_AUTOREPORTING != 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); } #endif int main(int argc, char *argv[]) { setlocale(LC_ALL, ""); /* Hack: * Right-to-left scripts don't work properly in many terminals. * Hebrew speaking people say he_IL.utf8 looks so mangled * they prefer en_US.utf8 instead. */ const char *msg_locale = setlocale(LC_MESSAGES, NULL); if (msg_locale && strcmp(msg_locale, "he_IL.utf8") == 0) setlocale(LC_MESSAGES, "en_US.utf8"); #if ENABLE_NLS bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); #endif #define PROGRAM_USAGE_MIDDLE_PART \ "\n" \ "Get or modify a value of the auto-reporting option. The changes will take\n" \ "effect immediately and will be persistent.\n" \ "\n" \ ""STATE_MANUAL":\n" \ "User have to report the detect problems manually\n" \ "\n" \ ""STATE_AUTO":\n" \ "ABRT uploads an uReport which was generated for a detected problem\n" \ "immediately after the detection phase. uReport generally contains a stack\n" \ "trace which only describes the call stack of the program at the time of the\n" \ "crash and does not contain contents of any variables. Every uReport also\n" \ "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" abrt_init(argv); #if AUTHENTICATED_AUTOREPORTING != 0 const char *program_usage_string = _( "& [ "STATE_MANUAL" | "STATE_AUTO" | yes | no | 1 | 0 ] \\\n" " [[--anonymous] | [--username USERNAME [--password PASSWORD]] | [--certificate SOURCE]]\n" PROGRAM_USAGE_MIDDLE_PART "See abrt-auto-reporting(1), reporter-ureport(1) and reporter-rhtsupport(1)\n" "for more details.\n" ); #else const char *program_usage_string = _( "& [ "STATE_MANUAL" | "STATE_AUTO" | yes | no | 1 | 0 ]\n" PROGRAM_USAGE_MIDDLE_PART "See abrt-auto-reporting(1) and reporter-ureport(1) for more details.\n" ); #endif enum { OPT_v = 1 << 0, #if AUTHENTICATED_AUTOREPORTING != 0 OPT_a = 1 << 1, OPT_u = 1 << 2, OPT_p = 1 << 3, OPT_c = 1 << 4, #endif }; #if AUTHENTICATED_AUTOREPORTING != 0 int anonymous = 0; const char *username = NULL; const char *password = NULL; const char *certificate = NULL; #endif /* Keep enum above and order of options below in sync! */ struct options program_options[] = { OPT__VERBOSE(&g_verbose), #if AUTHENTICATED_AUTOREPORTING != 0 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")), #endif OPT_END() }; #if AUTHENTICATED_AUTOREPORTING != 0 const unsigned opts = #endif parse_opts(argc, argv, program_options, program_usage_string); argv += optind; argc -= optind; #if AUTHENTICATED_AUTOREPORTING != 0 if ((opts & OPT_p) && !(opts & OPT_u)) { error_msg(_("You also need to specify --username for --password")); show_usage_and_die(program_usage_string, program_options); } 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); } 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); } #endif if (argc > 1) { error_msg(_("Invalid number of arguments")); show_usage_and_die(program_usage_string, program_options); } const char *opt_value = NULL; if (argc == 1) { 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) { opt_value = REPORTING_STATES[i][1]; break; } } if (opt_value == NULL) { 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(); #if AUTHENTICATED_AUTOREPORTING != 0 map_string_t *rhts_conf = new_map_string(); map_string_t *rhts_conf_bck = NULL; #endif 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; #if AUTHENTICATED_AUTOREPORTING != 0 if (!load_plugin_conf_file(RHTS_NAME, rhts_conf, false)) goto finito; #endif if (!load_plugin_conf_file(UREPORT_NAME, ureport_conf, false)) goto finito; #if AUTHENTICATED_AUTOREPORTING != 0 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; } #endif if (argc == 0) { printf("%s", get_abrt_reporting(conf)); exit_code = EXIT_SUCCESS; #if AUTHENTICATED_AUTOREPORTING != 0 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")); } #endif 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 AUTHENTICATED_AUTOREPORTING != 0 if (rhts_conf_bck != NULL) save_plugin_conf_file(RHTS_NAME, rhts_conf_bck); #endif } finito: free_map_string(ureport_conf); free_map_string(ureport_conf_bck); #if AUTHENTICATED_AUTOREPORTING != 0 free_map_string(rhts_conf); free_map_string(rhts_conf_bck); #endif free_map_string(conf); return exit_code; }