예제 #1
0
파일: bodhi.c 프로젝트: wlindauer/abrt
static GHashTable *bodhi_query_list(const char *query, const char *release)
{
    char *bodhi_url_bugs = xasprintf("%s/?%s", bodhi_url, query);

    post_state_t *post_state = new_post_state(POST_WANT_BODY
                                              | POST_WANT_SSL_VERIFY
                                              | POST_WANT_ERROR_MSG);

    const char *headers[] = {
        "Accept: application/json",
        NULL
    };

    get(post_state, bodhi_url_bugs, "application/x-www-form-urlencoded",
                     headers);

    if (post_state->http_resp_code != 200 && post_state->http_resp_code != 400)
    {
        char *errmsg = post_state->curl_error_msg;
        if (errmsg && errmsg[0])
            error_msg_and_die("%s '%s'", errmsg, bodhi_url_bugs);
    }
    free(bodhi_url_bugs);

//    log_warning("%s", post_state->body);

    json_object *json = json_tokener_parse(post_state->body);
    if (is_error(json))
        error_msg_and_die("fatal: unable parse response from bodhi server");

    /* we must check the http_resp_code because only error responses contain
     * 'status' item. 'bodhi_read_value' function prints an error message in
     * the case it did not found the item */
    if (post_state->http_resp_code != 200)
    {
        char *status_item = NULL;
        bodhi_read_value(json, "status", &status_item, BODHI_READ_STR);
        if (status_item != NULL && strcmp(status_item, "error") == 0)
        {
            free(status_item);
            bodhi_print_errors_from_json(json);
            json_object_put(json);
            xfunc_die(); // error_msg are printed in bodhi_print_errors_from_json
        }
    }

    GHashTable *bodhi_table = bodhi_parse_json(json, release);
    json_object_put(json);
    free_post_state(post_state);

    return bodhi_table;
}
예제 #2
0
static int interactive_upload_file(const char *url, const char *file_name,
                                   map_string_t *settings, char **remote_name)
{
    post_state_t *state = new_post_state(POST_WANT_ERROR_MSG);
    state->username = get_map_string_item_or_NULL(settings, "UploadUsername");
    char *password_inp = NULL;
    if (state->username != NULL && state->username[0] != '\0')
    {
        /* Load Password only if Username is configured, it doesn't make */
        /* much sense to load Password without Username. */
        state->password = get_map_string_item_or_NULL(settings, "UploadPassword");
        if (state->password == NULL)
        {
            /* Be permissive and nice, ask only once and don't check */
            /* the result. User can dismiss this prompt but the upload */
            /* may work somehow??? */
            char *msg = xasprintf(_("Please enter password for uploading:"), state->username);
            state->password = password_inp = ask_password(msg);
            free(msg);
        }
    }

    /* set SSH keys */
    state->client_ssh_public_keyfile = get_map_string_item_or_NULL(settings, "SSHPublicKey");
    state->client_ssh_private_keyfile = get_map_string_item_or_NULL(settings, "SSHPrivateKey");

    if (state->client_ssh_public_keyfile != NULL)
        log_debug("Using SSH public key '%s'", state->client_ssh_public_keyfile);
    if (state->client_ssh_private_keyfile != NULL)
        log_debug("Using SSH private key '%s'", state->client_ssh_private_keyfile);

    char *tmp = upload_file_ext(state, url, file_name, UPLOAD_FILE_HANDLE_ACCESS_DENIALS);

    if (remote_name)
        *remote_name = tmp;
    else
        free(tmp);

    free(password_inp);
    free_post_state(state);

    /* return 0 on success */
    return tmp == NULL;
}
예제 #3
0
static bool perform_attach(struct ureport_server_config *config, const char *ureport_hash, int rhbz_bug)
{
    char *dest_url = concat_path_file(config->ur_url, ATTACH_URL_SFX);
    const char *old_url = config->ur_url;
    config->ur_url = dest_url;
    post_state_t *post_state = ureport_attach_rhbz(ureport_hash, rhbz_bug, config);
    config->ur_url = old_url;
    free(dest_url);

    struct ureport_server_response *resp = get_server_response(post_state, config);
    free_post_state(post_state);
    /* don't use str_bo_bool() because we require "true" string */
    const int result = !resp || resp->is_error || strcmp(resp->value,"true") != 0;

    if (resp && resp->is_error)
    {
        error_msg(_("The server at '%s' responded with an error: '%s'"), config->ur_url, resp->value);
    }

    free_ureport_server_response(resp);

    return result;
}
예제 #4
0
파일: bodhi.c 프로젝트: vrutkovs/abrt
static GHashTable *bodhi_query_list(const char *query, const char *release)
{
    char *bodhi_url_bugs = xasprintf("%s/list", bodhi_url);

    post_state_t *post_state = new_post_state(POST_WANT_BODY
                                              | POST_WANT_SSL_VERIFY
                                              | POST_WANT_ERROR_MSG);

    const char *headers[] = {
        "Accept: application/json",
        NULL
    };

    post_string(post_state, bodhi_url_bugs, "application/x-www-form-urlencoded",
                     headers, query);

    if (post_state->http_resp_code != 200)
    {
        char *errmsg = post_state->curl_error_msg;
        if (errmsg && errmsg[0])
            error_msg_and_die("%s '%s'", errmsg, bodhi_url_bugs);
    }
    free(bodhi_url_bugs);

//    log("%s", post_state->body);

    json_object *json = json_tokener_parse(post_state->body);
    if (is_error(json))
        error_msg_and_die("fatal: unable parse response from bodhi server");

    GHashTable *bodhi_table = bodhi_parse_json(json, release);
    json_object_put(json);
    free_post_state(post_state);

    return bodhi_table;
}
예제 #5
0
static int create_and_upload_archive(
                const char *dump_dir_name,
                map_string_t *settings)
{
    int result = 1; /* error */

    pid_t child;
    TAR* tar = NULL;
    const char* errmsg = NULL;
    char* tempfile = NULL;

    struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
    if (!dd)
        xfunc_die(); /* error msg is already logged by dd_opendir */

    /* Gzipping e.g. 0.5gig coredump takes a while. Let client know what we are doing */
    log(_("Compressing data"));

//TODO:
//Encrypt = yes
//ArchiveType = .tar.bz2
//ExcludeFiles = foo,bar*,b*z
    const char* opt = getenv("Upload_URL");
    if (!opt)
        opt = get_map_string_item_or_empty(settings, "URL");
    char *url = opt[0] != '\0' ? xstrdup(opt) : ask_url(_("Please enter a URL (scp, ftp, etc.) where the problem data is to be exported:"));

    /* Create a child gzip which will compress the data */
    /* SELinux guys are not happy with /tmp, using /var/run/abrt */
    /* Reverted back to /tmp for ABRT2 */
    /* Changed again to /var/tmp because of Fedora feature tmp-on-tmpfs */
    tempfile = concat_path_basename(LARGE_DATA_TMP_DIR, dump_dir_name);
    tempfile = append_to_malloced_string(tempfile, ".tar.gz");

    int pipe_from_parent_to_child[2];
    xpipe(pipe_from_parent_to_child);
    child = vfork();
    if (child == 0)
    {
        /* child */
        close(pipe_from_parent_to_child[1]);
        xmove_fd(pipe_from_parent_to_child[0], 0);
        xmove_fd(xopen3(tempfile, O_WRONLY | O_CREAT | O_EXCL, 0600), 1);
        execlp("gzip", "gzip", NULL);
        perror_msg_and_die("Can't execute '%s'", "gzip");
    }
    close(pipe_from_parent_to_child[0]);

    /* If child died (say, in xopen), then parent might get SIGPIPE.
     * We want to properly unlock dd, therefore we must not die on SIGPIPE:
     */
    signal(SIGPIPE, SIG_IGN);

    /* Create tar writer object */
    if (tar_fdopen(&tar, pipe_from_parent_to_child[1], tempfile,
                /*fileops:(standard)*/ NULL, O_WRONLY | O_CREAT, 0644, TAR_GNU) != 0)
    {
        errmsg = "Can't create temporary file in "LARGE_DATA_TMP_DIR;
        goto ret;
    }

    /* Write data to the tarball */
    {
        string_vector_ptr_t exclude_from_report = get_global_always_excluded_elements();
        dd_init_next_file(dd);
        char *short_name, *full_name;
        while (dd_get_next_file(dd, &short_name, &full_name))
        {
            if (exclude_from_report && is_in_string_list(short_name, (const_string_vector_const_ptr_t)exclude_from_report))
                goto next;

            // dd_get_next_file guarantees that it's a REG:
            //struct stat stbuf;
            //if (stat(full_name, &stbuf) != 0)
            // || !S_ISREG(stbuf.st_mode)
            //) {
            //     goto next;
            //}
            if (tar_append_file(tar, full_name, short_name) != 0)
            {
                errmsg = "Can't create temporary file in "LARGE_DATA_TMP_DIR;
                free(short_name);
                free(full_name);
                goto ret;
            }
 next:
            free(short_name);
            free(full_name);
        }
    }
    dd_close(dd);
    dd = NULL;

    /* Close tar writer... */
    if (tar_append_eof(tar) != 0 || tar_close(tar) != 0)
    {
        errmsg = "Can't create temporary file in "LARGE_DATA_TMP_DIR;
        goto ret;
    }
    tar = NULL;
    /* ...and check that gzip child finished successfully */
    int status;
    safe_waitpid(child, &status, 0);
    child = -1;
    if (status != 0)
    {
        /* We assume the error was out-of-disk-space or out-of-quota */
        errmsg = "Can't create temporary file in "LARGE_DATA_TMP_DIR;
        goto ret;
    }

    /* Upload the tarball */
    /* Upload from /tmp to /tmp + deletion -> BAD, exclude this possibility */
    if (url && url[0] && strcmp(url, "file://"LARGE_DATA_TMP_DIR"/") != 0)
    {
        post_state_t *state = new_post_state(POST_WANT_ERROR_MSG);
        state->username = getenv("Upload_Username");
        char *password_inp = NULL;
        if (state->username != NULL && state->username[0] != '\0')
        {
            /* Load Password only if Username is configured, it doesn't make */
            /* much sense to load Password without Username. */
            state->password = getenv("Upload_Password");
            if (state->password == NULL)
            {
                /* Be permissive and nice, ask only once and don't check */
                /* the result. User can dismiss this prompt but the upload */
                /* may work somehow??? */
                char *msg = xasprintf(_("Please enter password for uploading:"), state->username);
                state->password = password_inp = ask_password(msg);
                free(msg);
            }
        }

        char *remote_name = upload_file_ext(state, url, tempfile, UPLOAD_FILE_HANDLE_ACCESS_DENIALS);

        result = (remote_name == NULL); /* error if NULL */
        free(remote_name);
        free(password_inp);
        free_post_state(state);
        /* cleanup code will delete tempfile */
    }
    else
    {
        result = 0; /* success */
        log(_("Archive is created: '%s'"), tempfile);
        free(tempfile);
        tempfile = NULL;
    }

 ret:
    free(url);
    dd_close(dd);
    if (tar)
        tar_close(tar);
    /* close(pipe_from_parent_to_child[1]); - tar_close() does it itself */
    if (child > 0)
        safe_waitpid(child, NULL, 0);
    if (tempfile)
    {
        unlink(tempfile);
        free(tempfile);
    }
    if (errmsg)
        error_msg_and_die("%s", errmsg);

    return result;
}
예제 #6
0
int main(int argc, char **argv)
{
    setlocale(LC_ALL, "");
#if ENABLE_NLS
    bindtextdomain(PACKAGE, LOCALEDIR);
    textdomain(PACKAGE);
#endif

    abrt_init(argv);

    struct ureport_server_config config = {
        .ur_url = SERVER_URL,
        .ur_ssl_verify = true,
    };

    bool insecure = !config.ur_ssl_verify;
    bool attach_reported_to = false;
    const char *dump_dir_path = ".";
    const char *ureport_hash = NULL;
    int rhbz_bug = -1;
    struct dump_dir *dd = NULL;
    struct options program_options[] = {
        OPT__VERBOSE(&g_verbose),
        OPT__DUMP_DIR(&dump_dir_path),
        OPT_STRING('u', "url", &config.ur_url, "URL", _("Specify server URL")),
        OPT_BOOL('k', "insecure", &insecure,
                          _("Allow insecure connection to ureport server")),
        OPT_STRING('a', "attach", &ureport_hash, "BTHASH",
                          _("bthash of uReport to attach")),
        OPT_INTEGER('b', "bug-id", &rhbz_bug,
                          _("Attach RHBZ bug (requires -a)")),
        OPT_BOOL('r', "attach-reported-to", &attach_reported_to,
                          _("Attach contents of reported_to")),
        OPT_END(),
    };

    const char *program_usage_string = _(
        "& [-v] [-u URL] [-k] [-a bthash -b bug-id] [-r] [-d DIR]\n"
        "\n"
        "Upload micro report or add an attachment to a micro report"
    );

    parse_opts(argc, argv, program_options, program_usage_string);

    config.ur_ssl_verify = !insecure;
    load_ureport_server_config(&config);
    post_state_t *post_state = NULL;

    /* we either need both -b & -a or none of them */
    if (ureport_hash && rhbz_bug > 0)
        return perform_attach(&config, ureport_hash, rhbz_bug);
    if (ureport_hash && rhbz_bug <= 0)
        error_msg_and_die(_("You need to specify bug ID to attach."));
    if (!ureport_hash && rhbz_bug > 0)
        error_msg_and_die(_("You need to specify bthash of the uReport to attach."));

    /* -r */
    if (attach_reported_to)
    {
        dd = dd_opendir(dump_dir_path, DD_OPEN_READONLY);
        if (!dd)
            xfunc_die();

        report_result_t *ureport_result = find_in_reported_to(dd, "uReport");
        report_result_t *bz_result = find_in_reported_to(dd, "Bugzilla");

        dd_close(dd);

        if (!ureport_result || !ureport_result->bthash)
            error_msg_and_die(_("This problem does not have an uReport assigned."));

        if (!bz_result || !bz_result->url)
            error_msg_and_die(_("This problem has not been reported to Bugzilla."));

        char *bthash = xstrdup(ureport_result->bthash);
        free_report_result(ureport_result);

        char *bugid_ptr = strstr(bz_result->url, "show_bug.cgi?id=");
        if (!bugid_ptr)
            error_msg_and_die(_("Unable to find bug ID in bugzilla URL '%s'"), bz_result->url);
        bugid_ptr += strlen("show_bug.cgi?id=");
        int bugid;
        /* we're just reading int, sscanf works fine */
        if (sscanf(bugid_ptr, "%d", &bugid) != 1)
            error_msg_and_die(_("Unable to parse bug ID from bugzilla URL '%s'"), bz_result->url);

        free_report_result(bz_result);

        const int result = perform_attach(&config, bthash, bugid);

        free(bthash);
        return result;
    }

    /* -b, -a nor -r were specified - upload uReport from dump_dir */
    int ret = 1; /* "failure" (for now) */
    char *dest_url = concat_path_file(config.ur_url, REPORT_URL_SFX);
    config.ur_url = dest_url;

    char *json_ureport = ureport_from_dump_dir(dump_dir_path);
    if (!json_ureport)
    {
        error_msg(_("Not uploading an empty uReport"));
        goto format_err;
    }

    post_state = post_ureport(json_ureport, &config);
    free(json_ureport);

    if (!post_state)
    {
        error_msg(_("Failed on submitting the problem"));
        goto format_err;
    }

    struct ureport_server_response *response = get_server_response(post_state, &config);

    if (!response)
        goto format_err;

    if (!response->is_error)
    {
        VERB1 log("is known: %s", response->value);
        ret = 0; /* "success" */

        dd = dd_opendir(dump_dir_path, /* flags */ 0);
        if (!dd)
            xfunc_die();

        if (response->bthash)
        {
            char *msg = xasprintf("uReport: BTHASH=%s", response->bthash);
            add_reported_to(dd, msg);
            free(msg);
        }

        if (response->reported_to_list)
        {
            for (GList *e = response->reported_to_list; e; e = g_list_next(e))
                add_reported_to(dd, e->data);
        }

        if (response->solution)
            dd_save_text(dd, FILENAME_NOT_REPORTABLE, response->solution);

        dd_close(dd);

        /* If a reported problem is not known then emit NEEDMORE */
        if (strcmp("true", response->value) == 0)
        {
            log(_("This problem has already been reported."));
            if (response->message)
                log(response->message);

            ret = EXIT_STOP_EVENT_RUN;
        }
    }
    else
    {
        error_msg(_("Server responded with an error: '%s'"), response->value);
    }

    free_ureport_server_response(response);

format_err:
    free_post_state(post_state);
    free(dest_url);

    return ret;
}