Blame src/lib/ureport.c

Packit Service 779887
/*
Packit Service 779887
    Copyright (C) 2012,2014  ABRT team
Packit Service 779887
    Copyright (C) 2012,2014  RedHat Inc
Packit Service 779887
Packit Service 779887
    This program is free software; you can redistribute it and/or modify
Packit Service 779887
    it under the terms of the GNU General Public License as published by
Packit Service 779887
    the Free Software Foundation; either version 2 of the License, or
Packit Service 779887
    (at your option) any later version.
Packit Service 779887
Packit Service 779887
    This program is distributed in the hope that it will be useful,
Packit Service 779887
    but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 779887
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 779887
    GNU General Public License for more details.
Packit Service 779887
Packit Service 779887
    You should have received a copy of the GNU General Public License along
Packit Service 779887
    with this program; if not, write to the Free Software Foundation, Inc.,
Packit Service 779887
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Packit Service 779887
*/
Packit Service 779887
#include <json.h>
Packit Service 779887
Packit Service 779887
#include <satyr/abrt.h>
Packit Service 779887
#include <satyr/report.h>
Packit Service 779887
Packit Service 779887
#include "internal_libreport.h"
Packit Service 779887
#include "client.h"
Packit Service 779887
#include "ureport.h"
Packit Service 779887
#include "libreport_curl.h"
Packit Service 779887
Packit Service 779887
#define DESTROYED_POINTER (void *)0xdeadbeef
Packit Service 779887
Packit Service 779887
#define BTHASH_URL_SFX "reports/bthash/"
Packit Service 779887
Packit Service 779887
static char *
Packit Service 779887
puppet_config_print(const char *key)
Packit Service 779887
{
Packit Service 779887
    char *command = xasprintf("puppet config print %s", key);
Packit Service 779887
    char *result = run_in_shell_and_save_output(0, command, NULL, NULL);
Packit Service 779887
    free(command);
Packit Service 779887
Packit Service 779887
    /* run_in_shell_and_save_output always returns non-NULL */
Packit Service 779887
    if (result[0] != '/')
Packit Service 779887
        goto error;
Packit Service 779887
Packit Service 779887
    char *newline = strchrnul(result, '\n');
Packit Service 779887
    if (!newline)
Packit Service 779887
        goto error;
Packit Service 779887
Packit Service 779887
    *newline = '\0';
Packit Service 779887
    return result;
Packit Service 779887
error:
Packit Service 779887
    free(result);
Packit Service 779887
    error_msg_and_die("Unable to determine puppet %s path (puppet not installed?)", key);
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
void
Packit Service 779887
ureport_server_config_set_url(struct ureport_server_config *config,
Packit Service 779887
                              char *server_url)
Packit Service 779887
{
Packit Service 779887
    free(config->ur_url);
Packit Service 779887
    config->ur_url = server_url;
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
void
Packit Service 779887
ureport_server_config_set_client_auth(struct ureport_server_config *config,
Packit Service 779887
                                      const char *client_auth)
Packit Service 779887
{
Packit Service 779887
    if (client_auth == NULL)
Packit Service 779887
        return;
Packit Service 779887
Packit Service 779887
    if (strcmp(client_auth, "") == 0)
Packit Service 779887
    {
Packit Service 779887
        free(config->ur_client_cert);
Packit Service 779887
        config->ur_client_cert = NULL;
Packit Service 779887
Packit Service 779887
        free(config->ur_client_key);
Packit Service 779887
        config->ur_client_key = NULL;
Packit Service 779887
Packit Service 779887
        log_notice("Not using client authentication");
Packit Service 779887
    }
Packit Service 779887
    else if (strcmp(client_auth, "puppet") == 0)
Packit Service 779887
    {
Packit Service 779887
        config->ur_client_cert = puppet_config_print("hostcert");
Packit Service 779887
        config->ur_client_key = puppet_config_print("hostprivkey");
Packit Service 779887
    }
Packit Service 779887
    else
Packit Service 779887
    {
Packit Service 779887
        char *scratch = xstrdup(client_auth);
Packit Service 779887
        config->ur_client_cert = xstrdup(strtok(scratch, ":"));
Packit Service 779887
        config->ur_client_key = xstrdup(strtok(NULL, ":"));
Packit Service 779887
        free(scratch);
Packit Service 779887
Packit Service 779887
        if (config->ur_client_cert == NULL || config->ur_client_key == NULL)
Packit Service 779887
            error_msg_and_die("Invalid client authentication specification");
Packit Service 779887
    }
Packit Service 779887
Packit Service 779887
    if (config->ur_client_cert && config->ur_client_key)
Packit Service 779887
    {
Packit Service 779887
        log_notice("Using client certificate: %s", config->ur_client_cert);
Packit Service 779887
        log_notice("Using client private key: %s", config->ur_client_key);
Packit Service 779887
Packit Service 779887
        free(config->ur_username);
Packit Service 779887
        config->ur_username = NULL;
Packit Service 779887
Packit Service 779887
        free(config->ur_password);
Packit Service 779887
        config->ur_password = NULL;
Packit Service 779887
    }
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
void
Packit Service 779887
ureport_server_config_set_basic_auth(struct ureport_server_config *config,
Packit Service 779887
                                     const char *login, const char *password)
Packit Service 779887
{
Packit Service 779887
    ureport_server_config_set_client_auth(config, "");
Packit Service 779887
Packit Service 779887
    free(config->ur_username);
Packit Service 779887
    config->ur_username = xstrdup(login);
Packit Service 779887
Packit Service 779887
    free(config->ur_password);
Packit Service 779887
    config->ur_password = xstrdup(password);
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
void
Packit Service 779887
ureport_server_config_load_basic_auth(struct ureport_server_config *config,
Packit Service 779887
                                      const char *http_auth_pref)
Packit Service 779887
{
Packit Service 779887
    if (http_auth_pref == NULL)
Packit Service 779887
        return;
Packit Service 779887
Packit Service 779887
    map_string_t *settings = NULL;
Packit Service 779887
Packit Service 779887
    char *tmp_password = NULL;
Packit Service 779887
    char *tmp_username = NULL;
Packit Service 779887
    const char *username = NULL;
Packit Service 779887
    const char *password = NULL;
Packit Service 779887
Packit Service 779887
    username = tmp_username = xstrdup(http_auth_pref);
Packit Service 779887
    password = strchr(tmp_username, ':');
Packit Service 779887
Packit Service 779887
    if (password != NULL)
Packit Service 779887
        /* It is "char *", see strchr() few lines above. */
Packit Service 779887
        *((char *)(password++)) = '\0';
Packit Service 779887
Packit Service 779887
    if (password == NULL)
Packit Service 779887
    {
Packit Service 779887
        char *message = xasprintf("Please provide uReport server password for user '%s':", username);
Packit Service 779887
        password = tmp_password = ask_password(message);
Packit Service 779887
        free(message);
Packit Service 779887
Packit Service 779887
        if (strcmp(password, "") == 0)
Packit Service 779887
            error_msg_and_die("Cannot continue without uReport server password!");
Packit Service 779887
    }
Packit Service 779887
Packit Service 779887
    ureport_server_config_set_basic_auth(config, username, password);
Packit Service 779887
Packit Service 779887
    free(tmp_password);
Packit Service 779887
    free(tmp_username);
Packit Service 779887
    free_map_string(settings);
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
void
Packit Service 779887
ureport_server_config_load(struct ureport_server_config *config,
Packit Service 779887
                           map_string_t *settings)
Packit Service 779887
{
Packit Service 779887
    UREPORT_OPTION_VALUE_FROM_CONF(settings, "URL", config->ur_url, xstrdup);
Packit Service 779887
    UREPORT_OPTION_VALUE_FROM_CONF(settings, "SSLVerify", config->ur_ssl_verify, string_to_bool);
Packit Service 779887
Packit Service 779887
    const char *http_auth_pref = NULL;
Packit Service 779887
    UREPORT_OPTION_VALUE_FROM_CONF(settings, "HTTPAuth", http_auth_pref, (const char *));
Packit Service 779887
    ureport_server_config_load_basic_auth(config, http_auth_pref);
Packit Service 779887
Packit Service 779887
    const char *client_auth = NULL;
Packit Service 779887
    if (http_auth_pref == NULL)
Packit Service 779887
    {
Packit Service 779887
        UREPORT_OPTION_VALUE_FROM_CONF(settings, "SSLClientAuth", client_auth, (const char *));
Packit Service 779887
        ureport_server_config_set_client_auth(config, client_auth);
Packit Service 779887
    }
Packit Service 779887
Packit Service 779887
    /* If SSLClientAuth is configured, include the auth items by default. */
Packit Service 779887
    bool include_auth = config->ur_client_cert != NULL || config->ur_username != NULL;
Packit Service 779887
    UREPORT_OPTION_VALUE_FROM_CONF(settings, "IncludeAuthData", include_auth, string_to_bool);
Packit Service 779887
Packit Service 779887
    if (include_auth)
Packit Service 779887
    {
Packit Service 779887
        const char *auth_items = NULL;
Packit Service 779887
        UREPORT_OPTION_VALUE_FROM_CONF(settings, "AuthDataItems", auth_items, (const char *));
Packit Service 779887
        config->ur_prefs.urp_auth_items = parse_list(auth_items);
Packit Service 779887
Packit Service 779887
        if (config->ur_prefs.urp_auth_items == NULL)
Packit Service 779887
            log_warning("IncludeAuthData set to 'yes' but AuthDataItems is empty.");
Packit Service 779887
    }
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
void
Packit Service 779887
ureport_server_config_init(struct ureport_server_config *config)
Packit Service 779887
{
Packit Service 779887
    config->ur_url = NULL;
Packit Service 779887
    config->ur_ssl_verify = true;
Packit Service 779887
    config->ur_client_cert = NULL;
Packit Service 779887
    config->ur_client_key = NULL;
Packit Service 779887
    config->ur_cert_authority_cert = NULL;
Packit Service 779887
    config->ur_username = NULL;
Packit Service 779887
    config->ur_password = NULL;
Packit Service 779887
    config->ur_http_headers = new_map_string();
Packit Service 779887
Packit Service 779887
    config->ur_prefs.urp_auth_items = NULL;
Packit Service 779887
    config->ur_prefs.urp_flags = 0;
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
void
Packit Service 779887
ureport_server_config_destroy(struct ureport_server_config *config)
Packit Service 779887
{
Packit Service 779887
    free(config->ur_url);
Packit Service 779887
    config->ur_url = DESTROYED_POINTER;
Packit Service 779887
Packit Service 779887
    free(config->ur_client_cert);
Packit Service 779887
    config->ur_client_cert = DESTROYED_POINTER;
Packit Service 779887
Packit Service 779887
    free(config->ur_client_key);
Packit Service 779887
    config->ur_client_key = DESTROYED_POINTER;
Packit Service 779887
Packit Service 779887
    free(config->ur_cert_authority_cert);
Packit Service 779887
    config->ur_cert_authority_cert = DESTROYED_POINTER;
Packit Service 779887
Packit Service 779887
    free(config->ur_username);
Packit Service 779887
    config->ur_username = DESTROYED_POINTER;
Packit Service 779887
Packit Service 779887
    free(config->ur_password);
Packit Service 779887
    config->ur_password = DESTROYED_POINTER;
Packit Service 779887
Packit Service 779887
    g_list_free_full(config->ur_prefs.urp_auth_items, free);
Packit Service 779887
    config->ur_prefs.urp_auth_items = DESTROYED_POINTER;
Packit Service 779887
Packit Service 779887
    free_map_string(config->ur_http_headers);
Packit Service 779887
    config->ur_http_headers = DESTROYED_POINTER;
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
void
Packit Service 779887
ureport_server_response_free(struct ureport_server_response *resp)
Packit Service 779887
{
Packit Service 779887
    if (!resp)
Packit Service 779887
        return;
Packit Service 779887
Packit Service 779887
    free(resp->urr_solution);
Packit Service 779887
    resp->urr_solution = DESTROYED_POINTER;
Packit Service 779887
Packit Service 779887
    g_list_free_full(resp->urr_reported_to_list, g_free);
Packit Service 779887
    resp->urr_reported_to_list = DESTROYED_POINTER;
Packit Service 779887
Packit Service 779887
    free(resp->urr_bthash);
Packit Service 779887
    resp->urr_bthash = DESTROYED_POINTER;
Packit Service 779887
Packit Service 779887
    free(resp->urr_message);
Packit Service 779887
    resp->urr_message = DESTROYED_POINTER;
Packit Service 779887
Packit Service 779887
    free(resp->urr_value);
Packit Service 779887
    resp->urr_value = DESTROYED_POINTER;
Packit Service 779887
Packit Service 779887
    free(resp);
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
static char *
Packit Service 779887
parse_solution_from_json_list(struct json_object *list,
Packit Service 779887
                              GList **reported_to)
Packit Service 779887
{
Packit Service 779887
    json_object *list_elem, *struct_elem;
Packit Service 779887
    const char *cause, *note, *url;
Packit Service 779887
    struct strbuf *solution_buf = strbuf_new();
Packit Service 779887
Packit Service 779887
    const unsigned length = json_object_array_length(list);
Packit Service 779887
Packit Service 779887
    const char *one_format = _("Your problem seems to be caused by %s\n\n%s\n");
Packit Service 779887
    if (length > 1)
Packit Service 779887
    {
Packit Service 779887
        strbuf_append_str(solution_buf, _("Your problem seems to be caused by one of the following:\n"));
Packit Service 779887
        one_format = "\n* %s\n\n%s\n";
Packit Service 779887
    }
Packit Service 779887
Packit Service 779887
    bool empty = true;
Packit Service 779887
    for (unsigned i = 0; i < length; ++i)
Packit Service 779887
    {
Packit Service 779887
        list_elem = json_object_array_get_idx(list, i);
Packit Service 779887
        if (!list_elem)
Packit Service 779887
            continue;
Packit Service 779887
Packit Service 779887
        if (!json_object_object_get_ex(list_elem, "cause", &struct_elem))
Packit Service 779887
            continue;
Packit Service 779887
Packit Service 779887
        cause = json_object_get_string(struct_elem);
Packit Service 779887
        if (!cause)
Packit Service 779887
            continue;
Packit Service 779887
Packit Service 779887
        if (!json_object_object_get_ex(list_elem, "note", &struct_elem))
Packit Service 779887
            continue;
Packit Service 779887
Packit Service 779887
        note = json_object_get_string(struct_elem);
Packit Service 779887
        if (!note)
Packit Service 779887
            continue;
Packit Service 779887
Packit Service 779887
        empty = false;
Packit Service 779887
        strbuf_append_strf(solution_buf, one_format, cause, note);
Packit Service 779887
Packit Service 779887
        if (!json_object_object_get_ex(list_elem, "url", &struct_elem))
Packit Service 779887
            continue;
Packit Service 779887
Packit Service 779887
        url = json_object_get_string(struct_elem);
Packit Service 779887
        if (url)
Packit Service 779887
        {
Packit Service 779887
            char *reported_to_line = xasprintf("%s: URL=%s", cause, url);
Packit Service 779887
            *reported_to = g_list_append(*reported_to, reported_to_line);
Packit Service 779887
        }
Packit Service 779887
    }
Packit Service 779887
Packit Service 779887
    if (empty)
Packit Service 779887
    {
Packit Service 779887
        strbuf_free(solution_buf);
Packit Service 779887
        return NULL;
Packit Service 779887
    }
Packit Service 779887
Packit Service 779887
    return strbuf_free_nobuf(solution_buf);
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
/* reported_to json element should be a list of structures
Packit Service 779887
   {
Packit Service 779887
     "reporter": "Bugzilla",
Packit Service 779887
     "type": "url",
Packit Service 779887
     "value": "https://bugzilla.redhat.com/show_bug.cgi?id=XYZ"
Packit Service 779887
   }
Packit Service 779887
 */
Packit Service 779887
static GList *
Packit Service 779887
parse_reported_to_from_json_list(struct json_object *list)
Packit Service 779887
{
Packit Service 779887
    int i;
Packit Service 779887
    json_object *list_elem, *struct_elem;
Packit Service 779887
    const char *reporter, *value, *type;
Packit Service 779887
    char *reported_to_line, *prefix;
Packit Service 779887
    GList *result = NULL;
Packit Service 779887
Packit Service 779887
    for (i = 0; i < json_object_array_length(list); ++i)
Packit Service 779887
    {
Packit Service 779887
        prefix = NULL;
Packit Service 779887
        list_elem = json_object_array_get_idx(list, i);
Packit Service 779887
        if (!list_elem)
Packit Service 779887
            continue;
Packit Service 779887
Packit Service 779887
        if (!json_object_object_get_ex(list_elem, "reporter", &struct_elem))
Packit Service 779887
            continue;
Packit Service 779887
Packit Service 779887
        reporter = json_object_get_string(struct_elem);
Packit Service 779887
        if (!reporter)
Packit Service 779887
            continue;
Packit Service 779887
Packit Service 779887
        if (!json_object_object_get_ex(list_elem, "value", &struct_elem))
Packit Service 779887
            continue;
Packit Service 779887
Packit Service 779887
        value = json_object_get_string(struct_elem);
Packit Service 779887
        if (!value)
Packit Service 779887
            continue;
Packit Service 779887
Packit Service 779887
        if (!json_object_object_get_ex(list_elem, "type", &struct_elem))
Packit Service 779887
            continue;
Packit Service 779887
Packit Service 779887
        type = json_object_get_string(struct_elem);
Packit Service 779887
        if (type)
Packit Service 779887
        {
Packit Service 779887
            if (strcasecmp("url", type) == 0)
Packit Service 779887
                prefix = xstrdup("URL=");
Packit Service 779887
            else if (strcasecmp("bthash", type) == 0)
Packit Service 779887
                prefix = xstrdup("BTHASH=");
Packit Service 779887
        }
Packit Service 779887
Packit Service 779887
        if (!prefix)
Packit Service 779887
            prefix = xstrdup("");
Packit Service 779887
Packit Service 779887
        reported_to_line = xasprintf("%s: %s%s", reporter, prefix, value);
Packit Service 779887
        free(prefix);
Packit Service 779887
Packit Service 779887
        result = g_list_append(result, reported_to_line);
Packit Service 779887
    }
Packit Service 779887
Packit Service 779887
    return result;
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
/*
Packit Service 779887
 * Reponse samples:
Packit Service 779887
 * {"error":"field 'foo' is required"}
Packit Service 779887
 * {"response":"true"}
Packit Service 779887
 * {"response":"false"}
Packit Service 779887
 */
Packit Service 779887
static struct ureport_server_response *
Packit Service 779887
ureport_server_parse_json(json_object *json)
Packit Service 779887
{
Packit Service 779887
    json_object *obj = NULL;
Packit Service 779887
    if (json_object_object_get_ex(json, "error", &obj))
Packit Service 779887
    {
Packit Service 779887
        struct ureport_server_response *out_response = xzalloc(sizeof(*out_response));
Packit Service 779887
        out_response->urr_is_error = true;
Packit Service 779887
        /*
Packit Service 779887
         * Used to use json_object_to_json_string(obj), but it returns
Packit Service 779887
         * the string in quote marks (") - IOW, json-formatted string.
Packit Service 779887
         */
Packit Service 779887
        out_response->urr_value = xstrdup(json_object_get_string(obj));
Packit Service 779887
        return out_response;
Packit Service 779887
    }
Packit Service 779887
Packit Service 779887
    if (json_object_object_get_ex(json, "result", &obj))
Packit Service 779887
    {
Packit Service 779887
        struct ureport_server_response *out_response = xzalloc(sizeof(*out_response));
Packit Service 779887
        out_response->urr_value = xstrdup(json_object_get_string(obj));
Packit Service 779887
Packit Service 779887
        json_object *message = NULL;
Packit Service 779887
        if (json_object_object_get_ex(json, "message", &message))
Packit Service 779887
            out_response->urr_message = xstrdup(json_object_get_string(message));
Packit Service 779887
Packit Service 779887
        json_object *bthash = NULL;
Packit Service 779887
        if (json_object_object_get_ex(json, "bthash", &bthash))
Packit Service 779887
            out_response->urr_bthash = xstrdup(json_object_get_string(bthash));
Packit Service 779887
Packit Service 779887
        json_object *reported_to_list = NULL;
Packit Service 779887
        if (json_object_object_get_ex(json, "reported_to", &reported_to_list))
Packit Service 779887
            out_response->urr_reported_to_list =
Packit Service 779887
                parse_reported_to_from_json_list(reported_to_list);
Packit Service 779887
Packit Service 779887
        json_object *solutions = NULL;
Packit Service 779887
        if (json_object_object_get_ex(json, "solutions", &solutions))
Packit Service 779887
            out_response->urr_solution =
Packit Service 779887
                parse_solution_from_json_list(solutions, &(out_response->urr_reported_to_list));
Packit Service 779887
Packit Service 779887
        return out_response;
Packit Service 779887
    }
Packit Service 779887
Packit Service 779887
    return NULL;
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
struct ureport_server_response *
Packit Service 779887
ureport_server_response_from_reply(post_state_t *post_state,
Packit Service 779887
                                   struct ureport_server_config *config)
Packit Service 779887
{
Packit Service 779887
    /* Previously, the condition here was (post_state->errmsg[0] != '\0')
Packit Service 779887
     * however when the server asks for optional client authentication and we do not have the certificates,
Packit Service 779887
     * then post_state->errmsg contains "NSS: client certificate not found (nickname not specified)" even though
Packit Service 779887
     * the request succeeded.
Packit Service 779887
     */
Packit Service 779887
    if (post_state->curl_result != CURLE_OK)
Packit Service 779887
    {
Packit Service 779887
        if (strcmp(post_state->errmsg, "") != 0)
Packit Service 779887
            error_msg(_("Failed to upload uReport to the server '%s' with curl: %s"),
Packit Service 779887
                                                                    config->ur_url,
Packit Service 779887
                                                                    post_state->errmsg);
Packit Service 779887
        else
Packit Service 779887
            error_msg(_("Failed to upload uReport to the server '%s'"), config->ur_url);
Packit Service 779887
Packit Service 779887
        if (post_state->curl_error_msg != NULL && strcmp(post_state->curl_error_msg, "") != 0)
Packit Service 779887
            error_msg(_("Error: %s"), post_state->curl_error_msg);
Packit Service 779887
Packit Service 779887
        return NULL;
Packit Service 779887
    }
Packit Service 779887
Packit Service 779887
    if (post_state->http_resp_code == 404)
Packit Service 779887
    {
Packit Service 779887
        error_msg(_("The URL '%s' does not exist (got error 404 from server)"), config->ur_url);
Packit Service 779887
        return NULL;
Packit Service 779887
    }
Packit Service 779887
Packit Service 779887
    if (post_state->http_resp_code == 500)
Packit Service 779887
    {
Packit Service 779887
        error_msg(_("The server at '%s' encountered an internal error (got error 500)"), config->ur_url);
Packit Service 779887
        return NULL;
Packit Service 779887
    }
Packit Service 779887
Packit Service 779887
    if (post_state->http_resp_code == 503)
Packit Service 779887
    {
Packit Service 779887
        error_msg(_("The server at '%s' currently can't handle the request (got error 503)"), config->ur_url);
Packit Service 779887
        return NULL;
Packit Service 779887
    }
Packit Service 779887
Packit Service 779887
    if (post_state->http_resp_code != 202
Packit Service 779887
            && post_state->http_resp_code != 400
Packit Service 779887
            && post_state->http_resp_code != 413)
Packit Service 779887
    {
Packit Service 779887
        /* can't print better error message */
Packit Service 779887
        error_msg(_("Unexpected HTTP response from '%s': %d"), config->ur_url, post_state->http_resp_code);
Packit Service 779887
        log_notice("%s", post_state->body);
Packit Service 779887
        return NULL;
Packit Service 779887
    }
Packit Service 779887
Packit Service 779887
    json_object *const json = json_tokener_parse(post_state->body);
Packit Service 779887
Packit Service 779887
    if (json == NULL)
Packit Service 779887
    {
Packit Service 779887
        error_msg(_("Unable to parse response from ureport server at '%s'"), config->ur_url);
Packit Service 779887
        log_notice("%s", post_state->body);
Packit Service 779887
        json_object_put(json);
Packit Service 779887
        return NULL;
Packit Service 779887
    }
Packit Service 779887
Packit Service 779887
    struct ureport_server_response *response = ureport_server_parse_json(json);
Packit Service 779887
    json_object_put(json);
Packit Service 779887
Packit Service 779887
    if (!response)
Packit Service 779887
        error_msg(_("The response from '%s' has invalid format"), config->ur_url);
Packit Service 779887
    else if ((post_state->http_resp_code == 202 && response->urr_is_error)
Packit Service 779887
                || (post_state->http_resp_code != 202 && !response->urr_is_error))
Packit Service 779887
    {
Packit Service 779887
        /* HTTP CODE 202 means that call was successful but the response */
Packit Service 779887
        /* has an error message */
Packit Service 779887
        error_msg(_("Type mismatch has been detected in the response from '%s'"), config->ur_url);
Packit Service 779887
    }
Packit Service 779887
Packit Service 779887
    return response;
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
bool
Packit Service 779887
ureport_server_response_save_in_dump_dir(struct ureport_server_response *resp,
Packit Service 779887
                                         const char *dump_dir_path,
Packit Service 779887
                                         struct ureport_server_config *config)
Packit Service 779887
{
Packit Service 779887
    struct dump_dir *dd = dd_opendir(dump_dir_path, /* flags */ 0);
Packit Service 779887
    if (!dd)
Packit Service 779887
        return false;
Packit Service 779887
Packit Service 779887
    if (resp->urr_bthash)
Packit Service 779887
    {
Packit Service 779887
        {
Packit Service 779887
            report_result_t rr = { .label = (char *)"uReport" };
Packit Service 779887
            rr.bthash = resp->urr_bthash;
Packit Service 779887
            add_reported_to_entry(dd, &rr);
Packit Service 779887
        }
Packit Service 779887
Packit Service 779887
        {
Packit Service 779887
            report_result_t rr = { .label = (char *)"ABRT Server" };
Packit Service 779887
            rr.url = ureport_server_response_get_report_url(resp, config);
Packit Service 779887
            add_reported_to_entry(dd, &rr);
Packit Service 779887
            free(rr.url);
Packit Service 779887
        }
Packit Service 779887
    }
Packit Service 779887
Packit Service 779887
    if (resp->urr_reported_to_list)
Packit Service 779887
    {
Packit Service 779887
        for (GList *e = resp->urr_reported_to_list; e; e = g_list_next(e))
Packit Service 779887
            add_reported_to(dd, e->data);
Packit Service 779887
    }
Packit Service 779887
Packit Service 779887
    if (resp->urr_solution)
Packit Service 779887
        dd_save_text(dd, FILENAME_NOT_REPORTABLE, resp->urr_solution);
Packit Service 779887
Packit Service 779887
    dd_close(dd);
Packit Service 779887
    return true;
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
char *
Packit Service 779887
ureport_server_response_get_report_url(struct ureport_server_response *resp,
Packit Service 779887
                                       struct ureport_server_config *config)
Packit Service 779887
{
Packit Service 779887
    char *bthash_url = concat_path_file(config->ur_url, BTHASH_URL_SFX);
Packit Service 779887
    char *report_url = concat_path_file(bthash_url, resp->urr_bthash);
Packit Service 779887
    free(bthash_url);
Packit Service 779887
    return report_url;
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
static void
Packit Service 779887
ureport_add_str(struct json_object *ur, const char *key, const char *s)
Packit Service 779887
{
Packit Service 779887
    struct json_object *jstring = json_object_new_string(s);
Packit Service 779887
    if (!jstring)
Packit Service 779887
        die_out_of_memory();
Packit Service 779887
Packit Service 779887
    json_object_object_add(ur, key, jstring);
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
char *
Packit Service 779887
ureport_from_dump_dir_ext(const char *dump_dir_path, const struct ureport_preferences *preferences)
Packit Service 779887
{
Packit Service 779887
    char *error_message;
Packit Service 779887
    struct sr_report *report = sr_abrt_report_from_dir(dump_dir_path,
Packit Service 779887
                                                       &error_message);
Packit Service 779887
Packit Service 779887
    if (!report)
Packit Service 779887
    {
Packit Service 779887
        if (NULL == preferences || !(preferences->urp_flags & UREPORT_PREF_FLAG_RETURN_ON_FAILURE))
Packit Service 779887
            error_msg_and_die("%s", error_message);
Packit Service 779887
Packit Service 779887
        log_notice("%s", error_message);
Packit Service 779887
        return NULL;
Packit Service 779887
    }
Packit Service 779887
Packit Service 779887
    if (preferences != NULL && preferences->urp_auth_items != NULL)
Packit Service 779887
    {
Packit Service 779887
        struct dump_dir *dd = dd_opendir(dump_dir_path, DD_OPEN_READONLY);
Packit Service 779887
        if (!dd)
Packit Service 779887
            xfunc_die(); /* dd_opendir() already printed an error message */
Packit Service 779887
Packit Service 779887
        GList *iter = preferences->urp_auth_items;
Packit Service 779887
        for ( ; iter != NULL; iter = g_list_next(iter))
Packit Service 779887
        {
Packit Service 779887
            const char *key = (const char *)iter->data;
Packit Service 779887
            char *value = dd_load_text_ext(dd, key,
Packit Service 779887
                    DD_LOAD_TEXT_RETURN_NULL_ON_FAILURE | DD_FAIL_QUIETLY_ENOENT);
Packit Service 779887
Packit Service 779887
            if (value == NULL)
Packit Service 779887
            {
Packit Service 779887
                perror_msg("Cannot include '%s' in 'auth'", key);
Packit Service 779887
                continue;
Packit Service 779887
            }
Packit Service 779887
Packit Service 779887
            sr_report_add_auth(report, key, value);
Packit Service 779887
            free(value);
Packit Service 779887
        }
Packit Service 779887
Packit Service 779887
        dd_close(dd);
Packit Service 779887
    }
Packit Service 779887
Packit Service 779887
    char *json_ureport = sr_report_to_json(report);
Packit Service 779887
    sr_report_free(report);
Packit Service 779887
Packit Service 779887
    return json_ureport;
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
char *
Packit Service 779887
ureport_from_dump_dir(const char *dump_dir_path)
Packit Service 779887
{
Packit Service 779887
    return ureport_from_dump_dir_ext(dump_dir_path, /*no preferences*/NULL);
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
struct post_state *
Packit Service 779887
ureport_do_post(const char *json, struct ureport_server_config *config,
Packit Service 779887
                const char *url_sfx)
Packit Service 779887
{
Packit Service 779887
    int flags = POST_WANT_BODY | POST_WANT_ERROR_MSG;
Packit Service 779887
Packit Service 779887
    if (config->ur_ssl_verify)
Packit Service 779887
        flags |= POST_WANT_SSL_VERIFY;
Packit Service 779887
Packit Service 779887
    struct post_state *post_state = new_post_state(flags);
Packit Service 779887
Packit Service 779887
    if (config->ur_client_cert && config->ur_client_key)
Packit Service 779887
    {
Packit Service 779887
        post_state->client_cert_path = config->ur_client_cert;
Packit Service 779887
        post_state->client_key_path = config->ur_client_key;
Packit Service 779887
        post_state->cert_authority_cert_path = config->ur_cert_authority_cert;
Packit Service 779887
    }
Packit Service 779887
    else if (config->ur_username && config->ur_password)
Packit Service 779887
    {
Packit Service 779887
        post_state->username = config->ur_username;
Packit Service 779887
        post_state->password = config->ur_password;
Packit Service 779887
    }
Packit Service 779887
Packit Service 779887
    char **headers = xmalloc(sizeof(char *) * (3 + size_map_string(config->ur_http_headers)));
Packit Service 779887
    headers[0] = (char *)"Accept: application/json";
Packit Service 779887
    headers[1] = (char *)"Connection: close";
Packit Service 779887
    headers[2] = NULL;
Packit Service 779887
Packit Service 779887
    if (config->ur_http_headers != NULL)
Packit Service 779887
    {
Packit Service 779887
        unsigned i = 2;
Packit Service 779887
        const char *header;
Packit Service 779887
        const char *value;
Packit Service 779887
        map_string_iter_t iter;
Packit Service 779887
        init_map_string_iter(&iter, config->ur_http_headers);
Packit Service 779887
        while (next_map_string_iter(&iter, &header, &value))
Packit Service 779887
            headers[i++] = xasprintf("%s: %s", header, value);
Packit Service 779887
        headers[i] = NULL;
Packit Service 779887
    }
Packit Service 779887
Packit Service 779887
    char *dest_url = concat_path_file(config->ur_url, url_sfx);
Packit Service 779887
Packit Service 779887
    post_string_as_form_data(post_state, dest_url, "application/json",
Packit Service 779887
                     (const char **)headers, json);
Packit Service 779887
Packit Service 779887
    /* Client authentication failed. Try again without client auth.
Packit Service 779887
     * CURLE_SSL_CONNECT_ERROR - cert not found/server doesnt trust the CA
Packit Service 779887
     * CURLE_SSL_CERTPROBLEM - malformed certificate/no permission
Packit Service 779887
     */
Packit Service 779887
    if ((post_state->curl_result == CURLE_SSL_CONNECT_ERROR
Packit Service 779887
         || post_state->curl_result == CURLE_SSL_CERTPROBLEM)
Packit Service 779887
            && config->ur_client_cert && config->ur_client_key)
Packit Service 779887
    {
Packit Service 779887
        warn_msg("Authentication failed. Retrying unauthenticated.");
Packit Service 779887
        free_post_state(post_state);
Packit Service 779887
        post_state = new_post_state(flags);
Packit Service 779887
Packit Service 779887
        post_string_as_form_data(post_state, dest_url, "application/json",
Packit Service 779887
                         (const char **)headers, json);
Packit Service 779887
Packit Service 779887
    }
Packit Service 779887
Packit Service 779887
    free(dest_url);
Packit Service 779887
Packit Service 779887
    for (unsigned i = size_map_string(config->ur_http_headers); i != 0; --i)
Packit Service 779887
        free(headers[i + 1]);
Packit Service 779887
    free(headers);
Packit Service 779887
Packit Service 779887
    return post_state;
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
struct ureport_server_response *
Packit Service 779887
ureport_submit(const char *json, struct ureport_server_config *config)
Packit Service 779887
{
Packit Service 779887
    struct post_state *post_state = ureport_do_post(json, config, UREPORT_SUBMIT_ACTION);
Packit Service 779887
Packit Service 779887
    if (post_state == NULL)
Packit Service 779887
    {
Packit Service 779887
        error_msg(_("Failed on submitting the problem"));
Packit Service 779887
        return NULL;
Packit Service 779887
    }
Packit Service 779887
Packit Service 779887
    struct ureport_server_response *resp = ureport_server_response_from_reply(post_state, config);
Packit Service 779887
    free(post_state);
Packit Service 779887
Packit Service 779887
    return resp;
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
char *
Packit Service 779887
ureport_json_attachment_new(const char *bthash, const char *type, const char *data)
Packit Service 779887
{
Packit Service 779887
    struct json_object *attachment = json_object_new_object();
Packit Service 779887
    if (!attachment)
Packit Service 779887
        die_out_of_memory();
Packit Service 779887
Packit Service 779887
    ureport_add_str(attachment, "bthash", bthash);
Packit Service 779887
    ureport_add_str(attachment, "type", type);
Packit Service 779887
    ureport_add_str(attachment, "data", data);
Packit Service 779887
Packit Service 779887
    char *result = xstrdup(json_object_to_json_string(attachment));
Packit Service 779887
    json_object_put(attachment);
Packit Service 779887
Packit Service 779887
    return result;
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
bool
Packit Service 779887
ureport_attach_string(const char *bthash, const char *type, const char *data,
Packit Service 779887
               struct ureport_server_config *config)
Packit Service 779887
{
Packit Service 779887
    char *json = ureport_json_attachment_new(bthash, type, data);
Packit Service 779887
    post_state_t *post_state = ureport_do_post(json, config, UREPORT_ATTACH_ACTION);
Packit Service 779887
    free(json);
Packit Service 779887
Packit Service 779887
    struct ureport_server_response *resp =
Packit Service 779887
        ureport_server_response_from_reply(post_state, config);
Packit Service 779887
    free_post_state(post_state);
Packit Service 779887
    /* don't use str_bo_bool() because we require "true" string */
Packit Service 779887
    const int result = !resp || resp->urr_is_error || strcmp(resp->urr_value, "true") != 0;
Packit Service 779887
Packit Service 779887
    if (resp && resp->urr_is_error)
Packit Service 779887
        error_msg(_("The server at '%s' responded with an error: '%s'"),
Packit Service 779887
                config->ur_url, resp->urr_value);
Packit Service 779887
Packit Service 779887
    ureport_server_response_free(resp);
Packit Service 779887
Packit Service 779887
    return result;
Packit Service 779887
}
Packit Service 779887
Packit Service 779887
bool
Packit Service 779887
ureport_attach_int(const char *bthash, const char *type, int data,
Packit Service 779887
                    struct ureport_server_config *config)
Packit Service 779887
{
Packit Service 779887
    char *data_str = xasprintf("%d", data);
Packit Service 779887
    const bool result = ureport_attach_string(bthash, type, data_str, config);
Packit Service 779887
    free(data_str);
Packit Service 779887
Packit Service 779887
    return result;
Packit Service 779887
}