/*
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 <stdio.h>
#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;
}