Blame SOURCES/0037-Bugzilla-pass-Bugzilla_token-in-all-XML-RPC-calls.patch

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