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

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