Blame src/daemon/abrt-auto-reporting.c

Packit 8ea169
/*
Packit 8ea169
    Copyright (C) 2014  RedHat inc.
Packit 8ea169
Packit 8ea169
    This program is free software; you can redistribute it and/or modify
Packit 8ea169
    it under the terms of the GNU General Public License as published by
Packit 8ea169
    the Free Software Foundation; either version 2 of the License, or
Packit 8ea169
    (at your option) any later version.
Packit 8ea169
Packit 8ea169
    This program is distributed in the hope that it will be useful,
Packit 8ea169
    but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 8ea169
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 8ea169
    GNU General Public License for more details.
Packit 8ea169
Packit 8ea169
    You should have received a copy of the GNU General Public License along
Packit 8ea169
    with this program; if not, write to the Free Software Foundation, Inc.,
Packit 8ea169
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Packit 8ea169
*/
Packit 8ea169
Packit 8ea169
#include "libabrt.h"
Packit 8ea169
#include "client.h"
Packit 8ea169
Packit 8ea169
#include <stdio.h>
Packit 8ea169
Packit 8ea169
#define CONF_NAME "abrt.conf"
Packit 8ea169
#define OPTION_NAME "AutoreportingEnabled"
Packit 8ea169
Packit 8ea169
#define STATE_MANUAL "disabled"
Packit 8ea169
#define STATE_AUTO "enabled"
Packit 8ea169
Packit 8ea169
#define RHTS_NAME "rhtsupport.conf"
Packit 8ea169
#define RHTS_USERNAME_OPTION "Login"
Packit 8ea169
#define RHTS_PASSWORD_OPTION "Password"
Packit 8ea169
Packit 8ea169
#define UREPORT_NAME "ureport.conf"
Packit 8ea169
#define UREPORT_HTTP_AUTH_OPTION "HTTPAuth"
Packit 8ea169
#define UREPORT_CLIENT_AUTH_OPTION "SSLClientAuth"
Packit 8ea169
#define UREPORT_RTHS_CREDENTIALS_AUTH "rhts-credentials"
Packit 8ea169
Packit 8ea169
const char *const REPORTING_STATES[8][2] = {
Packit 8ea169
    {STATE_MANUAL, "no" },
Packit 8ea169
    {STATE_AUTO,   "yes"},
Packit 8ea169
    {"no",         "no" },
Packit 8ea169
    {"yes",        "yes"},
Packit 8ea169
    {"0",          "no" },
Packit 8ea169
    {"1",          "yes"},
Packit 8ea169
    {"off",        "no" },
Packit 8ea169
    {"on",         "yes"},
Packit 8ea169
};
Packit 8ea169
Packit 8ea169
static int
Packit 8ea169
set_abrt_reporting(map_string_t *conf, const char *opt_value)
Packit 8ea169
{
Packit 8ea169
    const char *const def_value = REPORTING_STATES[0][1];
Packit 8ea169
    const char *const cur_value = get_map_string_item_or_NULL(conf, OPTION_NAME);
Packit 8ea169
Packit 8ea169
    if (  (cur_value == NULL && strcmp(def_value, opt_value) != 0)
Packit 8ea169
       || (cur_value != NULL && strcmp(cur_value, opt_value) != 0))
Packit 8ea169
    {
Packit 8ea169
        replace_map_string_item(conf, xstrdup(OPTION_NAME), xstrdup(opt_value));
Packit 8ea169
        return save_abrt_conf_file(CONF_NAME, conf);
Packit 8ea169
    }
Packit 8ea169
Packit 8ea169
    /* No changes needed -> success */
Packit 8ea169
    return 1;
Packit 8ea169
}
Packit 8ea169
Packit 8ea169
#if AUTHENTICATED_AUTOREPORTING != 0
Packit 8ea169
static int
Packit 8ea169
set_ureport_http_auth(map_string_t *conf, const char *opt_value)
Packit 8ea169
{
Packit 8ea169
    const char *const cur_value = get_map_string_item_or_NULL(conf, UREPORT_HTTP_AUTH_OPTION);
Packit 8ea169
Packit 8ea169
    if (cur_value == NULL || strcmp(cur_value, opt_value) != 0)
Packit 8ea169
    {
Packit 8ea169
        replace_map_string_item(conf, xstrdup(UREPORT_HTTP_AUTH_OPTION), xstrdup(opt_value));
Packit 8ea169
        remove_map_string_item(conf, UREPORT_CLIENT_AUTH_OPTION);
Packit 8ea169
Packit 8ea169
        return save_plugin_conf_file(UREPORT_NAME, conf);
Packit 8ea169
    }
Packit 8ea169
Packit 8ea169
    /* No changes needed -> success */
Packit 8ea169
    return 1;
Packit 8ea169
}
Packit 8ea169
Packit 8ea169
static int
Packit 8ea169
set_ureport_client_auth(map_string_t *conf, const char *opt_value)
Packit 8ea169
{
Packit 8ea169
    const char *const cur_value = get_map_string_item_or_NULL(conf, UREPORT_CLIENT_AUTH_OPTION);
Packit 8ea169
Packit 8ea169
    if (cur_value == NULL || strcmp(cur_value, opt_value) != 0)
Packit 8ea169
    {
Packit 8ea169
        replace_map_string_item(conf, xstrdup(UREPORT_CLIENT_AUTH_OPTION), xstrdup(opt_value));
Packit 8ea169
        remove_map_string_item(conf, UREPORT_HTTP_AUTH_OPTION);
Packit 8ea169
Packit 8ea169
        return save_plugin_conf_file(UREPORT_NAME, conf);
Packit 8ea169
    }
Packit 8ea169
Packit 8ea169
    /* No changes needed -> success */
Packit 8ea169
    return 1;
Packit 8ea169
}
Packit 8ea169
Packit 8ea169
static int
Packit 8ea169
clear_ureport_auth(map_string_t *conf)
Packit 8ea169
{
Packit 8ea169
    const char *const http_cur_value = get_map_string_item_or_NULL(conf, UREPORT_HTTP_AUTH_OPTION);
Packit 8ea169
    const char *const ssl_cur_value = get_map_string_item_or_NULL(conf, UREPORT_CLIENT_AUTH_OPTION);
Packit 8ea169
Packit 8ea169
    if (http_cur_value != NULL || ssl_cur_value != NULL)
Packit 8ea169
    {
Packit 8ea169
        remove_map_string_item(conf, UREPORT_HTTP_AUTH_OPTION);
Packit 8ea169
        remove_map_string_item(conf, UREPORT_CLIENT_AUTH_OPTION);
Packit 8ea169
Packit 8ea169
        return save_plugin_conf_file(UREPORT_NAME, conf);
Packit 8ea169
    }
Packit 8ea169
Packit 8ea169
    /* No changes needed -> success */
Packit 8ea169
    return 1;
Packit 8ea169
}
Packit 8ea169
Packit 8ea169
static int
Packit 8ea169
set_rhts_credentials(map_string_t *conf, const char *username, const char *password)
Packit 8ea169
{
Packit 8ea169
    const char *const username_cur_value = get_map_string_item_or_NULL(conf, RHTS_USERNAME_OPTION);
Packit 8ea169
    const char *const password_cur_value = get_map_string_item_or_NULL(conf, RHTS_PASSWORD_OPTION);
Packit 8ea169
Packit 8ea169
    if (  (username_cur_value == NULL || strcmp(username_cur_value, username) != 0)
Packit 8ea169
       || (password_cur_value == NULL || strcmp(password_cur_value, password) != 0))
Packit 8ea169
    {
Packit 8ea169
        replace_map_string_item(conf, xstrdup(RHTS_USERNAME_OPTION), xstrdup(username));
Packit 8ea169
        replace_map_string_item(conf, xstrdup(RHTS_PASSWORD_OPTION), xstrdup(password));
Packit 8ea169
Packit 8ea169
        return save_plugin_conf_file(RHTS_NAME, conf);
Packit 8ea169
    }
Packit 8ea169
Packit 8ea169
    /* No changes needed -> success */
Packit 8ea169
    return 1;
Packit 8ea169
}
Packit 8ea169
#endif
Packit 8ea169
Packit 8ea169
static const char *
Packit 8ea169
get_abrt_reporting(map_string_t *conf)
Packit 8ea169
{
Packit 8ea169
    const char *const cur_value = get_map_string_item_or_empty(conf, OPTION_NAME);
Packit 8ea169
    const int index = !!string_to_bool(cur_value);
Packit 8ea169
    return REPORTING_STATES[index][0];
Packit 8ea169
}
Packit 8ea169
Packit 8ea169
#if AUTHENTICATED_AUTOREPORTING != 0
Packit 8ea169
static const char *
Packit 8ea169
get_ureport_http_auth(map_string_t *conf)
Packit 8ea169
{
Packit 8ea169
    return get_map_string_item_or_NULL(conf, UREPORT_HTTP_AUTH_OPTION);
Packit 8ea169
}
Packit 8ea169
Packit 8ea169
static const char *
Packit 8ea169
get_ureport_client_auth(map_string_t *conf)
Packit 8ea169
{
Packit 8ea169
    return get_map_string_item_or_NULL(conf, UREPORT_CLIENT_AUTH_OPTION);
Packit 8ea169
}
Packit 8ea169
#endif
Packit 8ea169
Packit 8ea169
int main(int argc, char *argv[])
Packit 8ea169
{
Packit 8ea169
    setlocale(LC_ALL, "");
Packit 8ea169
    /* Hack:
Packit 8ea169
     * Right-to-left scripts don't work properly in many terminals.
Packit 8ea169
     * Hebrew speaking people say he_IL.utf8 looks so mangled
Packit 8ea169
     * they prefer en_US.utf8 instead.
Packit 8ea169
     */
Packit 8ea169
    const char *msg_locale = setlocale(LC_MESSAGES, NULL);
Packit 8ea169
    if (msg_locale && strcmp(msg_locale, "he_IL.utf8") == 0)
Packit 8ea169
        setlocale(LC_MESSAGES, "en_US.utf8");
Packit 8ea169
#if ENABLE_NLS
Packit 8ea169
    bindtextdomain(PACKAGE, LOCALEDIR);
Packit 8ea169
    textdomain(PACKAGE);
Packit 8ea169
#endif
Packit 8ea169
Packit 8ea169
#define PROGRAM_USAGE_MIDDLE_PART \
Packit 8ea169
            "\n" \
Packit 8ea169
            "Get or modify a value of the auto-reporting option. The changes will take\n" \
Packit 8ea169
            "effect immediately and will be persistent.\n" \
Packit 8ea169
            "\n" \
Packit 8ea169
            ""STATE_MANUAL":\n" \
Packit 8ea169
            "User have to report the detect problems manually\n" \
Packit 8ea169
            "\n" \
Packit 8ea169
            ""STATE_AUTO":\n" \
Packit 8ea169
            "ABRT uploads an uReport which was generated for a detected problem\n" \
Packit 8ea169
            "immediately after the detection phase. uReport generally contains a stack\n" \
Packit 8ea169
            "trace which only describes the call stack of the program at the time of the\n" \
Packit 8ea169
            "crash and does not contain contents of any variables.  Every uReport also\n" \
Packit 8ea169
            "contains identification of the operating system, versions of the RPM packages\n" \
Packit 8ea169
            "involved in the crash, and whether the program ran under a root user.\n" \
Packit 8ea169
            "\n"
Packit 8ea169
Packit 8ea169
    abrt_init(argv);
Packit 8ea169
#if AUTHENTICATED_AUTOREPORTING != 0
Packit 8ea169
    const char *program_usage_string = _(
Packit 8ea169
            "& [ "STATE_MANUAL" | "STATE_AUTO" | yes | no | 1 | 0 ] \\\n"
Packit 8ea169
            "  [[--anonymous] | [--username USERNAME [--password PASSWORD]] | [--certificate SOURCE]]\n"
Packit 8ea169
            PROGRAM_USAGE_MIDDLE_PART
Packit 8ea169
            "See abrt-auto-reporting(1), reporter-ureport(1) and reporter-rhtsupport(1)\n"
Packit 8ea169
            "for more details.\n"
Packit 8ea169
    );
Packit 8ea169
#else
Packit 8ea169
    const char *program_usage_string = _(
Packit 8ea169
            "& [ "STATE_MANUAL" | "STATE_AUTO" | yes | no | 1 | 0 ]\n"
Packit 8ea169
            PROGRAM_USAGE_MIDDLE_PART
Packit 8ea169
            "See abrt-auto-reporting(1) and reporter-ureport(1) for more details.\n"
Packit 8ea169
    );
Packit 8ea169
#endif
Packit 8ea169
Packit 8ea169
    enum {
Packit 8ea169
        OPT_v = 1 << 0,
Packit 8ea169
#if AUTHENTICATED_AUTOREPORTING != 0
Packit 8ea169
        OPT_a = 1 << 1,
Packit 8ea169
        OPT_u = 1 << 2,
Packit 8ea169
        OPT_p = 1 << 3,
Packit 8ea169
        OPT_c = 1 << 4,
Packit 8ea169
#endif
Packit 8ea169
    };
Packit 8ea169
Packit 8ea169
#if AUTHENTICATED_AUTOREPORTING != 0
Packit 8ea169
    int anonymous = 0;
Packit 8ea169
    const char *username = NULL;
Packit 8ea169
    const char *password = NULL;
Packit 8ea169
    const char *certificate = NULL;
Packit 8ea169
#endif
Packit 8ea169
Packit 8ea169
    /* Keep enum above and order of options below in sync! */
Packit 8ea169
    struct options program_options[] = {
Packit 8ea169
        OPT__VERBOSE(&g_verbose),
Packit 8ea169
#if AUTHENTICATED_AUTOREPORTING != 0
Packit 8ea169
        OPT_BOOL  (  'a', "anonymous",   &anonymous,               _("Turns the authentication off")),
Packit 8ea169
        OPT_STRING(  'u', "username",    &username,    "USERNAME", _("Red Hat Support user name")),
Packit 8ea169
        OPT_STRING(  'p', "password",    &password,    "PASSWORD", _("Red Hat Support password, if not given, a prompt for it will be issued")),
Packit 8ea169
        OPT_STRING(  'c', "certificate", &certificate, "SOURCE",   _("uReport SSL certificate paths or certificate type")),
Packit 8ea169
#endif
Packit 8ea169
        OPT_END()
Packit 8ea169
    };
Packit 8ea169
Packit 8ea169
#if AUTHENTICATED_AUTOREPORTING != 0
Packit 8ea169
    const unsigned opts =
Packit 8ea169
#endif
Packit 8ea169
    parse_opts(argc, argv, program_options, program_usage_string);
Packit 8ea169
Packit 8ea169
    argv += optind;
Packit 8ea169
    argc -= optind;
Packit 8ea169
Packit 8ea169
#if AUTHENTICATED_AUTOREPORTING != 0
Packit 8ea169
    if ((opts & OPT_p) && !(opts & OPT_u))
Packit 8ea169
    {
Packit 8ea169
        error_msg(_("You also need to specify --username for --password"));
Packit 8ea169
        show_usage_and_die(program_usage_string, program_options);
Packit 8ea169
    }
Packit 8ea169
Packit 8ea169
    if ((opts & OPT_u) && (opts & OPT_c))
Packit 8ea169
    {
Packit 8ea169
        error_msg(_("You can use either --username or --certificate"));
Packit 8ea169
        show_usage_and_die(program_usage_string, program_options);
Packit 8ea169
    }
Packit 8ea169
Packit 8ea169
    if ((opts & OPT_u) && (opts & OPT_a))
Packit 8ea169
    {
Packit 8ea169
        error_msg(_("You can use either --username or --anonymous"));
Packit 8ea169
        show_usage_and_die(program_usage_string, program_options);
Packit 8ea169
    }
Packit 8ea169
Packit 8ea169
    if ((opts & OPT_a) && (opts & OPT_c))
Packit 8ea169
    {
Packit 8ea169
        error_msg(_("You can use either --anonymous or --certificate"));
Packit 8ea169
        show_usage_and_die(program_usage_string, program_options);
Packit 8ea169
    }
Packit 8ea169
Packit 8ea169
#endif
Packit 8ea169
    if (argc > 1)
Packit 8ea169
    {
Packit 8ea169
        error_msg(_("Invalid number of arguments"));
Packit 8ea169
        show_usage_and_die(program_usage_string, program_options);
Packit 8ea169
    }
Packit 8ea169
Packit 8ea169
    const char *opt_value = NULL;
Packit 8ea169
    if (argc == 1)
Packit 8ea169
    {
Packit 8ea169
        const char *const new_value = argv[0];
Packit 8ea169
        for (int i = 0; i < sizeof(REPORTING_STATES)/sizeof(REPORTING_STATES[0]); ++i)
Packit 8ea169
        {
Packit 8ea169
            if (strcasecmp(new_value, REPORTING_STATES[i][0]) == 0)
Packit 8ea169
            {
Packit 8ea169
                opt_value = REPORTING_STATES[i][1];
Packit 8ea169
                break;
Packit 8ea169
            }
Packit 8ea169
        }
Packit 8ea169
Packit 8ea169
        if (opt_value == NULL)
Packit 8ea169
        {
Packit 8ea169
            error_msg(_("Unknown option value: '%s'\n"), new_value);
Packit 8ea169
            show_usage_and_die(program_usage_string, program_options);
Packit 8ea169
        }
Packit 8ea169
    }
Packit 8ea169
Packit 8ea169
    int exit_code = EXIT_FAILURE;
Packit 8ea169
Packit 8ea169
    map_string_t *conf = new_map_string();
Packit 8ea169
#if AUTHENTICATED_AUTOREPORTING != 0
Packit 8ea169
    map_string_t *rhts_conf = new_map_string();
Packit 8ea169
    map_string_t *rhts_conf_bck = NULL;
Packit 8ea169
#endif
Packit 8ea169
    map_string_t *ureport_conf = new_map_string();
Packit 8ea169
    map_string_t *ureport_conf_bck = NULL;
Packit 8ea169
Packit 8ea169
    if (!load_abrt_conf_file(CONF_NAME, conf))
Packit 8ea169
        goto finito;
Packit 8ea169
Packit 8ea169
#if AUTHENTICATED_AUTOREPORTING != 0
Packit 8ea169
    if (!load_plugin_conf_file(RHTS_NAME, rhts_conf, false))
Packit 8ea169
        goto finito;
Packit 8ea169
#endif
Packit 8ea169
Packit 8ea169
    if (!load_plugin_conf_file(UREPORT_NAME, ureport_conf, false))
Packit 8ea169
        goto finito;
Packit 8ea169
Packit 8ea169
#if AUTHENTICATED_AUTOREPORTING != 0
Packit 8ea169
    if ((opts & OPT_a))
Packit 8ea169
    {
Packit 8ea169
        ureport_conf_bck = clone_map_string(ureport_conf);
Packit 8ea169
Packit 8ea169
        if (!clear_ureport_auth(ureport_conf))
Packit 8ea169
            goto finito;
Packit 8ea169
    }
Packit 8ea169
Packit 8ea169
    if ((opts & OPT_u))
Packit 8ea169
    {
Packit 8ea169
        char *tmp_password = NULL;
Packit 8ea169
        if (!(opts & OPT_p))
Packit 8ea169
        {
Packit 8ea169
            password = tmp_password = ask_password(_("Password:"));
Packit 8ea169
            if (tmp_password == NULL)
Packit 8ea169
            {
Packit 8ea169
                error_msg(_("Cannot continue without password\n"));
Packit 8ea169
                goto finito;
Packit 8ea169
            }
Packit 8ea169
        }
Packit 8ea169
Packit 8ea169
        ureport_conf_bck = clone_map_string(ureport_conf);
Packit 8ea169
Packit 8ea169
        if (!set_ureport_http_auth(ureport_conf, UREPORT_RTHS_CREDENTIALS_AUTH))
Packit 8ea169
            goto finito;
Packit 8ea169
Packit 8ea169
        rhts_conf_bck = clone_map_string(rhts_conf);
Packit 8ea169
Packit 8ea169
        if (!set_rhts_credentials(rhts_conf, username, password))
Packit 8ea169
        {
Packit 8ea169
            save_plugin_conf_file(UREPORT_NAME, ureport_conf_bck);
Packit 8ea169
            goto finito;
Packit 8ea169
        }
Packit 8ea169
Packit 8ea169
        free(tmp_password);
Packit 8ea169
    }
Packit 8ea169
Packit 8ea169
    if ((opts & OPT_c))
Packit 8ea169
    {
Packit 8ea169
        ureport_conf_bck = clone_map_string(ureport_conf);
Packit 8ea169
Packit 8ea169
        if (!set_ureport_client_auth(ureport_conf, certificate))
Packit 8ea169
            goto finito;
Packit 8ea169
    }
Packit 8ea169
Packit 8ea169
#endif
Packit 8ea169
    if (argc == 0)
Packit 8ea169
    {
Packit 8ea169
        printf("%s", get_abrt_reporting(conf));
Packit 8ea169
        exit_code = EXIT_SUCCESS;
Packit 8ea169
Packit 8ea169
#if AUTHENTICATED_AUTOREPORTING != 0
Packit 8ea169
        if (g_verbose >= 1)
Packit 8ea169
        {
Packit 8ea169
            const char *tmp = get_ureport_http_auth(ureport_conf);
Packit 8ea169
            if (tmp != NULL)
Packit 8ea169
                /* Print only the part before ':' of a string like "username:password" */
Packit 8ea169
                printf(" %s (%*s)", _("HTTP Authenticated auto reporting"), (int)(strchrnul(tmp, ':') - tmp), tmp);
Packit 8ea169
            else if ((tmp = get_ureport_client_auth(ureport_conf)) != NULL)
Packit 8ea169
                printf(" %s (%s)", _("SSL Client Authenticated auto reporting"), tmp);
Packit 8ea169
            else
Packit 8ea169
                printf(" %s", _("anonymous auto reporting"));
Packit 8ea169
        }
Packit 8ea169
#endif
Packit 8ea169
        putchar('\n');
Packit 8ea169
Packit 8ea169
        goto finito;
Packit 8ea169
    }
Packit 8ea169
Packit 8ea169
    exit_code = set_abrt_reporting(conf, opt_value) ? EXIT_SUCCESS : EXIT_FAILURE;
Packit 8ea169
Packit 8ea169
    if (exit_code == EXIT_FAILURE)
Packit 8ea169
    {
Packit 8ea169
        if (ureport_conf_bck != NULL)
Packit 8ea169
            save_plugin_conf_file(UREPORT_NAME, ureport_conf_bck);
Packit 8ea169
Packit 8ea169
#if AUTHENTICATED_AUTOREPORTING != 0
Packit 8ea169
        if (rhts_conf_bck != NULL)
Packit 8ea169
            save_plugin_conf_file(RHTS_NAME, rhts_conf_bck);
Packit 8ea169
#endif
Packit 8ea169
    }
Packit 8ea169
Packit 8ea169
Packit 8ea169
finito:
Packit 8ea169
    free_map_string(ureport_conf);
Packit 8ea169
    free_map_string(ureport_conf_bck);
Packit 8ea169
#if AUTHENTICATED_AUTOREPORTING != 0
Packit 8ea169
    free_map_string(rhts_conf);
Packit 8ea169
    free_map_string(rhts_conf_bck);
Packit 8ea169
#endif
Packit 8ea169
    free_map_string(conf);
Packit 8ea169
    return exit_code;
Packit 8ea169
}