From 36010951c38483b4131012ebebd6b1f79c0ae799 Mon Sep 17 00:00:00 2001 From: Jakub Filak Date: Wed, 23 Apr 2014 13:33:52 +0200 Subject: [LIBREPORT PATCH 37/37] Bugzilla: pass Bugzilla_token in all XML RPC calls Introduce the session parameters for XML RPC calls. These parameters are added to every XML RPC call. abrt_xmlrpc_call*() functions expected formatting string in form of "({...})" for some good but unknown reason. Since now, the functions expects formatting string without the outer brackets. () - means empty array (allowed in xmlrpc-c) {} - means empty structure (allowed in xmlrpc-c) Cite: Instead of returning a cookie, the User.login call now returns a token that clients must pass in the Bugzilla_token parameter to subsequent RPC calls. If the token is not passed, Bugzilla will treat the RPC call as unauthenticated and will not allow access to non-public data. See https://partner-bugzilla.redhat.com/docs/en/html/api/Bugzilla/WebService.html#LOGGING_IN for more details. Client scripts that access Red Hat Bugzilla via XML-RPC or JSON-RPC and use login cookies for authentication must be updated to instead remember the token received when logging in and pass that token back to Bugzilla in subsequent RPC calls. [http://post-office.corp.redhat.com/archives/bugzilla-list/2014-April/msg00005.html] Resolves rhbz#1090465 Signed-off-by: Jakub Filak mmilata: fix typo in commit message subject Signed-off-by: Jakub Filak --- src/lib/abrt_xmlrpc.c | 94 +++++++++++++++++++++++++++++++++-------- src/lib/abrt_xmlrpc.h | 3 ++ src/plugins/reporter-bugzilla.c | 34 --------------- src/plugins/rhbz.c | 64 ++++++++++++++++++++++++---- src/plugins/rhbz.h | 4 ++ 5 files changed, 139 insertions(+), 60 deletions(-) diff --git a/src/lib/abrt_xmlrpc.c b/src/lib/abrt_xmlrpc.c index 48b556f..84ed50d 100644 --- a/src/lib/abrt_xmlrpc.c +++ b/src/lib/abrt_xmlrpc.c @@ -20,6 +20,12 @@ #include "abrt_xmlrpc.h" #include "proxies.h" +struct abrt_xmlrpc_param_pair +{ + char *name; + xmlrpc_value *value; +}; + void abrt_xmlrpc_die(xmlrpc_env *env) { error_msg_and_die("fatal: %s", env->fault_string); @@ -106,9 +112,77 @@ void abrt_xmlrpc_free_client(struct abrt_xmlrpc *ax) if (ax->ax_client) xmlrpc_client_destroy(ax->ax_client); + for (GList *iter = ax->ax_session_params; iter; iter = g_list_next(iter)) + { + struct abrt_xmlrpc_param_pair *param_pair = (struct abrt_xmlrpc_param_pair *)iter->data; + xmlrpc_DECREF(param_pair->value); + free(param_pair->name); + free(param_pair); + } + + g_list_free(ax->ax_session_params); + free(ax); } +void abrt_xmlrpc_client_add_session_param_string(xmlrpc_env *env, struct abrt_xmlrpc *ax, + const char *name, const char *value) +{ + struct abrt_xmlrpc_param_pair *new_ses_param = xmalloc(sizeof(*new_ses_param)); + new_ses_param->name = xstrdup(name); + + new_ses_param->value = xmlrpc_string_new(env, value); + if (env->fault_occurred) + abrt_xmlrpc_die(env); + + ax->ax_session_params = g_list_append(ax->ax_session_params, new_ses_param); +} + +/* internal helper function */ +static xmlrpc_value *abrt_xmlrpc_call_params_internal(xmlrpc_env *env, struct abrt_xmlrpc *ax, const char *method, xmlrpc_value *params) +{ + xmlrpc_value *array = xmlrpc_array_new(env); + if (env->fault_occurred) + abrt_xmlrpc_die(env); + + bool destroy_params = false; + if (xmlrpc_value_type(params) == XMLRPC_TYPE_NIL) + { + destroy_params = true; + params = abrt_xmlrpc_params_new(env); + } + + if (xmlrpc_value_type(params) == XMLRPC_TYPE_STRUCT) + { + for (GList *iter = ax->ax_session_params; iter; iter = g_list_next(iter)) + { + struct abrt_xmlrpc_param_pair *param_pair = (struct abrt_xmlrpc_param_pair *)iter->data; + + xmlrpc_struct_set_value(env, params, param_pair->name, param_pair->value); + if (env->fault_occurred) + abrt_xmlrpc_die(env); + } + } + else + { + log_warning("Bug: not yet supported XML RPC call type."); + } + + xmlrpc_array_append_item(env, array, params); + if (env->fault_occurred) + abrt_xmlrpc_die(env); + + xmlrpc_value *result = NULL; + xmlrpc_client_call2(env, ax->ax_client, ax->ax_server_info, method, + array, &result); + + if (destroy_params) + xmlrpc_DECREF(params); + + xmlrpc_DECREF(array); + return result; +} + /* internal helper function */ static xmlrpc_value *abrt_xmlrpc_call_full_va(xmlrpc_env *env, struct abrt_xmlrpc *ax, @@ -133,10 +207,8 @@ xmlrpc_value *abrt_xmlrpc_call_full_va(xmlrpc_env *env, struct abrt_xmlrpc *ax, suffix); } else - { - xmlrpc_client_call2(env, ax->ax_client, ax->ax_server_info, method, - param, &result); - } + result = abrt_xmlrpc_call_params_internal(env, ax, method, param); + xmlrpc_DECREF(param); return result; @@ -192,25 +264,13 @@ void abrt_xmlrpc_params_add_array(xmlrpc_env *env, xmlrpc_value *params, const c if (env->fault_occurred) abrt_xmlrpc_die(env); } - xmlrpc_value *abrt_xmlrpc_call_params(xmlrpc_env *env, struct abrt_xmlrpc *ax, const char *method, xmlrpc_value *params) { - xmlrpc_value *array = xmlrpc_array_new(env); - if (env->fault_occurred) - abrt_xmlrpc_die(env); - - xmlrpc_array_append_item(env, array, params); - if (env->fault_occurred) - abrt_xmlrpc_die(env); - - xmlrpc_value *result = NULL; - xmlrpc_client_call2(env, ax->ax_client, ax->ax_server_info, method, - array, &result); + xmlrpc_value *result = abrt_xmlrpc_call_params_internal(env, ax, method, params); if (env->fault_occurred) abrt_xmlrpc_die(env); - xmlrpc_DECREF(array); return result; } diff --git a/src/lib/abrt_xmlrpc.h b/src/lib/abrt_xmlrpc.h index 945a887..e11dcec 100644 --- a/src/lib/abrt_xmlrpc.h +++ b/src/lib/abrt_xmlrpc.h @@ -23,6 +23,7 @@ * include/xmlrpc-c/base.h: typedef int32_t xmlrpc_int32; */ +#include #include #include @@ -33,6 +34,7 @@ extern "C" { struct abrt_xmlrpc { xmlrpc_client *ax_client; xmlrpc_server_info *ax_server_info; + GList *ax_session_params; }; xmlrpc_value *abrt_xmlrpc_array_new(xmlrpc_env *env); @@ -45,6 +47,7 @@ void abrt_xmlrpc_params_add_array(xmlrpc_env *env, xmlrpc_value *params, const c struct abrt_xmlrpc *abrt_xmlrpc_new_client(const char *url, int ssl_verify); void abrt_xmlrpc_free_client(struct abrt_xmlrpc *ax); +void abrt_xmlrpc_client_add_session_param_string(xmlrpc_env *env, struct abrt_xmlrpc *ax, const char *name, const char *value); void abrt_xmlrpc_die(xmlrpc_env *env) __attribute__((noreturn)); void abrt_xmlrpc_error(xmlrpc_env *env); diff --git a/src/plugins/reporter-bugzilla.c b/src/plugins/reporter-bugzilla.c index 0e8b277..45aa2cc 100644 --- a/src/plugins/reporter-bugzilla.c +++ b/src/plugins/reporter-bugzilla.c @@ -807,40 +807,6 @@ void login(struct abrt_xmlrpc *client, struct bugzilla_struct *rhbz) } } -static -xmlrpc_value *rhbz_search_duphash(struct abrt_xmlrpc *ax, - const char *product, - const char *version, - const char *component, - const char *duphash) -{ - struct strbuf *query = strbuf_new(); - - strbuf_append_strf(query, "ALL whiteboard:\"%s\"", duphash); - - if (product) - strbuf_append_strf(query, " product:\"%s\"", product); - - if (version) - strbuf_append_strf(query, " version:\"%s\"", version); - - if (component) - strbuf_append_strf(query, " component:\"%s\"", component); - - char *s = strbuf_free_nobuf(query); - log_debug("search for '%s'", s); - xmlrpc_value *search = abrt_xmlrpc_call(ax, "Bug.search", "({s:s})", - "quicksearch", s); - free(s); - xmlrpc_value *bugs = rhbz_get_member("bugs", search); - xmlrpc_DECREF(search); - - if (!bugs) - error_msg_and_die(_("Bug.search(quicksearch) return value did not contain member 'bugs'")); - - return bugs; -} - int main(int argc, char **argv) { abrt_init(argv); diff --git a/src/plugins/rhbz.c b/src/plugins/rhbz.c index 534aaed..bad9ed4 100644 --- a/src/plugins/rhbz.c +++ b/src/plugins/rhbz.c @@ -85,7 +85,7 @@ static GList *rhbz_comments(struct abrt_xmlrpc *ax, int bug_id) * * ... */ - xmlrpc_value *xml_response = abrt_xmlrpc_call(ax, "Bug.comments", "({s:(i)})", + xmlrpc_value *xml_response = abrt_xmlrpc_call(ax, "Bug.comments", "{s:(i)}", "ids", bug_id); /* bugs * This is used for bugs specified in ids. This is a hash, where the @@ -215,7 +215,7 @@ bool rhbz_login(struct abrt_xmlrpc *ax, const char *login, const char *password) func_entry(); xmlrpc_env env; - xmlrpc_value *result = abrt_xmlrpc_call_full(&env, ax, "User.login", "({s:s,s:s})", + xmlrpc_value *result = abrt_xmlrpc_call_full(&env, ax, "User.login", "{s:s,s:s}", "login", login, "password", password); if (env.fault_occurred) @@ -228,6 +228,14 @@ bool rhbz_login(struct abrt_xmlrpc *ax, const char *login, const char *password) return false; } + char *token = rhbz_bug_read_item("token", result, RHBZ_READ_STR); + if (token != NULL) + { + log_debug("Adding session param Bugzilla_token"); + abrt_xmlrpc_client_add_session_param_string(&env, ax, "Bugzilla_token", token); + free(token); + } + //TODO: with URL like http://bugzilla.redhat.com (that is, with http: instead of https:) //we are getting this error: //Logging into Bugzilla at http://bugzilla.redhat.com @@ -297,7 +305,7 @@ unsigned rhbz_version(struct abrt_xmlrpc *ax) func_entry(); xmlrpc_value *result; - result = abrt_xmlrpc_call(ax, "Bugzilla.version", "()"); + result = abrt_xmlrpc_call(ax, "Bugzilla.version", "{}"); char *version = NULL; if (result) version = rhbz_bug_read_item("version", result, RHBZ_READ_STR); @@ -472,7 +480,7 @@ struct bug_info *rhbz_bug_info(struct abrt_xmlrpc *ax, int bug_id) * * ... */ - xmlrpc_value *xml_bug_response = abrt_xmlrpc_call(ax, "Bug.get", "({s:(i)})", + xmlrpc_value *xml_bug_response = abrt_xmlrpc_call(ax, "Bug.get", "{s:(i)}", "ids", bug_id); xmlrpc_value *bugs_memb = rhbz_get_member("bugs", xml_bug_response); @@ -668,7 +676,7 @@ int rhbz_attach_blob(struct abrt_xmlrpc *ax, const char *bug_id, * 6 -> base64, two arguments (char* plain data which will be encoded by xmlrpc-c to base64, * size_t number of bytes to encode) */ - result = abrt_xmlrpc_call(ax, "Bug.add_attachment", "({s:(s),s:s,s:s,s:s,s:6,s:i})", + result = abrt_xmlrpc_call(ax, "Bug.add_attachment", "{s:(s),s:s,s:s,s:s,s:6,s:i}", "ids", bug_id, "summary", fn, "file_name", filename, @@ -737,7 +745,12 @@ void rhbz_logout(struct abrt_xmlrpc *ax) { func_entry(); - xmlrpc_value* result = abrt_xmlrpc_call(ax, "User.logout", "(s)", ""); + xmlrpc_env env; + xmlrpc_value *result = abrt_xmlrpc_call_full(&env, ax, "User.logout", "{}"); + + if (env.fault_occurred) + log_warning("xmlrpc fault: (%d) %s", env.fault_code, env.fault_string); + if (result) xmlrpc_DECREF(result); } @@ -785,7 +798,7 @@ void rhbz_mail_to_cc(struct abrt_xmlrpc *ax, int bug_id, const char *mail, int f ); #endif /* Bugzilla 4.0+ uses this API: */ - result = abrt_xmlrpc_call(ax, "Bug.update", "({s:i,s:{s:(s),s:i}})", + result = abrt_xmlrpc_call(ax, "Bug.update", "{s:i,s:{s:(s),s:i}}", "ids", bug_id, "cc", "add", mail, "nomail", nomail_notify @@ -822,7 +835,7 @@ void rhbz_add_comment(struct abrt_xmlrpc *ax, int bug_id, const char *comment, int nomail_notify = !!IS_NOMAIL_NOTIFY(flags); xmlrpc_value *result; - result = abrt_xmlrpc_call(ax, "Bug.add_comment", "({s:i,s:s,s:b,s:i})", + result = abrt_xmlrpc_call(ax, "Bug.add_comment", "{s:i,s:s,s:b,s:i}", "id", bug_id, "comment", comment, "private", private, "nomail", nomail_notify); @@ -835,7 +848,7 @@ void rhbz_set_url(struct abrt_xmlrpc *ax, int bug_id, const char *url, int flags func_entry(); const int nomail_notify = !!IS_NOMAIL_NOTIFY(flags); - xmlrpc_value *result = abrt_xmlrpc_call(ax, "Bug.update", "({s:i,s:s,s:i})", + xmlrpc_value *result = abrt_xmlrpc_call(ax, "Bug.update", "{s:i,s:s,s:i}", "ids", bug_id, "url", url, @@ -848,3 +861,36 @@ void rhbz_set_url(struct abrt_xmlrpc *ax, int bug_id, const char *url, int flags if (result) xmlrpc_DECREF(result); } + +xmlrpc_value *rhbz_search_duphash(struct abrt_xmlrpc *ax, + const char *product, + const char *version, + const char *component, + const char *duphash) +{ + struct strbuf *query = strbuf_new(); + + strbuf_append_strf(query, "ALL whiteboard:\"%s\"", duphash); + + if (product) + strbuf_append_strf(query, " product:\"%s\"", product); + + if (version) + strbuf_append_strf(query, " version:\"%s\"", version); + + if (component) + strbuf_append_strf(query, " component:\"%s\"", component); + + char *s = strbuf_free_nobuf(query); + log_debug("search for '%s'", s); + xmlrpc_value *search = abrt_xmlrpc_call(ax, "Bug.search", "{s:s}", "quicksearch", s); + + free(s); + xmlrpc_value *bugs = rhbz_get_member("bugs", search); + xmlrpc_DECREF(search); + + if (!bugs) + error_msg_and_die(_("Bug.search(quicksearch) return value did not contain member 'bugs'")); + + return bugs; +} diff --git a/src/plugins/rhbz.h b/src/plugins/rhbz.h index 742927a..976d333 100644 --- a/src/plugins/rhbz.h +++ b/src/plugins/rhbz.h @@ -112,6 +112,10 @@ struct bug_info *rhbz_find_origin_bug_closed_duplicate(struct abrt_xmlrpc *ax, struct bug_info *bi); unsigned rhbz_version(struct abrt_xmlrpc *ax); +xmlrpc_value *rhbz_search_duphash(struct abrt_xmlrpc *ax, + const char *product, const char *version, const char *component, + const char *duphash); + #ifdef __cplusplus } #endif -- 1.8.3.1